如何用C++绘制叠加层?

问题描述 投票:0回答:1

我正在将 dll 加载到进程中并在新线程中创建覆盖。

我的想法是从主 dll 线程绘制到该覆盖层中。

这是maindll.cpp代码:

uintptr_t mainModule = NULL;
bool visuals = false;
HWND hwndOverlay;

void DoMagic() {

    uintptr_t LocalPlayer = *(uintptr_t*)(mainModule + Offsets::dwLocalPlayerPawn);
    if (LocalPlayer == 0)
        return;

    if (GetAsyncKeyState(VK_F1) & 1)
    {
        visuals = !visuals;
    }

    if (hwndOverlay) {
        HDC hdcOverlay = GetDC(hwndOverlay);
        if (visuals) Visuals(mainModule, LocalPlayer, hdcOverlay);
    }

    Sleep(1);
}

DWORD WINAPI OverlayThread(LPVOID lpParam) {
    HMODULE hModule = (HMODULE)lpParam;
    hwndOverlay = CreateOverlayWindow(hModule);

    if (!hwndOverlay) {
        MessageBox(NULL, L"Error creating overlay window", L"Error", MB_ICONERROR);
        return 1;
    }

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

    return 0;
}

DWORD WINAPI MainFunc(HMODULE hModule) {
    AllocConsole();
    FILE* f;
    freopen_s(&f, "CONOUT$", "w", stdout);    

    CloseHandle(CreateThread(nullptr, 0, OverlayThread, hModule, 0, nullptr));

    mainModule = (uintptr_t)GetModuleHandle(L"client.dll");
    if (hModule)
    {
        while (!GetAsyncKeyState(VK_END) & 1) DoMagic();
    }
    else
    {
        std::cout << "Main module not found, press ENTER to exit..." << std::endl;
        getchar();
    }

    fclose(f);
    FreeConsole();
    FreeLibraryAndExitThread(hModule, 0);
    return 0;
}

这是我的 CreateOverlayWindow() 函数,可能是错误的:

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
    switch (uMsg) {
    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    }
    return DefWindowProc(hwnd, uMsg, wParam, lParam);
}

HWND CreateOverlayWindow(HINSTANCE hInstance) {
    const wchar_t CLASS_NAME[] = L"OverlayClass";

    WNDCLASSEX wc = {};
    wc.cbSize = sizeof(WNDCLASSEX);
    wc.style = CS_HREDRAW | CS_VREDRAW;
    wc.lpfnWndProc = WindowProc;
    wc.hInstance = hInstance;
    wc.hCursor = LoadCursor(nullptr, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)CreateSolidBrush(RGB(0, 0, 0));
    wc.lpszClassName = CLASS_NAME;

    RegisterClassEx(&wc);

    HWND hwndOverlay = CreateWindowEx(WS_EX_TOPMOST | WS_EX_TRANSPARENT | WS_EX_LAYERED, CLASS_NAME, L"Overlay",
        WS_POPUP, 0, 0, 1920, 1080, nullptr, nullptr, hInstance, nullptr);

    SetLayeredWindowAttributes(hwndOverlay, RGB(0, 0, 0), 0, LWA_COLORKEY | LWA_ALPHA);

    ShowWindow(hwndOverlay, SW_SHOW);
    UpdateWindow(hwndOverlay);

    return hwndOverlay;
}

这是我的 Visuals() 函数,我已将其缩短以避免无用的信息,因为我尝试绘制的坐标是正确的:

//Sets the Brush Color
HBRUSH Brush = (playerTeam == localPlayerTeam) ? hBrushGreen : hBrushRed;
COLORREF TextCOLOR = (playerTeam == localPlayerTeam) ? TextColorGreen : TextColorRed;

//Draws the box
DrawBorderBox(playerFeetInScreen.x + center, playerFeetInScreen.y, width, head - extra, 1, hdcOverlay, Brush);

//Draw our heath by converting a int to a char
char healthChar[255];
sprintf_s(healthChar, sizeof(healthChar), "%i", playerHealth);
DrawString(playerFeetInScreen.x, playerFeetInScreen.y, TextCOLOR, healthChar, Font, hdcOverlay);

当我检查它尝试绘制的坐标时,我看到了正确的值,但我没有看到任何绘制到屏幕上的东西:(我不知道这是否重要,但我有 3 个屏幕。

如何从我的 C++ dll 绘制到屏幕上?

c++ gdi
1个回答
0
投票

我只需更改这一行:

SetLayeredWindowAttributes(hwndOverlay, RGB(0, 0, 0), 0, LWA_COLORKEY | LWA_ALPHA);

对此:

SetLayeredWindowAttributes(hwndOverlay, RGB(0, 0, 0), 0, LWA_COLORKEY);
© www.soinside.com 2019 - 2024. All rights reserved.