You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Win32 Rebar控件显示异常:Toolbar底部出现意外抓手如何解决?

Win32 Toolbar嵌入Rebar后底部出现意外抓手的解决方法

我开发了一个标准Win32应用,包含Toolbar和Rebar控件。先创建作为主窗口子控件的Toolbar,再创建Rebar并将Toolbar加入其band中。但Toolbar底部出现了意外的抓手(如图所示):
Toolbar底部意外抓手

以下是我的创建代码(复制自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);
}

控件创建时机为窗口显示并更新后,代码如下:

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

我尝试修改样式、调整Rebar band的尺寸与位置等操作,均未能解决问题。


问题原因分析

  1. Toolbar父窗口变更冲突:先将Toolbar创建为主窗口子控件并调用TB_AUTOSIZE、ShowWindow,后续加入Rebar时父窗口切换为Rebar,残留的布局状态导致显示异常。
  2. Rebar Band配置错误:RBBS_GRIPPERALWAYS样式强制显示抓手,且用TB_GETBUTTONSIZE获取的按钮尺寸代替Toolbar完整高度,导致band高度不足,抓手被挤压到Toolbar区域。
  3. 重复初始化公共控件:CreateRebar内重复调用InitCommonControlsEx,可能导致控件样式异常。

修复方案

1. 调整Toolbar创建逻辑

移除提前的TB_AUTOSIZE和ShowWindow调用,让Rebar管理Toolbar的显示与尺寸:

HWND CreateSimpleToolbar(HWND hWndParent)
{
    // ... 原有常量、创建Toolbar、图像列表、按钮添加逻辑不变 ...

    // 移除以下两行代码
    // SendMessage(hWndToolbar, TB_AUTOSIZE, 0, 0);
    // ShowWindow(hWndToolbar, TRUE);

    return hWndToolbar;
}

2. 修正Rebar Band配置

  • 移除RBBS_GRIPPERALWAYS样式,避免强制显示抓手;如需保留可拖动抓手,改用RBBS_GRIPPER(仅当band可拖动时显示)。
  • 用TB_GETHEIGHT获取Toolbar完整高度,替代按钮尺寸:
HWND CreateRebar(HWND hwndOwner, HWND hwndNavbar)
{
    // ... 参数检查逻辑不变 ...

    // 将InitCommonControlsEx移到程序启动初期,避免重复初始化
    // 移除此处的INITCOMMONCONTROLSEX代码块

    // ... 创建Rebar窗口逻辑不变 ...

    // 初始化band信息
    REBARBANDINFO rbBand = { REBARBANDINFOW_V3_SIZE }; // Unicode环境下使用宽字符版本
    rbBand.fMask = 
        RBBIM_STYLE       
        | RBBIM_CHILD       
        | RBBIM_CHILDSIZE   
        | RBBIM_SIZE;
    rbBand.fStyle = RBBS_CHILDEDGE; // 移除RBBS_GRIPPERALWAYS

    // 获取Toolbar完整高度
    int toolbarHeight = (int)SendMessage(hwndNavbar, TB_GETHEIGHT, 0, 0);

    // 设置band参数
    rbBand.hwndChild = hwndNavbar;
    rbBand.cyChild = toolbarHeight;
    rbBand.cyMinChild = toolbarHeight;
    rbBand.cx = (int)SendMessage(hwndNavbar, TB_GETMAXSIZE, 0, 0); // 自动适配Toolbar宽度

    // ... 插入band逻辑不变 ...

    return (hwndRebar);
}

3. 调整控件创建流程

确保InitCommonControlsEx在程序启动时只调用一次,比如在WinMain开头:

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    INITCOMMONCONTROLSEX icex;
    icex.dwSize = sizeof(INITCOMMONCONTROLSEX);
    icex.dwICC = ICC_COOL_CLASSES | ICC_BAR_CLASSES;
    InitCommonControlsEx(&icex);

    // ... 主窗口创建、消息循环等逻辑 ...

    // 创建控件
    HWND toolbar = CreateSimpleToolbar(hWnd);
    HWND rebar = CreateRebar(hWnd, toolbar);
    SendMessage(rebar, RB_AUTOSIZE, 0, 0); // 让Rebar自动调整大小

    // ... 消息循环 ...
}

内容的提问来源于stack exchange,提问作者user21591956

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 16:27:27