vc MDI子窗口标题丢失

来源:百度知道 编辑:UC知道 时间:2024/06/11 19:12:16
....
HWND parent = ::FindWindowEx(AfxGetMainWnd()->m_hWnd,NULL,"MDIClient",NULL); //在主窗口中查找
HWND child = ::FindWindowEx(parent,NULL,NULL,str); //查询子窗口是否已经打开
if (child != NULL) //判断子窗口是否已经打开
::BringWindowToTop(child); //设为活动窗口
else
{
//自定义创建子窗口
POSITION tplPos = AfxGetApp()->GetFirstDocTemplatePosition();
CDocTemplate * pDocTpl = AfxGetApp()->GetNextDocTemplate(tplPos);
CDocument * pNewDoc = new CDocument(); //创建一个新文档
CChildFrame * pNewChWnd = (CChildFrame *)(pDocTpl->CreateNewFrame(pNewDoc, NULL)); //创建子窗口框架
pNewChWnd->SetTitle(_T(str)); //设置文档标题
pNewChWnd->ShowWindow(SW_SHOWNORMAL); //显示子窗口
pNewChWnd->SetFocus(); //获取焦点
}
....
==================================================================
上面的方式创建的子窗口,当有两个子窗口A、B的时候,鼠标点不活动的子窗口内部区域(客户区)使子窗口A为活动窗口,然后鼠标点子窗口B改为子窗口B为活动窗口,此时变为不活动的子窗口A的标

在 CDocument * pNewDoc = new CDocument();后面添一句
pNewDoc->SetTitle(_(str));
然后再看看。

分析如下:
当子窗口由非活动转为活动时,MFC的CMDIFrameWnd类会自动调用OnUpdateFrameTitle(BOOL bAddToTitle)函数,在函数体中可以发现这样一句判断语句并进入:if (bAddToTitle &&
(pActiveChild = MDIGetActive()) != NULL &&
(pActiveChild->GetStyle() & WS_MAXIMIZE) == 0 &&
(pDocument != NULL ||
(pDocument = pActiveChild->GetActiveDocument()) != NULL))

最后执行UpdateFrameTitleForDocument(pDocument->GetTitle());
关键是最后一句会调用pDocument->GetTitle(),由于新的文档没有标题,导致CMDIFrameWnd也没有标题了!

调试技巧:
遇到问题后,知道了大概是在WM_ACTIVATE这块消息的处理时,MFC肯定内部会做处理,因此我们必须查看MFC内部是如何在子窗口得到WM_ACTIVATE时是如何处理的,可以重载这个消息处理函数,并在函数体中调用基类的这个消息处理函数,这样做的目的是方便设断点!设置了断点,然后鼠标单击新创建的窗口,使该断点触发,再通过VC菜单--调试》逐语句或逐过程,来跟踪MFC的基类代码。最后定位到“void CMDIFrameWnd::OnUpdateFrameTitle(BOOL bAddToTitle)”这个函数,且查到问题症结在“UpdateFrameTitleForDocument(pDocument->GetTitle());”这个函数上。问题找到!!!
P.S.在多文档MFC中,CMDIFrameWnd被激活得到的是WM_MDIACTIVATE,所以应该