Win32设置带背景图片的透明窗体

⌚Time: 2023-04-02 23:56:49

👨‍💻Author: Jack Ge

使用函数SetLayeredWindowAttributes设置窗体的透明度


BOOL SetLayeredWindowAttributes(

  [in] HWND     hwnd,

  [in] COLORREF crKey,

  [in] BYTE     bAlpha,

  [in] DWORD    dwFlags

);

[in] hwnd



类型:HWND



分层窗口的句柄。 通过使用 CreateWindowEx 函数创建窗口时指定WS_EX_LAYERED,或通过创建窗口后通过 SetWindowLong 设置WS_EX_LAYERED来创建分层窗口。



Windows 8:顶级窗口和子窗口支持WS_EX_LAYERED样式。 以前的 Windows 版本仅支持顶级窗口 WS_EX_LAYERED 。



[in] crKey



类型: COLORREF



一个 COLORREF 结构,指定在组合分层窗口时要使用的透明度颜色键。 窗口以这种颜色绘制的所有像素都是透明的。 若要生成 COLORREF,请使用 RGB 宏。



[in] bAlpha



类型: BYTE



用于描述分层窗口的不透明度的 Alpha 值。 类似于 BLENDFUNCTION 结构的 SourceConstantAlpha 成员。 bAlpha 为 0 时,窗口是完全透明的。 bAlpha 为 255 时,窗口不透明。



[in] dwFlags



类型:DWORD



要执行的操作。 此参数可使用以下一个或多个值。



Value   含义

LWA_ALPHA

0x00000002

使用 bAlpha 确定分层窗口的不透明度。

LWA_COLORKEY

0x00000001

使用 crKey 作为透明度颜色。

返回值

类型: BOOL



如果该函数成功,则返回值为非零值。

首先通过SetWindowLong函数将窗体设置WS_EX_LAYERED属性,允许实现透明窗体


LONG SetWindowLongA(

  [in] HWND hWnd,

  [in] int  nIndex,

  [in] LONG dwNewLong

);

SetWindowLong(hwnd, GWL_EXSTYLE, GetWindowLong(hwnd, GWL_EXSTYLE) | WS_EX_LAYERED);

SetLayeredWindowAttributes(hwnd, RGB(0, 0, 0), 200, LWA_ALPHA);

代码实现


#include <windows.h>

#define WS_EX_LAYERED 0x00080000

#define LWA_ALPHA 0x00000002

#define LWA_COLORKEY 0x00000001

typedef bool (FAR WINAPI *LAYERFUNC)(HWND,COLORREF,BYTE,DWORD);

bool set_layered_window_attributes(HWND hwnd,COLORREF crKey,BYTE bAlpha,DWORD dwFlags){

    HMODULE hmod = LoadLibrary("user32.dll");

    LAYERFUNC SetLayer = (LAYERFUNC)GetProcAddress(hmod,"SetLayeredWindowAttributes");

    bool bReturn = SetLayer(hwnd,crKey,bAlpha,dwFlags);

    FreeLibrary(hmod);

    return bReturn;

}

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







int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR pCmdLine, int nCmdShow)

{

    // Register the window class.

    const char CLASS_NAME[]  = "Sample Window Class";



    WNDCLASSA wc = { };



    wc.lpfnWndProc   = WindowProc;

    wc.hInstance     = hInstance;

    wc.lpszClassName = CLASS_NAME;



    RegisterClassA(&wc);



    // Create the window.



    HWND hwnd = CreateWindowExA(

        0,                              // Optional window styles.

        CLASS_NAME,                     // Window class

        "window",    // Window text

        WS_OVERLAPPEDWINDOW,            // Window style



        // Size and position

        CW_USEDEFAULT, CW_USEDEFAULT, 600, 400,



        NULL,       // Parent window    

        NULL,       // Menu

        hInstance,  // Instance handle

        NULL        // Additional application data

        );



    if (hwnd == NULL)

    {

        return 0;

    }

    SetWindowLong(hwnd, GWL_EXSTYLE, GetWindowLong(hwnd, GWL_EXSTYLE) | WS_EX_LAYERED);



    //set_layered_window_attributes(hwnd, RGB(0, 0, 0), 128, LWA_ALPHA);

    SetLayeredWindowAttributes(hwnd, RGB(0, 0, 0), 200, LWA_ALPHA);

    ShowWindow(hwnd, nCmdShow);

    // Run the message loop.



    MSG msg = { };

    while (GetMessage(&msg, NULL, 0, 0) > 0)

    {

        TranslateMessage(&msg);

        DispatchMessage(&msg);

    }



    return 0;

}



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

{

    switch (uMsg)

    {

    case WM_CREATE:



        return 0;

    case WM_DESTROY:

        PostQuitMessage(0);

        return 0;



    case WM_PAINT:

        {

            BITMAP  bitmap;

            HBITMAP hBitmap = (HBITMAP)LoadImage(NULL, "bitmap.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE | LR_CREATEDIBSECTION);

            GetObject(hBitmap, sizeof(bitmap), &bitmap);

 

            PAINTSTRUCT ps;

            HDC dc = BeginPaint(hwnd, &ps);

 

            HDC memdc = CreateCompatibleDC(dc);

            SelectObject(memdc, hBitmap);

            RECT rc;

            GetClientRect(hwnd,&rc);

            

            int showWidth = rc.right-rc.left;

            int showHeight = rc.bottom-rc.top;

            SetStretchBltMode(dc,COLORONCOLOR);

            StretchBlt(dc,rc.left,rc.top,showWidth,showHeight,memdc,0,0,bitmap.bmWidth,bitmap.bmHeight,SRCCOPY);

            DeleteDC(memdc);

            DeleteObject(hBitmap);

            EndPaint(hwnd, &ps);

        }

        return 0;



    }

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

}




使用UpdateLayeredWindow函数可使窗体特定区域透明