答案 0 :(得分:36)
解决方案正在使用GetWindowRect()
和MapWindowPoints()
的强大功能。
GetWindowRect()
检索窗口相对于监视器上显示的整个屏幕区域的坐标。我们需要将这些绝对坐标转换为主窗口区域的相对坐标。 MapWindowPoints()
将相对于一个窗口给出的坐标转换为相对于另一个窗口的坐标。所以我们需要一个屏幕区域的“句柄”和我们试图找到坐标的控件的父窗口的句柄。屏幕是Windows术语中的“窗口”,它被称为“桌面”。我们可以通过HWND_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
)相对于其父窗口的相对坐标。
答案 1 :(得分:11)
这是我用于windows或控件(子窗口)的解决方案
RECT rc;
GetClientRect(hWnd,&rc);
MapWindowPoints(hWnd,GetParent(hWnd),(LPPOINT)&rc,2);
答案 2 :(得分:0)
我知道它已经被回答过了,但是更容易获得子窗口在屏幕坐标中的矩形,获得其位置(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
答案 3 :(得分:0)
更简单
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);
}
答案 4 :(得分:-1)
这是一个将两个答案的元素都用到可用的东西的功能 - 特别是用于移动/调整控制坐标。
它接受来自资源的整体控制ID作为参数,以及其容器的句柄
在调用该函数之前,还应考虑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 scaling parameters 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;
}