如何重新设置窗口父句柄且不影响MoveWindow的屏幕坐标?
解决SetParent后MoveWindow坐标转换问题
当调用SetParent将WS_POPUP风格的窗口重新设置父窗口后,窗口的坐标空间会从屏幕坐标切换为父窗口客户区坐标,这是Windows窗口机制的正常行为。要继续用屏幕坐标控制窗口位置,只需先将屏幕坐标转换为父窗口的客户区坐标即可,具体步骤如下:
- 调用
ScreenToClient函数,把目标屏幕坐标转换为父窗口客户区内的相对坐标 - 使用转换后的坐标调用
MoveWindow
代码示例
// 假设新父窗口句柄为newParentHwnd,目标屏幕坐标为xScreen、yScreen POINT screenPt = { xScreen, yScreen }; // 将屏幕坐标转换为父窗口客户区坐标 ScreenToClient(newParentHwnd, &screenPt); // 用转换后的坐标移动窗口,最后一个参数为BOOL类型,表示是否立即重绘窗口 MoveWindow(m_hWnd, screenPt.x, screenPt.y, width, height, TRUE);
补充说明
你之前的MoveWindow调用中最后一个参数用了SWP_NOZORDER,这是SetWindowPos的参数,属于误用。MoveWindow的最后一个参数应为TRUE(重绘)或FALSE(不重绘),如果需要更精细的窗口位置控制,也可以改用SetWindowPos,配合坐标转换同样能实现需求:
RECT winRect; winRect.left = xScreen; winRect.top = yScreen; winRect.right = xScreen + width; winRect.bottom = yScreen + height; // 将屏幕矩形转换为父窗口客户区矩形 ScreenToClient(newParentHwnd, (POINT*)&winRect.left); ScreenToClient(newParentHwnd, (POINT*)&winRect.right); SetWindowPos(m_hWnd, NULL, winRect.left, winRect.top, winRect.right - winRect.left, winRect.bottom - winRect.top, SWP_NOZORDER | SWP_NOACTIVATE);
内容的提问来源于stack exchange,提问作者yendang9423082
相关产品推荐
相关产品推荐

