![](http://oshiete.xgoo.jp/images/v2/pc/qa/question_title.png?e8efa67)
いつもお世話になっております。
いま、RPGを作っているのですが、
名前をボタンで入力して
wsprintf(HITOMOJI,TEXT(""),wParam);
~wsprintf(ROKUMOJI,TEXT(""),wParam);
wsprintf(Name,TEXT("%s%s%s%s%s%s"),HITOMOJI~ROKUJIMO);
とやっているのですが、
入力1文字は問題なしで、
6文字だと
その後の処理(戦闘)で、
StetasWnd
には基本ステータス(TextOut)しか表示されないはずなのに、
メインウィンドウの文字がStetasWndに描画されてしまいます。
さらに、所持金は10~13しか追加されないはずなのに、
800000000000000とか、ありえない桁数になるんです。
いわゆるバグですが、これの解消法はありますでしょうか?
※うまく説明できてませんがお願いします。
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の部分を置き換えてやれば確認できますよね。
No.6
- 回答日時:
>逆にメモリの確保しすぎでもなりますか?
文字列を扱う関数は、\0が来れば文字列が終わったと判定するので、それより後に何が入っていようと問題にならないはずです。無駄に大量に確保しようとしてメモリ不足とかにならなければ。
この回答への補足
ありがとうございました。
文字が別のウィンドウに描画される現象は改善されましたが、数字(所持金)が異常な数字になるのがわからないです。
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といった引数が無意味な状態になっていると、書式文字列を間違っている可能性を考えてしまいます。
No.4
- 回答日時:
> 「VisualWndの文字」がです
で、そのウィンドウの描画部分はまたまた内緒ですか。
>wsprintfはTEXTがないとエラーがでました
単にTEXTを外すとエラーになるでしょう。私は
L"あ"
とすればと書いています。
あと、lstrcpyじゃいけない理由は何なんでしょうか?
この回答への補足
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を使ったほうがいいですよ。複数のウィンドウでウィンドウプロシージャを共有することになった場合に、書き直す部分が少なくなります。
この回答への補足
いろいろ焦ってて、間違えてます
「VisualWndの文字」がです
プロシージャの引数はNameWnd、StatesWndにしました(ご指摘をうけるまえに)
書き方は(つづりとか)それぞれだとおもいますが
wsprintfはTEXTがないとエラーがでました
変数は全てstaticな変数にしてあります
所持金、ステータスは static long です
No.2
- 回答日時:
部分的にコードを提示されても、変数(と思われるもの)の型とかがまったくわかりませんし、ウィンドウをどのように描画しているのかも提示せずに「基本ステータス(TextOut)しか表示されないはずなのに」とかいわれても、検証のしようがありません。
> wsprintf(HITOMOJI,TEXT(""),wParam);
これでちゃんと文字が入るんですか?
何か全然コードの書き方を理解していないように思えますが。
この回答への補足
恥ずかしながらコードを掲載します。
これが、問題の描画部分。
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;
長いのでここまでで。
わをん、濁点、半濁点はうまくいってないのでまだ途中です。
また、カタカナ、ひらがなの切り替え、小文字大文字の切り替えがあります。
ちゃんと、実行して思い通りの処理をしてくれています。
ヘタながら、書き方はわかっているつもりではあります。
No.1
- 回答日時:
>※うまく説明できてませんがお願いします。
の通り、残念ながらいったい何が起こっているのか完全に不明です。
該当部分のソースコードを漏れなく掲載するなどした方がよい回答が得られるかと思います。
>wsprintf(HITOMOJI,TEXT(""),wParam);
少なくともwsprintfの第二引数が空文字列なのはおかしいと思います。
http://msdn.microsoft.com/ja-jp/library/cc364872 …
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- JavaScript Javascriptが機能せず原因が分からないので教えて頂きたいです 3 2023/06/04 14:50
- JavaScript フォームが空欄の時にフォームの外をクリックすると、エラーが出るコードを調べています。 1 2023/06/25 11:51
- その他(プログラミング・Web制作) python質問 1 2023/08/14 11:54
- Visual Basic(VBA) VBA 重複チェック後に値をワークシートに転記する方法を教えてください。 1 2023/03/19 12:43
- Visual Basic(VBA) 以下のVBAで該当文字列の前後に付与したい。 例 前に付与 abc ユーザーID 12345 後に付 3 2022/04/19 21:50
- HTML・CSS ボタンをクリックした時に、入力フォームのすぐ下部に、「入力欄が空白です」というテキストメッセージが表 1 2022/04/27 16:25
- PHP 入力した部分を表示させたまま(保持)するにはどうすれば良いでしょうか? 1 2023/01/25 11:14
- PHP 文字列を段落で分ける方法を教えて下さい。 2 2023/03/09 10:03
- Visual Basic(VBA) Selenium Basicの件 5 2023/04/10 20:55
- その他(プログラミング・Web制作) Pythonについての質問です。 初心者ほやほやなのでお手柔らかにお願いします。 今手引きにそって入 2 2022/09/22 21:56
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
ゲームでは結局どっちが良いの?
-
VBで外部プログラムを位置のみ...
-
エクセルで作った新しいウイン...
-
Alt+P,Alt+NをPostmessageで送...
-
「アイテムは収集されました」...
-
検索の画面がでなくなってしま...
-
(ショートカットキー)Alt+...
-
リモートデスクトップの中のウ...
-
スケルトンの中のどこでウィン...
-
最大化でタスクバーを隠す
-
グローバルフック?にならない(...
-
EnumChildWindowsの使い方(VBA)
-
勝手にウィンドウが開いて止ま...
-
ラジオボタンの初期指定
-
Zオーダーが上から2番目のウイ...
-
UWSCで特定のChromeのタブをア...
-
VB6で指定したURLに飛ばしたい。
-
【VBA】既存のウィンドウを開い...
-
win32api 教えてください。
-
ExcelのBOOKが消えた!
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
エクセルで作った新しいウイン...
-
「アイテムは収集されました」...
-
ゲームでは結局どっちが良いの?
-
検索の画面がでなくなってしま...
-
勝手にウィンドウが開いて止ま...
-
VBA .Value=.Value ?
-
ラジオボタンの初期指定
-
作成したウインドウのサイズを...
-
Vba LongPtrについて教えてくだ...
-
Excelの上下を固定したい
-
他のアプリケーションの終了処理
-
【VB2008】 マウス操作の一時的...
-
「&HFFFF」「&H1A」とは?
-
VBで外部プログラムを位置のみ...
-
ExcelのBOOKが消えた!
-
Alt+P,Alt+NをPostmessageで送...
-
UWSCで特定のChromeのタブをア...
-
Console.WriteLine で表示されない
-
MFC ダイアログ上のID取得につ...
-
最大化と最小化ボタン
おすすめ情報