如何在 MFC 的 CWnd 中显示 CFormView?

Posted

技术标签:

【中文标题】如何在 MFC 的 CWnd 中显示 CFormView?【英文标题】:How to show CFormView in CWnd in MFC? 【发布时间】:2018-01-31 11:17:55 【问题描述】:

我有一个不支持文档/视图的 SDI MFC 应用程序。我想在 ChildView 的资源编辑器中嵌入带有控件的 CFormView。我该怎么做?

MFC 向导生成了 3 个文件:

App.cpp(源自CWinApp) MainFrame.cpp(源自CFrameWnd) ChildView.cpp(源自CWnd

现在,我生成了派生自 CFormView 的自定义类,其中 IDD_MYVIEW 是生成的资源 GUI 的 ID。

class MyFormView: public CFormView

public:
    enum  IDD = IDD_MYVIEW  ;

    MyFormView(): CFormView(IDD) ;
    virtual ~MyFormView() ;

如何在 ChildView 中显示这个 MyFormView?

当我尝试再次生成项目并在 MFC 向导中选中文档/视图架构复选框并将 View 的基类更改为 CFormView。我意识到 App 初始化与最初生成的不同。

目前第一个app初始化如下:

BOOL MfcApp::InitInstance() 

    // (...)

    CMainFrame* pFrame = new CMainFrame;
    if (!pFrame)
        return FALSE;
    m_pMainWnd = pFrame;
    // create and load the frame with its resources
    pFrame->LoadFrame(IDR_MAINFRAME,
        WS_OVERLAPPEDWINDOW | FWS_ADDTOTITLE, NULL,
        NULL);

    // The one and only window has been initialized, so show and update it
    pFrame->ShowWindow(SW_SHOW);
    pFrame->UpdateWindow();
    return TRUE;

此外 MainFrame 在 OnCreate 方法中初始化 ChildView。

int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)

    if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
        return -1;

    // create a view to occupy the client area of the frame
    if (!m_wndView.Create(NULL, NULL, AFX_WS_DEFAULT_VIEW, CRect(0, 0, 0, 0), this, AFX_IDW_PANE_FIRST, NULL))
    
        TRACE0("Failed to create view window\n");
        return -1;
    

其中m_wndViewChildView。我认为我应该在ChildViewOnCreate 方法中初始化CFormView,但我不知道该怎么做,也不知道如何“显示”它。因为CFormView没有这些方法。

另一方面,Doc/View 架构的初始化看起来像这样。并且似乎自动涵盖了我想要实现的目标。

BOOL MfcApp::InitInstance() 

    // (...)
    CSingleDocTemplate* pDocTemplate;
    pDocTemplate = new CSingleDocTemplate(
        IDR_MAINFRAME,
        RUNTIME_CLASS(CMFCPlaygroundDoc),
        RUNTIME_CLASS(CMainFrame),       
        RUNTIME_CLASS(CMFCPlaygroundView)); // <-- derived from CFormView
    if (!pDocTemplate)
        return FALSE;
    AddDocTemplate(pDocTemplate);
    // (...)

问题是,我看到在第二个生成的项目中,CFormView 被提供给 SingleDocTemplate 构造函数,我可以在那里放置我的控件。但是在第一个生成的项目中,我不知道在哪里可以将 CFormView 连接到显示的 ChildView。我不知道如何以及在哪里可以连接我的新 CFormView。

我发现 Doc/View 架构对于我需要的应用程序来说是压倒性的和不必要的,我想继续使用它只是为了理解它。

【问题讨论】:

在设计项目时,您可以选择 SDI 或 MDI 项目。单文档或多文档界面。您的文档与视图相关联。在项目设计时,您决定要使用哪种类型的视图。因此,该项目将为您提供一个骨架表单,供您添加控件。我不太明白你的问题是什么? 为什么要创建没有文档/视图的 SDI?你让自己很难受。如果你想要的只是一个对话框,那么为什么不创建一个基于对话框的项目呢。 Can a MFC dialog resource be attached to a CChildView?的可能重复 在这里试试:codeproject.com/Articles/5445/… @RonTLV:您可以发布链接作为答案吗?链接中的内容很重要,帮助我理解了我的问题。 【参考方案1】:

由于@RonTLV 没有发布他的链接作为答案,我将解释如何使用提供的Link @RonTLV 解决我的问题。

简而言之:我缺少 CFormView 类的 DYNCREATE 宏,并且在 MainFrame (CFrameWnd) 中需要一个指向 CFormView 的指针而不是实例,在 MainFrame 的 OnCreate 方法中必须向下转换(通过宏)。

您可以在下面找到带有必要宏的 CFormView 类头:

class MyFormView : public CFormView

    DECLARE_DYNCREATE(MyFormView)

public:
    enum  IDD = IDD_RANGERCONTROLS  ;

    MyFormView();// : CFormView(IDD) ;
    virtual ~MyFormView();

    DECLARE_MESSAGE_MAP()

public:
;

在 cpp 文件中我添加了IMPLEMENT_DYNCREATE 宏,如下所示:

IMPLEMENT_DYNCREATE(MyFormView, CFormView)

MyFormView::MyFormView()
    : CFormView(MyFormView::IDD)

;

MyFormView::~MyFormView()



BEGIN_MESSAGE_MAP(MyFormView, CFormView)
END_MESSAGE_MAP()

最后在MainFrame::OnCreate 方法中

CCreateContext ccx;
ccx.m_pNewViewClass = RUNTIME_CLASS(MyFormView);
m_pMainView = DYNAMIC_DOWNCAST(MyFormView, this->CreateView(&ccx));

if (NULL == m_pMainView)

    TRACE0("Creation of View failed.\n");


RecalcLayout();
m_pMainView->ShowWindow(SW_SHOW);
m_pMainView->OnInitialUpdate();
SetActiveView(m_pMainView);

其中,m_pMainView 被声明为 CMainFrame 的私有成员:

MyFormView* m_pMainView;

【讨论】:

以上是关于如何在 MFC 的 CWnd 中显示 CFormView?的主要内容,如果未能解决你的问题,请参考以下文章

HWND CWND 转换

MFC:如何从不同的线程绘制opengl?

(转)CWnd与HWND的区别与转换

创建单独的 MFC GUI 线程,不能移动/调整大小/最大化 CWnd

无法在 MFC 无窗口 Activex 中获取 Cwnd 类的句柄?

如何处理 CWnd 中的 wm_print 消息(使用 MFC)?