RoundRect на прозрачном фоне? - PullRequest
0 голосов
/ 19 июня 2019

Я хотел бы использовать RoundRect, чтобы нарисовать закрашенный круглый прямоугольник в WM_DRAWITEM для элемента управления для рисования владельцем.Это все работает нормально, но по какой-то причине он устанавливает области за пределами закругленных углов на белый (как будто сначала очистил квадрат, а затем нарисовал круглый прямоугольник).Я бы хотел, чтобы он не касался этой области, рассматривая ее как прозрачную.Как это сделать?

TIA !!

Ответы [ 2 ]

2 голосов
/ 19 июня 2019

Окна по умолчанию являются прямоугольниками.Когда вы рисуете их, вы должны нарисовать целый прямоугольник.Тем не менее, есть по крайней мере три способа, которыми владелец может нарисовать кнопку в виде круглого прямоугольника:

Простой способ : закрасить область вне кнопки круглого прямоугольника таким же цветом, что и фонцвет его родителя

Старый школьный путь : используйте SetWindowRgn (...), чтобы кнопка нарисованная владельцем имела область обрезки в форме круглого прямоугольника.Код для этого приведен ниже.Проблема этого метода в том, что нельзя сглаживать границу круглого прямоугольника.

Новый способ : поскольку дочерние окна Windows 8 могут быть созданы с расширенным WS_EX_LAYEREDстиль.Это должно позволить вам просто нарисовать окно в виде круглого прямоугольника;однако, это осложняется тем фактом, что (я думаю) вам нужно включить манифест, который устанавливает поддерживаемую ОС вашего исполняемого файла на Windows 8 и выше, иначе вызов CreateWindowEx (WS_EX_LAYERED, ...) просто потерпит неудачу (по крайней мере, это делает для меня, когда я пытаюсь это сделать).К сожалению, я не могу показать, как добавить манифест на макушку головы.

Ниже приведен очень элементарный код, демонстрирующий путь области окна.Вы можете исправить это, используя GDI + для рисования и настройки сглаженного рисования или перетаскивая растровое изображение вместо рисования вызовами GDI / GDI +.

// RoundRectButton.cpp : Defines the entry point for the application.
//

#include "stdafx.h"
#include "RoundRectButton.h"

#define BTN_ID 101

HINSTANCE g_instance = 0;
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);

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

    MSG msg = { 0 };
    WNDCLASS wc = { 0 };
    wc.lpfnWndProc = WndProc;
    wc.hInstance = hInstance;
    wc.hbrBackground = reinterpret_cast<HBRUSH>(COLOR_BACKGROUND);
    wc.lpszClassName = L"owner_draw_btn";

    if (!RegisterClass(&wc))
        return -1;

    if (!CreateWindow(wc.lpszClassName, L"foobar", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 0, 0, 640, 480, 0, 0, hInstance, NULL))
        return -1;

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

    return 0;
}

LRESULT HandleDrawItem(HWND hWnd, WPARAM wParam, LPARAM lParam, int corner_wd, int corner_hgt, 
        COLORREF unclicked_color, COLORREF clicked_color)
{
    auto* dis = reinterpret_cast<DRAWITEMSTRUCT*>(lParam);
    if (dis->CtlType != ODT_BUTTON)
        return 0;

    COLORREF fill_color = (dis->itemState & ODS_SELECTED) ? clicked_color : unclicked_color;

    auto rect = &dis->rcItem;
    //DrawFrameControl(dis->hDC, rect, DFC_BUTTON, style);
    HPEN pen = CreatePen(PS_SOLID, 6, RGB(0, 0, 0));
    HPEN old_pen = (HPEN) SelectObject(dis->hDC, pen);
    HBRUSH brush = CreateSolidBrush(fill_color);
    HBRUSH old_brush = (HBRUSH) SelectObject(dis->hDC, brush);

    RoundRect(dis->hDC, rect->left, rect->top, rect->right, rect->bottom, corner_wd, corner_hgt);

    SelectObject(dis->hDC, old_pen);
    SelectObject(dis->hDC, old_brush);

    DeleteObject(pen);
    DeleteObject(brush);

    TCHAR text[512];
    auto n = GetWindowText(dis->hwndItem, text, 512);
    SetBkMode(dis->hDC, TRANSPARENT);
    DrawText(dis->hDC, text, n, rect, DT_SINGLELINE | DT_VCENTER | DT_CENTER);

    return 0;
}

HWND CreateRoundRectButton(HWND parent, int x, int y, int wd, int hgt, int corner_wd, int corner_hgt, int id)
{
    HWND button = CreateWindow(
        L"button", L"foobar",
        BS_OWNERDRAW | WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS,
        x, y, wd, hgt, parent,
        (HMENU) id,
        g_instance,
        0
    );
    SetWindowRgn(button, CreateRoundRectRgn(0, 0, wd, hgt, corner_wd, corner_hgt), TRUE);
    return button;
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    static HWND button = NULL;
    DWORD err;
    switch (message)
    {
    case WM_CREATE:
        button = CreateRoundRectButton(hWnd, 15, 15, 150, 35, 15, 15, BTN_ID);
        return 0;

    case WM_DRAWITEM:
        return HandleDrawItem(hWnd, wParam, lParam, 15, 15, RGB(230,230,230), RGB(255,255,255));

    case WM_CLOSE:
        PostQuitMessage(0);
        return 0;
    }
    return DefWindowProc(hWnd, message, wParam, lParam);
}
0 голосов
/ 19 июня 2019

Поскольку это кнопочный элемент управления, похоже, он работает (я пытался добавить комментарии, но не смог отформатировать его).

case WM_CTLCOLORBTN:
{
  if ((HWND)lparam==GetDlgItem(hwnd, IDC_BUTTON)) {
    return (LRESULT) ::GetStockObject(NULL_BRUSH);
  }
  break;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...