Click here to Skip to main content
15,881,424 members
Articles / Desktop Programming / Win32
Tip/Trick

Guarantee Correct Spacing for toolbar Separators on Multiple TB_ADDBUTTONS Calls

Rate me:
Please Sign up or sign in to vote.
5.00/5 (2 votes)
15 Jan 2020CPOL 3.6K   3  
A solution for: If the toolbar is created button by button with single TB_ADDBUTTONS calls, the width of the separators is not calculated correctly.

Introduction

I create my toolbar by single TB_ADDBUTTONS message calls. I used TB_ADDBUTTONS message calls to create separators as well. But the width of the separators starts too small and then it increases with each separator.

Background

To get the right separator width (8px each), the TBSTYLE_SEP must not be added to the toolbar separately. To solve this problem, I changed my API and added the bPrependSeparator argument. This is the result:

Using the Code

I know - it could be made shorter, but the code is readable and does what it should:

C++
/// <summary>
/// Adds a new button to the tool bar.
/// </summary>
/// <param name="hBmpImage">The handler of the tool bar button image bitmap.
/// Can be <c>NULL</c>, if <c>byStyle</c> doesn't need an image.</param>
/// <param name="hBmpMask">The handler of the tool bar button mask bitmap.
/// Can be <c>NULL</c>, if transparency is not required.</param>
/// <param name="uiCommandID">The tool bar button command ID, that is in sync
/// with the menu item command ID.</param>
/// <param name="byState">The initial tool bar button state.</param>
/// <param name="byStyle">The tool bar button style.</param>
/// <param name="wszText">The optional text to display below the image.</param>
/// <param name="bPrependSeparator">The flag determining whether to prepend a separator.
/// </param>
/// <returns>The number of remaining image list slots for tool bar button images.</returns>
/// <remarks>Can still be called like this to create an not-prepended separator
/// (but the space isn't correct):
/// pToolBar->AddButton(NULL, NULL, (UINT)0, TBSTATE_ENABLED, TBSTYLE_SEP);</remarks>
UINT OgwwToolBar::AddButton(HBITMAP hBmpImage, HBITMAP hBmpMask, 
                            UINT uiCommandID, BYTE byState,
                            BYTE byStyle, LPCWSTR wszText, BOOL bPrependSeparator)
{
    if (hBmpImage != NULL)
    {
        ::ImageList_Add(_hImageList, hBmpImage, hBmpMask);
        _wBitmapUsed++;
    }

    if (bPrependSeparator != FALSE)
    {
        TBBUTTON tbb[2];
        ::ZeroMemory(tbb, sizeof(tbb));

        tbb[0].iBitmap   = 0;
        tbb[0].idCommand = 0;
        tbb[0].fsState   = TBSTATE_ENABLED;
        tbb[0].fsStyle   = TBSTYLE_SEP;
        tbb[0].iString   = 0;

        tbb[1].iBitmap   = (_hImageList != NULL) ? _wBitmapUsed - 1 : 0;
        tbb[1].idCommand = uiCommandID;
        tbb[1].fsState   = byState;
        tbb[1].fsStyle   = byStyle;
        tbb[1].iString   = 0; // SendMessageW(hToolBar, TB_ADDSTRING, 0, (LPARAM)wszText);

        // Try this if it doesn't work out right away:
        //::SendMessageW((HWND)_hHandle, TB_BUTTONSTRUCTSIZE, (WPARAM)sizeof(TBBUTTON), 0);
        ::SendMessageW((HWND)_hHandle, TB_ADDBUTTONS, 2, (LPARAM)tbb);
    }
    else
    {
        TBBUTTON tbb;
        ::ZeroMemory(&tbb, sizeof(tbb));

        tbb.iBitmap   = (_hImageList != NULL) ? _wBitmapUsed - 1 : 0;
        tbb.idCommand = uiCommandID;
        tbb.fsState   = byState;
        tbb.fsStyle   = byStyle;
        tbb.iString   = 0; // SendMessageW(hToolBar, TB_ADDSTRING, 0, (LPARAM)wszText);

        ::SendMessageW((HWND)_hHandle, TB_ADDBUTTONS, 1, (LPARAM)&tbb);
    }

    return (_wBitmapCount - _wBitmapUsed);
}

Happy programming!

Points of Interest

Not everything that is allowed/compiles works.

History

  • 16th January, 2020: Initial version

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Team Leader Celonis SA
Germany Germany
I am currently the CEO of Symbioworld GmbH and as such responsible for personnel management, information security, data protection and certifications. Furthermore, as a senior programmer, I am responsible for the automatic layout engine, the simulation (Activity Based Costing), the automatic creation of Word/RTF reports and the data transformation in complex migration projects.

The main focus of my work as a programmer is the development of Microsoft Azure Services using C# and Visual Studio.

Privately, I am interested in C++ and Linux in addition to C#. I like the approach of open source software and like to support OSS with own contributions.

Comments and Discussions

 
-- There are no messages in this forum --