I have a top-level Rebar hWndRebar1
and am trying to add 2 bands to it as children, (1) a combobox hWndSelectorComboBox
and (2) a toolbar hWndToolbarCutCopyPaste
with 3 buttons. Band #1 takes up 50% of the main window and Band #2 40% (the remaining 10% is for the Rebar's own decorations).
If, instead of the Toolbar, I simply create a Button control as the 2nd band of the rebar, everything works:
But if I add the Toolbar in the 2nd band of the rebar, it doesn't look right and completely covers the whole area, with an additional weird line on the far right.
My code: global variables, where hWndButton/CreateButton
can be interchanged with hWndToolbarCutCopyPaste/CreateToolbar
to test out these scenarios, and the main method is CreateRebar1
:
HWND hWndRebar1 = NULL;
HWND hWndSelectorComboBox = NULL;
HWND hWndButton = NULL;
HWND hWndToolbarCutCopyPaste = NULL;
void CreateRebar1(HWND hWndParent) {
// Create hWndRebar1
RECT rectMainWindow;
GetWindowRect(hWndParent, &rectMainWindow);
hWndRebar1 = CreateWindowEx(WS_EX_TOOLWINDOW, REBARCLASSNAME, NULL, WS_VISIBLE | WS_BORDER | WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | RBS_VARHEIGHT |RBS_BANDBORDERS,
0, 0, rectMainWindow.right - rectMainWindow.left, 50, hWndParent, NULL, GetModuleHandle(NULL), NULL);
// Add components to hWndRebar1
REBARINFO rbi;
REBARBANDINFO rbbi = { REBARBANDINFO_V3_SIZE };
// 1.Combobox, create and add
CreateSelectorComboBox(hWndRebar1, 0.5 * (rectMainWindow.right - rectMainWindow.left), 50);
RECT rcComboBox;
GetWindowRect(hWndSelectorComboBox, &rcComboBox);
ZeroMemory(&rbbi, sizeof(rbbi));
rbbi.cbSize = REBARBANDINFO_V3_SIZE;
rbbi.fMask = RBBIM_SIZE | RBBIM_CHILD | RBBIM_CHILDSIZE | RBBIM_ID | RBBIM_STYLE | RBBIM_TEXT | 0;
rbbi.cxMinChild = rcComboBox.right - rcComboBox.left;
rbbi.cyMinChild = rcComboBox.bottom - rcComboBox.top;
rbbi.cx = 100;
rbbi.fStyle = RBBS_CHILDEDGE |
RBBS_FIXEDBMP |
RBBS_GRIPPERALWAYS |
0;
rbbi.hwndChild = hWndSelectorComboBox;
SendMessage(hWndRebar1, RB_INSERTBAND, (WPARAM)-1, (LPARAM)(LPREBARBANDINFO)&rbbi);
// 2A. INTERCHANGEABLE (remove the toolbar): Button, create and add
CreateButton(hWndParent, 0.4 * (rectMainWindow.right - rectMainWindow.left), 50);
RECT rcButton;
GetWindowRect(hWndButton, &rcButton);
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 = rcButton.right - rcButton.left;
rbbi.cyMinChild = rcButton.bottom - rcButton.top;
rbbi.cx = 100;
rbbi.fStyle = RBBS_CHILDEDGE |
RBBS_FIXEDBMP |
RBBS_GRIPPERALWAYS |
0;
rbbi.hwndChild = hWndButton;
rbbi.lpText = (LPWSTR)TEXT("Button");
SendMessage(hWndRebar1, RB_INSERTBAND, (WPARAM)-1, (LPARAM)(LPREBARBANDINFO)&rbbi);
// 2B. INTERCHANGEABLE (remove the button): Toolbar, create and add
// Create Toolbar
CreateToolbarCutCopyPaste(hWndRebar1, 0.4 * (rectMainWindow.right - rectMainWindow.left), 50);
// Get toolbar dimensions of RBBand
DWORD dwBtnSize = (DWORD)SendMessage(hWndToolbarCutCopyPaste, TB_GETBUTTONSIZE, 0, 0);
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
rbbi.fStyle = RBBS_CHILDEDGE |
RBBS_FIXEDBMP |
RBBS_GRIPPERALWAYS |
0;
// Set values unique to the band with the toolbar.
rbbi.hwndChild = hWndToolbarCutCopyPaste;
rbbi.cyChild = LOWORD(dwBtnSize);
rbbi.cxMinChild = 3 * HIWORD(dwBtnSize);
rbbi.cyMinChild = LOWORD(dwBtnSize);
// The default width is the width of the buttons.
rbbi.cx = 0;
SendMessage(hWndRebar1, RB_INSERTBAND, (WPARAM)-1, (LPARAM)(LPREBARBANDINFO)&rbbi);
}
Auxiliary ComboBox, Button & Toolbar creation methods:
ComboBox
void CreateSelectorComboBox(HWND hWndParent, int cx, int cy) {
//hWndSelectorComboBox = CreateWindowEx(NULL, WC_COMBOBOX, NULL, WS_CHILD | WS_VISIBLE | CBS_DROPDOWN | WS_TABSTOP | WS_VSCROLL | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | 0, 0, 0, cx, cy, hWndParent, NULL, GetModuleHandle(NULL), NULL);
hWndSelectorComboBox = CreateWindowEx(0,
TEXT("combobox"),
NULL,
WS_VISIBLE |
WS_CHILD |
WS_TABSTOP |
WS_VSCROLL |
WS_CLIPCHILDREN |
WS_CLIPSIBLINGS |
CBS_AUTOHSCROLL |
CBS_DROPDOWN,
0,
0,
cx,
cy,
hWndParent,
NULL,
GetModuleHandle(NULL),
NULL);
}
Button
void CreateButton(HWND hWndParent, int cx, int cy) {
hWndButton = CreateWindowEx(0,
TEXT("button"),
TEXT("Button"),
WS_CHILD |
BS_PUSHBUTTON,
0,
0,
cx,
cy,
hWndRebar1,
NULL,
GetModuleHandle(NULL),
NULL);
}
Toolbar:
void CreateToolbarCutCopyPaste(HWND hWndParent, int cx, int cy)
{
// Declare and initialize local constants.
const int ImageListID = 0;
const int numButtons = 3;
const int bitmapSize = 16;
const DWORD buttonStyles = BTNS_AUTOSIZE;
// Get Window Width
RECT rectMainWindow;
GetWindowRect(hWndParent, &rectMainWindow);
// Create the toolbar.
hWndToolbarCutCopyPaste = CreateWindowEx(0, TOOLBARCLASSNAME,
NULL,
WS_CHILD | TBSTYLE_WRAPABLE | TBSTYLE_FLAT,
0, 0, cx, cy, hWndParent,
NULL, GetModuleHandle(NULL), NULL);
// Initialize separators & buttons
TBBUTTON tbButtons[numButtons] =
{
{ MAKELONG(STD_CUT, ImageListID), IDM_CUT, TBSTATE_ENABLED, buttonStyles, {0}, 0, (INT_PTR)L"Cut"},
{ MAKELONG(STD_COPY, ImageListID), IDM_COPY, TBSTATE_ENABLED, buttonStyles, {0}, 0, (INT_PTR)L"Copy"},
{ MAKELONG(STD_PASTE, ImageListID), IDM_PASTE, 0, buttonStyles, {0}, 0, (INT_PTR)L"Paste"}
};
// Create the image list.
g_hImageList = ImageList_Create(bitmapSize, bitmapSize, // Dimensions of individual bitmaps.
ILC_COLOR16 | ILC_MASK, // Ensures transparent background.
numButtons, 0);
// Toolbar construction messages
// Set the image list.
SendMessage(hWndToolbarCutCopyPaste, TB_SETIMAGELIST, (WPARAM)ImageListID, (LPARAM)g_hImageList);
// Load the button images.
SendMessage(hWndToolbarCutCopyPaste, TB_LOADIMAGES, (WPARAM)IDB_STD_SMALL_COLOR, (LPARAM)HINST_COMMCTRL);
// Add buttons.
SendMessage(hWndToolbarCutCopyPaste, TB_BUTTONSTRUCTSIZE, (WPARAM)sizeof(TBBUTTON), 0);
SendMessage(hWndToolbarCutCopyPaste, TB_ADDBUTTONS, (WPARAM)numButtons, (LPARAM)&tbButtons);
}
Wow I fixed it after finding another thread on a different forum that discusses this exact issue!
https://cboard.cprogramming.com/windows-programming/90161-rebar-toolbars.html
Apparently the issue is that the Toolbar had to have the additional styles | CCS_NOPARENTALIGN | CCS_NORESIZE | CCS_NODIVIDER.
Thus the Toolbar creation code should be
hWndToolbarCutCopyPaste = CreateWindowEx(0, TOOLBARCLASSNAME, NULL, WS_CHILD | TBSTYLE_WRAPABLE | TBSTYLE_FLAT |
CCS_NOPARENTALIGN | CCS_NORESIZE | CCS_NODIVIDER
, 0, 0, cx, cy, hWndParent, NULL, GetModuleHandle(NULL), NULL);
I would have never figured it on my own, and there's no documentation anywhere (and what little of it there is doesn't work, such as Microsoft's websites). Amazing!