Verschiedene Mausvorgänge
In den vorherigen Abschnitten wurden Mausklicks und Mausbewegungen erläutert. Hier sind einige andere Vorgänge aufgeführt, die mit der Maus ausgeführt werden können.
Ziehen von UI-Elementen
Wenn Ihre Benutzeroberfläche das Ziehen von UI-Elementen unterstützt, gibt es eine andere Funktion, die Sie in Ihrem Maus-nach-unten-Nachrichtenhandler aufrufen sollten: DragDetect. Die DragDetect-Funktion gibt TRUE zurück, wenn der Benutzer eine Mausbewegung initiiert, die als Ziehen interpretiert werden soll. Der folgende Code zeigt, wie Sie diese Funktion verwenden.
case WM_LBUTTONDOWN:
{
POINT pt = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) };
if (DragDetect(m_hwnd, pt))
{
// Start dragging.
}
}
return 0;
Hier ist die Idee: Wenn ein Programm Drag and Drop unterstützt, soll nicht jeder Mausklick als Ziehen interpretiert werden. Andernfalls könnte der Benutzer versehentlich etwas ziehen, wenn er einfach darauf klicken wollte (z. B. zum Auswählen). Wenn eine Maus jedoch besonders empfindlich ist, kann es schwierig sein, die Maus beim Klicken perfekt still zu halten. Daher definiert Windows einen Schwellenwert für den Ziehvorgang von wenigen Pixeln. Wenn der Benutzer die Maustaste drückt, wird dies nicht als Ziehen betrachtet, es sei denn, die Maus überschreitet diesen Schwellenwert. Die DragDetect-Funktion testet , ob dieser Schwellenwert erreicht ist. Wenn die Funktion TRUE zurückgibt, können Sie den Mausklick als Ziehen interpretieren. Andernfalls nicht.
Hinweis
Wenn DragDetectFALSE zurückgibt, unterdrückt Windows die WM_LBUTTONUP Meldung, wenn der Benutzer die Maustaste loslässt. Rufen Sie daher DragDetect nicht auf, es sei denn, Ihr Programm befindet sich derzeit in einem Modus, der das Ziehen unterstützt. (Beispielsweise, wenn bereits ein ziehbares UI-Element ausgewählt ist.) Am Ende dieses Moduls wird ein längeres Codebeispiel angezeigt, das die DragDetect-Funktion verwendet.
Einschränken des Cursors
Manchmal können Sie den Cursor auf den Clientbereich oder einen Teil des Clientbereichs beschränken. Die ClipCursor-Funktion schränkt die Bewegung des Cursors auf ein angegebenes Rechteck ein. Dieses Rechteck wird in Bildschirmkoordinaten anstelle von Clientkoordinaten angegeben, sodass der Punkt (0, 0) die obere linke Ecke des Bildschirms bedeutet. Um Clientkoordinaten in Bildschirmkoordinaten zu übersetzen, rufen Sie die Funktion ClientToScreen auf.
Der folgende Code beschränkt den Cursor auf den Clientbereich des Fensters.
// Get the window client area.
RECT rc;
GetClientRect(m_hwnd, &rc);
// Convert the client area to screen coordinates.
POINT pt = { rc.left, rc.top };
POINT pt2 = { rc.right, rc.bottom };
ClientToScreen(m_hwnd, &pt);
ClientToScreen(m_hwnd, &pt2);
SetRect(&rc, pt.x, pt.y, pt2.x, pt2.y);
// Confine the cursor.
ClipCursor(&rc);
ClipCursor verwendet eine RECT-Struktur , clientToScreen jedoch eine POINT-Struktur . Ein Rechteck wird durch seinen oberen linken und unteren rechten Punkt definiert. Sie können den Cursor auf einen beliebigen rechteckigen Bereich beschränken, einschließlich Bereiche außerhalb des Fensters, aber das Einschränken des Cursors auf den Clientbereich ist eine typische Möglichkeit, die Funktion zu verwenden. Das Einschränken des Cursors auf eine Region, die sich vollständig außerhalb Ihres Fensters befindet, wäre ungewöhnlich, und Benutzer würden dies wahrscheinlich als Fehler wahrnehmen.
Um die Einschränkung zu entfernen, rufen Sie ClipCursor mit dem Wert NULL auf.
ClipCursor(NULL);
Mausverfolgungsereignisse: Zeigen und Verlassen
Zwei weitere Mausnachrichten sind standardmäßig deaktiviert, können aber für einige Anwendungen nützlich sein:
- WM_MOUSEHOVER: Der Cursor hat einen festen Zeitraum lang über den Clientbereich gezeigt.
- WM_MOUSELEAVE: Der Cursor hat den Clientbereich verlassen.
Um diese Nachrichten zu aktivieren, rufen Sie die Funktion TrackMouseEvent auf.
TRACKMOUSEEVENT tme;
tme.cbSize = sizeof(tme);
tme.hwndTrack = hwnd;
tme.dwFlags = TME_HOVER | TME_LEAVE;
tme.dwHoverTime = HOVER_DEFAULT;
TrackMouseEvent(&tme);
Die TRACKMOUSEEVENT-Struktur enthält die Parameter für die Funktion. Das dwFlags-Element der Struktur enthält Bitflags, die angeben, welche Nachverfolgungsnachrichten Sie interessieren. Sie können wählen, wie hier gezeigt , sowohl WM_MOUSEHOVER als auch WM_MOUSELEAVE oder nur eine der beiden zu erhalten. Das dwHoverTime-Element gibt an, wie lange die Maus zeigen muss, bevor das System eine Hovermeldung generiert. Dieser Wert wird in Millisekunden angegeben. Die Konstante HOVER_DEFAULT bedeutet, dass der Systemstandard verwendet wird.
Nachdem Sie eine der angeforderten Nachrichten erhalten haben, wird die TrackMouseEvent-Funktion zurückgesetzt. Sie müssen sie erneut aufrufen, um eine weitere Nachverfolgungsnachricht zu erhalten. Sie sollten jedoch bis zur nächsten Mausbewegungsnachricht warten, bevor Sie TrackMouseEvent erneut aufrufen. Andernfalls wird Ihr Fenster möglicherweise mit Nachverfolgungsmeldungen überflutet. Wenn die Maus z. B. mit der Maus zeigt, generiert das System weiterhin einen Datenstrom mit WM_MOUSEHOVER Nachrichten, während sich die Maus im Stand befindet. Sie möchten eigentlich keine weitere WM_MOUSEHOVER Nachricht, bis sich die Maus an eine andere Stelle bewegt und wieder schwebt.
Hier sehen Sie eine kleine Hilfsklasse, die Sie verwenden können, um Mausverfolgungsereignisse zu verwalten.
class MouseTrackEvents
{
bool m_bMouseTracking;
public:
MouseTrackEvents() : m_bMouseTracking(false)
{
}
void OnMouseMove(HWND hwnd)
{
if (!m_bMouseTracking)
{
// Enable mouse tracking.
TRACKMOUSEEVENT tme;
tme.cbSize = sizeof(tme);
tme.hwndTrack = hwnd;
tme.dwFlags = TME_HOVER | TME_LEAVE;
tme.dwHoverTime = HOVER_DEFAULT;
TrackMouseEvent(&tme);
m_bMouseTracking = true;
}
}
void Reset(HWND hwnd)
{
m_bMouseTracking = false;
}
};
Das nächste Beispiel zeigt, wie Sie diese Klasse in Ihrer Fensterprozedur verwenden.
LRESULT MainWindow::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_MOUSEMOVE:
mouseTrack.OnMouseMove(m_hwnd); // Start tracking.
// TODO: Handle the mouse-move message.
return 0;
case WM_MOUSELEAVE:
// TODO: Handle the mouse-leave message.
mouseTrack.Reset(m_hwnd);
return 0;
case WM_MOUSEHOVER:
// TODO: Handle the mouse-hover message.
mouseTrack.Reset(m_hwnd);
return 0;
}
return DefWindowProc(m_hwnd, uMsg, wParam, lParam);
}
Mausnachverfolgungsereignisse erfordern eine zusätzliche Verarbeitung durch das System. Lassen Sie sie daher deaktiviert, wenn Sie sie nicht benötigen.
Aus Gründen der Vollständigkeit ist hier eine Funktion, die das System nach dem standardmäßigen Hover-Timeout abfragt.
UINT GetMouseHoverTime()
{
UINT msec;
if (SystemParametersInfo(SPI_GETMOUSEHOVERTIME, 0, &msec, 0))
{
return msec;
}
else
{
return 0;
}
}
Mausrad
Die folgende Funktion überprüft, ob ein Mausrad vorhanden ist.
BOOL IsMouseWheelPresent()
{
return (GetSystemMetrics(SM_MOUSEWHEELPRESENT) != 0);
}
Wenn der Benutzer das Mausrad dreht, erhält das Fenster mit Fokus eine WM_MOUSEWHEEL Meldung. Der wParam-Parameter dieser Nachricht enthält einen ganzzahligen Wert namens Delta , der angibt, wie weit das Rad gedreht wurde. Das Delta verwendet beliebige Einheiten, wobei 120 Einheiten als die Drehung definiert werden, die zum Ausführen einer "Aktion" erforderlich ist. Natürlich hängt die Definition einer Aktion von Ihrem Programm ab. Wenn beispielsweise das Mausrad zum Scrollen von Text verwendet wird, würde jede Drehung von 120 Einheiten eine Textzeile scrollen.
Das Deltazeichen gibt die Drehrichtung an:
- positiv: Rotieren Sie nach vorne, weg vom Benutzer.
- Negativ: Drehen Sie sich rückwärts zum Benutzer.
Der Wert des Deltas wird zusammen mit einigen zusätzlichen Flags in wParam platziert. Verwenden Sie das makro GET_WHEEL_DELTA_WPARAM , um den Wert des Deltas abzurufen.
int delta = GET_WHEEL_DELTA_WPARAM(wParam);
Wenn das Mausrad eine hohe Auflösung aufweist, kann der absolute Wert des Deltas kleiner als 120 sein. Wenn es in diesem Fall sinnvoll ist, dass die Aktion in kleineren Schritten ausgeführt wird, können Sie dies tun. Beispielsweise könnte Text in Schritten von weniger als einer Zeile scrollen. Andernfalls akkumulieren Sie das Gesamtdelta, bis sich das Rad ausreichend dreht, um die Aktion auszuführen. Speichern Sie das nicht verwendete Delta in einer Variablen, und führen Sie die Aktion aus, wenn sich 120 Einheiten (entweder positiv oder negativ) akkumulieren.
Nächste