Tabbed Views
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.
Date Last Updated: April 3, 1999

Comments
add/del & scroll function?
Posted by ahgu on 05/10/2006 11:22pmCan you add delete/new control to add/delete tabs? Also cursor to move if too many?
ReplyShortcut
Posted by Legacy on 11/16/2002 12:00amOriginally posted by: Jag
How add shortcut key for the tab?
And how to set tab order?
TIA
Jag
Reply
Cannot get client area size in OnInitUpdate()
Posted by Legacy on 07/29/2002 12:00amOriginally posted by: YI Ren
I have a SDI application, after adding the tabs, in the view's OnInitUpdate(), GetClientRect() returns 0 size of the view. I really need to know the size of the cient area, so I can resize it to 640x480. Any ideas why the ckient area has a size of zero ?
ReplyYes it works on my SDI application
Posted by Legacy on 05/29/2002 12:00amOriginally posted by: Guillermo Simanavicius
Yes, it works on my SDI application, please take a look on my sample at http://sinopsis.net/cpp/TabViewPPSample.zip
ReplyGuillermo
No one above could solved the print preview problem
Posted by Legacy on 05/22/2002 12:00amOriginally posted by: Kivanc Oner & Ali Yazgan
The techniques that both Marc Allaire and Guillermo Simanavicius are not capable of solving the print preview problem. Or we could not use the new codes efficiently. If anyone knows how to print preview from a CListView based SDI application please contact us...
ReplySheetal's exclusive page
Posted by Legacy on 04/10/2002 12:00amOriginally posted by: Sheetal
ReplyPrint Preview bug fix
Posted by Legacy on 03/22/2002 12:00amOriginally posted by: Marc Allaire
I investigated a little in the print preview bug.
It gives an assertion in the file winfrm.cpp, line 1842
Looking at that i see it tries to get the handle of
the control/window that has AFX_IDW_PANE_FIRST as its ID.
This should be the main pane, that print preview hides
before displaying the preview.
All there is to do to fix the problem is create the
ReplyCTabWnd window with AFX_IDW_PANE_FIRST for its ID
and print preview works.
Print Preview Crashes
Posted by Legacy on 04/22/1999 12:00amOriginally posted by: Jose Luis Flores
ReplyWhen I try to make a print preview the program crashes but when I try to print I have no problem, so ???? I have spent time looking for the error but ... without luck !
Problem with CRichEditView
Posted by Legacy on 02/19/1999 12:00amOriginally posted by: Emil Dimitrov
ReplyUsing it with splitter window
Posted by Legacy on 11/06/1998 12:00amOriginally posted by: Rochmad Setyadi
Reply