Click here to Skip to main content
15,881,455 members
Articles / Desktop Programming / WTL

Custom Tab Controls, Tabbed Frame and Tabbed MDI

Rate me:
Please Sign up or sign in to vote.
4.90/5 (144 votes)
13 Jul 200522 min read 1.6M   35.5K   395  
An extensible framework for creating customized tabs in ATL/WTL, with a VS.NET-like tab control implementation, tabbed frames, tabbed MDI, and more.
// History of TabbedMDI.h prior to codeproject article about it
//
// History (Date/Author/Description):
// ----------------------------------
//
// 2002/06/12: Daniel Bowen (DDB)
// - CTabbedMDIChildWindowImpl:
//   * Improve "Create" so that if the MDI child specifies "WS_MAXIMIZE"
//     as a style, the child starts out life maximized no matter if
//     any previously active child was maximized.  It also still
//     maximizes a new child if the currently active child is maximized
// - CMDITabOwner:
//   * Base class "CCoolTabOwnerImpl" is now "CCustomTabOwnerImpl"
//   * Instead of "m_bTabAreaOnTop" and "SetBoldSelectedTab", use the styles
//     CTCS_BOTTOM and CTCS_BOLDSELECTEDTAB (passed in CreateTabWindow call)
//   * Update "TCN_*" to "CTCN_*"
//   * No need to reflect notifications anymore
//   * Handle the new CTCN_CLOSE, and do the same thing as if
//     they had clicked the frame caption "close" button for the child.
//   * Don't reference CCoolTabItem directly, reference TTab::TItem
//     (which now is more likely to be CTabViewTabItem)
//   * Override new "SetTabAreaHeight" to update layout and invalidate
// - CTabbedMDIClient:
//   * Tab Area Height and its calculations are now managed by the tab owner
//
// 2002/05/13: Daniel Bowen (DDB)
// - Remove dependance on atlmisc.h types
//
// 2002/04/24: Daniel Bowen (DDB)
// - Rename:
//    UWM_MDICHILDTOOLTIPCHANGE => UWM_MDICHILDTABTOOLTIPCHANGE
//    UWM_MDICHILDTITLECHANGE => UWM_MDICHILDTABTEXTCHANGE
// - Ramon Casellas [casellas@infres.enst.fr] suggested
//    that the caption / window text / title of the MDI child
//    might not always be exactly what you want for the
//    corresponding tab's text.  I like that idea, so the
//    caption and tab text are no longer tied at the hip.
//    Changes to accomodate this:
//     * The tab text still starts out life with the
//       caption / window text of the frame (but it doesn't
//       have to stay that way).
//     * New "SetTabText" that the deriving MDI child can
//       call at anytime to update the text of the corresponding
//       MDI tab.
//     * SetTitle now takes an additional BOOL argument of
//       whether to update the tab text as well as set
//       the title / caption / window text
//     * CTabbedMDIChildWindowImpl::OnSetText doesn't send
//       UWM_MDICHILDTABTEXTCHANGE (UWM_MDICHILDTITLECHANGE) anymore.
//       You have to call SetTitle(text, TRUE) or SetTabText
//        explicitly now.
// - New "UWM_MDICHILDSHOWTABCONTEXTMENU" message sent to
//    the MDI *child* to request that the tab context menu be shown.
//    The default handler in CTabbedMDIChildWindowImpl simply
//    shows the "system menu" (GetSystemMenu).
//
// 2002/04/23: Daniel Bowen (DDB)
// - Tooltips:
//    * New UWM_MDICHILDTOOLTIPCHANGE message from MDI child to MDI client
//    * New "SetTabToolTip" for MDI child
// - New "CCoolTabItem" class used instead of TCITEM.
//   See "CoolTabCtrls.h" for an explanation.
// - ATL 7 compatibility issues pointed out to me by
//   Ramon Casellas [casellas@infres.enst.fr]
//
// 2002/04/22: Daniel Bowen (DDB)
// - Make the tab area height of the MDI tabs dependant on
//   the same metrics that the font of the tabs depends on.
// - Simon Steele (Simon Steele [s.steele@pnotepad.org]) made
//   an excellent suggestion about not hardcoding "CTabbedMDIClient"
//   in CTabbedMDIFrameWindowImpl.  Its now a template parameter.
// - CTabbedMDIClient and CMDITabOwner are now also templatized,
//   with a single template parameter specifying the the Tab Control type
//
// 2002/04/16: Daniel Bowen (DDB)
// - Enhanced CTabbedMDICommandBarCtrl. 
//   CTabbedMDICommandBarCtrl now gives you the option of whether
//   to use the "Document Icon" and frame caption buttons (min, close, etc,)
//   or not.  Simple call the cleverly named 
//   "UseMaxChildDocIconAndFrameCaptionButtons" method before calling
//   "SetMDIClient".
//      Background: In WTL 3.1, there wasn't any CMDICommandBarCtrl,
//   there was just CCommandBarCtrl.  With CCommandBarCtrl,
//   when the MDI child was maximized there was no document icon
//   in the menu or min/restore/close frame caption buttons in the
//   command bar on the right.  If you used this tabbed MDI stuff,
//   that was fine, because you could use the context menu for the
//   MDI tab to restore, minimize, etc.
//   With WTL 7.0, it forcefully asserts that you can't use
//   CCommandBarCtrl in an MDI application like you could in
///  WTL 3.1, and tells you to use CMDICommandBarCtrl.
//   CMDICommandBarCtrl adds the document icon and min/restore/close
//   buttons for maximized children.  CTabbedMDICommandBarCtrl
//   now gives you the choice of which style you want.

// 2002/04/15: Daniel Bowen (DDB)
// - CTabbedMDICommandBarCtrl
//    In case the frame window is living in a different image
//    (such as another DLL), instead of:
//      ::GetClassInfoEx(_Module.GetModuleInstance(), szClass, &wc);
//    use
//		m_hIconChildMaximized = (HICON) ::GetClassLong(wnd, GCL_HICONSM);
//    or
//		m_hIconChildMaximized = (HICON) ::GetClassLong(wnd, GCL_HICON);
// - Update comment at top of this file to mention CTabbedMDIChildWindowImpl
//    and CTabbedMDICommandBarCtrl.
// - Comment out a couple ATLTRACE statements
//
// 2002/04/10: Daniel Bowen (DDB)
// - Context Menu for MDI tab:
//     Now uses "GetSystemMenu" to get the window menu for the MDI child.
//     This is the same approach that CMDICommandBarCtrl::OnNcLButtonDown
//     uses when the MDI child is maximized and the user has clicked
//     on the document icon to the left of the menus.
//     If you run the application on Windows 2000 or 98 or greater,
//     there will be bitmaps in the menu.
//
//     Also note that when running on NT 4 or Win 95,
//     CMDICommandBarCtrl::OnNcLButtonDown will fail to show the
//     system menu at all because it doesn't like what it thinks is an
//     unknown flag - TPM_VERPOSANIMATION. To avoid that problem,
//     we won't even try to use TPM_VERPOSANIMATION.
//
// 2002/04/05: Daniel Bowen (DDB)
// - Updates related to WTL 7.0.
//   * WTL 7.0 wants you to use CMDICommandBarCtrl instead
//     of CCommandBarCtrl for MDI applications.
//     CMDICommandBarCtrl is decent, but there's some
//     anomolies even when its used in a plain vanilla app
//     (such as when the document icon doesn't update
//      depending on the active child).
//     Because we're subclassing the MDIClient and requiring
//     the MDI child frames to inherit from a special class,
//     there is now a "CTabbedMDICommandBarCtrl" that you
//     should use instead of CMDICommandBarCtrl.
// - CTabbedMDIChildWindowImpl:
//   * Add more messages from MDI child to MDI client:
//      UWM_MDICHILDMAXIMIZED
//      UWM_MDICHILDUNMAXIMIZED
//   * Override Create so that when a new child is created,
//     if the previous child was maximized, have the new
//     child be maximized as well (and prevent seeing a flickering
//     glimpse of the restored state of the new child)
//     See http://www.codeproject.com/useritems/WTLMDIChildMax.asp
//     for an explanation.
//   * Handle WM_SETFOCUS instead of depending on how
//     CFrameWindowImplBase handles it.  When the child is
//     maximized, ::IsWindowVisible(m_hWndClient) will return FALSE,
//     which results in the focus not being forwarded
//     to the "view" window.
//     See http://www.codeproject.com/useritems/WTLMDIChildMax.asp
//     for an explanation.
//
// 2002/02/07: Daniel Bowen (DDB)
// - New CCoolTabOwnerImpl MI class resulting from
//   refactoring due to commonality that existed between
//   CTabbedFrameImpl and CMDITabOwner.  Use this
//   class to help implement a windowing class that
//   will contain a CoolTabCtrl. This class lives in
//   TabbedFrame.h for now (see the header for more
//   or a description).
// - MDI child windows are now responsible for
//   a couple of things.  To have your MDI child windows
//   show up with corresponding tabs, be sure to
//   inherit from CTabbedMDIChildWindowImpl
//   instead of CMDIChildWindowImpl.
// - Redo a couple of implementation details of
//   how the MDI client keeps the MDI tabs and the
//   MDI child windows in synch.  See
//     OnMDIDestroy
//     OnChildActivationChange
//     OnChildTabTextChange
//   for details
// 
// 2002/01/31: Daniel Bowen (DDB)
// - Original Release
//

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Architect
United States United States
Daniel Bowen used to work as a Software Engineer for Evans & Sutherland in Salt Lake City, Utah working on the modeling tools for high end flight simulators. He then worked for the startup company WiLife Inc. in Draper, Utah working on the software portion of an easy to use and affordable digital video surveillance system. WiLife Inc. is now part of Logitech Inc.

Comments and Discussions