Perché il WM_MOVE dell'API Win32 viene chiamato mentre si trascina la finestra?

4

Ho due callback per WM_MOVE e WM_MOVING. Stranamente, WM_MOVE viene chiamato mentre si trascina la finestra. Mi aspettavo che WM_MOVE venisse chiamato solo quando ho finito di trascinare la finestra.

MSDN dice che WM_MOVE viene inviato dopo che una finestra viene spostata e WM_MOVING è quando la finestra si sta spostando. I documenti non mostrano alcun cambiamento per Windows 7 / VS2010, che è quello che sto usando.

WM_MOVE: link

Qualcuno l'ha mai visto prima? Durante il trascinamento, viene chiamato WM_MOVE, che non dovrebbe essere il più comprensibile.

    case WM_MOVE:
        {
            int x = LOWORD(lParam);
            int y = HIWORD(lParam);

            if (win.m_onMoveCallback)
                win.m_onMoveCallback(x, y);

            return 0;
        }
        break;

    case WM_MOVING:
        {
            int x = LOWORD(lParam);
            int y = HIWORD(lParam);

            if (win.m_onMovingCallback)
                win.m_onMovingCallback(x, y);

            return 0;
        }
        break;
    
posta Phil 19.12.2014 - 20:30
fonte

3 risposte

6

Indietro nel tempo di Windows 3.1, prima di Windows 95, hai trascinato la finestra, ma non si è mossa. Stavi solo spostando un contorno della finestra, sotto forma di una cornice semitrasparente. Solo quando hai terminato il trascinamento, la finestra si spostava (saltava alla posizione finale, all'epoca non c'erano acceleratori grafici, quindi il ridisegno di una finestra era un'operazione costosa, il ridimensionamento funzionava allo stesso modo).

In Windows 95, una delle grandi cose era, la finestra effettivamente spostata / ridimensionata mentre stavi trascinando il suo / ridimensionamento del bordo. Molto più bello.

Bene, questi due messaggi WM_XXX sono legati al trascinamento della cornice del movimento (ora invisibile, ma ancora presente come principio) rispetto allo spostamento della finestra stessa. Spero che ora sia più chiaro.

    
risposta data 19.12.2014 - 20:44
fonte
3

Quando definisci il completamento di una mossa come a livello microscopico, è logico che il WM_MOVE venga inviato seguendo un messaggio WM_MOVING. Windows determina uno spostamento basato su una modifica della posizione del mouse su un periodo di tempo molto piccolo (centinaia o migliaia di volte al secondo). Dal momento che non può sapere se hai finito di spostare, ottieni entrambi i messaggi.

Tornare indietro quando il periodo di tempo era più grande (circa 18 volte al secondo), era più facile capire se ti stessi ancora muovendo.

    
risposta data 19.12.2014 - 20:36
fonte
2

Ho trovato che WM_EXITSIZEMOVE è un'alternativa a WM_MOVE. Rileva quando ho finito di trascinare la finestra, ma non passa valori in WPARAM e LPARAM, quindi devi fare un po 'di rilevamento. Ecco un esempio approssimativo:

Per prima cosa, impostale come statico o globale:

static int x = 0, y = 0;
static bool move = false, resize = false;

In secondo luogo, esegui il rilevamento in WM_MOVING:

case WM_MOVING:
        {
            move = true; 
            RECT *r = (LPRECT)lParam;

            x = r->left;
            y = r->top;

            if (win.m_onMovingCallback)
                win.m_onMovingCallback(x, y);

            return 0;
        }
        break;

In terzo luogo, controlla lo stato delle mosse in WM_EXITSIZEMOVE:

    case WM_EXITSIZEMOVE:
        {
            if (move)
            {
                if (win.m_onMoveCallback)
                    win.m_onMoveCallback(x, y);

                move = false;
            }

            return 0;
        }
        break;
    
risposta data 19.12.2014 - 20:45
fonte

Leggi altre domande sui tag