0

I've got a standard Win32 application with a Toolbar and a Rebar control. I create the Toolbar control first, as a child of the main window, and then create the Rebar adding a band with the Toolbar.

A gripper appears at the bottom of the Toolbar, which is unexpected:

Image of problem

Here's my creation code (copied from MSDN):

HIMAGELIST g_hImageList = NULL;

HWND CreateSimpleToolbar(HWND hWndParent)
{
    // Declare and initialize local constants.
    const int ImageListID = 0;
    const int numButtons = 3;
    const int bitmapSize = 16;

    const DWORD buttonStyles = BTNS_AUTOSIZE;

    // Create the toolbar.
    HWND hWndToolbar = CreateWindowEx(0, TOOLBARCLASSNAME, NULL,
        WS_CHILD | TBSTYLE_FLAT | TBSTYLE_LIST, 0, 0, 0, 0,
        hWndParent, NULL, hInst, NULL);

    if (hWndToolbar == NULL)
        return NULL;

    // Create the image list.
    g_hImageList = ImageList_Create(bitmapSize, bitmapSize,   // Dimensions of individual bitmaps.
        ILC_COLOR16 | ILC_MASK,   // Ensures transparent background.
        numButtons, 0);

    // Set the image list.
    SendMessage(hWndToolbar, TB_SETIMAGELIST,
        (WPARAM)ImageListID,
        (LPARAM)g_hImageList);

    // Load the button images.
    SendMessage(hWndToolbar, TB_LOADIMAGES,
        (WPARAM)IDB_STD_SMALL_COLOR,
        (LPARAM)HINST_COMMCTRL);

    // Initialize button info.
    // IDM_NEW, IDM_OPEN, and IDM_SAVE are application-defined command constants.

    TBBUTTON tbButtons[numButtons] =
    {
        { MAKELONG(STD_FILENEW,  ImageListID), 100,  TBSTATE_ENABLED, buttonStyles, {0}, 0, (INT_PTR)L"Back"},
        { MAKELONG(STD_FILEOPEN, ImageListID), 101,  TBSTATE_ENABLED, buttonStyles, {0}, 0, (INT_PTR)L"Forward"},
        { MAKELONG(STD_FILESAVE, ImageListID), 102,  0,               buttonStyles, {0}, 0, (INT_PTR)L"Save"}
    };

    // Add buttons.
    SendMessage(hWndToolbar, TB_BUTTONSTRUCTSIZE, (WPARAM)sizeof(TBBUTTON), 0);
    SendMessage(hWndToolbar, TB_ADDBUTTONS, (WPARAM)numButtons, (LPARAM)&tbButtons);

    // Resize the toolbar, and then show it.
    SendMessage(hWndToolbar, TB_AUTOSIZE, 0, 0);
    ShowWindow(hWndToolbar, TRUE);

    return hWndToolbar;
}

#define NUMBUTTONS 3

HWND CreateRebar(HWND hwndOwner, HWND hwndNavbar)
{
    // Check parameters.
    if ((hwndNavbar == NULL))
    {
        return NULL;
    }

    // Initialize common controls.
    INITCOMMONCONTROLSEX icex;
    icex.dwSize = sizeof(INITCOMMONCONTROLSEX);
    icex.dwICC = ICC_COOL_CLASSES | ICC_BAR_CLASSES;
    InitCommonControlsEx(&icex);

    // Create the rebar.
    HWND hwndRebar = CreateWindowEx(WS_EX_TOOLWINDOW,
        REBARCLASSNAME,
        NULL,
        WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS |
        WS_CLIPCHILDREN | RBS_VARHEIGHT |
        CCS_NODIVIDER | RBS_BANDBORDERS,
        0, 0, 0, 0,
        hwndOwner,
        NULL,
        hInst, // global instance handle
        NULL);

    if (!hwndRebar)
    {
        return NULL;
    }

    // Initialize band info used by both bands.
    REBARBANDINFO rbBand = { REBARBANDINFOA_V3_SIZE };
    rbBand.fMask =
        RBBIM_STYLE       // fStyle is valid.
        | RBBIM_TEXT        // lpText is valid.
        | RBBIM_CHILD       // hwndChild is valid.
        | RBBIM_CHILDSIZE   // child size members are valid.
        | RBBIM_SIZE;       // cx is valid
    rbBand.fStyle = RBBS_CHILDEDGE | RBBS_GRIPPERALWAYS;

    // Get the height of the toolbar.
    DWORD dwBtnSize = (DWORD)SendMessage(hwndNavbar, TB_GETBUTTONSIZE, 0, 0);

    // Set values unique to the band with the toolbar.
    rbBand.lpText = LPWSTR("");
    rbBand.hwndChild = hwndNavbar;
    rbBand.cyChild = LOWORD(dwBtnSize);
    rbBand.cxMinChild = NUMBUTTONS * HIWORD(dwBtnSize);
    rbBand.cyMinChild = LOWORD(dwBtnSize);
    // The default width is the width of the buttons.
    rbBand.cx = 0;

    // Add the band that has the toolbar.
    if (!SendMessage(hwndRebar, RB_INSERTBAND, (WPARAM)-1, (LPARAM)&rbBand))
    {
        MessageBox(NULL,
            _T("Could not create band!"),
            _T("pXview"),
            NULL);
    }

    return (hwndRebar);
}

And it's created just after the window is shown and updated, like this:

HWND toolbar = CreateSimpleToolbar(hWnd);
CreateRebar(hWnd, toolbar);

I've tried changing styles, the way the Rebar band is sized and positioned, etc but couldn't fix it.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
wowits64
  • 1
  • 1
  • 3
  • UPDATE: If I use TBSTYLE_GROUP in the toolbar styles, it appears in the rebar but with a little border at the top – wowits64 Apr 09 '23 at 08:33

2 Answers2

0

You are creating the Toolbar as a child of the main window, and then creating the Rebar as a child of the main window underneath the Toolbar.

To put the Toolbar into the Rebar, create the Toolbar as a child of the Rebar instead, and then assign the Toolbar to the Rebar band. See creating rebar control and introduction a band with toolbar into the rebar

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • I created a new function which soleley adds the band after the toolbar is created, parented to the rebar, but it appears the same – wowits64 Apr 08 '23 at 08:26
0

According to your description, whether you want to remove the Rebar? If so, I suggest you could try deleting RBBS_GRIPPERALWAYS. RBBS_GRIPPERALWAYS: The band will always have a sizing grip, even if it is the only band in the rebar.

Edit:

As Remy Lebeau said, you need to create the Toolbar as a child of the Rebar instead, and then assign the Toolbar to the Rebar band. Here is a sample, you could refer to:

#include <windows.h>
#include<commctrl.h>
#include <tchar.h>
#pragma comment(lib,"Comctl32.lib")
#define TOP    0x00
#define LEFT   0x01
#define BOTTOM 0x02
#define RIGHT  0x03


HINSTANCE   g_hInst;
WORD        g_wSide;

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
HINSTANCE hInstance;
HIMAGELIST g_hImageList = NULL;
HWND hwnd;

HWND BuildRebar(HWND hwndParent)
{
    HWND     hwndRebar = NULL;
    LRESULT  lResult;

    hwndRebar = CreateWindowEx(WS_EX_TOOLWINDOW,
        REBARCLASSNAME,
        NULL,
        WS_VISIBLE |
        WS_BORDER |
        WS_CHILD |
        WS_CLIPCHILDREN |
        WS_CLIPSIBLINGS |
        RBS_VARHEIGHT |
        RBS_BANDBORDERS |
        ((g_wSide & 0x01) ? CCS_VERT : 0) | //g_wSide is odd if this is a vertical bar
        ((g_wSide == BOTTOM) ? CCS_BOTTOM : 0) |
        ((g_wSide == RIGHT) ? CCS_RIGHT : 0) |
        0,
        0,
        0,
        200,
        100,
        hwndParent,
        NULL,
        g_hInst,
        NULL);

    if (hwndRebar)
    {
        REBARINFO      rbi;
        HIMAGELIST     himlRebar;
        HICON          hIcon;
        REBARBANDINFO  rbbi = { REBARBANDINFO_V3_SIZE };
        HWND           hwndChild;
        RECT           rc;
        TCHAR          szString[64];

        //set up the ReBar
        himlRebar = ImageList_Create(32, 32, ILC_COLORDDB | ILC_MASK, 1, 0);
        //hIcon = LoadIcon(g_hInst, MAKEINTRESOURCE(IDI_ICON1));

       // ImageList_AddIcon(himlRebar, hIcon);

        rbi.cbSize = sizeof(rbi);
        rbi.fMask = RBIM_IMAGELIST;
        rbi.himl = himlRebar;
        lResult = SendMessage(hwndRebar, RB_SETBARINFO, 0, (LPARAM)&rbi);

        //add a band that contains a combobox
        hwndChild = CreateWindowEx(0,
            TEXT("combobox"),
            NULL,
            WS_VISIBLE |
            WS_CHILD |
            WS_TABSTOP |
            WS_VSCROLL |
            WS_CLIPCHILDREN |
            WS_CLIPSIBLINGS |
            CBS_AUTOHSCROLL |
            CBS_DROPDOWN |
            0,
            0,
            0,
            100,
            200,
            hwndRebar,
            NULL,
            g_hInst,
            NULL);

        //add some stuff to the combobox
        {
            int   i;

            SendMessage(hwndChild, WM_SETFONT, (WPARAM)GetStockObject(DEFAULT_GUI_FONT), MAKELPARAM(TRUE, 0));

            for (i = 0; i < 25; i++)
            {
                _stprintf_s(szString, _countof(szString), TEXT("Item %d"), i + 1);
                SendMessage(hwndChild, CB_ADDSTRING, 0, (LPARAM)szString);
            }
        }

        GetWindowRect(hwndChild, &rc);

        ZeroMemory(&rbbi, sizeof(rbbi));
        rbbi.cbSize = REBARBANDINFO_V3_SIZE;
        rbbi.fMask = RBBIM_SIZE |
            RBBIM_CHILD |
            RBBIM_CHILDSIZE |
            RBBIM_ID |
            RBBIM_STYLE |
            RBBIM_TEXT |
            RBBIM_BACKGROUND |
            RBBIM_IMAGE |
            0;

        rbbi.cxMinChild = rc.right - rc.left;
        rbbi.cyMinChild = rc.bottom - rc.top;
        rbbi.cx = 100;
        rbbi.fStyle = RBBS_CHILDEDGE |
            RBBS_FIXEDBMP |
            RBBS_GRIPPERALWAYS |
            0;
        //rbbi.wID = ID_COMBOBOX;
        rbbi.hwndChild = hwndChild;
        rbbi.lpText = (LPWSTR)TEXT("ComboBox");
        rbbi.cch = 2;
        //rbbi.hbmBack = LoadBitmap(g_hInst, MAKEINTRESOURCE(IDB_BACKGROUND));
        rbbi.iImage = 0;

        lResult = SendMessage(hwndRebar, RB_INSERTBAND, (WPARAM)-1, (LPARAM)(LPREBARBANDINFO)&rbbi);

        //add a band that contains a button
        hwndChild = CreateWindowEx(0,
            TEXT("button"),
            TEXT("Button"),
            WS_CHILD |
            BS_PUSHBUTTON |
            0,
            0,
            0,
            100,
            50,
            hwndRebar,
            NULL,
            g_hInst,
            NULL);

        GetWindowRect(hwndChild, &rc);

        ZeroMemory(&rbbi, sizeof(rbbi));
        rbbi.cbSize = REBARBANDINFO_V3_SIZE;
        rbbi.fMask = RBBIM_SIZE |
            RBBIM_CHILD |
            RBBIM_CHILDSIZE |
            RBBIM_ID |
            RBBIM_STYLE |
            RBBIM_TEXT |
            RBBIM_BACKGROUND |
            0;
        rbbi.cxMinChild = rc.right - rc.left;
        rbbi.cyMinChild = rc.bottom - rc.top;
        rbbi.cx = 100;
        rbbi.fStyle = RBBS_CHILDEDGE |
            RBBS_FIXEDBMP |
            RBBS_GRIPPERALWAYS |
            0;
        //rbbi.wID = ID_BUTTON;
        rbbi.hwndChild = hwndChild;
        rbbi.lpText = (LPWSTR)TEXT("Button");
        //rbbi.hbmBack = LoadBitmap(g_hInst, MAKEINTRESOURCE(IDB_BACKGROUND));


        lResult = SendMessage(hwndRebar, RB_INSERTBAND, (WPARAM)-1, (LPARAM)(LPREBARBANDINFO)&rbbi);
    }

    return hwndRebar;
}
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow)
{
    // Register the window class.
    const wchar_t CLASS_NAME[] = L"Sample Window Class";

    WNDCLASS wc = { };

    wc.lpfnWndProc = WindowProc;
    wc.hInstance = hInstance;
    wc.lpszClassName = CLASS_NAME;

    RegisterClass(&wc);

    // Create the window.

    HWND hwnd = CreateWindowEx(
        0,                              // Optional window styles.
        CLASS_NAME,                     // Window class
        L"Learn to Program Windows",    // Window text
        WS_OVERLAPPEDWINDOW,            // Window style

        // Size and position
        CW_USEDEFAULT, CW_USEDEFAULT, 800, 600,

        NULL,       // Parent window    
        NULL,       // Menu
        hInstance,  // Instance handle
        NULL        // Additional application data
    );

    if (hwnd == NULL)
    {
        return 0;
    }

    ShowWindow(hwnd, nCmdShow);

    // Run the message loop.

    MSG msg = { };
    while (GetMessage(&msg, NULL, 0, 0) > 0)
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return 0;
}

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch (uMsg)
    {
    case WM_CREATE:
    {
        g_wSide = TOP;

        BuildRebar(hwnd);
        break;
    }
    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;

    case WM_PAINT:
    {
        PAINTSTRUCT ps;
        HDC hdc = BeginPaint(hwnd, &ps);

        // All painting occurs here, between BeginPaint and EndPaint.

        FillRect(hdc, &ps.rcPaint, (HBRUSH)(COLOR_WINDOW + 1));

        EndPaint(hwnd, &ps);
    }
    return 0;

    }
    return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
Jeaninez - MSFT
  • 3,210
  • 1
  • 5
  • 20