class CGXTabWnd: public CWnd
The CGXTabWnd classprovides the functionality to simply switch between several views in a frame window. The CGXTabWnd class displays a tab-beam control on the bottom-left side of the frame window. The functionality of the CGXTabWnd class is like the functionality of a workbook in MS Excel.
CGXTabWnd canbe used either in a document frame window (CFrameWnd) or in a dialog template.
CGXTabWnd is mainly based on the code of the CSplitterWnd class. Embedding a CGXTabWnd window in a frame window is similar to embedding a splitter window in a frame window.
Using CGXTabWnd is simple.
1. Embedding a CGXTabWnd window in a document frame window
If you want to use the workbook window in an MDI frame window, you must derive a class from CMDIChildWnd. You have to embed a CGXTabWnd object in the derived class. Furthermore, you have to override OnCreateClient. In OnCreateClient, you must initialize the CGXTabWnd object and create the views.
BOOL CScrltabsMDIChildWnd::OnCreateClient(LPCREATESTRUCT /*lpcs*/, CCreateContext* pContext)
{
VERIFY(m_wndTab.Create(this, "Table 1", pContext));
m_wndTab.CreateView(RUNTIME_CLASS(CEditView), "Edit", pContext);
m_wndTab.CreateView(RUNTIME_CLASS(CResultView), "Result", pContext);
return TRUE;
}
In your view class, you have to consider that the scroll bars do not belong to your view class. They are child windows of the CGXTabWnd window. You have to override GetScrollBarCtrl in your view class and return a pointer to the corresponding scrollbar object. The sample program contains the necessary source code for this method.
If you want to know whether your view is being activated or deactivated, you can override OnActivateView.
2. Embedding a CGXTabWnd window in a dialog template
The class can be used directly in Visual Studio as user control.
In InitInstance you have to register the window class of the CGXTabWnd window by calling RegisterClass. In ExitInstance, you have to unregister the window class by calling UnregisterClass.
In Visual Studio, you can drag the user control icon into the dialog template. Next, you have to set the user control properties: any ID, Class: CGXTabWnd, Style: 0x50810000.
In your dialog class, you have to insert a function to get a pointer to the CGXTabWnd object.
CGXTabWnd& GetTabWnd()
{ return *((CGXTabWnd *) GetDlgItem(IDC_TABWND)); }
Furthermore, you have to embed your window objects:
CEdit edit1, edit2, edit3;
Next, you must override OnInitDialog to initialize the CGXTabWnd object with its sheets.
BOOL CAboutDlg::OnInitDialog()
{
CDialog::OnInitDialog();
edit1.Create(ES_MULTILINE|ES_WANTRETURN, CRect(0,0,1,1), &GetTabWnd(), GetTabWnd().GetNextID());
edit2.Create(ES_MULTILINE|ES_WANTRETURN, CRect(0,0,1,1), &GetTabWnd(), GetTabWnd().GetNextID());
edit3.Create(ES_MULTILINE|ES_WANTRETURN, CRect(0,0,1,1), &GetTabWnd(), GetTabWnd().GetNextID());
GetTabWnd().AttachWnd(&edit1, "Edit 1");
GetTabWnd().AttachWnd(&edit2, "Edit 2");
GetTabWnd().AttachWnd(&edit3, "Edit 3");
GetTabWnd().GetBeam().DisplayScrollBtns(FALSE); // no scroll buttons
GetTabWnd().SetFocus();
return FALSE; // return TRUE unless you set the focus to a control
}
3. User defined messages sent to the sheet
The workbook window sends several messages to the associated sheets:
- WM_GX_INITTAB is sent from AttachWnd with the zero-based index of the tab in wParam to the associated sheet. This message is sent after inserting a register into the tab-beam control. The sheet can change the name or the tab width, or can do any other operations. The WM_GX_INITTAB message is not sent to views. Views can be initialized in OnInitialUpdate.
- WM_GX_NEEDCHANGETAB is sent with the zero-based index of the currently selected tab in wParam to the associated sheet, when the user has double-clicked on tab. If you want to prevent editing the sheet name, you have to return FALSE. If you return TRUE, editing the sheet name is possible.
- WM_GX_CHANGEDTAB is sent with the zero-based index of the currently selected tab in wParam to the associated sheet, when the user has changed a tab name. The message is sent after changing the tab name. The purpose of the message is to allow the view to update the sheet name in the document and notify other views of the change.
Each embedded window or view obtains a unique ID. The first window obtains the ID AFX_IDW_PANE_FIRST. Subsequent windows get continuous IDs (max. 256). The scrollbars have the IDs AFX_IDW_HSCROLL_FIRST and AFX_IDW_VSCROLL_FIRST.
If you need access to tab information, such as name and width, you can use the GetBeam method. By calling GetBeam().FindTab(pWnd), you can look up the zero-based tab index for an embedded view.
#include <gxall.h>
Example
In your view class, you have to consider that the scroll bars do not belong to your view class. They are child windows of the CGXTabWnd window. You have to override GetScrollBarCtrl in your view class and return a pointer to the corresponding scrollbar object.
// header file
class CGXView : public CView
{
// Support for tabwnds
public:
static CGXTabWnd* GetParentTabWnd(const CWnd* pWnd, BOOL bAnyState);
CScrollBar* GetScrollBarCtrl(int nBar) const;
...
}
// Implementation
// CView overridable member functions
CGXTabWnd* CGXView::GetParentTabWnd(const CWnd* pWnd, BOOL bAnyState)
{
CGXTabWnd* pTabWnd = (CGXTabWnd*)pWnd->GetParent();
if (!pTabWnd->IsKindOf(RUNTIME_CLASS(CGXTabWnd)))
return NULL; // not a tabwnd
if (!bAnyState)
{
// ignore tabwnds in minimized (iconic) windows
while ((pWnd = pWnd->GetParent()) != NULL)
if (pWnd->IsIconic())
return NULL;
}
return pTabWnd;
}
CScrollBar* CGXView::GetScrollBarCtrl(int nBar) const
{
ASSERT(nBar == SB_HORZ || nBar == SB_VERT);
if (GetStyle() & ((nBar == SB_HORZ) ? WS_HSCROLL : WS_VSCROLL))
{
// it has a regular windows style scrollbar (no control)
return NULL;
}
CWnd* pParent = GetParentTabWnd(this, TRUE);
if (pParent == NULL)
return CView::GetScrollBarCtrl(nBar); // checks for splitterwnd
// appropriate PANE id - look for sibling scrollbar
UINT nIDScroll;
if (nBar == SB_HORZ)
nIDScroll = AFX_IDW_HSCROLL_FIRST;
else
nIDScroll = AFX_IDW_VSCROLL_FIRST;
// return shared scroll bars that are immediate children of tabwnd
return (CScrollBar*)pParent->GetDlgItem(nIDScroll);
}