HeaderPane
Main
Hide

SftButton/DLL 3.0 - Button Control

Share Link
Print

Simple Sample (C++/MFC)

This sample illustrates SftButton creation and configuration from a C++/MFC application. It covers process-wide registration, attaching CSftButton instances to dialog template controls through DDX_Control, configuring buttons through SFTBUTTON_CONTROL, loading and freeing GDI+ images for the Picture1 / Picture2 slots, runtime dark-mode and theme toggles, and routing dark-mode painting through the SftDarkMode helper.

The dialog hosts three SftButton controls and two checkboxes:

The source code is located at C:\Program Files (x86)\Softelvdm\SftButton DLL 3.0\Samples\MFC\Simple\ (or C:\Program Files\Softelvdm\SftButton DLL 3.0\Samples\MFC\Simple\ on 32-bit Windows versions).

Simple.cpp - CWinApp initialization

The CWinApp-derived class registers the SftButton window class in InitInstance and unregisters it in ExitInstance. SftDarkMode_Init runs alongside so dark-mode painting is available before the main dialog is shown.

/****************************************************************************/
/* SftButton/DLL 3.0 - Button Control for C/C++                             */
/* Copyright (C) 2026  Softel vdm, Inc. All Rights Reserved.                */
/****************************************************************************/

#include "stdafx.h"
#include "Simple.h"
#include "Maindlg.h"

#ifdef _DEBUG
#undef THIS_FILE
static char BASED_CODE THIS_FILE[] = __FILE__;
#endif

BEGIN_MESSAGE_MAP(CSimpleApp, CWinApp)
END_MESSAGE_MAP()

CSimpleApp::CSimpleApp()
{
}

CSimpleApp NEAR theApp;

BOOL CSimpleApp::InitInstance()
{
    SftDarkMode_Init();                  // Dark mode support
    CSftButton::RegisterApp();           // Register with SftButton/DLL

    CMainDlg dlg;
    m_pMainWnd = &dlg;
    dlg.DoModal();

    return FALSE;
}

int CSimpleApp::ExitInstance()
{
    CSftButton::UnregisterApp();         // Unregister from SftButton/DLL
    return CWinApp::ExitInstance();
}

Maindlg.h - dialog class

CMainDlg embeds three CSftButton members - one per dialog control - and two LPVOID slots for the GDI+ images that Button 2 displays. DDX_Control attaches the embedded CSftButton instances to the dialog-template controls in DoDataExchange.

/****************************************************************************/
/* SftButton/DLL 3.0 - Button Control for C/C++                             */
/* Copyright (C) 2026  Softel vdm, Inc. All Rights Reserved.                */
/****************************************************************************/

class CMainDlg : public CDialog
{
public:
    CMainDlg(CWnd* pParent = NULL);

    enum { IDD = IDD_MAIN };

    CSftButton m_Button1;
    CSftButton m_Button2;
    CSftButton m_Button3;

    LPVOID m_pImg1;                     // GDI+ image for Button2 Picture1
    LPVOID m_pImg2;                     // GDI+ image for Button2 Picture2

protected:
    virtual void DoDataExchange(CDataExchange* pDX);
    virtual BOOL OnInitDialog();
    virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam);

    afx_msg void OnButton1();
    afx_msg void OnButton2();
    afx_msg void OnButton3();
    afx_msg void OnButton3DropDown();
    afx_msg void OnUseThemes();
    afx_msg void OnDarkMode();
    afx_msg void OnDestroy();
    afx_msg void OnSettingChange(UINT uFlags, LPCTSTR lpszSection);

    DECLARE_MESSAGE_MAP()
};

Maindlg.cpp - dialog implementation

OnInitDialog configures each button through GetControlInfo / SetControlInfo, loads the GDI+ images for Button 2, and applies dark mode to the dialog itself with SftDarkMode_ApplyToDialog. ON_BN_CLICKED and ON_CONTROL entries in the message map dispatch click and drop-down notifications. OnDestroy frees the GDI+ images with SftButton_FreeGDIPlusImageLoadedFromFile after the controls have stopped using them. WindowProc forwards messages to SftDarkMode_HandleDialogMessage so the dialog repaints correctly under dark mode. OnSettingChange forwards WM_SETTINGCHANGE / ImmersiveColorSet to each button so AUTO-mode buttons re-render when the user flips the Windows "Choose your mode" setting at runtime.

/****************************************************************************/
/* SftButton/DLL 3.0 - Button Control for C/C++                             */
/* Copyright (C) 2026  Softel vdm, Inc. All Rights Reserved.                */
/****************************************************************************/

#include "stdafx.h"
#include "Simple.h"
#include "Maindlg.h"

#ifdef _DEBUG
#undef THIS_FILE
static char BASED_CODE THIS_FILE[] = __FILE__;
#endif

#define SFTBUTTONN_DROPDOWNCLICK            17

CMainDlg::CMainDlg(CWnd* pParent /*=NULL*/)
    : CDialog(CMainDlg::IDD, pParent)
    , m_pImg1(NULL)
    , m_pImg2(NULL)
{
}

void CMainDlg::DoDataExchange(CDataExchange* pDX)
{
    CDialog::DoDataExchange(pDX);
    DDX_Control(pDX, IDC_SFTBUTTON1, m_Button1);
    DDX_Control(pDX, IDC_SFTBUTTON2, m_Button2);
    DDX_Control(pDX, IDC_SFTBUTTON3, m_Button3);
}

BEGIN_MESSAGE_MAP(CMainDlg, CDialog)
    ON_BN_CLICKED(IDC_SFTBUTTON1, OnButton1)
    ON_BN_CLICKED(IDC_SFTBUTTON2, OnButton2)
    ON_BN_CLICKED(IDC_SFTBUTTON3, OnButton3)
    ON_CONTROL(SFTBUTTONN_DROPDOWNCLICK, IDC_SFTBUTTON3, OnButton3DropDown)
    ON_BN_CLICKED(IDC_USE_THEMES, OnUseThemes)
    ON_BN_CLICKED(IDC_DARK_MODE, OnDarkMode)
    ON_WM_DESTROY()
    ON_WM_SETTINGCHANGE()
END_MESSAGE_MAP()

BOOL CMainDlg::OnInitDialog()
{
    CDialog::OnInitDialog();

    // Set dialog icon
    HICON hIcon = AfxGetApp()->LoadIcon(IDI_ICON1);
    SetIcon(hIcon, TRUE);
    SetIcon(hIcon, FALSE);

    // Apply dark mode to dialog
    SftDarkMode_ApplyToDialog(m_hWnd);

    // Configure SftButton control 1
    {
        SFTBUTTON_CONTROL Ctl;
        Ctl.cbSize = sizeof(SFTBUTTON_CONTROL);
        m_Button1.GetControlInfo(&Ctl);
        Ctl.nDarkMode = SFTBUTTON_DARKMODE_AUTO;/* automatic dark mode support */
        m_Button1.SetControlInfo(&Ctl);
    }

    // Configure SftButton control 2
    {
        SFTBUTTON_CONTROL Ctl;
        Ctl.cbSize = sizeof(SFTBUTTON_CONTROL);
        m_Button2.GetControlInfo(&Ctl);
        Ctl.nDarkMode = SFTBUTTON_DARKMODE_AUTO;/* automatic dark mode support */
        Ctl.Text.align = SFT_PICALIGN_LEFT;/* text horizontal alignment */
        m_pImg1 = SftButton_LoadGDIPlusImageFromFile(_T("Res\\pic_world_48.png"));
        if (m_pImg1) Sft_SetPictureGDIPlusImage(&Ctl.Picture1, m_pImg1);
        Ctl.Picture1.align = SFT_PICALIGN_CENTER;
        Ctl.Picture1.valign = SFT_PICALIGN_VCENTER;
        m_pImg2 = SftButton_LoadGDIPlusImageFromFile(_T("Res\\pic_go_32.png"));
        if (m_pImg2) Sft_SetPictureGDIPlusImage(&Ctl.Picture2, m_pImg2);
        Ctl.Picture2.align = SFT_PICALIGN_LEFT;
        Ctl.Picture2.valign = SFT_PICALIGN_VCENTER;
        m_Button2.SetControlInfo(&Ctl);
    }

    // Configure SftButton control 3
    {
        SFTBUTTON_CONTROL Ctl;
        Ctl.cbSize = sizeof(SFTBUTTON_CONTROL);
        m_Button3.GetControlInfo(&Ctl);
        Ctl.fShowDropDown = TRUE;/* show drop-down arrow */
        Ctl.nDarkMode = SFTBUTTON_DARKMODE_AUTO;/* automatic dark mode support */
        m_Button3.SetControlInfo(&Ctl);
    }

    CheckDlgButton(IDC_USE_THEMES, BST_CHECKED);
    CheckDlgButton(IDC_DARK_MODE, SftDarkMode_IsActive() ? BST_CHECKED : BST_UNCHECKED);

    return TRUE;
}

void CMainDlg::OnButton1()
{
    AfxMessageBox(_T("Button 1 clicked!"));
}

void CMainDlg::OnButton2()
{
    AfxMessageBox(_T("Button 2 clicked!"));
}

void CMainDlg::OnButton3()
{
    AfxMessageBox(_T("Button 3 clicked!"));
}

void CMainDlg::OnButton3DropDown()
{
    AfxMessageBox(_T("Button 3 drop-down clicked!"));
}

void CMainDlg::OnUseThemes()
{
    int useThemes = (IsDlgButtonChecked(IDC_USE_THEMES) == BST_CHECKED)
                  ? SFTBUTTON_THEME_YES : SFTBUTTON_THEME_NO;
    CSftButton* btns[] = { &m_Button1, &m_Button2, &m_Button3 };
    for (int i = 0; i < (int)(sizeof(btns) / sizeof(btns[0])); ++i) {
        SFTBUTTON_CONTROL Ctl;
        Ctl.cbSize = sizeof(SFTBUTTON_CONTROL);
        btns[i]->GetControlInfo(&Ctl);
        Ctl.nUseThemes = useThemes;
        btns[i]->SetControlInfo(&Ctl);
    }
}

void CMainDlg::OnDarkMode()
{
    BOOL fDark = (IsDlgButtonChecked(IDC_DARK_MODE) == BST_CHECKED);
    int btnMode = fDark ? SFTBUTTON_DARKMODE_ON : SFTBUTTON_DARKMODE_OFF;
    m_Button1.SetDarkMode(btnMode);
    m_Button2.SetDarkMode(btnMode);
    m_Button3.SetDarkMode(btnMode);
    SftDarkMode_SetActive(fDark);
    SftDarkMode_ApplyToDialog(m_hWnd);
    InvalidateRect(NULL, TRUE);
}

void CMainDlg::OnDestroy()
{
    // Free GDI+ images now that the controls no longer reference them.
    if (m_pImg1) { SftButton_FreeGDIPlusImageLoadedFromFile(m_pImg1); m_pImg1 = NULL; }
    if (m_pImg2) { SftButton_FreeGDIPlusImageLoadedFromFile(m_pImg2); m_pImg2 = NULL; }
    CDialog::OnDestroy();
}

LRESULT CMainDlg::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
    // Route through SftDarkMode first so it can handle WM_CTLCOLOR*, WM_ERASEBKGND, etc.
    INT_PTR dmResult;
    if (SftDarkMode_HandleDialogMessage(m_hWnd, message, wParam, lParam, &dmResult))
        return dmResult;
    return CDialog::WindowProc(message, wParam, lParam);
}

void CMainDlg::OnSettingChange(UINT uFlags, LPCTSTR lpszSection)
{
    CDialog::OnSettingChange(uFlags, lpszSection);
    // Forward to the SftButton controls so they can update (AUTO mode)
    if (lpszSection && lstrcmpW((LPCWSTR)lpszSection, L"ImmersiveColorSet") == 0) {
        SftDarkMode_Init();
        SftDarkMode_ApplyToDialog(m_hWnd);
        m_Button1.SendMessage(WM_SETTINGCHANGE, uFlags, (LPARAM)lpszSection);
        m_Button2.SendMessage(WM_SETTINGCHANGE, uFlags, (LPARAM)lpszSection);
        m_Button3.SendMessage(WM_SETTINGCHANGE, uFlags, (LPARAM)lpszSection);
        InvalidateRect(NULL, TRUE);
    }
}

See Also Using C++/MFC | MFC and Notifications | Dark Mode | GDI+


Last Updated 05/09/2026 - (email)
© 2026 Softel vdm, Inc.