Win32应用中为Rebar添加Toolbar作为附加带的布局异常问题
Win32 Rebar控件添加Toolbar后布局异常的解决方法
问题根源分析
- Toolbar未设置可见性:创建Toolbar时未添加
WS_VISIBLE样式,导致Rebar无法正确识别其尺寸。 - Rebar Band宽度设置错误:Toolbar对应的Rebar Band设置
rbbi.cx = 0,未指定需求的40%主窗口宽度,导致Rebar自动计算尺寸出错。 - Toolbar样式冗余:
TBSTYLE_WRAPABLE会让按钮自动换行,不符合当前固定3个按钮的布局需求,应移除。 - 尺寸参数不匹配:未正确传递主窗口宽度到Band的尺寸设置,同时缺少
RBBIM_CY掩码来指定Band的高度。
修改后的核心代码
修正的CreateRebar1函数
HWND hWndRebar1 = NULL; HWND hWndSelectorComboBox = NULL; HWND hWndButton = NULL; HWND hWndToolbarCutCopyPaste = NULL; void CreateRebar1(HWND hWndParent) { // 获取主窗口尺寸 RECT rectMainWindow; GetWindowRect(hWndParent, &rectMainWindow); int mainWidth = rectMainWindow.right - rectMainWindow.left; // 创建Rebar控件 hWndRebar1 = CreateWindowEx(WS_EX_TOOLWINDOW, REBARCLASSNAME, NULL, WS_VISIBLE | WS_BORDER | WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | RBS_VARHEIGHT | RBS_BANDBORDERS, 0, 0, mainWidth, 50, hWndParent, NULL, GetModuleHandle(NULL), NULL); REBARBANDINFO rbbi = { REBARBANDINFO_V3_SIZE }; // 1. 添加组合框带(占主窗口50%宽度) CreateSelectorComboBox(hWndRebar1, 0.5 * mainWidth, 50); RECT rcComboBox; GetWindowRect(hWndSelectorComboBox, &rcComboBox); ZeroMemory(&rbbi, sizeof(rbbi)); rbbi.cbSize = REBARBANDINFO_V3_SIZE; rbbi.fMask = RBBIM_SIZE | RBBIM_CHILD | RBBIM_CHILDSIZE | RBBIM_STYLE; rbbi.cxMinChild = rcComboBox.right - rcComboBox.left; rbbi.cyMinChild = rcComboBox.bottom - rcComboBox.top; rbbi.cx = 0.5 * mainWidth; // 明确设置50%宽度 rbbi.fStyle = RBBS_CHILDEDGE | RBBS_FIXEDBMP | RBBS_GRIPPERALWAYS; rbbi.hwndChild = hWndSelectorComboBox; SendMessage(hWndRebar1, RB_INSERTBAND, (WPARAM)-1, (LPARAM)&rbbi); // 2. 添加Toolbar带(占主窗口40%宽度) CreateToolbarCutCopyPaste(hWndRebar1, 0.4 * mainWidth, 50); DWORD dwBtnSize = (DWORD)SendMessage(hWndToolbarCutCopyPaste, TB_GETBUTTONSIZE, 0, 0); int toolbarTotalWidth = 3 * HIWORD(dwBtnSize); ZeroMemory(&rbbi, sizeof(rbbi)); rbbi.cbSize = REBARBANDINFO_V3_SIZE; rbbi.fMask = RBBIM_SIZE | RBBIM_CHILD | RBBIM_CHILDSIZE | RBBIM_STYLE | RBBIM_CY; rbbi.fStyle = RBBS_CHILDEDGE | RBBS_FIXEDBMP | RBBS_GRIPPERALWAYS; rbbi.hwndChild = hWndToolbarCutCopyPaste; rbbi.cy = LOWORD(dwBtnSize); // 指定Band高度为按钮高度 rbbi.cyChild = LOWORD(dwBtnSize); rbbi.cxMinChild = toolbarTotalWidth; // 最小宽度为3个按钮总宽度 rbbi.cyMinChild = LOWORD(dwBtnSize); rbbi.cx = 0.4 * mainWidth; // 明确设置40%主窗口宽度 SendMessage(hWndRebar1, RB_INSERTBAND, (WPARAM)-1, (LPARAM)&rbbi); }
修正的CreateToolbarCutCopyPaste函数
void CreateToolbarCutCopyPaste(HWND hWndParent, int cx, int cy) { const int ImageListID = 0; const int numButtons = 3; const int bitmapSize = 16; const DWORD buttonStyles = BTNS_AUTOSIZE; // 创建Toolbar,添加WS_VISIBLE样式,移除TBSTYLE_WRAPABLE hWndToolbarCutCopyPaste = CreateWindowEx(0, TOOLBARCLASSNAME, NULL, WS_CHILD | WS_VISIBLE | TBSTYLE_FLAT, 0, 0, cx, cy, hWndParent, NULL, GetModuleHandle(NULL), NULL); 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"} }; g_hImageList = ImageList_Create(bitmapSize, bitmapSize, ILC_COLOR16 | ILC_MASK, numButtons, 0); SendMessage(hWndToolbarCutCopyPaste, TB_SETIMAGELIST, (WPARAM)ImageListID, (LPARAM)g_hImageList); SendMessage(hWndToolbarCutCopyPaste, TB_LOADIMAGES, (WPARAM)IDB_STD_SMALL_COLOR, (LPARAM)HINST_COMMCTRL); SendMessage(hWndToolbarCutCopyPaste, TB_BUTTONSTRUCTSIZE, (WPARAM)sizeof(TBBUTTON), 0); SendMessage(hWndToolbarCutCopyPaste, TB_ADDBUTTONS, (WPARAM)numButtons, (LPARAM)&tbButtons); // 让Toolbar自动调整到合适大小 SendMessage(hWndToolbarCutCopyPaste, TB_AUTOSIZE, 0, 0); }
关键修改点说明
- 给Toolbar添加
WS_VISIBLE样式,确保Rebar能正确获取其尺寸信息。 - 移除
TBSTYLE_WRAPABLE,避免按钮自动换行导致布局混乱。 - 明确设置Rebar Band的
rbbi.cx为需求的百分比宽度(50%和40%),而非依赖自动计算。 - 在Rebar Band的
fMask中添加RBBIM_CY,指定Band的高度,确保与Toolbar按钮高度匹配。 - 给Toolbar发送
TB_AUTOSIZE消息,让其自动调整到适配按钮的大小。
内容的提问来源于stack exchange,提问作者gene b.
相关产品推荐
相关产品推荐

