error C2440: “static_cast” : 无法从“void (__thiscall CMainFrame::* ) (NMTOOLBARA *,LRESULT *)”转换为“void

本文介绍了解决从VC6迁移到VC7时遇到的NMTOOLBAR错误问题。通过修改OnToolbarDropDown函数原型,并在函数实现中加入强制类型转换,可以有效解决此兼容性问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

将一个项目由vc6转 到vc7下面,ON_NOTIFY的NMTOOLBAR老是提示错误 error C2440: “static_cast” : 无法从“void (__thiscall CMainFrame::* ) (NMTOOLBARA *,LRESULT *)”转换为“void (__thiscall CCmdTarget::* ) (NMHDR *,LRESULT *)” 

解决方法:  

VC6下OnToolbarDropDown的函数原型: void CMainFrame::OnToolbarDropDown(NMTOOLBAR* pnmtb, LRESULT *plr) 把他改成: void CMainFrame::OnToolbarDropDown(NMHDR* pnmhdr, LRESULT *plr)    

在函数实现里加上强制转换

LPNMTOOLBAR pnmtb = reinterpret_cast<LPNMTOOLBAR>(pnmhdr);



亲测解决  http://m.blog.youkuaiyun.com/blog/napolun007/5915711

<think>我们正在处理MFC框架中的自定义标签栏实现。用户询问如何触发`CMainFrame::OnMDIChildCreate(CWnd* pChild)`函数。 在MFC中,当创建MDI子窗口时,框架会自动调用该函数。但是,这个函数并不是MFC的标准消息映射函数,因此需要我们自己实现消息路由。 步骤: 1. 首先,我们需要在CMainFrame类中声明该函数。 2. 然后,我们需要在MDI子窗口创建时,从子窗口发送一个自定义消息到主框架,或者重写MDI子窗口的创建过程,以便主框架能够捕获创建事件。 然而,MFC本身并没有直接提供这样的消息。我们可以通过以下方式之一来实现: - 在MDI子窗口的OnCreate函数中,获取主框架指针并调用主框架的自定义函数。 - 使用MFC的消息映射机制,自定义一个消息,并在子窗口创建时发送该消息到主框架。 这里我们采用第一种方法,因为它更直接。 实现示例: 在MainFrm.h中声明函数: ```cpp class CMainFrame : public CMDIFrameWndEx { // ... 其他声明 ... protected: // 声明处理MDI子窗口创建的函数 void OnMDIChildCreate(CWnd* pChild); }; ``` 在MDI子窗口的OnCreate函数中,调用主框架的这个函数: ```cpp int CChildFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CMDIFrameWnd::OnCreate(lpCreateStruct) == -1) return -1; // 获取主框架指针 CMainFrame* pMainFrame = dynamic_cast<CMainFrame*>(AfxGetMainWnd()); if (pMainFrame != nullptr) { pMainFrame->OnMDIChildCreate(this); } return 0; } ``` 但是,如果希望使用MFC的消息映射,我们可以定义一个用户消息: 在MainFrm.h中: ```cpp #define WM_MDICHILD_CREATE (WM_USER + 100) ``` 然后在CMainFrame的消息映射中添加: ```cpp BEGIN_MESSAGE_MAP(CMainFrame, CMDIFrameWndEx) // ... 其他消息 ... ON_MESSAGE(WM_MDICHILD_CREATE, &CMainFrame::OnMDIChildCreate) END_MESSAGE_MAP() ``` 在MDI子窗口的OnCreate中发送消息: ```cpp int CChildFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CMDIFrameWnd::OnCreate(lpCreateStruct) == -1) return -1; // 发送消息到主框架 AfxGetMainWnd()->SendMessage(WM_MDICHILD_CREATE, (WPARAM)this); return 0; } ``` 然后,在CMainFrame中实现OnMDIChildCreate函数: ```cpp LRESULT CMainFrame::OnMDIChildCreate(WPARAM wParam, LPARAM lParam) { CWnd* pChild = reinterpret_cast<CWnd*>(wParam); // 处理子窗口创建 // ... 比如将子窗口添加到自定义标签栏 ... return 0; } ``` 注意:使用SendMessage是同步的,会立即处理。如果不需要立即处理,也可以用PostMessage。 但是,根据用户之前的问题,他们正在实现自定义标签栏,所以当MDI子窗口创建时,他们需要将子窗口添加到标签控件中。 因此,我们采用第二种方法(自定义消息)可能更符合MFC的消息机制,避免直接依赖具体的子窗口类。 现在,我们给出完整的修正和实现步骤: 步骤1:在MainFrm.h中定义消息和声明消息处理函数 ```cpp // MainFrm.h class CMainFrame : public CMDIFrameWndEx { // ... 其他代码 ... protected: afx_msg LRESULT OnMDIChildCreate(WPARAM wParam, LPARAM lParam); // ... 其他代码 ... }; ``` 步骤2:在MainFrm.cpp中实现消息映射和函数 ```cpp // MainFrm.cpp BEGIN_MESSAGE_MAP(CMainFrame, CMDIFrameWndEx) // ... 其他消息映射 ... ON_MESSAGE(WM_MDICHILD_CREATE, &CMainFrame::OnMDIChildCreate) END_MESSAGE_MAP() // 定义消息值 #define WM_MDICHILD_CREATE (WM_USER + 100) LRESULT CMainFrame::OnMDIChildCreate(WPARAM wParam, LPARAM lParam) { CWnd* pChild = reinterpret_cast<CWnd*>(wParam); if (pChild != nullptr) { // 在这里将子窗口添加到标签控件 // 例如:m_wndCustomTabs.AddTab(pChild, _T("New Tab")); } return 0; } ``` 步骤3:在MDI子窗口的OnCreate中发送消息 ```cpp // ChildFrm.cpp int CChildFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CMDIFrameWnd::OnCreate(lpCreateStruct) == -1) return -1; // 发送自定义消息给主框架 AfxGetMainWnd()->SendMessage(WM_MDICHILD_CREATE, (WPARAM)this, 0); return 0; } ``` 这样,每当一个MDI子窗口被创建时,就会触发CMainFrame::OnMDIChildCreate函数。 注意:如果子窗口在创建时还没有完全初始化,可能需要考虑在OnCreate之后发送消息,或者使用PostMessage以确保子窗口已经完全创建。 另外,还需要处理子窗口的销毁事件,以便从标签栏中移除对应的标签。 因此,我们可以类似地处理WM_MDICHILD_DESTROY消息。 总结:通过自定义消息,我们可以实现MDI子窗口创建事件的触发。 §§相关问题§§ 1. 在MFC中,如何安全地使用自定义消息进行窗口间通信? 2. 当MDI子窗口被销毁时,如何自动更新自定义标签栏中的标签项? 3. 除了使用SendMessage,还有哪些方法可以在MFC中实现窗口创建事件的通知? 4. 如何确保在MDI子窗口创建过程中,自定义标签栏添加标签时子窗口已经完成初始化? 5. 在多文档应用程序中,如何处理多个不同类型的子窗口(如视图不同)在自定义标签栏中的显示?</think>### 触发 `CMainFrame::OnMDIChildCreate` 的方法 在 MFC 框架中,`OnMDIChildCreate` 不是内置的消息处理函数。要实现子窗口创建时的自定义处理,需要通过以下步骤手动实现消息路由: #### 1. **声明自定义消息** 在框架头文件中定义消息标识符: ```cpp // MainFrm.h #define WM_MDICHILD_CREATE (WM_USER + 100) // 自定义消息ID ``` #### 2. **添加消息映射** 在框架类中添加消息处理声明: ```cpp // MainFrm.h class CMainFrame : public CMDIFrameWndEx { // ... protected: afx_msg LRESULT OnMDIChildCreate(WPARAM wParam, LPARAM lParam); DECLARE_MESSAGE_MAP() }; ``` #### 3. **实现消息映射和处理** 在框架源文件中实现消息路由: ```cpp // MainFrm.cpp BEGIN_MESSAGE_MAP(CMainFrame, CMDIFrameWndEx) ON_MESSAGE(WM_MDICHILD_CREATE, &CMainFrame::OnMDIChildCreate) END_MESSAGE_MAP() LRESULT CMainFrame::OnMDIChildCreate(WPARAM wParam, LPARAM lParam) { CWnd* pChild = reinterpret_cast<CWnd*>(wParam); CString strTitle = reinterpret_cast<LPCTSTR>(lParam); // 在此添加子窗口创建后的处理逻辑 TRACE(_T("MDI子窗口已创建: %s\n"), strTitle); // 添加到自定义标签栏 m_wndCustomTabs.AddTab(pChild, strTitle); return 0; } ``` #### 4. **在子窗口触发消息** 在 MDI 子窗口的 `OnCreate` 方法中发送通知: ```cpp // ChildFrm.cpp int CChildFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CMDIChildWndEx::OnCreate(lpCreateStruct) == -1) return -1; // 获取文档标题 CString strTitle; GetWindowText(strTitle); // 通知主框架 CMainFrame* pMainFrame = dynamic_cast<CMainFrame*>(AfxGetMainWnd()); if (pMainFrame) { pMainFrame->SendMessage( WM_MDICHILD_CREATE, reinterpret_cast<WPARAM>(this), reinterpret_cast<LPARAM>(static_cast<LPCTSTR>(strTitle)) ); } return 0; } ``` ### 替代方案:使用虚函数重写 如果使用 `CMDIChildWndEx` 派生类,可以重写虚函数: ```cpp // ChildFrm.h class CChildFrame : public CMDIChildWndEx { virtual void OnCreate(); }; // ChildFrm.cpp void CChildFrame::OnCreate() { CMDIChildWndEx::OnCreate(); CMainFrame* pMain = dynamic_cast<CMainFrame*>(GetMDIFrame()); if (pMain) { pMain->OnMDIChildCreated(this); // 自定义处理函数 } } ``` ### 注意事项 1. **线程安全**:确保在 GUI 线程中发送消息 2. **对象生命周期**:子窗口应在完全初始化后发送通知 3. **类型转换**:使用 `dynamic_cast` 确保框架类型安全 4. **消息冲突**:自定义消息 ID 应在 `WM_USER+100` 到 `0x7FFF` 范围内
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值