CFrameWnd::GetActiveView函数点滴

本文探讨了一种在不使用文档视图结构的MFC应用程序中,CMainFrame::OnCmdMsg如何处理WM_COMMAND消息。文章指出CFrameWnd::GetActiveView在非文档视图结构中通常返回NULL,导致消息无法正确传递给视图。作者通过测试发现,必须在CMainFrame::OnCmdMsg中直接调用m_wndView.OnCmdMsg以确保消息传递给视图。作者正寻找更多关于CFrameWnd::GetActiveView的资料以验证其理解,并欢迎读者指正错误。

       我用vc6的生成向导生成了一个不使用document/view结构的运用程序。

        仔细看了一下他的结构,发现了一个函数如下(摘自mfc源代码):

BOOL CMainFrame::OnCmdMsg(UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo)
{
 // let the view have first crack at the command
 if (m_wndView.OnCmdMsg(nID, nCode, pExtra, pHandlerInfo))
 {
  return TRUE;
 }
 // otherwise, do default handling
 return CFrameWnd::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo);
}

         开始的时候,我对这段代码很不理解,因为OnCmdMsg函数是处理WM_COMMAND消息的。参照CFrameWnd::OnCmdMsg,CView::OnCmdMsg,CCmdTarget::OnCmdMsg,CDocument::OnCmdMsg的说明。似乎整个WM_COMMAND消息的流动路线已经被定型了,如下:

(图片摘自vckbase.com)

CFrameWnd::OnCmdMsg函数的部分代码如下:

BOOL CFrameWnd::OnCmdMsg(UINT nID, int nCode, voi

<think>我们遇到了一个编译错误:error C2352: 'CFrameWnd::ActivateFrame': illegal call of non-static member function。这个错误表明我们试图以非法方式调用非静态成员函数ActivateFrame。在MFC中,ActivateFrame是CFrameWnd类的一个非静态成员函数,因此必须通过一个CFrameWnd(或其派生类)的实例来调用。 错误原因分析: 通常,这个错误是因为我们试图直接使用类名来调用非静态成员函数,例如: CFrameWnd::ActivateFrame(nCmdShow); // 错误:非静态成员函数不能这样调用 正确的做法是通过一个框架窗口对象的指针或引用来调用该函数。 解决方案: 1. 确保在调用ActivateFrame时,是通过一个有效的框架窗口对象(如CMainFrame对象)来调用。 2. 在MFC应用程序中,我们通常在框架窗口创建后,在应用程序类的InitInstance函数中调用ActivateFrame。 示例代码: 假设我们有一个应用程序类CMyApp,和一个主框架类CMainFrame。在CMyApp::InitInstance中,我们创建并显示主框架窗口。 错误的调用方式: CFrameWnd::ActivateFrame(SW_SHOW); // 错误:非静态成员函数不能通过类名直接调用 正确的调用方式: 首先,我们需要获取主框架窗口的指针,然后通过该指针调用ActivateFrame。 在InitInstance中,通常的步骤是: 1) 创建框架窗口对象(但尚未创建窗口) 2) 调用LoadFrame创建窗口 3) 然后调用ShowWindow和UpdateWindow来显示窗口 但是,如果我们想要使用ActivateFrame来显示窗口,我们可以这样做: 修改应用程序类的InitInstance函数: ```cpp BOOL CMyApp::InitInstance() { // ... 其他初始化代码 // 创建主框架窗口 CMainFrame* pMainFrame = new CMainFrame; if (!pMainFrame->LoadFrame(IDR_MAINFRAME)) return FALSE; m_pMainWnd = pMainFrame; // 将主框架窗口设置为应用程序的主窗口 // 通过主框架窗口对象调用ActivateFrame pMainFrame->ActivateFrame(m_nCmdShow); // 注意:这里m_nCmdShow是应用程序启动时传递的参数 // 或者,如果我们要强制最大化,可以传递SW_SHOWMAXIMIZED // pMainFrame->ActivateFrame(SW_SHOWMAXIMIZED); return TRUE; } ``` 注意:ActivateFrame函数的作用是激活框架窗口并设置其显示状态(如正常、最大化、最小化)。它内部会调用ShowWindow和SetWindowPos等函数。 另外,我们也可以使用ShowWindow来显示窗口,但ActivateFrame除了显示窗口外,还会激活框架(使其成为活动窗口)并处理MDI子窗口的激活等。 如果我们在其他地方调用ActivateFrame,同样要确保通过一个有效的框架窗口对象指针来调用。 总结: 错误C2352是因为我们以调用静态成员函数的方式调用了非静态成员函数。解决方法是确保通过一个对象实例来调用。 如果问题仍然存在,请检查: - 调用ActivateFrame的上下文:是否在非成员函数中调用?是否在没有对象的情况下调用? - 调用ActivateFrame的对象指针是否有效(不为NULL)? 下面是一个错误示例和正确示例的对比: 错误示例: void SomeFunction() { // 错误:直接使用类名调用非静态成员函数 CFrameWnd::ActivateFrame(SW_SHOW); } 正确示例: void SomeFunction(CMainFrame* pFrame) { // 通过对象指针调用 pFrame->ActivateFrame(SW_SHOW); } 或者,如果我们有一个全局的框架窗口指针(如theApp.m_pMainWnd),可以这样调用: ((CMainFrame*)(theApp.m_pMainWnd))->ActivateFrame(SW_SHOW); 但是要注意,在框架窗口尚未创建时,m_pMainWnd可能为NULL。 最后,请确保在调用ActivateFrame之前,框架窗口已经创建(即已经调用了LoadFrame或Create函数)。 如果按照上述步骤操作,应该可以解决error C2352错误。</think>### 解决 MFC 中 `CFrameWnd::ActivateFrame` 非法调用错误 #### 错误原因分析 `error C2352: CFrameWnd::ActivateFrame: 非静态成员函数的非法调用` 通常发生在以下情况: 1. 直接通过类名调用非静态成员函数(缺少对象实例) 2. 在静态函数中错误调用非静态成员 3. 框架窗口未正确初始化时调用 4. 在错误的生命周期阶段调用该方法 #### 解决方案步骤 1. **正确调用方式(通过对象实例)** ```cpp // 正确调用方式(在框架类内部) void CMainFrame::OnSomeEvent() { // 通过当前对象调用 ActivateFrame(SW_SHOWMAXIMIZED); // ✅ 正确调用 } ``` 2. **在应用程序初始化时调用(推荐位置)** ```cpp BOOL CYourApp::InitInstance() { // ...其他初始化代码 // 创建主框架窗口 CMainFrame* pFrame = new CMainFrame; if (!pFrame->LoadFrame(IDR_MAINFRAME)) return FALSE; m_pMainWnd = pFrame; // 通过对象指针调用 pFrame->ActivateFrame(m_nCmdShow); // ✅ 合法调用[^1] return TRUE; } ``` 3. **确保窗口已初始化** ```cpp int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CFrameWnd::OnCreate(lpCreateStruct) == -1) return -1; // 确保窗口创建完成后再调用 PostMessage(WM_USER_ACTIVATE_FRAME); // 延迟调用 return 0; } // 消息处理函数 afx_msg LRESULT CMainFrame::OnActivateFrame(WPARAM, LPARAM) { ActivateFrame(SW_MAXIMIZE); // ✅ 安全调用 return 0; } ``` 4. **添加消息映射(若使用延迟调用)** ```cpp BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd) ON_MESSAGE(WM_USER_ACTIVATE_FRAME, OnActivateFrame) END_MESSAGE_MAP() ``` #### 关键注意事项 1. **对象生命周期**:确保在调用`ActivateFrame()`时框架窗口对象已完全初始化 2. **调用时机**: - 避免在构造函数中调用(此时窗口尚未创建) - 推荐在`OnCreate()`之后或通过`PostMessage()`延迟调用 3. **静态上下文**:在静态函数中调用时需先获取有效实例指针: ```cpp // 获取应用实例 CMainFrame* pFrame = (CMainFrame*)AfxGetApp()->m_pMainWnd; if(pFrame) pFrame->ActivateFrame(SW_SHOW); ``` #### 错误用法示例 ```cpp // ❌ 错误:直接通过类名调用 CFrameWnd::ActivateFrame(SW_SHOW); // 导致C2352错误 // ❌ 错误:在静态函数中无对象调用 void StaticFunction() { ActivateFrame(SW_SHOW); // 无有效对象 } ``` > **原理**:MFC框架中`CFrameWnd::ActivateFrame()`是虚函数,需要`this`指针访问窗口状态[^1]。直接通过类名调用相当于缺少`this`指针,违反C++对象模型规则。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值