WinAPI rebar 控件未显示

问题描述 投票:0回答:2

我正在用 C++ 开发一个纯 WinAPI 应用程序,我想添加一个位于 rebar 控件内部/之上的工具栏。我可以创建并添加工具栏,但无法显示钢筋(即使我设置了 RBBS_GRIPPERALWAYS 样式,也没有夹具):

我从 MSDN 页面上获取了有关工具栏/钢筋控件的代码,并组装了一个最小的示例,但仍然没有成功。 CreateWindow 和 SendMessage 等的返回代码对我来说看起来不错。我也尝试了这个问题的解决方案,但无论如何我都无法让它工作。任何帮助将不胜感激..这是完整的源代码:

#include "targetver.h"
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <CommCtrl.h>
#include <stdlib.h>
#include <malloc.h>
#include <memory.h>
#include <tchar.h>
#include "Resource.h"
#pragma comment(lib, "comctl32.lib")

// Enable visual styles
#pragma comment(linker,"\"/manifestdependency:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")

// Toolbar defines
#define IDM_NEW 100
#define IDM_OPEN 101
#define IDM_SAVE 102
#define NUM_TBBUTTONS 3

// Global variables
HINSTANCE g_hInst;
HIMAGELIST g_hImageList = NULL;

// Forward declarations
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
HWND CreateSimpleToolbar(HWND hwndParent);
HWND CreateSimpleRebar(HWND hwndParent, HWND hwndToolbar);

int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow) {
    // Initialize common controls.
    INITCOMMONCONTROLSEX icex;
    icex.dwSize = sizeof(INITCOMMONCONTROLSEX);
    icex.dwICC = ICC_COOL_CLASSES | ICC_BAR_CLASSES;
    InitCommonControlsEx(&icex);

    WNDCLASSEXW wcex;
    wcex.cbSize = sizeof(WNDCLASSEX);
    wcex.style = CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc = WndProc;
    wcex.cbClsExtra = 0;
    wcex.cbWndExtra = 0;
    wcex.hInstance = hInstance;
    wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_REBARTEST));
    wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
    wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW);
    wcex.lpszMenuName = MAKEINTRESOURCEW(IDC_REBARTEST);
    wcex.lpszClassName = _T("RebarTest");
    wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
    RegisterClassExW(&wcex);
    
    HWND hwndMainWindow = CreateWindowW(_T("RebarTest"), _T("AppTitle"), 
        WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, 
        nullptr, nullptr, hInstance, nullptr);
    if (!hwndMainWindow)
        return FALSE;

    ShowWindow(hwndMainWindow, nCmdShow);
    UpdateWindow(hwndMainWindow);

    MSG msg;
    while (GetMessage(&msg, nullptr, 0, 0)) {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return (int)msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {
    static HWND hwndToolbar, hwndRebar;
    switch (message)
    {
    case WM_CREATE:
    {
        hwndToolbar = CreateSimpleToolbar(hwnd);
        hwndRebar = CreateSimpleRebar(hwnd, hwndToolbar);
    }
    break;
    case WM_COMMAND:
    {
        int wmId = LOWORD(wParam);
        // Menüauswahl analysieren:
        switch (wmId)
        {       
        case IDM_EXIT:
            DestroyWindow(hwnd);
            break;
        default:
            return DefWindowProc(hwnd, message, wParam, lParam);
        }
    }
    break;
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hwnd, message, wParam, lParam);
    }
    return 0;
}

HWND CreateSimpleToolbar(HWND hwndParent) {
    // Create the toolbar.
    HWND hwndToolbar = CreateWindowEx(0, TOOLBARCLASSNAME, NULL,
        WS_CHILD | TBSTYLE_WRAPABLE, 0, 0, 0, 0, hwndParent, NULL, g_hInst, NULL);

    if (hwndToolbar == NULL)
        return NULL;

    // Create the image list.
    g_hImageList = ImageList_Create(16, 16, ILC_COLOR16 | ILC_MASK, NUM_TBBUTTONS, 0);

    // Set the image list and add buttons
    const int imageListID = 0;
    SendMessage(hwndToolbar, TB_SETIMAGELIST, (WPARAM)imageListID, (LPARAM)g_hImageList);
    SendMessage(hwndToolbar, TB_LOADIMAGES, (WPARAM)IDB_STD_SMALL_COLOR, (LPARAM)HINST_COMMCTRL);

    // Initialize button info.
    TBBUTTON tbButtons[NUM_TBBUTTONS] =
    {
        { MAKELONG(STD_FILENEW,  imageListID), IDM_NEW,  TBSTATE_ENABLED, BTNS_AUTOSIZE, {0}, 0, (INT_PTR)L"New" },
        { MAKELONG(STD_FILEOPEN, imageListID), IDM_OPEN, TBSTATE_ENABLED, BTNS_AUTOSIZE, {0}, 0, (INT_PTR)L"Open"},
        { MAKELONG(STD_FILESAVE, imageListID), IDM_SAVE, 0,               BTNS_AUTOSIZE, {0}, 0, (INT_PTR)L"Save"}
    };

    // Add buttons.
    SendMessage(hwndToolbar, TB_BUTTONSTRUCTSIZE, (WPARAM)sizeof(TBBUTTON), 0);
    SendMessage(hwndToolbar, TB_ADDBUTTONS, (WPARAM)NUM_TBBUTTONS, (LPARAM)&tbButtons);

    // Resize the toolbar, and then show it.
    SendMessage(hwndToolbar, TB_AUTOSIZE, 0, 0);
    ShowWindow(hwndToolbar, TRUE);
    return hwndToolbar;
}

HWND CreateSimpleRebar(HWND hwndParent, HWND hwndToolbar) {
    // Check parameters.
    if (!hwndParent || !hwndToolbar)
        return NULL;

    // 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,
        hwndParent, NULL, g_hInst, NULL);

    if (!hwndRebar)
        return NULL;

    // Get the height of the toolbar.
    DWORD dwBtnSize = (DWORD)SendMessage(hwndToolbar, TB_GETBUTTONSIZE, 0, 0);
    
    REBARBANDINFO rbBand;
    rbBand.cbSize = sizeof(REBARBANDINFO);
    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;
    rbBand.lpText = (LPWSTR)_T("");
    rbBand.hwndChild = hwndToolbar;
    rbBand.cyChild = LOWORD(dwBtnSize);
    rbBand.cxMinChild = NUM_TBBUTTONS * HIWORD(dwBtnSize);
    rbBand.cyMinChild = LOWORD(dwBtnSize);
    rbBand.cx = 0;  // The default width is the width of the buttons.

    // Add the band with the toolbar.
    SendMessage(hwndRebar, RB_INSERTBAND, (WPARAM)-1, (LPARAM)&rbBand);
    return hwndRebar;
}
c++ c winapi controls win32gui
2个回答
1
投票

这个问题的评论中所述,您需要定义一个_WIN32_WINNT,我假设您可能在“targetver.h”标头中拥有它。由于您正在声明通用控件版本 6,我认为您至少需要以 WS-2003/Vista 为目标,根据此。我首先尝试了

#define WINVER  0x0601
#define _WIN32_WINNT_WIN7 0x0601
与你的代码,它在我的机器上工作。

我认为您链接的问题有点过时了,这个表说公共控件版本6的结构大小应该是

REBARBANDINFO_V6_SIZE
。但是,在使用该结构尺寸时,我遇到了链接问题中的 4 像素高度问题。保持你的代码大小对我来说是有效的。

我认为您遇到的真正问题是您的工具栏正在处理其自身的大小调整和定位。如此关于工具栏控制页面所述,您需要更改此

HWND hwndToolbar = CreateWindowEx(0, TOOLBARCLASSNAME, NULL, WS_CHILD | TBSTYLE_WRAPABLE, 0, 0, 0, 0, hwndParent, NULL, g_hInst, NULL);

到此

HWND hwndToolbar = CreateWindowEx(0, TOOLBARCLASSNAME, NULL, WS_CHILD | TBSTYLE_WRAPABLE | CCS_NORESIZE | CCS_NOPARENTALIGN, 0, 0, 0, 0, hwndParent, NULL, g_hInst, NULL);

在 CreateSimpleToolbar 函数中,以便主机 rebar 可以控制工具栏的大小和位置。


0
投票

我花了一天的大部分时间试图解决类似的问题。我发现缺少 rbBand.cxMaxChild 是问题所在。通过不设置 cxMaxChild 属性,它被视为 0,因此钢筋的高度永远不会超过子项的最大高度,该高度被视为零。

© www.soinside.com 2019 - 2024. All rights reserved.