如何启用Win32应用程序的现代外观和工具栏?

4

最近我开始学习基于Win32 API的GUI编程。当我向我的简单应用程序添加工具栏控件(从comctl32.lib中)时,我发现它看起来很平面,而菜单栏具有更多“Windows 7友好”的3D外观和感觉(顶部白色发光和从上到下的垂直灰色渐变)。这种差异使它看起来很奇怪。

Default ToolBar style

然而,我发现许多其他应用程序在菜单栏和工具栏上都有一致的外观。例如Notepad++Notepad 2

Notepad++ Notepad 2

我已阅读了一些官方文件并尝试了解决方案,例如Visual Styles OverviewEnabling Visual Styles,然而,这只启用了扁平按钮样式(与旧的Win98实心按钮样式相比)。 它与我在第一张图片中获得的样式没有任何区别。
我试图阅读Notepad ++的源代码。 找到了ToolBar.cpp并相应地更改了我的代码,但没有任何变化。 我想我在代码库中迷失了。
这是我调用InitCommonControlsEx并创建ToolBar的代码。
// in WinMain
INITCOMMONCONTROLSEX icce;
icce.dwSize = sizeof(INITCOMMONCONTROLSEX);
icce.dwICC = ICC_BAR_CLASSES | ICC_COOL_CLASSES | ICC_USEREX_CLASSES;
InitCommonControlsEx(&icce);

// called in WM_CREATE handler, hwnd is the handle of the main window
VOID BuildToolBar(HWND hwnd)
{
    HWND hTool;
    TBBUTTON tbb[3];
    TBADDBITMAP tbab;

    hTool = CreateWindowEx(0, TOOLBARCLASSNAME, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | TBSTYLE_TOOLTIPS |TBSTYLE_FLAT | CCS_TOP | BTNS_AUTOSIZE, 0, 0, 0, 0, hwnd, (HMENU)IDC_MAIN_TOOL, GetModuleHandle(NULL), NULL);
    SendMessage(hTool, TB_BUTTONSTRUCTSIZE, (WPARAM)sizeof(TBBUTTON), 0);
    SendMessage(hTool, TB_SETEXTENDEDSTYLE, 0, (LPARAM)TBSTYLE_EX_HIDECLIPPEDBUTTONS);

    tbab.hInst = HINST_COMMCTRL;
    tbab.nID = IDB_STD_SMALL_COLOR;
    SendMessage(hTool, TB_ADDBITMAP, 0, (LPARAM)&tbab);

    ZeroMemory(tbb, sizeof(tbb));
    tbb[0].iBitmap = STD_FILENEW;
    tbb[0].fsState = TBSTATE_ENABLED;
    tbb[0].fsStyle = TBSTYLE_BUTTON;
    tbb[0].idCommand = ID_FILE_NEW;

    tbb[1].iBitmap = STD_FILEOPEN;
    tbb[1].fsState = TBSTATE_ENABLED;
    tbb[1].fsStyle = TBSTYLE_BUTTON;
    tbb[1].idCommand = ID_FILE_OPEN;

    tbb[2].iBitmap = STD_FILESAVE;
    tbb[2].fsState = TBSTATE_ENABLED;
    tbb[2].fsStyle = TBSTYLE_BUTTON;
    tbb[2].idCommand = ID_FILE_SAVEAS;

    SendMessage(hTool, TB_SETBUTTONSIZE, (WPARAM)0, (LPARAM)MAKELONG(16, 16));
    SendMessage(hTool, TB_ADDBUTTONS, sizeof(tbb) / sizeof(TBBUTTON), (LPARAM)&tbb);
    SendMessage(hTool, TB_AUTOSIZE, 0, 0);
}

所以,问题是:除了按钮的位图外,我如何为工具栏获得像Notepad++/Notepad2示例中那样的3D外观和感觉?
提前致谢。

1
工具栏选择从未缺乏。Notepad++使用Rebar控件,SDK页面在此处(http://msdn.microsoft.com/en-us/library/windows/desktop/bb774373%28v=vs.85%29.aspx)。看起来您没有正确获取视觉样式清单。 - Hans Passant
1
@HansPassant,SDK页面上的Rebar示例显示了一个嵌入在Rebar中的平面工具栏,而不是Notepad++风格。而“清单”解决方案页面上的示例也显示了平面样式。我想知道Nodepad ++如何将ToolBar / Rebar制作成那种工具栏样式。 - Arie Xiao
好的,Notepad++在我的电脑和你提供的截图上都是“扁平化”的。请注意可能存在旧版本,口味和Windows版本的快速更改。 - Hans Passant
我可以确认Arie Shaw是正确的,缺省Win32工具栏与图像#1相同。而Notepad2的工具栏则与图像#3相同。 - dns
1个回答

2

首先创建工具栏,然后再创建Rebar。

为了获得现代化的工具栏外观,必须将rbBand.hbmBack设置为NULL, 或从下面的代码中移除RBBIM_BACKGROUND标志。

以下是创建Rebar的方法:

HWND WINAPI CreateRebar (HWND hwndOwner)
{
    REBARINFO     rbi;
    REBARBANDINFO rbBand;
    RECT          rc;
    HWND   hwndCB, hwndRB;
    DWORD  dwBtnSize;

    hwndRB = CreateWindowExW(WS_EX_TOOLWINDOW,
        REBARCLASSNAME,
        NULL,
        WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS |
        WS_CLIPCHILDREN | RBS_VARHEIGHT |
        CCS_NODIVIDER,
        0, 0, 0, 0,
        hwndOwner,
        NULL,
        GetModuleHandleW(NULL),
        NULL);
    if (!hwndRB)
        return NULL;
    // Initialize and send the REBARINFO structure.
    rbi.cbSize = sizeof(REBARINFO);  // Required when using this
    // structure.
    rbi.fMask = 0;
    rbi.himl = (HIMAGELIST)NULL;
    if (!SendMessage(hwndRB, RB_SETBARINFO, 0, (LPARAM)&rbi))
        return NULL;
    // Initialize structure members that both bands will share.
    rbBand.cbSize = sizeof(REBARBANDINFO);  // Required
    rbBand.fMask = RBBIM_COLORS | RBBIM_TEXT | RBBIM_BACKGROUND |
        RBBIM_STYLE | RBBIM_CHILD | RBBIM_CHILDSIZE |
        RBBIM_SIZE;
    rbBand.fStyle = RBBS_CHILDEDGE | RBBS_FIXEDBMP;
    rbBand.hbmBack = NULL;  //
    // Create the combo box control to be added.
    hwndCB = CreateWindowW(TEXT("COMBOBOX"), NULL,
        WS_CHILD | WS_VISIBLE | CBS_HASSTRINGS | CBS_DROPDOWNLIST,
        410, 20, 120, 110, (HWND) NULL, NULL, NULL, NULL);;
    // Set values unique to the band with the combo box.
    GetWindowRect(hwndCB, &rc);
    rbBand.lpText = "Combo Box";
    rbBand.hwndChild = hwndCB;
    rbBand.cxMinChild = 0;
    rbBand.cyMinChild = rc.bottom - rc.top;
    rbBand.cx = 200;

    // Add the band that has the combo box.
    SendMessage(hwndRB, RB_INSERTBAND, (WPARAM)-1, (LPARAM)&rbBand);


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

    // Set values unique to the band with the toolbar.
    rbBand.lpText = "Tool Bar";
    rbBand.hwndChild = toolbar1;
    rbBand.cxMinChild = 0;
    rbBand.cyMinChild = HIWORD(dwBtnSize);
    rbBand.cx = 250;

    // Add the band that has the toolbar.
    SendMessage(hwndRB, RB_INSERTBAND, (WPARAM)-1, (LPARAM)&rbBand);
    return (hwndRB);
}

啊,它起作用了,谢谢。自从我上次接触WINAPI以来已经很长时间了。我仍然有一个问题,就是工具栏直到你把鼠标移到图标上才会显示出来。我稍后会调查一下这个问题。 - Arie Xiao

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接