如何在桌面上绘制一个矩形,如 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);
}