Windows Programmierung: Markierungsrechteck aufspannen
Willemers Informatik-Ecke
Soll ein Bereich mit der Maustaste markiert werden, empfielt sich eine grafische Rückmeldung für den Benutzer. Dazu spannt beispielsweise der Desktop ein Rechteck auf.

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);
}