如何在桌面上绘制一个矩形,如 UISpy/Spy++/etc..?
How do I draw a rectangle on the desktop like UISpy/Spy++/etc..?
我正在玩控制台应用程序,我认为如果我可以在桌面上的区域周围弹出一个矩形,这样我就可以直观地看到各种 RECT 的位置,那就太好了。就像您在 UISpy、Inspect、Spy++(将目标拖到 window 上)等东西中看到的那样。通常使用什么方法来做到这一点?
我试过了,但没用:
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;
}
好的,我让它工作了,但必须设置一个 WndProc(并将 create/message 循环移动到同一个线程):
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);
}
我正在玩控制台应用程序,我认为如果我可以在桌面上的区域周围弹出一个矩形,这样我就可以直观地看到各种 RECT 的位置,那就太好了。就像您在 UISpy、Inspect、Spy++(将目标拖到 window 上)等东西中看到的那样。通常使用什么方法来做到这一点?
我试过了,但没用:
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;
}
好的,我让它工作了,但必须设置一个 WndProc(并将 create/message 循环移动到同一个线程):
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);
}