2013-04-04 63 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

相關問題