如何在无文档/视图架构的SDI MFC程序中嵌入CFormView到ChildView
在无文档/视图架构的SDI MFC应用中嵌入CFormView到ChildView
不用纠结文档/视图架构的复杂逻辑,咱们直接手动把MyFormView嵌入到ChildView里,步骤很清晰:
1. 给ChildView添加FormView成员变量
首先在ChildView.h里引入MyFormView的头文件,然后声明一个指针成员来持有FormView实例:
#include "MyFormView.h" class CChildView : public CWnd { DECLARE_DYNAMIC(CChildView) // ... 已有代码 ... private: MyFormView* m_pFormView; // 保存FormView的指针 };
2. 在ChildView的OnCreate中创建并初始化FormView
CFormView虽然没有专门的Create方法,但它继承自CView,可以直接用CView::Create来创建窗口。修改ChildView.cpp的OnCreate方法:
int CChildView::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CWnd::OnCreate(lpCreateStruct) == -1) return -1; // 实例化并创建MyFormView m_pFormView = new MyFormView(); if (!m_pFormView->Create( NULL, // 类名,用默认的 NULL, // 窗口标题 WS_CHILD | WS_VISIBLE, // 子窗口+可见风格 CRect(0, 0, 0, 0), // 初始位置(后续会调整) this, // 父窗口是当前ChildView AFX_IDW_PANE_FIRST, // 控件ID,用MFC默认的视图ID NULL // 创建参数 )) { TRACE0("创建FormView失败!\n"); delete m_pFormView; m_pFormView = nullptr; return -1; } return 0; }
3. 让FormView跟随ChildView自动调整大小
当窗口缩放时,需要让FormView铺满ChildView的客户区。我们处理WM_SIZE消息:
- 在
ChildView.h里声明消息处理函数:
afx_msg void OnSize(UINT nType, int cx, int cy); afx_msg void OnDestroy(); // 后面用来销毁FormView
- 在
ChildView.cpp的消息映射里添加:
BEGIN_MESSAGE_MAP(CChildView, CWnd) // ... 已有映射 ... ON_WM_SIZE() ON_WM_DESTROY() END_MESSAGE_MAP()
- 实现
OnSize方法:
void CChildView::OnSize(UINT nType, int cx, int cy) { CWnd::OnSize(nType, cx, cy); // 确保FormView已创建且窗口有效 if (m_pFormView && m_pFormView->GetSafeHwnd()) { // 让FormView铺满整个ChildView客户区 m_pFormView->MoveWindow(0, 0, cx, cy); } }
4. 正确销毁FormView避免内存泄漏
在ChildView的OnDestroy方法里手动释放FormView:
void CChildView::OnDestroy() { CWnd::OnDestroy(); if (m_pFormView) { delete m_pFormView; m_pFormView = nullptr; } }
5. 完善MyFormView的MFC动态创建支持
虽然我们是手动new的FormView,但给它加上MFC的动态创建宏能避免潜在问题,在MyFormView.h里添加:
class MyFormView : public CFormView { DECLARE_DYNCREATE(MyFormView) // 添加这个宏 public: enum { IDD = IDD_MYVIEW }; MyFormView() : CFormView(IDD) {}; virtual ~MyFormView() {}; // ... 你的其他成员 ... };
然后在MyFormView.cpp里添加:
IMPLEMENT_DYNCREATE(MyFormView, CFormView) BEGIN_MESSAGE_MAP(MyFormView, CFormView) // 这里可以添加你的控件消息映射,比如按钮点击、编辑框输入等 END_MESSAGE_MAP()
为什么这么做?
- 和文档/视图架构不同,我们手动管理
MyFormView的生命周期:创建、显示、调整大小、销毁,完全绕开了文档模板的复杂逻辑。 CFormView本质是带对话框资源的CView,所以用CView::Create就能把它作为子窗口嵌入到ChildView中。WS_CHILD | WS_VISIBLE是关键风格,确保它作为子窗口显示在父窗口内部。
这样改完之后,运行你的程序就能看到资源编辑器里设计的控件正常显示在ChildView里了。
内容的提问来源于stack exchange,提问作者Rafal
相关产品推荐
相关产品推荐

