Click here to Skip to main content
Click here to Skip to main content

Custom Tab Controls, Tabbed Frame and Tabbed MDI

By , 13 Jul 2005
 

Introduction

I first saw the new Microsoft Visual Studio .NET after beta 2 was released. One of the things that stood out to me was how nice the tabs looked. It also finally included a tabbed MDI.

I soon after found Bjarke Viksøe's Cool Tab Controls. I was especially interested in the "DotNetTabCtrl". Bjarke soon linked to an updated version by Pascal Binggeli, that had support for the tabs to have images. There were several minor issues with both versions, but when I examined the code, it seemed an excellent foundation to build from.

Starting with the updates from Pascal, I began making my own updates. Initial updates included adding divider lines between the tabs, adjusting the layout to closer match VS.NET, adding implementations to use the tab control for a tabbed MDI, and adding other improvements. At first, I tried to make minimal changes to the base CCustomTabCtrl. I eventually began evolving even the base CCustomTabCtrl to accommodate my vision for what this could be.

Custom Tab Controls

CCustomTabCtrl is the base, templatized, ATL::CWindowImpl derived class to help implement a customized tab control window. The painting is double buffered for flicker free drawing. Clients never use this class directly, but instead use a class derived from it. Included out of the box are a handful of tab controls derived from CCustomTabCtrl:

  • CDotNetTabCtrl in "DotNetTabCtrl.h".

    Written by Daniel Bowen. Tab control with the look and feel of the tabs in VS.NET. Used for both MDI tabs, pane window tabs, and others.

  • CDotNetButtonTabCtrl in "DotNetTabCtrl.h".

    Written by Daniel Bowen. Tab control with the VS.NET style of button tabs (to look like VS.NET view of HTML with the Design/HTML buttons).

  • CButtonTabCtrl in "SimpleTabCtrls.h", CButtonTabCtrl in "SimpleDlgTabCtrls.h".

    Written by Bjarke Vikøe, updated for new CCustomTabCtrl by Daniel Bowen. Push button style tabs. The "DlgTabCtrl" version is meant to subclass an existing static control.

  • CFolderTabCtrl in "SimpleTabCtrls.h", CFolderTabCtrl in "SimpleDlgTabCtrls.h".

    Written by Bjarke Vikøe, updated for new CCustomTabCtrl by Daniel Bowen. Trapezoidal folder tabs similar to the tabs used in the output pane of Visual Studio 6. The "DlgTabCtrl" version is meant to subclass an existing static control.

  • CSimpleDotNetTabCtrl in "SimpleTabCtrls.h", CSimpleDotNetTabCtrl in "SimpleDlgTabCtrls.h".

    Written by Bjarke Vikøe, updated for new CCustomTabCtrl by Daniel Bowen. This is essentially Bjarke's original "CDotNetTabCtrl" with a flat tab look. The "DlgTabCtrl" version is meant to subclass an existing static control.

CCustomTabCtrl derived tab controls are meant to work similar to other common controls such as the list view (SysListView32) and the tree view (SysTreeView32). There is already an existing tab control (SysTabControl32) that is a common control. So why do we need CCustomTabCtrl? Because there are several customizations that are hard to do with it. SysTabControl32 was originally created to implement the task bar in Windows 95 and later (just like SysListView32 and SysTreeView32 were originally created for Windows Explorer). There are several features that other common controls have that SysTabControl32 is missing, such as custom drawing, insert and delete notifications, position displacement and more.

Custom Tab Items

One of the differences between CCustomTabCtrl derived tab controls and common controls in Windows are how items are managed. Common controls are meant to work with any client that can handle structures and window programming - from x86 assembly to Visual Basic. The "item" in most common controls is a structure. To get and set items, you fill out a structure with a mask to identify the fields you are interested in. There are several side effects of this design decision. One is that there is often more "memory copying" than really needs to be happening, especially with getting and setting text. Another is that there is no good way to know if a particular field is actually in use. Another effect is that any user data is always put into an "LPARAM" into one of these structures, cast to and from the real type of data.

CCustomTabCtrl takes a different approach, and lets you use any C structure or C++ class for the item that provides the needed interface. There are two such classes available out of the box - CCustomTabItem and CTabViewTabItem. The type of structure or class is a template parameter on the tab control class. If you want to use the tab control, and have instances of your own class for the tab items, the easiest thing to do is inherit from CCustomTabItem or CTabViewTabItem, and extend it to provide the extra functionality you need, then specify this new class as a parameter. To see the interface needed, simply look at CCustomTabItem.

Using Custom Tab Controls

Tab controls based on CCustomTabCtrl are meant to be used either as a stand-alone window, or to subclass an existing control on a dialog such as a static control. The parent of the tab control is responsible for creating, destroying, sizing and positioning the tab control window appropriately along side other child windows.

Depending on which custom tab control you use, it will probably depend on some system metrics to figure out which colors and fonts to use. If the user changes these system metrics (for example, by changing items on the "appearance" tab of the display control panel), the tab control can pick up these changes - but only if you propagate WM_SETTINGCHANGE from the main frame to the tab control. This can be done by handling WM_SETTINGCHANGE in the main frame, then calling CWindow::SendMessageToDescendants or the equivalent code. See the included sample applications for an example.

The samples provided with this article demonstrate how to use these tab controls as stand-alone windows used to switch between child "view" windows, where only one child view is visible at a time.

For a simple example of how to use a custom tab control for a tabbed MDI, see the "SimpleTabbedMDIDemo" sample. In this sample, the WTL wizard was run to create a default MDI Application. Instead of having CMainFrame inherit from CMDIFrameWindowImpl, change it to inherit from CTabbedMDIFrameWindowImpl. Instead of CMDICommandBarCtrl, use CTabbedMDICommandBarCtrl. Then in each MDI child frame, inherit from CTabbedMDIChildWindowImpl instead of CMDIChildWindowImpl.

The "TabDemo" sample uses a tabbed MDI as well, but in addition has a "popup tool window frame" that uses CDotNetTabCtrl to switch between child views. It also uses CDotNetButtonTabCtrl for the child frame to switch between an HTML view and an edit view (of the source of the HTML).

The "DockingDemo" sample shows how you might integrate these custom tab controls with Sergey Klimov's WTL Docking Windows. I've included the source for his docking windows with permission. However - be sure to get the latest updates from him! In the file "TabbedDockingWindow.h", there is the class CTabbedDockingWindow that inherits from CTabbedFrameImpl and Sergey's CTitleDockingWindowImpl.

The "TabbedSDISplitter" sample shows the use of a splitter in an SDI application, with the right side window "tabbed" to show multiple views. For another sample showing a slightly different use of these tabs in an SDI application, see the "SDITabbedSample" from Sergey Klimov's WTL Docking Windows and the work by Igor Katrayev.

It should be possible to integrate the custom tab controls in with other docking frameworks, splitters, etc. as well. As time allows, I'll try to get some more sample applications up.

Tabbed Frame

TabbedFrame.h contains classes to make it simple to add the ability to turn a frame window with one "view" into a tabbed frame window with a custom tab control to switch between one or more views. Included are the classes:

  • CCustomTabOwnerImpl - MI class that helps implement the parent of the actual custom tab control window. The class doesn't have a message map itself, and is meant to be inherited from along-side a CWindowImpl derived class. This class handles creation of the tab window as well as adding, removing, switching and renaming tabs based on an HWND.
  • CTabbedFrameImpl - Base template to derive your specialized frame window class from to get a frame window with multiple "view" child windows that you switch between using a custom tab control (such as CDotNetTabCtrl).
  • CTabbedPopupFrame - Simple class deriving from CTabbedFrameImpl that is suitable for implementing a tabbed "popup frame" tool window, with one or more views. See the "TabDemo" sample for an example of using this class.
  • CTabbedChildWindow - Simple class deriving from CTabbedFrameImpl that is suitable for implementing a tabbed child window, with one or more views. See the "TabbedSDISplitter" sample for an example of using this class.

Tabbed MDI

TabbedMDI.h contains classes to help implement a tabbed MDI using a custom tab control. There are multiple approaches to implementing a tabbed MDI. The approach that is used here is to subclass the out-of-the-box "MDIClient" from the OS, and require each MDI child frame to inherit from a special class CTabbedMDIChildWindowImpl (instead of the normal CMDIChildWindowImpl). Included are the classes:

  • CTabbedMDIFrameWindowImpl - Instead of having CMainFrame inherit from CMDIFrameWindowImpl, you can have it inherit from CTabbedMDIFrameWindowImpl. For an out-of-the box WTL MDI application, there are three instances of CMDIFrameWindowImpl to replace with CTabbedMDIFrameWindowImpl.
  • CTabbedMDIChildWindowImpl - If you want your MDI child window to have a corresponding tab in the MDI tab window, inherit from this class instead of from CMDIChildWindowImpl. This class also provides a couple of nice additional features:
    • When the child frame is created, if the previously active MDI child is maximized, the new window is also maximized.
    • Your child frame class can specify WS_MAXIMIZE so that it is forced to start out life maximized.
    • The method SetTitle is provided to set the frame title (and possibly the corresponding MDI tab's text).
    • The method SetTabText lets you set the text for the corresponding MDI tab regardless of what the frame caption (window text) is.
    • The method SetTabToolTip lets you set the tooltip's text for the corresponding MDI tab.
    • Your derived class can handle the message UWM_MDICHILDSHOWTABCONTEXTMENU to show a context menu for the corresponding MDI tab. The default context menu is the window's system menu.
  • CTabbedMDIClient - The CTabbedMDIFrameWindowImpl contains CTabbedMDIClient, which subclasses the "MDI Client" window (from the OS, that manages the MDI child windows). It handles sizing/positioning the tab window, calling the appropriate Display, Remove, UpdateText for the tabs with the HWND of the active child, etc. You can use CTabbedMDIClient without using CTabbedMDIFrameWindowImpl. To do so, simply call SetTabOwnerParent(m_hWnd), then SubclassWindow(m_hWndMDIClient) on a CTabbedMDIClient member variable after calling CreateMDIClient in your main frame class.
  • CMDITabOwner - The MDITabOwner is the parent of the actual tab window (such as CDotNetTabCtrl), and sibling to the "MDI Client" window. The tab owner tells the MDI child when to display a context menu for the tab (the default menu is the window's system menu). The tab owner changes the active MDI child when the active tab changes. It also does the real work of hiding and showing the tabs. It also handles adding, removing, and renaming tabs based on an HWND.
  • CTabbedMDICommandBarCtrl - In your MDI application, instead of using CMDICommandBarCtrl, use CTabbedMDICommandBarCtrl. It addresses a couple of bugs in WTL 7.0's CMDICommandBarCtrl, and allows you to enable or disable whether you want to see the document icon and min/max/close button in the command bar when the child is maximized.

Note to previous users

I originally posted my version of the "DotNetTabCtrl" code to the WTL mailing list's site on groups.yahoo.com, and to Bjarke Viksøe. If you have used a previous version downloaded from either of these places, there are only a couple of updates to your client code to accommodate updates that I've made:

  • Instead of:
    #include "CoolTabCtrls.h"

    now you need:

    #include "CustomTabCtrl.h"
    #include "DotNetTabCtrl.h"
    // (include other versions of tab controls)
  • Instead of calling SetBoldSelectedTab, use the CTCS_BOLDSELECTEDTAB style.
  • Instead of notifications starting with "TCN_", they now start with "CTCN_" (they are numerically identical to tab control "TCN_" notifications where there is overlap).
  • Instead of using the tab control styles starting with "TCS_", use the custom tab control styles starting with "CTCS_" (they are numerically identical to tab control "TCS_" styles where there is overlap).
  • Use CTCHITTESTINFO instead of TCHITTESTINFO.
  • Tab related classes now take a template argument of the data item type.
  • If you inherited off of CCustomTabCtrl or CDotNetTabCtrlImpl or others, there have been a few other interface changes that hopefully will be obvious to address (you'd get compile errors).
  • For the history of the files prior to the release of this article, please reference the prior history.

Custom Tab Control Reference

Requirements

  • ATL 3.0, 7.0, or 7.1
  • WTL 7.1

Styles

  • CTCS_SCROLL - This enables "scroll buttons". When the tab items don't get all the real estate they want, they overflow and the scroll button for that side is enabled. You can call the methods Get/SetScrollDelta and Get/SetScrollRepeat to adjust how much is scrolled and how fast scrolling is repeated when holding down the button.
  • CTCS_BOTTOM - If this style is set, the tab window is meant to be displayed on the bottom of the client area. Otherwise, it is meant to be displayed on the top of the client area. It is up to the parent of the tab window to honor this style.
  • CTCS_CLOSEBUTTON - This enables a "close" button. When this button is clicked, the parent gets a "CTCN_CLOSE" notification.
  • CTCS_HOTTRACK - Enables hot tracking tab items. If you are targeting Windows 2000/98 or later, be sure to #define WINVER and/or _WIN32_WINNT to 0x0500 or later, before including this file (usually in your precompiled header) so that the new "COLOR_HOTLIGHT" is used.

    Note: If you specify CTCS_SCROLL or CTCS_CLOSEBUTTON, those buttons are always hot tracked regardless of this style.

  • CTCS_FLATEDGE - Tab controls derived from CCustomTabCtrl can use this style to determine whether to draw the outline of the control with a flat look.
  • CTCS_DRAGREARRANGE - If you set this style, a tab item can be dragged to another position within the same tab control.
  • CTCS_BOLDSELECTEDTAB - The selected tab's text is rendered in the bold version of the tab font.
  • CTCS_TOOLTIPS - Enable tooltips to be displayed. Each item's tooltip defaults to the text of the tab, but can be adjusted by calling SetToolTip on the tab item.

Notifications

These messages are sent to the parent of the tab control window in the form of a WM_NOTIFY message.

  • NM_CLICK - Notifies a tab control's parent window when the left mouse button has been pressed. The lParam of the message is a pointer to a NMCTCITEM structure, with iItem being the index of the item which the cursor is over, or -1 if no item is under the cursor. In the handler, return TRUE to prevent the default processing to occur, or FALSE to allow it. The default processing selects the item under the cursor. This notification is not sent when clicking on a scroll or close button.
  • NM_DBLCLK - Notifies a tab control's parent window when the left mouse button has been double clicked. The lParam of the message is a pointer to a NMCTCITEM structure, with iItem being the index of the item which the cursor is over, or -1 if no item is under the cursor. In the handler, return TRUE to prevent the default processing to occur, or FALSE to allow it.
  • NM_RCLICK - Notifies a tab control's parent window when the right mouse button has been pressed. The lParam of the message is a pointer to a NMCTCITEM structure, with iItem being the index of the item which the cursor is over, or -1 if no item is under the cursor. In the handler, return TRUE to prevent the default processing to occur, or FALSE to allow it. The default processing selects the item under the cursor.
  • NM_RDBLCLK - Notifies a tab control's parent window when the right mouse button has been double clicked The lParam of the message is a pointer to a NMCTCITEM structure, with iItem being the index of the item which the cursor is over, or -1 if no item is under the cursor. In the handler, return TRUE to prevent the default processing to occur, or FALSE to allow it.
  • NM_CUSTOMDRAW - Notifies a tab control's parent window about drawing operations. The lParam of the message is a pointer to a NMCTCCUSTOMDRAW structure. See MSDN for an explanation of how custom drawing works with common controls in general, in the article "Customizing a Control's Appearance". For the most part, the custom tab control is very similar (especially to custom drawing a toolbar control). The one difference is that the NMCTCCUSTOMDRAW structure lets you set the HFONT for the inactive and selected item, instead of selecting the item's font into the device context and returning CDRF_NEWFONT on each CDDS_ITEMPREPAINT (you can still change the HFONT on each CDDS_ITEMPREPAINT, or you can just set it in the CDDS_PREPAINT notification).
  • CTCN_FIRST - Value of first custom tab control notification code.
  • CTCN_LAST - Value of last custom tab control notification code. If a derived class wants to define its own message, it can use CTCN_LAST - 1, CTCN_LAST - 2, etc.
  • CTCN_SELCHANGE - Notifies a tab control's parent window that the currently selected tab has changed. The lParam of the message is a pointer to a NMCTC2ITEMS structure, with iItem1 being the old selected item, and iItem2 the new item to select.
  • CTCN_SELCHANGING - Notifies a tab control's parent window that the currently selected tab is about to change. The lParam of the message is a pointer to a NMCTC2ITEMS structure, with iItem1 being the old selected item, and iItem2 the new item to select. The receiver of the message should return TRUE to prevent the selection from changing, or FALSE to allow the selection to change.
  • CTCN_INSERTITEM - Notifies a tab control's parent window that an item has been inserted. The lParam of the message is a pointer to a NMCTCITEM structure, with iItem being the index of the inserted item.
  • CTCN_DELETEITEM - Notifies a tab control's parent window that an item is about to be deleted. The lParam of the message is a pointer to a NMCTCITEM structure, with iItem being the index of the item to be deleted. The receiver of the message should return TRUE to prevent the deletion, or FALSE to allow it.
  • CTCN_MOVEITEM - Notifies a tab control's parent window that an item has been moved to another index by a "MoveItem" call. The lParam of the message is a pointer to a NMCTC2ITEMS structure, with iItem1 being the old index, and iItem2 the new index.
  • CTCN_SWAPITEMPOSITIONS - Notifies a tab control's parent window that two items have been switched in position by a "SwapItemPositions" call. The lParam of the message is a pointer to a NMCTC2ITEMS structure, with iItem1 being the index of the first item, and iItem2 the index of the second.
  • CTCN_CLOSE - Notifies a tab control's parent window that the "close" button has been clicked. The close button is only displayed for tab controls with CTCS_CLOSEBUTTON set.
  • CTCN_BEGINITEMDRAG - Notifies a tab control's parent window that a tab item drag has started. The lParam of the message is a pointer to a NMCTCITEM structure, with iItem being the index of the item being dragged.
  • CTCN_ACCEPTITEMDRAG - Notifies a tab control's parent window that a tab item drag has ended and is accepted by the user. The lParam of the message is a pointer to a NMCTC2ITEMS structure, with iItem1 being the index of the item in its original place, and iItem2 the new index of the item.
  • CTCN_CANCELITEMDRAG - Notifies a tab control's parent window that a tab item drag has ended and was cancelled by the user. The lParam of the message is a pointer to a NMCTCITEM structure, with iItem being the index of the item that was being dragged.

Structures

  • NMCTCITEM -
    • NMHDR hdr; - Generic Notification Information.
    • int iItem; - Index of item involved in action, or -1 if not used.
    • POINT pt; - Screen coordinate of point of action.
  • NMCTC2ITEMS -
    • NMHDR hdr; - Generic Notification Information.
    • int iItem1; - Index of first item involved in action.
    • int iItem2; - Index of second item involved in action.
    • POINT pt; - Screen coordinate of point of action.
  • CTCHITTESTINFO -
    • POINT pt; - Position to hit test, in client coordinates.
    • UINT flags; - Variable that receives the results of a hit test. The tab control sets this member to one of the following values:
      • CTCHT_NOWHERE - The position is not over a tab.
      • CTCHT_ONITEM - The position is over a tab item.
      • CTCHT_ONCLOSEBTN - The position is over the close button.
      • CTCHT_ONSCROLLRIGHTBTN - The position is over the right scroll button.
      • CTCHT_ONSCROLLLEFTBTN - The position is over the left scroll button.
  • NMCTCCUSTOMDRAW -
    • NMCUSTOMDRAW nmcd; - General custom draw structure.
    • HFONT hFontInactive; - Font for text of inactive tabs.
    • HFONT hFontSelected; - Font for text of selected tab.
    • HBRUSH hBrushBackground; - HBRUSH to PatBlt into background.
    • COLORREF clrTextInactive; - Color of text of inactive tab.
    • COLORREF clrTextSelected; - Color of test of selected tab.
    • COLORREF clrSelectedTab; - Color of the selected tab's background.
    • COLORREF clrBtnFace; - Used in drawing 3D shapes. Defaults to COLOR_BTNFACE.
    • COLORREF clrBtnShadow; - Used in drawing 3D shapes. Defaults to COLOR_BTNSHADOW.
    • COLORREF clrBtnHighlight; - Used in drawing 3D shapes. Defaults to COLOR_BTNHIGHLIGHT.
    • COLORREF clrBtnText; - Used in drawing 3D shapes. Defaults to COLOR_BTNTEXT.
    • COLORREF clrHighlight; - Used when a derived tab wants a "highlight" color.
    • COLORREF clrHighlightHotTrack; - Used for hot tracking.
    • COLORREF clrHighlightText; - Used when a derived tab wants a "highlight text" color.
  • CTCSETTINGS -
    • signed char iPadding; - Tab item padding.
    • signed char iMargin; - Tab item margin.
    • signed char iSelMargin; - Selected tab item margin.
    • signed char iIndent; - Indent from left of client area to beginning of first tab (sometimes used similarly on the right of client area).
    • CDotNetTabCtrlImpl (base class of CDotNetTabCtrl and CDotNetButtonTabCtrl) interprets margin and padding like so:
      M - Margin
      P - Padding
      I - Image
      Text - Tab Text
      
      With image:
           __________________________
      
          | M | I | P | Text | P | M |
           --------------------------
      
      Without image:
           ______________________
      
          | M | P | Text | P | M |
           ----------------------

Constants

  • FindItem flags
    • CTFI_NONE - 0x0000
    • CTFI_RECT - 0x0001
    • CTFI_IMAGE - 0x0002
    • CTFI_TEXT - 0x0004
    • CTFI_TOOLTIP - 0x0008
    • CTFI_TABVIEW - 0x0010
    • CTFI_HIGHLIGHTED - 0x0020
    • CTFI_CANCLOSE - 0x0040
    • CTFI_LAST - CTFI_CANCLOSE
    • CTFI_ALL - 0xFFFF

#define the following constants before you #include CustomTabCtrl.h to redefine them.

  • Scroll Repeat (milliseconds).
    • CTCSR_NONE - 0
    • CTCSR_SLOW - 100
    • CTCSR_NORMAL - 25
    • CTCSR_FAST - 10
  • Drag and Drop Constants
    • CTCD_SCROLLZONEWIDTH - 20 (pixels)

Methods

Note: This is one place where custom tab controls are dissimilar to common controls. Instead of sending messages to the window, you call public methods - much like working with the common control wrappers of WTL. If you want corresponding messages to these methods, then let me know.

  • SubclassWindow - Call when you have an existing window, such as a static control, that you want to subclass into a custom tab control window.
  • GetTooltips - Get the tooltip control window (the WTL tooltip control window wrapper is returned).
  • Get/SetImageList - Images for tab items are kept in an image list. The WTL image list wrapper is used.
  • Get/SetScrollDelta - The distance in pixels that each atomic scroll operation scrolls the view. Only valid when the CTCS_SCROLL style is set. Valid values are 0-63.
  • Get/SetScrollRepeat - When a scroll button is held down, the scroll repeat determines how quickly the atomic scroll operation is repeated. Only valid when the CTCS_SCROLL style is set. A Windows timer is used to repeat the scroll. Valid values are: ectcScrollRepeat_None, ectcScrollRepeat_Slow, ectcScrollRepeat_Normal, and ectcScrollRepeat_Fast.
  • InsertItem - Insert a new tab item. There are two versions of this method. The first allows you to pass the parameters for the tab item. The second allows you to call the CreateTabItem method to create a new tab, set the parameters on that item, then insert the item (the tab control takes ownership of the item created with CreateTabItem).
  • MoveItem - Move an existing tab item to another index, and shift the affected tab item indexes.
  • SwapItemPositions - Swap the positions of two tab items.
  • DeleteItem - Delete a tab item.
  • DeleteAllItems - Delete all the tab items.
  • GetItem - Get the pointer to the tab item class. The tab item class will either be CCustomTabItem, a class derived from CCustomTabItem, or a class with the same interface as CCustomTabItem.
  • Get/SetCurSel - The currently selected tab item. SetCurSel will first send a notification that the selected item is about to change (CTCN_SELCHANGING). If the receiver of the notification doesn't cancel the attempt, the current selection is changed, and another notification is sent to say the selection has changed (CTCN_SELCHANGE).
  • GetItemCount - Returns the number of tab items.
  • HitTest - Determines which tab, if any, is at a specified position (in client coordinates).
  • EnsureVisible - Ensures that the tab item specified is in view. Only really useful when CTCS_SCROLL is set.
  • GetItemRect - Get the RECT of an item in client device coordinates.
  • HighlightItem - Similar to TCM_HIGHLIGHTITEM for SysTabControl32 and the MFC and WTL wrappers CTabCtrl::HighlightItem.
  • FindItem - Find the next tab item matching the search criteria The function is meant to mimic how CListViewCtrl::FindItem and LVM_FINDITEM work, since there are no comparable messages or functions for a tab control.

Acknowledgements

I'd like to thank Bjarke Viksøe for his original "Cool Tab controls" and for all of the other cool things on his web site that he so generously shares with the world. I'd also like to thank all the many others who have given feedback, made suggestions, and helped this become what it is today.

History

  • 4 July, 2002 - updated source and demo.
  • 22 November, 2002 - updated source and demo.
  • 29 April, 2004 - updated source and demo. See the history of each file for a detailed description of changes.
  • 29 June, 2004 - updated source and demo. See the history of each file for a detailed description of changes.
  • 15 March, 2005 - updated source and demo. Support for VC 8.0, WTL 7.5, 64-bit, warnings level 4. Various minor bug fixes.
  • 08 April, 2005 - updated source and demo. Support for SetMinTabCountForVisibleTabs.
  • 14 July, 2005 - updated source and demo. HTML View focus enhancement, namespace qualify ATL and WTL use, various other minor bug fixes.

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

About the Author

Daniel Bowen
Architect
United States United States
Member
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.

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
GeneralMy vote of 5memberzxzxzxzx32928 Dec '11 - 16:53 
it's very good.it's useful to me.
Questionhow to add CLeftPaneTreeView to right tab group at TabDemo projectmemberDoubleGhost25 May '10 - 5:30 
Hi Daniel,
How can I add CLeftPaneTreeView to right tab group at TabDemo project ? Thank you very much!
Just do it!!!

Questionis .NET version available?memberViji Raj25 Jan '10 - 8:22 
Is .NET version available?
QuestionAbout TabControlmemberNiharvyas7 Aug '09 - 21:56 
Does Tab control Opens a page in new tab when that page is redirected from another page??
QuestionDid dockingframe's arrange is settled by class ssection ?memberkhaki668817 Jun '09 - 23:59 
Did dockingframe's arrange is settled by class ssection ?
How to let vertical dockframe up to horizontal dockingframe ?
AnswerRe: Did dockingframe's arrange is settled by class ssection ?memberkhaki668818 Jun '09 - 20:53 
I found a solution to solved this question.
in dockingframe.h locate like that:
 
public:
CDockingFrameImplBase()
:m_vPackage(false),m_hPackage(true)
{
}
 
change m_vPackage(false),m_hPackage(true)
to m_vPackage(true),m_hPackage(false)
it's worked.
GeneralSomething wrong with CDotNetTabCtrlmemberLove In Snowing11 Apr '09 - 2:51 
Hello, Daniel.
 
I create a object m_tab with your CDotNetTabCtrl, and something goes wrong.
 
The code is:
m_tab.Create(m_hWnd, rcDefault, NULL, WS_VISIBLE | WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | TCS_BOTTOM | TCS_TOOLTIPS | CTCS_HOTTRACK);
for(char i = 'A' ; i <= 'Z' ; i++)
{
CString str;
str.Format(_T("%c"), i);
m_tab.InsertItem(i - 'A', str.GetBuffer(0));
}
 
Each tab appears normally but the one lable "I", thers is no any text on the tab, but the tooltip shows correctly.
 
How to slove the problem ?
 
English is not my mother tongue, so forgive my poor English.
 
By the way, how can I contact with you ?

GeneralRe: Something wrong with CDotNetTabCtrlmemberMember 300059018 May '10 - 18:41 
Because the i is too thin , you can use “ i "
GeneralPlease clarify licencememberpeterchen15 Jan '09 - 4:56 
Excellent piece of work!
 
Could you please clarify the licencing conditions?
 

AnswerRe: Please clarify licencememberDaniel Bowen20 Jan '09 - 19:36 
peterchen wrote:
Excellent piece of work!
 
Could you please clarify the licencing conditions?

 
I'll follow up with you through e-mail.
 
I'm horribly being on replies to this article, but I'm still here Smile | :) Someday I might catch up...
 
-Daniel
GeneralRe: Please clarify licencememberharrys123429 Jan '10 - 6:21 
Hi Daniel, it was pleasure going through your code. Always nice to see a well written piece of code.
 
I currently have a tabbed class (that I use it as an addin to a 3rd party app). I will like to implement the close tab button in my own code (using MFC). Not sure if I can do this since I just started looking at possible solutions to this problem.
 
Of' course basing my code to your code base will be a great start (even if you are using ATL/WTL), but unfortunately the license of your code is vague at best. Can you please elaborate on your explicit license agreement.
 
Again thank you for sharing your code.
 
.Harrys.
QuestionhimemberMember 371951621 Mar '08 - 5:09 
can who help me :how to have XP-style in designe C# program ? --- library
GeneralNotificationsmembersqueakyariwheel21 Sep '07 - 8:06 
Before I start digging, does anyone have a quick solution for getting notifications (e.g. mouse click, move enter etc.) from docked, tabbed autohide windows? I can grab some of the msgs I am after in a PreTranslateMessage handler in my MainFrame but not all. Looking to allow for dropping of items onto the tab not just the client wnd and also looking to disable undocking based on user settings.
 
Thanks in advance.
GeneralUsing this framework problem, tooltip not displaymemberfree2000fly8 May '07 - 20:08 
I'm using "Custom Tab Controls, Tabbed Frame and Tabbed MDI", any thing looks OK, but once:
 
When I compiled it with VC8, Any thing OK.
But when I compiled it with VC6, the tooltips on the "Custom Tab Controls" do NOT display any more,
I don't know the reason, anyone help me?
 
My project web site:
 
http://sourceforge.net/projects/superpad[^]
 

 


 
Work hunting

GeneralRe: Using this framework problem, tooltip not displaymemberfree2000fly1 Aug '07 - 5:22 
I have find out the solution, see below URL:
http://www.cppblog.com/wlwlxj/archive/2007/07/23/28628.html[^]

 
Work hunting

GeneralTabbedSDISplittermemberhahahua24 Apr '07 - 11:41 
Is there anyone who can tell me how to add an double click event to the intems of the CTreectrl for the TabbedSDISplitter demo.
 
Thanks!
QuestionHow to Show and Hide Pages In sample project TabbedSDISplittermemberGuoliangLiu2 Mar '07 - 22:05 
HI,
 
As one beginner of WTL, I couldn't find out how to show and hide pages in
 
the sample project TabbedSDISplitter,any one could help? THANKS IN ADVANCE.

QuestionNM_RELEASEDCAPTURE messagememberRaviPK27 Feb '07 - 1:25 
Why you are not supporting NM_RELEASEDCAPTURE event in this customized tab control?
GeneralThank youmemberDouglas Troy31 Jan '07 - 20:22 
... for doing the work on this control and sharing with the community.
 



:..::. Douglas H. Troy ::..

Bad Astronomy |VCF|wxWidgets|WTL

Questioncannot go into "CMyCustomListView::OnItemPostPaint" methodmembergaojinsong27 Jan '07 - 0:30 
sorry sir, i want to know:
 
accroding to Project "TabbedSDISplitter"
i cannot go into "CMyCustomListView::OnItemPostPaint" method,
if i put a control inherit from "CMyCustomListView" into
dialog box(IDD_SDIDLG_FORM).
 
code like this:
 
class CSdiDlgView :public CDialogImpl,
public CDialogResize
{
...
CMyCustomListView m_list;
};
 
LRESULT CSdiDlgView::OnInitDialog(...){
m_list.SubclassWindow(GetDlgItem(IDC_LIST));
}
 
can somebody help me!
QuestionHow to let the "Task List" of panewindows first selected.membergaojinsong20 Jan '07 - 17:33 
i want to konw
How to let the "Task List" of panewindows first selected.
now first is "Test Dialog" pane.
AnswerRe: How to let the "Task List" of panewindows first selected.membergaojinsong21 Jan '07 - 21:09 
m_PaneWindows.front()->Show();Smile | :)
GeneralDockingDemo trouble && VS 2005 PEmemberHeToC16 Jan '07 - 22:34 
Help pls)
first error that had occured was smth like errit in manifest compiling, i disabled the option @genereate manifest file" and whis trouble has gone..
another issue is that this samle after compilation requires ATL80.dll.. strange
but after i copy this file to the dir with executable, msgbox appears with
"R6304 An application has made an attempt to load ATL80.DLL incorrectly...." message..
ps: project was compiled as a devug version.
any changes in @project options->Use of ATL@
such as (Not Uing ATL/Using as LIB/As dll) has no affect on this trouble
GeneralRe: DockingDemo trouble && VS 2005 PEmemberHeToC16 Jan '07 - 22:38 
hmm occationally in Release mode all is ok...
strange
GeneralUsing Tabbed Framework with STLPort5.0.2: bugsmemberloyso_b27 Dec '06 - 3:45 
When I'm using the Tabbed Framework with STLPort5.0.2 VS2003 SP1, I see a strange bugs when I'm resizing tabbed windows. Could you fix it, Daniel?

QuestionUsing CTabbedFrameImpl for main frame?memberdomehead5 Dec '06 - 20:33 
I'm new to WTL but like it a lot better than MFC so far. I create a lot of small utilities for work that have a basic tabbed interface, and I was hoping to use the CTabbedFrameImpl in place of my CFrameWindowImpl for my main frame. Basically I want to have CDotNetTabCtrl as my "view", then other "views" would be managed by the tab control.
 
But, I'm not at all sure how to make this work, and none of the samples demonstrate this basic approach. From what I gather, I need to change the base class to CTabbedFrameImpl instead of CFrameWindowImpl. I'm not clear what else needs to be done. The article mentions using CCustomTabOwnerImpl as a mix-in class, I assume of the frame window, but I'm confused.
 
Can anyone point me in the right direction?
 
Thanks!
 
Mike
AnswerRe: Using CTabbedFrameImpl for main frame?memberdomehead8 Dec '06 - 6:41 
Okay, figured this out...
 
1) Define a custom WM_POSTCREATE
#define WM_POSTCREATE WM_APP + 101
 
(This is needed because the first tab item added to the tab control is created at the wrong position, I presume because the menubar/toolbars have not been created yet.   Following the TabbedSDISplitter example, we create a custom WM_POSTCREATE and then do a PostMessage at the end of OnCreate to cause OnPostCreate to be called after Create has returned.   This also means that the actual tabs are added in OnPostCreate instead of in OnCreate.)
 
2) Changes to CMainFrame
class CMainFrame :
public CTabbedFrameImpl<CMainFrame, CDotNetTabCtrl<CTabViewTabItem>,
                                      CFrameWindowImpl<CMainFrame> >,
public CUpdateUI<CMainFrame>,
public CMessageFilter,
public CIdleHandler
{
protected:
typedef CTabbedFrameImpl<CMainFrame, CDotNetTabCtrl<CTabViewTabItem>, \
                CFrameWindowImpl<CMainFrame> > baseClass;
typedef CMainFrame thisClass;
 
....
BEGIN_MSG_MAP(CMainFrame)
...
   MESSAGE_HANDLER(WM_POSTCREATE, OnPostCreate)
...
 
3) In CMainFrame::OnCreate, post a WM_POSTCREATE message
PostMessage(WM_POSTCREATE, 0, 0);
 
4) Create the OnPostCreate method and code that method to add the tabs to the tab control, e.g.:
 
LRESULT CMainFrame::OnPostCreate( UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/ )
{
     // create child views for the tab window
     m_FirstChildView.Create(m_hWnd);
            m_SecondChildView.Create(m_hWnd);
     m_iTabIndex = this->AddTabWithIcon(m_FirstChildView, _T("FirstView"), MAKEINTRESOURCE(IDR_MAINFRAME));
            m_iTabIndex = this->AddTab(m_SecondChildView, _T("SecondView"));
 
     return 0;
}
 
Mike
GeneralWTL / MFCmemberblackbondi22 Nov '06 - 5:02 
How can I mix WTL with MFC? Are there any rules to respect? I want to use your Tabbed MDI in my MFC projct?
GeneralRe: WTL / MFCmembersophia nguyen12 Oct '07 - 14:46 
You can find it here
QuestionHow to use TabbedMDISave and build errormemberkite31 Aug '06 - 6:40 
Hi,
 
I'm very like this framework and I'm using it to build a application, in my application
I need handle WM_CLOSE, so I try to use TabbedMDISave:
1. include TabbedMDISave.h in stdafx.h
2. include TabbedMDISave.cpp in stdafx.cpp
 
When I build it, I got 104 errors, following are some errors:
Error 1 error C2653: 'CTabbedMDIChildModifiedList' : is not a class or namespace name g:\demos\xpad\xpad\tabbingframework\tabbedmdisave.cpp 65
Error 2 error C4430: missing type specifier - int assumed. Note: C++ does not support default-int g:\demos\xpad\xpad\tabbingframework\tabbedmdisave.cpp 65
Error 3 error C2550: 'CTabbedMDIChildModifiedList' : constructor initializer lists are only allowed on constructor definitions g:\demos\xpad\xpad\tabbingframework\tabbedmdisave.cpp 67
Warning 4 warning C4508: 'CTabbedMDIChildModifiedList' : function should return a value; 'void' return type assumed g:\demos\xpad\xpad\tabbingframework\tabbedmdisave.cpp 68
Error 5 error C2653: 'CTabbedMDIChildModifiedList' : is not a class or namespace name g:\demos\xpad\xpad\tabbingframework\tabbedmdisave.cpp 70
Error 6 error C2653: 'CTabbedMDIChildModifiedList' : is not a class or namespace name g:\demos\xpad\xpad\tabbingframework\tabbedmdisave.cpp 75
Error 7 error C2673: 'FinalRelease' : global functions do not have 'this' pointers g:\demos\xpad\xpad\tabbingframework\tabbedmdisave.cpp 77
Error 8 error C2227: left of '->Clear' must point to class/struct/union/generic type g:\demos\xpad\xpad\tabbingframework\tabbedmdisave.cpp 77
Error 9 error C2065: 'm_parentItem' : undeclared identifier g:\demos\xpad\xpad\tabbingframework\tabbedmdisave.cpp 81
Error 10 error C2653: 'CTabbedMDIChildModifiedList' : is not a class or namespace name g:\demos\xpad\xpad\tabbingframework\tabbedmdisave.cpp 84
Error

 
My build enviroments : VS 2005 and WTL 8.0 , en-XP with sp2.
How can I do to fix it?
 
Very thanks.
 


Generaltoo complicatedmemberhongdong14 Aug '06 - 15:18 
Is there any simple one instead?
GeneralIs there any way... [modified]memberShaka Zulu29 Jul '06 - 5:49 
I'm a native Win32 Api Programmer, not so familiar with ATL and WTL.
My Question is is there any way to use your Tab Framework in win32 C/C++ API Application.
As a matter of fact i'm interested only by the DotNetTabCtrl,not by the whole framework.
Can i use the templates for that control, for example to build a DLL with WTL that export
functions as interface that can be used in win32 API application,functions for initializing and managing the DotNetTabCtrl.
Thanks for your answer in advance !
 


GeneralTab and Shift-Tab Control NavigationmemberGil Rivlis7 Jul '06 - 10:28 

I use a form views in the tab control. The form view has controls (Edit, ListView, etc).
The problem is that tab navigation does not work between the controls.
 
Anyone has an idea how to fix that?
 
Thanks
Gil Rivlis
 
"...Everybody has opinions: I have them, you have them. And we are all told from the moment we open our eyes, that everyone is entitled to his or her opinion. Well, that's horsepuckey, of course. We are not entitled to our opinions; we are entitled to our _informed_ opinions. Without research, without background, without understanding, it's nothing. It's just bibble-babble...."
--- Harlan Ellison
GeneralEmail address doesn't workmembertonygeek27 Jun '06 - 11:13 
Daniel, what is email address to contact you nowadays?
 
Tony
GeneralUnexpected Behaviour when toggling show/hide state of docked panesmemberldwren14 Jun '06 - 22:39 

Like many other posters I saw your article and was very impressed with the look of the interface. I am fairly new to Windows programming and these examples have caused me to shift my focus from MFC to WTL.
 
To assist me with my learning process I decided to reproduce your 'DockingDemo' example within my own project. I have now got to the stage of having tabbed MDI children and a tabbed docking toolbar, although in my case I am deriving my docked views from CTreeViewCtrlEx.
 
Show/hide docked panes
 
I have noticed some strange behaviour when toggling the show/hide status on the docked panes and having checked back against my reference project it would seem you have the same issues with your DockedDemo example.
 
If I remove the tabs in reverse order (-5 -4 -3 -2 -1) and then put them back as specified below I get more docked panes than expected:
+1 Task List visible (docked bottom)
+2 Command pane visible (as expected, creates a tab with the Task List)
+3 Output pane visible (docked bottom, but not combined with tabs (1) & (2))
+4 Find pane visible (docked bottom, again not combined with either of the previous panes)
 
If I remove these in reverse order (-5 -4 -3 -2 -1) then I show the panes as:
+2 Task List and Command pane visible (tabbed in single window but not docked - top left corner of screen)
+3 Output pane visible (docked bottom)
+4 Find pane visible (docked bottom but not tabbed)
 
If I remove them in forward order (-1 -2 -3 -4 -5) I seem to get the reverse behaviour. (4) & (5) are tabbed together whilst the others form their own docked toolbars. If (4) is shown before (5) then both (4) and (5) show together and again they are undocked in the top left corner of the screen.
 

Message passing
 
I have attached a context menu, with the ID_FILE_NEW command, to my docked TreeView, but I have not managed to get the command back to the MainFrame for actioning. I have tried:
pPaneWindow->SetReflectNotifications(false);
and also tried setting FORWARD_NOTIFICATIONS on various classes but with no success.
 
I have overcome this by adding a member to my view class that gets initialised with CMainFrame:m_hWnd. This allows me to either:
1) Handle the message locally then send it back to the MainFrame for processing
2) Attach my context menu directly to the CMainFrame:m_hWnd
 
I'm sure this is not the ideal solution so any pointers in the right direction will be helpful.
 
Thanks in advance for any assistance.

QuestionTrying to subclass CTabCtrlmemberimbmay6 Jun '06 - 10:42 
I'm relatively new to WTL and I'm trying to create a dialog with a CTabCtrl on it that uses the CDotNetTabCtrl. I've tried a number of different things and I'm not getting anywhere. Can someone provide a short example of how to use CDotNetTabCtrl with an existing CTabCtrl on a dialog? TIA.
Generalm_stateMgr.Store();membercrystalicetpmc6 Apr '06 - 2:11 
if there are hide pane
can not restore right
why???Confused | :confused:
 
sorry for my poor english
 
thank you very much
 
crystalice
Questionhow to use it with dialog?memberDrizt30 Mar '06 - 4:25 
I use this class like this (from Bjarke Vikøe's cool tab)
"To use it, place a Tab control on your dialog.
Add it as a member variable to your dialog implementation file...
 
CDotNetButtonTabCtrl m_ctlTab;
 
In the OnInitDialog() event handler, add the following line:
 
LRESULT OnInitDialog(UINT /*uMsg*/,
WPARAM /*wParam*/,
LPARAM /*lParam*/,
BOOL& /*bHandled*/)
{
...
m_ctlTab.SubclassWindow(GetDlgItem(IDC_TAB1));
...
}
 
Add the following reflection macro to your main message map:
 
BEGIN_MSG_MAP(CMainDlg)
...
REFLECT_NOTIFICATIONS()
END_MSG_MAP()
"
 
But the dialog is very ugly,Have I missed anything?
 
BTW:this is really great job.
Generaltabbed childmemberpicazo5 Mar '06 - 8:16 
Hi Daniel,
 
First of all, thank you for sharing such a great project.
 
Second, my question/request:
I was wondering if you could provide another example like the docking one that you provided, also with tabbed child windows. However, instead of an html frame/view, if you could show how to add views with controls such as trees, lists, or just forms (various other controls).
 
Thanks a lot,
 
P.S. I know this should not be hard given the demos you provided, but I just started learning WTL a couple days ago.
 
-----------------
Genaro
GeneralRe: tabbed childmemberDaniel Bowen14 Mar '06 - 7:05 
The best thing to do is to install the WTL wizard (setup*.js in the AppWiz folder), then use it to create different test projects where you choose different types of view classes. You can then take that view class, and use it as a tab view class.
 
-Daniel
QuestionUpdated version?memberpropellerpit20 Feb '06 - 18:09 
Daniel, it looks like you made some updates and bugfixes to the code. Is it possible to get your updated version?
AnswerRe: Updated version?memberpropellerpit6 Mar '06 - 15:00 
It looks like the current version of your Custom Tab Controls is not working anymore Sergey Klimov's updated WTL Docking windows that is available from his web site.
Your update would be greatly appreciated!
Btw, thank you very much for this awesome project!
GeneralRe: Updated version?memberDaniel Bowen14 Mar '06 - 7:20 
I just found out about Sergey's new code. I'll take a look at what needs to change on my end to work with his new code. My guess is that I might need a changed version of VC7LikeCaption.h, but I'm not sure what else. I'm not sure when I would have new code for you to use though. I'm not convinced yet that I'll move all the samples I have where I use a modified version of his code to use his new version (which is just a snapshot, and not an official version yet). It looks like it does have some good things (especially the persistance changes), but there might not be all the fixes that the modified code has or there may be other compatibility issues.
 
As far as other changes I've made since the July update, there's not much, so I'll just list the diffs here:
 
  • Line 616 in DotNetTabCtrl.h. Change DT_PATH_ELLIPSIS to DT_END_ELLIPSIS. This is so that if the text doesn't fit in the given space, ... is used at the end to let you know there's more text (rather than possibly in the middle).
  • Line 559 in TabbedFrame.h. Put an (int) cast in front of nOldCount.
  • After line 816 in TabbedFrame.h, add this function:
    	void SetImageSize(int cx, int cy)
    	{
    		m_cxImage = cx;
    		m_cyImage = cy;
    	}
 
-Daniel
Generalalt+space does not work!memberTrioo23314 Jan '06 - 4:26 
Hi
 
I've noticed that the "ALT+SPACE" key combination does not work on any application that has a CTabbedChildWindow (or variant) in it - my applications and the demo applications that accompany this article. Could someone explain why this is and what can be done to fix this issue?
 
Thanks!
GeneralRe: alt+space does not work!memberDaniel Bowen14 Mar '06 - 7:23 
Hmm. I just tried this with the TabbedSDISplitter sample, and it seemed to work. Did you ever figure this out?
 
-Daniel
QuestionDoesn't draw collectly when theme changedmemberRoy.6 Jan '06 - 18:52 
Hi,
 
When you changed Windows theme from XP Style to classic,
you can see CFlyingTab Control doesn't draw correctly
under Windows XP.
 
following step-by-step instructions for reproduce this problem.
 
1. Start /DockingDemo/Release/DockingDemo.exe
2. Change Windows Theme from XP theme to classic theme
( or from classic theme to XP theme).
3. You can see CFlyingTab Control Position is wrong, and
Tab Color(COLOR_BTNFACE ?) is wrong.
 
I guess it caused because toolbar height is different between
XP theme and classic theme. Recently you add WM_SETTINGCHANGES or WM_SYSCOLORCHANGE HANDLER but it doesn't seem to work well.
 
Is this reproduce in your system?
 
Thanks in advance.
 
Roy.
Questionhow to change AutoHideDockingWindow Tabsmembersenkiner19 Dec '05 - 4:36 
First of all, thanks for your great codeSmile | :)
 
i want to bring a AutoHideDockingWindow Tab to the foreground,how shall I do it?
 
Best regards
 
James
AnswerRe: how to change AutoHideDockingWindow TabsmemberDaniel Bowen19 Dec '05 - 19:21 
senkiner wrote:
First of all, thanks for your great code

 
Thanks Smile | :)
 
senkiner wrote:
i want to bring a AutoHideDockingWindow Tab to the foreground,how shall I do it?

 
If you are using CTabbedAutoHideDockingWindow (from TabbedDockingWindow.h) and have a hold of a pointer, try calling pPaneWindow->Show();
 
You can also call Hide() to hide it, and AutoHide to auto hide it.
 
-Daniel
Generaland another problemmembersenkiner22 Dec '05 - 16:30 
thanks very much!
 
and another problem is when you open more than 50 documents(MDI tabs),there will appear something strange,for example,the system menu will disappears,and you can not open a new document any more,is this a memory lack bug?
 
sorry for my poor english!
 
best regards!
GeneralRe: and another problemmemberDaniel Bowen30 Dec '05 - 11:20 
That sounds like the symptom of a GDI leak or other GDI problem. Is this reproducable with one of the samples untouched, or is it in your own application? What operating system does it happen on?
 
-Daniel

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web04 | 2.6.130516.1 | Last Updated 14 Jul 2005
Article Copyright 2002 by Daniel Bowen
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid