选项卡顶部的控件在 Win32 GUI 中具有不正确的背景

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

我正在尝试创建一个 Win32 应用程序(没有其他 GUI 依赖项),它有一组选项卡和这些选项卡中的控件。我按照 Raymond Chen 的指南 创建了以下合理的最小示例,这似乎与 Microsoft 的文档 相矛盾,但无论哪种方式似乎都不会影响绘图:

#include <Windows.h>
#include <windowsx.h>
#include <CommCtrl.h>
#include <uxtheme.h>

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

LRESULT CALLBACK wndproc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
    switch (uMsg) {
        case WM_DESTROY: {
            PostQuitMessage(0);
            return 0;
        }
        case WM_PAINT: {
            PAINTSTRUCT ps;
            HDC hdc = BeginPaint(hwnd, &ps);

            // All painting occurs here, between BeginPaint and EndPaint.

            FillRect(hdc, &ps.rcPaint, (HBRUSH) (COLOR_WINDOW));

            EndPaint(hwnd, &ps);

            return 0;
        }
    }

    return DefWindowProc(hwnd, uMsg, wParam, lParam);
}

int main(int argc, char **argv) {
    HINSTANCE hinst = GetModuleHandle(NULL);

    INITCOMMONCONTROLSEX icex;
    icex.dwSize = sizeof(INITCOMMONCONTROLSEX);
    icex.dwICC = ICC_TAB_CLASSES;
    InitCommonControlsEx(&icex);

    LOGFONT lf;
    GetObject (GetStockObject(DEFAULT_GUI_FONT), sizeof(LOGFONT), &lf); 
    HFONT hfont = CreateFont (lf.lfHeight, lf.lfWidth, 
        lf.lfEscapement, lf.lfOrientation, lf.lfWeight, 
        lf.lfItalic, lf.lfUnderline, lf.lfStrikeOut, lf.lfCharSet, 
        lf.lfOutPrecision, lf.lfClipPrecision, lf.lfQuality, 
        lf.lfPitchAndFamily, lf.lfFaceName); 

    const wchar_t CLASS_NAME[]  = L"Window Class";

    WNDCLASS wc = { 0,
        wndproc,
        0,
        0,
        hinst,
        NULL,
        NULL,
        NULL,
        NULL,
        (LPCSTR)CLASS_NAME
    };

    RegisterClass(&wc);

    HWND window_hwnd = CreateWindow((LPCSTR)CLASS_NAME, "Tabs Example", WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX, CW_USEDEFAULT, CW_USEDEFAULT, 640, 480, NULL, NULL, hinst, NULL);
    SendMessage(window_hwnd, WM_SETFONT, (WPARAM)hfont, TRUE);

    HWND tab_hwnd = CreateWindow(WC_TABCONTROL, "", WS_CHILD | WS_VISIBLE, 0, 0, 640, 480, window_hwnd, NULL, hinst, NULL);
    SendMessage(tab_hwnd, WM_SETFONT, (WPARAM)hfont, TRUE);

    TCITEM item;
    item.mask = TCIF_TEXT | TCIF_IMAGE;
    item.iImage = -1;
    
    item.pszText = "One!";
    TabCtrl_InsertItem(tab_hwnd, 0, &item);

    item.pszText = "Two!";
    TabCtrl_InsertItem(tab_hwnd, 1, &item);

    item.pszText = "Three!";
    TabCtrl_InsertItem(tab_hwnd, 2, &item);

    HWND groupbox_hwnd = CreateWindow(WC_BUTTON, "Groupbox", WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_GROUPBOX, 10, 32, 600, 400, window_hwnd, NULL, hinst, NULL);
    SendMessage(groupbox_hwnd, WM_SETFONT, (WPARAM)hfont, TRUE);

    HWND text_hwnd = CreateWindow(WC_STATIC, "Static Text", WS_CHILD | WS_VISIBLE | SS_CENTER, 100, 100, 100, 100, window_hwnd, NULL, hinst, NULL);
    SendMessage(text_hwnd, WM_SETFONT, (WPARAM)hfont, TRUE);

    ShowWindow(window_hwnd, SW_NORMAL);

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

}

问题是,运行时,标签内容绘制不正确。选项卡中的每个控件都有一个带有窗口背景颜色的背景:

(注意“Groupbox”文本和“静态文本”背后不正确的背景)

我试过使用像这样的

WM_CTLCOLORSTATIC
使用透明背景:

case WM_CTLCOLORSTATIC: {
    HDC hEdit = (HDC)wParam;
    SetBkMode(hEdit, TRANSPARENT);
    SetTextColor(hEdit, RGB(0, 0, 0));
    return GetStockObject(HOLLOW_BRUSH);
}

但这会导致组框渲染不正确:

(注意在“Groupbox”文本后面绘制的 groupbox 分隔线)

此外,我尝试将选项卡控件重新排序到底部,这使得 Groupbox 显示不正确:

SetWindowPos(tab_hwnd, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);

(注意整个组框下的灰色背景)

windows winapi win32gui
1个回答
0
投票

对于大多数控件

WM_PRINTCLIENT
都可以。

case WM_PRINTCLIENT:
    {
        // Paint area outside tabs control here if needed.
        ...
        // Now paint tabs area
        RECT    r1, r2;
        GetWindowRect(hwnd, &r1);
        GetWindowRect(tags_hwnd, &r2);
        POINT   old;
        ::SetWindowOrgEx((HDC)wparam, r1.left - r2.left, r1.top - r2.top, &old);
        LRESULT result = SendMessage(tabs_hwnd, WM_PRINTCLIENT, wparam, lparam);
        ::SetWindowOrgEx((HDC)wparam, old.x, old.y, 0);
        return result;
    }

WM_PRINTCLIENT
应该绘制整个客户区域,因此经常使用子对话框或帮助窗口是有原因的。

不幸的是STATIC控制不调用

WM_PRINTWINDOW
,可以使用
WM_CTLCOLORSTATIC
代替。

这个版本在

WM_CTLCOLORSTATIC
中作画有点难看。 更正确的解决方案是创建新的 hdc 和内存位图,将背景渲染到其中,从中创建画笔 并返回结果。

case WM_CTLCOLORSTATIC:
    {
        // Let tabs set initial state
        LRESULT result = SendMessage(tabs_hwnd, WM_CTLCOLORSTATIC, wparam, lparam);

        if ( IsAppThemed() )
        {
            // A little ugly, we paint here.
            // The alternative is to create brush for needed area.
            RECT    r1, r2;
            GetWindowRect(hwnd, &r1);
            GetWindowRect(tags_hwnd, &r2);
            POINT   old;
            ::SetWindowOrgEx((HDC)wparam, r1.left - r2.left, r1.top - r2.top, &old);
            LRESULT result = SendMessage(tabs_hwnd, WM_PRINTCLIENT, wparam, lparam);
            ::SetWindowOrgEx((HDC)wparam, old.x, old.y, 0);

            SetBkMode((HDC)wparam, TRANSPARENT);
            result = GetStockObject(HOLLOW_BRUSH);
        }
        return result;
    }
© www.soinside.com 2019 - 2024. All rights reserved.