dcsimg

Tabbed Views

WEBINAR:
On-Demand

Desktop-as-a-Service Designed for Any Cloud ? Nutanix Frame


This program is useful if you need multiple views of the same document but you only want one of them to be visible at once. It draws a number of tabs under the menu/toolbars that can be used to select the active view.

First we create a CWnd-derived class


class CTabWnd : public CWnd
{
 // Construction
 public:
  CTabWnd();
 
 // Generated message map functions
protected:
 //{{AFX_MSG(CTabWnd)
 afx_msg BOOL OnEraseBkgnd(CDC* pDC);
 afx_msg void OnPaint();
 //}}AFX_MSG
DECLARE_MESSAGE_MAP()
}
Then we add a Create function to initialize our control.

BOOL CTabWnd::Create(DWORD dwStyle, CWnd* pParentWnd, UINT nID)
{
 CRect rect, parent;
 ASSERT(pParentWnd);

 if (!CWnd::Create(NULL, "SealiteTabWnd", WS_CHILD|WS_VISIBLE, rect, pParentWnd, nID, NULL))
  return FALSE;

 m_dwStyle=dwStyle;
 return TRUE;
}
As you can see the window is created with an uninitialized rect. It will be resized as soon as it receives a WM_SIZEPARENT function. It will fill the entire client area and the views are creating using it as a parent. Because the control is created in the client area of the parent window it has to draw itself the client edge. For best results it is recommended that you remove the WS_EX_CLIENTEDGE style of the parent window.

Next, we add a linked list of views and a CreateView function to add views in it.

typedef struct
{
 CWnd *pWnd;
 char szLabel[32];
 int x_min, x_max;
}

CList <TABWND_MEMBER*,TABWND_MEMBER *> m_viewList;
BOOL CreateView(LPCTSTR lpszLabel, CRuntimeClass *pViewClass, CCreateContext *pContext);
In the CreateView function we instantiate the pViewClass using CRuntimeClass::CreateObject() and add the resulting CView to the list.

The created views have to be resized whenever the parent window resize, so we add a handler for WM_SIZEPARENT.


LRESULT CTabWnd::OnSizeParent(WPARAM, LPARAM lParam)
{
 PostMessage(WM_TABRESIZE);
 return 0;
}
To find out how much space is available for the client area after the control bars have allocated space for themselves we have to use the RepositionBars function with the CWnd::reposQuery parameter. Unfortunatly in a WM_SIZEPARENT handler RepositionBars does not return a valid rectangle because the message is used by the control bars to resize the client area. To walk around this we post a message and in its handler we can safely call this function.

The next thing to do is handle the WM_PAINT message to draw the selector and the WM_LBUTTONUP message to switch the views. The SetActiveView function is used to make sure that the window/command messages are routed to the active view. When the current tab is changed both the view thats going to be selected and the one thats going to be unselected are sent the WM_TABCHANGED message.

This is a rather complex subject and it is imposible to throughly cover it in a few pages. For more information you should go through the CTabWnd (you can download the project and source files by clicking the link at the beginning of this page) and CSplitterWnd.

Download demo project - 25 KB

Date Last Updated: April 3, 1999



This article was originally published on April 3rd, 1999

Most Popular Programming Stories

More for Developers

RSS Feeds

Thanks for your registration, follow us on our social networks to keep up-to-date