Winapi 如何在win32而不是MFC中使用ScreenToClient?

Winapi 如何在win32而不是MFC中使用ScreenToClient?,winapi,Winapi,正如MSDN所说 BOOL ScreenToClient( _In_ HWND hWnd, LPPOINT lpPoint ); ScreenToClient的第二段是指向点的指针, MSDN所说的品脱是 typedef struct tagPOINT { LONG x; LONG y; } POINT, *PPOINT; 它只有x和y。它不像MFC ScreenToClient函数,para是一个rect,rect有宽度和高度。 我不知道如何使用win32 ScreenT

正如MSDN所说

BOOL ScreenToClient(
  _In_  HWND hWnd,
  LPPOINT lpPoint
);
ScreenToClient的第二段是指向点的指针, MSDN所说的品脱是

typedef struct tagPOINT {
  LONG x;
  LONG y;
} POINT, *PPOINT;
它只有x和y。它不像MFC ScreenToClient函数,para是一个rect,rect有宽度和高度。
我不知道如何使用win32 ScreenToClient函数。

请注意,
RECT

typedef struct _RECT {
  LONG left;
  LONG top;
  LONG right;
  LONG bottom;
} RECT, *PRECT;
看起来像是记忆中的两个连续点。因此,您可以执行MFC源代码所执行的操作,大致如下(现在我面前没有MFC源代码):


从C的角度来看,这并不是最干净的东西,但这些结构必须保持二进制兼容。

MFC实际上有两种方法,它们是重载的。一个接受
结构,就像Win32函数一样,另一个接受
RECT
结构,两者的工作方式相同:它将每个点从屏幕映射到客户端

如果您有一个
RECT
,希望在不使用MFC的情况下获取客户机坐标,则只需手动执行,如下所示:

RECT rect = GetMyRect();

POINT rectTL;
rectTL.x = rect.left;
rectTL.y = rect.top;
ScreenToClient( hWnd, &rectTL );

POINT rectBR;
rectBR.x = rect.right
rectBR.y = rect.bottom;
ScreenToClient( hWnd, &rectBR );

rect.left   = rectTL.x;
rect.top    = rectTL.y;
rect.right  = rectBR.x;
rect.bottom = rectBR.y;
可以使用在单个操作中转换RECT:

RECT r = ...;
MapWindowPoints(NULL, hWnd, (LPPOINT)&r, 2);

这是可行的,但我从不喜欢对内存布局中的结构进行假设。当然,但由于每个MFC应用程序都这样做,向后兼容性要求Microsoft永远不要更改内存布局。但是,请继续将成员复制到两点结构中,如果您愿意,再复制一次。从下一位程序员的角度来看,下面的假设——正确与否——并不明显。它看起来只是一个可疑的演员阵容。对于性能来说,这样的技巧可能是必要的,但在您有数据支持之前,这是一个过早的优化。+1-在这里使用RECT可能看起来很奇怪,但它在MSDN上得到了专门的支持和文档,以防有人怀疑它是否在做假设:而且它在从右到左的镜像情况下也做了正确的事情,哪个客户端的屏幕没有。
RECT r = ...;
MapWindowPoints(NULL, hWnd, (LPPOINT)&r, 2);