re | win32 gdi透明窗口中画框 鼠标穿透

re | win32 gdi透明窗口中画框 鼠标穿透

使用vs2022编译的,便于游戏辅助的画框mzbox项目。

#include <Windows.h>

WCHAR szTitle[] = L"mzbox";
WCHAR szWindowClass[] = L"mzclazz";
HINSTANCE g_hInst;
HWND g_hWnd;

BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
    g_hInst = hInstance; // 将实例句柄存储在全局变量中
    // ex: 置顶、分层、鼠标穿透
    HWND hWnd = CreateWindowEx(WS_EX_TOPMOST | WS_EX_LAYERED | WS_EX_TRANSPARENT, szWindowClass, szTitle, WS_POPUP, 200, 200, 200, 200, NULL, NULL, hInstance, NULL);
    g_hWnd = hWnd;    // 保存全局句柄
    if (!hWnd)
    {
        return FALSE;
    }
    //SetLayeredWindowAttributes(hWnd, 0, (255 * 50) / 100, LWA_ALPHA);  // 整个窗口透明
    SetLayeredWindowAttributes(hWnd, RGB(255, 255, 255), 0, LWA_COLORKEY);
    ShowWindow(hWnd, nCmdShow);
    UpdateWindow(hWnd);
    return TRUE;
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
    case WM_COMMAND:
    {
        int wmId = LOWORD(wParam);
        // 分析菜单选择:
        switch (wmId)
        {
        default:
            return DefWindowProc(hWnd, message, wParam, lParam);
        }
    }
    break;
    case WM_PAINT:
    {
        PAINTSTRUCT ps;
        HDC hdc = BeginPaint(hWnd, &ps);
        // TODO: 在此处添加使用 hdc 的任何绘图代码...
        HPEN hPen;
        hPen = CreatePen(PS_SOLID, 3, RGB(255, 0, 0));
        SelectObject(hdc, hPen);
        // SelectObject(hdc, CreateSolidBrush(RGB(0, 255, 0)));
        Rectangle(hdc, 0, 0, 200, 200);
        DeleteObject(hPen);
        EndPaint(hWnd, &ps);
    }
    break;
    //case WM_CTLCOLORSTATIC:
    //    SetBkMode((HDC)wParam, TRANSPARENT);
    //    return (BOOL)((HBRUSH)GetStockObject(NULL_BRUSH));
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hWnd, message, wParam, lParam);
    }
    return 0;
}



ATOM MyRegisterClass(HINSTANCE hInstance)
{
    WNDCLASSEXW wcex = { 0 };

    wcex.cbSize = sizeof(WNDCLASSEX);

    wcex.style = CS_HREDRAW | CS_VREDRAW;
    wcex.lpfnWndProc = WndProc;
    wcex.cbClsExtra = 0;
    wcex.cbWndExtra = 0;
    wcex.hInstance = hInstance;
    wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
    wcex.hbrBackground = NULL;
    wcex.lpszMenuName = NULL;
    wcex.lpszClassName = szWindowClass;

    return RegisterClassExW(&wcex);
}


DWORD WINAPI ThreadProc(
    _In_ LPVOID lpParameter
) {
    int x = 0;
    int y = 0;
    Sleep(1000);   // 启动延迟
    while (1) {
        // 移动窗口位置
        SetWindowPos(g_hWnd, g_hWnd, x, y, 200, 200, SWP_NOZORDER);
        x++;
        y++;
        Sleep(100);
    }
}

int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
    _In_opt_ HINSTANCE hPrevInstance,
    _In_ LPWSTR    lpCmdLine,
    _In_ int       nCmdShow)
{
    MyRegisterClass(hInstance);
    // 执行应用程序初始化:
    if (!InitInstance(hInstance, nCmdShow))
    {
        return FALSE;
    }
    // 启动刷新线程
    CreateThread(NULL, 0, ThreadProc, NULL, 0, NULL);

    MSG msg;
    // 主消息循环:
    while (GetMessage(&msg, nullptr, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return (int)msg.wParam;

}


后续需要在新线程中刷新窗口的绘制,使用InvalidateRect(g_hWnd, NULL, true);即可

posted @ 2024-01-02 20:07  Mz1  阅读(92)  评论(0编辑  收藏  举报