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

Win32自定义圆角按钮白色背景及抗锯齿失效问题求助

Win32自定义圆角按钮白色背景问题求助

我通过Win32的BS_OWNERDRAW样式实现了自定义矩形按钮,但在创建圆角按钮时,按钮后方出现白色背景的问题,经大量研究仍未解决,特寻求帮助。

以下是我使用的代码:

#define UNICODE
#include <windows.h>
#include <gdiplus.h>

using namespace Gdiplus;

LRESULT CALLBACK MainWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{

    // Define window properties variables
    const wchar_t g_szClassName[] = L"myWindowClass";

    WNDCLASSEX wc;
    HWND hwnd;
    MSG Msg;

    // Registering the Window Class
    wc.cbSize = sizeof(WNDCLASSEX);
    wc.style = 0;
    wc.lpfnWndProc = MainWndProc;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    wc.hInstance = hInstance;
    wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
    wc.lpszMenuName = NULL;
    wc.lpszClassName = g_szClassName;
    wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);

    if (!RegisterClassEx(&wc))
    {
        MessageBox(NULL, L"Failed to register window class", L"Error", MB_OK);
        return 1;
    }

    // Creating the window
    HWND hWnd = CreateWindowEx(0, L"myWindowClass", L"New Window",
                            WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
                            500, 350, NULL, NULL, GetModuleHandle(NULL), NULL);

    if (hWnd == NULL)
    {
        MessageBox(NULL, L"Failed to create window", L"Error", MB_OK);
        return 1;
    }

    // Show the window
    ShowWindow(hWnd, SW_SHOW);

    // Message loop
    while (GetMessage(&Msg, NULL, 0, 0))
    {
        TranslateMessage(&Msg);
        DispatchMessage(&Msg);
    }

    return Msg.wParam;
}

LRESULT CALLBACK MainWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    HWND buttonHandle;
    Gdiplus::GdiplusStartupInput gdiplusStartupInput;
    ULONG_PTR gdiplusToken;
    GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);

    switch (uMsg)
    {
    case WM_CLOSE:
        DestroyWindow(hwnd);
        break;
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    case WM_CREATE:
    {
        // cretae the button
        buttonHandle = CreateWindowEx(0, L"BUTTON", L"OK",
                                    WS_VISIBLE | WS_CHILD | BS_OWNERDRAW,
                                    50, 50, 200, 100, hwnd, (HMENU)1, NULL, NULL);

        break;
    }
    case WM_PAINT:
    {
        // fill the window with a solid color
        PAINTSTRUCT ps;
        HDC hdc = BeginPaint(hwnd, &ps);
        HBRUSH hBrush = CreateSolidBrush(RGB(30, 30, 30));
        FillRect(hdc, &ps.rcPaint, hBrush);
        DeleteObject(hBrush);
        EndPaint(hwnd, &ps);
        return 0;
    }
    case WM_DRAWITEM:
    {
        LPDRAWITEMSTRUCT lpdis = (LPDRAWITEMSTRUCT)lParam;

        // Get button rectangle
        RECT buttonRect = lpdis->rcItem;

        // Create Gdiplus::Graphics object from device context
        Gdiplus::Graphics graphics(lpdis->hDC);
        graphics.SetSmoothingMode(Gdiplus::SmoothingModeAntiAlias); // Set anti-alias mode for smoother edges
        // Define button color with alpha channel (transparency)
        Gdiplus::Color buttonColor = Gdiplus::Color(255, 170, 70, 70);

        // Create solid brush for button color
        Gdiplus::SolidBrush brush(buttonColor);
        int x = buttonRect.left;
        int y = buttonRect.top;
        int width = buttonRect.right - buttonRect.left;
        int height = buttonRect.bottom - buttonRect.top;
        // Draw a rounded rectangle
        int cornerRadius = 40;
        Gdiplus::GraphicsPath path;
        path.AddArc(x, y, cornerRadius, cornerRadius, 180, 90);
        path.AddArc(x + width - cornerRadius, y, cornerRadius, cornerRadius, 270, 90);
        path.AddArc(x + width - cornerRadius, y + height - cornerRadius, cornerRadius, cornerRadius, 0, 90);
        path.AddArc(x, y + height - cornerRadius, cornerRadius, cornerRadius, 90, 90);
        path.CloseFigure();
        graphics.FillPath(&brush, &path);
        break;
    }

    default:
        return DefWindowProc(hwnd, uMsg, wParam, lParam);
    }
    return 0;
}

运行效果:
Win32圆角按钮白色背景问题

更新记录

  • 更新1:尝试了Remy Lebeau提供的两种解决方案,第一种方法无效;第二种使用SetLayeredWindowAttributes的方法结果接近预期,但存在瑕疵。
  • 更新2:为第一种方法添加WS_CLIPSIBLINGS后成功解决白色背景问题,但失去了平滑边缘特性;若在第二种方法中去掉SetSmoothingMode,也能解决背景问题,但同样丢失抗锯齿效果。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 17:57:07