2
votes

I have a SDI MFC App without Document/View support. I want to embed the CFormView with controls designed in resource editor in ChildView. How do I do that?

The MFC Wizard generated 3 files:

  • App.cpp (derived from CWinApp)
  • MainFrame.cpp (derived from CFrameWnd)
  • ChildView.cpp (derived from CWnd)

Now, I have generated custom class that derives from CFormView, where IDD_MYVIEW is the generated ID to resource GUI.

class MyFormView: public CFormView
{
public:
    enum { IDD = IDD_MYVIEW  };

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

How do I display this MyFormView in ChildView?

As I tried generating the project again and checked in the MFC wizard the Document/View architecture checkbox and changed the base class of View to CFormView. I realized that the App initialization is different than the initially generated one.

Currently the first app is initialized as follows:

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;
}

furthermore the MainFrame initializes the ChildView in the OnCreate method.

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;
    }
}

where m_wndView is the ChildView. I think that I should initialize the CFormView in OnCreate method of the ChildView, but I don't know how to do that nor how to "show" it. Because the CFormView does not have these methods.

On the other hand the initialization with the Doc/View architecture looks like this. And seems to automatically cover what I want to achieve.

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);
    // (...)
}

The thing is, I see that in the second generated Project the CFormView is provided to the SingleDocTemplate constructor and I could place my controls there. But in the first generated project I don't know where I could connect the CFormView to displayed ChildView. I don't know how and where can I connect my new CFormView.

I find the Doc/View architecture overwhelming and unnecessary for the app I need and would like to proceed with it just for the sake of understanding it.

1
When you design your project you choose a SDI or a MDI project. A single or multi document interface. Your document is associated with a view. At project design time you decide what type of view you are going to use. So the project will provide you with a skeleton form for you to add your controls to. I don't quite see what your problem is?Andrew Truckle
Why create a SDI without a doc/view? You are making it hard for yourself. If all you want is a dialog then why not make a dialog based project instead.Andrew Truckle
@RonTLV: Could you post the link as an answer? The content from the link is a spot on and helped me understand my problem.Rafal

1 Answers

3
votes

Since @RonTLV didn't post his Link as an answer, I will interpret how I could fix my problem with the Link @RonTLV provided.

In short: I was missing the DYNCREATE macros for my CFormView class and in the MainFrame (CFrameWnd) there needs to be a pointer instead of instance to the CFormView, which in the OnCreate method of MainFrame must be downcasted (via macro).

Below you can find the CFormView class header with necessary macros:

class MyFormView : public CFormView
{
    DECLARE_DYNCREATE(MyFormView)

public:
    enum { IDD = IDD_RANGERCONTROLS  };

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

    DECLARE_MESSAGE_MAP()

public:
};

In the cpp file I have added the IMPLEMENT_DYNCREATE macro as shown below:

IMPLEMENT_DYNCREATE(MyFormView, CFormView)

MyFormView::MyFormView()
    : CFormView(MyFormView::IDD)
{
};

MyFormView::~MyFormView()
{
}

BEGIN_MESSAGE_MAP(MyFormView, CFormView)
END_MESSAGE_MAP()

And finally in the MainFrame::OnCreate method

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);

where, m_pMainView is declared as the private member of CMainFrame:

MyFormView* m_pMainView;