2013-04-04 2 views
1

Я только начал изучать области окна, и я пытаюсь создать эллиптическое окно, которое я могу перемещать, перетаскивая область клиента. К сожалению, когда я перетаскиваю окно, окно мигает от эллипса до нормального окна (как будто я никогда не звонил SetWindowRgn) и обратно, многократно и быстро.Как правильно перемещать окно с областью?

Я прочитал в MSDN, что мне нужно позвонить SetWindowRgn(nullptr);, а затем переместить окно, а затем сбросить регион, который я уже сделал в своем коде. Я перемещаю окно, вызывая SetWindowPos с SWP_NOZORDER, SWP_NOSIZE и SWP_NOREDRAW, и я попытался добавить все SWP_NOSENDCHANGING, 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, если установлено moving, чтобы узнать, было ли это просто какое-то другое сообщение, которое отправлялось с ним, но это привело к тому, что окно ничего не делало, когда тащили. Затем я применил это условие к обработчикам WM_PAINT и WM_ERASEBKGND, но это привело к той же проблеме мерцания при перетаскивании.

Чтобы легче было протестировать его, вот full code (просто рудиментарное создание окна и т. Д.). Я собираюсь переместить окно правильно? Есть ли какое-то сообщение или что-то, что я должен обработать, но не так ли? Это происходит на Window 7 Ultimate N.

ответ

4

Более простой способ обработки логики перемещения - обрабатывать сообщение WM_NCHITTEST, возвращая HTCAPTION. Это заставляет Windows обрабатывать все логики перемещения для вас.

+0

Это работает блестяще, спасибо! – chris

Смежные вопросы