0

The task is to draw to external windows such as drawing a line to a window running. (Kind of like ESP for games).

I have this code to draw to desktop (draws a rectangle), but how would I change it to draw to a window running of my choice?

Code to draw to desktop:

#include <iostream>
#include <Windows.h>

int main() {

/* hide console window */
ShowWindow(FindWindowA("ConsoleWindowClass", NULL), false);

/* Calling GetDC with argument 0 retrieves the desktop's DC */
HDC hDC_Desktop = GetDC(0);

/* Draw a simple blue rectangle on the desktop */
RECT rect = { 20, 20, 200, 200 };
HBRUSH blueBrush = CreateSolidBrush(RGB(0, 0, 255));
FillRect(hDC_Desktop, &rect, blueBrush);

Sleep(10);
return 0;
}
Alan Birtles
  • 32,622
  • 4
  • 31
  • 60
  • Edit: Can I change the 0 in GetDC to a window of my choice? – RichardJ532 May 25 '20 at 19:52
  • 4
    Simple answer: You can't. Rendering to a window is private to the owner of that window. If you want to appear graphics in front of other windows, create your own transparent overlay window. There are literally tens if not hundreds of questions like this. Do some research. – IInspectable May 25 '20 at 20:08

1 Answers1

1

When the external window is redrawn, the rectangle you drew will disappear. If you want the rectangle to not disappear when the window is refreshed, please follow @llspectable's suggestion.

You can add WS_EX_LAYERED style to make a layered window.

If you want to do something behind the layered window, you can add WS_EX_TRANSPARENT for transparency.

Here is some code you can refer.

#include <Windows.h>
#include <stdio.h>
#include <iostream>

using namespace std;


LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 
{
    PAINTSTRUCT ps;
    HDC hdc;
    RECT rect;
    switch (message)
    {
    case WM_PAINT:
    {
        hdc = BeginPaint(hwnd, &ps);
        RECT rect = { 0, 0, 200, 200 };
        HBRUSH blueBrush = CreateSolidBrush(RGB(0, 0, 255));
        FillRect(hdc, &rect, blueBrush);
        EndPaint(hwnd, &ps);
    }
    break;
    case WM_SIZE:
    {
        HWND notepad = (HWND)0x00060BA6; //Test window
        GetWindowRect(notepad, &rect);

        float m = (200.0 / 1920.0);
        float n = (200.0 / 1040.0);

        int wh = (rect.right - rect.left) * m;
        int ht = (rect.bottom - rect.top) * n;

        int x = 100 * m;
        int y = 100 * n;

        SetWindowPos(hwnd, HWND_TOPMOST, x+rect.left, y+rect.top, wh, ht, SWP_SHOWWINDOW);
    }
    break;
    case WM_DESTROY:
    {
        PostQuitMessage(0);
        return 0;
    }
    }
    return DefWindowProc(hwnd, message, wParam, lParam);   
};

HINSTANCE hinst;

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevinstance, PSTR szCmdLine, int iCmdShow) {
    HWND hwnd;

    hinst = GetModuleHandle(NULL);
    // create a window class:
    WNDCLASS wc = {};
    wc.lpfnWndProc = WndProc;
    wc.hInstance = hinst;
    wc.lpszClassName = L"win32";

    // register class with operating system:
    RegisterClass(&wc);

    // create and show window:
    hwnd = CreateWindowEx(WS_EX_LAYERED| WS_EX_TRANSPARENT, L"win32", L"My program", WS_POPUP &~WS_BORDER, 0, 0, 0, 0, NULL, NULL, hinst, NULL);

    SetLayeredWindowAttributes(hwnd, NULL, 255, LWA_ALPHA);
    if (hwnd == NULL) {
        return 0;
    }

    ShowWindow(hwnd, SW_SHOW);


    MSG msg = {};

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

}

Note: If you want the layered window to follow a specific external window together, then you need to handle the WM_SIZE message separately. If you have any other questions, please feel free to let me know.

Strive Sun
  • 5,988
  • 1
  • 9
  • 26