お世話になります。たいちうです。
スタティックコントロールでポップアップメニューを表示させているのですが、
メニューアイテムの有効無効の切替えのためのON_UPDATE_COMMAND_UIの
マッピングがうまくできません。TRACEで確認すると、メニューアイテムが
クリックされたときにON_UPDATE_COMMAND_UIで関連付けた関数が呼ばれています。
原因のわかる方、お教え願います。
以下、詳しく。
・Windows2000/XP/98 VC6.0+SP5
・MFC SDIでCFormView使用
・CStaticを継承させたクラスCHogeを作成し、
CFormViewに貼り付けたstaticのコントロールメンバ変数とする。
・CHogeは、ModifyStyleでSS_NOTIFYを設定。
OnContextMenuでポップアップメニューを表示。ポップアップの所有はthis(CHoge)。
・CHogeでON_COMMANDを追加し、CHogeのメンバ関数でメッセージを処理。
ここまでは問題なくできています。
つまり、CFormView上のスタティックコントロールを右クリックして、
ポップアップメニューを表示させ、メニューアイテムを選択すると、
CHogeのメンバ関数が呼ばれています。
メニューアイテムを無効にするつもりでON_UPDATE_COMMAND_UIとCHogeのメンバ
関数を新しく追加したのですが、TRACEで確認すると、関数が呼ばれるのはクリック
したときでON_COMMANDの方の関数の直前に呼ばれます。
無効にするつもりのアイテムも選択できてしまうのが現状です。
OnContextMenuでアイテムを無効にすることはできましたので、ON_UPDATE_COMMAND_UIに
こだわる理由はないのですが、何が間違っているのか気になっています。
ちょっとややこしい質問かもしれませんが、識者の方々、もしお時間が許しましたら、
その、あれしてください。よろしくお願いします。
多少違うかもしれませんが大筋は合っていると思いますのでご参考までに。
メニューが表示されるときに WM_INITMENUPOPUP が親ウインドウに届きます。
CFrameWndにはこれの独自処理ハンドラがあり、ここでメニューのUpdateCmdUI
処理が行なわれているようです。
しかしたいちうさんの場合ポップアップの所有をCHogeとしているため
WM_INITMENUPOPUPの独自ハンドラを持っていないCStaticでは、UpdateCmdUI
処理されないのだと思います。
また、メニュー選択時にはWM_COMMANDがポストされますが、CWnd::OnCommand()
では無効なアイテムのコマンド実行を防止するために、先に一度UpdateCmdUI処
理を呼び出してから、ユーザーのコマンドハンドラを呼び出すようになっている
ようです。これはCWndでの処理なので、CStaticでも処理されるのでしょう。
親をCFrameWnd派生クラスにすればUpdateCmdUI機構は働くと思いますが、
CHoge内で処理を行なうということであれば、WM_CONTEXTMENUか、WM_INITMENUPOPUP
内で独自に処理を実装することになりそうですね。
Wandererさま、回答有難うございます。
回答は付かないのかなとそろそろ思い始めていました。
> メニューが表示されるときに WM_INITMENUPOPUP が親ウインドウに届きます。
> CFrameWndにはこれの独自処理ハンドラがあり、ここでメニューのUpdateCmdUI
> 処理が行なわれているようです。
>
> しかしたいちうさんの場合ポップアップの所有をCHogeとしているため
> WM_INITMENUPOPUPの独自ハンドラを持っていないCStaticでは、UpdateCmdUI
> 処理されないのだと思います。
確認しましたが、CFrameWnd::OnInitMenuPopup()の中でCCmdUI::DoUpdate()を呼び出して、
CN_UPDATE_COMMAND_UIメッセージを発生させているようですね。
CStatic::OnInitMenuPopup()ではそんな処理はありませんでした。
> また、メニュー選択時にはWM_COMMANDがポストされますが、CWnd::OnCommand()
> では無効なアイテムのコマンド実行を防止するために、先に一度UpdateCmdUI処
> 理を呼び出してから、ユーザーのコマンドハンドラを呼び出すようになっている
> ようです。これはCWndでの処理なので、CStaticでも処理されるのでしょう。
なるほど。確かにUpdateCmdUIのみを記述したときには呼ばれませんでした。
> 親をCFrameWnd派生クラスにすればUpdateCmdUI機構は働くと思いますが、
> CHoge内で処理を行なうということであれば、WM_CONTEXTMENUか、WM_INITMENUPOPUP
> 内で独自に処理を実装することになりそうですね。
はい。クラス内で処理したいのでWM_CONTEXTMENUで処理しようと思います。
有難うございました。おかげさまで理解を少し深めることができました。