2009-02-06 4 views
5

Ho una finestra che gestisco i messaggi WM_NCLBUTTONUP, al fine di gestire i clic sui pulsanti personalizzati nella barra dei sottotitoli. Funziona alla grande quando la finestra è ingrandita, ma quando non lo è, il messaggio WM_NCLBUTTONUP non arriva mai! Ricevo però un messaggio WM_NCLBUTTONDOWN. Stranamente WM_NCLBUTTONUP arriva se faccio clic sulla destra della barra dei menu, ma ovunque lungo la barra della didascalia/frame della finestra, il messaggio non arriva mai.Il problema curioso del messaggio WM_NCLBUTTONUP mancante quando una finestra non è ingrandita

Dopo un po 'di debugging ho scoperto che se ho impostato un punto di interruzione CMainFrame :: OnNcLButtonDown(), cliccato barra del titolo, ma mantenere il pulsante del mouse premuto, lasciare che la pausa debugger nella funzione, premere F5 per continuare debugging, quindi rilascia il pulsante del mouse: magicamente viene inviato WM_NCLBUTTONUP !!

La mia domanda è duplice, (1) che diavolo sta succedendo? (2) come faccio a aggirare questo "problema".

Ho anche notato che ci sono molte altre persone su Internet che hanno lo stesso problema (un rapido Google rivela molte altre persone con lo stesso problema, ma nessuna soluzione).

Modifica
Grazie per le prime due risposte, ho provato a chiamare ReleaseCapture in NCLButtonDown, ma non ha alcun effetto (infatti, esso restituisce NULL, che indica una cattura non è a posto). Posso solo supporre che la funzionalità della classe base (def window proc) possa impostare una cattura. Investigherò il lunedì ...

risposta

4

Ho avuto lo stesso problema. Il problema è infatti che un clic del tasto sinistro sulla didascalia della finestra inizia un trascinamento, e quindi l'acquisizione del mouse, che impedisce a WM_NCLBUTTONUP di arrivare.

La soluzione è quella di ignorare 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); 
} 

Quindi, in sostanza si informa di Windows che l'area occupata dal pulsante non è parte del titolo della finestra, ma una parte non specifica della zona non-client (HTBORDER).

Nota: se si è chiamato SetCapture() e non si è ancora chiamato ReleaseCapture() quando si prevede che il messaggio WM_NCLBUTTONDOWN venga inserito, non verrà visualizzato nemmeno con la modifica sopra riportata. Ciò può essere irritante poiché è normale acquisire il mouse durante l'interazione con tali pulsanti personalizzati in modo da poter annullare il clic/evidenziare se il mouse lascia la finestra. Tuttavia, in alternativa all'utilizzo di cattura, è possibile considerare SetTimer()/KillTimer() con un intervallo breve (ad esempio 100 ms), che non causerà la scomparsa dei messaggi WM_NCLBUTTONUP.

2

Un'ipotesi selvaggia: un po 'di codice sta catturando il mouse, probabilmente per facilitare il movimento della finestra quando prendi il titolo. Ciò spiegherebbe anche perché l'interruzione del debugger potrebbe far apparire il messaggio - l'interazione del debugger sta cancellando l'acquisizione del mouse.

Suggerirei di eseguire Spy ++ su quella finestra ed è bambini e cercare di capire chi riceve il messaggio di attivazione.

Per quanto riguarda il modo di risolverlo - non può aiutarti senza guardare il codice attuale. Dovrai scoprire chi è il colpevole e guardare il loro codice.

1

Per aggiungere a Franci Penov's answer, un clic sulla barra del titolo viene interpretato come l'inizio di un trascinamento per riposizionare la finestra. La finestra sta catturando il mouse in modo che possa eseguire il trascinamento. Poiché una finestra ingrandita non può essere trascinata, l'acquisizione viene saltata e il messaggio viene indirizzato normalmente.

1

include ReleaseCapture() in WM_NCLBUTTONDOWN {blocco codice}

Problemi correlati