所以我使用的是Visual C ++,我创建了一个可拖动的无边框窗口。无论如何,顶部有一个工具栏,我希望能够通过该工具栏拖动窗口。我仍然希望工具栏能够正常工作,但我不知道如何能够通过它拖动窗口。这是我当前的窗口(参见顶部的工具栏):
这是我目前使其可拖动的代码:
case WM_NCHITTEST: {
LRESULT hit = DefWindowProc(hWnd, message, wParam, lParam);
if(hit == HTCLIENT) hit = HTCAPTION;
return hit;
}
break;
答案 0 :(得分:1)
您正在通过挂钩WM_NCHITTEST走在正确的轨道上。现在,你需要改变什么构成客户命中与字幕命中。如果我现在理解您的代码,那么您在窗口的客户区域(除了边框之外的所有区域)中单击的任何位置都将允许您将窗口拖到其他位置。这将使您与应用程序的交互非常困难。相反,只有在确定击中位于菜单区域内后,才应返回HTCAPTION。特别是,菜单栏的区域没有文件/编辑/帮助按钮。
case WM_NCHITTEST: {
LRESULT hit = DefWindowProc(hWnd, message, wParam, lParam);
if (hit == HTCLIENT) { // The hit was somewhere in the client area. Don't know where yet.
// Perform your test for whether the hit was in the region you would like to intercept as a move and set hit only when it is.
// You will have to pay particular attention to whether the user is actually clicking on File/Edit/Help and take care not to intercept this case.
// hit = HTCAPTION;
}
return hit;
break;
}
这里要记住的一些事情:
答案 1 :(得分:0)
在我的一个应用程序中,我还希望将窗口设置为我称之为“客户区可拖动”的窗口。不幸的是提到的解决方案(用HTCAPTION取代HTCLIENT) 确实存在严重缺陷:
双击客户区现在显示的行为与此相同 双击标题(即最小化/最大化窗口)!
为了解决这个问题,我在我的消息处理程序(摘录)中执行了以下操作:
case WM_MOUSEMOVE:
// Move window if we are dragging it
if (mIsDragging) // variable: bool mIsDragging;
{
POINT mousePos = {GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)};
mIsDragging = (ClientToScreen(hWnd, &mousePos) &&
SetWindowPos(hWnd,
NULL,
mDragOrigin.left + mousePos.x - mDragPos.x,
mDragOrigin.top + mousePos.y - mDragPos.y,
0,
0,
SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE));
}
break;
case WM_LBUTTONDOWN:
// Check if we are dragging and safe current cursor position in case
if (wParam == MK_LBUTTON)
{
POINT mousePos = {GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)};
if (ClientToScreen(hWnd, &mousePos) &&
DragDetect(hWnd, mousePos))
{
// Check if the cursor is pointing to your new caption here!!!!
mIsDragging = true;
mDragPos = mousePos;
GetWindowRect(hWnd, &mDragOrigin);
SetCapture(hWnd);
}
}
break;
// Remove this case when ESC key handling not necessary
case WM_KEYDOWN:
// Restore original window position if ESC is pressed and dragging active
if (!mIsDragging || wParam != VK_ESCAPE)
{
break;
}
// ESC key AND dragging... we restore original position of window
// and fall through to WM_LBUTTONUP as if mouse button was released
// (i.o.w. NO break;)
SetWindowPos(hWnd, NULL, mDragOrigin.left, mDragOrigin.top, 0, 0,
SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
case WM_LBUTTONUP:
ReleaseCapture();
break;
case WM_CAPTURECHANGED:
mIsDragging = false;
break;
(伪)代码省略了返回值(默认值:0)和变量定义 应该让程序清楚!? (如果没有给我留言,我会添加更多 或所有代码)。
ps:我刚刚发现了另一个全面的描述,也解释了这些差异 这两个解决方案:http://tinyurl.com/bqtyt3q