在主框架的OnCreate函数中,你可以看到工具条和状态栏的创建,理论上来说,你也应该可以看到主菜单的创建。找找看,发现没有。但是当你运行程序的时候,却又明明有主菜单。很显然,MFC还是创建了主菜单,只是在某个函数中将它隐藏了。那是在哪呢?慢慢找,不着急。
你看到前面有这样的一句话,
if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
return -1;
感觉有点像,莫非主框架类调用了基类的oncreate函数创建了主菜单?看看它的参数,在CSDN看看,如下:
typedef struct tagCREATESTRUCT { // cs LPVOID lpCreateParams;
HINSTANCE hInstance;
HMENU hMenu;
HWND hwndParent;
int cy;
int cx;
int y;
int x;
LONG style;
LPCTSTR lpszName;
LPCTSTR lpszClass;
DWORD dwExStyle;
} CREATESTRUCT;
里面果真有个HMENU,这是个菜单句柄,可能性加大了。但是你现在还不能肯定,怎么办?把这句话注释掉,看是不是主菜单没有了?如果没有了主菜单,那么就可以肯定主菜单肯定是在这句代码中创建的。好的,试试看,主菜单还在。显然寻找失败了,不然主菜单不可能还在。
继续寻找,发现下面还有个:
if( !CFrameWnd::PreCreateWindow(cs) )
return FALSE;
return TRUE;
}
难道是这个吗?按照上面相同的方法,我将这句注释掉,发现主菜单不见了,而且提示“创建空文档失败”。显然,我们现在还不能肯定主菜单一定是在这个函数中创建的。我们搜下包含文字"LoadMenu"的文件,因为创建主菜单往往要加载菜单资源。发现在WINFRAM.CPP中有CFrameWnd::Create函数包含loadMenu. 接下来分别在CFrameWnd::OnCreate(lpCreateStruct) == -1), if( !CFrameWnd::PreCreateWindow(cs) ) 和LOADMENU加三个断点,发现程序的确运行到这三个位置,并且LOADMENU是在CFrameWnd::OnCreate(lpCreateStruct) == -1)之前。现在看看CFrameWnd::PreCreateWindow(cs),代码如下:
BOOL CFrameWnd::PreCreateWindow(CREATESTRUCT& cs)
{
if (cs.lpszClass == NULL)
{
VERIFY(AfxDeferRegisterClass(AFX_WNDFRAMEORVIEW_REG));
cs.lpszClass = _afxWndFrameOrView; // COLOR_WINDOW background
}
if ((cs.style & FWS_ADDTOTITLE) && afxData.bWin4)
cs.style |= FWS_PREFIXTITLE;
if (afxData.bWin4)
cs.dwExStyle |= WS_EX_CLIENTEDGE;
return TRUE;
}可以看到,它并没有做什么,只是修改了窗口的样式。
现在我们可以得出两个结论,主菜单是在precreatewindow之后创建的,并且是在oncreate被调用之前创建的。
我们看看还有什么代码我们没有用到,在这些代码中可能含有我们所要找的东西。我们知道设置主菜单的函数为setmenu,它是CFRAMEWND的成员函数,我们在CFRAMEWND的实现代码中搜索它,有以下几个函数包括它。
OnUpdateFrameMenu,OnDestroy,OnSetPreviewMode.这三个函数都有可能,我们用排除法。查询MSDN,发现后面两个在一般情况下不会被调用,故可以肯定主菜单是在cframewnd加载,在ONUPDATEFRAMEMENU中设置的。我们可以看下主框架的函数调用顺序。
loadFrame->precreatewindow->create(加载菜单)->oncreate->oncreateclient->createview->InitialUpdateFrame->
OnIdleUpdateCmdUI(在这里调用了OnIdleUpdateCmdUI设置了主菜单)。
这是我自己的探索过程,能力有限,有可能有错误,关键在于思路。
另外提示一下:如果 要隐藏主菜单或者设置自己的菜单为主菜单,可以映射主框架的Wm_SHOWWINDOW消息。这个消息是发生在主框架和视图已经建立后,窗口显示前。如果在之前的地方设置,会出现错误,而在显示之后再设置菜单就达不到预定的目的。