c++ - 拖动窗口时,WindowFromPoint 不会触发 WM_NCHITTEST
问题描述
除了当前正在拖动的窗口之外,我正在尝试按照此答案中提供的说明找到某个点下方的窗口。
WindowFromPoint
我尝试的问题是,在拖动操作期间调用时,WM_NCHITTEST
显然没有触发消息。所以整个事情都不起作用,我无法获得被拖动的窗口下方的窗口。
这是一个最小的可重现示例。如果您运行此程序并通过标题栏拖动其中一个窗口,您会注意到“OnNcHitTest”不会显示在调试控制台中,即使WM_WINDOWPOSCHANGED
正在处理和WindowFromPoint
调用它也是如此。
#include <windows.h>
#include <atlbase.h>
#include <atlwin.h>
#include <atltypes.h>
using namespace ATL;
class CMyWindow :
public CWindowImpl<CMyWindow, CWindow, CWinTraits<WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME, WS_EX_TOOLWINDOW>>
{
public:
CMyWindow() : m_fDragging(FALSE)
{
}
BEGIN_MSG_MAP(CMyWindow)
MESSAGE_HANDLER(WM_WINDOWPOSCHANGED, OnWindowPosChanged)
MESSAGE_HANDLER(WM_NCHITTEST, OnNcHitTest)
MESSAGE_HANDLER(WM_EXITSIZEMOVE, OnExitSizeMove)
MESSAGE_HANDLER(WM_SYSCOMMAND, OnSysCommand)
COMMAND_HANDLER(IDCANCEL, BN_CLICKED, OnClickedCancel)
END_MSG_MAP()
private:
LRESULT OnSysCommand(UINT, WPARAM wParam, LPARAM, BOOL& bHandled)
{
bHandled = FALSE;
if ((wParam & 0xFFF0) == SC_MOVE)
{
m_fDragging = TRUE;
ATLTRACE(L"\nDrag begin\n");
}
return 0;
}
LRESULT OnExitSizeMove(UINT, WPARAM, LPARAM, BOOL& bHandled)
{
bHandled = FALSE;
m_fDragging = FALSE;
ATLTRACE(L"\nDrag end\n");
return 0;
}
LRESULT OnNcHitTest(UINT, WPARAM, LPARAM, BOOL& bHandled)
{
ATLTRACE(L"\nOnNcHitTest\n");
if (m_fDragging)
return HTTRANSPARENT;
bHandled = FALSE;
return 0;
}
LRESULT OnWindowPosChanged(UINT, WPARAM, LPARAM, BOOL& bHandled)
{
ATLTRACE(L"\nOnWindowPosChanged\n");
bHandled = FALSE;
if (m_fDragging)
{
CPoint pt;
if (GetCursorPos(&pt))
{
ATLTRACE(L"\nCalling WindowFromPoint\n");
HWND hwndFromPoint = WindowFromPoint(pt);
}
}
return 0;
}
LRESULT OnClickedCancel(WORD, WORD, HWND, BOOL&)
{
DestroyWindow();
return 0;
}
void OnFinalMessage(HWND)
{
delete this;
}
BOOL m_fDragging;
};
INT APIENTRY wWinMain(HINSTANCE, HINSTANCE, LPWSTR, INT)
{
for (UINT i = 0; i < 3; ++i)
{
CMyWindow* pwnd = new CMyWindow();
if (pwnd)
{
CRect rc(0, 0, 500, 500);
if (pwnd->Create(NULL, &rc))
{
pwnd->CenterWindow(NULL);
pwnd->ShowWindow(SW_SHOW);
}
}
}
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (INT)msg.wParam;
}
谁能解释我做错了什么?这是否与移动/大小模态循环或其他什么有关?我认为这不是问题,因为只要WM_WINDOWPOSCHANGED
被触发WindowFromPoint
并被调用,那么我认为WM_NCHITTEST
会被发送。但也许我错了。
或者问题是否与鼠标位于非客户区域有关?
谢谢你的帮助。
解决方案
我进行了更改OnNcHitTest
以允许拖动客户区中的任何点:
LRESULT OnNcHitTest(UINT, WPARAM, LPARAM, BOOL& bHandled)
{
ATLTRACE(L"\nOnNcHitTest\n");
if (m_fDragging)
return HTTRANSPARENT;
else
return HTCAPTION;
bHandled = FALSE;
return 0;
}
现在,如果您拖动标题以外的任何内容,OnNcHitTest
则在拖动过程中调用。你会得到不同的 HWND 句柄。不知道为什么会有区别。
你到底想达到什么目的?自定义拖放?
推荐阅读
- python - 为什么同一个对象的同一个绑定方法的ID是相等的?
- angular - RxJS 主题/可观察问题
- ios - 卸载包后无法运行 React Native iOS 应用程序
- python - 如何从第一个元素是python中的列名的列表中创建单列的DataFrame
- hadoop - 如何从 Sqoop 导入中捕获已处理记录的计数?
- android - 如何通过传感器获取 android 设备位置和平移
- unix - 提取与unix中的模式匹配的所有子字符串
- c++ - Opencv average filter gives different output than Matlab average filter
- bash - 使用需要自定义端口号的 ssh 登录时有什么方法可以隐藏端口号
- c# - Cannot Switch between Bootstrap Tabs