A splitter window holds two or more views of a document inside of it. There are two kinds of splitter windows , the dynamic splitter window and the static splitter window.
The author designed the Pop Framework so you can build both. In the Adding a Static Splitter section below we show how to change from one build to the other. Our default build uses dynamic splitter, which you can activate with Window Split . In understanding the role of splitter windows we need to understand their place in the window tree. Ordinarily a CView is the immediate window child of its frame. In the case of MDI, which is what we're focusing on, the frame is a ChildFrame object (which is an instance of the CMDIChildWnd class). In the case of SDI, the frame would be a MainFrame object which is an instance of the CFrameWnd class. But in any case, the usual situation is that your view is right inside the frame, in terms of the windows tree. When we add a splitter window, it gets in between the frame and view. Here's a picture showing the two kinds of window trees.
Let's describe how to add either kind of splitter. 'Dynamic' sounds more exciting and complicated than 'static,' but in some ways the static splitter windows are more powerful, and they're slightly harder to program. Let's explain the easier case first. Adding a dynamic splitter
BOOL CChildFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext) { /* When adding a splitter, be sure to comment out the base class code. */ // CMDIChildWnd::OnCreateClient(lpcs, pContext); /* We pass the CSplitterWnd::Create call the "this" pointer, the max number of rows (1 or 2), the max number of columns (1 or 2), and an (x,y) size at which you want a pane to just disappear, the pContext variable, and a flags variable. */ return _cSplitterWnd.Create(this, 1, 2, CSize(20, 20), pContext, WS_CHILD WS_VISIBLE SPLS_DYNAMIC_SPLIT); /* The default includes WS_HSCROLL WS_VSCROLL in the sixth argument, but I don't want scrollbars here. */ } And that's it! If you rebuild now, you've got a working dynamic splitter window! If you use the Window Split selection, you can split any of your views in two. But there is one more consideration. It may be that you want the two panes of the split view to automatically be different. To do this, you could put some code like the following into your game's override of initializeView(CPopView* pview) , so as to make the views in the two panes be different. When the window is not split, your default behavior will be that of the 'left pane.' CSplitterWnd* csplitter = (CSplitterWnd*)(pview->GetParent()); if (pview == csplitter->GetPane(0,0) ) //we're the left, main view. { //Change the view settings the values you want in the left pane } else //we're the right, subsidiary view. { /* Change the view settings to the values you want in the right pane. */ } You might also want to override the cGame child's initializeCritterViewer(cCritterViewer *pviewer) with a similar kind of switch on pviewer->_pownerview . Adding a static splitterIf you use a static splitter window, you have the ability to make your window keep a fixed layout no matter what size it is. The idea is to allocate some fixed proportion, like 0.75 of the window for the left pane and give the rest to the right pane. Of course the user can still move the splitter bar back and forth, but whenever we resize the frame window we'll go back to our standard proportions . Look for the following block of code at the top of the Childfrm.h file. Comment STATIC_SPLITTER in, set the Build Set Active Configuration . . . to select the Release option and rebuild. /* Comment STATIC_SPLITTER out to have a dynamic (user selectable) splitter window rather than a static (automatically present) splitter window. If we have STATIC_SPLITTER, then we use LEFT_PANE_PERCENT to specify how much of the width of the child frame window is devoted to the left pane. The PERCENT macro is defined in stdafx.h to convert the 0 to 100 range to 0.0 to 1.0. */ //#define STATIC_SPLITTER #define LEFT_PANE_PERCENT PERCENT(50) Run the new *.exe and notice that when you resize the window, the left splitter pane always takes up 50 percent of the screen. Change the LEFT_PANE_PERCENT number to 75 and build again. What makes this a little tricky is that a static splitter window is not fully initialized until you've both called CSplitterWnd::CreateStatic and repeatedly called CSplitterWnd::CreateView to put valid CView objects inside its panes. What with all the things the MDI framework does to initialize itself, you will hit the ChildFrame::OnSize method three or four times before you've managed to finish executing the ChildFrame::OnCreateClient code that initializes the _cSplitterWnd . So you need a BOOL _splittercreated field to keep you from trying to set the sizes of the _cSplitterWnd 's panes before they're fully ready. If you look in the Pop ChildFrm code, you'll find the following two things.
As in the case of the dynamic splitter, you may want to change your CPopView::OnCreate to initialize the views differently according to which pane of the splitter window they appear in. Finally, if you want to change the behavior of the relative sizes of the panes when you resize the window, you can tweak the CChildFrame::OnSize method a bit further. |