cwindowswinapiuser-interfacecomctl32

How to enable modern look and feel of tool bar for Win32 Application?


Recently I started learning GUI programming based on Win32 API. When I add tool bar control (from comctl32.lib) to my simple application I find it looks flat while the menu bar has more "Windows 7 friendly" 3D look and feel (white glow at the top and vertical gray gradient from top to bottom). The difference makes it look wired.

Default ToolBar style

However, I find many other applications have consistent look and feel for both menu bar and tool bar. Eg. Notepad++ and Notepad 2.

Notepad++ Notepad 2

I've read some official documents and tried the solution, such as Visual Styles Overview, Enabling Visual Styles, however, it only enables the flat button style (compared to the old Win98 solid button style). It made no difference with the style I got in the first picture.

I tried to read Notepad++'s source code. Found ToolBar.cpp and made some changes to my code accordingly, but nothing changed. I think I was lost in the code base.

Here is my code of calling InitCommonControlsEx and creation of the 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);
}

So, The Question Is: Despite the bitmaps of the buttons, how can I get 3D look and feel for the tool bar, just like the Notepad++/Notepad2 example?

Thanks in advance.


Solution

  • Create Toolbar first and then Rebar.

    the rbBand.hbmBack must be set to NULL to get modern look toolbar, or remove RBBIM_BACKGROUND flag from the code below.

    Here's how to create 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);
    }