2009-02-06 13 views
5

Mam okno, które obsługuję wiadomości WM_NCLBUTTONUP, w celu obsługi kliknięć przycisków niestandardowych na pasku napisów. Działa to świetnie, gdy okno jest zmaksymalizowane, ale gdy nie jest, wiadomość WM_NCLBUTTONUP nigdy nie nadchodzi! Dostaję jednak wiadomość WM_NCLBUTTONDOWN. O dziwo WM_NCLBUTTONUP pojawia się, gdy kliknę po prawej stronie paska menu, ale w dowolnym miejscu wzdłuż paska napisów/ramki okna, wiadomość nigdy nie nadejdzie.Ciekawy problem brakującego komunikatu WM_NCLBUTTONUP, gdy okno nie jest zmaksymalizowane

Po chwili debugowania odkryłem, że jeśli ustawię punkt przerwania na CMainFrame :: OnNcLButtonDown(), kliknąłem pasek napisów, ale trzymam wciśnięty przycisk myszy, niech debugger włamie się do funkcji, naciśnij F5, aby kontynuować debugowanie, a następnie zwolnij przycisk myszy - magicznie WM_NCLBUTTONUP jest wysyłany !!

Moje pytanie jest dwojakie (1) co do diabła się dzieje? (2) w jaki sposób obejść ten "problem".

Zauważam również, że istnieje kilka innych osób w Internecie, które mają ten sam problem (szybkie Google ujawnia wiele innych osób z tym samym problemem, ale bez rozwiązania).

Edit
Dzięki dla pierwszych dwóch odpowiedzi, próbowałem dzwoniąc ReleaseCapture w NCLButtonDown, ale to nie ma żadnego wpływu (w rzeczywistości, zwraca NULL, wskazując przechwytywania nie jest na miejscu). Mogę tylko założyć, że funkcja klasy podstawowej (def window proc) może ustawić przechwytywanie. Zbadam w poniedziałek ...

Odpowiedz

4

Miałem ten sam problem. Problem polega na tym, że kliknięcie lewym przyciskiem myszy na podpisie okna rozpoczyna przeciąganie, a tym samym przechwytywanie myszy, co zapobiega pojawianiu się WM_NCLBUTTONUP.

Rozwiązaniem jest przesłonić WM_NCHITTEST:

LRESULT CALLBACK WndProc(HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam) 
{ 
    switch (nMsg) 
    { 
     ... 
     case WM_NCHITTEST: 
      Point p(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam); 
      ScreenToClient(p); 
      if (myButtonRect.Contains(p)) 
      { 
       return HTBORDER; 
      } 
      break; 
    } 
    return DefWindowProc(hWnd, nMsg, wParam, lParam); 
} 

Więc zasadniczo poinformować system Windows, że obszar zajmowany przez przycisk nie jest częścią tytuł okna, lecz nieswoista część obszaru non-klient (HTBORDER).

Przypis: Jeśli wywołałeś SetCapture() i jeszcze nie nazwałeś ReleaseCapture(), gdy oczekujesz pojawienia się komunikatu WM_NCLBUTTONDOWN, to nie pojawi się, nawet z powyższą zmianą. Może to być irytujące, ponieważ przechwytywanie myszy podczas interakcji z takimi niestandardowymi przyciskami jest normalne, aby można było anulować kliknięcie/podświetlenie, gdy mysz opuści okno. Jednakże, jako alternatywę dla przechwytywania, można rozważyć użycie SetTimer()/KillTimer() z krótkim interwałem (np. 100 ms), który nie spowoduje zniknięcia komunikatów WM_NCLBUTTONUP.

2

Dziki domysł - jakiś kod przechwytuje mysz, prawdopodobnie po to, aby ułatwić poruszanie się okna po zdobyciu tytułu. To by wyjaśniało również, dlaczego włamanie do debuggera spowodowałoby pojawienie się komunikatu - interakcja z debuggerem powoduje wyczyszczenie przechwytywania myszy.

Proponuję, abyś uruchomił Szpiega ++ w tym oknie, a to dzieci i spróbuj dowiedzieć się, kto otrzyma wiadomość o przycisku.

Jeśli chodzi o sposób naprawy - nie może ci w tym pomóc, nie patrząc na rzeczywisty kod. Musisz dowiedzieć się, kto jest winowajcą i spojrzeć na ich kod.

1

Aby dodać do Franci Penov's answer, kliknięcie na pasku tytułu jest interpretowane jako początek przeciągania w celu zmiany położenia okna. Okno przechwytuje mysz, dzięki czemu można wykonać przeciągnięcie. Ponieważ zmaksymalizowanego okna nie można przeciągnąć, przechwytywanie jest pomijane, a wiadomość jest przesyłana normalnie.

1

zawierają ReleaseCapture() w WM_NCLBUTTONDOWN {blok kodu}

Powiązane problemy