Vorgehen
In der Fensterfunktion werden drei Ereignisse der Maus gefangen: das Drücken der Maustaste, das Schieben der Maus und das Loslassen der Taste. Das Schieben interessiert allerdings nur dann, wenn die Taste gedrückt ist!Einige Informationen merkt sich die Fensterfunktion. Zunächst steht in einer boolschen Variablen, ob die Maustaste unten ist. Diese Information steht in der Variablen dragging. Der Anfang des Aufspannens wird als Ecke des Rechtecks benötigt. Sie steht in StartPos. Schließlich wird die letzte Mausposition als die andere Ecke gebraucht (MousePos). Alle diese Variablen sind als static angelegt.
SetCapture und ReleaseCapture
Die Mausaktionen empfängt ein Programm nur über dem eigenen Fenster. Beim Aufspannen ist es aber notwendig, daß auch die Mausbewegung außerhalb notiert wird, solange die Maustaste gedrückt wird. Dies erreicht SetCapture. Um die Wirkung wieder aufzuheben, wird ReleaseCapture aufgerufen. Sinnigerweise geschieht das bei Loslassen der Maustaste.Maustaste unten
Hier beginnt das Aufspannen. Es wird dragging gesetzt und SetCapture aufgerufen. Die Mausposition wird unter StartPos und MousePos abgelegt.Mausbewegung
Bei einer Bewegung wird, sofern die Maustaste gedrückt ist, das alte Rechteck gelöscht und das neue gezeichnet. Beim allerersten Mal ist StartPos und MousePos gleich. Ein Rechteck wird so nicht gezeichnet und bedarf keiner Sonderbehandlung.Loslassen der Maustaste
Hier beginnen die Aufräumarbeiten. Das Gummiband wird entfernt und mit ReleaseCapture wird die Maus für andere Fenster freigegeben. Auch das Flag, das feststellt, ob die Maustaste gedrückt ist, muß freigegeben werden.HDC hDC; static POINTS MousePos, StartPos; static bool dragging = false; . . . case WM_LBUTTONDOWN: dragging = true; SetCapture(hWnd); StartPos = MAKEPOINTS(lParam); MousePos = StartPos; break; case WM_MOUSEMOVE: if (dragging) { hDC = GetDC(hWnd); drawCapture(hDC, StartPos, MousePos); MousePos = MAKEPOINTS(lParam); drawCapture(hDC, StartPos, MousePos); ReleaseDC(hWnd, hDC); } break; case WM_LBUTTONUP: MousePos = MAKEPOINTS(lParam); ReleaseCapture(); hDC = GetDC(hWnd); drawCapture(hDC, StartPos, MousePos); ReleaseDC(hWnd, hDC); dragging = false; break; |
Zeichnen des invertierenden Rechtecks
Die Funktion drawCapture zeichnet das inverse Rechteck. Es basiert auf ein paar LineTo-Befehlen und dem SetROP2(hDC, R2_NOT), der bewirkt, daß der Hintergrund invertiert wird. So wird erreicht, daß ein zweifaches Zeichnen des gleichen Rechtecks ein Auslöschen bewirkt.void drawCapture(HDC hDC, POINTS pa, POINTS pe) { SetROP2(hDC, R2_NOT); MoveToEx(hDC, pa.x, pa.y, 0); LineTo(hDC, pa.x, pe.y); LineTo(hDC, pe.x, pe.y); LineTo(hDC, pe.x, pa.y); LineTo(hDC, pa.x, pa.y); } |