I'm playing around in a console application and thought it be nice if I could just popup a rectangle around areas on the desktop so I can visually see where various RECTs are. Like you see with things like UISpy, Inspect, Spy++ (drag target over window), etc.. What method is typically used to do that?
I tried this, but it is not working:
void DoMessageLoop(void * parg)
{
MSG msg;
// Main message loop:
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
_endthread();
}
HWND CreateLayeredWindow(RECT *prc)
{
LPCTSTR szWindowClass = _T("TransparentClass");
// Register class
WNDCLASSEX wcex = {0};
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.lpfnWndProc = DefWindowProc;
wcex.hInstance = GetModuleHandle(NULL);
wcex.lpszClassName = szWindowClass;
RegisterClassEx(&wcex);
HWND hWnd = CreateWindowEx(WS_EX_LAYERED | WS_EX_TOPMOST, szWindowClass, 0, WS_OVERLAPPEDWINDOW, prc->left,
prc->top, prc->right-prc->left, prc->bottom-prc->top, NULL, NULL, GetModuleHandle(NULL), NULL);
SetLayeredWindowAttributes(hWnd, RGB(255,0,255), 50, LWA_COLORKEY);
HBRUSH brush=CreateSolidBrush(RGB(255, 0, 255));
HPEN pen=CreatePen(PS_SOLID, 1, RGB(255, 0, 0));
HDC hdc=GetDC(hWnd);
HBRUSH oldbrush=(HBRUSH)SelectObject(hdc, brush);
HPEN oldpen=(HPEN) SelectObject(hdc, pen);
Rectangle(hdc, 0, 0, prc->right-prc->left, prc->bottom-prc->top);
SelectObject(hdc, oldpen);
SelectObject(hdc, oldbrush);
DeleteObject(pen);
DeleteObject(brush);
ReleaseDC(hWnd, hdc);
ShowWindow(hWnd, SW_SHOW);
_beginthread(DoMessageLoop, 0, hWnd);
return hWnd;
}
Okay, I got it working, but had to setup a WndProc (and move create/message loop to same thread):
LRESULT DrawRedRect(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
{
static RECT rcarea;
switch (msg) {
case WM_CREATE:
{
CREATESTRUCT *cs=(CREATESTRUCT*) lp;
rcarea=*((LPRECT) cs->lpCreateParams);
return DefWindowProc(hwnd, msg, wp, lp);
}
case WM_PAINT:
{
PAINTSTRUCT ps {};
HDC hdc=BeginPaint(hwnd, &ps);
RECT rc {};
GetClientRect(hwnd, &rc);
_ASSERT((rc.right-rc.left) == (rcarea.right-rcarea.left));
_ASSERT((rc.bottom-rc.top) == (rcarea.bottom-rcarea.top));
HPEN hPen=CreatePen(PS_SOLID, 5, RGB(255, 0, 0));
HBRUSH hBrush=CreateSolidBrush(MYTRANSPARENTCOLOR);
HGDIOBJ hOldPen=SelectObject(hdc, hPen);
HGDIOBJ hOldBrush=SelectObject(hdc, hBrush);
Rectangle(hdc, rc.left, rc.top, rc.right, rc.bottom);
if (hOldPen)
SelectObject(hdc, hOldPen);
if (hOldBrush)
SelectObject(hdc, hOldBrush);
if (hPen)
DeleteObject(hPen);
if (hBrush)
DeleteObject(hBrush);
EndPaint(hwnd, &ps);
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, msg, wp, lp);
}
return 0;
}
//-----------------------------------------------------------------------------------
HWND g_hWnd=NULL;
void CreateLayeredWindowThread(void *parg)
{
const PRECT &prc=reinterpret_cast<PRECT>(parg);
_ASSERT(g_hWnd==NULL);
LPCTSTR szWindowClass = _T("TransparentClass");
// Register class
WNDCLASSEX wcex = {0};
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.lpfnWndProc = DefWindowProc;
wcex.hInstance = GetModuleHandle(NULL);
wcex.lpszClassName = szWindowClass;
wcex.lpfnWndProc=DrawRedRect;
RegisterClassEx(&wcex);
RECT winrect=*prc;
AdjustWindowRect(&winrect, WS_POPUP, FALSE);
g_hWnd = CreateWindowEx(WS_EX_LAYERED | WS_EX_TOPMOST | WS_EX_NOACTIVATE | WS_EX_TOOLWINDOW, szWindowClass, 0, WS_POPUP, prc->left,
winrect.top, winrect.right-winrect.left, winrect.bottom-winrect.top, NULL, NULL, GetModuleHandle(NULL), (LPVOID) prc);
SetLayeredWindowAttributes(g_hWnd, MYTRANSPARENTCOLOR, 0, LWA_COLORKEY);
ShowWindow(g_hWnd, SW_SHOW);
MSG msg;
// Main message loop:
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
_endthread();
}
//-----------------------------------------------------------------------------------
void CreateLayeredWindow(RECT *prc)
{
_beginthread(CreateLayeredWindowThread, 0, prc);
}