# SftTabs/DLL 7.0 — Full Documentation > SftTabs/DLL is a DLL-based tab control for the Windows™ operating system, offering an alternative method of displaying multiple dialogs or cascading menu selections, by displaying tabs as found in a file cabinet or a notebook. Online documentation: https://softelvdm.com/Documentation/SftTabs%20DLL%207%200 Complete API reference (separate file): https://softelvdm.com/Vault/Softelvdm.com/llms/SftTabs-DLL-7.0-reference.txt ## SftTabs/DLL - Tab Control *Source: https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/1_product_description* SftTabs/DLL is a DLL-based tab control for the Windows™ operating system, offering an alternative method of displaying multiple dialogs or cascading menu selections, by displaying tabs as found in a file cabinet or a notebook. ### Tab Control SftTabs/DLL offers many features; from a simple, single-row tab control to a multi-row, multi-color tab control in a notebook style. - [SftTabs/DLL Wizard](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/g_wizarddesign) - 75 customizable tab styles - Single or multiple [tab rows](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/pop_tabrows) - Automatic multi-row tab layout (auto-flow) - Different color tabs, solid or gradient-filled - Owner-drawn (custom-rendered) tabs and tab control [background](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/g_background) - Themes support - [Transition effects](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/g_transitioneffects) - Background bitmaps and transparent controls - Customizable images on each tab for regular, hot and disabled tabs using bitmaps, icons, image lists, [GDI+](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/g_gdiplus) images, checkboxes, radiobuttons. - Hidden tabs - Enabled/disabled tabs - Single or multiline tab labels - Keyboard mnemonics (accelerator keys) on tab labels - Selectable tab label text alignment (left, right, center) - Built-in Minimize, Restore, Close buttons - Optional close button on each tab - [Wizard-style dialogs](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/g_wizardstyle) - Tabbed dialogs and tabbed windows - Tab reordering - Tab drag & drop - Up to 32 rows of tabs - Up to 256 tabs per tab control - Multiple tab styles - Tab colors can change based on tab status - Fixed or variable width tabs - Tab control with or without [client area](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/pop_clientarea) - [ToolTips](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/g_tooltips) - [Flyby highlighting](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/g_flyby_highlighting) - Ellipses for truncated tab text - Scrollable tabs - User-customizable [scroll button](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/pop_scrollbutton) bitmaps - Reduced menu complexity by using tab controls - Support for C and C++ (MFC) using Visual Studio - Support for Windows 10 and above, 64-bit, 32-bit and ARM64 applications - Complete implementation, not a sub/superclassed Windows control - [Windows dark mode](https://softelvdm.com/Documentation/SftDarkMode/Topic/1_main) support, tracking the Windows "Choose your mode" setting automatically - [Windows High Contrast](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/g_highcontrast) [accessibility](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/g_accessibility) support - Per-Monitor v2 DPI awareness - Built-in UI Automation provider and live-region announcements for screen readers (Narrator, NVDA, JAWS) - Documentation for AI coding assistants - an offline, full-text API reference formatted for large-language-model grounding, plus an AGENTS.md pointer file, so assistants such as Claude, GitHub Copilot and Cursor can answer questions and generate code against the complete API ### SftTabs/DLL Wizard Application The SftTabs/DLL Wizard allows you to design and test a tab control without any programming. Tab labels, the number of tab rows, tab colors, icon and bitmap locations are just a few of the items you can customize. Once you are satisfied with your tab control look, the SftTabs/DLL Wizard can even generate the required run-time code for C or C++ with MFC. So your programming effort is kept to a minimum. ### Source Code The source code for the MFC classes for tab control access, tabbed dialogs and tabbed windows is supplied. Any application that you develop can use SftTabs/DLL royalty-free (some restrictions apply), as long as only the DLL is shipped with your application. ### Languages Supported SftTabs/DLL supports C, C++ and other languages when using the standard SendMessage Windows API. The DLLs can be called using the definitions provided in the supplied header file. In addition, SftTabs/DLL is shipped with class definitions which support the Microsoft Foundation Class Library (MFC). ### Environments Supported - 64-bit support when running Windows 10 and above with Intel 64-bit processors - 32-bit applications on Windows 10 and above - ARM64 support when running Windows 11 and above on ARM64 processors UNICODE support is available for all platforms. The product supports the same easy to use API on all platforms. ### Royalties Any application that you develop can use SftTabs/DLL royalty-free in run-time only mode; design-time features are not available. Each user (developer) who needs access to any portion of the product must license a copy of SftTabs/DLL. ### AI / LLM Documentation The complete SftTabs/DLL documentation is also published in an AI/LLM-readable format, following the [llms.txt convention](https://llmstxt.org). The index covering all Softel vdm products is at [https://softelvdm.com/llms.txt](https://softelvdm.com/llms.txt). The product installation includes an AGENTS.md file at the installation root, which points AI coding assistants at the product's online guide and API reference. The documentation is always read online, as it is updated between product releases. ## New Features *Source: https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/g_newfeatures* Only a **minimal conversion is required when upgrading to SftTabs/DLL 7.0**. SftTabs/DLL 7.0 is virtually 100% source code compatible to version 6.5 and earlier versions. ### New in 7.0 - New built-in [UI Automation](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/g_accessibility) provider exposes tab control structure to Narrator, NVDA, JAWS and other screen readers - tab list, per-tab labels / mnemonics / [tooltips](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/g_tooltips) / enabled state / hidden state, active-tab selection, scroll / close / minimize / restore chrome buttons, and per-tab close buttons (where *fHasCloseButton* is set). See Accessibility (Screen Readers). - New built-in accessibility support: the tab control honors [Windows dark mode](https://softelvdm.com/Documentation/SftDarkMode/Topic/1_main) (see [Dark Mode](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/g_darkmode)), [Windows High Contrast](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/g_highcontrast) (see High Contrast), and is Per-Monitor v2 DPI aware (see DPI). A new [Announce](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/function_announce) function pushes short status text to attached screen readers through a UI Automation notification event. - New [SetDarkMode](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/function_darkmode) / GetDarkMode / IsDarkModeActive functions - dark mode setting with AUTO / ON / OFF modes; AUTO tracks the Windows "Choose your mode" setting automatically. - New [SetHighContrastMode](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/function_highcontrast) / GetHighContrastMode / IsHighContrastActive functions - honor the Windows High Contrast accessibility setting with AUTO / ON / OFF modes. - New [GetDPI](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/function_dpi) function returns the effective DPI for the monitor the tab control is currently displayed on. - New [SetImageScaling](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/function_imagescaling) / GetImageScaling functions opt into automatic DPI scaling of all images drawn by the tab control (tab pictures, scroll and close/minimize/restore button bitmaps). - New [SetPixelScaling](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/function_pixelscaling) / GetPixelScaling functions opt into interpreting caller-supplied pixel dimensions (margins, row indent, forced tab size) as 96-DPI reference values, for resolution-independent serialized configurations. - New SFTTABSN_DARKMODE_CHANGED notification indicating the active dark mode state changed. - New SFTTABSN_DPI_CHANGED notification indicating the monitor DPI changed. - New SFTTABSN_HIGHCONTRAST_CHANGED notification indicating the active high contrast state changed. - The [SFTTABS_CONTROL](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/struct_sfttabs_control) structure exposes the new settings (*nDarkMode*, *nHighContrastMode*, *imageScaling*, *pixelScaling*) and read-only resolved states (*fDarkModeActive*, *fHighContrastActive*). - The [SFTTABS_DRAWINFO](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/struct_sfttabs_drawinfo) structure exposes the current effective DPI (*dpi* field) on every owner-draw callback. - SftTabs/DLL 7.0 no longer provides help documentation integrated with development tools in various custom formats - instead documentation is located at [https://softelvdm.com/Documentation/SftTabs DLL 7 0](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200), which allows for continuous documentation updates without the need to release a new product version. Web access is required to access the product documentation. - New documentation for AI coding assistants. SftTabs/DLL 7.0 includes an offline, full-text API reference formatted for large-language-model grounding, together with an AGENTS.md pointer file, so AI assistants such as Claude, GitHub Copilot and Cursor can answer questions and generate code against the complete SftTabs/DLL API. ## Installing SftTabs/DLL *Source: https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/g_installation* When you are ready to install SftTabs/DLL: 1. Run the setup application - The download location is provided either with your license information at the time of purchase or you can download the product demo from our web site. Both the product and demo setup applications are identical and can be used interchangeably. ![Setup Application](https://softelvdm.com/Vault/Softelvdm.com/docx/SftTabs%20DLL%207.0/image/installation1.png) 2. Follow the instructions on the installation dialogs. Please note that the single developer version of SftTabs/DLL can only be installed by one user on one system. Multiple developer licenses and site licenses are available. Contact Softel vdm, Inc. for more information. 3. During the installation, you will be prompted to register the product using the License Manager application. Without proper registration, the product will not run. Once you are a registered user, you can take advantage of our [product support](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/g_contactsoftel), such as free maintenance versions, and you will receive information regarding new releases. 4. Once SftTabs/DLL has been successfully installed, you will find a new program group * SftTabs DLL 7.0*. Entries for the SftTabs/DLL Demo and sample applications have been added. ## Upgrading to Version 7.0 *Source: https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/g_upgrading* Only a minimal conversion is required when upgrading from an earlier version of SftTabs/DLL to SftTabs/DLL 7.0. SftTabs/DLL 7.0 is virtually 100% source compatible with SftTabs/DLL 6.5. Your application(s) must be recompiled to use SftTabs/DLL 7.0. SftTabs/DLL 7.0 and an older version of SftTabs/DLL can coexist in the same application to make the conversion as easy as possible, however, they cannot be used in the same source code file. ### Upgrading to Version 7.0 Even though SftTabs/DLL 7.0 is not completely upward compatible, the conversion effort is very minimal. Some structures used in earlier releases of SftTabs have been increased in size, resulting in the requirement to recompile your source code. To allow for SftTabs/DLL 6.5 and this new version to coexist when used by multiple applications, the DLLs have been renamed and a new window class is used. SftTabs/DLL 7.0 is source code compatible with older releases of SftTabs/DLL, provided the following changes are made in existing applications: ### Converting an Existing Application The conversion effort to implement SftTabs/DLL 7.0 in an application that currently uses version 6.5 is minimal. Most applications will only have to change the window class name used in DIALOG resources (see below). #### 1. Window Class Change In SftTabs/DLL 6.5 (the release prior to SftTabs/DLL 7.0), the window class used for SftTabs was SftTabsControl65. This window class has been dropped and has been renamed to **SftTabsControl70**. Any DIALOG resources that use the old window classes must be changed to use SftTabsControl70. Without this change, the dialogs will not be displayed. If the window class name was "hard-coded" in calls to Create or CreateWindow(Ex), the class name must also be changed. The preferred method is to use the preprocessor symbol [SFTTABS_CLASS](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/def_sfttabs_class). #### 2. Dll And Lib Files Name Change The Dlls and Lib files have been renamed for this new release. For the new file names, please see the section "[Building Applications](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/g_buildingapp)". #### 3. **SFTTABS_CONTROL**, New Members, Initialization In order to use [new features](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/g_newfeatures), [SetVersion](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/function_setversion) must be called with the new version indicator SFTTABS_7_0. Once the new version is activated in your source code, the new members found in the [SFTTABS_CONTROL](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/struct_sfttabs_control) structure **must** be initialized. If SetVersion is called with an earlier version indicator, these fields need not be initialized. New tab control features will however not be available. | ***Member*** | Suggested Initialization Value | | --- | --- | | *new in 7.0* | | | nDarkMode | [SFTTABS_DARKMODE_AUTO](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/function_darkmode) (2) - follow the Windows "Choose your mode" setting; set to SFTTABS_DARKMODE_OFF (0) to preserve pre-modernization behavior | | nHighContrastMode | [SFTTABS_HIGHCONTRAST_AUTO](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/function_highcontrast) (2) - follow the [Windows High Contrast](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/g_highcontrast) [accessibility](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/g_accessibility) setting; set to SFTTABS_HIGHCONTRAST_OFF (0) to preserve pre-modernization behavior | | imageScaling | [SFTTABS_IMAGESCALING_ASIS](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/function_imagescaling) (0) - back-compat default; set to SFTTABS_IMAGESCALING_STRETCH (1) to auto-scale all images by currentDPI/96 | | pixelScaling | [SFTTABS_PIXELSCALING_ASIS](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/function_pixelscaling) (0) - back-compat default; set to SFTTABS_PIXELSCALING_STRETCH (1) to treat caller-supplied dimensions as 96-DPI reference values | By using the suggested initialization values, the tab control will continue to operate as in earlier versions. #### 5. Dll And Lib Files Name Change The Dlls and Lib files have been renamed for this new release. For the new file names, please see the section "Building Applications". When linking statically, the library Gdiplus.lib must be added to the linker project settings (see the section "Building Applications"). ### What's New in 7.0 SftTabs/DLL 7.0 adds four major accessibility and rendering features that are enabled automatically on existing controls with no API changes required. Each has a dedicated guide: - [Dark mode](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/g_darkmode) that follows the Windows 10 "Choose your mode" setting, or can be forced per control - see Dark Mode. - Windows High Contrast accessibility support with strict color-policy compliance - see High Contrast. - UI Automation live-region announcements for screen readers via the new [Announce](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/function_announce) function - see Accessibility (Screen Readers). - Per-Monitor v2 DPI awareness with two optional opt-in flags for automatic [image scaling](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/g_dpi) and caller-supplied pixel-dimension scaling - see Per-Monitor DPI and Scaling. Existing applications inherit the new accessibility and Per-Monitor DPI behavior by simply recompiling against the 7.0 headers and libraries, provided the new SFTTABS_CONTROL members are initialized appropriately (see the initialization table in section 3 above). To also scale caller-supplied images and pixel dimensions automatically, one-line opt-in calls are available - see SetImageScaling and SetPixelScaling. ## Tab Control Components *Source: https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/g_components* The following describes the individual components that are available in a SftTabs/DLL tab control. Click on the area of interest to see a description of that portion of the control. ## ToolTips *Source: https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/g_tooltips* ToolTips are small windows describing a tab's purpose. ToolTips are displayed if the mouse cursor stays above a tab for a certain period of time. ToolTip windows are automatically removed if the mouse cursor is moved away from the tab or if the user presses a key on the keyboard. ![](https://softelvdm.com/Vault/Softelvdm.com/docx/SftTabs%20DLL%207.0/image/tooltip_1.gif) ToolTips are optional (see [SFTTABS_CONTROL](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/struct_sfttabs_control) and [SetToolTip](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/function_settooltip)) and can be defined using the [SftTabs/DLL Wizard](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/g_wizarddesign). ToolTips are also available for [scroll buttons](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/pop_scrollbutton) and Minimize, Restore and Close buttons (see SFTTABS_CONTROL). ## FlyBy Highlighting *Source: https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/g_flyby_highlighting* If flyby highlighting is enabled, a tab's text will be underlined and use a different text color when the mouse cursor is above a tab. ![](https://softelvdm.com/Vault/Softelvdm.com/docx/SftTabs%20DLL%207.0/image/flyby_1.gif) Flyby highlighting is optional (see [SFTTABS_CONTROL](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/struct_sfttabs_control)) and can be defined using the [SftTabs/DLL Wizard](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/g_wizarddesign). If the defined tab control style supports and [uses themes](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/g_using_themes), flyby highlighting should be enabled. Instead of underlining the text, the defined theme's representation method is used when the mouse cursor is above a tab. ## Transition Effects *Source: https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/g_transitioneffects* Tabbed dialogs offer transition effects as the user switches between tab pages. The new page to be activated can simply be displayed, or it can use a transition effect which "slides" or "rolls" the new page into place. An application can define a default transition effect which applies to all tab pages using the [SFTTABS_CONTROL](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/struct_sfttabs_control), defaultAnimationStyleShow and defaultAnimationTimeShow members (see [SetControlInfo](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/function_setcontrolinfo)). Each tab page can override the default transition effect using the [SFTTABS_TAB](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/struct_sfttabs_tab), animationStyleShow and animationTimeShow members (see [SetTabInfo](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/function_settabinfo)). > Transition effects cannot be defined using the [SftTabs/DLL Wizard](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/g_wizarddesign). These must be implemented at run-time using the sample code shown in the API section. ### Example This example defines a default transition effect for all tab pages of the [current tab](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/pop_activetab) control: C ``` SFTTABS_CONTROL Ctl; SftTabs_GetControlInfo(hwndTab, &Ctl); Ctl.defaultAnimationStyleShow = SFTTABS_EXPAND_CENTER; Ctl.defaultAnimationTimeShow = 200; SftTabs_SetControlInfo(hwndTab, &Ctl); ``` C++ ``` SFTTABS_CONTROL Ctl; m_Tab1.GetControlInfo(&Ctl); Ctl.defaultAnimationStyleShow = SFTTABS_EXPAND_CENTER; Ctl.defaultAnimationTimeShow = 200; m_Tab1.SetControlInfo(&Ctl); ``` ### Example This example defines a transition effect for just one z: C ``` SFTTABS_TAB Tab; SftTabs_GetTabInfo(hwndTab, 2, &Tab); Tab.animationStyleShow = SFTTABS_SLIDE_FROM_LEFT; Tab.animationTimeShow = 400; SftTabs_SetTabInfo(hwndTab, 2, &Tab); ``` C++ ``` SFTTABS_TAB Tab; m_Tab.GetTabInfo(2, &Tab); Tab.animationStyleShow = SFTTABS_SLIDE_FROM_LEFT; Tab.animationTimeShow = 400; m_Tab.SetTabInfo(2, &Tab); ``` ## Background *Source: https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/g_background* Tabbed dialogs offer built-in background handling, using background colors, background bitmaps and even through an application-defined callback, which can paint the background. > Background bitmaps require Common Controls version 6. Background colors based on [SFTTABS_TAB](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/struct_sfttabs_tab), colorClientArea are supported in all environments. If special background handling is used, any controls located on the tab page are automatically rendered in a style allowing portions of the background to show through the control, giving a transparent effect. > Some third-party controls do not properly support transparent rendering. These controls cannot be used with special background handling. Most standard Windows controls and common controls support transparent rendering without problems. Most ActiveX controls and third-party controls also work correctly, but may have to be defined using their API to support transparency. An application can define a background color for a tab page using the SFTTABS_TAB, colorClientArea member (see [SetTabInfo](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/function_settabinfo)). This defined color is automatically applied to the background of the tab page. If a background color is not defined for a tab page, the tab control's defined background bitmap is used instead. The background bitmap is defined using the [SFTTABS_CONTROL](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/struct_sfttabs_control), hInsideBitmap member (see [SetControlInfo](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/function_setcontrolinfo)). If [Windows themes](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/g_using_themes) are active, the theme's background supersedes the application's defined background color or background bitmap. These are never used if themes are active. An application can define a callback which is called when the background needs to be painted. This callback may optionally be used even if Windows themes are active. When [using C](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/g_usingc), the [SftTabs_TransparentControls](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/function_transparentcontrols) function handles background painting. When [using C++/MFC](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/g_usingcpp), [CSftTabsPage::m_lpfnDrawBackground](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/function_csfttabspage_m_lpfndrawbackground) can be used to define a background painting callback. ## Mouse and Keyboard Interface *Source: https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/g_mouseinterface* Tabs in a tab control can be activated using the left mouse button. By clicking on a currently inactive tab, that tab will become the [active tab](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/pop_activetab). This takes place under program control. The application receives a [SFTTABSN_SWITCHING](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/i_notifications) and SFTTABSN_SWITCHED WM_COMMAND notification. Tabs can also be made active using the keyboard. Just as regular Windows controls (such as buttons) respond to an Alt + *key* combination, the tab control responds to keyboard accelerators, if any one of the tab labels has been defined to support this. When defining tab text, the & character indicates that the following character is to be recognized by an Alt + *key* combination, e.g., the tab with the tab label "&First" will be made active when the user presses Alt-F. The & character will never be shown. The following character will be underlined instead. Switching tabs using Alt-*key* combinations is always supported when the tab control has the input focus. For cases where other windows have the input focus, the enclosing window or dialog has to be registered for keyboard accelerators to be recognized by the tab control (see [SftTabs_RegisterDialog](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/function_registerdialog) or SftTabs_RegisterWindow for more information). Control + Tab key combinations and Control + Shift + Tab key combinations are used to switch to the next (or previous) tab. That tab will become the new active tab. Control + *arrow key* key combinations can be used to scroll in a scrollable tab control. For Control + *arrow key* key combinations to have an effect, the tab control must be the active control, i.e., the control which currently has the input focus. ## GDI+ *Source: https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/g_gdiplus* If GDI+ is available, the tab control supports additional features not otherwise available: - Image support for PNG, TIFF, JPEG, GIF, Exif, EMF+, EMF (GDI+ images) with full support for alpha-blended (translucent and semi-transparent) images GDI+ is available on all supported Windows versions (Windows 10 and above). An application can test whether GDI+ is available using the [GetGDIPlusAvailable](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/function_gdiplusavailable) function. ## Bitmap Transparency *Source: https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/g_bitmap_transparency* SftTabs/DLL automatically uses bitmap transparency for all tab label bitmaps used in a tab control. When a bitmap is displayed, the [background](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/g_background) can show through portions of the bitmap. SftTabs/DLL accomplishes this by dynamically modifying a copy of the bitmap to adjust for the background. ![](https://softelvdm.com/Vault/Softelvdm.com/docx/SftTabs%20DLL%207.0/image/transparency_1.gif) ![](https://softelvdm.com/Vault/Softelvdm.com/docx/SftTabs%20DLL%207.0/image/transparency_1b.gif) The top, left pixel of each bitmap is inspected as the bitmap is painted. The color of that pixel represents the bitmap's background color. This color is replaced throughout the bitmap with the actual background. ![](https://softelvdm.com/Vault/Softelvdm.com/docx/SftTabs%20DLL%207.0/image/transparency_2.gif) If the bitmap image includes the top, left pixel, add an extra row or column of pixels to the bitmap, so the image does not include the top, left pixel. Bitmap transparency is only used for bitmaps and is not used for icons, images in an ImageList control or other images that can be represented by a [SFT_PICTURE](https://softelvdm.com/Documentation/SftPicture2/Topic/struct_sft_picture) structure. Bitmap transparency for bitmaps is fully automatic and cannot be turned off. ## Wizard-Style Dialogs *Source: https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/g_wizardstyle* It is very easy to implement Wizard-style dialogs with SftTabs/DLL. SftTabs/DLL offers a special tab control style that does not display any tabs, but still manages all required attached pages. Because the tab control doesn't offer any visible tabs, an external event such as a button click has to be used to change the tab control's [current tab](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/pop_activetab) (using [SetCurrentTab](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/function_setcurrenttab)). The application has to explicitly control the current tab. By changing the current tab, the application can navigate all tab pages. ![Wizard-Style Dialog](https://softelvdm.com/Vault/Softelvdm.com/docx/SftTabs%20DLL%207.0/image/wizard1.gif) During development of an application, it may be easier to use a regular tab style, so the programmer can test the pages simply by clicking on a tab. Once the pages have been debugged and tested, the tab control style can be changed to a wizard style tab control. An application can use the [SftTabs_PaintBitmap](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/function_paintbitmap) function to paint a bitmap on a dialog. SftTabs/DLL includes two [samples](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/g_samples) that demonstrate how to implement Wizard-style dialogs. ## Using Themes *Source: https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/g_using_themes* Windows themes can be selected by the user using the Settings app or the Control Panel. If a theme is selected, the display of user interface controls, such as SftTabs/DLL, adapts to the current display theme. Themes can provide various display styles for the same control. With themes active, Windows renders (paints) the control: | | | | --- | --- | | ![](https://softelvdm.com/Vault/Softelvdm.com/docx/SftTabs%20DLL%207.0/image/theme2.gif) | ![](https://softelvdm.com/Vault/Softelvdm.com/docx/SftTabs%20DLL%207.0/image/theme1.gif) | | Without themes | With Themes | By setting [SFTTABS_CONTROL](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/struct_sfttabs_control), *fAllowThemes* to TRUE, SftTabs/DLL adapts to the current theme used. If set to FALSE, themes are not honored and the control is rendered using the built-in style. Because Windows renders controls when themes are active and because Windows offers only one tab style, themes are only supported by one tab style (SFTTABSSTYLE_MODERN_I). SftTabs/DLL makes it easy to use the same application across all supported platforms. If Windows themes are not available, the control will simply use its built-in display style, otherwise it will fully exploit Windows themes. To prepare an application for proper themes support, the tab control should be designed using the [SftTabs/DLL Wizard](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/g_wizarddesign). It should be viewed in the SftTabs/DLL Wizard both with and without themes (see the *Styles tab, Use Themes option) to make sure that the defined tab control is visually satisfactory in both cases.* Tab controls designed using the SftTabs/DLL Wizard with themes will work identically on all supported platforms. Keep in mind that numerous tab definitions, particularly relating to colors, have no effect when themes are active. You can find out if a specific tab setting has any effect with themes active by consulting the tab setting's detail information in this online help. Windows themes are automatically suppressed when [Dark Mode](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/g_darkmode) or [Windows High Contrast](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/g_highcontrast) is active on the tab control. See Dark Mode and High Contrast for details on the alternative rendering paths used in each case. ## Dark Mode *Source: https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/g_darkmode* SftTabs/DLL 7.0 supports dark mode. Users who have selected the Windows 10 "Choose your mode" [accessibility](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/g_accessibility) setting to Dark will see SftTabs controls rendered with a dark color palette; users who have selected Light see the traditional palette. The tab control follows the system setting automatically - no per-application setup is required. What changes in dark mode: the tab control [background](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/g_background), tab labels, active-tab highlight, [scroll buttons](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/pop_scrollbutton) and close/minimize/restore buttons all switch to dark-palette colors. [Windows themes](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/g_using_themes) are suppressed while dark mode is active so the control renders through its built-in dark-aware GDI path rather than the system's light-themed tab style. The tab control's dark mode setting has three values (see [SetDarkMode](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/function_darkmode)): | | | | --- | --- | | **AUTO** (default) | Follow the Windows "Choose your mode" setting. The control re-renders when the system setting flips. | | **ON** | Always use the dark palette, regardless of the Windows setting. Useful when the hosting application has its own Light / Dark toggle and wants the tab control to follow it. | | **OFF** | Always use the light palette, regardless of the Windows setting. Useful when the application does not yet support dark mode end-to-end and mixing dark and light controls would look wrong. | SFTTABSN_DARKMODE_CHANGED is sent to the parent window each time the active dark mode state flips (AUTO mode only) so the application can repaint its own chrome around the tab control. IsDarkModeActive reports the current state at any time. Caller-supplied color overrides ([SetCtlColors](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/function_setctlcolors), per-tab colors in [SFTTABS_TAB](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/struct_sfttabs_tab)) remain in effect in dark mode unless [high contrast mode](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/g_highcontrast) is also active. If you need specific tabs to stand out in dark mode, pick accent colors that read well on both a light and a dark background (mid-tone saturated values in the RGB 30-210 range tend to work in both). Owner-drawn tabs ([SFTTABS_DRAWTABPROC](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/typedef_sfttabs_drawtabproc)) are responsible for their own dark-mode compliance. The [SFTTABS_DRAWINFO](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/struct_sfttabs_drawinfo) structure carries the tab control's current palette in its *colorBg* / *colorFg* members and IsDarkModeActive can be queried if role-specific colors are needed. The default render path handles non-owner-drawn tabs automatically. ### Host dialog integration The tab control follows the dark mode setting at the **control** level. The hosting dialog itself - title bar, dialog background, static labels, group boxes, edits and any standard Win32 controls placed alongside the tab control - also needs to be wired into dark mode for the dialog to render coherently. The shared [SftDarkMode](https://softelvdm.com/Documentation/SftDarkMode/Topic/1_main) helper provides that integration: a single header (SftDarkMode.h) used by every Softel vdm DLL product that handles dialog title bars, WM_CTLCOLOR* responses, the Windows "Choose your mode" toggle, and dark NC scrollbars on standard controls. A typical adoption is four call sites: [SftDarkMode_Init](https://softelvdm.com/Documentation/SftDarkMode/Topic/function_init) at process startup, [SftDarkMode_ApplyToDialog](https://softelvdm.com/Documentation/SftDarkMode/Topic/function_applytodialog) from each WM_INITDIALOG, [SftDarkMode_HandleDialogMessage](https://softelvdm.com/Documentation/SftDarkMode/Topic/function_handledialogmessage) routed from each dialog procedure, and an optional [SftDarkMode_SetActive](https://softelvdm.com/Documentation/SftDarkMode/Topic/function_setactive) when the application exposes its own Light / Dark toggle. Platform note: Dark mode requires Windows 10 or later. On earlier platforms the setting is stored but has no visual effect. ## High Contrast *Source: https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/g_highcontrast* Windows High Contrast is an [accessibility](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/g_accessibility) setting, not a visual preference. Users who enable it have committed to a specific high-contrast color scheme for everything on screen, and Microsoft's accessibility guidelines require applications to let the user's scheme win over any application-chosen colors. SftTabs/DLL 7.0 follows this rule automatically. When Windows High Contrast is active, the tab control: - renders [backgrounds](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/g_background) in *COLOR_WINDOW*, text in *COLOR_WINDOWTEXT*, active-tab highlight in *COLOR_HIGHLIGHT* / *COLOR_HIGHLIGHTTEXT*, and similar for other roles, - ignores caller-supplied color overrides ([SetCtlColors](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/function_setctlcolors), per-tab colors in [SFTTABS_TAB](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/struct_sfttabs_tab)) on the default render path - the user's contrast theme wins, - suppresses [Windows themes](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/g_using_themes) so the control falls back to the non-themed GDI path that honors system colors directly. The tab control's high contrast setting has three values (see [SetHighContrastMode](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/function_highcontrast)): | | | | --- | --- | | **AUTO** (default) | Follow the Windows High Contrast setting. The control re-renders when the setting flips. | | **ON** | Always use the system palette, regardless of the Windows High Contrast setting. Useful for testing or for applications that want consistent high-contrast rendering for a specific tab control. | | **OFF** | Ignore the Windows High Contrast setting and render normally. Not recommended in shipping applications - it means users with accessibility needs will see rendering that does not comply with their contrast theme. | SFTTABSN_HIGHCONTRAST_CHANGED is sent to the parent window each time the active state flips (AUTO mode only) so the application can repaint its own chrome to match. IsHighContrastActive reports the current state at any time. Owner-drawn tabs ([SFTTABS_DRAWTABPROC](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/typedef_sfttabs_drawtabproc)) are responsible for their own high-contrast compliance. Owner-draw code should query IsHighContrastActive and re-map its role colors to system-palette values when the return value is TRUE. Failing to do this makes owner-drawn tabs unreadable under a user's high-contrast theme. [Dark mode](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/g_darkmode) and Windows High Contrast are independent. If the user has both enabled, high contrast takes precedence - the contrast theme's palette wins over the dark palette, because honoring the user's contrast theme is the stronger accessibility requirement. ## Accessibility (Screen Readers) *Source: https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/g_accessibility* SftTabs/DLL 7.0 ships with built-in Windows UI Automation (UIA) support. Users who rely on Narrator, NVDA, JAWS or any other UIA-compatible assistive technology can read and navigate SftTabs controls without the hosting application doing any work. No opt-in, no code change, no separate build. What the screen reader sees: | | | | --- | --- | | Control type | **Tab**. The root advertises *UIA_TabControlTypeId* with *IsSelectionRequired=TRUE* and the *Selection* pattern. Automation harnesses and AT software can enumerate the tabs, query the [active tab](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/pop_activetab), and switch tabs programmatically. | | Tab items | One **TabItem** child per real tab (visible and hidden). Each tab item advertises the *SelectionItem* pattern - activation is via *SelectionItem.Select* per the UIA spec (TabItems do not advertise Invoke). Hidden tabs still appear in the tree with *IsOffscreen=TRUE* so AT clients can discover them. | | Tab item properties | *Name* from the tab label with *&* mnemonic markers stripped (spec requirement); *AccessKey* carrying the mnemonic character; *HelpText* from the tab's *lpszToolTip* so the same text shown as an on-hover [tooltip](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/g_tooltips) is also announced; *IsEnabled* from *fEnabled && !fHidden*; *PositionInSet* / *SizeOfSet* for set context; *HasKeyboardFocus* set on the active tab when the control has focus. | | Chrome buttons | **Button** elements for the scroll-left, scroll-right, close, minimize, and restore chrome buttons (when they exist as HWNDs). Each advertises *Invoke*. *Name* is a short identifier ("Close", "Minimize", "Restore", "Scroll Left", "Scroll Right"); *HelpText* carries the per-button tooltip set on the control (*szCloseToolTip* / *szMinimizeToolTip* / etc.). | | Per-tab close button | When a tab's *fHasCloseButton* is TRUE, the tab exposes a nested **Button** child with the *Invoke* pattern. Invoking the close button synthesizes a click on the tab's second-picture area - the same code path as a real click, so the application receives the standard [SFTTABSN_LBUTTONDOWN_IMAGE2](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/i_notifications) notification. Tabs without *fHasCloseButton* remain childless. | Automatic event notifications raised to UIA clients: *Selection_Invalidated* + *AutomationFocusChanged* on every tab switch, *StructureChanged* on tab insert / delete / reset / move / layout, *AutomationFocusChanged* on focus changes. All events are internally guarded by *UiaClientsAreListening* so the cost when no assistive technology is attached is one cached function-pointer call. There is nothing to turn on. The provider loads on demand the first time a UIA client queries the control, so there is no overhead for applications whose users never attach an assistive technology. Two things the application controls: - Set per-tab tooltip text (*lpszToolTip* in [SFTTABS_TAB](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/struct_sfttabs_tab)) so the on-hover tooltip text is also announced to screen readers as the tab's *HelpText*. Set per-button tooltip text (*szCloseToolTip*, *szMinimizeToolTip*, *szRestoreToolTip*, *szLeftToolTip*, *szRightToolTip* on [SFTTABS_CONTROL](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/struct_sfttabs_control)) for the chrome buttons. - Call [Announce](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/function_announce) to push short application-status text ("Saved", "Tab closed", "Switched to page 3 of 5") to attached screen readers. Announce is the right tool for momentary status updates that do not have a visible representation in the tab control. [Dark mode](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/g_darkmode) and [Windows High Contrast](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/g_highcontrast) are independent accessibility settings. SftTabs honors both automatically (see [SetDarkMode](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/function_darkmode) and [SetHighContrastMode](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/function_highcontrast)). Platform note: The UIA notification event used by Announce requires Windows 10 version 1709 or later. On earlier platforms Announce is a silent no-op. All other UIA features work on Windows 7 and later. ## Per-Monitor DPI and Scaling *Source: https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/g_dpi* SftTabs/DLL 7.0 is fully Per-Monitor v2 DPI-aware. A tab control hosted on a Per-Monitor v2 aware top-level window will re-render automatically when its window moves to a monitor of a different DPI or when the system DPI changes. The control owns the metrics it controls; the caller owns the images and fonts it provides. Two opt-in flags let the caller hand those over to the control as well. ### Host setup The host application must declare Per-Monitor v2 DPI awareness. This is the single most common reason SftTabs/DLL 7.0 applications do not re-render correctly when moved between monitors of different DPI. Without a PMv2 declaration, Windows silently keeps the process in System-aware mode: the DPI is fixed for the process lifetime, SftTabs does not observe DPI changes, [SFTTABSN_DPI_CHANGED](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/function_dpi) is never raised, and high-DPI monitors render at System-DPI sizes stretched by Windows. Visual Studio's default *app.manifest* does **not** declare PMv2 awareness - the developer must opt in explicitly. Two approaches - pick one: #### Application manifest (recommended) Add a ** / ** element to the application manifest. Both elements are usually included for back-compatibility with older Windows 10 builds: ``` PerMonitorV2 True/PM ``` In a Visual Studio C++ project, set *Project Properties -> Manifest Tool -> Input and Output -> Additional Manifest Files* to the .manifest file above, or edit the auto-generated manifest directly. In a C# / .NET project, check *Application -> DPI awareness* and select *Per Monitor V2*. #### Runtime API Alternatively, call SetProcessDpiAwarenessContext at process startup, before any window is created: ``` SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2); ``` Caveat: This call must run before the first window (including hidden startup dialogs or splash screens) is created. If a window has already been created, Windows rejects the call and the process remains in whichever mode the manifest specified - which, with the Visual Studio default, is System-aware. #### Verifying the declaration worked Quick check at runtime: GetDpiForWindow on the tab control returns the current monitor's DPI - 96 at 100%, 120 at 125%, 144 at 150%, 192 at 200%. If the returned value never changes as you drag the window between monitors with different scale factors, the host is not in PMv2 mode. ### What scales automatically When the host is Per-Monitor v2 aware, the tab control scales these metrics itself on every DPI change without any caller involvement: - tab heights and row heights, - [scroll button](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/pop_scrollbutton) sizes, - focus rectangle thickness, - close / minimize / restore button sizes, - 3D frame widths. ### What the caller controls Two independent opt-in flags let the caller choose whether caller-supplied pixel metrics and caller-supplied images also scale with DPI. Both default to back-compatible behavior (no automatic scaling) so existing applications keep working unchanged. | Flag | Covers | ASIS (default) | STRETCH | | --- | --- | --- | --- | | [SetImageScaling](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/function_imagescaling) | Every image the tab control draws: caller-supplied tab pictures ([SFTTABS_TAB](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/struct_sfttabs_tab), TabPicture and TabPicture2, including hot and disabled variants); scroll button and close/minimize/restore button bitmaps ([SFTTABS_CONTROL](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/struct_sfttabs_control), hButtonBitmap, hButtonBitmap2, and their disabled counterparts). | Images are drawn at their native pixel size. Bitmaps supplied at 96 DPI look physically smaller on a high-DPI monitor. | Images are scaled by *currentDPI / 96*. Bitmaps use *HALFTONE* stretch; [GDI+](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/g_gdiplus) images use *InterpolationModeHighQualityBicubic*. | | [SetPixelScaling](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/function_pixelscaling) | Caller-supplied pixel dimensions on SFTTABS_CONTROL: *leftMargin* and *rightMargin* (margins on the [tab row](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/pop_tabrows)), *rowIndent* (row indentation), *forcedSize* (forced tab row height / width). | Values are used verbatim in physical screen pixels. A margin of 10 is 10 pixels on any monitor. | Values are interpreted as 96-DPI reference pixels. A margin of 10 is 10 pixels at 100%, 15 pixels at 150%, 20 pixels at 200%. Storage and getters always return caller-reference units so serialized configurations stay portable. | ### Decision guide | Goal | Setting | | --- | --- | | "My existing application already ships multiple image sizes or only targets 96 DPI" | Leave SetImageScaling ASIS (default). Ship tab pictures sized for the target DPI. | | "I want crisp images on high-DPI monitors without code changes" | Call SetImageScaling with SFTTABS_IMAGESCALING_STRETCH once at control creation. | | "My margins and forced tab sizes should stay physically the same across monitors" | Call SetPixelScaling with SFTTABS_PIXELSCALING_STRETCH once at control creation. | | "My serialized / saved layout metrics must stay portable across DPI" | SetPixelScaling STRETCH. Storage stays in 96-DPI reference pixels regardless of monitor. | | "I have a drawing callback ([SFTTABS_DRAWTABPROC](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/typedef_sfttabs_drawtabproc)) that caches pixel metrics" | Stop caching. Read the *[dpi](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/struct_sfttabs_drawinfo)* field on every SFTTABS_DRAWINFO callback and re-compute pixel sizes each paint. | ### Caller responsibilities on DPI change When the control's monitor DPI changes, SftTabs raises **SFTTABSN_DPI_CHANGED** to the parent window. The application should: - re-send WM_SETFONT with a font sized for the new DPI (SftTabs does not own the application's font), - if SetImageScaling is ASIS and the caller wants crisp images, re-register tab pictures (SFTTABS_TAB, TabPicture / TabPicture2) at the new physical size, - if SetImageScaling is STRETCH, no action needed - the control scales existing images automatically, - if SetPixelScaling is ASIS, re-apply margins / indent / forced size scaled for the new DPI, - if SetPixelScaling is STRETCH, no action needed - the control scales stored values automatically. ### Owner-draw The SFTTABS_DRAWINFO structure carries the control's current effective DPI in its **dpi** field. Owner-draw code should read this value on every paint and must not cache pixel metrics across callbacks. GetDPI returns the same value outside a paint callback. Platform note: Per-Monitor v2 DPI awareness requires Windows 10 version 1703 or later. On older platforms the host process runs in System-aware or Unaware mode and DPI is effectively fixed for the process lifetime - SftTabs still renders correctly but does not fire SFTTABSN_DPI_CHANGED. ## Demo Application *Source: https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/g_demo_application* During the installation of SftTabs/DLL, an icon for the demo application "Demo" is installed in the program group *SftTabs/DLL 7.0*. This demo application shows some of the features available in SftTabs/DLL. It is also used to access other [samples](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/g_samples) included in the demo or product and the online help. ![Demo Application](https://softelvdm.com/Vault/Softelvdm.com/docx/SftTabs%20DLL%207.0/image/demo.png) > All sample programs and complete sample source code can be found in the directory \Program Files (x86)\Softelvdm\SftTabs DLL 7.0\Samples. Each sample is installed in its own subdirectory. All samples are supplied with a precompiled executable (EXE) and an entry is added to the *SftTabs/DLL 7.0* program group for each sample. ## Samples *Source: https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/g_samples* SftTabs/DLL includes sample code for both C and C++. The samples listed in the following table can be found in the folder "\Program Files (x86)\Softelvdm\SftTabs DLL 7.0\Samples". These samples are also referenced throughout the documentation. ### C | C Sample | Description | | --- | --- | | [C Dialog Sample](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/sample_c_dialog) | Illustrates a simple tabbed dialog with nested tabs, some graphics, [transition effects](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/g_transitioneffects). | | [C Images Sample](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/sample_c_images) | Illustrates [GDI+](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/g_gdiplus) images, bitmaps, icons, checkboxes and image handling techniques. | | [C Window Sample](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/sample_c_window) | Illustrates a tabbed window. | ### C++ | | | | --- | --- | | [C++ Dialog Sample](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/sample_cpp_dialog) | Illustrates a simple tabbed dialog with nested tabs, some graphics, transition effects. | | [C++ Features 1 Sample](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/sample_cpp_features1) | Illustrates a [background bitmap](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/g_background) (outside tab control) and owner-draw tabs. | | [C++ Images Sample](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/sample_cpp_images) | Illustrates GDI+ images, bitmaps, icons, checkboxes and image handling techniques. | | [C++ MDI Sample](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/sample_cpp_mdi) | Illustrates an MDI application with a tab control to select the active document. | | [C++ SDI Sample](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/sample_cpp_sdi) | Illustrates an SDI application using a tab control on its document view. | | [C++ Wizard 1 Sample](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/sample_cpp_wizard1) | Illustrates a tabbed dialog with a wizard-style tab control. | | [C++ Wizard 2 Sample](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/sample_cpp_wizard2) | Illustrates a tabbed dialog with a wizard-style tab control. | ## Dialog Sample (C) *Source: https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/sample_c_dialog* This sample illustrates a simple tabbed dialog with nested tabs, some graphics and [transition effects](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/g_transitioneffects). The source code is located at C:\Program Files (x86)\Softelvdm\SftTabs DLL 7.0\Samples\C\Dialog\Dialog.c or C:\Program Files\Softelvdm\SftTabs DLL 7.0\Samples\C\Dialog\Dialog.c (on 32-bit Windows versions). [Full sample source — Dialog Sample (C) (1484 lines) →](https://softelvdm.com/Vault/Softelvdm.com/llms/SftTabs-DLL-7.0-samples.txt) ## Images Sample (C) *Source: https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/sample_c_images* This sample illustrates [GDI+](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/g_gdiplus) images, bitmaps, icons, checkboxes and image handling techniques. The source code is located at C:\Program Files (x86)\Softelvdm\SftTabs DLL 7.0\Samples\C\Images\Images.c or C:\Program Files\Softelvdm\SftTabs DLL 7.0\Samples\C\Images\Images.c (on 32-bit Windows versions). [Full sample source — Images Sample (C) (733 lines) →](https://softelvdm.com/Vault/Softelvdm.com/llms/SftTabs-DLL-7.0-samples.txt) ## Window Sample (C) *Source: https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/sample_c_window* This sample illustrates a tabbed window. The source code is located at C:\Program Files (x86)\Softelvdm\SftTabs DLL 7.0\Samples\C\Window\Window.c or C:\Program Files\Softelvdm\SftTabs DLL 7.0\Samples\C\Window\Window.c (on 32-bit Windows versions). [Full sample source — Window Sample (C) (701 lines) →](https://softelvdm.com/Vault/Softelvdm.com/llms/SftTabs-DLL-7.0-samples.txt) ## Dialog Sample (C++) *Source: https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/sample_cpp_dialog* This sample illustrates a simple tabbed dialog with nested tabs, some graphics and [transition effects](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/g_transitioneffects). The source code is located at C:\Program Files (x86)\Softelvdm\SftTabs DLL 7.0\Samples\MFC\Dialog\Maindlg.cpp or C:\Program Files\Softelvdm\SftTabs DLL 7.0\Samples\MFC\Dialog\Maindlg.cpp (on 32-bit Windows versions). [Full sample source — Dialog Sample (C++) (357 lines) →](https://softelvdm.com/Vault/Softelvdm.com/llms/SftTabs-DLL-7.0-samples.txt) ## Features 1 Sample (C++) *Source: https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/sample_cpp_features1* This sample illustrates a [background bitmap](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/g_background) (outside the tab control) and owner-draw tabs. The source code is located at C:\Program Files (x86)\Softelvdm\SftTabs DLL 7.0\Samples\MFC\Features 1\SampleDlg.cpp or C:\Program Files\Softelvdm\SftTabs DLL 7.0\Samples\MFC\Features 1\SampleDlg.cpp (on 32-bit Windows versions). [Full sample source — Features 1 Sample (C++) (403 lines) →](https://softelvdm.com/Vault/Softelvdm.com/llms/SftTabs-DLL-7.0-samples.txt) ## Images Sample (C++) *Source: https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/sample_cpp_images* This sample illustrates [GDI+](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/g_gdiplus) images, bitmaps, icons, checkboxes and image handling techniques. The source code is located at C:\Program Files (x86)\Softelvdm\SftTabs DLL 7.0\Samples\MFC\Images\Maindlg.cpp or C:\Program Files\Softelvdm\SftTabs DLL 7.0\Samples\MFC\Images\Maindlg.cpp (on 32-bit Windows versions). [Full sample source — Images Sample (C++) (303 lines) →](https://softelvdm.com/Vault/Softelvdm.com/llms/SftTabs-DLL-7.0-samples.txt) ## MDI Sample (C++) *Source: https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/sample_cpp_mdi* This sample illustrates an MDI application using a tab control to select the active document. The source code is located at C:\Program Files (x86)\Softelvdm\SftTabs DLL 7.0\Samples\MFC\MDI\MainFrm.cpp or C:\Program Files\Softelvdm\SftTabs DLL 7.0\Samples\MFC\MDI\MainFrm.cpp (on 32-bit Windows versions). [Full sample source — MDI Sample (C++) (423 lines) →](https://softelvdm.com/Vault/Softelvdm.com/llms/SftTabs-DLL-7.0-samples.txt) ## SDI Sample (C++) *Source: https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/sample_cpp_sdi* This sample illustrates an SDI application using a tab control on its document view. The source code is located at C:\Program Files (x86)\Softelvdm\SftTabs DLL 7.0\Samples\MFC\SDI\SmplView.cpp or C:\Program Files\Softelvdm\SftTabs DLL 7.0\Samples\MFC\SDI\SmplView.cpp (on 32-bit Windows versions). [Full sample source — SDI Sample (C++) (472 lines) →](https://softelvdm.com/Vault/Softelvdm.com/llms/SftTabs-DLL-7.0-samples.txt) ## Wizard 1 Sample (C++) *Source: https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/sample_cpp_wizard1* This sample illustrates a tabbed dialog with a wizard-style tab control. The source code is located at C:\Program Files (x86)\Softelvdm\SftTabs DLL 7.0\Samples\MFC\Wizard 1\WizDlg.cpp or C:\Program Files\Softelvdm\SftTabs DLL 7.0\Samples\MFC\Wizard 1\WizDlg.cpp (on 32-bit Windows versions). [Full sample source — Wizard 1 Sample (C++) (446 lines) →](https://softelvdm.com/Vault/Softelvdm.com/llms/SftTabs-DLL-7.0-samples.txt) ## Wizard 2 Sample (C++) *Source: https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/sample_cpp_wizard2* This sample illustrates a tabbed dialog with a wizard-style tab control. The source code is located at C:\Program Files (x86)\Softelvdm\SftTabs DLL 7.0\Samples\MFC\Wizard 2\WizDlg.cpp or C:\Program Files\Softelvdm\SftTabs DLL 7.0\Samples\MFC\Wizard 2\WizDlg.cpp (on 32-bit Windows versions). [Full sample source — Wizard 2 Sample (C++) (343 lines) →](https://softelvdm.com/Vault/Softelvdm.com/llms/SftTabs-DLL-7.0-samples.txt) ## SftTabs/DLL Wizard *Source: https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/g_wizarddesign* During the installation of SftTabs/DLL, an icon for the application *Wizard* is installed in the program group *SftTabs DLL 7.0*. ![SftTabs/DLL Wizard](https://softelvdm.com/Vault/Softelvdm.com/docx/SftTabs%20DLL%207.0/image/wiz/wizard.gif) This application can be used to generate most of the source code needed to create and initialize a tab control in a dialog or a window. It honors most SftTabs/DLL attributes and should be used at design-time to build the necessary tab control initialization code. The SftTabs/DLL Wizard application is used to design a tab control layout and to populate it with tab labels. You design the desired look on the property pages (on the right hand side) and immediately see it reflected in the sample tab control (on the left side); the sample window can be resized to adjust the size of the control. Once the desired layout has been achieved, the run-time source code used to create and initialize the tab control can be generated for C and C++/MFC by clicking on the corresponding tab. The generated source code contains step by step instructions on how to incorporate it into an application. ## SftTabs/DLL Wizard Help *Source: https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/idh_wizardhelp* ### SftTabs/DLL Wizard > **Note:** This help topic appears every time the [SftTabs/DLL Wizard](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/g_wizarddesign) is started. You can turn it off using the Wizard's "Help, Start Wizard Help" menu command. The SftTabs/DLL Wizard is used to define a new tab control layout or to edit an existing one. The definitions are saved in tab definition files with the extension *.TAB. Visit each property page (on the right hand side) and set the desired properties. These will immediately be reflected in the sample tab control (on the left side). The sample window can be resized to adjust the size of the control. The most important tab is the **"Class Info"** tab. Define the C or C++ information as it is used in your application. Once you have filled in this information correctly, click on the **C** or **C++/MFC** tab. The source code displayed can now be copied into your application. Make sure to read the step-by-step instructions in the source code. This source code usually requires only minimal changes to work in your application. You will have to provide your own bitmaps, but the other initialization information can be used as-is. Once you have defined your tab control settings, you can save the TAB file (for later editing). If you make modifications to your tab control definition, you will of course have to again copy the generated source code (or portions). If you want detailed information about a specific setting that can be changed by the SftTabs/DLL Wizard, make the control for the setting the current control by moving the input focus and hit F1. ## SftTabs/DLL Wizard - Design Pages *Source: https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/idh_control_page* The [SftTabs/DLL Wizard](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/g_wizarddesign) uses several design property pages - **Style**, **Tabs**, **[ToolTips](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/g_tooltips)**, **Fonts**, **Colors**, **Class Info**, **Events** and **Control** - to design a tab control layout and populate it with tabs. Settings made on these pages are reflected immediately in the sample tab control. When the desired layout has been achieved, the C and C++/MFC tabs produce the source code needed to create and initialize the tab control in an application. For detailed information about an individual setting, move the input focus to that control and hit F1. ### Style The Style page controls the overall appearance of the tab control - the basic tab style, scrolling, the Minimize/Restore/Close buttons, tab and row layout, borders and label rendering. | Label | Description | | --- | --- | | Style | Selects the basic tab control style. | | Use exact window region | Uses an exact window region so the parent's [background](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/g_background) shows through the unused parts of a non-rectangular tab shape. | | Use themes | Draws the control using the current Windows visual theme. | | Scrollable tabs | Enables scrollable tabs (restricted to a single row); some styles do not support scrolling. | | [Scroll buttons](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/pop_scrollbutton) | Options to hide the scroll buttons, hide them only when all tabs are visible, place them on the left or top, make them full tab size, or show a ragged edge for a truncated tab. | | Button style / alignment (scroll) | Selects the button style and alignment used for the scroll buttons. | | Minimize / Restore / Close buttons | Selects which of the Minimize, Restore and Close buttons are available on the control. | | Enable buttons | Enables or disables the individual Minimize, Restore and Close buttons. | | Close button generates [WM_CLOSE](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/i_windows_messages) | The Close button posts a WM_CLOSE message instead of sending a close notification. | | Full size buttons | Makes the Minimize/Restore/Close buttons as large as a tab. | | Alignment (close buttons) | Selects the alignment of the Minimize/Restore/Close buttons. | | Fixed width tabs | Gives every tab the same width (or height for vertical rows) instead of sizing each tab to its label. | | Fill rows completely | Fills each [tab row](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/pop_tabrows) completely to minimize margins. | | Bold font for [active tab](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/pop_activetab) | Draws the active tab's label in bold. | | Tabs per row / Tab rows | Sets the number of tabs per row and the number of rows. | | Allow all tabs to be inactive | Allows every tab to be deactivated at the same time. | | Row indentation | Uses the style's automatic row indentation or an explicit pixel offset for a cascading multi-row layout. | | Margins | Sets the left and right margins, or uses the style's built-in margin. | | 3D border outline | Adjusts the control's colors for a 3D outline; turn it off on backgrounds unsuitable for 3D rendering. | | Provide [client area](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/pop_clientarea) | Provides a client area for pages and child controls (not supported by all styles). | | Multiline labels | Allows tab labels to contain line breaks. | | Use drawing callback | Paints selected tabs through a drawing callback and generates the matching callback sample code. | | Drop label if it doesn't fit | Omits a tab's label when it does not fit (best used with graphic tabs). | | Show '...' if text truncated | Appends a trailing ellipsis to truncated label text. | | Enable ToolTips | Displays the ToolTips defined on the ToolTips page. | | Enable flyby highlights | Highlights a tab's label when the mouse cursor moves over it. | | Show focus rectangle | Draws a focus rectangle around the active tab's label when the control has the input focus. | ### Tabs The Tabs page edits the list of individual tabs and their per-tab properties, and adds, inserts or deletes tabs. | Label | Description | | --- | --- | | Tab label | Click a tab label to edit its text; click elsewhere or press Return to finish. | | Enabled / Hidden | Sets each tab's status - enabled or disabled, and visible or fully hidden. | | Sample picture / alignment | Assigns a sample tab graphic and its alignment (an application supplies its own images at run time). | | Active colors | The foreground and background colors (or a background gradient) used when the tab is active. | | Inactive colors | The foreground and background colors (or a background gradient) used when the tab is not active, plus the flyby highlight color. | | Client-area color | The client-area background color (or gradient) associated with the tab. | | Use client-area color | Fills the frames of the rows behind the current row with each tab's client-area color. | | Add / Insert / Delete | Adds a tab at the end, inserts a tab after the selected tab, or deletes the selected tab. | | Copy colors | Copies a tab's active colors to its inactive colors, for the selected tab or for all tabs. | ### ToolTips The ToolTips page enables and edits the ToolTip text for the tabs and buttons. | Label | Description | | --- | --- | | Enable ToolTips | Enables display of ToolTips for the tabs and for the scroll and Minimize/Restore/Close buttons. | | ToolTips grid | Lists the ToolTip text for each tab and button; click an entry in the ToolTip Text column to change it. | ### Fonts The Fonts page selects the font used throughout the tab control. | Label | Description | | --- | --- | | Font | Selects the single font used for all tabs. | ### Colors The Colors page defines the named control-area colors and the background bitmaps for the tab control. | Label | Description | | --- | --- | | Control area / Color | Select a control area, then view or change its color. | | Inside / Outside background | Assigns or clears the inside and outside background bitmaps (illustrative only - the generated code declares them but does not load them). | ### Class Info Based on the information entered on this page, the generated source code is adjusted to reflect the following settings: | Label | Description | | --- | --- | | C variable name | The variable that holds the tab control's window handle in a C application. This field is not used for C++ applications. | | C++ object name | The variable name for the C++ tab control object ([CSftTabs](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/i_cppclasses)) in the parent window. This field is not used for C applications. | | Control ID | The ID used for the control in a DIALOG resource and as its child-window ID. | | Tabbed dialog or window | Selects a tabbed dialog (CSftTabsDialog / CSftTabsPage) or a tabbed window (CSftTabsWindowSheet / CSftTabsWindowPage). | | Dialog/resource or run time | Selects whether the control lives in a dialog or resource-based window, or is created at run time. | | Sheet class / base class | The class name (and its base class) for the main window that contains the tab control. | | Page class / base class | The class name (and its base class) used for the generated tab pages. | ### Events All notifications generated by the tab control are displayed in a list as they occur. Interact with the sample tab control to populate the list. This is useful for understanding which notifications fire and when. The **Clear All** button clears the list. ### Control The Control tab provides an immediate, read-only view of the [SFTTABS_CONTROL](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/struct_sfttabs_control) structure for the current tab control. Every member is shown with the value taken from the sample tab control, and the display updates as changes are made on the other pages. ## C, C++/MFC - Generated Source Code *Source: https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/idh_edit_page* The source code generated using the C or C++/MFC tabs can be used to implement a tab control in an application. Usually the source code can be used with just minor modifications. By following the comments in this source code, the relevant sections can be copied to your application. Use the *Edit*, *Find* menu command to locate text. ## Using SftTabs/DLL *Source: https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/g_usingsfttabs* Depending on the programming language used, the steps necessary to add a tab control to an application differ somewhat, but the following steps outline the basic method: First, a tab control is added to a dialog using a resource editor (see section [Creating a Dialog Resource](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/g_vc)). When the dialog is later used in an application, the tab control is automatically created and can be accessed using the supplied API. A tab control can also be created outside of a dialog. This is documented in the language specific programming sections [Using C](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/g_usingc) and [Using C++/MFC](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/g_usingcpp). Once the tab control has been created, the API functions documented in section C, C++ API can be used to add tabs, define attributes, respond to events, etc. The following [samples](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/g_samples) create a very minimal tab control with three tabs as pictured below. This example can easily be extended by adding a few calls to define tab bitmaps or icons and change other tab components to alter the appearance of the tab control. #### Sample Code [Using SftTabs/DLL - C Sample](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/g_usingsfttabsc) [Using SftTabs/DLL - C++/MFC Sample](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/g_usingsfttabscppmfc) ## Using SftTabs/DLL - C Sample *Source: https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/g_usingsfttabsc* The following code has been created using the [SftTabs/DLL Wizard](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/g_wizarddesign) application: ``` static const SFTTABS_CONTROL CtlInit = { SFTTABSSTYLE_MODERN_I, /* tab style */ 1, /* number of rows */ 0, /* number of tabs per row (if fFixed) */ 0, /* width of left margin */ 0, /* width of right margin */ FALSE, /* same width for all tabs */ TRUE, /* Client area wanted */ FALSE, /* allow multiline label text */ TRUE, /* use with dialog */ FALSE, /* use specified background color only for text */ FALSE, /* scrollable tabs */ FALSE, /* hide scroll buttons */ FALSE, /* bold font for active tab wanted */ FALSE, /* fill rows completely */ NULL, /* scroll button bitmap */ NULL, /* Dialog data associated with active tab */ NULL, /* Dialog window handle associated with active tab */ NULL, /* Frame, used as client area */ TRUE, /* Tooltips wanted */ FALSE, /* drop text if it doesn't fit */ FALSE, /* conditional scroll buttons */ BMBUTTONSTYLE_THEME_SCROLL2, /* scroll button style */ TRUE, /* display ... if truncated */ TRUE, /* Flyby highlighting */ TRUE, /* use client area colors in partially obscured frames */ FALSE, /* scroll buttons on left side */ -1, /* row indentation */ FALSE, /* don't show truncated pattern for clipped tab */ FALSE, /* full size scroll buttons */ TRUE, /* use themes */ FALSE, /* use exact window region */ FALSE, /* always show prefix _ */ 0,0,0,0, /* animation values */ NULL, /* disabled button bitmap */ TRUE, /* focus rectangle if the control has i/p focus */ FALSE, /* TRUE if Close button wanted */ FALSE, /* TRUE if Close button disabled */ TRUE, /* TRUE if WM_CLOSE message wanted */ FALSE, /* TRUE if Minimize, Restore, Close buttons are full size */ SFTTABS_BUTTON_NEAR, /* scroll button alignment */ SFTTABS_BUTTON_NEAR, /* Minimize, Restore, Close button alignment */ FALSE, /* TRUE if Minimize button wanted */ FALSE, /* TRUE if Minimize button disabled */ FALSE, /* TRUE if Restore button wanted */ FALSE, /* TRUE if Restore button disabled */ NULL, /* Close, Minimize, Restore button bitmap */ NULL, /* Close, Minimize, Restore disabled button bitmap */ TEXT("Scroll Left/Up"), /* scroll left button tooltip */ TEXT("Scroll Right/Down"), /* scroll button tooltip */ TEXT("Close"), /* Close button tooltip */ TEXT("Minimize"), /* Minimize button tooltip */ TEXT("Restore"), /* Restore button tooltip */ 0, /* custom modifications */ 0, /* forced height/width depending on tab style - 0 to ignore */ FALSE, /* switch tabs on button release (or down if FALSE) */ FALSE, /* Rendering compatible with pre-6.0 */ FALSE, /* don't display clientarea border - select styles only */ }; static const SFTTABS_TAB Tab0 = { /*&One */ SFTTABS_NOCOLOR, SFTTABS_NOCOLOR, /* background, foreground color */ SFTTABS_NOCOLOR, SFTTABS_NOCOLOR, /* background, foreground color (when selected) */ { SFTTABS_GRAPH_NONE, 0 }, /* location */ TRUE, /* enabled/disabled */ 0, /* userdata */ (SFTTABS_DWORD_PTR) 0, /* Page_callback */ /* user supplied tab callback */ NULL, /* reserved */ SFTTABS_NOCOLOR, /* Flyby foreground color */ SFTTABS_NOCOLOR, /* Client area background color */ 0,0,0,0, /* animation values */ NULL, /* tab-specific ImageList handle*/ FALSE, /* hidden tab */ SFTTABS_NOCOLOR, /* gradient fill background color */ SFTTABS_NOCOLOR, SFTTABS_NOCOLOR, /* gradient fill background color, active tab */ SFTTABS_NOCOLOR, SFTTABS_NOCOLOR, /* gradient fill client area color */ SFTTABS_NOCOLOR, }; static const SFTTABS_TAB Tab1 = { /*&Two */ SFTTABS_NOCOLOR, SFTTABS_NOCOLOR, /* background, foreground color */ SFTTABS_NOCOLOR, SFTTABS_NOCOLOR, /* background, foreground color (when selected) */ { SFTTABS_GRAPH_NONE, 0 }, /* location */ TRUE, /* enabled/disabled */ 0, /* userdata */ (SFTTABS_DWORD_PTR) 0, /* Page_callback */ /* user supplied tab callback */ NULL, /* reserved */ SFTTABS_NOCOLOR, /* Flyby foreground color */ SFTTABS_NOCOLOR, /* Client area background color */ 0,0,0,0, /* animation values */ NULL, /* tab-specific ImageList handle*/ FALSE, /* hidden tab */ SFTTABS_NOCOLOR, /* gradient fill background color */ SFTTABS_NOCOLOR, SFTTABS_NOCOLOR, /* gradient fill background color, active tab */ SFTTABS_NOCOLOR, SFTTABS_NOCOLOR, /* gradient fill client area color */ SFTTABS_NOCOLOR, }; static const SFTTABS_TAB Tab2 = { /*T&hree */ SFTTABS_NOCOLOR, SFTTABS_NOCOLOR, /* background, foreground color */ SFTTABS_NOCOLOR, SFTTABS_NOCOLOR, /* background, foreground color (when selected) */ { SFTTABS_GRAPH_NONE, 0 }, /* location */ TRUE, /* enabled/disabled */ 0, /* userdata */ (SFTTABS_DWORD_PTR) 0, /* Page_callback */ /* user supplied tab callback */ NULL, /* reserved */ SFTTABS_NOCOLOR, /* Flyby foreground color */ SFTTABS_NOCOLOR, /* Client area background color */ 0,0,0,0, /* animation values */ NULL, /* tab-specific ImageList handle*/ FALSE, /* hidden tab */ SFTTABS_NOCOLOR, /* gradient fill background color */ SFTTABS_NOCOLOR, SFTTABS_NOCOLOR, /* gradient fill background color, active tab */ SFTTABS_NOCOLOR, SFTTABS_NOCOLOR, /* gradient fill client area color */ SFTTABS_NOCOLOR, }; static const SFTTABS_TAB Tab3 = { /*&Four */ SFTTABS_NOCOLOR, SFTTABS_NOCOLOR, /* background, foreground color */ SFTTABS_NOCOLOR, SFTTABS_NOCOLOR, /* background, foreground color (when selected) */ { SFTTABS_GRAPH_NONE, 0 }, /* location */ TRUE, /* enabled/disabled */ 0, /* userdata */ (SFTTABS_DWORD_PTR) 0, /* Page_callback */ /* user supplied tab callback */ NULL, /* reserved */ SFTTABS_NOCOLOR, /* Flyby foreground color */ SFTTABS_NOCOLOR, /* Client area background color */ 0,0,0,0, /* animation values */ NULL, /* tab-specific ImageList handle*/ FALSE, /* hidden tab */ SFTTABS_NOCOLOR, /* gradient fill background color */ SFTTABS_NOCOLOR, SFTTABS_NOCOLOR, /* gradient fill background color, active tab */ SFTTABS_NOCOLOR, SFTTABS_NOCOLOR, /* gradient fill client area color */ SFTTABS_NOCOLOR, }; static const SFTTABS_TAB Tab4 = { /*F&ive */ SFTTABS_NOCOLOR, SFTTABS_NOCOLOR, /* background, foreground color */ SFTTABS_NOCOLOR, SFTTABS_NOCOLOR, /* background, foreground color (when selected) */ { SFTTABS_GRAPH_NONE, 0 }, /* location */ TRUE, /* enabled/disabled */ 0, /* userdata */ (SFTTABS_DWORD_PTR) 0, /* Page_callback */ /* user supplied tab callback */ NULL, /* reserved */ SFTTABS_NOCOLOR, /* Flyby foreground color */ SFTTABS_NOCOLOR, /* Client area background color */ 0,0,0,0, /* animation values */ NULL, /* tab-specific ImageList handle*/ FALSE, /* hidden tab */ SFTTABS_NOCOLOR, /* gradient fill background color */ SFTTABS_NOCOLOR, SFTTABS_NOCOLOR, /* gradient fill background color, active tab */ SFTTABS_NOCOLOR, SFTTABS_NOCOLOR, /* gradient fill client area color */ SFTTABS_NOCOLOR, }; static const SFTTABS_TAB Tab5 = { /*&Six */ SFTTABS_NOCOLOR, SFTTABS_NOCOLOR, /* background, foreground color */ SFTTABS_NOCOLOR, SFTTABS_NOCOLOR, /* background, foreground color (when selected) */ { SFTTABS_GRAPH_NONE, 0 }, /* location */ TRUE, /* enabled/disabled */ 0, /* userdata */ (SFTTABS_DWORD_PTR) 0, /* Page_callback */ /* user supplied tab callback */ NULL, /* reserved */ SFTTABS_NOCOLOR, /* Flyby foreground color */ SFTTABS_NOCOLOR, /* Client area background color */ 0,0,0,0, /* animation values */ NULL, /* tab-specific ImageList handle*/ FALSE, /* hidden tab */ SFTTABS_NOCOLOR, /* gradient fill background color */ SFTTABS_NOCOLOR, SFTTABS_NOCOLOR, /* gradient fill background color, active tab */ SFTTABS_NOCOLOR, SFTTABS_NOCOLOR, /* gradient fill client area color */ SFTTABS_NOCOLOR, }; /* Replace "Page_callback" with the names of the actual */ /* callback routines once they have been implemented and */ /* remove the comment marks. */ /*- Initialize Tab Control -----------------------------------------------------*/ /* Usually added to the WM_INITDIALOG or WM_CREATE message handler of the tab */ /* control's parent window (i.e., the tabbed dialog) */ /*------------------------------------------------------------------------------*/ int index; HWND hwndTab; hwndTab = GetDlgItem(hwndParent, IDC_TAB); /* get the window handle */ /* Initialization is faster if we set redraw off */ SendMessage(hwndTab, WM_SETREDRAW, (WPARAM)FALSE, 0); /* Set the tab control font */ SendMessage(hwndTab, WM_SETFONT, (WPARAM)m_hFont, MAKELPARAM(TRUE, 0)); /* Tab control font */ /* We are using new features */ SftTabs_SetVersion(hwndTab, SFTTABS_7_0); index = SftTabs_AddTab(hwndTab, TEXT("&One")); SftTabs_SetTabInfo(hwndTab, index, &Tab0); index = SftTabs_AddTab(hwndTab, TEXT("&Two")); SftTabs_SetTabInfo(hwndTab, index, &Tab1); index = SftTabs_AddTab(hwndTab, TEXT("T&hree")); SftTabs_SetTabInfo(hwndTab, index, &Tab2); index = SftTabs_AddTab(hwndTab, TEXT("&Four")); SftTabs_SetTabInfo(hwndTab, index, &Tab3); index = SftTabs_AddTab(hwndTab, TEXT("F&ive")); SftTabs_SetTabInfo(hwndTab, index, &Tab4); index = SftTabs_AddTab(hwndTab, TEXT("&Six")); SftTabs_SetTabInfo(hwndTab, index, &Tab5); SftTabs_SetControlInfo(hwndTab, &CtlInit); SftTabs_SetCurrentTab(hwndTab, 0); /* Make the first tab the current tab */ // Make sure to turn redraw back on SendMessage(hwndTab, WM_SETREDRAW, (WPARAM)TRUE, 0); InvalidateRect(hwndTab, NULL, TRUE); // Activate current page. SftTabs_ActivatePage(hwndParent, hwndTab, NULL, TRUE); // Mark the window as a main, tabbed dialog (so accel. keys work) by registering it. // Register the dialog AFTER activating the current page SftTabs_RegisterDialog(hwndParent); return FALSE; // WM_INITDIALOG, input focus already set /*------------------------------------------------------------------------------*/ /* This sample code can be used for cleanup processing. */ /* This code is usually used in a WM_DESTROY message handler of the parent */ /* dialog or window. */ /*------------------------------------------------------------------------------*/ /* Delete the font used for the tab control. */ DeleteObject(m_hFont); /* Item font */ /* Unregister, or the window properties used won't be removed */ SftTabs_UnregisterDialog(hwndParent); /* destroy all pages */ SftTabs_Destroy(hwndParent, GetDlgItem(hwndParent, IDC_TAB)); /*------------------------------------------------------------------------------*/ /* This is sample code that responds to the tab switching notifications sent by */ /* the tab control to the parent window using a WM_COMMAND message. The */ /* appropriate SftTabs/DLL API is called to switch between pages. */ /* This code implements a suitable WM_COMMAND message handler. */ /*------------------------------------------------------------------------------*/ case WM_COMMAND: { HWND hwndCtl = (HWND) lParam; int id = LOWORD(wParam); int code = HIWORD(wParam); if (hwndCtl) { switch (id) { case IDC_TAB: switch (code) { case SFTTABSN_SWITCHING:// we're about to switch away from // the current page. If you need to know what the new // page will be, use SftTabs_GetNextTab(hwndCtl). if (!SftTabs_DeactivatePage(hwndParent, hwndCtl)) // couldn't deactivate current page, so don't switch SendMessage(hwndCtl, WM_CANCELMODE, 0, 0); break; case SFTTABSN_SWITCHED:// we switched to a new page SftTabs_ActivatePage(hwndParent, hwndCtl, NULL, FALSE); break; } break; case IDOK: case IDCANCEL: if (code == BN_CLICKED) SendMessage(hwndParent, WM_COMMAND, id, 0); break; } } else { switch (id) { case IDOK: // The currently active page will be called with a // WM_QUERYENDSESSION/SftTabs_GetEndPageMessage message to determine // whether it can be closed if (SftTabs_ClosePossible(hwndParent, GetDlgItem(hwndParent, IDC_TAB))) EndDialog(hwndParent, TRUE); break; case IDCANCEL: EndDialog(hwndParent, FALSE); break; // The above assumes that this is a modal dialog. If it is a modeless // don't use EndDialog, use DestroyWindow instead. } } break; } /*------------------------------------------------------------------------------*/ /* This sample code page callback routine can be used to create a page callback */ /* for each page attached to a tab. The SFTTABS_TAB structure of each tab */ /* points to a callback routine so the page can be created and destroyed by */ /* the application-provided callback. */ /*------------------------------------------------------------------------------*/ /* This first form of the callback routine destroys the page everytime the user */ /* switches away from the page. If you would like to preserve the page and */ /* just hide it instead, use the second form of the callback below. */ HWND CALLBACK Page_Callback(BOOL fCreate, HWND hwndOwner, HWND hwndPage, HWND hwndTab) { if (fCreate) { // creating a new page if (hwndPage) { // already created, we could do some initialization here. // this will be called every time the page becomes active // The WM_CREATE/WM_INITDIALOG/WM_DESTROY messages are also sent to // the page and could be used to determine activation/deactivation. // of the page. // optional, set the main window's title to the window title defined for this page SftTabs_CopyWindowTitle(hwndPage, hwndOwner); return NULL; } else { // Create the page. // You can create and initialize any type of window here, not just dialogs. // Use CreateWindow to create other windows. Don't specify WS_VISIBLE, but // make sure you use WS_TABSTOP. // When creating a non-dialog window, make sure to call SftTabs_SetPageActive // after the page has been created. HWND hwnd = CreateDialogParam(g_hInst, MAKEINTRESOURCE(IDD_your_dialog_ID), hwndOwner, (DLGPROC)Page_yourDialogProc, (LPARAM)(UINT_PTR)hwndTab);// pass tab control as data // optional, set the main window's title to the window title defined for this page SftTabs_CopyWindowTitle(hwnd, hwndOwner); return hwnd; } } else { // destroying page // We'll always destroy this page (to save resources) DestroyWindow(hwndPage); return NULL; } } /* This second form of the callback routine hides the page when the user */ /* switches away from the page. If you would like to destroy the page instead, */ /* use the first form of the callback above. */ HWND CALLBACK Page_Callback(BOOL fCreate, HWND hwndOwner, HWND hwndPage, HWND hwndTab) { if (fCreate) { // creating a new page if (hwndPage) { // already created, we could do some initialization here. // this will be called every time the page becomes active. // The WM_SHOWWINDOW message is also sent to the page and could // be used to determine activation/deactivation of the page. // optional, set the main window's title to the window title defined for this page SftTabs_CopyWindowTitle(hwndPage, hwndOwner); return NULL; // return NULL, ignored } else { // Create the page. // You can create and initialize any type of window here, not just dialogs. // Use CreateWindow to create other windows. Don't specify WS_VISIBLE, but // make sure you use WS_TABSTOP. // When creating a non-dialog window, make sure to call SftTabs_SetPageActive // after the page has been created. HWND hwnd = CreateDialogParam(g_hInst, MAKEINTRESOURCE(IDD_your_dialog_ID), hwndOwner, (DLGPROC)Page_yourDialogProc, (LPARAM)(UINT_PTR)hwndTab);// pass tab control as data // optional, set the main window's title to the window title defined for this page SftTabs_CopyWindowTitle(hwnd, hwndOwner); return hwnd; } } else { // destroying page if (hwndOwner) // - because we're switching away return hwndPage; // keep the window handle, don't destroy it else { // - because we're closing the main dialog DestroyWindow(hwndPage); return NULL; } } } /*------------------------------------------------------------------------------*/ /* Use the following sample code as the framework for your page. It is a */ /* standard dialog procedure with just minor modifications. */ /*------------------------------------------------------------------------------*/ BOOL CALLBACK Page_yourDialogProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) { LRESULT lRes; switch (msg) { case WM_INITDIALOG: // ... your initialization code // Initialize page SftTabs_SetPageActive(hwndDlg, (HWND) lParam, NULL); // The following insures that the focus is set to the correct control. return !SftTabs_IsRegisteredDialog(GetParent(hwndDlg)); // case WM_other_messages: // ... your other messages go here break; } // Any message your dialog procedure doesn't handle, must come here if (SftTabs_HandleDialogMessage(hwndDlg, msg, wParam, lParam)) return TRUE; if (SftTabs_TransparentControls(hwndDlg, NULL, &msg, &wParam, &lParam, &lRes, 0, 0)) return (BOOL) lRes; return FALSE; // Message not handled by dialog proc } /*------------------------------------------------------------------------------*/ /* Add the following sample code at the end of your main window's or dialog's */ /* procedure to handle messages that may be of interest to SftTabs/DLL. */ /*------------------------------------------------------------------------------*/ // Call SftTabs/DLL to let it handle some messages (mostly for keyboard accel. keys) if (SftTabs_HandleDialogMessage(hwndDlg, msg, wParam, lParam)) return TRUE; ``` ## Using SftTabs/DLL - C++/MFC Sample *Source: https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/g_usingsfttabscppmfc* The following code has been created using the [SftTabs/DLL Wizard](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/g_wizarddesign) application: ``` /*- Tab Control Initialization Data --------------------------------------------*/ static const SFTTABS_CONTROL CtlInit = { SFTTABSSTYLE_MODERN_I, /* tab style */ 1, /* number of rows */ 0, /* number of tabs per row (if fFixed) */ 0, /* width of left margin */ 0, /* width of right margin */ FALSE, /* same width for all tabs */ TRUE, /* Client area wanted */ FALSE, /* allow multiline label text */ TRUE, /* use with dialog */ FALSE, /* use specified background color only for text */ FALSE, /* scrollable tabs */ FALSE, /* hide scroll buttons */ FALSE, /* bold font for active tab wanted */ FALSE, /* fill rows completely */ NULL, /* scroll button bitmap */ NULL, /* Dialog data associated with active tab */ NULL, /* Dialog window handle associated with active tab */ NULL, /* Frame, used as client area */ TRUE, /* Tooltips wanted */ FALSE, /* drop text if it doesn't fit */ FALSE, /* conditional scroll buttons */ BMBUTTONSTYLE_THEME_SCROLL2, /* scroll button style */ TRUE, /* display ... if truncated */ TRUE, /* Flyby highlighting */ TRUE, /* use client area colors in partially obscured frames */ FALSE, /* scroll buttons on left side */ -1, /* row indentation */ FALSE, /* don't show truncated pattern for clipped tab */ FALSE, /* full size scroll buttons */ TRUE, /* use themes */ FALSE, /* use exact window region */ FALSE, /* always show prefix _ */ 0,0,0,0, /* animation values */ NULL, /* disabled button bitmap */ TRUE, /* focus rectangle if the control has i/p focus */ FALSE, /* TRUE if Close button wanted */ FALSE, /* TRUE if Close button disabled */ TRUE, /* TRUE if WM_CLOSE message wanted */ FALSE, /* TRUE if Minimize, Restore, Close buttons are full size */ SFTTABS_BUTTON_NEAR, /* scroll button alignment */ SFTTABS_BUTTON_NEAR, /* Minimize, Restore, Close button alignment */ FALSE, /* TRUE if Minimize button wanted */ FALSE, /* TRUE if Minimize button disabled */ FALSE, /* TRUE if Restore button wanted */ FALSE, /* TRUE if Restore button disabled */ NULL, /* Close, Minimize, Restore button bitmap */ NULL, /* Close, Minimize, Restore disabled button bitmap */ TEXT("Scroll Left/Up"), /* scroll left button tooltip */ TEXT("Scroll Right/Down"), /* scroll button tooltip */ TEXT("Close"), /* Close button tooltip */ TEXT("Minimize"), /* Minimize button tooltip */ TEXT("Restore"), /* Restore button tooltip */ 0, /* custom modifications */ 0, /* forced height/width depending on tab style - 0 to ignore */ FALSE, /* switch tabs on button release (or down if FALSE) */ FALSE, /* Rendering compatible with pre-6.0 */ FALSE, /* don't display clientarea border - select styles only */ }; static const SFTTABS_TAB Tab0 = { /*&One */ SFTTABS_NOCOLOR, SFTTABS_NOCOLOR, /* background, foreground color */ SFTTABS_NOCOLOR, SFTTABS_NOCOLOR, /* background, foreground color (when selected) */ { SFTTABS_GRAPH_NONE, 0 }, /* location */ TRUE, /* enabled/disabled */ 0, /* userdata */ 0, /* reserved */ NULL, /* reserved */ SFTTABS_NOCOLOR, /* Flyby foreground color */ SFTTABS_NOCOLOR, /* Client area background color */ 0,0,0,0, /* animation values */ NULL, /* tab-specific ImageList handle*/ FALSE, /* hidden tab */ SFTTABS_NOCOLOR, /* gradient fill background color */ SFTTABS_NOCOLOR, SFTTABS_NOCOLOR, /* gradient fill background color, active tab */ SFTTABS_NOCOLOR, SFTTABS_NOCOLOR, /* gradient fill client area color */ SFTTABS_NOCOLOR, }; static const SFTTABS_TAB Tab1 = { /*&Two */ SFTTABS_NOCOLOR, SFTTABS_NOCOLOR, /* background, foreground color */ SFTTABS_NOCOLOR, SFTTABS_NOCOLOR, /* background, foreground color (when selected) */ { SFTTABS_GRAPH_NONE, 0 }, /* location */ TRUE, /* enabled/disabled */ 0, /* userdata */ 0, /* reserved */ NULL, /* reserved */ SFTTABS_NOCOLOR, /* Flyby foreground color */ SFTTABS_NOCOLOR, /* Client area background color */ 0,0,0,0, /* animation values */ NULL, /* tab-specific ImageList handle*/ FALSE, /* hidden tab */ SFTTABS_NOCOLOR, /* gradient fill background color */ SFTTABS_NOCOLOR, SFTTABS_NOCOLOR, /* gradient fill background color, active tab */ SFTTABS_NOCOLOR, SFTTABS_NOCOLOR, /* gradient fill client area color */ SFTTABS_NOCOLOR, }; static const SFTTABS_TAB Tab2 = { /*T&hree */ SFTTABS_NOCOLOR, SFTTABS_NOCOLOR, /* background, foreground color */ SFTTABS_NOCOLOR, SFTTABS_NOCOLOR, /* background, foreground color (when selected) */ { SFTTABS_GRAPH_NONE, 0 }, /* location */ TRUE, /* enabled/disabled */ 0, /* userdata */ 0, /* reserved */ NULL, /* reserved */ SFTTABS_NOCOLOR, /* Flyby foreground color */ SFTTABS_NOCOLOR, /* Client area background color */ 0,0,0,0, /* animation values */ NULL, /* tab-specific ImageList handle*/ FALSE, /* hidden tab */ SFTTABS_NOCOLOR, /* gradient fill background color */ SFTTABS_NOCOLOR, SFTTABS_NOCOLOR, /* gradient fill background color, active tab */ SFTTABS_NOCOLOR, SFTTABS_NOCOLOR, /* gradient fill client area color */ SFTTABS_NOCOLOR, }; static const SFTTABS_TAB Tab3 = { /*&Four */ SFTTABS_NOCOLOR, SFTTABS_NOCOLOR, /* background, foreground color */ SFTTABS_NOCOLOR, SFTTABS_NOCOLOR, /* background, foreground color (when selected) */ { SFTTABS_GRAPH_NONE, 0 }, /* location */ TRUE, /* enabled/disabled */ 0, /* userdata */ 0, /* reserved */ NULL, /* reserved */ SFTTABS_NOCOLOR, /* Flyby foreground color */ SFTTABS_NOCOLOR, /* Client area background color */ 0,0,0,0, /* animation values */ NULL, /* tab-specific ImageList handle*/ FALSE, /* hidden tab */ SFTTABS_NOCOLOR, /* gradient fill background color */ SFTTABS_NOCOLOR, SFTTABS_NOCOLOR, /* gradient fill background color, active tab */ SFTTABS_NOCOLOR, SFTTABS_NOCOLOR, /* gradient fill client area color */ SFTTABS_NOCOLOR, }; static const SFTTABS_TAB Tab4 = { /*F&ive */ SFTTABS_NOCOLOR, SFTTABS_NOCOLOR, /* background, foreground color */ SFTTABS_NOCOLOR, SFTTABS_NOCOLOR, /* background, foreground color (when selected) */ { SFTTABS_GRAPH_NONE, 0 }, /* location */ TRUE, /* enabled/disabled */ 0, /* userdata */ 0, /* reserved */ NULL, /* reserved */ SFTTABS_NOCOLOR, /* Flyby foreground color */ SFTTABS_NOCOLOR, /* Client area background color */ 0,0,0,0, /* animation values */ NULL, /* tab-specific ImageList handle*/ FALSE, /* hidden tab */ SFTTABS_NOCOLOR, /* gradient fill background color */ SFTTABS_NOCOLOR, SFTTABS_NOCOLOR, /* gradient fill background color, active tab */ SFTTABS_NOCOLOR, SFTTABS_NOCOLOR, /* gradient fill client area color */ SFTTABS_NOCOLOR, }; static const SFTTABS_TAB Tab5 = { /*&Six */ SFTTABS_NOCOLOR, SFTTABS_NOCOLOR, /* background, foreground color */ SFTTABS_NOCOLOR, SFTTABS_NOCOLOR, /* background, foreground color (when selected) */ { SFTTABS_GRAPH_NONE, 0 }, /* location */ TRUE, /* enabled/disabled */ 0, /* userdata */ 0, /* reserved */ NULL, /* reserved */ SFTTABS_NOCOLOR, /* Flyby foreground color */ SFTTABS_NOCOLOR, /* Client area background color */ 0,0,0,0, /* animation values */ NULL, /* tab-specific ImageList handle*/ FALSE, /* hidden tab */ SFTTABS_NOCOLOR, /* gradient fill background color */ SFTTABS_NOCOLOR, SFTTABS_NOCOLOR, /* gradient fill background color, active tab */ SFTTABS_NOCOLOR, SFTTABS_NOCOLOR, /* gradient fill client area color */ SFTTABS_NOCOLOR, }; /*------------------------------------------------------------------------------*/ /* This sample code can be used to initialize the tab control. */ /* This code is usually used in an OnInitDialog (WM_INITDIALOG), OnCreate */ /* (WM_CREATE) or OnInitialUpdate member function of the tab control's parent */ /* dialog or window. */ /*------------------------------------------------------------------------------*/ int index; /* Associate the tab control created from the dialog */ /* resource with the C++ object. */ m_Tab.SubclassDlgItem(IDC_TAB, this /* parent window */); /* You could use DDX/DDV instead and add the following */ /* line to the DoDataExchange function of the tab */ /* control's parent window (remove the //). */ // DDX_Control(pDX, IDC_TAB, m_Tab); /* Initialization is faster if we set redraw off */ m_Tab.SetRedraw(FALSE); /* Create the font used for the tab control. */ /* Fonts are owned by the application and have to remain */ /* valid as long as the tab control uses the font. */ int height; // Height in pixels HDC hDC; // Device context hDC = ::GetDC(NULL); // Get a device context /* Create the font to be used for the tab control. */ height = MulDiv(8, ::GetDeviceCaps(hDC, LOGPIXELSY), 72); /* Convert point-size to pixels */ m_Font.CreateFont(-height, 0, 0, 0, FW_NORMAL, 0, 0, 0, 0, 0, 0, 0, 0, _T("MS Shell Dlg")); ::ReleaseDC(NULL, hDC); // Release device context m_Tab.SetFont(&m_Font, FALSE); // Set tab control font /* We are using new features */ m_Tab.SetVersion(SFTTABS_7_0); index = m_Tab.AddTab(_T("&One")); m_Tab.SetTabInfo(index, &Tab0); // If you don't want to attach a page to the tab, the following is optional // m_Tab.SetTabDialog(index, new an_object_based_on_CSftTabsPage(this)); // tab page index = m_Tab.AddTab(_T("&Two")); m_Tab.SetTabInfo(index, &Tab1); // If you don't want to attach a page to the tab, the following is optional // m_Tab.SetTabDialog(index, new an_object_based_on_CSftTabsPage(this)); // tab page index = m_Tab.AddTab(_T("T&hree")); m_Tab.SetTabInfo(index, &Tab2); // If you don't want to attach a page to the tab, the following is optional // m_Tab.SetTabDialog(index, new an_object_based_on_CSftTabsPage(this)); // tab page index = m_Tab.AddTab(_T("&Four")); m_Tab.SetTabInfo(index, &Tab3); // If you don't want to attach a page to the tab, the following is optional // m_Tab.SetTabDialog(index, new an_object_based_on_CSftTabsPage(this)); // tab page index = m_Tab.AddTab(_T("F&ive")); m_Tab.SetTabInfo(index, &Tab4); // If you don't want to attach a page to the tab, the following is optional // m_Tab.SetTabDialog(index, new an_object_based_on_CSftTabsPage(this)); // tab page index = m_Tab.AddTab(_T("&Six")); m_Tab.SetTabInfo(index, &Tab5); // If you don't want to attach a page to the tab, the following is optional // m_Tab.SetTabDialog(index, new an_object_based_on_CSftTabsPage(this)); // tab page m_Tab.SetControlInfo(&CtlInit); // Make sure to turn redraw back on m_Tab.SetRedraw(TRUE); m_Tab.InvalidateRect(NULL, TRUE); // If you are not using the sheet/page classes, remove the call to InitializeTabControl. // Initialize tab control. Instead you have to make one of the tabs active using SetCurrentTab. InitializeTabControl(0, &m_Tab, NULL); // return FALSE; if this is a dialog's OnInitDialog member function /*------------------------------------------------------------------------------*/ /* Page Implementation */ /*------------------------------------------------------------------------------*/ // Individual pages are implemented by creating a dialog with a dialog // resource. You can create each page as an object derived from CSftTabsPage // (which is derived from CDialog). // Once you have created the dialog resource, you can use ClassWizard to generate // the implementation of the page object by deriving its new class from // CDialog. Because your object is really derived from CSftTabsPage, // you have to manually edit all references to CDialog and change // them to CSftTabsPage. // When using ClassWizard to add new functions to this new class, make sure to // change any reference to CDialog to use CSftTabsPage instead. ``` ## Building Applications *Source: https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/g_buildingapp* This section describes how to prepare an application using the C or C++ programming language to successfully use SftTabs/DLL. ### Updating Project Settings #### Include Files In order for #include files to be located in the SftTabs/DLL product directory, each project that uses SftTabs/DLL must be updated to search the product directory. The default include directory name is \Program Files (x86)\Softelvdm\SftTabs DLL 7.0\Include unless changed during installation. Make sure to update all configurations (both Debug and Release). Using the *Project*, *Properties...* menu command, the project's Property Pages are accessed so the #include directory search path settings can be modified. ![Additional Include Directory](https://softelvdm.com/Vault/Softelvdm.com/docx/SftTabs%20DLL%207.0/image/usingc1_vsnet.gif) #### Lib Files In addition, the correct [Lib file](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/g_distributing) must be linked using the Link Input settings. The Lib file name depends on the current processor target, according to the table below (see "Adding The Lib File"). The file name must be enclosed in quotes (") if the path contains spaces. Make sure to update all configurations (both Debug and Release). Using the *Project*, *Properties...* menu command, the project's Linker, Input properties are accessed so Additional Dependencies can be modified. ![Link Settings](https://softelvdm.com/Vault/Softelvdm.com/docx/SftTabs%20DLL%207.0/image/usingc2_vsnet.gif) #### Adding The Lib File The application's executable (Exe or Dll) must be linked with the correct Lib file, depending on the target environment (see "Updating Project Settings" above). If a Dll is used, it must be available and accessible at run-time for proper execution. The Dll used at run-time depends on the Lib file used at link time. If static linking is selected, the Dll is not required. All required Lib and Dll files are located in the product directories \Program Files (x86)\Softelvdm\SftTabs DLL 7.0\Lib and \Program Files (x86)\Softelvdm\SftTabs DLL 7.0\Dll. ##### Intel 64-Bit Operating Systems When building applications for 64-bit processors running Windows 10 and above, one of the following Lib files is used: | Lib File | Dll File | Description | | --- | --- | --- | | SftTabs_x64_A_70.lib | SftTabs_x64_A_70.dll | 64-bit Applications using** ANSI** character representation | | SftTabs_x64_A_70_Static.lib | none - see section "Linking Statically" below | 64-bit Applications using** ANSI** character representation | | SftTabs_x64_U_70.lib | SftTabs_x64_U_70.dll | 64-bit Applications using** UNICODE ** character representation | | SftTabs_x64_U_70_Static.lib | none - see section "Linking Statically" below | 64-bit Applications using** UNICODE** character representation | Depending on the Lib file used, the matching Dll must be distributed with your application. When using a statically linked library, the Dll is not required, but the application must be updated as described in section "Linking Statically" below. ##### Intel 32-Bit Operating Systems When building applications for Windows 10 and above, one of the following Lib files is used: | Lib File | Dll File | Description | | --- | --- | --- | | SftTabs_IX86_A_70.lib | SftTabs_IX86_A_70.dll | 32-bit Applications using** ANSI** character representation | | SftTabs_IX86_A_70_Static.lib | none - see section "Linking Statically" below | 32-bit Applications using** ANSI** character representation | | SftTabs_IX86_U_70.lib | SftTabs_IX86_U_70.dll | 32-bit Applications using** UNICODE ** character representation | | SftTabs_IX86_U_70_Static.lib | none - see section "Linking Statically" below | 32-bit Applications using** UNICODE** character representation | Depending on the Lib file used, the matching Dll must be distributed with your application. When using a statically linked library, the Dll is not required, but the application must be updated as described in section "Linking Statically" below. ##### ARM64 Operating Systems When building applications for ARM64 processors running Windows 11 and above, one of the following Lib files is used: | Lib File | Dll File | Description | | --- | --- | --- | | SftTabs_ARM64_A_70.lib | SftTabs_ARM64_A_70.dll | ARM64 Applications using** ANSI** character representation | | SftTabs_ARM64_U_70.lib | SftTabs_ARM64_U_70.dll | ARM64 Applications using** UNICODE ** character representation | Depending on the Lib file used, the matching Dll must be distributed with your application. #### Linking Statically This step is only required if a Lib file is selected above, that eliminates the Dll. If the Dll is distributed with your application and a suitable Lib file is chosen above, this step can be skipped. The entire project must be compiled with the [SFTTABS_STATIC](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/def_sfttabs_static) preprocessor symbol defined: Make sure to update all configurations (both Debug and Release). Using the *Project*, *Properties...* menu command, the project's C/C++, Preprocessor properties are accessed so Preprocessor Definitions can be modified. ![Linking Statically](https://softelvdm.com/Vault/Softelvdm.com/docx/SftTabs%20DLL%207.0/image/usingc3_vsnet.gif) #### Resource Script When linking statically, your application must provide the resources for SftTabs/DLL controls. This is accomplished by including the provided header file SftTabsResources.rci into the application's resource script. This file uses predefined ID values which cannot be changed. Make sure to update all configurations (both Debug and Release). ``` #include "SftTabsResources.rci" ``` Update the resource script by switching to Resource View using the *View*, *Resource View* menu command, then use the *Edit*, *Resource Includes* menu command: ![Resource Includes](https://softelvdm.com/Vault/Softelvdm.com/docx/SftTabs%20DLL%207.0/image/usingc4_vsnet.gif) In order for the include file to be located, the include path for Resources must be updated: ![Resource Includes](https://softelvdm.com/Vault/Softelvdm.com/docx/SftTabs%20DLL%207.0/image/usingc5_vsnet.gif) #### Additional Lib Files > Depending on the Lib file used, it may also be necessary to add additional Lib files to the application. Typically, version.lib is required to allow successful linking. ``` version.lib ``` Make sure to update all configurations (both Debug and Release). Certain features of the control require [GDI+](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/g_gdiplus) support. GDI+ is available on all supported Windows versions (Windows 10 and above). If you don't want to distribute gdiplus.dll, you can use the delayload feature of the linker by adding the following to your linker options: ``` /delayload:gdiplus.dll ``` This will allow the control to use GDI+, if available, and use alternate presentation methods if it is not available. Using the *Project*, *Properties...* menu command, the project's Linker, Input properties are accessed so Additional Dependencies can be modified. ![Version.lib](https://softelvdm.com/Vault/Softelvdm.com/docx/SftTabs%20DLL%207.0/image/usingc6_vsnet.gif) ## Creating a Dialog Resource *Source: https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/g_vc* This section describes how to add a tab control to a dialog using Visual Studio. ### Adding a Tab Control to a Dialog To add a SftTabs/DLL control to a dialog, use the "Custom Control" toolbar button. Click on the button and then the dialog being designed to add a control. ![Custom Control](https://softelvdm.com/Vault/Softelvdm.com/docx/SftTabs%20DLL%207.0/image/vc7_1.png) Once a custom control has been added to a dialog, you can edit the control properties by using the *View, Properties...* menu command. ![Properties](https://softelvdm.com/Vault/Softelvdm.com/docx/SftTabs%20DLL%207.0/image/vc7_2.png) To define a SftTabs/DLL control, enter the class **SftTabsControl70** in the edit field labeled *Class*. A window caption is not necessary, so the edit field marked *Caption* can be left blank. ### SftTabs/DLL Control Styles To enter a SftTabs/DLL [window style](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/i_windowstyles) in the *User Control Properties* dialog, use the following list to add the desired style values and enter the resulting hexadecimal value in the field marked *Style*. For detailed information, see Tab Control Styles. | Style | Value | ***Description*** | | --- | --- | --- | | WS_BORDER | 0x00800000 | Draws a border around the control. The border is a dark line. Generally not useful for a tab control. | | WS_CHILD | 0x40000000 | Creates a child window. Usually required. | | WS_DISABLED | 0x08000000 | Creates a tab control that is initially disabled. A disabled tab control cannot receive input from the user. | | WS_GROUP | 0x00020000 | Specifies the first control of a group of controls. All controls defined with the WS_GROUP style after the first control belong to the same group. The next control with the WS_GROUP style ends the group and starts the next group. | | WS_TABSTOP | 0x00010000 | Specifies a control that can receive the keyboard focus when the user presses the TAB key. Pressing the TAB key changes the keyboard focus to the next control with the WS_TABSTOP style. | | WS_VISIBLE | 0x10000000 | Creates a tab control that is initially visible. Usually required. | The tab control can be customized using run-time code, which can be created using the [SftTabs/DLL Wizard](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/g_wizarddesign) application. ### Designing a Tabbed Dialog A tabbed dialog is designed just like a regular dialog. The only difference is the tab control, which is added to make it a tabbed dialog. The tab control has to be designed using the SftTabs/DLL Wizard application and the resulting source code can then be copied to your application. A tab control used with a tabbed dialog must provide a [client area](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/pop_clientarea) or a frame window has to be defined when calling [SftTabs_SetControlInfo](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/function_setcontrolinfo) or [CSftTabsDialog::InitializeTabControl](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/function_csfttabsdialog_initializetabcontrol). The size of the tab control's client area must be large enough to accommodate all pages. Differences in font sizes and display resolutions may cause problems if the client area is not large enough. A page will always be sized as large as the client area allows. To make tabbed dialog versus page size consistent, make sure to always specify the same font to be used for all dialogs. ### Designing a Page The size of the tab control's client area must be large enough to accommodate a page. Differences in font sizes and display resolutions may cause problems if the client area is not large enough. A page will always be sized as large as the client area allows. A tab page is designed just like a regular dialog with a few minor restrictions. A page is always a modeless dialog which has a tabbed dialog as its parent window. For that reason, the window style of a page has to be defined as "Child". The dialog should be defined without frame, border or other decoration. A system menu and title bar may be defined so a dialog caption can be entered. The system menu, title bar and the dialog caption will be removed by SftTabs/DLL before the page is shown. The page's caption will be used as the dialog caption for the main, tabbed dialog. This offers an easy way to change the tabbed dialog's window title when switching between pages. To make tabbed dialog versus page size consistent, make sure to always specify the same font to be used for all dialogs. ### Test Mode In the dialog test mode offered by Visual Studio, the SftTabs/DLL control will not be displayed. Instead, a gray box will show the location of the control. When using the tab key to test the tab stops, the simulated SftTabs/DLL control will not receive the input focus and appear not to have a tab stop defined. ## Using C *Source: https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/g_usingc* This section describes how to use SftTabs/DLL in an application written using the C programming language. ### Adding SftTabs/DLL to an Application Please see "[Building Applications](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/g_buildingapp)" to prepare a project for development with SftTabs/DLL. | | | | --- | --- | | A) | Every source program making use of a SftTabs/DLL control must include the required header file SftTb.h by using the #include directive. | ``` #include "SftTb.h" /* SftTabs/DLL required header file */ ``` This include statement should appear after the #include statement. The file is located in the directory \Program Files (x86)\Softelvdm\SftTabs DLL 7.0\Include (unless changed during the installation).The project settings may need to be updated so the #include file can be located (see "Building Applications" for more information). | | | | --- | --- | | B) | In order to use SftTabs/DLL controls, an application must call the [SftTabs_RegisterApp](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/function_registerapp) function. The call to this function is required so that SftTabs/DLL window classes can be registered. This call has to be made before any SftTabs/DLL controls are created. Add the following statement to your source code, where your application registers its window classes (normally during application initialization): | ``` SftTabs_RegisterApp(hInstance); /* Use SftTabs/DLL with this application */ ``` | | | | --- | --- | | C) | Once SftTabs/DLL controls are no longer needed, an application must call the [SftTabs_UnregisterApp](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/function_unregisterapp) function. The call to this function is required so that SftTabs/DLL window classes can be unregistered and cleanup processing can take place. This call has to be made after all SftTabs/DLL controls have been destroyed (normally during application termination). | ``` SftTabs_UnregisterApp(hInstance); /* No longer use SftTabs/DLL */ ``` | | | | --- | --- | | D) | The application's executable (Exe or Dll) must be linked with the correct [Lib file](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/g_distributing), depending on the target environment. Please see "Building Applications" for more information.The project settings may need to be updated so the Lib files can be located (see "Building Applications" for more information). | ### Adding a Tab Control There are two methods to add a tab control to an application: - using dialog resources
  • using CreateWindow(Ex) - Adding a tab control using dialog resources is accomplished by using a resource editor to design a dialog. Once a tab control is created, its window handle can be obtained by using the Windows GetDlgItem function. For more information, see [Creating a Dialog Resource](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/g_vc). Another method to create a tab control is by using the CreateWindow(Ex) Windows call: ``` hwndPreview = CreateWindow(TEXT(SFTTABS_CLASS), NULL, WS_CHILD, 0, 0, 0, 0, hwndMain, (HMENU) IDC_TABS, hInstance, NULL); ``` For more information on the various parameters used, see the Windows API documentation. ### Handling Notifications As with standard Windows controls, applications must respond to events and messages to cause controls to respond to user requests. For additional information, see [Notifications](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/i_notifications). #### Switching Between Tabs Switching between tabs is fully automatic, however, an application may wish to prevent a user from switching to another tab. By responding to the WM_COMMAND, SFTTABSN_SWITCHING notification, an application can prevent completion of the tab switch by sending a WM_CANCELMODE message to the tab control. ``` case WM_COMMAND: { HWND hwndCtl = (HWND) lParam; int id = LOWORD(wParam); int code = HIWORD(wParam); if (hwndCtl) { switch (id) { case IDC_TAB: switch (code) { case SFTTABSN_SWITCHING:// we're about to switch away from // the current page. If you need to know what the new // page will be use SftTabs_GetNextTab(hwndCtl). if (!IsOKToSwitch()) SendMessage(hwndCtl, WM_CANCELMODE, 0, 0); break; case SFTTABSN_SWITCHED:// we switched to a new page SftTabs_ActivatePage(hwndParent, hwndCtl, NULL, FALSE); break; } break; case IDOK: case IDCANCEL: if (code == BN_CLICKED) SendMessage(hwndParent, WM_COMMAND, id, 0); break; } } break; } ``` An application has to make attached controls or dialogs visible when switching between tabs. The SftTabs/DLL API offers functions to manage dialogs and Windows controls that are attached to tabs. See Implementing Tabbed Dialogs and Implementing Tabbed Windows for more information. ### Implementing Tabbed Dialogs A tabbed dialog is created just like any other dialog. A tabbed dialog has a tab control with an available [client area](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/pop_clientarea). In this client area, pages are displayed. Each tab has an attached page (although during development of a tabbed dialog, a tab doesn't require an attached page). As the user switches between tabs, the appropriate page is created, displayed and destroyed. A tabbed dialog and each page have a dialog procedure. This makes conversion of existing dialogs and development of new pages very easy. Tabbed dialogs and pages are first designed using a resource editor. The section Creating a Dialog Resource describes how the necessary tabbed dialog and page (dialog) resources are created. Once the necessary dialogs have been designed, the tab control layout can be defined using the [SftTabs/DLL Wizard](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/g_wizarddesign). The SftTabs/DLL Wizard also creates much of the code required to initialize the tab control. This code should be copied to the application (with possibly minor modifications). #### Creating a Tabbed Dialog Dialog Procedure The following sample code (from \Program Files (x86)\Softelvdm\SftTabs DLL 7.0\Samples\C\Dialog\Dialog.c) shows a typical dialog procedure used for a tabbed dialog. Most of the code has been created using the SftTabs/DLL Wizard and then copied into the application. ``` /**********************************************************************/ /* Frame Dialog Proc */ /**********************************************************************/ /*- Tab Control Initialization Data --------------------------------------------*/ static const SFTTABS_CONTROL CtlInit = { SFTTABSSTYLE_MODERN_I, /* tab style */ 2, /* number of rows */ 0, /* number of tabs per row (if fFixed) */ 0, /* width of left margin */ 0, /* width of right margin */ FALSE, /* same width for all tabs */ TRUE, /* Client area wanted */ FALSE, /* allow multiline label text */ TRUE, /* use with dialog */ FALSE, /* use specified background color only for text */ FALSE, /* scrollable tabs */ FALSE, /* hide scroll buttons */ TRUE, /* bold font for active tab wanted */ TRUE, /* fill rows completely */ NULL, /* scroll button bitmap */ NULL, /* Dialog data associated with active tab */ NULL, /* Dialog window handle associated with active tab */ NULL, /* Frame, used as client area */ TRUE, /* Tooltips wanted */ FALSE, /* drop text if it doesn't fit */ FALSE, /* conditional scroll buttons */ BMBUTTONSTYLE_STD, /* scroll button style */ FALSE, /* display ... if truncated */ TRUE, /* Flyby highlighting */ FALSE, /* use client area colors in partially obscured frames */ FALSE, /* scroll buttons on left side */ -1, /* row indentation */ FALSE, /* don't show truncated pattern for clipped tab */ FALSE, /* full size scroll buttons */ TRUE, /* use themes */ TRUE, /* use exact window region */ FALSE, /* always show prefix _ */ 0,0,0,0, /* animation values */ NULL, /* disabled button bitmap */ TRUE, /* focus rectangle if the control has i/p focus */ FALSE, /* TRUE if Close button wanted */ FALSE, /* TRUE if Close button disabled */ FALSE, /* TRUE if WM_CLOSE message wanted */ FALSE, /* TRUE if Minimize, Restore, Close buttons are full size */ SFTTABS_BUTTON_NEAR, /* scroll button alignment */ SFTTABS_BUTTON_NEAR, /* Minimize, Restore, Close button alignment */ FALSE, /* TRUE if Minimize button wanted */ FALSE, /* TRUE if Minimize button disabled */ FALSE, /* TRUE if Restore button wanted */ FALSE, /* TRUE if Restore button disabled */ NULL, /* Close, Minimize, Restore button bitmap */ NULL, /* Close, Minimize, Restore disabled button bitmap */ TEXT(""), /* scroll left button tooltip */ TEXT(""), /* scroll button tooltip */ TEXT(""), /* Close button tooltip */ TEXT(""), /* Minimize button tooltip */ TEXT(""), /* Restore button tooltip */ 0, /* custom modifications */ 0, /* forced height/width depending on tab style - 0 to ignore */ FALSE, /* switch tabs on button release (or down if FALSE) */ FALSE, /* Rendering compatible with pre-6.0 */ FALSE, /* don't display clientarea border - select styles only */ }; static const SFTTABS_TAB Tab0 = { /*The First One */ SFTTABS_NOCOLOR, RGB(0,0,255), /* background, foreground color */ SFTTABS_NOCOLOR, RGB(0,0,255), /* background, foreground color (when selected) */ { SFTTABS_GRAPH_LEFT, 0 }, /* location */ TRUE, /* enabled/disabled */ 0, /* userdata */ (SFTTABS_DWORD_PTR) Page1_Callback, /* user supplied tab callback */ NULL, /* reserved */ SFTTABS_NOCOLOR, /* Flyby foreground color */ SFTTABS_NOCOLOR, /* Client area background color */ 0,0,0,0, /* animation values */ NULL, /* tab-specific ImageList handle*/ FALSE, /* hidden tab */ SFTTABS_NOCOLOR, /* gradient fill background color */ SFTTABS_NOCOLOR, SFTTABS_NOCOLOR, /* gradient fill background color, active tab */ SFTTABS_NOCOLOR, SFTTABS_NOCOLOR, /* gradient fill client area color */ SFTTABS_NOCOLOR, }; static const SFTTABS_TAB Tab1 = { /*&Second */ SFTTABS_NOCOLOR, RGB(255,0,0), /* background, foreground color */ SFTTABS_NOCOLOR, RGB(255,0,0), /* background, foreground color (when selected) */ { SFTTABS_GRAPH_RIGHT, 0 }, /* location */ TRUE, /* enabled/disabled */ 0, /* userdata */ (SFTTABS_DWORD_PTR) Page2_Callback, /* user supplied tab callback */ NULL, /* reserved */ SFTTABS_NOCOLOR, /* Flyby foreground color */ SFTTABS_NOCOLOR, /* Client area background color */ 0,0,0,0, /* animation values */ NULL, /* tab-specific ImageList handle*/ FALSE, /* hidden tab */ SFTTABS_NOCOLOR, /* gradient fill background color */ SFTTABS_NOCOLOR, SFTTABS_NOCOLOR, /* gradient fill background color, active tab */ SFTTABS_NOCOLOR, SFTTABS_NOCOLOR, /* gradient fill client area color */ SFTTABS_NOCOLOR, }; static const SFTTABS_TAB Tab2 = { /*&Third */ SFTTABS_NOCOLOR, RGB(128,128,0), /* background, foreground color */ SFTTABS_NOCOLOR, RGB(128,128,0), /* background, foreground color (when selected) */ { SFTTABS_GRAPH_NONE, 0 }, /* location */ TRUE, /* enabled/disabled */ 0, /* userdata */ (SFTTABS_DWORD_PTR) Page3_Callback, /* user supplied tab callback */ NULL, /* reserved */ SFTTABS_NOCOLOR, /* Flyby foreground color */ SFTTABS_NOCOLOR, /* Client area background color */ 0,0,0,0, /* animation values */ NULL, /* tab-specific ImageList handle*/ FALSE, /* hidden tab */ SFTTABS_NOCOLOR, /* gradient fill background color */ SFTTABS_NOCOLOR, SFTTABS_NOCOLOR, /* gradient fill background color, active tab */ SFTTABS_NOCOLOR, SFTTABS_NOCOLOR, /* gradient fill client area color */ SFTTABS_NOCOLOR, }; static const SFTTABS_TAB Tab3 = { /*F&ourth */ SFTTABS_NOCOLOR, RGB(0,255,255), /* background, foreground color */ SFTTABS_NOCOLOR, RGB(0,255,255), /* background, foreground color (when selected) */ { SFTTABS_GRAPH_NONE, 0 }, /* location */ TRUE, /* enabled/disabled */ 0, /* userdata */ (SFTTABS_DWORD_PTR) Page4_Callback, /* user supplied tab callback */ NULL, /* reserved */ SFTTABS_NOCOLOR, /* Flyby foreground color */ SFTTABS_NOCOLOR, /* Client area background color */ 0,0,0,0, /* animation values */ NULL, /* tab-specific ImageList handle*/ FALSE, /* hidden tab */ SFTTABS_NOCOLOR, /* gradient fill background color */ SFTTABS_NOCOLOR, SFTTABS_NOCOLOR, /* gradient fill background color, active tab */ SFTTABS_NOCOLOR, SFTTABS_NOCOLOR, /* gradient fill client area color */ SFTTABS_NOCOLOR, }; static const SFTTABS_TAB Tab4 = { /*F&ifth */ SFTTABS_NOCOLOR, RGB(0,0,128), /* background, foreground color */ SFTTABS_NOCOLOR, RGB(0,0,128), /* background, foreground color (when selected) */ { SFTTABS_GRAPH_NONE, 0 }, /* location */ TRUE, /* enabled/disabled */ 0, /* userdata */ (SFTTABS_DWORD_PTR) Page5_Callback, /* user supplied tab callback */ NULL, /* reserved */ SFTTABS_NOCOLOR, /* Flyby foreground color */ SFTTABS_NOCOLOR, /* Client area background color */ 0,0,0,0, /* animation values */ NULL, /* tab-specific ImageList handle*/ FALSE, /* hidden tab */ SFTTABS_NOCOLOR, /* gradient fill background color */ SFTTABS_NOCOLOR, SFTTABS_NOCOLOR, /* gradient fill background color, active tab */ SFTTABS_NOCOLOR, SFTTABS_NOCOLOR, /* gradient fill client area color */ SFTTABS_NOCOLOR, }; static const SFTTABS_TAB Tab5 = { /*Si&xth */ SFTTABS_NOCOLOR, RGB(128,0,0), /* background, foreground color */ SFTTABS_NOCOLOR, RGB(128,0,0), /* background, foreground color (when selected) */ { SFTTABS_GRAPH_NONE, 0 }, /* location */ TRUE, /* enabled/disabled */ 0, /* userdata */ (SFTTABS_DWORD_PTR) Page6_Callback, /* user supplied tab callback */ NULL, /* reserved */ SFTTABS_NOCOLOR, /* Flyby foreground color */ COLOR_INFOBK|0x80000000, /* Client area background color */ 0,0,0,0, /* animation values */ NULL, /* tab-specific ImageList handle*/ FALSE, /* hidden tab */ SFTTABS_NOCOLOR, /* gradient fill background color */ SFTTABS_NOCOLOR, SFTTABS_NOCOLOR, /* gradient fill background color, active tab */ SFTTABS_NOCOLOR, SFTTABS_NOCOLOR, /* gradient fill client area color */ SFTTABS_NOCOLOR, }; ``` The dialog procedure shown here initializes the tab control in its WM_INITDIALOG message handler. ``` BOOL CALLBACK MainDialogProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) { switch (msg) { case WM_INITDIALOG: { int index; HWND hwndTab; SFTTABS_TAB Tab; // Center this dialog CenterWindow(hwndDlg); hwndTab = GetDlgItem(hwndDlg, IDC_TAB); /* get the window handle */ /* load the bitmaps/icons */ m_hSampleBitmap = LoadBitmap(g_hInst, MAKEINTRESOURCE(IDB_BITMAP)); m_hSampleIcon = LoadIcon(g_hInst, MAKEINTRESOURCE(IDI_ICON)); /* Initialization is faster if we set redraw off */ SendMessage(hwndTab, WM_SETREDRAW, (WPARAM)FALSE, 0); /* We are using new features */ SftTabs_SetVersion(hwndTab, SFTTABS_7_0); index = SftTabs_AddTab(hwndTab, TEXT("The First One")); SftTabs_SetToolTip(hwndTab, index, TEXT("Demonstrates tabbing into and out of the tab page")); Tab = Tab0; Tab.graph.item.hBitmap = m_hSampleBitmap; SftTabs_SetTabInfo(hwndTab, index, &Tab); index = SftTabs_AddTab(hwndTab, TEXT("&Second")); SftTabs_SetToolTip(hwndTab, index, TEXT("Demonstrates how an application can prevent tab switching")); Tab = Tab1; Tab.graph.item.hIcon = m_hSampleIcon; SftTabs_SetTabInfo(hwndTab, index, &Tab); index = SftTabs_AddTab(hwndTab, TEXT("&Third")); SftTabs_SetToolTip(hwndTab, index, TEXT("This page is reset everytime you switch to it")); SftTabs_SetTabInfo(hwndTab, index, &Tab2); index = SftTabs_AddTab(hwndTab, TEXT("F&ourth")); SftTabs_SetToolTip(hwndTab, index, TEXT("A page with private OK, Cancel, Next and Previous page buttons")); SftTabs_SetTabInfo(hwndTab, index, &Tab3); index = SftTabs_AddTab(hwndTab, TEXT("F&ifth")); SftTabs_SetToolTip(hwndTab, index, TEXT("A page that has not yet been implemented")); SftTabs_SetTabInfo(hwndTab, index, &Tab4); index = SftTabs_AddTab(hwndTab, TEXT("Si&xth")); SftTabs_SetToolTip(hwndTab, index, TEXT("A page with nested tab controls and pages")); SftTabs_SetTabInfo(hwndTab, index, &Tab5); SftTabs_SetControlInfo(hwndTab, &CtlInit); SftTabs_SetCurrentTab(hwndTab, 0); // Make sure to turn redraw back on SendMessage(hwndTab, WM_SETREDRAW, (WPARAM)TRUE, 0); InvalidateRect(hwndTab, NULL, TRUE); // Activate current page SftTabs_ActivatePage(hwndDlg, hwndTab, NULL, TRUE); // Mark the window as a main, tabbed dialog (so accel. keys work) by registering it. // Register the dialog AFTER activating the current page SftTabs_RegisterDialog(hwndDlg); // Update Tab2 to use transition effects { SFTTABS_TAB Tab; SftTabs_GetTabInfo(hwndTab, 2, &Tab); Tab.animationStyleShow = SFTTABS_SLIDE_FROM_LEFT; Tab.animationTimeShow = 400; SftTabs_SetTabInfo(hwndTab, 2, &Tab); } // Update Tab5 to use transition effects { SFTTABS_TAB Tab; SftTabs_GetTabInfo(hwndTab, 5, &Tab); Tab.animationStyleShow = SFTTABS_EXPAND_CENTER; Tab.animationTimeShow = 400; SftTabs_SetTabInfo(hwndTab, 5, &Tab); } { // Animate the entire window // Animation works on windows 98, 2000 or better only HMODULE hUser32 = GetModuleHandle(TEXT("USER32.DLL")); if (hUser32) { typedef BOOL (WINAPI* LPFNANIMATEWINDOW)(HWND, DWORD, DWORD); LPFNANIMATEWINDOW lpfnAnimateWindow; lpfnAnimateWindow = (LPFNANIMATEWINDOW)GetProcAddress(hUser32, "AnimateWindow"); if (lpfnAnimateWindow) lpfnAnimateWindow(hwndDlg, 300, AW_HOR_POSITIVE); } } return FALSE; // WM_INITDIALOG, input focus already set } ... more ... ``` The call to [SftTabs_ActivatePage](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/function_activatepage) makes the current page active. The [SftTabs_RegisterDialog](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/function_registerdialog) call registers the dialog for special tabbed dialog handling by SftTabs/DLL. After registering the dialog, TAB and ESCAPE key handling, default button setting and keyboard accelerator keys (Alt-x) will be performed by SftTabs/DLL. A tabbed dialog should always return FALSE when handling the WM_INITDIALOG message. The focus has been set already by SftTabs/DLL, so returning FALSE will prevent Windows from setting the focus (to the wrong control). The following WM_DESTROY message handler shows the required cleanup calls to delete all bitmaps that the application has loaded, and also unregisters the dialog from SftTabs/DLL: ``` case WM_DESTROY: /* delete the bitmaps/icons */ DeleteObject(m_hSampleBitmap); // Unregister, or the window properties used won't be removed SftTabs_UnregisterDialog(hwndDlg); // destroy all pages SftTabs_Destroy(hwndDlg, GetDlgItem(hwndDlg, IDC_TAB)); break; ... more ... ``` The following WM_COMMAND message handler responds to notifications sent to the tabbed dialog by the tab control. When the user attempts to switch to another page by clicking a tab using the left mouse button or by using the keyboard, a SFTTABSN_SWITCHING notification is sent to the tabbed dialog. The dialog then calls [SftTabs_DeactivatePage](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/function_deactivatepage) to test if the active page can be left. This call to SftTabs_DeactivatePage results in [WM_QUERYENDSESSION](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/i_windows_messages) and [SftTabs_GetEndPageMessage](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/function_getendpagemessage) messages being sent to the page's dialog procedure. Based on the dialog procedure's response, the page may or may not be deactivated. By handling the WM_QUERYENDSESSION or SftTabs_GetEndPageMessage message, a page can prevent a user from switching away from a tab. If a new tab has become active, the tabbed dialog receives a SFTTABSN_SWITCHED notification, so the associated page can be made active by the call to SftTabs_ActivatePage. ``` case WM_COMMAND: { // Extract WM_COMMAND parameters HWND hwndCtl = (HWND) lParam; int id = LOWORD(wParam); int code = HIWORD(wParam); if (hwndCtl) { switch (id) { case IDC_TAB: switch (code) { case SFTTABSN_SWITCHING:// we're about to switch away from // the current page. If you need to know what the new // page will be, use SftTabs_GetNextTab(hwndCtl). if (!SftTabs_DeactivatePage(hwndDlg, hwndCtl)) // couldn't deactivate current page, so don't switch SendMessage(hwndCtl, WM_CANCELMODE, 0, 0); break; case SFTTABSN_SWITCHED:// we switched to a new page SftTabs_ActivatePage(hwndDlg, hwndCtl, NULL, FALSE); break; } break; case IDOK: case IDCANCEL: if (code == BN_CLICKED) SendMessage(hwndDlg, WM_COMMAND, id, 0); break; } } else { switch (id) { case IDOK: // The currently active page will be called with a // WM_QUERYENDSESSION/SftTabs_GetEndPageMessage message to determine // whether it can be closed if (SftTabs_ClosePossible(hwndDlg, GetDlgItem(hwndDlg, IDC_TAB))) EndDialog(hwndDlg, TRUE); break; case IDCANCEL: EndDialog(hwndDlg, FALSE); break; } // The above assumes that this is a modal dialog. If it is a modeless // don't use EndDialog, use DestroyWindow instead. } break; } } ... more ... ``` At the end of the dialog procedure, a call to [SftTabs_HandleDialogMessage](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/function_handledialogmessage) should be made to allow SftTabs/DLL to process any messages. Without this call, SftTabs/DLL may not be able to provide the tabbed dialog handling, such as TAB and ESCAPE key processing, etc. Please note that the [SftTabs_TransparentControls](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/function_transparentcontrols) function is not used in a main dialog, only in tab pages. ``` if (SftTabs_HandleDialogMessage(hwndDlg, msg, wParam, lParam)) return TRUE; return FALSE; } ``` The [SFTTABS_TAB](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/struct_sfttabs_tab) structures used to define each tab in the tab control also define a callback routine of type [SFTTABS_TABCALLBACK](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/typedef_sfttabs_tabcallback). This callback routine is responsible for creating and destroying the dialog which represents the page. SftTabs/DLL will hide and disable a dialog, but it is up to this callback routine to create and destroy the dialog. The following tab definition is repeated here so it can be shown next to the callback function: ``` static const SFTTABS_TAB Tab2 = { /*&Third */ SFTTABS_NOCOLOR, RGB(128,128,0), /* background, foreground color */ SFTTABS_NOCOLOR, RGB(128,128,0), /* background, foreground color (when selected) */ { SFTTABS_GRAPH_NONE, 0 }, /* Bitmap, Icon */ TRUE, /* enabled/disabled */ 0, /* userdata */ (SFTTABS_DWORD_PTR) Page3_Callback, /* user supplied tab callback */ NULL, /* reserved */ SFTTABS_NOCOLOR, /* Flyby foreground color */ SFTTABS_NOCOLOR, /* Client area background color */ 0,0,0,0, /* animation values */ NULL, /* tab-specific ImageList handle*/ FALSE, /* hidden tab */ SFTTABS_NOCOLOR, /* gradient fill background color */ SFTTABS_NOCOLOR, SFTTABS_NOCOLOR, /* gradient fill background color, active tab */ SFTTABS_NOCOLOR, SFTTABS_NOCOLOR, /* gradient fill client area color */ SFTTABS_NOCOLOR, }; HWND CALLBACK Page3_Callback(BOOL fCreate, HWND hwndOwner, HWND hwndPage, HWND hwndTab) { if (fCreate) { // creating a new page if (hwndPage) { // already created, we could do some initialization here. // this will be called every time the page becomes active // The WM_CREATE/WM_INITDIALOG/WM_DESTROY messages are also sent to // the page and could be used to determine activation/deactivation. // of the page. // optional, set the main window's title to the window title defined for this page SftTabs_CopyWindowTitle(hwndPage, hwndOwner); return NULL; } else { // Create the page. // You can create and initialize any type of window here, not just dialogs. // Use CreateWindow to create other windows. Don't specify WS_VISIBLE, but // make sure you use WS_TABSTOP. // When creating a non-dialog window, make sure to call SftTabs_SetPageActive // after the page has been created. HWND hwnd = CreateDialogParam(g_hInst, MAKEINTRESOURCE(IDD_PAGE3), hwndOwner, (DLGPROC)Page3_DialogProc, (LPARAM)hwndTab);// pass tab control as data // optional, set the main window's title to the window title defined for this page SftTabs_CopyWindowTitle(hwnd, hwndOwner); return hwnd; } } else { // destroying page // We'll always destroy this page (to save resources) DestroyWindow(hwndPage); return NULL; } } ``` This callback routine is called by SftTabs/DLL to perform certain functions based on the parameters passed. The callback routine creates the dialog (page) using CreateDialogParam. The window handle of the tab control is passed as the last parameter to CreateDialogParam. The WM_INITDIALOG processing of the page's dialog procedure needs access to the tab control's window handle for the call to [SftTabs_SetPageActive](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/function_setpageactive). This is a convenient way to pass it to the dialog procedure. Of course, it could also be passed using other mechanisms. > The tab page dialog resource must be defined as a child window with the WS_CHILD [window style](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/i_windowstyles). It cannot be defined as a popup or overlapped window (WS_POPUP or WS_OVERLAPPED) #### Creating a Page Dialog Procedure Once the page is created, all Windows messages for the page are sent to the page's dialog procedure. Any messages that the page doesn't handle should be passed to SftTabs/DLL by using a call to SftTabs_HandleDialogMessage. ``` BOOL CALLBACK Page3_DialogProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) { LRESULT lResult; switch (msg) { case WM_INITDIALOG: SetWindowText(GetDlgItem(hwndDlg, IDC_P3_EDIT1), TEXT("Type Here")); // initialize page SftTabs_SetPageActive(hwndDlg, (HWND) lParam, NULL); return !SftTabs_IsRegisteredDialog(GetParent(hwndDlg)); } if (SftTabs_HandleDialogMessage(hwndDlg, msg, wParam, lParam)) return TRUE; if (SftTabs_TransparentControls(hwndDlg, NULL, &msg, &wParam, &lParam, &lResult, 0, 0)) return (BOOL) lResult; return FALSE; } ``` When the page is initialized and handles the WM_INITDIALOG message, it must call SftTabs_SetPageActive to notify SftTabs/DLL that this page is the active page. SftTabs/DLL will at this time resize the page to fit into the tab control's client area, override certain incompatible window styles and make the page visible. When the very first page is initialized, the focus should be on the first control in that page. Otherwise, when other pages have been active before, the focus should remain on the control which currently has the focus (usually the tab control). The return value of the WM_INITDIALOG message handler determines the focus handling. GetParent below returns the window handle of the page's parent window, which should be the tabbed dialog. This window handle can be tested to find out if the dialog has been registered with SftTabs/DLL. When the very first page is activating, the tabbed dialog has not yet been registered, [SftTabs_IsRegisteredDialog](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/function_isregistereddialog) would return FALSE and the dialog procedure would subsequently return TRUE, allowing the focus to be set to the first control. Otherwise, if this is not the very first page, FALSE would be returned, and the focus would remain on the control that currently has the focus. ``` return !SftTabs_IsRegisteredDialog(GetParent(hwndDlg)); ``` ### Implementing Tabbed Windows A tabbed window is created just like a regular window. A tabbed window has at least one tab control as its child window (with or without a client area). Each tab has an attached page (although during development of a tabbed dialog, a tab doesn't require an attached page). As the user switches between tabs, the appropriate page is created, displayed and destroyed. #### Creating a Tabbed Window Window Procedure The following sample code (from \Program Files (x86)\Softelvdm\SftTabs DLL 7.0\Samples\C\Window\Window.c) shows a typical window procedure used for a tabbed window. Most of the code has been created using the SftTabs/DLL Wizard and then copied into the application. ``` /**********************************************************************/ /* Frame Window */ /**********************************************************************/ /*- Tab Control Initialization Data --------------------------------------------*/ static const SFTTABS_CONTROL CtlInit = { SFTTABSSTYLE_MODERN_II, /* tab style */ 1, /* number of rows */ 0, /* number of tabs per row (if fFixed) */ 0, /* width of left margin */ 0, /* width of right margin */ FALSE, /* same width for all tabs */ FALSE, /* Client area wanted */ FALSE, /* allow multiline label text */ TRUE, /* use with dialog */ FALSE, /* use specified background color only for text */ TRUE, /* scrollable tabs */ FALSE, /* hide scroll buttons */ TRUE, /* bold font for active tab wanted */ FALSE, /* fill rows completely */ NULL, /* scroll button bitmap */ NULL, /* Dialog data associated with active tab */ NULL, /* Dialog window handle associated with active tab */ NULL, /* Frame, used as client area */ TRUE, /* Tooltips wanted */ FALSE, /* drop text if it doesn't fit */ FALSE, /* conditional scroll buttons */ BMBUTTONSTYLE_THEME_SCROLL, /* scroll button style */ FALSE, /* display ... if truncated */ TRUE, /* Flyby highlighting */ FALSE, /* use client area colors in partially obscured frames */ TRUE, /* scroll buttons on left side */ 0, /* row indentation */ FALSE, /* don't show truncated pattern for clipped tab */ TRUE, /* full size scroll buttons */ FALSE, /* use themes */ FALSE, /* use exact window region */ FALSE, /* always show prefix _ */ 0,0,0,0, /* animation values */ NULL, /* disabled button bitmap */ TRUE, /* focus rectangle if the control has i/p focus */ FALSE, /* TRUE if Close button wanted */ FALSE, /* TRUE if Close button disabled */ FALSE, /* TRUE if WM_CLOSE message wanted */ FALSE, /* TRUE if Minimize, Restore, Close buttons are full size */ SFTTABS_BUTTON_NEAR, /* scroll button alignment */ SFTTABS_BUTTON_NEAR, /* Minimize, Restore, Close button alignment */ FALSE, /* TRUE if Minimize button wanted */ FALSE, /* TRUE if Minimize button disabled */ FALSE, /* TRUE if Restore button wanted */ FALSE, /* TRUE if Restore button disabled */ NULL, /* Close, Minimize, Restore button bitmap */ NULL, /* Close, Minimize, Restore disabled button bitmap */ TEXT("Scroll Left"), /* scroll left button tooltip */ TEXT("Scroll Right"), /* scroll button tooltip */ TEXT(""), /* Close button tooltip */ TEXT(""), /* Minimize button tooltip */ TEXT(""), /* Restore button tooltip */ 0, /* custom modifications */ 0, /* forced height/width depending on tab style - 0 to ignore */ FALSE, /* switch tabs on button release (or down if FALSE) */ FALSE, /* Rendering compatible with pre-6.0 */ FALSE, /* don't display clientarea border - select styles only */ }; static const SFTTABS_TAB Tab0 = { /*&Listbox */ RGB(129,169,226), RGB(0,0,0), /* background, foreground color */ RGB(129,169,226), RGB(0,0,0), /* background, foreground color (when selected) */ { SFTTABS_GRAPH_NONE, 0 }, /* location */ TRUE, /* enabled/disabled */ 0, /* userdata */ (SFTTABS_DWORD_PTR) Page1_Callback, /* user supplied tab callback */ NULL, /* reserved */ RGB(0,0,255), /* Flyby foreground color */ RGB(129,169,226), /* Client area background color */ 0,0,0,0, /* animation values */ NULL, /* tab-specific ImageList handle*/ FALSE, /* hidden tab */ RGB(222,236,254), /* gradient fill background color */ RGB(129,169,226), RGB(222,236,254), /* gradient fill background color, active tab */ RGB(129,169,226), RGB(129,169,226), /* gradient fill client area color */ RGB(222,236,254), }; static const SFTTABS_TAB Tab1 = { /*&Edit Control */ RGB(129,169,226), RGB(0,0,0), /* background, foreground color */ RGB(129,169,226), RGB(0,0,0), /* background, foreground color (when selected) */ { SFTTABS_GRAPH_NONE, 0 }, /* location */ TRUE, /* enabled/disabled */ 0, /* userdata */ (SFTTABS_DWORD_PTR) Page2_Callback, /* user supplied tab callback */ NULL, /* reserved */ RGB(0,0,255), /* Flyby foreground color */ RGB(129,169,226), /* Client area background color */ 0,0,0,0, /* animation values */ NULL, /* tab-specific ImageList handle*/ FALSE, /* hidden tab */ RGB(222,236,254), /* gradient fill background color */ RGB(129,169,226), RGB(222,236,254), /* gradient fill background color, active tab */ RGB(129,169,226), RGB(129,169,226), /* gradient fill client area color */ RGB(222,236,254), }; static const SFTTABS_TAB Tab2 = { /*&Dialog */ RGB(129,169,226), RGB(0,0,0), /* background, foreground color */ RGB(129,169,226), RGB(0,0,0), /* background, foreground color (when selected) */ { SFTTABS_GRAPH_NONE, 0 }, /* location */ TRUE, /* enabled/disabled */ 0, /* userdata */ (SFTTABS_DWORD_PTR) Page3_Callback, /* user supplied tab callback */ NULL, /* reserved */ RGB(0,0,255), /* Flyby foreground color */ RGB(129,169,226), /* Client area background color */ 0,0,0,0, /* animation values */ NULL, /* tab-specific ImageList handle*/ FALSE, /* hidden tab */ RGB(222,236,254), /* gradient fill background color */ RGB(129,169,226), RGB(222,236,254), /* gradient fill background color, active tab */ RGB(129,169,226), RGB(129,169,226), /* gradient fill client area color */ RGB(222,236,254), }; ``` The window procedure shown here initializes the tab control in its WM_CREATE message handler. ``` LRESULT CALLBACK Frame_WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { ... other source code removed case WM_CREATE: { int index; /* This static window is just a filler window above the tab control */ /* We only need it to get the right background color above the tab control */ pfrm->hwndStatic = CreateWindow(/* Create a static window */ TEXT("STATIC"), /* Window Class */ TEXT(""), /* Window Title (not used) */ WS_CHILD|WS_VISIBLE, /* Window Style */ 0, 0, /* x, y */ 0, 0, /* cx, cy */ hwnd, /* Parent Window */ NULL, /* control ID */ g_hInst, /* Application Instance */ NULL); /* creation data */ if (pfrm->hwndStatic == NULL) /* create failed */ return -1; /* Create the tab control */ pfrm->hwndTab = CreateWindow( /* Create the tab control */ TEXT(SFTTABS_CLASS), /* Window Class */ TEXT(""), /* Window Title (not used) */ WS_CHILD|WS_VISIBLE| /* Window Style */ WS_CLIPCHILDREN|WS_TABSTOP| SFTTABSSTYLE_STANDARD, 0, 0, /* x, y */ 0, 0, /* cx, cy */ hwnd, /* Parent Window */ (HMENU) IDC_TAB, /* Tab control ID */ g_hInst, /* Application Instance */ NULL); /* creation data */ if (pfrm->hwndTab == NULL) /* create failed */ return -1; /* Create a frame window. This frame window will be used by SftTabs/DLL */ /* to resize the pages that are attached to the tabs */ pfrm->hwndFrame = CreateWindow( /* Create a static window */ TEXT("STATIC"), /* Window Class */ TEXT(""), /* Window Title (not used) */ WS_CHILD, /* Window Style NOTE: IT'S NOT VISIBLE */ 0, 0, /* x, y */ 0, 0, /* cx, cy */ hwnd, /* Parent Window */ NULL, /* control ID */ g_hInst, /* Application Instance */ NULL); /* creation data */ if (pfrm->hwndFrame == NULL) /* create failed */ return -1; /* Initialization is faster if we set redraw off */ SendMessage(pfrm->hwndTab, WM_SETREDRAW, (WPARAM)FALSE, 0); /* We are using new features */ SftTabs_SetVersion(pfrm->hwndTab, SFTTABS_7_0); index = SftTabs_AddTab(pfrm->hwndTab, TEXT("&Listbox")); SftTabs_SetToolTip(pfrm->hwndTab, index, TEXT("A standard listbox is attached to this tab")); SftTabs_SetTabInfo(pfrm->hwndTab, index, &Tab0); index = SftTabs_AddTab(pfrm->hwndTab, TEXT("&Edit Control")); SftTabs_SetToolTip(pfrm->hwndTab, index, TEXT("A standard edit control is attached to this tab")); SftTabs_SetTabInfo(pfrm->hwndTab, index, &Tab1); index = SftTabs_AddTab(pfrm->hwndTab, TEXT("&Dialog")); SftTabs_SetToolTip(pfrm->hwndTab, index, TEXT("A dialog is attached to this tab")); SftTabs_SetTabInfo(pfrm->hwndTab, index, &Tab2); SftTabs_SetControlInfo(pfrm->hwndTab, &CtlInit); SftTabs_SetCurrentTab(pfrm->hwndTab, 0); // Make sure to turn redraw back on SendMessage(pfrm->hwndTab, WM_SETREDRAW, (WPARAM)TRUE, 0); InvalidateRect(pfrm->hwndTab, NULL, TRUE); // Activate current page. Note the frame window is supplied in this example. // if your tab control has a client area (see fClientArea), you don't need a // frame window SftTabs_ActivatePage(hwnd, pfrm->hwndTab, pfrm->hwndFrame, TRUE); // Mark the window as a main, tabbed windows (so accel. keys work) by registering it. // Register the window AFTER activating the current page SftTabs_RegisterWindow(hwnd); return 0L; } ... other source code removed ``` The call to SftTabs_ActivatePage makes the current page active. The SftTabs_RegisterWindow call registers the window for special tabbed window handling by SftTabs/DLL. After registering the window, keyboard accelerator keys (Alt-x) handling will be performed by SftTabs/DLL. The following WM_SIZE message handler resizes the tabbed window's child windows: ``` case WM_SIZE: { RECT rect; // resize all child windows // get frame window dimension GetClientRect(hwnd, &rect); // calculate position of tab control if (pfrm->hwndTab) { SFTTABS_CONTROL Ctl; // Get tab control info SftTabs_GetControlInfo(pfrm->hwndTab, &Ctl); // Ctl.naturalSize has best height for this tab control rect.top += 5+Ctl.naturalSize; } // reposition static control which serves as a filler window above the tab control if (pfrm->hwndStatic) MoveWindow(pfrm->hwndStatic, rect.left, 0, rect.right-rect.left, 5, TRUE); // now reposition tab control if (pfrm->hwndTab) MoveWindow(pfrm->hwndTab, 0, 5, rect.right-rect.left, rect.top-5, TRUE); // reposition the frame window if (pfrm->hwndFrame) MoveWindow(pfrm->hwndFrame, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top, TRUE); // now that the frame window has the right size, resize all pages if (pfrm->hwndTab) SftTabs_ResizePages(pfrm->hwndTab); return 0L; } ``` The following WM_DESTROY message handler shows the required cleanup calls and also unregisters the dialog from SftTabs/DLL: ``` case WM_DESTROY: // Unregister, or the window properties used won't be removed SftTabs_UnregisterWindow(hwnd); // destroy all pages (BEFORE destroying tab control) SftTabs_Destroy(hwnd, pfrm->hwndTab); if (pfrm->hwndStatic) DestroyWindow(pfrm->hwndStatic); if (pfrm->hwndFrame) DestroyWindow(pfrm->hwndFrame); if (pfrm->hwndTab) DestroyWindow(pfrm->hwndTab); break; ``` The following WM_COMMAND message handler responds to notifications sent to the tabbed window by the tab control. When the user attempts to switch to another page by clicking a tab using the left mouse button or by using the keyboard, a SFTTABSN_SWITCHING notification is sent to the tabbed window. The window then calls SftTabs_DeactivatePage to test if the active page can be left. This call to SftTabs_DeactivatePage results in a WM_QUERYENDSESSION message being sent to the page's dialog or window procedure. Based on the window procedure's response, the page may or may not be deactivated. By handling the WM_QUERYENDSESSION message, a page can prevent a user from switching away from a tab. If a new tab has become active, the tabbed window receives a SFTTABSN_SWITCHED notification, so the associated page can be made active by the call to SftTabs_ActivatePage. ``` case WM_COMMAND: { HWND hwndCtl = (HWND) lParam; int id = LOWORD(wParam); int code = HIWORD(wParam); if (hwndCtl) { switch (id) { case IDC_TAB: switch (code) { case SFTTABSN_SWITCHING:// we're about to switch away from // the current page. If you need to know what the new // page will be use SftTabs_GetNextTab(hwndCtl). if (!SftTabs_DeactivatePage(hwnd, hwndCtl)) // couldn't deactivate current page, so don't switch SendMessage(hwndCtl, WM_CANCELMODE, 0, 0); break; case SFTTABSN_SWITCHED:// we switched to a new page SftTabs_ActivatePage(hwnd, hwndCtl, NULL, FALSE); break; } break; case IDOK: case IDCANCEL: if (code == BN_CLICKED) SendMessage(hwnd, WM_COMMAND, id, 0); break; } } else { switch (id) { case IDM_EXIT: // The currently active page will be called with a // WM_QUERYENDSESSION/SftTabs_GetEndPageMessage message to determine // whether it can be closed if (SftTabs_ClosePossible(hwnd, GetDlgItem(hwnd, IDC_TAB))) { DestroyWindow(hwnd); PostQuitMessage(0); } break; } } break; ``` At the end of the window procedure, a call to SftTabs_HandleDialogMessage should be made to allow SftTabs/DLL to process any messages. Without this call, SftTabs/DLL may not be able to provide the tabbed dialog handling. ``` ... other source code removed // Call SftTabs/DLL to let it handle some messages (mostly for keyboard accel. keys) { LRESULT lRes; if (SftTabs_HandleWindowMessage(hwnd, msg, wParam, lParam, &lRes)) return lRes; } return DefWindowProc(hwnd, msg, wParam, lParam); } ``` The SFTTABS_TAB structures used to define each tab in the tab control also define a callback routine of type SFTTABS_TABCALLBACK. This callback routine is responsible for creating and destroying the window which represents the page. SftTabs/DLL will hide and disable a window, but it is up to this callback routine to create and destroy the window. The following tab definition is repeated here so it can be shown next to the callback function: ``` static const SFTTABS_TAB Tab1 = { /*&Edit Control */ RGB(129,169,226), RGB(0,0,0), /* background, foreground color */ RGB(129,169,226), RGB(0,0,0), /* background, foreground color (when selected) */ { SFTTABS_GRAPH_NONE, 0 }, /* Bitmap, Icon */ TRUE, /* enabled/disabled */ 0, /* userdata */ (SFTTABS_DWORD_PTR) Page2_Callback, /* user supplied tab callback */ NULL, /* reserved */ RGB(0,0,255), /* Flyby foreground color */ RGB(129,169,226), /* Client area background color */ 0,0,0,0, /* animation values */ NULL, /* tab-specific ImageList handle*/ FALSE, /* hidden tab */ RGB(222,236,254), /* gradient fill background color */ RGB(129,169,226), RGB(222,236,254), /* gradient fill background color, active tab */ RGB(129,169,226), RGB(129,169,226), /* gradient fill client area color */ RGB(222,236,254), }; HWND CALLBACK Page2_Callback(BOOL fCreate, HWND hwndOwner, HWND hwndPage, HWND hwndTab) { if (fCreate) { // creating a new page if (hwndPage) { // already created, we could do some initialization here. // this will be called every time the page becomes active. // The WM_SHOWWINDOW message is also sent to the page and could // be used to determine activation/deactivation of the page. SetWindowText(hwndPage, TEXT("Thank you for coming back.")); return NULL; // return NULL, ignored } else { // create the window HWND hwnd; // Create the edit control // You can create and initialize any type of window here, not just dialogs. // Use CreateWindow to create other windows. Don't specify WS_VISIBLE, but // make sure you use WS_TABSTOP. hwnd = CreateWindow( /* Create the list box */ "EDIT", /* Window Class */ TEXT(""), /* Window Title (not used) */ WS_CHILD| /* Window Style */ WS_TABSTOP|ES_MULTILINE|ES_WANTRETURN, 0, 0, /* x, y */ 0, 0, /* cx, cy */ hwndOwner, /* Parent Window */ (HMENU) IDC_EDIT, /* control ID */ g_hInst, /* Application Instance */ NULL); /* creation data */ if (hwnd == NULL) /* create failed */ return NULL; SendMessage(hwnd, WM_SETFONT, SendMessage(hwndTab, WM_GETFONT, 0, 0L), FALSE); SetWindowText(hwnd, TEXT("This is an edit control.\r\nClick a tab or use Alt-xxx to switch to another tab. " " Make sure to look at the \"Dialog\" tab also.")); SftTabs_SetPageActive(hwnd, hwndTab, NULL); return hwnd; } } else { // destroying page if (hwndOwner) // - because we're switching away return hwndPage; // keep the window handle, don't destroy it else { // - because we're closing the main dialog DestroyWindow(hwndPage); return NULL; } } } ``` This callback routine is called by SftTabs/DLL to perform certain functions based on the parameters passed. The callback routine creates the window (page) using CreateWindow. ## Using C++/MFC *Source: https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/g_usingcpp* This section describes how to use SftTabs/DLL in an application written [using C](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/g_usingc)++ and the Microsoft Foundation Class library (MFC). ### Adding SftTabs/DLL to an Application Please see "[Building Applications](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/g_buildingapp)" to prepare a project for development with SftTabs/DLL. | | | | --- | --- | | A) | Every source program making use of a SftTabs/DLL control must include the required header file SftTb.h by using the #include directive. | ``` #include "SftTb.h" /* SftTabs/DLL required header file */ ``` This include statement should appear after the #include statement or can be included at the end of stdafx.h. The file is located in the directory \Program Files (x86)\Softelvdm\SftTabs DLL 7.0\Include (unless changed during the installation).The project settings may need to be updated so the #include file can be located (see "Building Applications" for more information). | | | | --- | --- | | B) | The source program SftTbM.CPP must be added to your project. It is added to the project, without making any modifications to the file, using Visual Studio's *Project, Add To Project, Files...* menu command. The file is located in the directory \Program Files (x86)\Softelvdm\SftTabs DLL 7.0\Include (unless changed during the installation).Instead of simply adding it to the project, you can include the file using the #include directive. However, it must be included in a source file (*.CPP) as it is not a header file and only one source file can #include the file SftTbM.CPP. | ``` #include "SftTbM.cpp" ``` This include statement should appear after the #include "SftTb.h" statement.The project settings may need to be updated so the source file or #include file can be located (see "Building Applications" for more information). | | | | --- | --- | | C) | In order to use SftTabs/DLL controls, an application must call the [CSftTabs::RegisterApp](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/function_registerapp) function. The call to this function is required so that SftTabs/DLL window classes can be registered. This call has to be made before any SftTabs/DLL controls are created. Add the following statement to your source code. The preferred location is the InitInstance member function of your CWinApp or CSftTabs_App based application object: | ``` CSftTabs::RegisterApp(); /* Use SftTabs/DLL with this application */ ``` | | | | --- | --- | | D) | Once SftTabs/DLL controls are no longer needed, an application must call the [CSftTabs::UnregisterApp](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/function_unregisterapp) function. The call to this function is required so that SftTabs/DLL window classes can be unregistered and cleanup processing can take place. This call has to be made after all SftTabs/DLL controls have been destroyed. The preferred location is the ExitInstance member function of your CWinApp based application object: | ``` CSftTabs::UnregisterApp(); /* No longer use SftTabs/DLL */ ``` | | | | --- | --- | | E) | The application's executable (Exe or Dll) must be linked with the correct [Lib file](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/g_distributing), depending on the target environment. Please see "Building Applications" for more information.The project settings may need to be updated so the Lib files can be located (see "Building Applications" for more information). | ### Adding a Tab Control ClassWizard does not support new classes such as [CSftTabs](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/i_cppclasses), so any tab control instance variables, notification handlers, message map entries, etc., have to be added manually. There are two methods to add a tab control to an application: - using dialog resources
  • using [CSftTabs::Create](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/function_csfttabs_create) - Adding a tab control using dialog resources is accomplished by using a resource editor to design a dialog. For more information, see [Creating a Dialog Resource](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/g_vc). Once a tab control is created, its CSftTabs based object can be obtained by using the Windows GetDlgItem function or attached to a CSftTabs object using SubclassDlgItem. ``` CSftTabs * pTab; pTab = (CSftTabs *) GetDlgItem(IDC_TAB); ``` or ``` CSftTabs m_Tab; m_Tab.SubclassDlgItem(IDC_TAB, this); ``` Another method to create a tab control is by using the CSftTabs::Create member function. ``` CSftTabs m_Tab; m_Tab.Create(WS_CHILD | WS_VISIBLE, CRect(250,200,400,700), pParentWnd, IDC_TABS); ``` For more information on the various parameters used, see the CSftTabs::Create member function documentation. ### Handling Notifications As with standard Windows controls, applications must respond to events and messages to cause controls to respond to user requests. For additional information, see [Notifications](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/i_notifications). ClassWizard does not support new classes such as CSftTabs, so any tab control instance variables, notification handlers, message map entries, etc., have to be added manually. To simplify this process, you can copy these items that are generated by ClassWizard for other "standard" Windows controls. #### Switching Between Tabs Switching between tabs is fully automatic, however, an application may wish to prevent a user from switching to another tab. By responding to the WM_COMMAND, SFTTABSN_SWITCHING notification, an application can prevent completion of the tab switch by sending a WM_CANCELMODE message to the tab control. ``` // Event handler prototype added to dialog/window class afx_msg void OnTabSwitching(); // Event handler(s) added to message map BEGIN_MESSAGE_MAP(CSampleView, CView) ON_SFTTABSN_SWITCHING(IDC_TAB, OnTabSwitching) END_MESSAGE_MAP() // Event handler implementation void CSampleView::OnTabSwitching() { if (YouDontLikeThisUser()) m_Tab.SendMessage(WM_CANCELMODE);// cancel switching } ``` An application has to make attached controls or dialogs visible when switching between tabs. The SftTabs/DLL API offers functions to manage dialogs and Windows controls that are attached to tabs. See Implementing Tabbed Dialogs and Implementing Tabbed Windows for more information. ### Implementing Tabbed Dialogs A tabbed dialog is created just like any other dialog. A tabbed dialog has a tab control with an available [client area](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/pop_clientarea). In this client area, pages are displayed. Each tab has an attached page (although during development of a tabbed dialog, a tab doesn't require an attached page). As the user switches between tabs, the appropriate page is created, displayed and destroyed. A tabbed dialog and each page are based on the class CSftTabsDialog and CSftTabsPage, which are both derived from the MFC class CDialog. This makes conversion of existing dialogs and development of new pages very easy. Tabbed dialogs and pages are first designed using a resource editor. The section Creating a Dialog Resource describes how the necessary tabbed dialog and page (dialog) resources are created. ClassWizard can be used to create the dialogs and pages. However, ClassWizard can only create new classes based on CDialog (not CSftTabsDialog or CSftTabsPage). After ClassWizard generates a new class derived from CDialog, you have to manually change references to CDialog to the classes CSftTabsDialog and CSftTabsPage. When adding new member functions, make sure to call the CSftTabsDialog and CSftTabsPage base classes instead of CDialog. Once the necessary dialogs have been designed, the tab control layout can be defined using the [SftTabs/DLL Wizard](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/g_wizarddesign). The SftTabs/DLL Wizard also creates much of the code required to initialize the tab control. This code should be copied to the application (with possibly minor modifications). #### Creating a Tabbed Dialog The following sample code (from \Program Files (x86)\Softelvdm\SftTabs DLL 7.0\Samples\MFC\Dialog\MainDlg.cpp) shows a typical implementation of a tabbed dialog. Most of the code has been created using the SftTabs/DLL Wizard and then copied into the application. ``` /*- Tab Control Initialization Data --------------------------------------------*/ static const SFTTABS_CONTROL CtlInit = { SFTTABSSTYLE_MODERN_I, /* tab style */ 2, /* number of rows */ 0, /* number of tabs per row (if fFixed) */ 0, /* width of left margin */ 0, /* width of right margin */ FALSE, /* same width for all tabs */ TRUE, /* Client area wanted */ FALSE, /* allow multiline label text */ TRUE, /* use with dialog */ FALSE, /* use specified background color only for text */ FALSE, /* scrollable tabs */ FALSE, /* hide scroll buttons */ TRUE, /* bold font for active tab wanted */ TRUE, /* fill rows completely */ NULL, /* scroll button bitmap */ NULL, /* Dialog data associated with active tab */ NULL, /* Dialog window handle associated with active tab */ NULL, /* Frame, used as client area */ TRUE, /* Tooltips wanted */ FALSE, /* drop text if it doesn't fit */ FALSE, /* conditional scroll buttons */ BMBUTTONSTYLE_STD, /* scroll button style */ FALSE, /* display ... if truncated */ TRUE, /* Flyby highlighting */ FALSE, /* use client area colors in partially obscured frames */ FALSE, /* scroll buttons on left side */ -1, /* row indentation */ FALSE, /* don't show truncated pattern for clipped tab */ FALSE, /* full size scroll buttons */ TRUE, /* use themes */ TRUE, /* use exact window region */ FALSE, /* always show prefix _ */ 0,0,0,0, /* animation values */ NULL, /* disabled button bitmap */ TRUE, /* focus rectangle if the control has i/p focus */ FALSE, /* TRUE if Close button wanted */ FALSE, /* TRUE if Close button disabled */ FALSE, /* TRUE if WM_CLOSE message wanted */ FALSE, /* TRUE if Minimize, Restore, Close buttons are full size */ SFTTABS_BUTTON_NEAR, /* scroll button alignment */ SFTTABS_BUTTON_NEAR, /* Minimize, Restore, Close button alignment */ FALSE, /* TRUE if Minimize button wanted */ FALSE, /* TRUE if Minimize button disabled */ FALSE, /* TRUE if Restore button wanted */ FALSE, /* TRUE if Restore button disabled */ NULL, /* Close, Minimize, Restore button bitmap */ NULL, /* Close, Minimize, Restore disabled button bitmap */ TEXT(""), /* scroll left button tooltip */ TEXT(""), /* scroll button tooltip */ TEXT(""), /* Close button tooltip */ TEXT(""), /* Minimize button tooltip */ TEXT(""), /* Restore button tooltip */ 0, /* custom modifications */ 0, /* forced height/width depending on tab style - 0 to ignore */ FALSE, /* switch tabs on button release (or down if FALSE) */ FALSE, /* Rendering compatible with pre-6.0 */ FALSE, /* don't display clientarea border - select styles only */ }; static const SFTTABS_TAB Tab0 = { /*The First One */ SFTTABS_NOCOLOR, RGB(0,0,255), /* background, foreground color */ SFTTABS_NOCOLOR, RGB(0,0,255), /* background, foreground color (when selected) */ { SFTTABS_GRAPH_LEFT, 0 }, /* location */ TRUE, /* enabled/disabled */ 0, /* userdata */ 0, /* reserved */ NULL, /* reserved */ SFTTABS_NOCOLOR, /* Flyby foreground color */ SFTTABS_NOCOLOR, /* Client area background color */ 0,0,0,0, /* animation values */ NULL, /* tab-specific ImageList handle*/ FALSE, /* hidden tab */ SFTTABS_NOCOLOR, /* gradient fill background color */ SFTTABS_NOCOLOR, SFTTABS_NOCOLOR, /* gradient fill background color, active tab */ SFTTABS_NOCOLOR, SFTTABS_NOCOLOR, /* gradient fill client area color */ SFTTABS_NOCOLOR, }; static const SFTTABS_TAB Tab1 = { /*&Second */ SFTTABS_NOCOLOR, RGB(255,0,0), /* background, foreground color */ SFTTABS_NOCOLOR, RGB(255,0,0), /* background, foreground color (when selected) */ { SFTTABS_GRAPH_RIGHT, 0 }, /* location */ TRUE, /* enabled/disabled */ 0, /* userdata */ 0, /* reserved */ NULL, /* reserved */ SFTTABS_NOCOLOR, /* Flyby foreground color */ SFTTABS_NOCOLOR, /* Client area background color */ 0,0,0,0, /* animation values */ NULL, /* tab-specific ImageList handle*/ FALSE, /* hidden tab */ SFTTABS_NOCOLOR, /* gradient fill background color */ SFTTABS_NOCOLOR, SFTTABS_NOCOLOR, /* gradient fill background color, active tab */ SFTTABS_NOCOLOR, SFTTABS_NOCOLOR, /* gradient fill client area color */ SFTTABS_NOCOLOR, }; static const SFTTABS_TAB Tab2 = { /*&Third */ SFTTABS_NOCOLOR, RGB(128,128,0), /* background, foreground color */ SFTTABS_NOCOLOR, RGB(128,128,0), /* background, foreground color (when selected) */ { SFTTABS_GRAPH_NONE, 0 }, /* location */ TRUE, /* enabled/disabled */ 0, /* userdata */ 0, /* reserved */ NULL, /* reserved */ SFTTABS_NOCOLOR, /* Flyby foreground color */ SFTTABS_NOCOLOR, /* Client area background color */ 0,0,0,0, /* animation values */ NULL, /* tab-specific ImageList handle*/ FALSE, /* hidden tab */ SFTTABS_NOCOLOR, /* gradient fill background color */ SFTTABS_NOCOLOR, SFTTABS_NOCOLOR, /* gradient fill background color, active tab */ SFTTABS_NOCOLOR, SFTTABS_NOCOLOR, /* gradient fill client area color */ SFTTABS_NOCOLOR, }; static const SFTTABS_TAB Tab3 = { /*F&ourth */ SFTTABS_NOCOLOR, RGB(0,255,255), /* background, foreground color */ SFTTABS_NOCOLOR, RGB(0,255,255), /* background, foreground color (when selected) */ { SFTTABS_GRAPH_NONE, 0 }, /* location */ TRUE, /* enabled/disabled */ 0, /* userdata */ 0, /* reserved */ NULL, /* reserved */ SFTTABS_NOCOLOR, /* Flyby foreground color */ SFTTABS_NOCOLOR, /* Client area background color */ 0,0,0,0, /* animation values */ NULL, /* tab-specific ImageList handle*/ FALSE, /* hidden tab */ SFTTABS_NOCOLOR, /* gradient fill background color */ SFTTABS_NOCOLOR, SFTTABS_NOCOLOR, /* gradient fill background color, active tab */ SFTTABS_NOCOLOR, SFTTABS_NOCOLOR, /* gradient fill client area color */ SFTTABS_NOCOLOR, }; static const SFTTABS_TAB Tab4 = { /*F&ifth */ SFTTABS_NOCOLOR, RGB(0,0,128), /* background, foreground color */ SFTTABS_NOCOLOR, RGB(0,0,128), /* background, foreground color (when selected) */ { SFTTABS_GRAPH_NONE, 0 }, /* location */ TRUE, /* enabled/disabled */ 0, /* userdata */ 0, /* reserved */ NULL, /* reserved */ SFTTABS_NOCOLOR, /* Flyby foreground color */ SFTTABS_NOCOLOR, /* Client area background color */ 0,0,0,0, /* animation values */ NULL, /* tab-specific ImageList handle*/ FALSE, /* hidden tab */ SFTTABS_NOCOLOR, /* gradient fill background color */ SFTTABS_NOCOLOR, SFTTABS_NOCOLOR, /* gradient fill background color, active tab */ SFTTABS_NOCOLOR, SFTTABS_NOCOLOR, /* gradient fill client area color */ SFTTABS_NOCOLOR, }; static const SFTTABS_TAB Tab5 = { /*Si&xth */ SFTTABS_NOCOLOR, RGB(128,0,0), /* background, foreground color */ SFTTABS_NOCOLOR, RGB(128,0,0), /* background, foreground color (when selected) */ { SFTTABS_GRAPH_NONE, 0 }, /* location */ TRUE, /* enabled/disabled */ 0, /* userdata */ 0, /* reserved */ NULL, /* reserved */ SFTTABS_NOCOLOR, /* Flyby foreground color */ SFTTABS_NOCOLOR, /* Client area background color */ 0,0,0,0, /* animation values */ NULL, /* tab-specific ImageList handle*/ FALSE, /* hidden tab */ SFTTABS_NOCOLOR, /* gradient fill background color */ SFTTABS_NOCOLOR, SFTTABS_NOCOLOR, /* gradient fill background color, active tab */ SFTTABS_NOCOLOR, SFTTABS_NOCOLOR, /* gradient fill client area color */ SFTTABS_NOCOLOR, }; ``` The OnInitDialog message handler of the tabbed dialog initializes the tab control and associates CSftTabsPage based objects to each tab. ``` BOOL CMainDlg::OnInitDialog() { CSftTabsDialog::OnInitDialog(); SetIcon(m_hIcon, TRUE); // Set big icon SetIcon(m_hIcon, FALSE); // Set small icon int index; SFTTABS_TAB Tab; /* Associate the tab control created from the dialog */ /* resource with the C++ object. */ m_Tab.SubclassDlgItem(IDC_TAB, this /* parent window */); /* You could use DDX/DDV instead and add the following */ /* line to the DoDataExchange function of the tab */ /* control's parent window (remove the //). */ // DDX_Control(pDX, IDC_TAB, m_Tab); /* Initialization is faster if we set redraw off */ m_Tab.SetRedraw(FALSE); /* We are using new features */ m_Tab.SetVersion(SFTTABS_7_0); index = m_Tab.AddTab(_T("The First One")); m_Tab.SetToolTip(index, _T("Demonstrates tabbing into and out of the tab page")); Tab = Tab0; Tab.graph.item.hBitmap = (HBITMAP) m_SampleBitmap.m_hObject; m_Tab.SetTabInfo(index, &Tab); m_Tab.SetTabDialog(index, new CPage1(this)); /* tab page */ index = m_Tab.AddTab(_T("&Second")); m_Tab.SetToolTip(index, _T("Demonstrates how an application can prevent tab switching")); Tab = Tab1; Tab.graph.item.hIcon = m_hSampleIcon; m_Tab.SetTabInfo(index, &Tab); m_Tab.SetTabDialog(index, new CPage2(this)); /* tab page */ index = m_Tab.AddTab(_T("&Third")); m_Tab.SetToolTip(index, _T("This page is reset everytime you switch to it")); m_Tab.SetTabInfo(index, &Tab2); m_Tab.SetTabDialog(index, new CPage3(this)); /* tab page */ index = m_Tab.AddTab(_T("F&ourth")); m_Tab.SetToolTip(index, _T("A page with private OK, Cancel, Next and Previous page buttons")); m_Tab.SetTabInfo(index, &Tab3); m_Tab.SetTabDialog(index, new CPage4(this)); /* tab page */ index = m_Tab.AddTab(_T("F&ifth")); m_Tab.SetToolTip(index, _T("A page that has not yet been implemented")); m_Tab.SetTabInfo(index, &Tab4); // If you don't want to attach a page to the tab, the following is optional // m_Tab.SetTabDialog(index, new an_object_based_on_CSftTabsPage(this)); /* tab page */ index = m_Tab.AddTab(_T("Si&xth")); m_Tab.SetToolTip(index, _T("A page with nested tab controls and pages")); m_Tab.SetTabInfo(index, &Tab5); m_Tab.SetTabDialog(index, new CPage6(this)); /* tab page */ m_Tab.SetControlInfo(&CtlInit); // Make sure to turn redraw back on m_Tab.SetRedraw(TRUE); m_Tab.InvalidateRect(NULL, TRUE); // If you are not using the sheet/page classes, remove the call to InitializeTabControl. // Initialize tab control InitializeTabControl(0, &m_Tab, NULL); // Update Tab2 to use transition effects { SFTTABS_TAB Tab; m_Tab.GetTabInfo(2, &Tab); Tab.animationStyleShow = SFTTABS_SLIDE_FROM_LEFT; Tab.animationTimeShow = 400; m_Tab.SetTabInfo(2, &Tab); } // Update Tab5 to use transition effects { SFTTABS_TAB Tab; m_Tab.GetTabInfo(5, &Tab); Tab.animationStyleShow = SFTTABS_EXPAND_CENTER; Tab.animationTimeShow = 400; m_Tab.SetTabInfo(5, &Tab); } { // Animate Window // Animation works on windows 98, 2000 or better only HMODULE hUser32 = GetModuleHandle(TEXT("USER32.DLL")); if (hUser32) { typedef BOOL (WINAPI* LPFNANIMATEWINDOW)(HWND, DWORD, DWORD); LPFNANIMATEWINDOW lpfnAnimateWindow; lpfnAnimateWindow = (LPFNANIMATEWINDOW)GetProcAddress(hUser32, "AnimateWindow"); if (lpfnAnimateWindow) { CenterWindow(); lpfnAnimateWindow(m_hWnd, 300, AW_HOR_POSITIVE); } } } return FALSE; // if this is a dialog's OnInitDialog member function } ``` Each call to [CSftTabs::SetTabDialog](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/function_csfttabs_settabdialog) associates a CSftTabsPage based dialog to a tab. Cleanup of all resources, including the dynamically allocated pages, is done automatically when the tabbed dialog is destroyed. The call to [InitializeTabControl](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/function_csfttabsdialog_initializetabcontrol) starts the tabbed dialog handling and creates the current page. A tabbed dialog should always return FALSE from the OnInitDialog member function. The input focus has already been set by SftTabs/DLL, so returning FALSE will prevent Windows from setting the focus (to the wrong control). #### Creating a Page The implementation of a page is identical to a regular dialog, except that the base class is CSftTabsPage instead of CDialog. > The tab page dialog resource must be defined as a child window with the WS_CHILD [window style](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/i_windowstyles). It cannot be defined as a popup or overlapped window (WS_POPUP or WS_OVERLAPPED) ### Implementing Tabbed Windows A tabbed window is created just like a regular window. A tabbed window has at least one tab control as its child window (with or without a client area). Each tab has an attached page (although during development of a tabbed window, a tab doesn't require an attached page). As the user switches between tabs, the appropriate page is created, displayed and destroyed. A tabbed window and each page are based on the class CWnd or any of its derived classes, such as CView, CFormView, etc. Using multiple inheritance, a window can inherit the required support to make it into a tabbed window or a page. This makes conversion of existing windows and development of new pages very easy. ClassWizard can be used to create the tabbed window and the pages initially. By using multiple inheritance, the classes CSftTabsWindowSheet and CSftTabsWindowPage are used to add tabbed window and page support to the new classes. #### Creating a Tabbed Window Most CWnd based classes are suitable to be used as a tabbed window. By using multiple inheritance, a class can be used as a tabbed window by inheriting the required support from the class CSftTabsWindowSheet. ``` class CSampleView : public CFormView, public CSftTabsWindowSheet { ... class definitions } ``` The following sample code (from \Program Files (x86)\Softelvdm\SftTabs DLL 7.0\Samples\MFC\SDI\SmplView.cpp) shows a typical implementation of a tabbed window. Most of the code has been created using the SftTabs/DLL Wizard and then copied into the application. ``` /*- Tab Control Initialization Data --------------------------------------------*/ static const SFTTABS_CONTROL CtlInit = { SFTTABSSTYLE_MODERN_I, /* tab style */ 1, /* number of rows */ 0, /* number of tabs per row (if fFixed) */ 2, /* width of left margin */ 0, /* width of right margin */ FALSE, /* same width for all tabs */ TRUE, /* Client area wanted */ FALSE, /* allow multiline label text */ TRUE, /* use with dialog */ FALSE, /* use specified background color only for text */ TRUE, /* scrollable tabs */ FALSE, /* hide scroll buttons */ FALSE, /* bold font for active tab wanted */ FALSE, /* fill rows completely */ NULL, /* scroll button bitmap */ NULL, /* Dialog data associated with active tab */ NULL, /* Dialog window handle associated with active tab */ NULL, /* Frame, used as client area */ TRUE, /* Tooltips wanted */ FALSE, /* drop text if it doesn't fit */ FALSE, /* conditional scroll buttons */ BMBUTTONSTYLE_THEME_SCROLL, /* scroll button style */ TRUE, /* display ... if truncated */ TRUE, /* Flyby highlighting */ TRUE, /* use client area colors in partially obscured frames */ TRUE, /* scroll buttons on left side */ -1, /* row indentation */ FALSE, /* don't show truncated pattern for clipped tab */ TRUE, /* full size scroll buttons */ TRUE, /* use themes */ TRUE, /* use exact window region */ FALSE, /* always show prefix _ */ 0,0,0,0, /* animation values */ NULL, /* disabled button bitmap */ TRUE, /* focus rectangle if the control has i/p focus */ FALSE, /* TRUE if Close button wanted */ FALSE, /* TRUE if Close button disabled */ FALSE, /* TRUE if WM_CLOSE message wanted */ FALSE, /* TRUE if Minimize, Restore, Close buttons are full size */ SFTTABS_BUTTON_NEAR, /* scroll button alignment */ SFTTABS_BUTTON_NEAR, /* Minimize, Restore, Close button alignment */ FALSE, /* TRUE if Minimize button wanted */ FALSE, /* TRUE if Minimize button disabled */ FALSE, /* TRUE if Restore button wanted */ FALSE, /* TRUE if Restore button disabled */ NULL, /* Close, Minimize, Restore button bitmap */ NULL, /* Close, Minimize, Restore disabled button bitmap */ TEXT(""), /* scroll left button tooltip */ TEXT(""), /* scroll button tooltip */ TEXT(""), /* Close button tooltip */ TEXT(""), /* Minimize button tooltip */ TEXT(""), /* Restore button tooltip */ 0, /* custom modifications */ 0, /* forced height/width depending on tab style - 0 to ignore */ FALSE, /* switch tabs on button release (or down if FALSE) */ FALSE, /* Rendering compatible with pre-6.0 */ FALSE, /* don't display clientarea border - select styles only */ }; static const SFTTABS_TAB Tab0 = { /*&1 Text */ SFTTABS_NOCOLOR, SFTTABS_NOCOLOR, /* background, foreground color */ SFTTABS_NOCOLOR, SFTTABS_NOCOLOR, /* background, foreground color (when selected) */ { SFTTABS_GRAPH_NONE, 0 }, /* location */ TRUE, /* enabled/disabled */ 0, /* userdata */ 0, /* reserved */ NULL, /* reserved */ SFTTABS_NOCOLOR, /* Flyby foreground color */ SFTTABS_NOCOLOR, /* Client area background color */ 0,0,0,0, /* animation values */ NULL, /* tab-specific ImageList handle*/ FALSE, /* hidden tab */ SFTTABS_NOCOLOR, /* gradient fill background color */ SFTTABS_NOCOLOR, SFTTABS_NOCOLOR, /* gradient fill background color, active tab */ SFTTABS_NOCOLOR, SFTTABS_NOCOLOR, /* gradient fill client area color */ SFTTABS_NOCOLOR, }; static const SFTTABS_TAB Tab1 = { /*&2 Statistics */ SFTTABS_NOCOLOR, SFTTABS_NOCOLOR, /* background, foreground color */ SFTTABS_NOCOLOR, SFTTABS_NOCOLOR, /* background, foreground color (when selected) */ { SFTTABS_GRAPH_NONE, 0 }, /* location */ TRUE, /* enabled/disabled */ 0, /* userdata */ 0, /* reserved */ NULL, /* reserved */ SFTTABS_NOCOLOR, /* Flyby foreground color */ SFTTABS_NOCOLOR, /* Client area background color */ 0,0,0,0, /* animation values */ NULL, /* tab-specific ImageList handle*/ FALSE, /* hidden tab */ SFTTABS_NOCOLOR, /* gradient fill background color */ SFTTABS_NOCOLOR, SFTTABS_NOCOLOR, /* gradient fill background color, active tab */ SFTTABS_NOCOLOR, SFTTABS_NOCOLOR, /* gradient fill client area color */ SFTTABS_NOCOLOR, }; static const SFTTABS_TAB Tab2 = { /*&3 Attributes */ SFTTABS_NOCOLOR, SFTTABS_NOCOLOR, /* background, foreground color */ SFTTABS_NOCOLOR, SFTTABS_NOCOLOR, /* background, foreground color (when selected) */ { SFTTABS_GRAPH_NONE, 0 }, /* location */ TRUE, /* enabled/disabled */ 0, /* userdata */ 0, /* reserved */ NULL, /* reserved */ SFTTABS_NOCOLOR, /* Flyby foreground color */ SFTTABS_NOCOLOR, /* Client area background color */ 0,0,0,0, /* animation values */ NULL, /* tab-specific ImageList handle*/ FALSE, /* hidden tab */ SFTTABS_NOCOLOR, /* gradient fill background color */ SFTTABS_NOCOLOR, SFTTABS_NOCOLOR, /* gradient fill background color, active tab */ SFTTABS_NOCOLOR, SFTTABS_NOCOLOR, /* gradient fill client area color */ SFTTABS_NOCOLOR, }; static const SFTTABS_TAB Tab3 = { /*S&oftel vdm, Inc. */ SFTTABS_NOCOLOR, SFTTABS_NOCOLOR, /* background, foreground color */ SFTTABS_NOCOLOR, SFTTABS_NOCOLOR, /* background, foreground color (when selected) */ { SFTTABS_GRAPH_NONE, 0 }, /* location */ TRUE, /* enabled/disabled */ 0, /* userdata */ 0, /* reserved */ NULL, /* reserved */ SFTTABS_NOCOLOR, /* Flyby foreground color */ SFTTABS_NOCOLOR, /* Client area background color */ 0,0,0,0, /* animation values */ NULL, /* tab-specific ImageList handle*/ FALSE, /* hidden tab */ SFTTABS_NOCOLOR, /* gradient fill background color */ SFTTABS_NOCOLOR, SFTTABS_NOCOLOR, /* gradient fill background color, active tab */ SFTTABS_NOCOLOR, SFTTABS_NOCOLOR, /* gradient fill client area color */ SFTTABS_NOCOLOR, }; ``` The Create member function of the tabbed window initializes the tab control and associates CSftTabsWindowPage based objects to each tab. ``` BOOL CSampleView::Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext) { if (!CFormView::Create(lpszClassName, lpszWindowName, dwStyle, rect, pParentWnd, nID, pContext)) return FALSE; m_SavedContext = *pContext; // save so we can use it later int index; /* Associate the tab control created from the dialog */ /* resource with the C++ object. */ m_MainTab.SubclassDlgItem(IDC_MAINTAB, this /* parent window */); /* You could use DDX/DDV instead and add the following */ /* line to the DoDataExchange function of the tab */ /* control's parent window (remove the //). */ // DDX_Control(pDX, IDC_MAINTAB, m_MainTab); /* Initialization is faster if we set redraw off */ m_MainTab.SetRedraw(FALSE); m_pTabEdit = new CTabEdit(); // Edit FormView m_pTabStats = new CStatsPage(); // Statistics page m_pTabAttr = new CAttrPage(); // Attributes page m_pTabLogo = new CLogo(); // Logo page /* We are using new features */ m_MainTab.SetVersion(SFTTABS_7_0); index = m_MainTab.AddTab(_T("&1 Text")); m_MainTab.SetToolTip(index, _T("Displays the currently opened file")); m_MainTab.SetTabInfo(index, &Tab0); m_MainTab.SetTabWindowPage(index, m_pTabEdit); m_pTabEdit->SaveContext(&m_SavedContext); // save doc/view context index = m_MainTab.AddTab(_T("&2 Statistics")); m_MainTab.SetToolTip(index, _T("Shows file information")); m_MainTab.SetTabInfo(index, &Tab1); m_MainTab.SetTabWindowPage(index, m_pTabStats); m_pTabStats->SaveContext(&m_SavedContext); // save doc/view context index = m_MainTab.AddTab(_T("&3 Attributes")); m_MainTab.SetToolTip(index, _T("Changes font and printer margin information")); m_MainTab.SetTabInfo(index, &Tab2); m_MainTab.SetTabWindowPage(index, m_pTabAttr); m_pTabAttr->SaveContext(&m_SavedContext); // save doc/view context index = m_MainTab.AddTab(_T("S&oftel vdm, Inc.")); m_MainTab.SetToolTip(index, _T("Company logo")); m_MainTab.SetTabInfo(index, &Tab3); m_MainTab.SetTabWindowPage(index, m_pTabLogo); m_MainTab.SetControlInfo(&CtlInit); // Make sure to turn redraw back on m_MainTab.SetRedraw(TRUE); m_MainTab.InvalidateRect(NULL, TRUE); // If you are not using the sheet/page classes, remove the call to InitializeTabControl. // Initialize tab control InitializeTabControl(this, 0, &m_MainTab, NULL); // Mark the view as a main, tabbed window (so accel. keys work) by registering it. SftTabs_RegisterWindow(m_hWnd); // resize this formview based on size of dialog in resource ResizeParentToFit(); return TRUE; } ``` Each call to [CSftTabs::SetTabWindowPage](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/function_csfttabs_settabwindowpage) associates a CSftTabsWindowPage based window with a tab. The call to [CSftTabsWindowSheet::InitializeTabControl](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/function_csfttabswindowsheet_initializetabcontrol) starts the tabbed window handling and creates the current page. Cleanup of all resources is accomplished by the call to [CSftTabsWindowSheet::TerminateTabControl](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/function_csfttabswindowsheet_terminatetabcontrol). ``` void CSampleView::OnDestroy() { // Remove all pages from the tab control TerminateTabControl(this, &m_MainTab); // Unregister, or the window properties used won't be removed SftTabs_UnregisterWindow(m_hWnd); // the logo page must be explicitly delete'd delete m_pTabLogo; CFormView::OnDestroy(); } ``` The following WM_SIZE message handler OnSize resizes the tabbed window's child windows: ``` void CSampleView::OnSize(UINT nType, int cx, int cy) { CFormView::OnSize(nType, cx, cy); if (m_MainTab.m_hWnd) { CRect rect; m_MainTab.GetClientRect(&rect); m_MainTab.MapWindowPoints(this, (LPPOINT)&rect, 2); m_MainTab.MoveWindow(rect.left, rect.top, cx-2*rect.left, cy-rect.top - rect.left, TRUE); } } ``` As the main tabbed window receives notifications from the tab control that the user is switching to another page, it has to handle these notifications using the [CSftTabsWindowSheet::TabSwitching](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/function_csfttabswindowsheet_tabswitching) and [CSftTabsWindowSheet::TabSwitched](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/function_csfttabswindowsheet_tabswitched) member functions. By calling the CSftTabsWindowSheet::TabSwitching member function, the class implementation then calls [CSftTabsWindowPage::AllowSwitch](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/function_csfttabswindowpage_allowswitch) to determine if the current page can be left, giving the application the opportunity to cancel tab switching. ``` void CSampleView::OnTabSwitching() { // Switching away from the current tab TabSwitching(this, &m_MainTab); } void CSampleView::OnTabSwitched() { // In case no one else wants to be an active view (such as the CLogo page), // we'll make the main view current GetParentFrame()->SetActiveView(this); // Switch to the new tab TabSwitched(this, &m_MainTab); // When switching tabs, views "grab" the input focus. You can explicitly set the // focus back to the tab control m_MainTab.SetFocus(); } ``` #### Creating a Page Most CWnd based classes are suitable to become a page in a tabbed window. By using multiple inheritance, a class can be used as a page by inheriting the required support from the class CSftTabsWindowPage. ``` class CAttrPage : public CFormView, public CSftTabsWindowPage { ... class definitions } ``` The following sample code (from \Program Files (x86)\Softelvdm\SftTabs DLL 7.0\Samples\MFC\SDI\AttrPage.cpp) shows a typical implementation of a page. Most of the code has been created using SftTabs/DLL Wizard. ``` BOOL CAttrPage::ActivatePage(CWnd* pParent, CSftTabs* pTabCtl) { // This is called when the user switches to a page if (!m_hWnd) { // The window doesn't exist, create it now. Make sure it's NOT VISIBLE // You can modify this to create another type of window instead. // The exact syntax of the Create function used depends on the base // class used. if (!Create(NULL, NULL, WS_TABSTOP | // Tabstop style is important WS_CHILD, CRect(0,0,0,0), // location pParent, // Parent Window IDC_ATTR, // control ID &m_SavedContext)) // make sure the above control ID does not collide with // IDs used by other pages or by the tab control itself return FALSE; // Additional initialization if desired // Because the document already exists, we need to explicitly call // OnInitialUpdate(); OnInitialUpdate(); } else { // The user switched back to this page } // This page is now active SftTabs_SetPageActive(m_hWnd, pTabCtl->m_hWnd, NULL); // Enable + show it, its size is 0,0,0,0, it will be resized by the tab control EnableWindow(TRUE); ShowWindow(SW_SHOW); // Make sure this view is made active GetParentFrame()->SetActiveView(this, TRUE); return TRUE; } void CAttrPage::DeactivatePage(CWnd* pParent, CSftTabs* pTabCtl, BOOL fFinal) { if (fFinal) { // You must destroy the window, the tabbed window (parent) is going away if (m_hWnd) DestroyWindow(); else PostNcDestroy(); // Views delete themselves in their PostNcDestroy member function // But that means a view has to have been "Create"ed for that to work. // For that reason we call PostNcDestroy explicitly in the DeactivatePage // routine of this object. That way the view can be "delete"ed without // having been "Create"ed first. } else { // Hide the page. If you want, you could use DestroyWindow here too. // In that case you save resources and the window will be recreated // when the user switches back to this page ShowWindow(SW_HIDE); EnableWindow(FALSE); } // clear associated page in tab's control structure SftTabs_SetPageInactive(pTabCtl->m_hWnd); } ``` The [CSftTabsWindowPage::ActivatePage](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/function_csfttabswindowpage_activatepage) and [CSftTabsWindowPage::DeactivatePage](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/function_csfttabswindowpage_deactivatepage) member functions must be implemented by a page. SftTabs/DLL Wizard generates the required sample code. These functions allow the application to do initialization and termination processing for each page. ## MFC and Notifications *Source: https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/g_notificationsmfc* [Notifications](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/i_notifications) can be handled by a tab control's parent window or directly by the tab control itself (in a derived class). WM_COMMAND messages are sent by the control to the parent window. The notification codes used are listed in section "Notifications". ### Parent Window If you want to handle Windows notification messages sent by a tab control to its parent (usually a class derived from CDialog or CView), add a message-map entry and a message-handler member function to the parent class for each notification. Message-map entries take the following form for WM_COMMAND and WM_NOTIFY notifications: ``` ON_Notification( id, memberFxn ) ``` The parent's function prototype is as follows: ``` /* for WM_COMMAND notifications */ afx_msg void memberFxn( ); ``` ``` /* for WM_NOTIFY notifications - not currently used */ afx_msg void memberFxn(NMHDR * pNotifyStruct, LRESULT* result); ``` *Notification* specifies one of the available notification codes listed in Notifications. *id *specifies the child window ID of the control sending the notification and *memberFxn* is the name of the parent member function in your application which handles the notification. ### Example ``` // Event handler prototype added to dialog/window class afx_msg void OnTabSwitching(); // Event handler(s) added to message map BEGIN_MESSAGE_MAP(CSampleView, CView) ON_SFTTABSN_SWITCHING(IDC_TAB, OnTabSwitching) END_MESSAGE_MAP() // Event handler implementation void CSampleView::OnTabSwitching() { if (!SwitchingOK()) m_Tab.SendMessage(WM_CANCELMODE);// cancel switching } ``` ### Derived Objects By overriding the OnChildNotify function of an object derived from [CSftTabs](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/i_cppclasses), you can handle messages in the object's class. The parameters are as documented in Notifications. Please see the MFC documentation for additional information regarding the OnChildNotify function. However, the use of message reflection as shown next is the preferred method to handle messages. MFC defines the ON_CONTROL_REFLECT and ON_NOTIFY_REFLECT macros which allow adding notifications directly to the message map. SftTabs/DLL implements all required macros based on ON_CONTROL_REFLECT and ON_NOTIFY_REFLECT. See the MFC documentation for more information on message reflection. Message-map entries take the following form: ``` ON_Notification_REFLECT( memberFxn ) ``` The function prototype is as follows: ``` /* for WM_COMMAND notifications */ afx_msg void memberFxn( ); ``` ``` /* for WM_NOTIFY notifications - not currently used */ afx_msg void memberFxn(NMHDR * pNotifyStruct, LRESULT* result); ``` *Notification* specifies one of the available notification codes listed in Notifications. memberFxn is the name of the member function in your object's class which handles the notification. ### Example ``` // Event handler prototype added to dialog/window class afx_msg void OnTabSwitching(); // Event handler(s) added to message map BEGIN_MESSAGE_MAP(CSampleView, CView) ON_SFTTABSN_SWITCHING(IDC_TAB, OnTabSwitching) END_MESSAGE_MAP() // Event handler implementation void CSampleView::OnTabSwitching() { if (!SwitchingOK()) m_Tab.SendMessage(WM_CANCELMODE);// cancel switching } ``` ## Distributing the Dlls *Source: https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/g_distributing* Distributing the DLLs included with SftTabs DLL 7.0 is only possible in accordance with the licensing agreement. The licensing agreement is furnished with the purchase of SftTabs DLL 7.0. The DLLs contain your license number and are serialized. Modification of the original DLLs as included with the product is not permitted to insure that no incompatibilities exist between different software packages that use SftTabs DLL 7.0. Any install procedure that is used to install DLLs which are included with SftTabs DLL 7.0 must do proper version checking. > Applications you create with SftTabs/DLL for distribution must be complete end-user applications. It is not possible to distribute the controls to unlicensed users for development purposes. This means that your distributed end-user application cannot be a Debug build, cannot contain debug information, symbol information, etc. ### DLLs The following DLLs can be distributed royalty-free with your application in accordance with the licensing agreement. The licensing agreement is furnished with the purchase of SftTabs DLL 7.0. The application's executable (Exe or DLL) must be linked with the correct LIB file, depending on the target environment and the compiler used. The DLL must be available and accessible at run-time for proper execution (unless static [linking](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/g_buildingapp) is used). The DLL used at run-time depends on the LIB file used at link time. For the required DLL, please see "Building Applications". If the application in linked statically to SftTabs/DLL 7.0, a DLL is not required. All required files can be found in the directory \Program Files (x86)\Softelvdm\SftTabs DLL 7.0\Lib and \Program Files (x86)\Softelvdm\SftTabs DLL 7.0\DLL, unless changed during the installation. Please note that available processor support depends on the installed and purchased product versions. ### GDI+ (Optional) Certain features of the control require [GDI+](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/g_gdiplus) support. GDI+ is available on all supported Windows versions (Windows 10 and above). If GDI+ support is not available, the features are simply disabled and alternate presentation methods are used, if necessary. ### Target Directory The DLLs can be installed in the application's directory and can be used locally, without interfering with any other applications which may use other versions of SftTabs DLL 7.0. The DLLs included with SftTabs/DLL can also be installed in the Windows System directory. 64-bit DLLs are installed in the System32 directory and 32-bit DLLs are installed in the SysWOW64 directory. When installing DLLs in Windows directories, strict version checking and reference counting must be performed to avoid conflicts if different software packages use SftTabs/DLL. ### Version Checking The DLLs included with SftTabs/DLL carry proper version information. A shared DLL should only be replaced if its version information indicates that the existing DLL is older. Commercial installers and setup programs have built-in features to insure proper DLL versioning. See your installer's documentation for more information. ### Reference Counting If a DLL is installed into the Windows System(32) or SysWOW64 directory, it can potentially be installed and used by other applications also. It is required that any DLL installed in such a shared location keep proper reference counts by updating the proper Windows registry keys: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\SharedDLLs Commercial installers and setup programs have built-in features to insure proper usage and reference counting. See your installer's documentation for more information. ## Technical Support for SftTabs/DLL 7.0 *Source: https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/g_contactsoftel* ### Product Updates New major versions and product maintenance are available with an active [support subscription](https://softelvdm.com/About/Support%20Subscription). Your product purchase includes the first year's support subscription at no extra charge. After the first year, the support subscription can be renewed for continued availability of major versions and product maintenance. While your support subscription is active, free product maintenance for the current release is available from our web site. Such free updates usually don't include any [new features](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200/Topic/g_newfeatures) as a new release would, but include product and documentation fixes and corrections. In addition, new major and minor versions are also available at no extra charge for the duration of your active support subscription. You can download updates by using the *Product Update* entry in the *SftTabs/DLL 7.0* program group of the Start menu or from the *Product Updates* link on the About dialog. ### Before Contacting Product Support Your product purchase includes the first year's support subscription at no extra charge, which includes free product support. After the first year, the support subscription can be renewed for continued availability of product support, major versions and product maintenance. - Obtain help using the documentation provided at [https://softelvdm.com/Documentation/SftTabs DLL 7 0](https://softelvdm.com/Documentation/SftTabs%20DLL%207%200). - Review support information or download product maintenance from our web site at [https://softelvdm.com/Product/Support/Name/SftTabs DLL 7 0?ProductId=3126](https://softelvdm.com/Product/Support/Name/SftTabs%20DLL%207%200?ProductId=3126). If this does not resolve your problem, please contact Softel vdm, Inc. Product Support. ### Contacting Product Support If you have reviewed the product documentation, please contact Softel vdm, Inc. Product Support. For current contact information please visit [https://softelvdm.com/support](https://softelvdm.com/support). **IMPORTANT: **Please include your license number in all cases. Without your license number, we will not be able to help you. Your license number is printed on your installation media (CD) or you may have received it as part of your online delivery.