正如标题所说,我想仅在用户将其从客户区的一部分拖动时才移动窗口。这将模仿正常的标题栏移动,这是因为我的表单是自定义的,它没有任何标题或标题栏。目前,我使用如下代码:
...
case WM_NCHITTEST:
return HTCAPTION;
并且无论在何处拖动,用户都可以移动窗口。我想限制这种可能性(只有窗口的顶部才允许移动)。我还没有尝试检查鼠标按下的位置,因为我不知道如何在WM_NCHITTEST
消息中执行此操作。
我在Visual Studio 2015中使用普通的Win32(winapi)C代码(目前没有MFC或其他任何东西)。
答案 0 :(得分:6)
如果您只是返回HTCAPTION
以回复所有 WM_NCHITTEST
消息,则会遇到麻烦。你会破坏滚动条,关闭按钮,调整边框大小等等,这些都是通过不同的HT*
值实现的。
但你有正确的想法。你想让你的窗口的客户区可以拖动,所以你需要让Windows认为你的客户区实际上是标题区(正如你所知,它是可拖动的)。该代码如下所示:
LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
// ...
case WM_NCHITTEST:
{
// Call the default window procedure for default handling.
const LRESULT result = ::DefWindowProc(hWnd, uMsg, wParam, lParam);
// You want to change HTCLIENT into HTCAPTION.
// Everything else should be left alone.
return (result == HTCLIENT) ? HTCAPTION : result;
}
// ...
}
但是,根据您问题中的图片,您似乎希望将此限制仅限于窗口的某个区域。您需要准确定义该区域的内容,然后点击测试以查看用户是否已在该区域中单击。假设rcDraggable
是包含the red box shown in your image边界的RECT
结构(在屏幕坐标中),您可以使用以下代码:
static RECT rcDraggable = ...
LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
// ...
case WM_NCHITTEST:
{
// Call the default window procedure for default handling.
const LRESULT result = ::DefWindowProc(hWnd, uMsg, wParam, lParam);
// Get the location of the mouse click, which is packed into lParam.
POINT pt;
pt.x = GET_X_LPARAM(lParam);
pt.y = GET_Y_LPARAM(lParam);
// You want to change HTCLIENT into HTCAPTION for a certain rectangle, rcDraggable.
// Everything else should be left alone.
if ((result == HTCLIENT) && (PtInRect(&rcDraggable, pt))
{
return HTCAPTION;
}
return result;
}
// ...
}
如果您根据客户端坐标定义rcDraggable
,则需要在执行命中测试之前将其转换为屏幕坐标以响应WM_NCHITTEST
。为此,请拨打MapWindowPoints
function,如下所示:
RECT rc = rcDraggable;
MapWindowPoints(hWnd, /* a handle to your window */
NULL, /* convert to screen coordinates */
reinterpret_cast<POINT*>(&rc),
(sizeof(RECT) / sizeof(POINT)));
答案 1 :(得分:1)
你可以在WM_LBUTTONDOWN处理程序中调用一些魔术代码,AFAIR:
ReleaseCapture();
SendMessage(yourWindowHandle, WM_SYSCOMMAND, 0xf012, 0) ;
几年前我在Delphi和Windows XP中使用过这种方法。我认为c ++必须类似。当然,在执行此操作之前,您可以检查x和y。