■現状
子ダイアログにWS_EX_CONTROLPARENTスタイルを設定し、
子ダイアログと親ダイアログ間をTabキーで移動できるようにしています。
■問題点
子ダイアログ内のボタンをENTERキーで押下出来ない。
(WS_EX_CONTROLPARENTを外せば押下可能になる。)
■解決方法?
親ダイアログにメッセージハンドラを追加することにより、
ENTERキーでボタンを押下可能なところまでは確認出来ました。
■質問
WS_EX_CONTROLPARENTを使用した際には、クリックイベントなどは
親ダイアログに実装するのが一般的なのでしょうか?
他に良い実装方法などありましたら、宜しくお願いします。
ENTERキーは「デフォルトボタンの押下処理」ですね。
WS_EX_CONTROLPARENTスタイルの子DLGはキーボード処理を
親DLGに移管してしまっているので「問題点」のような状態に
なるのだと思います。
さて、「質問」の「クリックイベント」ですが、これは、
一般にイベントを発生したコントロールの直近の親が処理するのが
普通だと思います。このケースではWS_EX_CONTROLPARENTスタイルの
子DLGになります。
ただし、親のDLGの消滅に関わるような重要なイベントは親DLGで
処理するのが相当でしょう。この場合子DLGは当該のイベントを
親にリフレクトするか、通告して親に処理してもらうのが妥当だと
考えます。
仲澤@失業者さん、返信ありがとうございます。
質問内容が伝わりにくい記載になってしまい申し訳ありません。
■現状
クリックイベントは子ダイアログに実装。
■問題点
子ダイアログのボタンにフォーカスを当て、エンターキーを押下するが、
子ダイアログのクリックイベントが呼び出されない。
→親ダイアログに処理が移管されてしまっている為という原因は理解出来ました。
■質問
このエンターキーを押下した際のイベントを取得するには、
どのように実装するのが一般的なのでしょうか?
■解決方法?
親ダイアログにイベントハンドラを追加し、その中で子ダイアログのクリックイベントを呼び出すという方法になるのでしょうか??
色々な状態が想定できるので具体的には答えられませんが、
親DLGは、子DLGをCreate()したことはわかっているはずなので、
発生したWM_COMMANDの内、BN_CLICKEDの場合で、かつ自分の
直近の子供でないことが明らかな場合は、子DLGのWM_COMMAND
ハンドラを呼び出すのが一番簡単だと思われます。
直接呼び出しても大丈夫な場合もありますが、心配なら
PostMessage()しても良いと思います。
一般にWM_COMMANDがコントロールから直接発生した場合は、lParamに
このコントロールのHWNDが入っていると考えられます。この場合
「このHWNDの親が自分でない場合」という判定でもOKかもしれません。
上記方法が一般的かどうかはわかりませんが、原則として
「子のWM_COMMANDは直近の親が処理すべき」と考えます。
つまり、ENTERでのWM_COMMANDの発生はその親に対して行うべきなので
あって、たとえWS_EX_CONTROLPARENTであろうと、親の親に送られて
しまうのはWindowsの処理がおかしいので、やむを得ずこの様に処理する
という認識です。
直接の回答ではありません。ご了承ください。
自分も昔、同じような親子ダイアログを作ったときに悩みました。
そのときは、子ダイアログ側のPreTranslateMessage()で
「プッシュボタン上でのVK_RETURNのWM_KEYDOWNならクリック処理を呼ぶ」
という処理を入れて無理やり動くようにした憶えがあります。
親ダイアログ側には特別な処理は必要無かったはずです。
ちなみに、この手の親子ダイアログのときは、
WS_EX_CONTROLPARENTではなくDS_CONTROLを付けるのが通常だと思います。
でも、たとえばコントロールパネル内の設定ダイアログなどは
タブコントロールの選択によって複数の子ダイアログを切り替えていますが、
これらの子ダイアログ内のボタンはEnterキーで押せますし、
VisualStudioのオプションダイアログも同じように正しく押せます。
MFCが想定していない親子構造にでもなってしまっているのでしょうかね
(なにかダイアログ内のスタイル設定が抜けているとか?)。
対応方法が確立されているのであれば、自分も知りたいと思っています。
仲澤@失業者さん、NORさん、返信ありがとうございます。
>>原則として「子のWM_COMMANDは直近の親が処理すべき」と考えます。
やはりそれが一番自然ですよね。この方針で実装を進めていきたいと思います。
>>子ダイアログ側のPreTranslateMessage()で
>>「プッシュボタン上でのVK_RETURNのWM_KEYDOWNならクリック処理を呼ぶ」
取りあえず私も上記の実装を行って問題を解決しました。
お二人とも、有り難う御座います!