• ベストアンサー

WINAPIでキーから文字列を入力できない

今,WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp)内の case WM_CHAR:で wsprintf(input, "入力=\"%c\"", (int)wp); としているのですが,今の状態では文字列を入力できません。 どうすればいいでしょうか、教えて下さい。

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

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

文字列の格納の仕方でしたか(^_^;) それなら、 case WM_CHAR:  wsprintf( input, "%s%c", input, (int)wp );  break; で出来ますよ。 (ただし、inputの配列をオーバーした時の処理はしていません) あとは表示するときに  TCHAR buf[ 256 ];  wsprintf( buf, "入力=\"%s\"", input ); という様に表示用の変数で 表示を行えば完了です。

arukanoid
質問者

補足

一応文字列を入力できるようになりました。ありがとうございます。 ただ問題なのがWM_CHAR内で ・ ・ ・ wsprintf( input, "%s%c", input, (int)wp ); ・ ・ となるので文字列となる前に次の処理に行ってしまいます。 何か上手く処理する方法はないでしょうか?

その他の回答 (5)

回答No.5

//サンプルコードですので注意して使ってください #include <windows.h> #include <cstring> #include <cstdio> LRESULT CALLBACK WindowFunc(HWND, UINT, WPARAM, LPARAM); char str[255]; // 出力される文字 int X=0, Y=0; // 現在の表示される位置 int max_X, max_H; // 画面のサイズ HDC hhdc; HBITMAP hbit; HBRUSH hbrush; int WINAPI WinMain(HINSTANCE hThisInst, HINSTANCE , LPSTR , int _int) { /* TranslateMessage(&msg); // 記入もれしていないということなのでここいらへんは省略します */ } LRESULT CALLBACK WindowFunc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { static HDC hdc; static PAINTSTRUCT ps; switch(message) { case WM_CREATE: // 画面のサイズを取得する max_X = GetSystemMetrics(SM_CXSCREEN); max_H = GetSystemMetrics(SM_CYSCREEN); hdc = GetDC(hwnd); hhdc = CreateCompatibleDC(hdc); hbit = CreateCompatibleBitmap(hdc, max_X, max_H); SelectObject(hhdc, hbit); hbrush = (HBRUSH) GetStockObject(WHITE_BRUSH); SelectObject(hhdc, hbrush); PatBlt(hhdc, 0, 0, max_X, max_H, PATCOPY); ReleaseDC(hwnd, hdc); break; case WM_CHAR: hdc = GetDC(hwnd); sprintf(str, "%c", (char) wParam); // 文字を文字列にする // 改行処理 if((char)wParam == '\r') { Y += 11; X = 0; } else { TextOut(hhdc, X, Y, str, strlen(str)); TextOut(hdc, X, Y, str, strlen(str)); X += 11; } ReleaseDC(hwnd, hdc); break; case WM_PAINT: // 再描画とかでのメッセージ hdc = BeginPaint(hwnd, &ps); // デバイスコンテキストを取得する BitBlt(hdc, 0, 0, max_X, max_H, hhdc, 0, 0, SRCCOPY); EndPaint(hwnd, &ps); break; case WM_DESTROY: // プログラムを終了する DeleteDC(hhdc); DeleteObject(hbit); PostQuitMessage(0); break; default: return DefWindowProc(hwnd, message, wParam, lParam); } return 0; } /////////////////// 以上のコード(一部省略)で作業ウインドウにキーボードから文字の入力ができるとおもいます、 また、strcpy という関数で文字と文字の合成もできますよ。

arukanoid
質問者

お礼

大部分のコードを載せていただいてありがとうございます。 せっかく教えていただいたのに自分の勉強不足で上手く活用することができませんでした。 もっと学び教えていただいたコードを上手く用いたプログラムを作れるようにしたいと思います。 またよろしくお願いします。

回答No.4

inputの型が間違っているか、 画面の更新を行っていなくて確認ができてない可能性があります。 この場合はinputの型はTCHAR型の配列が適しています。 (宣言例) TCHAR input[ 256 ]; 画面の更新はいろいろありますが、 InvalidateRect( hWnd, NULL, TRUE ); で可能です。 参考になりましたでしょうか。

arukanoid
質問者

補足

回答ありがとうございます。 ご指摘の通りにTCHAR型に変更したのですが上手くいきませんでした。 画面の更新についてはInvaidataRectですでに行なっており、入力文字が毎回変わって表示されるので問題はないかと思います。 今現在typingゲームに近いものを作っているのですが文字列入力ができなければ完成しないので困っています。 お手数ですがWM_CHARの中をここに書いたら見て問題点を指摘していただけないでしょうか?

回答No.3

No,2で意見したものです、 先ほどのコートは、case WM_CHAR: に記述してください、 WM_CREATEに書くのは、間違いです。

arukanoid
質問者

補足

返答が遅れてしまって大変申し訳ありません。 教えていただいたコードを使っていろいろ試したのですがうまくいきません。自分の知識が足りないのはわかっているのですが、お手数ですが動くサンプルコードを教えていただけないでしょうか?お願いします。

回答No.2

int X=0, Y=0; // 現在の出力座標のカーソル位置 以下のようなコードをcase WM_CREATE:内に記述してもらえば文字を文字列として扱えると思います、 hdc = GetDC(hwnd);//通常は、case WM_CREATE:に記述 sprintf(str, "%c", (char) wParam); if((char)wParam == '\r') //改行処理,他にも処理も必要ですが省略します、 { Y += 11; X = 0; }else { TextOut(hhdc, X, Y, str,strlen(str));          // 再描画用のHDCへ TextOut(hdc, X, Y, str,strlen(str)); // ウィンドウに出力する X += 11; } ReleaseDC(hwnd, hdc);    // case WM_DESTROY:等に書くべきですがここに

  • namacya
  • ベストアンサー率8% (21/243)
回答No.1

TranslateMessage() を使用してください。

arukanoid
質問者

補足

返答が遅れてしまって大変申し訳ありません。 TranslateMessage()は使っているのですがどう使えばキーボードからの文字列入力が行えるのかわかりません、できればサンプルコードお願いします。

関連するQ&A

  • 何もしないメッセージだけ表示するウィンドウ

    ゲーム用に何もしないメッセージだけ表示するウィンドウを作りたいのですが、 猫でもわかるゲームプログラミングのコードが間違っているのか、 機能しません。 #include <windows.h> LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp); int WINAPI WinMain(HINSTANCE hCurInst, HINSTANCE hPrevInst, LPSTR lpsCmdLine, int nCmdShow) { return (int)msg.wParam; } LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) { switch (msg){ } return 0; } このように、打ち込んだのですが、どこが間違っているのか解りません。 回答お願いいたします。

  • wsprintf( ) でポインタに代入

    wsprintf(p, "%d" , i); を書いたせいで、i の値が変わります。 wsprintf(p, "%d" , i); によってどんなことが起こっているのか詳しく知りたいです。 ポインタのことがまだよく分かってないんです。 #include <windows.h> LPCSTR szStr = "\n char c[255];\n char *p = \"\\0\";\n int i = 12345;\n\n switch (msg){\n case WM_LBUTTONDOWN:\n  wsprintf(c, \"%d\" , i);\n  wsprintf(p, \"%d\" , i);\n  MessageBox(hWnd , c , \"\" , MB_OK);\n break;"; LRESULT CALLBACK WndProc(HWND , UINT , WPARAM , LPARAM); int WINAPI WinMain(HINSTANCE hInstance , HINSTANCE , LPSTR , int){ 省略 return msg.wParam; } LRESULT CALLBACK WndProc(HWND hWnd , UINT msg , WPARAM wParam , LPARAM lParam){ HDC hDC; PAINTSTRUCT ps; RECT rt; char c[255]; char *p = "\0"; int i = 12345; switch (msg){ case WM_LBUTTONDOWN: wsprintf(c, "%d" , i); wsprintf(p, "%d" , i); MessageBox(hWnd , c , "" , MB_OK); break; case WM_PAINT: GetClientRect(hWnd, &rt); hDC = BeginPaint(hWnd, &ps); DrawText(hDC, szStr, lstrlen(szStr), &rt, DT_WORDBREAK); EndPaint(hWnd, &ps); break; case WM_DESTROY: PostQuitMessage(0); break; default: return(DefWindowProc(hWnd , msg , wParam , lParam)); } return (0L); }

  • msgが定義されていない

    Visual Studio2019でwindowsアプリケーションでゲームを作っているんですが、 どうやってもmsgが定義されていないが直りません。 #include <windows.h> LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp); //WinMain関数 int WINAPI WinMain(HINSTANCE hCurInst, HINSTANCE hPrevInst, LPSTR lpsCmdLine, int nCmdShow) { //ウィンドウクラスの登録 //メインウィンドウの生成 //メッセージループ return (int)msg.wParam; } //ウィンドウプロシージャ LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) { switch (msg) { //メッセージごとにやりたいことを記述する } return 0; } ご教示お願いします。

  • デスクトップをサブクラス

    デスクトップ以外のサブクラスなら何度もやったことがあります。 DLLを使わずにデスクトップをサブクラスにできますか? DLLを使わずにデスクトップをサブクラス化しようとしたけど、 サブクラスの対象がデスクトップだと特殊なのか、 サブクラスにできていないみたいでした。 MessageBeep(0xFFFFFFFF); が実行されなかったからそう思いました。 FARPROC Org_Proc; LRESULT CALLBACK DeskProc(HWND, UINT, WPARAM, LPARAM); OrgProc = (FARPROC)GetWindowLong(HWND_DESKTOP, GWL_WNDPROC); SetWindowLong(HWND_DESKTOP, GWL_WNDPROC, (LONG)DeskProc); LRESULT CALLBACK DeskProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) {  if(msg == WM_LBUTTONDOWN)MessageBeep(0xFFFFFFFF);  return CallWindowProc((WNDPROC)Org_Proc, hWnd, msg, wp, lp); }

  • WINAPIでのキー入力した文字列の比較について

    以前ここで教えていただいた wsprintf( input, "%s%c", input, (int)wp ); を使って文字列の比較判定を行ないたいのですが WM_CHAR内で wsprintf( input, "%s%c", input, (int)wp ); wsprintf( ans, "%s", input); check= strcmp(que ,input); //queはファイルからのアルファベット文字列 if(check == 0){ //正解した時の処理 } else{ 不正解だった時の処理 } としているのですが一文字入力するごとにelseに引っかかって上手くいきません,どうすればいいでしょうか? よろしくお願いします。

  • static で宣言

    LRESULT CALLBACK WinProc(HWND hWnd, UINT msg,WPARAM wP, LPARAM lP){ static char str = 'a'; 1回目の WinProc() 実行の時しか static char str = 'a'; は実行されない。 LRESULT CALLBACK WinProc(HWND hWnd, UINT msg,WPARAM wP, LPARAM lP){ char str = 'a'; としても、1回目の WinProc() 実行の時しか char str = 'a'; は 実行されないんですか?

  • 子ウインドウの作成と破棄について

    CALLBACK のみを書きました。 メインウインドウを破棄したら 子ウインドウも破棄したいのですが、 うまく出来ません。 どうすればよろしいでしょうか? よろしくお願いします。 #include<windows.h> #include"ChildWindow.h" char MainWindowClassName[]="mainwindow"; LRESULT CALLBACK WndProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam) { static HWND childWnd; switch(message) { case WM_ACTIVATEAPP: childWnd=Child_CreateWindow(hWnd,message,wParam,lParam); break; case WM_DESTROY: DestroyWindow(childWnd); PostQuitMessage(0); break; default: return DefWindowProc(hWnd,message,wParam,lParam); } } ///////////////////////////////////////////// #include<windows.h> char ChildWindowClassName[]="childwindow"; LRESULT CALLBACK ChildProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam) { switch(message) { case WM_LBUTTONDOWN: MessageBox(NULL,"","",MB_OK); break; default: return DefWindowProc(hWnd,message,wParam,lParam); } } ATOM Child_RegistWindow(HINSTANCE hInstance){} HWND Child_InitInstance(HWND hParentWnd,HINSTANCE hInst,int CmdShow){} HWND Child_CreateWindow(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam) { int CmdShow=1; Child_RegistWindow(NULL); HWND ChildWnd=Child_InitInstance(hWnd,NULL,CmdShow); MSG msg; while(GetMessage(&msg,NULL,0,0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return ChildWnd; }

  • グローバルで宣言

    HWND g_wnd; のようにグローバルで宣言して1つのウインドウを作った場合、 それに対応するWndProcで LRESULT CALLBACK WndProc(HWND hwnd, UINT uMsg ,WPARAM wp, LPARAM lp) { ここでは、hwndとg_wndはどっちを使っても同じですか? }

  • DragQueryFile()でエラー

    現在、VC++2005SP1でダイアログベースのアプリを書いていますが、エディットコントールでのドラッグアンドドロップの実装で躓いています。なぜかDragQueryFile()で-1が返って来て直後にGetlastError()を呼ぶと6(無効なハンドル)が返って来ます。 現象の再現を確認しながらコードを以下のレベルまで簡略にしました。 どこかまずいところがあればご教示頂きたく思います。 #include "stdafx.h" #include <stdio.h> #include <locale.h> #include <shellapi.h> #include "Resource.h" TCHAR input_file[MAX_PATH]; void InitDialog( HWND hWnd ); LRESULT CALLBACK MyDragDropProc( HWND, unsigned, WORD, LONG ); WNDPROC lpfnOldEditProc; LRESULT CALLBACK DlgProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp); int APIENTRY _tWinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPTSTR lpCmdLine, int nCmdShow ) {   _tsetlocale(LC_ALL, _T(""));   INT_PTR dret = DialogBox(hInst, MAKEINTRESOURCE( IDD_DIALOG ), NULL, (DLGPROC)DlgProc );   return 0; } LRESULT CALLBACK DlgProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) {   switch (msg) {   case WM_INITDIALOG: InitDialog( hWnd ); return TRUE;   case WM_COMMAND:     switch (LOWORD(wp)) {     case IDOK: EndDialog(hWnd, IDOK); return TRUE;     case IDCANCEL: EndDialog(hWnd, IDCANCEL); return TRUE;     }   }   return FALSE; } void InitDialog( HWND hWnd ) {   DragAcceptFiles( GetDlgItem( hWnd, IDC_EDIT_INPUT_FILE ), TRUE );   lpfnOldEditProc = (WNDPROC)SetWindowLong( GetDlgItem( hWnd, IDC_EDIT_INPUT_FILE ), GWL_WNDPROC, (LONG)MyDragDropProc ); } LRESULT CALLBACK MyDragDropProc( HWND hWnd, unsigned msg, WORD wp, LONG lp ) {   UINT wFilesDropped;   HDROP hDrop = (HDROP)wp;   TCHAR buff[256];   int err;   switch ( msg ) {   case WM_DROPFILES:     wFilesDropped = DragQueryFile( hDrop, (UINT)-1, NULL, 0 );     err = GetLastError();     _itot_s( err, buff, 256, 10 );     MessageBox( NULL, buff, NULL, MB_OK );     wFilesDropped = DragQueryFile( (HDROP)wp, 0, input_file, MAX_PATH );     MessageBox( hWnd, input_file, NULL, MB_OK );     DragFinish( hDrop );     break;   default:     return CallWindowProc( (WNDPROC)lpfnOldEditProc, hWnd, msg, wp, lp );   }   return 0; }

  • ウィンドウプロシージャで無限再帰

    VC++6.0 Windows2000です。 #define EDITBOX 1234 LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) {  switch (msg)  {   case WM_COMMAND:    switch (LOWORD(wp))    {     case EDITBOX:      GetDlgItemText(hWnd, EDITBOX, str, 32);      ---- ここでstrの文字列を改変 ----      SetDlgItemText(hWnd, EDITBOX, str);      break;    }    break;  } } みたいなことをすると無限再帰が発生してしまうのですが、無限再帰を防ぎつつ等価な動作をさせる方法をよろしくお願いします。