WTL Splitters and Pane Containers

WTL Splitters and Panes Image

原文出自:http://www.codeproject.com/Articles/2414/WTL-Splitters-and-Pane-Containers

Introduction

This article describes the basic use of WTL's CSplitterWindowas an application window divider and CPaneContainer as a host forchild windows. The included demonstration project is 3-pane SDI applicationusing vertical and horizontal splitters. Each splitter pane holds a panecontainer and one of the pane containers holds an edit control.

Splitters

Splitters can be either vertical or horizontal and are used in popularmultipane applications such as Microsoft Outlook to divide the application'smain window into functional sections. The splitter window template is found inatlsplit.h. This header file offers two ready to use splitterimplementations. CSplitterWindow is a standard vertical splitterwhile CHorSplitterWindow provides a horizontal splitter.

3-pane Layout

A Microsoft Outlook style 3-pane layout requires a vertical splitter, whichdivides the screen into left and right segments, and a horizontal splitter,which divides the right segment of the vertical splitter into top and bottom.The main frame of the application is parent to the vertical splitter while thevertical splitter is parent to the horizontal. Basic setup coding, using them_vSplit and m_hzSplit member variables, is asfollows:

// client rect for vertical splitter
CRect rcVert;
GetClientRect(&rcVert);

// create the vertical splitter
m_vSplit.Create(m_hWnd, rcVert, NULL,
  WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN);

// client rect for horizontal splitter
CRect rcHorz;
GetClientRect(&rcHorz);

// create the horizontal splitter. Note that vSplit is parent of hzSplit
m_hzSplit.Create(m_vSplit.m_hWnd, rcHorz, NULL,
  WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN);

// add the horizontal splitter to the right pane (1) of vertical splitter
m_vSplit.SetSplitterPane(1, m_hzSplit);

In addition, several options were set for both splitters. The code snippetbelow shows how to set a minimum split size of 35 pixels. This limits how closeto the left or right edge of the main window the splitter can be moved. Also,the initial splitter position is set 85 pixels from the left and the "ghost bar"effect is enabled. In ghost bar mode, a dark gray bar is displayed while thesplitter is being dragged. In normal mode, the entire splitter and pane contentsare dragged.

// set the vertical splitter parameters
m_vSplit.m_cxyMin = 35; // minimum size
m_vSplit.SetSplitterPos(85); // from left
m_vSplit.m_bFullDrag = false; // ghost bar enabled

At this point, the framework of a 3-pane application is in place. The nextsection of this article describes how to add content to the splitters. Splitterpanes can contain controls, such as a treelist or listview, or a child window,such as a dialog or pane container. In our sample project we add a panecontainer to each section of the application, setting various options, andthen add an edit control to one of the pane containers.

Pane Containers

Pane Containers provide an area where child windows and controls can behosted. They also provide a header bar with a title and close button. A commonuse for pane containers is to provide helpful titles and a logical grouping ofrelated program elements. The CPaneContainer class is found in theatlctrlx.h header file.

Initializing a Pane Container

There are three basic steps needed to use a pane container. First, createthe container using the appropriate splitter handle as parent. Second, add thecontainer to the appropriate splitter section. Third, set the container title.These steps are shown in the code below. This code sets up the pane containerfor the left section of the vertical split.

// create the left container
m_lPane.Create(m_vSplit.m_hWnd);

// add container to left pane (0) of vertical splitter
m_vSplit.SetSplitterPane(0, m_lPane);

// set the left pane title
m_lPane.SetTitle("Left Pane");

If desired, the title can be set when the pane container is created bysupplying the title text or a resource ID for the title string as the secondparameter to the pane container create statement.

After the container is created and assigned to a splitter, you may setextended options. The extended options are PANECNT_NOCLOSEBUTTONand PANECNT_VERTICAL. The first option controls whether or not aClose button is displayed in the container header and the second controlswhether the header is layed out horizontally, at the top of the container, orvertically, on the left side of the container. Note that header titles are notdisplayed when the header is set to vertical orientation. Extended options areset as follows:

// remove the close button from the top container
m_tPane.SetPaneContainerExtendedStyle(PANECNT_NOCLOSEBUTTON);

Adding a Container Child

As mentioned earlier, a pane container can host a child window or a childcontrol, such as the edit control in the sample program. The steps for adding achild control to a pane container are:

  1. Create the control as usual
  2. Configure the control per your needs
  3. Add the control to the pane container

You would use similar steps to add any kind of window to the container. Thiscode shows how an edit control is added to the bottom pane container of thesample project:

// create and configure an edit control. Note that m_bPane is the parent
m_edit.Create(m_bPane.m_hWnd, rcDefault, NULL,
  WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, WS_EX_CLIENTEDGE);
m_edit.SetFont((HFONT)GetStockObject(DEFAULT_GUI_FONT), TRUE);
m_edit.SetWindowText(" Bottom Pane -- with vertical header and edit as child");

// assign the edit to the bottom container
m_bPane.SetClient(m_edit.m_hWnd);

Handling the Close Button

When a user click on the pane container's Close button (marked with an X),the button sends an ID_PANE_CLOSE notification. The sample projectcatches the notification in the main frame's message map and uses the followingroutine to process it:

LRESULT OnPaneClose(WORD, WORD, HWND hWndCtl, BOOL&)
{ // hide the container whose Close button was clicked
  ::ShowWindow(hWndCtl, SW_HIDE);

  // find the container's parent splitter
  HWND hWnd = ::GetParent(hWndCtl);
  CSplitterWindow* pWnd;
  pWnd = (CSplitterWindow*)::GetWindowLong(hWnd, GWL_ID);

  // take the container that was Closed out of the splitter
  int nCount = pWnd->m_nPanesCount;
  for(int nPane = 0; nPane < nCount; nPane++)
  { if (hWndCtl == pWnd->m_hWndPane[nPane])
    { pWnd->SetSinglePaneMode(nCount - nPane - 1);
      break; } }

  return 0; }

Use DestroyWindow(hWndCtl) instead of ShowWindowif you want to totally remove the container instead of just hiding it. You mayalso want to use SetSplitterPane(nPane, NULL) instead ofSetSinglePaneMode if you want to stay in multipane mode instead ofchanging to single pane mode.

In addition, you might want to replace an existing child window or controlwith another. Do so by creating it and adding it to the container after the oldone is removed. If you do implement that as a feature, you may also want tooverride the container's DrawButtonImage method to provide anappropriate button image.

Terms Of Use

The sample project available with this article is free. Use the code howeveryou wish.

THIS SOFTWARE IS DISTRIBUTED AS-IS, WITHOUT WARRANTIES OF ANY KIND.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

Ed Gadziemski
Founder KwikiVac
United States United States
Ed has over 40 years experience in computer technology and a bachelor's degree in Business Administration. He currently owns an online retail business and previously owned a software consulting firm. During his career, he has led software development departments and created software still in use in the communications and healthcare industries. Ed is a veteran of the United States Army. He lives in Arizona in the United States.
 
This material is copyright 2014 by Ed Gadziemski. Unauthorized use is strictly prohibited. All rights reserved.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值