65.9K
CodeProject is changing. Read more.
Home

Folder Tab Control for Windows MFC (like MS Excel)

starIconstarIconstarIconstarIconstarIcon

5.00/5 (10 votes)

Oct 6, 2003

1 min read

viewsIcon

220182

downloadIcon

4944

Folder Tab control for Windows MFC (like MS Excel).

Sample Image - foldertabcontrol.jpg

Introduction

This is a folder tab window control for MFC. It looks and acts very much like the folder tab control for MS Excel, except it does not allow re-ordering of the folder tabs. It has a first button for the first tab, a next button for the next tab, a last button for the last tab and a previous button for the previous tab. You can also rename the folder tabs and delete/add new tabs interactively.

Paul DiLascia at MSDN magazine originally wrote this code in 3 separate issues of MSDN ( the last article was in the October 2002 issue). I just added the first and last buttons and the tab renaming capability.

Using the code

Paul wrote a FolderFrame.cpp class for handling the view of this class automatically. However, my view is a diagramming toolkit with zoom and pan that requires a lot of view specific code, so I do not use his FolderFrame class.

To include this control in my app, I just added it to my View class:

#include "ftab.h"
CFolderTabCtrl FolderTabs;

Then I created it in my OnCreate method:

          // create the folder tabs window
     CFolderTabCtrl& ftc = FolderTabs;
     VERIFY (ftc.Create (WS_CHILD|WS_VISIBLE, rc, this, 1, FTS_BUTTONS));

Then I draw it in my OnDraw method along with my horizontal scrollbar:

      // get the sizes of the client area and redraw the folder 

      // tabs and the scrollbars - must do this as we might be 

      // redrawing because of a change in number of folder tabs

   RECT rect;

   GetClientRect (&rect);

   int newHeight = rect.bottom;

   int newWidth = rect.right;

      // reposition the folder tabs window (calc size and limit first)

   int folderTabWidth = FolderTabs.GetDesiredWidth ();

   int folderTabLimit = (newWidth * 4) / 5;

   if (folderTabWidth > folderTabLimit) folderTabWidth = folderTabLimit;

   FolderTabs.MoveWindow (0, newHeight - GetSystemMetrics (SM_CYHSCROLL),
             folderTabWidth, GetSystemMetrics (SM_CYHSCROLL), TRUE);

   // reposition and redraw the horizontal scroll bar

   HorzScrollBar.MoveWindow (folderTabWidth, 
             newHeight - GetSystemMetrics (SM_CYHSCROLL),
             newWidth - folderTabWidth - GetSystemMetrics (SM_CXVSCROLL), 
             GetSystemMetrics (SM_CYHSCROLL), TRUE);

   SCROLLINFO si;

   ZeroMemory (&si, sizeof (SCROLLINFO));

   si.cbSize = sizeof (SCROLLINFO);

   si.fMask = SIF_RANGE | SIF_POS | SIF_PAGE;

   si.nMin = 0;

   si.nMax = giPaperWdDP;

   si.nPos = gisFlsHorzOffset;

   si.nPage = gisFlsHorzInc;

   HorzScrollBar.SetScrollInfo (&si, TRUE);

I added several message map items in my View class for handling the folder messages:

   ON_NOTIFY(FTN_TABCHANGED, 1, OnChangedTab)
   ON_NOTIFY(FTN_EDITSHEETS, 1, OnEditSheets)
   ON_NOTIFY(FTN_TABNAMECHANGED, 1, OnChangedTabName)
   ON_NOTIFY(FTN_ADDSHEET, 1, OnAddSheet)
   ON_NOTIFY(FTN_DELETESHEET, 1, OnDeleteSheet)

My View class also has the methods for handling messages from the folder tab control:

//////////////////
// Changed tab
//

void CFlsView::OnChangedTab(NMHDR* nmtab, LRESULT* pRes)
{
   NMFOLDERTAB& nmft = *(NMFOLDERTAB*)nmtab;
   giCurrentLayer = nmft.iItem;   //  your new tab number in the view
   Invalidate ();
}

//////////////////
// right mouse click on sheet tabs and select properties
//

void CFlsView::OnEditSheets(NMHDR* nmtab, LRESULT* pRes)
{
   //  put up your properties dialog now
}

//////////////////
// Changed tab name
//

void CFlsView::OnChangedTabName(NMHDR* nmtab, LRESULT* pRes)
{
   NMFOLDERTAB& nmft = *(NMFOLDERTAB*)nmtab;
   int sheet = nmft.iItem;
   giCurrentLayer = sheet;
   strncpy (LayerInfo [sheet].Name, nmft.lpText, LYR_NAMELEN);
}

//////////////////
// add page
//

void CFlsView::OnAddSheet(NMHDR* nmtab, LRESULT* pRes)
{

   NMFOLDERTAB& nmft = *(NMFOLDERTAB*)nmtab;
   int sheet = nmft.iItem;

   // add new sheet to the view
   FolderTabs.AddItem (LayerInfo [newSheet].Name);

   giCurrentLayer = newSheet;
   FolderTabs.SelectItem (giCurrentLayer);
   Invalidate ();

}

//////////////////
// Delete page
//

void CFlsView::OnDeleteSheet(NMHDR* nmtab, LRESULT* pRes)
{

   NMFOLDERTAB& nmft = *(NMFOLDERTAB*)nmtab;

   int sheet = nmft.iItem;

   if (0 == sheet)
   {
      CString text = "You cannot delete ";
      text += LayerInfo [sheet].Name;
      text += ".";
      int result = MessageBox (text, "Your App name", MB_OK);
   }
   else
   {

      DeleteLayer (sheet);
      // fix the view
      FolderTabs.RemoveItem (sheet);
      // if deleting the current sheet then reset the current sheet to 0
      if (sheet == giCurrentLayer)
      giCurrentLayer = 0;
      Invalidate ();
   }
}