MDI の CMainFrame メニューは SDI と同様に消すことができる.
しかし,アクティブビューに対応するフレームメニューは MDICLIENT に WM_MDISETMENU を送って設定しているため消すことができない.
CMenu *MDISetMenu() をオーバーライドしようにも virtual でないのでできない.
CMainFrame::m_hWndMDIClient をサブクラス化して WM_MDISETMENU をフックすればなんとかメニューを消すことができる.
■MainFrameBackWnd.h
/////////////////////////////////////////////////////////////////////////////
// CMainFrameBackWnd ウィンドウ(MDICLIENTのサブクラス)
class CMainFrameBackWnd : public CWnd
{
// 生成されたメッセージ マップ関数
protected:
//{{AFX_MSG(CMainFrameBackWnd)
afx_msg void OnPaint();
//}}AFX_MSG
afx_msg LRESULT OnSetMenuNotify(WPARAM wParam, LPARAM lParam);
};
■MainFrm.h
/////////////////////////////////////////////////////////////////////////////
// CMainFrame
class CMainFrame : public CMDIFrameWnd
{
// アトリビュート
private:
CMainFrameBackWnd m_backWnd;
};
■MainFrm.cpp
/////////////////////////////////////////////////////////////////////////////
// CMainFrame メッセージ ハンドラ
BOOL CMainFrame::CreateClient( LPCREATESTRUCT lpCreateStruct, CMenu* pWindowMenu )
{
// まず MDICLIENT を作る
BOOL ret = CMDIFrameWnd::CreateClient(lpCreateStruct, pWindowMenu);
if( !ret ) {
return FALSE;
}
// ここでサブクラス化
if( m_hWndMDIClient ) {
if( !m_backWnd.GetSafeHwnd() ) {
m_backWnd.SubclassWindow(m_hWndMDIClient);
}
}
return TRUE;
}
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
// 元のメニューを消す
SetMenu(NULL);
return 0;
}
■MainFrameBackWnd.cpp
BEGIN_MESSAGE_MAP(CMainFrameBackWnd, CWnd)
//{{AFX_MSG_MAP(CMainFrameBackWnd)
ON_WM_PAINT()
//}}AFX_MSG_MAP
// メッセージマップの追加
ON_MESSAGE(WM_MDISETMENU, OnSetMenuNotify)
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CMainFrameBackWnd メッセージ ハンドラ
LRESULT CMainFrameBackWnd::OnSetMenuNotify(WPARAM wParam, LPARAM lParam)
{
// フレームのメニューを無視させる
return CWnd::DefWindowProc(WM_MDISETMENU, (WPARAM)0, lParam);
}
ON_MESSAGE で取ってきたメッセージを
return CWnd::DefWindowProc(WM_MDISETMENU, (WPARAM)0, lParam);
と呼び出しても問題はないかどうかは気になるところである.
(場合によるとしか言えない)
return 0;
とすると,lParam がポップアップメニュー用のハンドルらしいから,ポップアップメニューまで勝手に潰してしまうのは「フレームメニューを出さない」という観点からするとまずい気がする.
(ポップアップを使用しないのであれば return 0 で問題はないと推測する)
参照
MDIメニューの変更はどこでしているのか?