【发布时间】:2021-08-08 14:03:06
【问题描述】:
我正在尝试按照this 回答中提供的说明,以便在当前被拖动的窗口旁边找到某个点下方的窗口。
我尝试的问题是在拖动操作期间调用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 就会被发送。但也许我错了。
或者问题是否与鼠标位于非客户区有关?
感谢您的帮助。
【问题讨论】:
-
坦率地说,我不明白为什么被拖动的窗口会被发送
WM_NCHITTEST消息......显然,结果将是HTCAPTION,否则它不会被拖动。跨度> -
那么链接的答案应该如何工作?
-
等待作者解答...
标签: c++ winapi drag-and-drop