tab control for multiple views

I have an SDI application that has multiple views. I create all of the views when the document is opened, and then show only the one that is selected, hiding the others.

What I would like is to use a CTabCtrl to switch between the views. But I don't know how to (or where to) attach the control.

Any help would be greatly appreciated
kbbAsked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

RONSLOWCommented:
I have at least four sets of saomple code showing how to do this - each uses a slightly different method (eg. its own tab class, using CTabCtrl, using PropertySheets etc).

I can send these to you if you give me your eMail address - mine is Roger_Onslow@compsys.com.au

NOTE: There are lots of ways of acheiving this - it is best if your look at several example and work out the best solution for your particular application.

0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
RONSLOWCommented:
PS: Here is one of the smaller sets of sample code... I'll eMail it to you with the others I have when you send me your eMail address.

// TabView.h : interface of the CTabView class
//
/////////////////////////////////////////////////////////////////////////////

#ifndef _TABVIEW_H
#define _TABVIEW_H
class CTabView : public CCtrlView
{
      DECLARE_DYNCREATE(CTabView)
protected: // create from serialization only
      CTabView();

// Attributes
public:
      CTabCtrl& GetTabCtrl() const;
      CDocument* GetDocument();      // Change this to more generic doc
      CObArray m_VwList;                        // List of pointers to tab child views
      CImageList m_ctlImage;                  // Keep Image List on the stack?
      int m_nTabCount;                        // How many Tabs are there?
      int m_nActiveTab;                        // Zero based number of selected tab
      int m_nLastActiveTab;                  // Zero based number of last selected tab
      BOOL m_bCreated;                        // Flag - True after 'OnInitialUpdate'
      BOOL m_bSizing;                              // Flag - True after 'OnSize'
      CFont* m_pFont;                              // Smaller Default font
      CRect m_rOldRect;
      int m_nMarginPixels;                        // how big is the margin?

// Overridables
protected:
      virtual void RemoveImageList(int nImageList);
      virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);
      virtual BOOL AddTab(int nTab, int nImage, LPSTR csCaption);
   virtual BOOL AddTab(int nTab, int nImage, UINT nCaptionID);
   virtual BOOL RemoveTab(int nTab);
      virtual BOOL RemoveAllTabs();
      virtual int GetSelectedTab();
      virtual int GetTabCount();
      virtual void SetTabCount(int nCount);
      virtual void SetImageList(int nImageListID);
      virtual BOOL GetChildRect(CRect& rVwRect);
      // Operations
public:

// Overrides
      // ClassWizard generated virtual function overrides
      //{{AFX_VIRTUAL(CTabView)
      public:
      virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
      virtual BOOL DestroyWindow();
      virtual BOOL OnChildNotify(UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pLResult);
      virtual void OnInitialUpdate();
      protected:
      virtual BOOL OnPreparePrinting(CPrintInfo* pInfo);
      virtual void OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo);
      virtual void OnEndPrinting(CDC* pDC, CPrintInfo* pInfo);
      virtual void OnDraw(CDC* pDC);
      //}}AFX_VIRTUAL

// Implementation
public:
      virtual ~CTabView();
#ifdef _DEBUG
      virtual void AssertValid() const;
      virtual void Dump(CDumpContext& dc) const;
#endif

protected:

// Generated message map functions
protected:
      //{{AFX_MSG(CTabView)
      afx_msg BOOL OnEraseBkgnd(CDC* pDC);
      afx_msg void OnSize(UINT nType, int cx, int cy);
      afx_msg void OnSysColorChange();
      //}}AFX_MSG
      DECLARE_MESSAGE_MAP()
};

#ifndef _DEBUG  // debug version in TabView.cpp
inline CDocument* CTabView::GetDocument()
   { return (CDocument*)m_pDocument; }
#endif

/////////////////////////////////////////////////////////////////////////////
#endif
=========================

// TabView.cpp : implementation of the CTabView class
//

#include "stdafx.h"
#include "ownsetup.h"

#include "TabView.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CTabView

IMPLEMENT_DYNCREATE(CTabView, CCtrlView)

BEGIN_MESSAGE_MAP(CTabView, CCtrlView)
      //{{AFX_MSG_MAP(CTabView)
      ON_WM_ERASEBKGND()
      ON_WM_SIZE()
      ON_WM_SYSCOLORCHANGE()
      //}}AFX_MSG_MAP
      // Standard printing commands
      ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint)
      ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint)
      ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CTabView construction/destruction

CTabView::CTabView() : CCtrlView(WC_TABCONTROL,AFX_WS_DEFAULT_VIEW | TCS_FOCUSNEVER)
{
      m_nTabCount = 0;
      m_nActiveTab = -1;
      m_nLastActiveTab = -1;
      m_bCreated = FALSE;
      m_bSizing = FALSE;
      m_nMarginPixels = 0;
   m_pFont = NULL;
}

CTabView::~CTabView()
{

   if (m_pFont)
      delete m_pFont;
}

BOOL CTabView::PreCreateWindow(CREATESTRUCT& cs)
{
      return CCtrlView::PreCreateWindow(cs);
}


/////////////////////////////////////////////////////////////////////////////
// CTabView printing

BOOL CTabView::OnPreparePrinting(CPrintInfo* pInfo)
{
      // default preparation
      return DoPreparePrinting(pInfo);
}

void CTabView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
      // TODO: add extra initialization before printing
}

void CTabView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
      // TODO: add cleanup after printing
}

/////////////////////////////////////////////////////////////////////////////
// CTabView diagnostics

#ifdef _DEBUG
void CTabView::AssertValid() const
{
      CCtrlView::AssertValid();
}

void CTabView::Dump(CDumpContext& dc) const
{
      CCtrlView::Dump(dc);
}

CDocument* CTabView::GetDocument() // non-debug version is inline
{
      ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CDocument)));
      return (CDocument*)m_pDocument;
}
#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CTabView message handlers
CTabCtrl& CTabView::GetTabCtrl() const
{
      return *(CTabCtrl*)this;
}

BOOL CTabView::GetChildRect(CRect& rVwRect)
{
      CTabCtrl& ctlTab = (CTabCtrl&) GetTabCtrl();
      CRect rTabRect;
      CRect rParentRect;
      CPoint pntTabBottom;
      
      GetClientRect(rParentRect);
      BOOL bGotItemRect = ctlTab.GetItemRect(0,rTabRect);
      pntTabBottom = rTabRect.BottomRight();
      pntTabBottom.x = 0;
      CPoint pntPrntBottomRight = rParentRect.BottomRight();
      CRect rTempViewRect(pntTabBottom,pntPrntBottomRight);
      rTempViewRect.DeflateRect(m_nMarginPixels, m_nMarginPixels);
      rVwRect = rTempViewRect;
      return TRUE;
}

BOOL CTabView::AddTab(int nTab, int nImage, UINT nCaptionID)
{
   CString Caption;
   Caption.LoadString(nCaptionID);
   return AddTab(nTab, nImage, Caption.GetBuffer(1));
}

BOOL CTabView::AddTab(int nTab, int nImage, LPSTR csCaption)
{
      CTabCtrl& ctlTab = (CTabCtrl&) GetTabCtrl();
      TC_ITEM thisItem;

      if (csCaption != NULL)
            thisItem.mask = TCIF_TEXT|TCIF_IMAGE;
      else
            thisItem.mask = TCIF_IMAGE;

      thisItem.pszText = csCaption;
      thisItem.iImage = nImage;

      return ctlTab.InsertItem(nTab,&thisItem);
}

BOOL CTabView::RemoveTab(int nTab)
{
      CTabCtrl& ctlTab = (CTabCtrl&) GetTabCtrl();
      return ctlTab.DeleteItem(nTab);
}

BOOL CTabView::RemoveAllTabs()
{
      CTabCtrl& ctlTab = (CTabCtrl&) GetTabCtrl();
      return ctlTab.DeleteAllItems( );
}

int CTabView::GetSelectedTab()
{
      CTabCtrl& ctlTab = (CTabCtrl&) GetTabCtrl();
      return ctlTab.GetCurSel();
}

int CTabView::GetTabCount()
{
      CTabCtrl& ctlTab = (CTabCtrl&) GetTabCtrl();
      return ctlTab.GetItemCount();
}

void CTabView::SetTabCount(int nCount)
{
      CTabCtrl& ctlTab = (CTabCtrl&) GetTabCtrl();
      m_nTabCount = GetTabCount();
}

void CTabView::SetImageList(int nImageListID)
{
      CTabCtrl& ctlTab = (CTabCtrl&) GetTabCtrl();
      m_ctlImage.Create(nImageListID,16,0,RGB(255,255,255));
      m_ctlImage.SetBkColor(GetSysColor(COLOR_3DFACE));

      ctlTab.SetImageList(&m_ctlImage);
}


void CTabView::RemoveImageList(int nImageList)
{
      HIMAGELIST h = (HIMAGELIST)SendMessage(TCM_GETIMAGELIST,(WPARAM)nImageList);
      if(CImageList::FromHandlePermanent(h) != NULL)
      {
            SendMessage(TCM_SETIMAGELIST, (WPARAM)nImageList, NULL);
      }
}


BOOL CTabView::DestroyWindow()
{
      RemoveImageList(0);                        //Only One Image list is possible

      return CCtrlView::DestroyWindow();
}

void CTabView::DrawItem(LPDRAWITEMSTRUCT)
{
      ASSERT (FALSE);
}

BOOL CTabView::OnChildNotify(UINT message, WPARAM wParam, LPARAM lParam,
      LRESULT* pResult)
{
      
      if( message == WM_NOTIFY)
      {
            NMHDR* pnmh = (NMHDR *) lParam;
            int nMessage = pnmh->code;

            if (nMessage == TCN_SELCHANGE)
            {
                  TRACE("Tab Selection Changed!");
                  int nSel = GetTabCtrl().GetCurSel( );
                  if (m_VwList.GetSize() == 0)
                  {
                        TRACE("ERROR: CTabView::OnChildNotify nSel = %d, m_vwViewList size = %d\n",nSel, m_VwList.GetSize());
                        if (message != WM_DRAWITEM)
                              return CCtrlView::OnChildNotify(message, wParam, lParam, pResult);
                  
                        ASSERT(pResult == NULL);
                        UNUSED(pResult);

                        DrawItem((LPDRAWITEMSTRUCT)lParam);
                  }

                  if (nSel != m_nActiveTab)
                  {
                        BOOL bShowResult;
                        int nOldView = m_nActiveTab;
                        m_nLastActiveTab = nOldView;
                        m_nActiveTab = nSel;
                        
                        LockWindowUpdate( );

                        bShowResult = ((CWnd*)(m_VwList[nOldView]))->ShowWindow(SW_HIDE);
                        bShowResult = ((CWnd*)(m_VwList[nSel]))->ShowWindow(SW_SHOW);
                        
                        CRect rViewRect;
                        GetChildRect(rViewRect);
                        UnlockWindowUpdate();
                        RedrawWindow( rViewRect, NULL, RDW_INVALIDATE | RDW_UPDATENOW | RDW_NOERASE );
                  }
            }
      }
      if (message != WM_DRAWITEM)
            return CCtrlView::OnChildNotify(message, wParam, lParam, pResult);

      ASSERT(pResult == NULL);
      UNUSED(pResult);

      DrawItem((LPDRAWITEMSTRUCT)lParam);
      return TRUE;
}

void CTabView::OnInitialUpdate()
{
      m_bCreated = FALSE;
      CCtrlView::OnInitialUpdate();

   // Create the font to use for the tabs
      CTabCtrl& ctlTab = (CTabCtrl&) GetTabCtrl();

      m_pFont = new CFont;
      m_pFont->CreateFont(14,0,0,0,500,0,0,0,
            ANSI_CHARSET,OUT_TT_PRECIS,
            CLIP_TT_ALWAYS,DEFAULT_QUALITY,
            VARIABLE_PITCH|FF_SWISS,
            "arial");

      ctlTab.SetFont( m_pFont );
      m_bCreated = TRUE;
}

void CTabView::OnDraw(CDC* pDC)
{
      // TODO: Add your specialized code here and/or call the base class
      CDocument* pDoc = GetDocument();
      
}

BOOL CTabView::OnEraseBkgnd(CDC* pDC)
{
      if (m_VwList.GetSize() > 0)
      {
            CTabCtrl& ctlTab = (CTabCtrl&) GetTabCtrl();
            
            // Get rectangle enclosing the whole tab control
            CRect rCntrlRect;
            GetClientRect(rCntrlRect);
            
            // Account for clipping where part of the window is offscreen
            CRect rClipRect;
            pDC->GetClipBox(rClipRect);
            
            // Get the intersection of control rect and the clip rect
            rCntrlRect &= rClipRect;

            // Get the intersection of the clip rect and the contained view rect
            CRect rViewRect;
            GetChildRect(rViewRect);
            rViewRect &= rClipRect;
            
            CRgn rgnUpdateRgn;
            CRgn rgnTempRgn;
            
            // merge all to a region to paint...
            rgnUpdateRgn.CreateRectRgn(0,0,0,0);
            rgnTempRgn.CreateRectRgn( 0,0,0,0 );

            rgnUpdateRgn.SetRectRgn(rCntrlRect);
            rgnTempRgn.SetRectRgn(rViewRect);

            rgnUpdateRgn.CombineRgn( &rgnUpdateRgn, &rgnTempRgn, RGN_DIFF );
            rgnTempRgn.DeleteObject();
            
            COLORREF clr3DFace = (COLORREF) ::GetSysColor(COLOR_3DFACE);
            CBrush brshBkBrush(clr3DFace);
            
            // Paint it and delete the region...
            pDC->FillRgn(&rgnUpdateRgn, &brshBkBrush);
            rgnUpdateRgn.DeleteObject();

            return TRUE;
      }
      else
            return CCtrlView::OnEraseBkgnd(pDC);
}

void CTabView::OnSize(UINT nType, int cx, int cy)
{
      CCtrlView::OnSize(nType, cx, cy);
      
      // TODO: Add your message handler code here

      TRACE("CTabView::OnSize called\n");
      int nTabCount = GetTabCount();

      if ((nTabCount != 0) & (m_bCreated == TRUE))
      {
            CRect rViewRect(0,0,0,0);
            BOOL bResult = GetChildRect(rViewRect);

            if (rViewRect.Width() == 0)
                  m_rOldRect = CRect(0,0,0,0);
            else
            {
                  for (int nCounter = 0; nCounter < nTabCount; nCounter++)
            ((CWnd*) (m_VwList[nCounter]))->MoveWindow(rViewRect);
                  UpdateWindow();
                  m_rOldRect = rViewRect;
            }
            m_bSizing = TRUE;
      }
      
}

void CTabView::OnSysColorChange()
{
      CCtrlView::OnSysColorChange();
      m_ctlImage.SetBkColor(GetSysColor(COLOR_3DFACE));
}

0
RONSLOWCommented:
Have you emailed me of given me your email address so I can send you more samples?

0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
System Programming

From novice to tech pro — start learning today.