C/C++で透過ウィンドウプログラムを実現

この記事では、Windows 環境で C/C++ の WIN32API を使用して透明ウィンドウを実現するいくつかの方法を紹介します。ご質問がある場合は、プライベートメッセージを送信するか、コメント欄にコメントしてください。

1. 透明窓の実現

1. 方法 1

この関数を通じてSetLayeredWindowAttributes、次のコードを追加する必要があります。

// 设置窗口透明度
SetLayeredWindowAttributes(
	hWnd,       // 窗口句柄
	0,          // 需要透明化的颜色值,0表示不使用颜色值
	128,        // 透明度,取值为0-255
	LWA_ALPHA   // 指定透明度效果
);

完全なサンプル コードは次のとおりです。

#include <Windows.h>

LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    
    
    switch (message)
    {
    
    
    case WM_DESTROY:
    {
    
    
        PostQuitMessage(0);
        break;
    }
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow)
{
    
    
    // 定义窗口类
    const wchar_t CLASS_NAME[] = L"MyWindowClass";
    WNDCLASSEX wc = {
    
     0 };
    wc.cbSize = sizeof(wc);                         
    wc.lpfnWndProc = WindowProc;                  
    wc.lpszClassName = CLASS_NAME;
    wc.style = CS_HREDRAW | CS_VREDRAW;
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
    wc.cbWndExtra = sizeof(LONG_PTR);
    wc.hIcon = LoadIcon(hInstance, IDI_APPLICATION);
    wc.hIconSm = LoadIcon(hInstance, IDI_APPLICATION);
    wc.hInstance = hInstance;
    wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    wc.cbClsExtra = 0;
    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);

    // 注册窗口
    RegisterClassEx(&wc);

    // 创建窗口
    HWND hWnd = CreateWindowEx(
        WS_EX_LAYERED,                  
        CLASS_NAME,                     
        "透明窗口", 
        WS_OVERLAPPEDWINDOW,           
        CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
        NULL,       
        NULL,       
        hInstance,  
        NULL        
    );
    // 创建失败
    if (hWnd == NULL)
    {
    
    
        return -1;
    }

    // 设置窗口透明度
    SetLayeredWindowAttributes(
        hWnd,       // 窗口句柄
        0,          // 颜色键
        128,        // 透明度,取值为0-255
        LWA_ALPHA   // 
    );

    // 显示窗口
    ShowWindow(hWnd, nCmdShow);

    // 消息循环
    MSG msg = {
    
     0 };
    while (GetMessage(&msg, NULL, 0, 0))
    {
    
    
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return 0;
}

2.方法2

SetWindowLong()および関数を使用してSetLayeredWindowAttributes()、透明ウィンドウを実装します。

完全なサンプルコードは次のとおりです。

#include <windows.h>

LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    
    
    switch (msg)
    {
    
    
    case WM_CREATE:  // 多用于窗口的初始化
        // 设置窗口扩展样式为WS_EX_LAYERED
        SetWindowLong(hWnd, GWL_EXSTYLE, GetWindowLong(hWnd, GWL_EXSTYLE) | WS_EX_LAYERED);
        // 设置窗口透明度为50%(0-255,255为完全不透明)
        SetLayeredWindowAttributes(hWnd, 0, 128, LWA_ALPHA);
        break;
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hWnd, msg, wParam, lParam);
    }
    return 0;
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    
    
    const char *CLASS_NAME = "MyClass";

    WNDCLASS wc = {
    
    0};
    wc.lpfnWndProc = WndProc;
    wc.hInstance = hInstance;
    wc.lpszClassName = CLASS_NAME;
    RegisterClass(&wc);

    HWND hWnd = CreateWindowEx(WS_EX_LAYERED, CLASS_NAME, "Transparent Window", WS_OVERLAPPEDWINDOW,
                               CW_USEDEFAULT, CW_USEDEFAULT, 400, 300, NULL, NULL, hInstance, NULL);
    
    ShowWindow(hWnd, nCmdShow);

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

    return 0;
}

3. 方法 3

この関数を使用してUpdateLayeredWindow()透明ウィンドウを実現します。完全なコード例は次のとおりです。

#include <windows.h>

LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    
    
    switch (msg)
    {
    
    
    case WM_CREATE:
    {
    
    
        // 创建窗口的设备上下文
        HDC hdc = GetDC(hWnd);

        // 创建透明位图
        int width = 400;
        int height = 300;
        HBITMAP hBitmap = CreateCompatibleBitmap(hdc, width, height);

        // 创建与位图相关联的设备上下文
        HDC hdcMem = CreateCompatibleDC(hdc);
        SelectObject(hdcMem, hBitmap);

        // 绘制透明背景
        BLENDFUNCTION blend = {
    
     0 };
        blend.BlendOp = AC_SRC_OVER;
        blend.BlendFlags = 0;
        blend.AlphaFormat = AC_SRC_ALPHA;
        blend.SourceConstantAlpha = 128; // 透明度(0-255,255为完全不透明)

        RECT rcClient;
        GetClientRect(hWnd, &rcClient);
        FillRect(hdcMem, &rcClient, (HBRUSH)(COLOR_WINDOW + 1));

        // 使用UpdateLayeredWindow函数设置窗口为透明窗口
        POINT ptDst = {
    
     0, 0 };
        SIZE sizeWnd = {
    
     width, height };
        POINT ptSrc = {
    
     0, 0 };
        UpdateLayeredWindow(hWnd, hdc, NULL, &sizeWnd, hdcMem, &ptSrc, 0, &blend, ULW_ALPHA);

        // 释放资源
        DeleteDC(hdcMem);
        DeleteObject(hBitmap);
        ReleaseDC(hWnd, hdc);
    }
    break;
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hWnd, msg, wParam, lParam);
    }
    return 0;
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    
    
    const char* CLASS_NAME = "MyClass";

    WNDCLASS wc = {
    
     0 };
    wc.lpfnWndProc = WndProc;
    wc.hInstance = hInstance;
    wc.lpszClassName = CLASS_NAME;
    RegisterClass(&wc);

    HWND hWnd = CreateWindowEx(WS_EX_LAYERED, CLASS_NAME, "Transparent Window", WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT, CW_USEDEFAULT, 400, 300, NULL, NULL, hInstance, NULL);

    ShowWindow(hWnd, nCmdShow);

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

    return 0;
}

2番目、半透明ウィンドウの実現

1.ウィンドウ透明描画不透明

透明なウィンドウと不透明な描画の実装:

#include <windows.h>

// 窗口类名称
#define CLASS_NAME "MyWindowClass"

// 窗口标题
#define WINDOW_TITLE "Transparent Window"

// 窗口大小
#define WINDOW_WIDTH 640
#define WINDOW_HEIGHT 480

// GDI 绘图颜色
#define DRAW_COLOR RGB(0, 0, 255)

// 窗口透明色
#define TRANSPARENT_COLOR RGB(0, 0, 0)

// 窗口过程函数
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    
    
    switch (msg)
    {
    
    
    case WM_PAINT:
    {
    
    
        PAINTSTRUCT ps;
        HDC hdc = BeginPaint(hwnd, &ps);

        // 使用透明色创建一个画刷
        HBRUSH hBrush = CreateSolidBrush(TRANSPARENT_COLOR);

        // 用画刷填充背景
        RECT rect;
        GetClientRect(hwnd, &rect);
        FillRect(hdc, &rect, hBrush);

        // 绘制一个不透明的矩形
        HBRUSH hDrawBrush = CreateSolidBrush(DRAW_COLOR);
        RECT drawRect = {
    
     50, 50, 200, 200 };
        FillRect(hdc, &drawRect, hDrawBrush);

        // 释放资源
        DeleteObject(hBrush);
        DeleteObject(hDrawBrush);

        EndPaint(hwnd, &ps);
        break;
    }
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hwnd, msg, wParam, lParam);
    }

    return 0;
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    
    
    // 注册窗口类
    WNDCLASS wc = {
    
     0 };
    wc.lpfnWndProc = WndProc;
    wc.hInstance = hInstance;
    wc.hbrBackground = (HBRUSH)GetStockObject(NULL_BRUSH);
    wc.lpszClassName = CLASS_NAME;
    RegisterClass(&wc);

    // 创建窗口
    HWND hwnd = CreateWindowEx(WS_EX_LAYERED | WS_EX_TRANSPARENT | WS_EX_TOOLWINDOW,
        CLASS_NAME, WINDOW_TITLE,
        WS_POPUP | WS_VISIBLE,
        0, 0, WINDOW_WIDTH, WINDOW_HEIGHT,
        NULL, NULL, hInstance, NULL);

    // 设置透明色
    SetLayeredWindowAttributes(hwnd, TRANSPARENT_COLOR, 0, LWA_COLORKEY);

    // 消息循环
    MSG msg;
    while (GetMessage(&msg, NULL, 0, 0))
    {
    
    
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return (int)msg.wParam;
}

2.ウィンドウ半透明描画不透明

#include <windows.h>

// 窗口类名称
#define CLASS_NAME L"MyWindowClass"

// 窗口标题
#define WINDOW_TITLE L"Transparent Window"

// 窗口大小
#define WINDOW_WIDTH 640
#define WINDOW_HEIGHT 480

// 窗口透明度
#define WINDOW_ALPHA 200

// 窗口过程函数
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    
    
    switch (msg)
    {
    
    
    case WM_DESTROY:
    {
    
    
        PostQuitMessage(0);
        break;
    }
    case WM_LBUTTONDBLCLK:
    {
    
    
        // 鼠标双击时关闭窗口
        DestroyWindow(hwnd);
        break;
    }
    case WM_LBUTTONDOWN:
    {
    
    
        // 鼠标左键按下时开始拖动窗口
        SendMessage(hwnd, WM_SYSCOMMAND, SC_MOVE | HTCAPTION, 0);
        break;
    }
    case WM_PAINT:
    {
    
    
        PAINTSTRUCT ps;
        HDC hdc = BeginPaint(hwnd, &ps);

        // 绘制一个不透明的矩形
        HBRUSH hDrawBrush = CreateSolidBrush(RGB(0, 0, 255));
        RECT drawRect = {
    
     50, 50, 200, 200 };
        FillRect(hdc, &drawRect, hDrawBrush);

        // 释放资源
        DeleteObject(hDrawBrush);

        EndPaint(hwnd, &ps);
        break;
    }
    default:
        return DefWindowProc(hwnd, msg, wParam, lParam);
    }

    return 0;
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    
    
    // 注册窗口类
    WNDCLASS wc = {
    
     0 };
    wc.lpfnWndProc = WndProc;
    wc.hInstance = hInstance;
    wc.hbrBackground = (HBRUSH)GetStockObject(NULL_BRUSH);
    wc.lpszClassName = CLASS_NAME;
    wc.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
    RegisterClass(&wc);

    // 创建窗口
    HWND hwnd = CreateWindowEx(WS_EX_LAYERED,
        CLASS_NAME, WINDOW_TITLE,
        WS_POPUP | WS_VISIBLE | WS_SYSMENU,
        0, 0, WINDOW_WIDTH, WINDOW_HEIGHT,
        NULL, NULL, hInstance, NULL);

    // 设置窗口透明度
    SetLayeredWindowAttributes(hwnd, 0, WINDOW_ALPHA, LWA_ALPHA);

    // 消息循环
    MSG msg;
    while (GetMessage(&msg, NULL, 0, 0))
    {
    
    
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return 0;
}

参考資料:
よく使われるWin32Api各種まとめ
Win32ウィンドウとQtウィンドウの部分透明化
Win32の実現 SetLayeredWindowAttributesを使ってウィンドウを透明化
Win32ウィンドウを透明にするいくつかの方法Shadow 【Win32SDK基礎】
ウィンドウ詳細解説(超詳しく)(詳しく紹介) Windows(Win32)アプリケーションの簡単なウィンドウ作成と主要な機能の詳細説明 (1) Win32 描画概要



おすすめ

転載: blog.csdn.net/hfy1237/article/details/130948335