在透明窗口中绘制一个半透明矩形

奥古斯特·维什涅夫斯基

我在stackoverflow中找到了这段代码,它确实使用位图在透明窗口上绘制了一个矩形。但是以某种方式我无法更改矩形的透明度。更确切地说,我可以,但是它变得更暗了。好像位图本身具有黑色背景。如何使矩形透明?

void paintRect(HDC hdc, RECT dim, COLORREF penCol, COLORREF brushCol, int opacity)
    {
        HDC tempHDC = CreateCompatibleDC(hdc);
    
        BITMAPINFO bitmapInfo;
        ZeroMemory(&bitmapInfo, sizeof(BITMAPINFO));
    
        bitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
        bitmapInfo.bmiHeader.biWidth = dim.right - dim.left;
        bitmapInfo.bmiHeader.biHeight = dim.bottom - dim.top;
        bitmapInfo.bmiHeader.biPlanes = 1;
        bitmapInfo.bmiHeader.biBitCount = 32;
        bitmapInfo.bmiHeader.biCompression = BI_RGB;
        bitmapInfo.bmiHeader.biSizeImage = (dim.right - dim.left) * (dim.bottom - dim.top) * 4;
    
        HBITMAP hBitmap = CreateDIBSection(tempHDC, &bitmapInfo, DIB_RGB_COLORS, NULL, NULL, 0x0);
    
        SelectObject(tempHDC, hBitmap);
        SetDCPenColor(tempHDC, RGB(0, 0, 255));
        SetDCBrushColor(tempHDC, RGB(0, 0, 255));
        FillRect(tempHDC, &dim, CreateSolidBrush(RGB(0, 0, 255)));
    
        BLENDFUNCTION blend = { AC_SRC_OVER, 0, 255, 0 };
        AlphaBlend(hdc, dim.left, dim.top, dim.right, dim.bottom, tempHDC, dim.left, dim.top, dim.right, dim.bottom, blend);
    }

完整代码

#include <Windows.h>

int wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow);
LRESULT CALLBACK windowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);

int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow)
{
    WNDCLASS windowClass {};

    windowClass.lpfnWndProc = windowProc;
    windowClass.hInstance = hInstance;
    windowClass.lpszClassName = L"Keystrokes";
    windowClass.style = CS_NOCLOSE;
    windowClass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
    windowClass.hCursor = LoadCursor(NULL, IDC_ARROW);

    if (!RegisterClass(&windowClass))
    {
        return 0;
    }

    HWND hwnd = CreateWindowEx(WS_EX_LAYERED | WS_EX_TOPMOST | WS_EX_TOOLWINDOW, L"Keystrokes", L"Keystrokes", WS_POPUP, 0, 0, 148, 140, 0, 0, hInstance, 0);

    if (!hwnd)
    {
        return 0;
    }

    SetLayeredWindowAttributes(hwnd, RGB(0, 0, 0), 0, LWA_COLORKEY);

    ShowWindow(hwnd, nCmdShow);

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

    return 0;
}

void paintRect(HDC hdc, RECT dim, COLORREF penCol, COLORREF brushCol, int opacity)
{
    HDC tempHDC = CreateCompatibleDC(hdc);

    BITMAPINFO bitmapInfo;
    ZeroMemory(&bitmapInfo, sizeof(BITMAPINFO));

    bitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    bitmapInfo.bmiHeader.biWidth = dim.right - dim.left;
    bitmapInfo.bmiHeader.biHeight = dim.bottom - dim.top;
    bitmapInfo.bmiHeader.biPlanes = 1;
    bitmapInfo.bmiHeader.biBitCount = 32;
    bitmapInfo.bmiHeader.biCompression = BI_RGB;
    bitmapInfo.bmiHeader.biSizeImage = (dim.right - dim.left) * (dim.bottom - dim.top) * 4;

    HBITMAP hBitmap = CreateDIBSection(tempHDC, &bitmapInfo, DIB_RGB_COLORS, NULL, NULL, 0x0);

    SelectObject(tempHDC, hBitmap);
    SetDCPenColor(tempHDC, RGB(0, 0, 255));
    SetDCBrushColor(tempHDC, RGB(0, 0, 255));
    FillRect(tempHDC, &dim, CreateSolidBrush(RGB(0, 0, 255)));

    BLENDFUNCTION blend = { AC_SRC_OVER, 0, 255, 0 };
    AlphaBlend(hdc, dim.left, dim.top, dim.right, dim.bottom, tempHDC, dim.left, dim.top, dim.right, dim.bottom, blend);
}

LRESULT CALLBACK windowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch (uMsg)
    {
        case WM_LBUTTONDOWN:
        {
            SendMessage(hwnd, WM_NCLBUTTONDOWN, HTCAPTION, 0);
        }
        
        break;

        case WM_MBUTTONDOWN:
        {
            PostQuitMessage(0);
        }

        break;

        case WM_PAINT:
        {
            PAINTSTRUCT ps;
            HDC hDC = BeginPaint(hwnd, &ps);

            paintRect(hDC, { 0, 0, 48, 48 }, RGB(255, 0, 0), RGB(255, 255, 255), 255);

            EndPaint(hwnd, &ps);
        }
    }

    return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
Zhu Song - MSFT

“好像位图本身具有黑色背景。”

因为您的背景设置为:

windowClass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);

当然,您可以将其设置为NULL_BRUSH透明:

windowClass.hbrBackground = (HBRUSH)GetStockObject(NULL_BRUSH);

在此处输入图片说明

但是,当您移动它时,您会发现这并不是使窗口透明,而是停止绘制背景:

在此处输入图片说明

正如@Ben在这里回答

您尚未使窗口透明,只是刚刚停止绘制背景。您所看到的背景就是刚被绘制在窗口下方的任何东西。

您需要参考分层Windows

您不能直接在窗口上添加矩形,应该使用分层的窗口,然后添加所需的内容。

您可以参考以下示例:

#include <Windows.h>
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int WINAPI WinMain(_In_  HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_  LPSTR szCmdLine, _In_  int iCmdShow)
{
    static TCHAR szAppName[] = TEXT("test window");
    HWND hwnd;
    MSG msg;
    WNDCLASS wndclass;
    wndclass.style = CS_HREDRAW | CS_VREDRAW;
    wndclass.lpfnWndProc = WndProc;
    wndclass.cbClsExtra = 0;
    wndclass.cbWndExtra = 0;
    wndclass.hInstance = hInstance;
    wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
    wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
    wndclass.lpszMenuName = NULL;
    wndclass.lpszClassName = szAppName;
    if (!RegisterClass(&wndclass))
    {
        MessageBox(NULL, TEXT("This program requires Windows NT!"), szAppName, MB_ICONERROR);
    }

    hwnd = CreateWindowEx(WS_EX_LAYERED | WS_EX_TOPMOST | WS_EX_TOOLWINDOW, szAppName,
        TEXT("the hello program"),
        WS_POPUP,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        148,
        148,
        NULL,
        NULL,
        hInstance,
        NULL);
    SetLayeredWindowAttributes(hwnd, 0, 1, LWA_ALPHA);
    ShowWindow(hwnd, iCmdShow);
    UpdateWindow(hwnd);
    while (GetMessageW(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessageW(&msg);
    }
    return msg.wParam;
}
VOID FadeRect(RECT* prc, HDC hdc)
{
    BOOL fFade = FALSE;
    static HWND hwnd;
    SIZE size;
    POINT ptSrc = { 0, 0 };
    BLENDFUNCTION blend;

    SystemParametersInfo(SPI_GETSELECTIONFADE, 0, &fFade, 0);
    if (!fFade)
        return;
    if (!hwnd) hwnd = CreateWindowEx(WS_EX_LAYERED | 
        WS_EX_TRANSPARENT | 
        WS_EX_TOPMOST | WS_EX_TOOLWINDOW,
        L"static", L"static", WS_POPUP | WS_VISIBLE, prc->left,
        prc->top, prc->right, prc->bottom, NULL, (HMENU)0, NULL, NULL);
    else MoveWindow(hwnd, prc->left, prc->top, prc->right, prc->bottom, TRUE);

    RECT rect{ prc->left,prc->top,prc->right,prc->bottom };
    size.cx = prc->right - prc->left;
    size.cy = prc->bottom - prc->top;

    blend.BlendOp = AC_SRC_OVER;
    blend.BlendFlags = 0;
    blend.AlphaFormat = 0;
    blend.SourceConstantAlpha = 150;
    UpdateLayeredWindow(hwnd, NULL, NULL, &size, hdc, &ptSrc, 0,
        &blend, ULW_ALPHA);
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
    case WM_LBUTTONDOWN:
    {
        SendMessage(hwnd, WM_NCLBUTTONDOWN, HTCAPTION, 0);
        InvalidateRect(hwnd, NULL, TRUE);
    }
    break;
    case WM_MBUTTONDOWN:
    {
        PostQuitMessage(0);
    }

    break;

    case WM_PAINT:
    {
        PAINTSTRUCT ps;
        RECT rect;
        GetClientRect(hwnd, &rect);
        MapWindowPoints(hwnd, GetParent(hwnd), (LPPOINT)&rect, 2);
        HDC hDC = BeginPaint(hwnd, &ps);
        RECT rc{ rect.left,rect.top,rect.left + 48,rect.top + 48 };
        FadeRect(&rc, hDC);
        EndPaint(hwnd, &ps);
    }
    break;
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    }

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

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

如何在其中包含一些用户控件的面板上绘制一个半透明的矩形?

来自分类Dev

在iOS中绘制半透明矩形

来自分类Dev

在iOS中绘制半透明矩形

来自分类Dev

在顶层保留半透明背景的一个片段

来自分类Dev

如何在画布上绘制多个半透明矩形?

来自分类Dev

如何绘制半透明的NSTableRowView?

来自分类Dev

如何绘制半透明的NSTableRowView?

来自分类Dev

DirectX中两个矩形的透明度,一个接一个-我看到的是窗口背景,而不是第二个纹理

来自分类Dev

在画布中,如何绘制2个半透明的重叠圆

来自分类Dev

在画布中,如何绘制2个半透明的重叠圆

来自分类Dev

在一个窗口中绘制许多csv文件

来自分类Dev

gnuplot bashshell在一个窗口中绘制多条曲线

来自分类Dev

创建一个透明的表面以在pygame中绘制像素

来自分类Dev

从一个方向看,体绘制更透明

来自分类Dev

如何在matlab中绘制一个透明的圆圈?

来自分类Dev

Qt半透明背景导致子窗口小部件被“压印”在父窗口中

来自分类Dev

如何使 CSS 半透明的两个形状看起来像一个?

来自分类Dev

制作一个透明窗口作为绘图画布

来自分类Dev

OpenGL:创建一个“透明的类似窗口的对象”

来自分类Dev

WPF制作一个越来越透明的窗口

来自分类Dev

Qt-在Windows中绘制一个完全透明的窗口,而无需使用WA_TranslucentBackground

来自分类Dev

如何在另一个JComponent上添加半透明JPanel

来自分类Dev

Android:片段以半透明的方式覆盖另一个片段

来自分类Dev

当半透明div覆盖另一个div时,CSS会消除悬停效果

来自分类Dev

如何设计一个很酷的半透明启动画面?

来自分类Dev

从__block typeof(self)blockSelf呈现一个半透明的模态视图

来自分类Dev

有不透明的孩子时是否可以有一个透明的窗口?

来自分类Dev

有不透明的孩子时是否可以有一个透明的窗口?

来自分类Dev

Tkinter窗口中的透明背景

Related 相关文章

  1. 1

    如何在其中包含一些用户控件的面板上绘制一个半透明的矩形?

  2. 2

    在iOS中绘制半透明矩形

  3. 3

    在iOS中绘制半透明矩形

  4. 4

    在顶层保留半透明背景的一个片段

  5. 5

    如何在画布上绘制多个半透明矩形?

  6. 6

    如何绘制半透明的NSTableRowView?

  7. 7

    如何绘制半透明的NSTableRowView?

  8. 8

    DirectX中两个矩形的透明度,一个接一个-我看到的是窗口背景,而不是第二个纹理

  9. 9

    在画布中,如何绘制2个半透明的重叠圆

  10. 10

    在画布中,如何绘制2个半透明的重叠圆

  11. 11

    在一个窗口中绘制许多csv文件

  12. 12

    gnuplot bashshell在一个窗口中绘制多条曲线

  13. 13

    创建一个透明的表面以在pygame中绘制像素

  14. 14

    从一个方向看,体绘制更透明

  15. 15

    如何在matlab中绘制一个透明的圆圈?

  16. 16

    Qt半透明背景导致子窗口小部件被“压印”在父窗口中

  17. 17

    如何使 CSS 半透明的两个形状看起来像一个?

  18. 18

    制作一个透明窗口作为绘图画布

  19. 19

    OpenGL:创建一个“透明的类似窗口的对象”

  20. 20

    WPF制作一个越来越透明的窗口

  21. 21

    Qt-在Windows中绘制一个完全透明的窗口,而无需使用WA_TranslucentBackground

  22. 22

    如何在另一个JComponent上添加半透明JPanel

  23. 23

    Android:片段以半透明的方式覆盖另一个片段

  24. 24

    当半透明div覆盖另一个div时,CSS会消除悬停效果

  25. 25

    如何设计一个很酷的半透明启动画面?

  26. 26

    从__block typeof(self)blockSelf呈现一个半透明的模态视图

  27. 27

    有不透明的孩子时是否可以有一个透明的窗口?

  28. 28

    有不透明的孩子时是否可以有一个透明的窗口?

  29. 29

    Tkinter窗口中的透明背景

热门标签

归档