我们的一个MFC遗留应用程序显示了我现在还不太了解的行为。但是,我不是MFC专家。我观察到的症状和导致问题的症状是,在应用启动期间,框架会调用OnInitialUpdate两次视图。据我所知,文档应该只调用一次。
我的调查显示应用程序在其InitInstance中调用以下代码:
CMainFrame *const pMainFrame = new CMainFrame;
if (!pMainFrame->LoadFrame(IDR_MAINFRAME)) { return FALSE; }
m_pMainWnd = pMainFrame;
这会导致在框架内调用CFrameWnd::LoadFrame
。从这里开始调用OnInitialUpdate。第一次调用Create
时,第二次调用SendMessageToDescendants
时发送WM_INITIALUPDATE
。
我们的应用程序重载CMainFrame::OnCreateClient
以创建拆分器窗口:
Splitter.CreateStatic(this, 2, 2);
Splitter.CreateView(0, 0, RUNTIME_CLASS(MyView),CSize(0,0), pContext);
// ...
对Splitter.CreateView
的调用是第一次触发OnInitialUpdate的内容。但正如我从文档中看到的那样,这个实现是按照预期的。所以不幸的是,这是我被卡住的地方。我不明白来自SendMessageToDescendants(WM_INITIALUPDATE, 0, 0, TRUE, TRUE)
或来自CSplitterWnd::CreateView
的{{3}}来电是否错误。
修改
进一步调查表明,如果传递的CSplitterWnd::CreateView
是nullptr,则WM_INITIALUPDATE
仅发送CCreateContext
。所以我检查了CMainFrame::OnCreateClient
,它确实被框架调用,pContext
为nullptr。
EDIT2
根据评论中的要求,添加了DocTemplate的代码:
CSingleDocTemplate *const pDocTemplate = new CSingleDocTemplate(
IDR_MAINFRAME,
RUNTIME_CLASS(CMenuDoc),
RUNTIME_CLASS(CMainFrame),
RUNTIME_CLASS(CMenuView));
if (!pDocTemplate)
return FALSE;
AddDocTemplate(pDocTemplate);
还有一个电话
Splitter.CreateView(1, 1, RUNTIME_CLASS(CMenuView),CSize(0,0), pContext);
CMainFrame::OnCreateClient
中的。如果我理解这些评论是错误的吗?
OnInitialUpdate的两次调用是针对相同的视图实例。如果我正确地跟踪堆栈跟踪,CCreateContext
是nullptr的原因是没有上下文传递给LoadFrame
。传递给CFrameWnd::LoadFrame
的上下文仅转发给CMainFrame::OnCreateClient
。但是我应该通过什么背景?