• ベストアンサー

wParam

wParamは、unsigned int型で、仮想キーコードを、格納してますよね。 wsprintf()内で(TCHAR)キャストしてますが、 これは、変数strの型がTCHAR型なので(wParamは、unsigned intなので型をあわせるために)やっているんですか? (TCHAR)キャストしないとエラーになりますか?教えてください。 HDC hdc; TCHAR str[255]; swich(umsg){   case WM_CHAR:     wsprintf( str, TEXT("%c"), (TCHAR)wPara );     hdc = GetDC(hwnd);     TextOut(hdc, 0, 0, str, lstrlen(str));     return0 }

noname#168725
noname#168725

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

  • ベストアンサー
  • jacta
  • ベストアンサー率26% (845/3158)
回答No.3

そもそも8ビットに収まらない文字を扱うのであれば、キャストしようがしまいが駄目なので、8ビット以内の文字に限定して回答します。 可変個引数に渡した実引数(今回の場合は(TCHAR)wParaがそうです)は、既定の実引数拡張という型変換が行われます。すなわち、実引数がintまたはunsigned int以下の場合には、intまたはunsigned intに暗黙的に型変換されるわけです。 処理系がわからないので推測の域を出ませんが、TCHARはおそらく、char, unsigned char, unsigned short, wchar_t(基本となる型は多分unsigned short)のどれかに定義されていると思います。であれば、いずれもintまたはunsigned int以下ですので、既定の実引数拡張の対象となります。 既定の実引数拡張の対象となるのであれば、明示的なキャストがあってもなくても動作には変わりありません。元々がかなり環境に依存したコードですので、必要以上に移植性を考慮する必要もないでしょうし。 ちなみに、既定の実引数拡張が行われる限り、リトルエンディアンかどうかは全く関係ありません。

noname#168725
質問者

お礼

回答ありがとうございます。 私は、初心者でして難しそうですが、キャストの必要はないようですね。 どうも詳しく教えていただきありがとうございました。

その他の回答 (3)

回答No.4

回答への補足で恐縮ですが。 >・私が知る限りでは『wsprintf』関数で『%c』を指定した場合、それに対応する引数を > 『wsprintf』自身が内部で(char)型に勝手にキャストして処理します。 これは明らかな間違いです。 wsprintf()(或いはその内部で呼び出した関数)はintとして渡された引き数を charと解釈するかもしれませんがキャストするわけではありません。 #例えば%cに対応する引き数としてポインタや実数値を渡したら……言うまでもありませんね。 初心者がプログラミングする上で意識しなければいけないことではありませんが、 回答をする立場でしたらご承知あるべきと思いますので老婆心ながら。

noname#168725
質問者

お礼

回答ありがとうございます、 補足どうもです。 初心者にはとらえがたい所を教えていただきありがとうございます!

  • glphon
  • ベストアンサー率26% (41/152)
回答No.2

 一応型キャストしておいた方がwsprintfにやさしいと思います。  少し使い得ない方法ですがこちらのプログラムをテストしてみてください。 ====== #include <stdio.h> #include <windows.h> int main() { WPARAM wp = L'あ'; char str[64]; wsprintf (str, "%d/%d", (TCHAR)wp, wp); puts(str); return 0; } =========  きちんと型キャストした場合は型にあわせた数値が送られています。  数値が違うのに何故きちんと動いてるように見えるのか。  今回は奇跡的にtata120様のコンピュータがこのバグを防ぐ環境にあったからといえます(奇跡というと大げさかも知れませんが)  例を挙げますが[]を1バイトの塊だと思ってください。  wParaが'a'(=0x61)だとすると、WPARAMは4バイトなので[00][00][00][61]となります。  蛇足ですが(TCHAR)wParaとすると上位3バイトを切捨てて[61]を返します。  ここで問題なのは%cですが、こちらは対象の先頭から1バイトを必要とします。  つまりwParaの先頭から1バイトです。  しかし上記を見ても分かるとおりwParaの先頭は[00]です。  やはり不思議としか言えません。  ですがtata120様のコンピュータがリトルエンディアンである事が鍵となります。  リトルエンディアンのコンピュータは2バイト以上の変数を尻を先頭から置きます。  つまりwParaは[00][00][00][61]という値でありながらメモリ上では[61][00][00][00]と置かれているという事です。  なので%cで取得した時にきちんとした値が得られたように見えた訳です。  Windowsが乗っかっているPCは大抵がリトルエンディアンなので問題ないと思いますが、一応キャストしてあげたほうがいいと思います。  tata120様には不必要な説明になったかも知れませんが、一応書いて見ました。  分かりづらいところもあると思いますが、その点は申し訳ありません。

noname#168725
質問者

お礼

回答ありがとうございます! 私は、初心者であいまいな知識が多く、解説がいろいろ参考にになりました。 どうもありがとうございました!

  • Oh-Orange
  • ベストアンサー率63% (854/1345)
回答No.1

★どうなんでしょうね? ・私が知る限りでは『wsprintf』関数で『%c』を指定した場合、それに対応する引数を  『wsprintf』自身が内部で(char)型に勝手にキャストして処理します。 ・ですから、自分で『wsprintf』の引数『wPara』をキャストする必要性はないと思います。 ・何処かのサイトで見つけた『小技』で書かれていたんですか…。 最後に: ・(TCHAR)型に、キャストしなくても良いです。 ・エラーにはなりませんよ。→動作も異常にはなりません。 ・以上。おわり。

noname#168725
質問者

お礼

すばやい回答ありがとうございます! キャストはしなくても良さそうですネ! ありがとうございました。

関連するQ&A

  • (SHORT)

    ウインドウプロシージャ内ですが、(SHORT)は何のためについているんでしょうか?(どんな効果がありますか) 教えてください。 case WM_MOUSEWHEEL :     wsprintf(str,TEXT("WHEEL %s"),        ((SHORT)HIWORD(wparam))>0 ? TEXT("↑"):TEXT("↓"));     hdc=GetDC(hwnd);     TextOut(hdc,0,0,str,lstrlen(str));

  • wsprintf( ポインタ , "%d" , "123" );

    char str[100]; char *ptr; wsprintf(str, "%d", "1234567"); と wsprintf(ptr, "%d", "1234567"); について、 TextOut(hDC,0,10,str,lstrlen(str)); TextOut(hDC,0,30,ptr,lstrlen(ptr)); で出力したいんだけど、str ならできたけど、 ptr の方が文字化けしていました。 lstrlen(ptr); がいけないのかと思って、 その値を調べたら 0 でした。 strlen( ) はポインタに対応していると思いました。 #include <iostream.h> main(){ char *p = "あいう"; cout << strlen(p); } で 6 だったから。 Win32 の lstrlen( ) はポインタに対応していないんですか?

  • C言語で文字列バッファを消去する方法

    今、C言語とWin32 APIを使ってプログラミングをしています。 wsprintf(str,TEXT("プレイヤーの攻撃!")); TextOut(hdc,0,520,bstr,lstrlen(str)); if(ehp <= 0) {    wsprintf(str,TEXT("敵を倒しました"));    TextOut(hdc,0,520,bstr,lstrlen(str)); } このコードを実行すると、2回目のTextOutのところで 「敵をたおしました撃!」と出てしまいます。 きっとstrに以前の文字列が残っているからだと思いますが、 この保存した文字列を消去するにはどうしたらよいのでしょうか? for文でstr[0]から'\0'までナル文字を代入し続けたり、いろいろと試したのですが駄目でした。どうかこんな自分にご助力お願いできないでしょうか? どうかお願い致します。

  • Windows APIでおかしな事になる。

    Windows APIでプログラミングをしています。 Windows APIでプログラミングをしています。 char*型の文字列を表示させようと、このように記述しました。 const char * y; y=f(); SelectObject(hdc , hFont); SetBkColor(hdc , RGB(255 , 255 , 255)); wsprintf( str, "名前は、%s", y ); TextOut(hdc , 300, 20, str, lstrlen(str)); すると、表示できたのはいいのですが、 タイトルバーをクリックしてウィンドウを広げたり、別のウィンドウを一番前に持ってきて、 その後、そのウィンドウを出したりすると、エラーが出て、強制終了になってしまします。 何か問題はありますか? ちなみに、strの宣言はこのようになっております。 static TCHAR str[64]; あとですが、 wsprintf( str, "名前は、%s", y ); この部分のyを&yに変えると、エラーは起こりませんが、 変な文字が表示されてしまいます。 ウィンドウを少し操作すると、その文字がまた変な文字に変わります。 何が原因でしょうか。

  • リサイズで文字が消えちゃう

    LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) {  HDC hdc;  char *str;  switch (msg) {   case WM_KEYDOWN:   hdc = GetDC(hWnd);   str = "キーダウンした";   TextOut(hdc,1,1,str,strlen(str));   ReleaseDC(hWnd,hdc);   break; キーを押すと、LRESULT CALLBACK でウインドウに文字が 表示されるようにしました。 でも、この文字は別のウインドウに隠れて、再びウインドウが 表示された場合とかには消えています。 消えないようにするためにはどうしたらいいですか? void Swit(HWND hWnd) {  HDC hdc;  char *str;  if (キーダウンのフラグがあったとして、それが true なら) {   hdc = GetDC(hWnd);   str = "キーダウンした";   TextOut(hdc,1,1,str,strlen(str));   ReleaseDC(hWnd,hdc);  } return; } if ( ウインドウ再描画 == true ){ Swit() } というのを考えました。 LRESULT CALLBACK で、キーが押された場合にフラグを true にして ウインドウが再描画された場合にフラグをチェックして文字を 表示する という方法を考えたんだけど、これを BCC32 でコンパイル するためにはどういうソースを書いたらいいか分からないし、 もっといい方法があれば教えてください。

  • なぜhButton1ボタンからのWM_COMMANDはフックできてクライアントエリアのWM_RBUTTONDOWNはフックできないのでしょうか?

    #define STRLBUTTON TEXT("マウス左ボタンが押されました from mainProc") #define STRRBUTTON TEXT("マウス右ボタンが押されました from my_HookProc") #define STRCOMMAND TEXT("ボタンが押されました") HWND hButton1; LRESULT CALLBACK my_HookProc(int nCode, WPARAM wParam, LPARAM lParam) { CWPRETSTRUCT *pcwpRetStruct = (CWPRETSTRUCT *)lParam; HDC hDC; if(nCode==HC_ACTION) { hDC = GetDC(pcwpRetStruct->hwnd); switch(pcwpRetStruct->message) { case WM_COMMAND: TextOut(hDC, 10, 10, STRCOMMAND, strlen(STRCOMMAND)); break; case WM_RBUTTONDOWN: TextOut(hDC, 10, 10, STRRBUTTON, strlen(STRRBUTTON)); break; } ReleaseDC(pcwpRetStruct->hwnd, hDC); } return CallNextHookEx(NULL, nCode, wParam, lParam); } LRESULT CALLBACK mainProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { static HHOOK hHook; HDC hDC; switch(uMsg) { case WM_DESTROY: UnhookWindowsHookEx(hHook); PostQuitMessage(0); return 0; case WM_CREATE: hHook = SetWindowsHookEx(WH_CALLWNDPROCRET, my_HookProc, NULL, GetCurrentThreadId() ); if(!hHook) MessageBox(NULL, "hooking failed", NULL, MB_OK); hButton1 = CreateWindow( "BUTTON", "hButton1", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, 10, 40, 100, 20, hWnd, NULL, ((LPCREATESTRUCT)lParam)->hInstance, NULL ); return 0; case WM_LBUTTONDOWN: hDC = GetDC(hWnd); TextOut(hDC, 10, 10, STRLBUTTON, strlen(STRLBUTTON)); ReleaseDC(hWnd, hDC); return 0; } return DefWindowProc(hWnd, uMsg, wParam, lParam); }

  • TextOut( ) を BeginPaint( ) と GetDC( )

    LRESULT CALLBACK の case WM_PAINT: で、 hdc = BeginPaint(hWnd, &ps); TextOut(hdc,0,0,str,strlen(str)); EndPaint(hWnd, &ps); ↑問題無し。↓文字がちらつく。 hdc = GetDC(hWnd); TextOut(hdc,0,0,str,strlen(str)); ReleaseDC(hWnd,hdc); ちらつきの原因は、高速で TextOut( ) が繰り返されるから だと思いました。 どうして TextOut( ) が繰り返されるんですか? 上の方法の場合は、 ReleaseDC(hWnd,hdc); は書かなくてもいいですか?

  • WM_CHAR or WM_KEYDOWN の「wParam」について

    よくわかっていないのですが、 switch (message) { case WM_CHAR: というところで、wParamから、文字の情報取得して、 HDC宣言して、TextOut関数使用…、の途中で、 wParamの文字情報は、どのようにすれば TextOut関数に渡せるのでしょうか? Visual C++を勉強したてで、勉強の成果をと思い、 テキストエディタを作ってみたいと思ったのですが、 さて、どうしたらよいのでしょうか? エラー内容は、unsigned int → const char * にできません、ということなのですが、 じゃぁ、型の変換の仕方は?という感じです。 初心者なので、簡単な例をつけて説明してくださると助かります。よろしくお願いします。

  • TextOut( ) が動かない

    LRESULT CALLBACK WndProc( HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam){ PAINTSTRUCT ps; HDC hdc; switch(msg){ case WM_KEYDOWN:  if( wParam == VK_ESCAPE ){   hdc = BeginPaint(hWnd, &ps);   TextOut(hdc,0,0,str,strlen(str));   EndPaint(hWnd, &ps);  }  break; case WM_PAINT:  break; エスケープキーで文字表示をやりたいけど TextOut( ) が動作していないみたいでした。 switch(msg){ case WM_KEYDOWN:  if( wParam == VK_ESCAPE ){   hdc = BeginPaint(hWnd, &ps);   TextOut(hdc,0,0,str,strlen(str));   EndPaint(hWnd, &ps);  }  break; case WM_PAINT:  hdc = BeginPaint(hWnd, &ps);  TextOut(hdc,0,0,str,strlen(str));  EndPaint(hWnd, &ps);  break; とすると、常に文字が表示されたから、やっぱり case WM_KEYDOWN: の中の TextOut( ) が 動作していないんだと思いました。 TextOut( ) は case WM_PAINT: からのつながりが ある場合でないと実行されないんですか? ソースのおかしいところがあったら教えてください。

  • WM_PAINT

    WM_PAINT について教えてほしいのですが、 WM_PAINTがシステムから発行されるタイミングとして、 クライアント領域に無効領域がある時 UpdateWindow()を呼び出した時 InvalidateRect()を呼び出した時があると思いますが 例えば LRESULT CALLBACK WndProc(HWND , UINT , WPARAM , LPARAM) { LPCTSTR  Str = TEXT("Kitty"); switch (msg) { case WM_CREATE:    hdc = GetDC(hwnd);    SetTextColor(hdc , RGB(255, 0 , 0));    ReleaseDC(hwnd , hdc);    return 0; case WM_PAINT:    hdc = BeginPaint(hwnd , &ps);    TextOut(hdc, 10 , 10 , Str, lstrlen(Str));    EndPaint(hwnd , &ps);    return 0; } return DefWindowProc(hwnd , msg , wp , lp); } の場合, WM_PAINTはどのタイミングでシステムから呼び出されるんですか? WinMain()でUpdateWindow()もInvalidateRect()もつかっていないのですが。 いつシステムから送られるかご教授をお願いします。