WM_KEYDOWNが拾えない(EditBox関連)

このQ&Aのポイント
  • メインウィンドウに子ウィンドウを貼り付けデータを表示させる方法について質問があります。
  • 子ウィンドウでのWM_KEYDOWNが拾えない問題があり、親ウィンドウでWM_KEYDOWNを送信しているが、エディットボックスを破棄した後方向キーでの移動ができなくなる現象が発生しています。
  • EditBoxをサブクラス化してリターンキーで閉じるようにしていますが、解決策をご教示ください。
回答を見る
  • ベストアンサー

WM_KEYDOWN が拾えない(EditBox関連)

メインとなるウィンドウ(親)のクライアント領域に子ウィンドウを貼り付けそこにデータを表示させています。内容的にはエクセルのような表形式になっていてセルを選択でき、方向キーで選択を移動できます。 移動は子ウィンドウでWM_KEYDOWNが拾えなかったので親ウィンドウでWM_KEYDONWを子ウィンドウにSendMessageして子ウィンドウで処理させています。このやり方に少々疑問も感じますがとりあえずここまでは期待通りに動いてくれています。 ここからが問題なのですが、データを修正する時に子ウィンドウにEditBox(孫)を作成し直接入力できるようにしましたが、入力が終わりエディットボックスを破棄した後、以前のように方向キーでの移動が出来なくなってしまいました。親ウィンドウでWM_KEYDOWNを拾えていないようです。でも、最小化などにより一度親ウィンドウがフォーカスを失うと再び正常に戻ります。 EditBoxはサブクラス化してリターンキーで閉じるようになってます。 良い解決方法がありましたらお願いします。 環境:VC++6.0(SDK) WindowsMe

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

  • ベストアンサー
  • taka_tetsu
  • ベストアンサー率65% (1020/1553)
回答No.3

>ただ、以前のようにWM_KEYDOWNでWM_CLOSEを"SEND"した場合、(EditBoxプロシージャ内の)どこでSetFocusしてもだめだった理由がいまひとつ理解できていないのでちょっとすっきりしませんが...。 ウィンドウプロシージャから見たSend時の処理の流れ WM_KEYDOWNの受け取り ↓ WM_CLOSEの受け取り ↓ WM_CLOSEに対する処理 ↓ WM_KEYDOWNに対する処理 Post時の処理の流れ WM_KEYDOWNの受け取り ↓ WM_KEYDOWNに対する処理 ↓ WM_CLOSEの受け取り ↓ WM_CLOSEに対する処理 これで違いはわかりますか? Sendしてしまうと、WM_CLOSEの処理が行われた後で WM_KEYDOWNに対する内部処理がエディットのウィンドウプロシージャ内で行われます。 ここはブラックボックスなので、何が行われているかは わからないですが、フォーカスに関係するような処理でも 行われているのでしょう。

eye209
質問者

お礼

ありがとうございます。 順を追って流れを見ると違いがはっきり分かりました。 taka_tetsuさんのおかげで基本的かつ重要なことを学べました。

その他の回答 (2)

  • taka_tetsu
  • ベストアンサー率65% (1020/1553)
回答No.2

>EditBox破棄後、EditBoxにあったフォーカスは親(子)ウィンドウには戻りませんでした。 参考までに、何が持ってました? ハンドル値がわかればSPYで調べられますよね。 >サブクラス化したEditBoxのプロシージャ内でリターンキーによりEditBox自身を閉じた時に >SetFocusしてもだめでした。 どのタイミングでSetFocusしました? WM_KEYDOWN?WM_DESTROY? タイミングをずらせばいいのであれば、WM_DESTROYのときに親ウィンドウにWM_USERかなんかをPOSTしてあげれば何とかなると思います。

eye209
質問者

お礼

>>...POSTしてあげれば何とかなると思います。 今まで何も考えずにSendMessageばかり使ってましてそれでも何とかなっていたのでPostとSendの違いを深く理解していませんでした。 taka_tetsuさんの言葉をきっかけにPostMessageについて調べ直し、直ちに制御を返すことに気づき使ってみました。 結果、WM_CLOSEをSendではなくPostしたらSetFocusするまでもなく親ウィンドウにフォーカスが移り、キー操作もちゃんと拾えるようになりました。(初歩的なことでお恥ずかしい) ただ、以前のようにWM_KEYDOWNでWM_CLOSEを"SEND"した場合、(EditBoxプロシージャ内の)どこでSetFocusしてもだめだった理由がいまひとつ理解できていないのでちょっとすっきりしませんが...。 いずれにしても解決への糸口を提供していただきまして今回の件だけでなく今後のデバッグのためにも参考になりました。

  • taka_tetsu
  • ベストアンサー率65% (1020/1553)
回答No.1

>移動は子ウィンドウでWM_KEYDOWNが拾えなかったので 子ウィンドウは、もしかしてスタティックなコントロールとか使用していませんか? >入力が終わりエディットボックスを破棄した後、以前のように方向キーでの移動が出来なくなってしまいました。親ウィンドウでWM_KEYDOWNを拾えていないようです。 キーで動かないのは子ウィンドウがキーボードフォーカスを持ってない体と思われます。なんで、エディットを破棄した後にSetFocusすれば平気かも。 それでもだめなときは、キーボードフォーカスはどこにあるかGetFocusで調べてみてください。 このときに、デバッグ用にメッセージボックスなどフォーカスの移動が 発生するようなものは表示させないでくださいね。

eye209
質問者

お礼

ありがとうございます。早速、GetFocusで調べてみました。EditBox破棄後、EditBoxにあったフォーカスは親(子)ウィンドウには戻りませんでした。ご指摘のとおりEditBox破棄後、別のタイミングでSetFocusすれば元に戻りましたが、サブクラス化したEditBoxのプロシージャ内でリターンキーによりEditBox自身を閉じた時にSetFocusしてもだめでした。今の状態だと 編集する → リターンキーで編集を終える → 方向キーが使えない ということになってしまいます。 ちなみに子ウィンドウはCreateWindowで作ったWM_CHILDのタイトルなしのウィンドウです。

関連するQ&A

  • WM_KEYDOWNでPrtScを捕まえる方法??

    ごく普通のウィンドウプロシージャでキーの判別を行っています 下記のように条件(1)が WM_KEYUP の際には(2)、(3)ともに検出します LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) { switch (msg) { case WM_KEYUP: ............ (1) switch(wp) { case VK_RETURN: { break; } ..... (2) case VK_SNAPSHOT: { break; } ..... (3) default: { break; } } break; } return; ところが条件(1)を WM_KEYDOWN に変更すると(2)の Enter は検出しますが、(3)の PrtSc を検出してくれません 質問1 なぜ PrtSc を WM_KEYDOWN では検出しないのですか? 質問2 WM_KEYUP WM_KEYDOWN のいずれか一方にしか反応しないキーはまだありますか? 質問3 どのようにしたら PrtSc の WM_KEYDOWN を捕まえることが出来ますか? 自分でも調べてみましたが、どうも判然と致しません 宜しくご指導のほどお願い申し上げます

  • ダイアログのWM_KEYDOWNで処理を実行したい

    現在、VC++6を用いて、MFC を使わずにアプリケーションを作っている初心者です。 最終的にはWIN_CEハンディーターミナルで動作させる予定です。 ダイアログにフォーカスがある状態で、"↓"キー入力があった場合に処理を行いたいのですが、 ダイアログ及び親ウインドウにWM_KEYDOWNが発生していないみたいなのです。 (SPY++にて確認しました。) DialogBox、CreateDialogの両方でやってみたのですがうまくいきません。 なにか良い方法はありますか? よろしくお願いします。

  • EditBoxのサブクラス化

    いつもお世話になっております。 現在、EditBoxのサブクラス化についてやっておりまして、詰まってしまったのでお聞きしたいです。 EditBoxにおいてENTERとESCAPEを押下されたときにある処理をしようとしてサブクラス化をしたのですが、その結果その他のキーが受け付けられなくなってしまいました。 defaultで何かすればいいかと思いいろいろやってみましたがよくわからなかったのでアドバイスお願いします。 現在のソースは以下のとおりです。 LRESULT CALLBACK EditProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {  switch (uMsg)  {   case WM_KEYUP:   {    if (wParam == VK_RETURN)    {     // 処理    }    else if (wParam == VK_ESCAPE)    {     // 処理    }   }  break;  }  return false; } ここでENTERとESC以外は普通に入力したいのですがどのようにすれば実現できるかアドバイスお願いします。 環境は WindowsXP SP3 Visual Studio6.0 です。よろしくお願いします。

  • VBA API WM_KEYDOWN

    エクセル内のオブジェクトの移動を判定するため、マウスアップを検出しようと考えています。 GetAsyncKeyStateでできるのですが、エクセルが受け取るWM_KEYDOWNを受け取る方法はないのでしょうか? そもそもWindowsがイベント待ちで動いているのに、GetAsyncKeyStateだとループ処理で監視することになるので、すっきりしません。私だけでしょうか? ちなみに、新規に図形を作ったり、図形を移動したりしたときに処理したいですが、このイベントは準備されていないですよね?

  • SendMessage(hW,WM_CREATE,0,0);を

    SendMessage(hW,WM_CREATE,0,0); を実行するとシステムがWM_DOWNやWM_CHARを発行しなくなるみたいです というのはそれ以降キー入力を無視するようになるのです いったんアプリをアイコン化してウィンドウ化するとWM_DOWNやWM_CHARを発行するようになります WM_CREATEを送ってもWM_DOWNやWM_CHARを発行しなくなるのを阻止するために何か方法はないでしょうか?

  • チェックボックスのキーダウン時に矢印キーを検知する方法について

    チェックボックスのキーダウン時に矢印キーを検知する方法について VB6のチェックボックスについて質問させて頂きます。 環境   Windows 2000 SP4   Visual Basic 6.0(SP6) チェックボックスのキーダウン時に矢印キーを検知する方法について、ご存知の方がいらっしゃいましたら、ぜひ教えて頂きたいです。 自分なりに調べてみた結果は以下の通りです。 チェックボックスのKeyDownイベントでは矢印キーは検知できませんでした。 次に試したのが、サブクラス化を行い、WM_KEYDOWNを取得する方法です。 正直、サブクラス化を行えば矢印キーを確実に検知できると考えていたのですが、なぜか矢印キーを押してもWM_KEYDOWNメッセージを取得できず、このため矢印キーの検知ができませんでした。 矢印キー以外のキー、例えばAやSなどは問題なく検知できました。 ちなみに、この状態でSpy++を起動し、矢印キーを押したときのメッセージを確認してみると、チェックボックスウィンドウはきちんとWM_KEYDOWNを受け取っていました。 それなのにサブクラス化した方ではWM_KEYDOWNは取得できません。 まだ完全にサブクラス化の概念を理解している訳ではないため、恐らく何か原因があるのでしょうが、想像ができないでいます。 ( Windowsから送られるメッセージがチェックボックスウィンドウに届くまでの間に誰がメッセージを処理してるのかが分かりません。自分は間に何もないと考えていました )。 この動作についても知っている方がいたら、説明して頂けるととても助かります。 すいませんが、ご教授お願い致します。

  • プログラムを組んでいる途中、行き詰ってしまったので質問させていただきま

    プログラムを組んでいる途中、行き詰ってしまったので質問させていただきます。 ボタンを左クリックしたらコモンダイアログを表示し、ファイル名を取得するものを作っていたのですが、ファイルを選択した後ボタンが押したままになってしまいます。 ボタンはサブクラス化をしてあります。(サブクラス化しないと上手くいっているため、原因はここだと思います。) 画面が切り替わると判断できるものがあれば、その中でボタンを離したことにすれば良いと考えたのですが、判断できるウィンドウメッセージが分かりません。 サブクラス化したボタンプロシージャの中身の一部 switch(Msg){  case WM_LBUTTONDOWN:   SendMessage(親ウィンドウのハンドル,Msg,wParam,lParam);  case /*ここに切り替わりを判断できるメッセージ*/:   SendMessage(親ウィンドウのハンドル,WM_LBUTTONUP,(省略),(省略));   break; ※とりあえず左クリックのみ対応と言うことでWM_LBUTTONUPになっています。 分かる方いましたら、お願いします。 環境:Windows 言語:C++(WinAPI使用)

  • テキストボックスからフォーカス外す

     editBox = CreateWindow(   "EDIT",   "あああ",   SS_CENTER | WS_CHILD | WS_VISIBLE,   0,0,100,20,   hWnd,   NULL,   hInstance,   NULL); テキストボックスのフォーカスを外すにはどうしたら いいんですか? ESCキーでフォーカスを外そうと思ったら、 テキストボックスにフォーカスがあるせいで case WM_KEYDOWN が動作しません。 フォーカスを外すというソース自体も分かっていません。  case WM_KEYDOWN:   if( wParam == VK_ESCAPE )    ?  break;

  • エディットでEnterキーでのTAB移動

    Win32APIを使ってプログラミングしています。 通常はTABでフォーカスを移動するのが良いと思うのですが、Enterキーで移動させたいと思います。 ところが、一行のエディットだとEnterキーを押すとビープ音が鳴ってしまいます。 フォーカス移動はできるのですが、ビープ音を鳴らないようにするにはどうすればいいのでしょう? 多分WM_KEYDOWNかWM_KEYUP、WM_CHARのどれかで書けばいいと思ってるんですが… よろしくお願いします。

  • Excelマクロ、フォーム入力での矢印移動禁止

    データをユーザーフォームで入力するマクロを作りましたが、 項目の移動をするとき矢印キーだとcomboboxの中身が入れ替わってしまうので、矢印キーでの移動を禁止してリターンキーとタブキーでの移動にしたいんですが、やり方がわかりません。 どうすればいいのでしょうか?ご伝授ください。

専門家に質問してみよう