Um in einem Programm eine Interaktion mit dem Benutzer realisieren zu können, dann ist wohl die Einbindung der Maus unumgänglich. Ihre Implementierung stützt sich ausschließlich auf das Nachrichtenkonzept. So werden folgende Standardnachrichten an das Programm gesandt:
Mausnachricht | verursachendes Ereignis |
---|---|
WM_MOUSEMOVE | - Maus wird bewegt |
WM_LBUTTONDOWN | - Linke Maustaste wird gedrückt |
WM_LBUTTONUP | - Linke Maustaste wird losgelassen |
WM_RBUTTONDOWN | - Rechte Maustaste wird gedrückt |
WM_RBUTTONUP | - Rechte Maustaste wird losgelassen |
WM_MBUTTONDOWN | - Mittlere Maustaste wird gedrückt |
WM_MBUTTONUP | - Mittlere Maustaste wird losgelassen |
Wie bereits erwähnt, werden gleichzeitig auch zwei 32-Bit-Parameter ('lParam' und 'wParam') mitgesandt, welche bei allen sieben Nachrichten die gleiche Bedeutung haben. Zum einen sollte bei der Behandlung der Nachrichten bekannt sein, wo sich die Maus gegenwärtig befindet. Außerdem wird übermittelt, welche zusätzlichen Tasten ("Strg", "Shift" und Maustasten) gedrückt worden sind. Um al diese Informationen auf zwei Parameter verteilen zu können, spaltet man einen der Parameter ('lParam') in zwei 16-Bit-Werte auf, die jeweils die X- und die Y-Koordinate enthält. Zu diesem Zweck bietet Windows die Makros 'LOWORD' und 'HIWORD' an. Die jeweiligen Koordinaten können dann wie folgt ermittelt werden:
signed int xPos = LOWORD(lParam); //X-Koordinate signed int yPos = HIWORD(lParam); //Y-Koordinate
Die Koordinaten sind relativ zum Fensterursprung (linke obere Ecke), d.h. wenn sie negativ sind, befinden sie sich außerhalb des Fensters. Wenn man dies nicht anders erwünscht, befinden sich die Koordinaten immer innerhalb des Fensters, welches die Nachricht behandelt.
Der Parameter 'wParam' besteht aus einer Kombination von Konstanten, die jeweils angeben ob eine weitere Taste gedrückt ist oder nicht. Dazu sind folgende Konstanten definiert:
Konstante | gedrückte Taste | Wert |
---|---|---|
MK_CONTROL | - "Strg"-Taste | 0x0008 |
MK_LBUTTON | - Linke Maustaste | 0x0001 |
MK_MBUTTON | - Mittlere Maustaste | 0x0010 |
MK_RBUTTON | - Rechte Maustaste | 0x0002 |
MK_SHIFT | - "Shift"-Taste | 0x0004 |
Bei jede der Konstanten ist ein Bit gesetzt, d.h. jedes Bit (bzw. die ersten fünf) beschreibt den Status einer Taste. Sind n Tasten gedrückt, so sind auch n von fünf Bits gesetzt. hat Ist Beispielsweise die linke und die rechte Maustaste gedrückt so wäre der Wert von 'wParam' wie folgt:
wParam = MK_LBUTTON | MK_RBUTTON;
Es ist jedoch unmöglich den Parameter auf jede mögliche Kombination von gesetzten Bits zu überprüfen. Außerdem ist es eventuell wünschenswert zu ermitteln, ob eine Taste überhaupt gedrückt ist, egal ob weitere Tasten gleichzeitig gedrückt werden oder nicht. Soll überprüft werden, ob die linke Maustaste gedrückt ist, dann wäre folgende Anweisung weniger sinnvoll:
if (wParam == MK_LBUTTON) { /* --- Behandlung --- ... */ }
Die Bedingung wäre nämlich überhaupt nur dann erfüllt, wenn nur die linke Maustaste gedrückt wird. Um zu überprüfen ob alleine das Bit gesetzt ist oder nicht, welches den Status ser gewünschten Taste angibt setzt man einfach alle anderen auf 0. Dies erreicht man mit folgender Anweisung:
WPARAM Param = wParam & MK_LBUTTON; //Alle Bits außer das der linken Taste werden auf 0 gesetzt
Nun ist es ein leichtes den Status abzufragen. Man brauch nur überprüfen ob der modifizierte Parameter der Konstanten der gewünschten Taste entspricht. Ist dies der Fall, dann ist die Taste gedrückt, im anderen Fall ist dieser Parameter dann 0, weil alle Bits auf 0 gesetzt sind und die Taste ist nicht gedrückt. Die logischste Realisierung wäre:
if ((wParam & MK_LBUTTON) == MK_LBUTTON) { /* --- Behandlung --- ... */ }
Es reicht allerdings aus zu überprüfen, ob der modifizierte Parameter ungleich 0 ist:
if (wParam & MK_LBUTTON) //entspricht if ((wParam & MK_LBUTTON) != 0) { /* --- Behandlung --- ... */ }
Soweit zu den Parametern. Nun sollen die Nachrichten in die Fensterprozedur eingebunden werden.
Greifen wir noch einmal auf den Rahmencode der Fensterprozedur zurück und erweitern diesen, um die bisher bekannten Nachrichten, wobei wir uns zunächst auf die Nachrichten, welche mit der linken Maustaste einher gehen, konzentrieren:
//Implementierung der Fensterprozedur LRESULT CALLBACK WndProc(HWND hWnd, UINT uiMessage, WPARAM wParam, LPARAM lParam) { //Variablen für WM_PAINT-Zweig PAINTSTRUCT ps; RECT rc; //Grafikobjekte HDC hDC; //Gerätekontext //Variablen für Mausnachrichten static bool bLButtonDown = false; static signed int X1, X2, Y1, Y2; switch (uiMessage) { case WM_PAINT: //Koordinaten des Anwendungsbereiches ermitteln GetClientRect(hWnd, &rc); //Zeichenvorgang beginnen HDC hDC = BeginPaint(hWnd, &ps); /* --- Zeichenoperationen --- ... */ //Zeichenvorgang beenden EndPaint(hWnd, &ps); return 0; case WM_CLOSE: DestroyWindow(hWnd); return 0; case WM_LBUTTONDOWN: //Koordinaten für den ersten Punkt ermitteln (zweiten Punkt initialisieren) X1 = X2 = LOWORD(lParam); Y1 = Y2 = HIWORD(lParam); //linke Maustaste gedrückt bLButtonDown = true; return 0; case WM_LBUTTONUP: //Koordinaten für den zweiten Punkt ermitteln X2 = LOWORD(lParam); Y2 = HIWORD(lParam); //linke Maustaste nicht mehr gedrückt bLButtonDown = false; return 0; case WM_DESTROY: PostQuitMessage(0); return 0; default: break; } return DefWindowProc(hWnd, uiMessage, wParam, lParam); }
Hier wird beim Drücken der linken Maustaste die Position des Mauszeigers in den Variablen 'X1' und 'Y1' festgehalten. Außerdem wird der Status der linken Maustaste in der Variablen 'bLButtonDown' gespeichert. Die Variablen müssen statisch sein, da sie nach der Behandlung der Nachricht 'WM_LBUTTONDOWN' noch in der Funktion erhalten bleiben sollen, um bei späteren Behandlungen z.B. bei der Behandlung der 'WM_LBUTTONUP'-Nachricht noch gültige Werte zu besitzen. Bei der Behandlung der letzteren Nachricht werden nämlich erneut die Koordinaten gespeichert. An dieser Stelle könnte man dann beispielsweise eine entsprechende Figur zeichnen.
Hier sollte die Behandlung der Mausnachrichten deutlich geworden sein. Das beinhaltet unter anderem die Bestimmung der Mausposition und des Status der Aktions- und Maustasten.
Die Behandlung der Mausnachrichten soll im nächsten Kapitel an einem Beispiel genauer erläutert werden. So sollen wie bereits angesprochen Figuren durch, das Drücken und Loslassen der linken Maustaste an der gewünschten Stelle auf dem Bildschirm erscheinen.