- ベストアンサー
ダイアログプログラムでEnterキーを検出するには?
おせわになります。 開発環境はWindowsXP、VisualC++.NET、SDK開発です。 ダイアログ上のテキストボックスでエンターキーが入力されたら、 値を取り込むというプログラムを考えています。 ただ、WM_KEYDOWNではENTERが検出できないで困っています。 WM_SYSKEYでもENTERを押してもOKボタンが押されてしまいます。 過去のログを見ますとTranslateMessageでフックするというような 記述がありますが、具体的なコードは無いでしょうか? メイン関数内のループでMSGを処理するのではと思っていますが 思うような動作が出来ません。
- みんなの回答 (2)
- 専門家の回答
質問者が選んだベストアンサー
- ベストアンサー
複数行のエディットフィールドであれば BOOL CALLBACK DlgProc(HWND hDlg,UINT msg,WPARAM wParam,LPARAM lParam) { static LONG preProc; switch (GetDlgCtrlID(hDlg)==IDC_EDIT1?WM_USER+1:msg) { case WM_USER+1: switch (msg) { case WM_CHAR: if (wParam==13) MessageBeep(0); } return CallWindowProcA((WNDPROC)preProc,hDlg,msg,wParam,lParam); case WM_INITDIALOG: preProc=SetWindowLong(GetDlgItem(hDlg,IDC_EDIT1),GWL_WNDPROC,(LONG)DlgProc); return 1; case WM_COMMAND: switch (LOWORD(wParam)) { case IDCANCEL: EndDialog(hDlg,0); return 1; } } return 0; } int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR nCmdLine, int lCmdShow) { DialogBoxParam(hInstance,MAKEINTRESOURCE(IDD_DIALOG1),0,DlgProc,0); return 0; } と言う感じ(重複サブクラスプロシージャ)でシンプルにできます。 ただし、1行専用フィールドと場合はスレッドフックが必要です。 <セット> hHook=SetWindowsHookEx(WH_KEYBOARD,KeyboardProc,0,GetCurrentThreadId()); <プロシージャ> LRESULT CALLBACK KeyboardProc(int code,WPARAM wParam,LPARAM lParam) { if (nCode===HC_ACTION) if (wParam==0xD) { ここでエンターキー入力の処理 } return CallNextHookEx(hHook,nCode,wParam,lParam); } と言った感じでできると思いますよ。 スレッドフックは参考URLを参照してください。
その他の回答 (1)
- kumonomoto
- ベストアンサー率41% (12/29)
ご希望の方法とは違うかもしれませんが、テキストボックス等のコントロールを含む ウィンドウのウィンドウプロシージャの変更を行うサブクラス化というものがあります。 HWND hwTx; //テキストボックスのウィンドウハンドル WNDPROC wpDef; //テキストボックスのデフォルトのウィンドウプロシージャのアドレス //ウィンドウプロシージャのアドレスを取得 wpDef = (WNDPROC)GetWindowLong( hwTx, GWL_WNDPROC ); //新たにウィンドウプロシージャを設定する SetWindowLong( hwTx, GWL_WNDPROC, (LONG)WinProcCnt ); //新しいウィンドウプロシージャ LRESULT CALLBACK WinProcCnt( HWND hw, UINT msg, WPARAM wp, LPARAM lp ) { switch( msg ){ case WM_CHAR: switch( LOWORD(wp) ){ case VK_RETURN: //ENTER入力時の処理 break; } } //デフォルトのウィンドウプロシージャへ return CallWindowProc( wpDef, hw, msg, wp, lp ); }
補足
回答ありがとうございます。 サブクラス化をしたのですが思ったような動作が出来ません。 状況としては、ダイアログのある場所をクリックすると CreateWindowでエディットボックス(改行無し)を作成し、数値を入れてEnterキーを押すと数値が反映されるようにしたいと思っています。 具体的には以下のコードを書いています。 //クリックした所にエディットボックスを貼り付ける g_hEdit=CreateWindow("EDIT",szText ,WS_CHILD | WS_VISIBLE | ES_RIGHT,//ウィンドウスタイル rcAll.left,rcAll.top,//X.Y rcAll.right-rcAll.left,rcAll.bottom-rcAll.top,//幅、高さ GetDlgItem(hWnd,IDC_LIST1), //親ウィンドウのハンドル (HMENU)IDC_LISTEDIT,//コントロールID g_Inst,//インスタンスハンドル NULL); //サブクラス化 g_orgListEditProc=(WNDPROC)SetWindowLong(g_hEdit,GWL_WNDPROC,(LONG)ListEditProc); SendMessage(g_hEdit, WM_SETFONT, (WPARAM)GetStockObject(DEFAULT_GUI_FONT), MAKELPARAM(FALSE, 0)); SetFocus(g_hEdit); 新しいエディットボックスに数値を入れてエンターキーを押すと、 IDOKに飛んでしまうのです。 エディットボックス内に普通の数字を入れるとKEYDOWNで検知できているのですが、Enterキーは検知できません。WM_SYSKEYでも検知できません。 動作としては、エディットボックスではなくIDOKボタンにフォーカスが行っている状態のようにみえます。 状況を説明してみたのですがいかがでしょうか?
補足
VTClientさんありがとうございます。 上記のコードを使ってエンターキーの検出ができました。 ありがとうございました。