1
votes

I have a SDI MFC application which CMainFrame class is derived from CFrameWndEx. The app uses the CSingleDocument template for connecting Document/View/Frame.

I need to have another window with the contents of a View related to the same document of the view of the Main Window. Is it correct to have another instance of the CMainFrame as a secondary window?

2

2 Answers

2
votes

After some approaches I came to a solution:

1st:

Have two CMainFrame instances on the App, where the second has a boolean field to indicate it is one or other. This boolean allowed me to skip the creation of everthing creation only on the second, because I only want it to be a rectangle with the view. I've added a special public constructor that to CMainFrame that always puts the referred boolean to true.

    CMainFrame *pSecondFrame = new CMainFrame(TRUE /*dumb*/);

It worked, but it was very slow. The view of the first MainFrame was completely unusable due to its lack of speed.

2nd:

Have a CSecondFrame that is also derived from CFrameWndEx and has almost nothing on its body. As IDR_MAINFRAME has nothing, I can expect to do LoadFrame(IDR_MAINFRAME) and have an almost empty frame on the App.

    CSecondFrame *pSecondFrame = new CSecondFrame();

It worked, but it was very slow. The view of the first MainFrame was completely unusable due to its lack of speed.

For both 1st and 2nd approaches, I had to add a new CreateContext, as I can not reuse the mainframe View:

if (!pSecondFrame->LoadFrame(IDR_MAINFRAME))
    return FALSE;

CMainFrame* pMainFrame=(CMainFrame*)::AfxGetMainWnd();
if (!pMainFrame)
        return FALSE;

CMyView* pView=(CMyView*)(pMainFrame->GetActiveView());
if (!pView)
    return FALSE;

CCreateContext context;

context.m_pCurrentDoc=pMainFrame->GetActiveDocument();
context.m_pNewViewClass= RUNTIME_CLASS(CMyView);
context.m_pLastView= pView;
context.m_pCurrentFrame = pSecondFrame;

pSecondFrame->CreateView(&context);

3rd:

At the beginning of the InitInstance function I have the Document Template:

So lets play with its CreateNewFrame method: POSITION pos= pDocTemplate->GetFirstDocPosition();

            //pFrameTemp attribution

    CFrameWnd* pSecondFrame= pDocTemplate->CreateNewFrame(pDocTemplate->GetNextDoc(pos),pFrameTemp);

I tried different things for the pFrameTemp: NULL, a CMainFrame, CSecondFrame. Everytime I got a frame that is carbon-copy of the main and I dont't want this.

For the CMainFrame and CSecondFrame cases I tried to explicity call their Create( ...) functions, which fail,so they don't even pass on their OnCreate(...) method. Instead of this I also tried to do a LoadFrame(IDR_MAINFRAME) for both cases. Now I will have three frames: The Main, the Second, which is carbon-copy of the main, and the one created with LoadFrame, which is totally blank.

4th: After seeing that he CreateNewFrame method creates a new Frame based on the frame it has on the template and not the one that is passed in its parameter, I decided to try create addicionally another template:

CSingleDocTemplate* pSecondDocTemplate;
pSecondDocTemplate2 = new CSingleDocTemplate(
    MenuID,
    RUNTIME_CLASS(CMyDoc),
    RUNTIME_CLASS(CSecondFrame),//only the frame differs
    RUNTIME_CLASS(CMyView));
AddDocTemplate(pSecondDocTemplate);

POSITION pos= pDocTemplate->GetFirstDocPosition();
CFrameWnd* pSecondFrame=pSecondDocTemplate->CreateNewFrame(pDocTemplate->GetNextDoc(pos), NULL);

Notice that I am giving the doc of the first template as parameter, not the second, to CreateNewFrame. This is the only solution I tested that works and doesn't slow down operations in the view.

It seems I need, for every solution I presented to do

 pSecondFrame->ShowWindow(SW_SHOW);

for getting the window visible.

0
votes

Have you considered adding an additional CView in a splitter window? This SO topic covers it, and has links to details.