2013-04-04 65 views
1

我刚开始查看窗口区域,并试图创建一个椭圆窗口,可以通过拖动客户区来移动。不幸的是,当我拖动窗口时,窗口从椭圆来回闪烁到正常窗口(好像我从未称呼过SetWindowRgn),并且反复快速地返回。我如何正确移动一个区域的窗口?

我在MSDN上读到我必须调用SetWindowRgn(nullptr);,然后移动窗口,然后重置我在代码中已完成的区域。我通过拨SetWindowPosSWP_NOZORDER,SWP_NOSIZESWP_NOREDRAW移动窗口,我试过在所有的SWP_NOSENDCHANGING,​​和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); 
} 

我也试过在WM_MOUSEMOVE末,这并不能改变什么叫ValidateRgn(hwnd, nullptr);。另外,我试图在打电话的条件下返回0,如果设置moving是为了查看它是否只是其他一些正在发送的消息而已,它会导致窗口什么也不做,拖累。然后,我将这个条件应用于WM_PAINTWM_ERASEBKGND处理程序,但是在拖动时会导致相同的闪烁问题。

为了更容易地测试,这里的full code(只是简单的窗口创建等)。我是否正确地移动窗户?有一些信息或我应该处理的东西,但不?这发生在Window 7 Ultimate N.

回答

4

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

+0

工作出色,谢谢! – chris 2013-04-04 01:16:31

相关问题