Multiple Views Layout Without a Splitter

Introduction

Many times, I have stumbled across questions regarding using multiple views shown in one frame without a splitter window. Therefore, I decided to write a small application showing how that can be done.

The sample application uses a fairly unknown message: WM_SIZEPARENT declared in afxpriv.h. But first, see how MFC frame windows maintain the child windows' layout. The WM_SIZE handler implementation calls RecalcLayout. In turn, RecalcLayout calls RepositionBars. Do not let the function name full you; it actually should be called RepositionChildren because this is exactly what that function does. It enumerates all child windows and sends a message to resize all.

To enumerate all child windows, it calls GetNextWindow after retrieving top child—in other words, the child that is first in the Z order; so, the search starts with the first child window that is created and goes down to the last one. To resize windows, the function uses BeginDeferWindowPos, DeferWindowPos, and EndDeferWindowPos; they resize all children at the same time, thus reducing flickering. For each child window, RepositionBars sends the above-mentioned WM_SIZEPARENT message to allow each child to decide what area to occupy and add itself to a DeferWindowPos path.

There is one exception. The view with the magic AFX_IDW_PANE_FIRST ID is put aside until the end, and resized after all other children are already positioned, taking whatever real estate is left for it. By the way, the AFX_IDW_PANE_FIRST ID is used by the default implementation of the RecalcLayout. RecalcLayout can be overridden and other IDs can be designated as the special one.

How do other child windows know that certain areas of the parent's client have already been taken by other children? MFC is using its own structure to carry that information from the first child to the last one: AFX_SIZEPARENTPARAMS. MSDN is quite shy about documenting it. It has the following members:

  • HDWP hDWP
  • RECT rect
  • SIZE sizeTotal
  • BOOL bStretch
  • hDWP: A handle returned by BeginDeferWindowPos
  • rect: A rectangle that represents the parent's client area trimmed by other children

Basically, it is an area that is available for taking the following:

  • sizeTotal: Represents the size of the child window (width and height) after repositioning.
  • bStreech: Tells the window to stretch itself to take all available space. Can be ignored by non-toolbar windows.

How this structure is used is totally up to the implementation.

View windows should be created after all toolbars and the status bar are created (remember the Z order). The best place to do this is in the WM_CREATE message handler. A child window with AFX_IDW_PANE_FIRST can be created anytime.

How to Use the AFX_SIZEPARENTPARAMS Structure

When the frame window is created, it receives the WM_CREATE message. Before toolbars are created, the base class calls OnCreateClient where a view registered with the document template is created. After it returns, it is time to create control bars if desired. I have included a child toolbar and commented out a part of the code that creates a status bar. Uncomment it if you want to see status bar too.

After the control bars are done, I placed a call to CreatePanes to creates other views. To simplify, I added two views. This order assures that the WM_SIZEPARENT message will be sent in the proper order. This sample only illustrates how to use this message and the AFX_SIZEPARENTPARAMS structure. Each layout design will require a different approach; however, it is very similar to what is presented here.

After the control bars have decided what part of the client area of the frame window to take, the framework sends a WM_SIZEPARENT message to the first additional pane (CTitleFormView) that serves as a kind of title. The height of this window does not change and is calculated in the view's OnCreate handler. In sizing the message handler, the window takes half of the width of the available client area and sets its own heights; it uses a lpLayout structure to pass those values to the next window and sets the sizeTotal member of the structure to own rectangle size. After all calculations, the view calls AfxRepositionWindow that calls DeferWindowPos, adding the view's parameters to a defer path. If the handle to the defer window position is null, it only performs calculations without calling AfxRepositionWindow.

Now, a message is sent to a CDisplayView. It uses values from the lpLayout structure to position itself in the lower part of the right half of the client area and adjusts the rect member of the structure to show the leftover area that will be taken by the main view—AFX_IDW_PANE_FIRST. As a result of passing the document pointer when panes were created, all views share the same document object; therefore, UpdateAllViews can be called to update all panes. It happens upon the list view selection change. That is a reminder showing how the doc/view architecture works.

Conclusion

There is no additional class that could be included in other projects. This article serves as an example, showing how to use WM_SIZEPARENT message as well as explaining (documenting) the AFX_SIZEPARENTPARAMS structure.



About the Author

John Z. Czopowik VC++ MVP

Microsoft VC++ MVP

Downloads

Comments

  • There are no comments yet. Be the first to comment!

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Hybrid cloud platforms need to think in terms of sweet spots when it comes to application platform interface (API) integration. Cloud Velocity has taken a unique approach to tight integration with the API sweet spot; enough to support the agility of physical and virtual apps, including multi-tier environments and databases, while reducing capital and operating costs. Read this case study to learn how a global-level Fortune 1000 company was able to deploy an entire 6+ TB Oracle eCommerce stack in Amazon Web …

  • Java developers know that testing code changes can be a huge pain, and waiting for an application to redeploy after a code fix can take an eternity. Wouldn't it be great if you could see your code changes immediately, fine-tune, debug, explore and deploy code without waiting for ages? In this white paper, find out how that's possible with a Java plugin that drastically changes the way you develop, test and run Java applications. Discover the advantages of this plugin, and the changes you can expect to see …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds