Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Guarantee Correct Spacing for toolbar Separators on Multiple TB_ADDBUTTONS Calls

0.00/5 (No votes)
16 Jan 2020 1  
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.

Image 1

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:

Image 2

Using the Code

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

/// <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 has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here