Display multiple simultaneous views of the same document

How can I convince the Doc / View MFC architecture to allow me to simultaneously display two different types of the same document?

For example, let's say my CDocument subcategory is an archive of some description.
I want a UI where the names of all the records in this archive are presented in the CListView subclass in the left pane, and information about the currently selected record is displayed in the CEditView subclass in the right pane.

Only CSingleDocTemplate allows you to connect one document, one frame and one view. I still want to use the SDI application, but I need one document and two different views - isn't that all the point of a good Doc / View architecture?

+4
source share
3 answers

SDI stands for "Single Document Interface", it limits you to only one document at a time, but not the number of views that you can open for this document.

Probably the most common approach to opening multiple views in an SDI application is Windows Splitter .

You add one view to CSingleDocTemplate (no matter which one)

 pDocTemplate = new CSingleDocTemplate( IDR_MYRESOURCEID, RUNTIME_CLASS(CMyDoc), RUNTIME_CLASS(CMyFrameWnd), RUNTIME_CLASS(CMyListView)); 

An instance of CSplitterWnd m_wndSplitter appears in the frame window and you overload the OnCreateClient virtual function:

 BOOL CMyFrameWnd::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext) { VERIFY(m_wndSplitter.CreateStatic(this,1,2)); // one row / two columns VERIFY(m_wndSplitter.CreateView(0,0,RUNTIME_CLASS(CMyListView), CSize(300,300),pContext)); VERIFY(m_wndSplitter.CreateView(0,1,RUNTIME_CLASS(CMyEditView), CSize(300,300),pContext)); return TRUE; } 

This example creates a separator window with one row and two columns. On the left side of the splitter is a view of type CMyListView , and on the right side is a view of type CMyEditView .

You can even insert multiple splitter windows one into another to create arbitrary complex collections of views in the frame window.

Here is a short tutorial that shows how to work with splitter windows in an SDI application:

http://www.codeproject.com/KB/splitter/splitterwindowtutorial.aspx

Edit

Posting the views that you add to the document separator inside MFC: CCreateContext* pContext , which is passed to OnCreateClient , contains the m_pCurrentDoc link to the current document (Framewindow knows about this document). MFC uses this in CView::OnCreate (ViewCore.cpp) to add a view to the document: m_pCurrentDoc->AddView(this) and set the document pointer m_pDocument in the view.

Therefore, subsequent calls to UpdateAllViews your document will take care of all views.

+7
source

Revised based on comment:

Good thing you need is a static splitter window. The easiest way (I know) to create this is to start with the SDI MFC project and tell it that you want a splitter window (in the AppWizard, in the "User Interface Functions" section, check "Split window"). This will create a dynamic delimiter, i.e. It will start with only one panel, and you can create a second one by dragging the separation panel, but when you do this, you will only get two identical views (although you can scroll them separately from each other).

Then we need to do a little work to turn this from a dynamic splitter into a static splitter. It is probably best to start by looking at the code for a dynamic splitter. If you look at this CMainFrame application, you will find that it has:

 CSplitterWnd m_wndSplitter; 

If you look in the main frame of OnCreateClient , you will find something like this:

 return m_wndSplitter.Create(this, 2, 2, // TODO: adjust the number of rows, columns CSize(10, 10), // TODO: adjust the minimum pane size pContext); 

This is what we need to change - this is Create - this is what the dynamic delimiter creates. We need to get rid of this and create a static splitter instead. The first step for this is to create another presentation class - right now we have only one presentation class, but we want two, one for each panel.

The easiest way (which I know) to create our second presentation class is to run a second copy of VS and create another (separate) application. We will say that it runs the view class for this application with CListView . Then we take the files for this view and add them to our original project. To simplify the connection process, we want to make sure that this second project uses the same name for its document class, as it was done first.

At this moment, we have the code for our second view, but it is not associated with anything else, so the created view will not be visible. To make it visible, we must include its title in CMainframe.cpp (or any other name that it has in your target project). Then, back to OnCreateClient and replace the above code with the following:

 CRect rect; GetClientRect(&rect); BOOL ret = m_wndSplitter.CreateStatic(this, 2, 1); // 2 rows, 1 column of views // row 0, column 0 will be the "OriginalView". The initial split will be // in half -- ie, each pane will be half the height of the frame client // m_wndSplitter.CreateView(0, 0, RUNTIME_CLASS(OriginalView), CSize(1, rect.Height()/2), pContext); m_wndSplitter.CreateView(1, 0, RUNTIME_CLASS(ListBasedView), CSize(1, rect.Height()/2), pContext); 

At the moment, I have created a horizontal split with “OriginalView” in the upper panel and “ListBaseView” in the lower panel, but (I think), it should be pretty obvious what changes to reorder the views.

From there, of course, you will have to write code in each view in order to do what it should do, but since each of them is still a separate, normal view, each of them is quite independent, so the development seems to be normal. The only significant difference is that you must follow the invalidation rules of your document, and (especially if one of the road views is for updating), you may want to use hints to indicate which part of the data was invalidated so that you can write each point The view updates only what is needed, and not just redraws all its data every time.

+2
source

Maybe this article, Several Views Using SDI is what you need.

+1
source

Source: https://habr.com/ru/post/1347130/


All Articles