如何找到Win32控件/窗口相对于其父窗口的位置?

hkB*_*sai 26 winapi position window win32gui

给定Win32窗口的句柄,我需要找到它相对于其父窗口的位置.

我知道几个函数(例如; GetWindowRect()GetClientRect()),但它们都没有显式返回所需的坐标.

我该怎么做呢?

hkB*_*sai 36

该溶液是用的组合功率GetWindowRect()MapWindowPoints().

GetWindowRect()检索窗口相对于监视器上显示的整个屏幕区域的坐标.我们需要将这些绝对坐标转换为主窗口区域的相对坐标.将MapWindowPoints()相对于一个窗口给出的坐标相对于另一个窗口变换.所以我们需要一个屏幕区域的"句柄"和我们试图找到坐标的控件的父窗口的句柄.屏幕是Windows术语中的"窗口",它被称为"桌面".我们可以通过HWND_DESKTOP定义的常量访问Desktop的句柄WinUser.h(包括Windows.h足够的).我们只需调用Win32函数就可以得到父窗口的句柄GetParent().现在我们拥有调用该MapWindowPoints()函数所需的所有参数.

RECT YourClass::GetLocalCoordinates(HWND hWnd) const
{
    RECT Rect;
    GetWindowRect(hWnd, &Rect);
    MapWindowPoints(HWND_DESKTOP, GetParent(hWnd), (LPPOINT) &Rect, 2);
    return Rect;
}
Run Code Online (Sandbox Code Playgroud)

MapWindowPoints() 定义为:

int MapWindowPoints(
  _In_     HWND hWndFrom,
  _In_     HWND hWndTo,
  _Inout_  LPPOINT lpPoints,
  _In_     UINT cPoints
);
Run Code Online (Sandbox Code Playgroud)

MapWindowPoints()将坐标相对转换hWndFromhWndTo.在我们的例子中,我们进行从Desktop(HWND_DESKTOP)到父窗口(GetParent(hWnd))的转换.因此,结果RECT结构保存子窗口(hWnd)相对于其父窗口的相对坐标.

  • 今天我花了相当多的时间来找到这个问题的解决方案。互联网上甚至本网站上有很多关于此事的错误和误导性信息。一个很大的悲剧是 Win32 没有给出一个明确的函数来收集这些信息,而且很难找到一个好的解释和示例代码来解决这个简单的问题。我在这里分享该解决方案,以帮助将来搜索该解决方案的其他用户。 (2认同)

thi*_*zzy 11

这是我用于Windows或控件(子窗口)的解决方案

RECT rc;
GetClientRect(hWnd,&rc);
MapWindowPoints(hWnd,GetParent(hWnd),(LPPOINT)&rc,2);
Run Code Online (Sandbox Code Playgroud)

  • 确实有一个矩形,@ Erdinc.它有两点.`MapWindowPoints`的最后一个参数需要*points*的数量来映射.实际上,如果未传递2,则在镜像(从右到左)窗口的情况下,该函数可能无法执行您所期望的操作.请参阅[文档中的备注](http://msdn.microsoft.com/en-us/library/dd145046.aspx). (2认同)

Шер*_*рей 5

我知道之前已经回答过,但是在屏幕坐标中获取子窗口的矩形,获取它的位置 ( POINT ptCWPos = {rectCW.left, rectCW.top};) 并使用该ScreenToClient()函数要容易得多,该函数会将屏幕坐标点转换为窗口的客户端坐标点:

PS:我知道这看起来像很多代码,但大部分都是摆弄矩形位置;在大多数情况下,实际上需要矩形位置而不是整个矩形。


HWND hwndCW, hwndPW; // the child window hwnd
                     // and the parent window hwnd
RECT rectCW;
GetWindowRect(hwndCW, &rectCW); // child window rect in screen coordinates
POINT ptCWPos = { rectCW.left, rectCW.top };
ScreenToClient(hwndPW, &ptCWPos); // transforming the child window pos
                                  // from screen space to parent window space
LONG iWidth, iHeight;
iWidth = rectCW.right - rectCW.left;
iHeight = rectCW.bottom - rectCW.top;

rectCW.left = ptCWPos.x;
rectCW.top = ptCWPos.y;
rectCW.right = rectCW.left + iWidth;
rectCW.bottom = rectCW.right + iHeight; // child window rect in parent window space

Run Code Online (Sandbox Code Playgroud)