给定 Win32 窗口的句柄,我需要找到它相对于其父窗口的位置。
我知道几个函数(例如;GetWindowRect()
和GetClientRect()
),但它们都没有明确返回所需的坐标。
我该怎么做呢?
给定 Win32 窗口的句柄,我需要找到它相对于其父窗口的位置。
我知道几个函数(例如;GetWindowRect()
和GetClientRect()
),但它们都没有明确返回所需的坐标。
我该怎么做呢?
解决方案是使用 和 的组合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;
}
MapWindowPoints()
定义为:
int MapWindowPoints(
_In_ HWND hWndFrom,
_In_ HWND hWndTo,
_Inout_ LPPOINT lpPoints,
_In_ UINT cPoints
);
MapWindowPoints()
将坐标相对从 变换hWndFrom
为hWndTo
。在我们的例子中,我们进行从桌面(HWND_DESKTOP
)到父窗口(GetParent(hWnd)
)的转换。因此,生成的RECT
结构保存了我们的子窗口 ( hWnd
) 相对于其父窗口的相对坐标。
这是我用于 Windows 或控件(子窗口)的解决方案
RECT rc;
GetClientRect(hWnd,&rc);
MapWindowPoints(hWnd,GetParent(hWnd),(LPPOINT)&rc,2);
我知道之前已经回答过了,但是在屏幕坐标中获取子窗口的矩形,获取它的位置(POINT ptCWPos = {rectCW.left, rectCW.top};
)并使用该ScreenToClient()
函数会容易得多,这会将屏幕坐标点转换为窗口的客户端坐标点:
PS:我知道这看起来像很多代码,但大部分都是在摆弄 rect 位置;在大多数情况下,实际上需要矩形位置而不是整个矩形。
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
这是基于上述答案的非常基本的 typedef 结构:
typedef struct tagRectCl {
static RECT rectOut;
RECT RectCl(int ctrlID, HWND &hwndCtrl, HWND &ownerHwnd)
{
RECT rectIn;
GetWindowRect(hwndCtrl, &rectIn); //get window rect of control relative to screen
MapWindowPoints(NULL, ownerHwnd, (LPPOINT)&rectIn, 2);
rectOut = rectIn;
return rectOut;
}
RECT RectCl(int ctrlID)
{
// for rectOut already populated
return rectOut;
}
};
}RectCl;
RECT RectCl::rectOut = {};
这个想法是将 ctrlID 扩展到一系列控件,其中rectOut
可以考虑存储对应的 s 以获得更适应的结构。
用法:以下返回转换后的矩形:
RECT rect1 = RectCl().RectCl(IDC_CTRL1, hWndCtrl, hWndOwner);
以下是一个部分编码的函数,它将两个答案的元素转换为可用于对话的内容- 特别是对于移动/调整控制坐标,这是登陆此页面的原始原因。它接受来自资源或项目
的完整控件 ID 作为参数,以及其容器的句柄。
还应该考虑在调用函数之前是否通过监听in来最小化。HMENU
CreateWindow
ownerHwnd
SIZE_MINIMIZED
WM_SIZE
BOOL ProcCtrl(int ctrlID, HWND ownerHwnd)
{
RECT rcClient = {0};
HWND hwndCtrl = GetDlgItem(ownerHwnd, ctrlID);
if (hwndCtrl)
{
GetWindowRect(hwndCtrl, &rcClient); //get window rect of control relative to screen
MapWindowPoints(NULL, ownerHwnd, (LPPOINT)&rcClient,2);
/* Set extra scaling parameters here to suit in either of the following functions
if (!MoveWindow(hwndCtrl, rcClient.left, rcClient.top,
rcClient.right-rcClient.left, rcClient.bottom-rcClient.top, TRUE))
{
//Error;
return FALSE;
}
//if (!SetWindowPos(hwndCtrl, NULL, (int)rcClient.left, (int)(rcClient.top),
//(int)(rcClient.right - rcClient.left), (int)(rcClient.bottom - rcClient.top), SWP_NOZORDER))
{
//Error;
//return FALSE;
}
}
else
{
//hwndCtrl Error;
return FALSE;
}
return TRUE;
}
更简单
BOOL CAuxFormView::OnInitDialog()
{
// run the default
CDialog::OnInitDialog();
// define a rectangular
CRect rc1;
// get area of the control to the screen coordinates
m_Viewer_Ctrl.GetWindowRect(rc1);
// transform the screen coordinates relevant to the Dialog coordinates
ScreenToClient(rc1);
// move and refresh the control to the new area
m_Viewer_Ctrl.MoveWindow(rc1);
}