我正在尝试将窗口部分移出屏幕顶部。但是,在我完成移动后,Windows的默认行为会将其弹回。是的,我理解为什么存在这种特殊功能;但是,我仍然不希望它出现在我的窗户上。然后我注意到我可以使用SetWindowPos
将一个窗口部分地设置在屏幕顶部,并且它不会弹回。例如,SetWindowPos(...., -100, -100, ....)
会将我的窗口设置在屏幕上方100像素,它将保持在那里。
所以,不是正常移动我的窗口(比如发送SendMessage(hwnd, WM_SYSCOMMAND, SC_MOVE | 0x0002, 0);
,我想使用SetWindowPos
移动。我的想法是处理WM_MOUSEMOVE
并检查鼠标左键是否关闭。如果鼠标左键按下,我会调用SetWindowPos
对当前鼠标位置,之前的鼠标位置进行一些数学运算,并将其传递给SetWindowPos
。
到目前为止,我有它工作,但不是很好。首先,如果鼠标快速移动,它根本不起作用。其次,当鼠标移动缓慢时,窗口会随着移动而摇晃。
这是我的WinProc:
LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static int lastMouseX = 0;
static int lastMouseY = 0;
switch (message) /* handle the messages */
{
case WM_LBUTTONDOWN:
lastMouseX = LOWORD(lParam);
lastMouseY = HIWORD(lParam);
break;
//case WM_NCMOUSEMOVE:
case WM_MOUSEMOVE:
if(wParam == MK_LBUTTON)
{
int currentMouseX = LOWORD(lParam);
int currentMouseY = HIWORD(lParam);
int deltaX = currentMouseX - lastMouseX;
int deltaY = currentMouseY - lastMouseY;
RECT prc;
GetWindowRect(hwnd, &prc);
SetWindowPos(hwnd, NULL, prc.left + deltaX, prc.top + deltaY, 0, 0, SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE);
lastMouseX = currentMouseX;
lastMouseY = currentMouseY;
}
break;
case WM_DESTROY:
PostQuitMessage (0); /* send a WM_QUIT to the message queue */
break;
default: /* for messages that we don't deal with */
return DefWindowProc (hwnd, message, wParam, lParam);
}
return 0;
}
以下是完整代码http://pastebin.com/9A8iV5GW
进一步检查Windows消息,我确切地看到Windows将窗口向下移动的位置,但我仍然不知道我需要做什么。我知道它可以做到,因为我已经在其他应用程序中看到过它。
<--I stop moving here with WM_LBUTTONUP -->
<windowMessage id="514" name="WM_LBUTTONUP">
<wParam>0x00000000</wParam>
<lParam>0x0049009E</lParam>
<returnValue>0x00000000</returnValue>
<-- And here is when windows moves it back down -->
</windowMessage><windowMessage id="534" name="WM_MOVING">
<wParam>0x00000009</wParam>
<lParam>0x003FF220</lParam>
<returnValue>0x00000000</returnValue>
</windowMessage><windowMessage id="70" name="WM_WINDOWPOSCHANGING">
<wParam>0x00000000</wParam>
<lParam>0x003FEF98</lParam>
<returnValue>0x00000000</returnValue>
</windowMessage><windowMessage id="36" name="WM_GETMINMAXINFO">
<wParam>0x00000000</wParam>
<lParam>0x003FEC20</lParam>
<returnValue>0x00000000</returnValue>
</windowMessage><windowMessage id="71" name="WM_WINDOWPOSCHANGED">
<wParam>0x00000000</wParam>
<lParam>0x003FEF98</lParam>
<returnValue>0x00000000</returnValue>
</windowMessage><windowMessage id="533" name="WM_CAPTURECHANGED">
<wParam>0x00000000</wParam>
<lParam>0x00000000</lParam>
<returnValue>0x00000000</returnValue>
</windowMessage><windowMessage id="70" name="WM_WINDOWPOSCHANGING">
<wParam>0x00000000</wParam>
<lParam>0x003FF210</lParam>
<returnValue>0x00000000</returnValue>
</windowMessage><windowMessage id="562" name="WM_EXITSIZEMOVE">
<wParam>0x00000000</wParam>
<lParam>0x00000000</lParam>
<returnValue>0x00000000</returnValue>
</windowMessage>
答案 0 :(得分:1)
这对我有用(使用捕获的窗口消息设计):
case WM_ENTERSIZEMOVE:
in_movesize_loop = true;
inhibit_movesize_loop = false;
break;
case WM_EXITSIZEMOVE:
in_movesize_loop = false;
inhibit_movesize_loop = false;
break;
case WM_CAPTURECHANGED:
inhibit_movesize_loop = in_movesize_loop;
break;
case WM_WINDOWPOSCHANGING:
if (inhibit_movesize_loop) {
WINDOWPOS* wp = reinterpret_cast<WINDOWPOS*>(lParam);
wp->flags |= SWP_NOMOVE;
return 0;
}
break;