如何正确移动带有区域的窗口?

时间:2013-04-04 00:53:46

标签: c++ windows winapi region

我刚刚开始研究窗口区域,我正在尝试创建一个椭圆形窗口,我可以通过拖动客户区来移动它。不幸的是,当我拖动窗口时,窗口从椭圆到正常窗口来回闪烁(好像我从未调用SetWindowRgn),然后反复快速地返回。

我在MSDN上看到我必须调用SetWindowRgn(nullptr);,然后移动窗口,然后重置我已在代码中完成的区域。我通过SetWindowPosSWP_NOZORDERSWP_NOSIZE致电SWP_NOREDRAW来移动窗口,我尝试添加所有SWP_NOSENDCHANGING,{{1}而且,SWP_DEFERERASE也无济于事。

这是我的窗口程序,重点是SWP_NOCOPYBITS。我知道如果我释放窗外的按钮,它将无法工作;我计划在这个工作之后解决这个问题。我也遗漏了错误检查。很明显,调用确实有效,因为窗口确实在我拖动时移动。

WM_MOUSEMOVE

我也尝试在LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { static bool moving{}; switch (msg) { case WM_DESTROY: { PostQuitMessage(0); return 0; } case WM_LBUTTONDOWN: { moving = true; return 0; } case WM_LBUTTONUP: { moving = false; return 0; } case WM_MOUSEMOVE: { static POINT old{0, 0}; if (moving) { RECT r; GetWindowRect(hwnd, &r); int x = GET_X_LPARAM(lParam); int y = GET_Y_LPARAM(lParam); RECT newPos; newPos.left = r.left + x - old.x; newPos.top = r.top + y - old.y; SetWindowRgn(hwnd, nullptr, FALSE); SetWindowPos(hwnd, nullptr, newPos.left, newPos.top, 0, 0, SWP_NOZORDER | SWP_NOSIZE | SWP_NOREDRAW ); SetWindowRgn(hwnd, CreateEllipticRgn(200, 200, 600, 400), FALSE); } old.x = GET_X_LPARAM(lParam); old.y = GET_Y_LPARAM(lParam); return 0; } } return DefWindowProc(hwnd, msg, wParam, lParam); } 结束时调用ValidateRgn(hwnd, nullptr);,这不会改变任何内容。同样,我已经尝试将WM_MOUSEMOVE调用包装在一个条件中,如果设置了DefWindowProc则返回0,以便查看是否只是发送的其他消息正在弄乱它,但是这导致窗口在拖动时无效。然后我将该条件应用于movingWM_PAINT处理程序,但这会在拖动时导致相同的闪烁问题。

为了更容易地测试它,这里是full code(只是基本的窗口创建等)。我要以正确的方式移动窗户吗?是否有一些我应该处理的消息或事情,但不是吗?这种情况发生在Window 7 Ultimate N。

1 个答案:

答案 0 :(得分:4)

处理移动逻辑的一种更简单的方法是处理WM_NCHITTEST消息,返回HTCAPTION。这使得Windows可以为您处理所有移动逻辑。