• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:win32api 教えてください。)

win32apiのバグによる問題と解消法

このQ&Aのポイント
  • RPG作成時に発生するwin32apiのバグについて質問です。
  • 文字入力やメインウィンドウの表示に関する問題が発生しています。
  • バグの解消法について教えていただきたいです。

質問者が選んだベストアンサー

  • ベストアンサー
回答No.7

> Para=(rand() % (MDATE[monsNo].MonsLv+2))+MDATE[monsNo].PARA; ここの計算部分が怪しいので、下記の各変数の値が思った通りになっているか確認しましょう。 monsNo MDATE[monsNo].MonsLv MDATE[monsNo].PARA 開発環境がわかりませんが、デバッグウィンドウが使用できるならそこに表示させれば確認できますし、なければ一時的に > wsprintf(GetPARA,L"%sは%ldパラを得た。",NAME,Para); のParaの部分を置き換えてやれば確認できますよね。

crashbeen
質問者

お礼

丁寧な説明、ありがとうございました。 解決しました。   すいませんが、この質問は削除します。(クソゲーですが、念のため

crashbeen
質問者

補足

Paraの部分を変えてみましたが、まったく改善されませんでした。

その他の回答 (6)

回答No.6

>逆にメモリの確保しすぎでもなりますか? 文字列を扱う関数は、\0が来れば文字列が終わったと判定するので、それより後に何が入っていようと問題にならないはずです。無駄に大量に確保しようとしてメモリ不足とかにならなければ。

crashbeen
質問者

お礼

丁寧な説明、ありがとうございました。 解決しました。   すいませんが、この質問は今夜削除します。(クソゲーですが、念のため

crashbeen
質問者

補足

ありがとうございました。 文字が別のウィンドウに描画される現象は改善されましたが、数字(所持金)が異常な数字になるのがわからないです。 static long Para=0,SYOJIPARA=0; static TCHAR GetPARA[50],NAME[50],nowpara[50]; Para=0; Para=(rand() % (MDATE[monsNo].MonsLv+2))+MDATE[monsNo].PARA; wsprintf(GetPARA,L"%sは%ldパラを得た。",NAME,Para); TextOut(hdcv,150,270,GetPARA,lstrlen(GetPARA)); SYOJIPARA+=Para; EX+=MDATE[monsNo].MonsKeiken; wsprintf(nowpara,L"所持金: %ldパラ",SYOJIPARA);

回答No.5

>描画する部分を消してもでてきました ならば、文字列の変数の領域を超えていないか確認しましょう。 例えば、 wchar_t test1[5], test2[10]; lstrcpy(test1, L"あいうえお"); とすると、test1には5文字分しかメモリが確保されていないのに あいうえお\0 の6文字が格納されます。6文字目は別の変数の領域などにはみ出している形になります。 ここで、test2がたまたまtest1の後ろに確保されているとして、 lstrcpy(test1, L"あいうえお"); lstrcpy(test2, L"かきくけこ"); というコードを実行すると、最初の命令ではみ出した部分はtest2[0]に入ってしまい、そのあとの命令で\0が上書きされるため、メモリ上では あいうえおかきくけこ\0 という並びになります。ここで、test1をTextOutなどで表示させると、test1には入れていないはずの"かきくけこ"まで表示されてしまいます。 こういった部分を検証するために、変数の定義を何度も聞いているのですが。おそらく、関係ないと思ったのでしょうが、原因がわからないバグは、自分が関係ないと思っている部分が影響していることが多いです。「こうなるはず」とか「こうなっているはず」という考えを捨てて、1つ1つ考えた通りに動作しているか確認していくことが、結局は早道だと思いますよ。その経験が積み重なっていくと、最初に何を確認したらよいかという優先順位がわかってくると思います。 あと、wsprintfじゃなくlstrcpyを使う理由は、何をするための命令かがわかりやすいことと、wsprintfは書式文字列を解析して文字列を格納するので、単純に文字列をコピーするlstrcpyよりも内部で実行される命令が多くなる(=遅くなる)ことです。 他人がソースを見たとき(あるいは、自分が見たときでも、時間がたって内容をよく覚えていないようなとき)には、wsprintfが使われていて、wParamといった引数が無意味な状態になっていると、書式文字列を間違っている可能性を考えてしまいます。

crashbeen
質問者

お礼

消せない・・・ まあいいか。   ありがとうございました。

crashbeen
質問者

補足

なるほど。 lstrcpyについてはやってみます 逆にメモリの確保しすぎでもなりますか?

回答No.4

> 「VisualWndの文字」がです で、そのウィンドウの描画部分はまたまた内緒ですか。 >wsprintfはTEXTがないとエラーがでました 単にTEXTを外すとエラーになるでしょう。私は L"あ" とすればと書いています。 あと、lstrcpyじゃいけない理由は何なんでしょうか?

crashbeen
質問者

補足

wsprintfで格納した("%sは%ldパラを得た")がでてくるんです 描画する部分を消してもでてきました あと、lstrcpyじゃないといけない理由は何でしょうか?(けしかけるようですいません

回答No.3

>StetasWnd >には基本ステータス(TextOut)しか表示されないはずなのに、 >メインウィンドウの文字がStetasWndに描画されてしまいます。 という現象なのに、メインウィンドウのウィンドウプロシージャを内緒にして解決すると思います? それに、hWndの子ウィンドウと書かれてるけど、hWndはウィンドウプロシージャの引数として出てくるだけで、そこにはSatesWndかNameWndが入ってるはずなので、意味が不明です。(ちなみに、ステータスは「Status」と書きます) 所持金についても、Paraのことなんでしょうが変数の型は相変わらず不明だし、計算に使用している変数も同様に不明じゃ、原因なんかわかりません。 >wsprintf(MOJI,TEXT("あ"),wParam); lstrcpy(MOJI,TEXT("あ")); じゃだめなんですか? wParamなんて必要ないと思いますけど。 MOJIに1文字しか入らない仕様なら、もっと違うやり方があるし、wsprintfなんだからTEXTマクロ使わずにL"あ"でいいと思いますけど。 あと、ウィンドウプロシージャでウィンドウハンドルをhWndで受け取ったのなら、WM_PAINTの処理でもhWndを使ったほうがいいですよ。複数のウィンドウでウィンドウプロシージャを共有することになった場合に、書き直す部分が少なくなります。

crashbeen
質問者

補足

いろいろ焦ってて、間違えてます 「VisualWndの文字」がです プロシージャの引数はNameWnd、StatesWndにしました(ご指摘をうけるまえに) 書き方は(つづりとか)それぞれだとおもいますが wsprintfはTEXTがないとエラーがでました 変数は全てstaticな変数にしてあります 所持金、ステータスは static long です

回答No.2

部分的にコードを提示されても、変数(と思われるもの)の型とかがまったくわかりませんし、ウィンドウをどのように描画しているのかも提示せずに「基本ステータス(TextOut)しか表示されないはずなのに」とかいわれても、検証のしようがありません。 > wsprintf(HITOMOJI,TEXT(""),wParam); これでちゃんと文字が入るんですか? 何か全然コードの書き方を理解していないように思えますが。

crashbeen
質問者

補足

恥ずかしながらコードを掲載します。 これが、問題の描画部分。   LRESULT CALLBACK StatesProc ( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) { switch(uMsg) { case WM_DESTROY: DestroyWindow(StatesWnd); return 0; case WM_PAINT: hdcs = BeginPaint(StatesWnd,&ps); TextOut(hdcs,10,10,(LPCWSTR)States,lstrlen((LPCWSTR)States)); TextOut(hdcs,10,30,(LPCWSTR)lv,lstrlen((LPCWSTR)lv)); TextOut(hdcs,15,55,(LPCWSTR)nowhp,lstrlen((LPCWSTR)nowhp)); TextOut(hdcs,15,75,(LPCWSTR)nowmp,lstrlen((LPCWSTR)nowmp)); TextOut(hdcs,20,95,(LPCWSTR)str,lstrlen((LPCWSTR)str)); TextOut(hdcs,20,115,(LPCWSTR)bougyo,lstrlen((LPCWSTR)bougyo)); TextOut(hdcs,15,135,(LPCWSTR)nowex,lstrlen((LPCWSTR)nowex)); TextOut(hdcs,15,155,(LPCWSTR)nowpara,lstrlen((LPCWSTR)nowpara)); EndPaint(StatesWnd,&ps); return 0; } return DefWindowProc(hWnd , uMsg , wParam , lParam); } StatesWndというウィンドウで親ウィンドウは、hWndです。 HDC hdcs;となっているのは、原因がわからなかったので、とりあえず それぞれの処理で分けてみましたけど、うまくいかないです これが、 switch(wParam){ case KOUGEKI_ID: playerattack=0; monsattack=0; Para=0; playerattack=(rand() % (Lv+1)+STR)- (MDATE[monsNo].MonsBOUGYO); monsattack=(rand() % (MDATE[monsNo].MonsLv+1)+MDATE[monsNo].MonsSTR) - BOUGYO; Para=(rand() % (MDATE[monsNo].MonsLv+2))+MDATE[monsNo].PARA; if(playerattack<0){ playerattack=0; }else if(monsattack<0){ monsattack=0; } wsprintf(MonsterName,MDATE[monsNo].MonsName,wParam); wsprintf(PlayerAttack,TEXT("%sに%ldのダメージ!"),MDATE[monsNo].MonsName,playerattack); wsprintf(MonsterAttack,TEXT("%sに%ldのダメージ!"),NAME,monsattack); wsprintf(GetKeiken,TEXT("%sは%ldの経験値を得た。"),NAME,MDATE[monsNo].MonsKeiken); wsprintf(GetPARA,TEXT("%sは%ldパラを得た。"),NAME,Para); HP-=monsattack; (MDATE[monsNo].MonsHP)-=playerattack; wsprintf(nowhp,TEXT("HP: %ld/%ld"),HP,MAXHP); battle=1; InvalidateRect(StatesWnd,NULL,FALSE); InvalidateRect(VisualWnd,NULL,FALSE); break; } この処理の箇所でおかしくなります。 これはVisualWndというウィンドウで、hWndの子ウィンドウです。   それで、文字入力の部分。     LRESULT CALLBACK NameProc ( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) { switch(uMsg) { case WM_DESTROY: DestroyWindow(NameWnd); case WM_PAINT: hdcn = BeginPaint(NameWnd,&ps); MoveToEx(hdcn,50,150,NULL); LineTo(hdcn,70,150); MoveToEx(hdcn,75,150,NULL); LineTo(hdcn,95,150); MoveToEx(hdcn,100,150,NULL); LineTo(hdcn,120,150); MoveToEx(hdcn,125,150,NULL); LineTo(hdcn,145,150); MoveToEx(hdcn,150,150,NULL); LineTo(hdcn,170,150); MoveToEx(hdcn,175,150,NULL); LineTo(hdcn,195,150); if(ni==1){ TextOut(hdcn,50,130,HITOMOJI,lstrlen(HITOMOJI)); }else if(san==1){ TextOut(hdcn,75,130,HUTAMOJI,lstrlen(HUTAMOJI)); }else if(yon==1){ TextOut(hdcn,100,130,SANMOJI,lstrlen(SANMOJI)); }else if(go==1){ TextOut(hdcn,125,130,YONMOJI,lstrlen(YONMOJI)); }else if(roku==1){ TextOut(hdcn,150,130,GOMOJI,lstrlen(GOMOJI)); }else if(nana==1){ TextOut(hdcn,175,130,ROKUMOJI,lstrlen(ROKUMOJI)); } EndPaint(NameWnd,&ps); return 0; case WM_COMMAND: if(iti==1){ InvalidateRect(NameWnd,NULL,FALSE); }else if(ni==1){ InvalidateRect(NameWnd,NULL,FALSE); }else if(san==1){ InvalidateRect(NameWnd,NULL,FALSE); }else if(yon==1){ InvalidateRect(NameWnd,NULL,FALSE); }else if(go==1){ InvalidateRect(NameWnd,NULL,FALSE); }else if(roku==1){ InvalidateRect(NameWnd,NULL,FALSE); }else if(nana==1){ InvalidateRect(NameWnd,NULL,FALSE); } switch(LOWORD(wParam)) { case ADAN_ID: if(agyou==1){ if(hiragana==1){ if(komoji==1){ wsprintf(MOJI,TEXT("ぁ"),wParam); }else{ wsprintf(MOJI,TEXT("あ"),wParam); } }else{ if(komoji==1){ wsprintf(MOJI,TEXT("ァ"),wParam); }else{ wsprintf(MOJI,TEXT("ア"),wParam); } } }else if(yagyou==1){ if(hiragana==1){ if(komoji==1){ wsprintf(MOJI,TEXT("ゃ"),wParam); }else{ wsprintf(MOJI,TEXT("や"),wParam); } }else{ if(komoji==1){ wsprintf(MOJI,TEXT("ャ"),wParam); }else{ wsprintf(MOJI,TEXT("ヤ"),wParam); } } }   ・・・・・・・・・・・・・・ break;   長いのでここまでで。 わをん、濁点、半濁点はうまくいってないのでまだ途中です。 また、カタカナ、ひらがなの切り替え、小文字大文字の切り替えがあります。 ちゃんと、実行して思い通りの処理をしてくれています。   ヘタながら、書き方はわかっているつもりではあります。  

  • LOHA
  • ベストアンサー率52% (203/388)
回答No.1

>※うまく説明できてませんがお願いします。 の通り、残念ながらいったい何が起こっているのか完全に不明です。 該当部分のソースコードを漏れなく掲載するなどした方がよい回答が得られるかと思います。 >wsprintf(HITOMOJI,TEXT(""),wParam); 少なくともwsprintfの第二引数が空文字列なのはおかしいと思います。 http://msdn.microsoft.com/ja-jp/library/cc364872.aspx

crashbeen
質問者

お礼

ありがとうございました。 解決しました。   すいませんが、この質問は削除します。(クソゲーですが、念のため

crashbeen
質問者

補足

TEXTのとこには あ~んが入ります。 書き忘れてました、すいません ソースコードをそのまま載せるのが恥ずかしかったので…

関連するQ&A