CreateFile関数のハンドルを閉じる

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
dic

CreateFile関数のハンドルを閉じる

#1

投稿記事 by dic » 15年前

WIN32API CreateFile関数で、指定したファイルを読み込もうとしてるのですが、
オープンしたハンドルを閉じる関数ってないのでしょうか?
もしくは、閉じる必要がないのでしょうか?
ファイル数が20万くらいあるので、
リソースをすんごく使いそうなんですが
閉じる関数がMSDNに見当たらなかったので

MNS

Re:CreateFile関数のハンドルを閉じる

#2

投稿記事 by MNS » 15年前

Win32APIについては全く詳しくはありませんが、
調べてみた感じでは、CloseHandle関数を使うようです。

dic

Re:CreateFile関数のハンドルを閉じる

#3

投稿記事 by dic » 15年前

ネットワーク越しにファイルやりとりしてるんで
まだ、テスト準備中なんですが
準備態勢ができたら試します
ありがとうございました

yrao

選択画面の拡張

#4

投稿記事 by yrao » 15年前

こんにちは。

(先日質問させていただいたスペルプラクティスの実装については、自己解決できました。)
 
 
ゲームの選択画面についての質問です。
現在メニュー画面の作成をしているのですが、次の三つのことについて知りたいです。
 
① 「GAME START」や、「OPTION」などのような、選択する項目それぞれに座標を設定する方法
② 添付画像のように、選択項目が一画面に入りきらない場合、次のページを用意して、残りの項目を表示する  方法
③ 現在、選択項目には文字を使っているのですが、画像を項目として使用することはできるのでしょうか。
 
 
 
選択画面のプログラムは、龍神録プログラミングの支館のものを使っています(以下記載)。


void MenuDraw( int x , int y , char title[/url] , char **str , int *menu ){
    int num=0,i=0;
    int dx=0,len=0;
    char **str2 = str;

    //背景を暗く
    //SetDrawBlendMode( DX_BLENDMODE_ALPHA , 80 ) ;
    //DrawBox( FX , FY , FX+FMX , FY+FMY , color[1] , TRUE ) ;
    //SetDrawBlendMode( DX_BLENDMODE_NOBLEND , 0 ) ;

    //タイトル表示
    dx =  x - GetDrawFormatStringWidthToHandle( font[1] , title ) / 2;
    DrawFormatStringToHandle(dx,y,color[0],font[1],"%s",title);
    y += 30;    //改行

    //情報の取得
    while ( *str2 ){
        if( len < GetDrawFormatStringWidthToHandle( font[0] , *str2 ) ){
            len = GetDrawFormatStringWidthToHandle( font[0] , *str2 );
        }
        ++num;
        *str2++;

        if( i++ > 50 )    break;    //無限ループ防止
    }
    dx =  x - len / 2;

    //選択制御
    if( CheckStatePad(configpad.up)   == 1 && *menu > 0 )        --*menu;
    else if( CheckStatePad(configpad.up)   == 1 )                *menu = num-1;
    if( CheckStatePad(configpad.down) == 1 && *menu < num-1 )    ++*menu;
    else if( CheckStatePad(configpad.down) == 1 )                *menu = 0;

    y += *menu * 30;  
    SetDrawBlendMode( DX_BLENDMODE_ALPHA , 100 ) ;
    DrawBox( dx-10 , y , dx+10 + len , y + 18 , color[0] , TRUE ) ;    //選択位置の表示
    SetDrawBlendMode( DX_BLENDMODE_NOBLEND , 0 ) ;
    y -= *menu * 30;    

    //項目の表示
    i=0;
    while ( *str ){
        dx = x - GetDrawFormatStringWidthToHandle( font[0] , *str ) / 2;
        DrawFormatStringToHandle(dx,y,color[0],font[0],"%s",*str++);
        y += 30; 

        if( i++ > 50 )    break;    //無限ループ防止
    }
}


//表示例
void menu_game(){//タイトル画面
    char *str[10]={
        {"GAME START"},
        {"SPELL PRACTICE"},
        {"REPLAY"},
        {"GALLERLY"},
        {"RESULT"},
        {"OPTION"},
        {"QUIT"}
    };
    static int menu;

    MenuDraw( 520 , FY+FMY/3 , "" , str , &menu);

    if( CheckStatePad(configpad.shot) == 1 ){
        switch(menu){
            case 0:
                func_state = 90;    //難易度選択へ
                break;
            case 1:
                func_state = 20;    //SPELL PRACTICEへ
                break;
            case 2:
                func_state = 30;    //REPLAYへ
                break;
            case 3:
                func_state = 40;    //GALLERLYへ
                break;
            case 4:
                func_state = 50;    //RESULTへ
                break;
            case 5:
                func_state = 60;    //OPTIONへ
                break;
            case 6:
                DxLib_End();
                break;
            default:
                printfDx("不明なメニューが選択されました\n");
                break;
        }
        menu=0;
    }
}


以上のようなプログラムで表示をしています。
 
龍神録や東方では、これらの項目は、斜めに並べて表示されたりしているので、①の方法が知りたいです。
また、例えばスペルプラクティスの選択画面では、項目が一画面に入りきらず、画面の下端を越えて表示されてしまうので、②を実装したいと考えています。
 
アドバイスよろしくおねがいします。
 


     画像

kazuoni

Re:選択画面の拡張

#5

投稿記事 by kazuoni » 15年前

1,「GAME START」や、「OPTION」などのような、選択する項目それぞれに座標を設定する方法

例えばDrawStringでx,yを指定する、
DrawGraphでx,yを指定するという回答では不足でしょうか?^^;
構造体などで、選択文字、座標、色などをまとめて管理するとよいかと。


2, 添付画像のように、選択項目が一画面に入りきらない場合、次のページを用意して、残りの項目を表示する方法

添付画像がないので分かりませんが・・・
例えば、メニュー画面で右を押したら次のメニューが表示されるとかですかね。
これも選択画面と同じように右キーが押されたらメニュー欄更新
とすればよいかと。

3, 現在、選択項目には文字を使っているのですが、画像を項目として使用することはできるのでしょうか。
DrawStringをDrawGraphに変えればよいです。

#丸1などは環境依存文字ですので、なるべく避けた方が良いようです。

yrao

Re:選択画面の拡張

#6

投稿記事 by yrao » 15年前

kazuoniさんどうもです。
(画像添付ミス、すいませんでした)
 
②、③については解決することができたのですが、
①の、

>DrawStringでx,yを指定する
>構造体などで、選択文字、座標、色などをまとめて管理する。

について、よく分からないので詳しく教えてくださいm(__)m

今のところ、表示する文字列のみ個々に指定できるようになっているのですが、座標、色なども個別に設定できるようにするには、どのように書きかえればよいのでしょうか。
文字列と同じように、x座標、y座標の配列を用意し指定する、ということはできるのでしょうか。



 

 

softya

Re:選択画面の拡張

#7

投稿記事 by softya » 15年前

>今のところ、表示する文字列のみ個々に指定できるようになっているのですが、座標、色なども個別に設定できるようにするには、どのように書きかえればよいのでしょうか。
>文字列と同じように、x座標、y座標の配列を用意し指定する、ということはできるのでしょうか。

出来ます。
敵やボスキャラクタは、すでに構造体配列で管理されているなら難しいところはありません。

出来ないと考える理由はなんでしょうか?
今後の回答の参考になりますので、ぜひ聞かせて下さい。
※ 責めているわけありません。敵を構造体で管理出来て、この処理が出来ないのが純粋に不思議なだけです。 画像

kazuoni

Re:選択画面の拡張

#8

投稿記事 by kazuoni » 15年前

> 座標、色なども個別に設定できるようにするには、どのように書きかえればよいのでしょうか。
> 文字列と同じように、x座標、y座標の配列を用意し指定する、ということはできるのでしょうか。

ごめんなさい。よく現状が把握できません。
自分が言いたかったのは、
DrawString(x1,y1,str1,color1);
DrawString(x2,y2,str2,color1);
DrawString(x3,y3,str3,color1);
よりは
typedef struct
{
    int x,y,color;
    char *str;
}MenuData;

MenuData mData[3];

// 各データをmDataにセット

for(int i=0 ; i<3 ; ++i)
    DrawString(mData.x,mData.y,mData.str,mData.color);

のほうが管理しやすいですよって事です。

# 丸1などは環境依存文字ですので、なるべく避けた方が良いようです。
# 丸1などは環境依存文字ですので、なるべく避けた方が良いようです。 画像

yrao

Re:選択画面の拡張

#9

投稿記事 by yrao » 15年前

>softyaさん

できないと考える理由ですか・・・
記載した選択画面の処理の意味を完全に理解できていないからだと思います。(ポインタの部分など特に)
そのため、構造体を作ったとしても、プログラムのどの部分をどのように変更すればいいのか分からないのです;


>kazuoniさん

> DrawString(x1,y1,str1,color1);
> DrawString(x2,y2,str2,color1);
> DrawString(x3,y3,str3,color1);
> よりは
> typedef struct
> {
> int x,y,color;
> char *str;
> }MenuData;
>
> MenuData mData[3];
>
> // 各データをmDataにセット
>
> for(int i=0 ; i<3 ; ++i)
> DrawString(mData.x,mData.y,mData.str,mData.color);
> のほうが管理しやすいですよって事です。


自分がやりたかったのはそういうことです。
 
kazuoniさんのソースを参考に、とりあえずx座標、y座標を個別に設定できるようにしてみようと思い、
 
--strct.h--

typedef struct{
    int x,y;
}MenuData;


--define.h--

//メニュー項目の最大数
#define MENU_MAX 30

--Gv.h--

GLOBAL MenuData mData[MENU_MAX];


ここまでは書いてみたのですが、

//項目の表示
    
i=0;
while ( *str ){         
    dx = x - GetDrawFormatStringWidthToHandle( font[0] , *str ) / 2;    DrawFormatStringToHandle(dx,y,color[0],font[0],"%s",*str++);
    y += 30; 
    if( i++ > 50 )break;    //無限ループ防止
}



この部分をどう書きかえればよいか分かりません・・・
 
まず、赤文字にした部分ですが、x,y座標はmData.x,mData.yでそれぞれ設定するので、これらの処理はいらないですよね?

次に、青文字にした部分ですが、この部分はどのように変更すればよいでしょうか。
for(int i=0;i<MENU_MAX;i++){
・・・
}
と書きかえればよいのでしょうか?

yrao

Re:選択画面の拡張

#10

投稿記事 by yrao » 15年前

すいません文字に色がつきません・・・

赤文字の部分というのは、

  dx = x - GetDrawFormatStringWidthToHandle( font[0] , *str ) / 2;
y += 30;
i=0;

で、青文字の部分というのは


while ( *str ){
 
  ・・・ 

 if( i++ > 50 )break; //無限ループ防止
}

です。

kazuoni

Re:選択画面の拡張

#11

投稿記事 by kazuoni » 15年前

> x,y座標はmData.x,mData.yでそれぞれ設定するので、これらの処理はいらないですよね?
初期化の際にこれを行いますが、毎ループ求める必要はないですね。
よって、ここでは必要ありません。

> 青文字にした部分ですが、この部分はどのように変更すればよいでしょうか。
> for(int i=0;i<MENU_MAX;i++){
> と書きかえればよいのでしょうか?
おっしゃる通りです。
とりあえず、試してみてください。

yrao

Re:選択画面の拡張

#12

投稿記事 by yrao » 15年前

試してみました。
     //項目の表示
    for(int i=0;i<MENU_MAX;i++){
        DrawFormatStringToHandle(mData.x,mData.y,color[0],font[0],"%s",*str++);
    }

void menu_game(){//タイトル画面
    char *str[10]={
        {"GAME START"},
        {"SPELL PRACTICE"},
        {"REPLAY"},
        {"GALLERLY"},
        {"RESULT"},
        {"OPTION"},
        {"QUIT"}
    };
    for(int i=0;i<MENU_MAX;i++){
        mData.x=20+i*20;
        mData.y=50+i*5;
    }    
    //mData[10].x={50,55,60,65,70,75,80}
    //mData[10].y={50,70,90,110,130,150,200}
    static int menu;

    MenuDraw( 520 , FY+FMY/3 , "" , str , &menu);

    if( CheckStatePad(configpad.shot) == 1 ){
        switch(menu){
            case 0:
                func_state = 90;    //難易度選択へ
                break;
            case 1:
                func_state = 20;    //SPELL PRACTICEへ
                break;
            case 2:
                func_state = 30;    //REPLAYへ
                break;
            case 3:
                func_state = 40;    //GALLERLYへ
                break;
            case 4:
                func_state = 50;    //RESULTへ
                break;
            case 5:
                func_state = 60;    //OPTIONへ
                break;
            case 6:
                DxLib_End();
                break;
            default:
                printfDx("不明なメニューが選択されました\n");
                break;
        }
        menu=0;
    }
}



しかしこれだと、『ハンドルされていない例外が発生しました』というメッセージがでてしまいます。

それと、今の座標の設定の仕方では、座標を等間隔にずらすことしかできていません;
char *str[10]={
    {"GAME START"},
    {"SPELL PRACTICE"},
    {"REPLAY"},
    {"GALLERLY"},
    {"RESULT"},
    {"OPTION"},
    {"QUIT"}
};

のような方法で座標も設定したいのですが。。。

softya

Re:選択画面の拡張

#13

投稿記事 by softya » 15年前

とりあえず、メニューだけので動くプロジェクトを作ってみた方が良いでしょう。
良く分からないまま、いじっていても良く分からないプログラムが出来るだけです。
プログラムで将来変更したくなったときに自分で変更出来無いものが出来ても仕方がありません。ここは、じっくり機能が理解出来るようにシンプルな物を組んでみてはどうでしょう?
いや、そんな事はないと言うなら私は止めませんが。

kazuoni

Re:選択画面の拡張

#14

投稿記事 by kazuoni » 15年前

softyaさんと同意見です。

とりあえず、これ辺が怪しいというところを。

> *str++
これって、ポインタ進めてしまって大丈夫ですか?


> それと、今の座標の設定の仕方では、座標を等間隔にずらすことしかできていません;
> のような方法
「のような方法」という方法が、どういうことかよくわかりません。
一つずつ座標設定すればよいのでは?

conio

Re:選択画面の拡張

#15

投稿記事 by conio » 15年前

>>char *str[10]={
>>    {"GAME START"},
>>    {"SPELL PRACTICE"},
>>    {"REPLAY"},
>>    {"GALLERLY"},
>>    {"RESULT"},
>>    {"OPTION"},
>>    {"QUIT"}
>>};
>>のような方法で座標も設定したいのですが。。。


↓こんな感じでしょうか?
-------------------------------------------------------------------------------
typedef struct{
    char* Name;
    int ptX;
    int ptY;
}MENU;


const MENU m[/url] = {    {"aiueo", 30, 0},
                    {"kakikukeko", 30, 30},
                    {"sasisuseso", 30, 60}    };
-------------------------------------------------------------------------------

少年X

Re:選択画面の拡張

#16

投稿記事 by 少年X » 15年前

僕はtitle_selectという関数を作り、中身は
int Key_count;
という変数を用意して、

if(上ボタンが押されたら){
Key_count--;
if(Key_count==-1)Key_count=5;
}

if(下ボタンが押されたら){
Key_count++;
if(Key_count==6)Key_count=0;
}

あとは、Key_countの値から座標を決めるなり、配列の番号を指定して画像を切り替えたりできると思います。
説明不足ですみません。

yrao

Re:選択画面の拡張

#17

投稿記事 by yrao » 15年前

返答遅れてしまって申し訳ないです。
 
>conioさん
>少年Xさん
 
回答どうもありがとうございます。とても参考になりました。
 
>softyaさん
>kazuoniさん

確かにシンプルなプログラムから作って理解していくのが正統法で、確実な勉強法だと思います。

今現在のプログラムを理解するというのは駄目でしょうか?(すみません今回あまり時間がないのです・・・)

どうもこのプログラムはポインタについて勉強しないと理解できなさそうだと思ったので、一応、基礎的な部分だけですが勉強してきました。
 
そこで改めて書いてみたのが以下のプログラムなのですが、エラーが幾つか発生してしまっています。
改善方法だけでもアドバイスいただければ幸いです。

_________________________________________________
void MenuDraw(int x[/url],int y[/url] , char title[/url] , char **str , int *menu ){
    int num=0,i=0;
    int dx=0,len=0;
    char **str2 = str;
    

    
    //情報の取得
    while ( *str2 ){
        if( len < GetDrawFormatStringWidthToHandle( font[0] , *str2 ) ){
            len = GetDrawFormatStringWidthToHandle( font[0] , *str2 );//文字列の長さ所得
        }
        ++num;
        *str2++;
        

        if( i++ > 50 )    break;    //無限ループ防止
    }
    

    //選択制御
    if( CheckStatePad(configpad.up)   == 1 && *menu > 0 )        
        --*menu;//選択を一つ上に
    else if( CheckStatePad(configpad.up)   == 1 )                
        *menu = num-1;//上端なら、一番下の選択(num-1)へ
    
    if( CheckStatePad(configpad.down) == 1 && *menu < num-1 )    
        ++*menu;//選択を一つ下に
    else if( CheckStatePad(configpad.down) == 1 )                
        *menu = 0;    //下端なら、一番上の選択(0)へ

      
    
    
    SetDrawBlendMode( DX_BLENDMODE_ALPHA , 100 ) ;//四角描画用にアルファブレンド
    DrawBox( &x[num],&y[num],&x[num]+10+len,&y[num]+ 18,color[0],TRUE) ;    //選択位置の表示
    SetDrawBlendMode( DX_BLENDMODE_NOBLEND , 0 ) ;//描画もどす
    
    
    i=0;
    while ( *str ){
        DrawFormatStringToHandle(&x[num],&y[num],color[0],font[0],"%s",*str++);
    if( i++ > 50 )    break;    //無限ループ防止
    }
    

}
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
void menu_game(){//タイトル画面
    char *str[10]={
        {"GAME START"},
        {"SPELL PRACTICE"},
        {"REPLAY"},
        {"GALLERLY"},
        {"RESULT"},
        {"OPTION"},
        {"QUIT"}
    };
    int x[10]={
        200,250,200,200,200,200,200
    };
    int y[10]={
        100,130,160,190,220,250,280
    };
    int* xP=x;
    int* yP=y;
    
    static int menu;

    MenuDraw( &xP , &yP , "" , str , &menu);

    if( CheckStatePad(configpad.shot) == 1 ){
        switch(menu){
            case 0:
                func_state = 90;    //難易度選択へ
                break;
            case 1:
                func_state = 20;    //SPELL PRACTICEへ
                break;
            case 2:
                func_state = 30;    //REPLAYへ
                break;
            case 3:
                func_state = 40;    //GALLERLYへ
                break;
            case 4:
                func_state = 50;    //RESULTへ
                break;
            case 5:
                func_state = 60;    //OPTIONへ
                break;
            case 6:
                DxLib_End();
                break;
            default:
                printfDx("不明なメニューが選択されました\n");
                break;
        }
        menu=0;
    }
}
 
_________________________________________________

*エラー内容*

DrawBox( &x[num],&y[num],&x[num]+10+len,&y[num]+ 18,color[0],TRUE) ;

DrawFormatStringToHandle(&x[num],&y[num],color[0],font[0],"%s",*str++);
の部分で、

1 番目の引数を 'int *__w64 ' から 'int' に変換できません。(新しい機能 ; ヘルプを参照)
 
というエラー
 
MenuDraw( &xP , &yP , "" , str , &menu);
の部分で、

1 番目の引数を 'int **__w64 ' から 'int [/url]' に変換できません。(新しい機能 ; ヘルプを参照)
 
というエラー
 
 
以上3つのエラーです。

調べてみたところ、
'int *__w64 ' から 'int' に変換できません
というエラーは、データにアドレスを代入しているためにおこるらしいのですが・・・
ポインタについて勉強不足なゆえ、改善方法が分かりません;
ご教授お願いします。

kazuoni

Re:選択画面の拡張

#18

投稿記事 by kazuoni » 15年前

引数に座標の配列を渡す必要があるかどうかは置いておいて・・・

> MenuDraw( &xP , &yP , "" , str , &menu);
ではなく
> MenuDraw( x , y , "" , str , &menu);
でコンパイルは通るのではないでしょうか。

yrao

Re:選択画面の拡張

#19

投稿記事 by yrao » 15年前

kazuoniさんどうもです。
 
エラーのでていた三つの処理を、kazuoniさんがおっしゃったように変更したところ、コンパイルは通りました。
 
ですが、項目すべてが(0,0)の位置に表示されてしまいます。。。

kazuoni

Re:選択画面の拡張

#20

投稿記事 by kazuoni » 15年前

DrawBoxの渡す引数で&x[num]...等ととしていますが、ここも修正しましたか?

まだポインタの基礎が理解できていないようです。
> 今現在のプログラムを理解する
と書いていますが、現在のプログラムが正しくないので、
理解する以前の問題になります。
時間がないとのことですが、このまま曖昧で進めば、
いずれまたポインタで躓くかと思われます。
もう一度基礎を固めることをお勧めします。
その方がここで返事を待つ時間が経り、最終的に早く開発がすすめられます。

また、0になぜなっているのかデバッガで順に追ってみてください。
VC++ならブレークポイントを張るなど。
画像

yrao

Re:選択画面の拡張

#21

投稿記事 by yrao » 15年前

> DrawBoxの渡す引数で&x[num]...等ととして「ますが、ここも修正しましたか?

x[num]...
の用に変更しました。
[num]がまちがっているのでしょうか?

> > 今現在のプログラムを理解する
> と書いていますが、現在のプログラムが正しくないので、
> 理解する以前の問題になります。

すみませんこれは、プログラミングの支館の選択画面のプログラムを理解する、という意味でした・・・


> まだポインタの基礎が理解できていないようです。
> 時間がないとのことですが、このまま曖昧で進めば、
> いずれまたポインタで躓くかと思われます。
> もう一度基礎を固めることをお勧めします。
> その方がここで返事を待つ時間が経り、最終的に早く開発がすすめられます。

分かりました。
具体的に、今回ポインタについてこの部分を理解した方が良い、という所はありますでしょうか。

softya

Re:選択画面の拡張

#22

投稿記事 by softya » 15年前

>今現在のプログラムを理解するというのは駄目でしょうか?(すみません今回あまり時間がないのです・・・)

これは初耳ですね。課題か何かですか?
いつがリミットでしょうか?

>すみませんこれは、プログラミングの支館の選択画面のプログラムを理解する、という意味でした・・・

支館の何処の部分が理解できないか分からないので答えようが無いです。

>具体的に、今回ポインタについてこの部分を理解した方が良い、という所はありますでしょうか。

ポインタを使わなくて良い所で使わない事。今回のメニュー処理で文字列ポインタ以外は必要ないと思うんですが。配列はちゃんと配列として使いましょう。
慣れないポインタや配列の引数で苦労するぐらいなら、初めから配列やポインタを引数としてなるべく使わないで済ませる様工夫をしてください。
今回ごちゃごちゃしているのは、ポインタ以前に関数や関数の引数、構造体や変数の初期化など基本的なことが分かっていない事がほぼ原因です。なので問題点は全般的と言えると思います。

yrao

Re:選択画面の拡張

#23

投稿記事 by yrao » 15年前

>課題か何かですか?

課題ではないです。趣味での制作です。



>ポインタを使わなくて良い所で使わない事。今回のメニュー処理で文字列ポインタ以外は必要ないと思うんですが。配列はちゃんと配列として使いましょう。
>慣れないポインタや配列の引数で苦労するぐらいなら、初めから配列やポインタを引数としてなるべく使わないで済ませる様工夫をしてください。
>今回ごちゃごちゃしているのは、ポインタ以前に関数や関数の引数、構造体や変数の初期化など基本的なことが分かっていない事がほぼ原因です。なので問題点は全般的と言えると思います。

softyaさんのご指摘どおり、ポインタを使わずにプログラムを書いてみました。
今回は、項目も指定した座標で表示することができたのですが、やはり不具合が出てしまっています。
アドバイスよろしくお願いしますm(__)m

__________________________________________________

struct.h に、以下を追加
typedef struct{
  int MenuNum;
}MenuData;
GV.h に、以下を追加
GLOBAL MenuData mData;


ini.cpp内、ini()に、以下を追加
memset(&mData,0,sizeof(MenuData));

control.cpp内に、以下を追加
void MenuDraw(int x[50],int y[50] , char title[/url] , char **str , int *menu){
    int num=0,i=0;
    int dx=0,len=0;
    char **str2 = str;
    
    
    

    
    //情報の取得
    while ( *str2 ){
        if( len < GetDrawFormatStringWidthToHandle( font[0] , *str2 ) ){
            len = GetDrawFormatStringWidthToHandle( font[0] , *str2 );//文字列の長さ所得
        }
        
        ++num;
        *str2++;
        

        if( i++ > 50 )    break;    //無限ループ防止
    }
    
    
    //選択制御
    if( CheckStatePad(configpad.up)   == 1 && *menu > 0 ){        
        --*menu;//選択を一つ上に
        mData.MenuNum--;
    }
    else if( CheckStatePad(configpad.up)   == 1 ){                
        *menu = num-1;//上端なら、一番下の選択(num-1)へ
        mData.MenuNum=num-1;
    }
    
    if( CheckStatePad(configpad.down) == 1 && *menu < num-1 ){    
        ++*menu;//選択を一つ下に
        mData.MenuNum++;
    }
    else if( CheckStatePad(configpad.down) == 1 ){                
        *menu = 0;    //下端なら、一番上の選択(0)へ
        mData.MenuNum=0;
    }
    
    
    
    if ( *str ){
        
        SetDrawBlendMode( DX_BLENDMODE_ALPHA , 100 ) ;//四角描画用にアルファブレンド
        DrawBox(x[mData.MenuNum],y[mData.MenuNum],x[mData.MenuNum]+10+len,y[mData.MenuNum]+ 18,color[0],TRUE) ;    //選択位置の表示
        SetDrawBlendMode( DX_BLENDMODE_NOBLEND , 0 ) ;//描画もどす
    }
    
    
    
    i=0;
    while ( *str ){
        DrawFormatStringToHandle(x,y,color[0],font[0],"%s",*str++);
        
        
    if( i++ > 50 )    break;    //無限ループ防止
    }
    

}
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
void menu_game(){//タイトル画面
    char *str[10]={
        {"GAME START"},
        {"SPELL PRACTICE"},
        {"REPLAY"},
        {"GALLERLY"},
        {"RESULT"},
        {"OPTION"},
        {"QUIT"}
    };
    int x[10]={
        100,110,122,136,152,170,190
    };
    int y[10]={
        200,230,260,290,320,350,380
    };
    
    static int menu;

    MenuDraw( x , y , "" , str , &menu);

    if( CheckStatePad(configpad.shot) == 1 ){
        switch(menu){
            case 0:
                func_state = 90;    //難易度選択へ
                break;
            case 1:
                func_state = 20;    //SPELL PRACTICEへ
                break;
            case 2:
                func_state = 30;    //REPLAYへ
                break;
            case 3:
                func_state = 40;    //GALLERLYへ
                break;
            case 4:
                func_state = 50;    //RESULTへ
                break;
            case 5:
                func_state = 60;    //OPTIONへ
                break;
            case 6:
                DxLib_End();
                break;
            default:
                printfDx("不明なメニューが選択されました\n");
                break;
        }
        menu=0;
    }
}



以上のように書いてみたのですが、mData.MenuNumの値が毎回リセットされないので、例えば、二つ目の項目(SPELL PRACTICE)を選択した場合、次の画面、つまりスペルプラクティスの選択画面では、最初から二つ目の項目にカーソルが合っている状態になってしまいます。また、それによって、選択項目の文字列と実際の結果もずれてしまいます。



case 0:
    mData.MenuNum=0;
         func_state = 90;    //難易度選択へ
    break;
case 1:
    mData.MenuNum=0;
         func_state = 20;    //SPELL PRACTICEへ
    break;
・
・
・
・
・


のようにしたところ、解決はしたのですが、すべての条件分木でこの処理を書かなくてはならないのは効率が悪い気がします・・・

kazuoni

Re:選択画面の拡張

#24

投稿記事 by kazuoni » 15年前

> 二つ目の項目(SPELL PRACTICE)を選択した場合、次の画面、
>つまりスペルプラクティスの選択画面では、
>最初から二つ目の項目にカーソルが合っている状態になってしまいます。

menu=0;
の下に
mData.MenuNum=0;
と付け加えればよいだけの様に思いますが。

> 効率が悪い気がします・・・
それをいうと、menuとmData.MenuNumってなにが違うの?
そもそもmDataって必要なの?何のための構造体なの?
などという考え方も出てきてしまうのですが。。

閉鎖

“C言語何でも質問掲示板” へ戻る