[c++/DX 9/winapi] Berechnung Mauskoordinaten

kickerxy123

Erfahrenes Mitglied
Guten Tag zusammen!

folgendes Problem besteht derzeit: Ich möchte die Mauskoordinaten abfragen und damit prüfen, ob die Maus auf einem (von mir definierten DirectX-) Element liegt (Boundary Check). Soweit kein Thema, wie folgt sieht es aus:

C++:
DWORD r = GetMessagePos(); 
if(pos.x < ... && pos.y < ... etc) {...}

Das funktioniert, solange mein Spiel im Vollbildmodus ist, einwandfrei. Im Windowmode tauchen Probleme (logischerweise) auf, da die Mauskoordinaten nicht relativ zur Fensterecke sind, sondern global. Als Lösung habe ich folgendes versucht:

C++:
	DWORD r = GetMessagePos(); 
	pos = MAKEPOINTS(r);
	if(!ScreenToClient(g_hwnd, (POINT*)&pos)){...}

leider macht die ScreenToClient Funktion gar nichts?

Alternativ hatte ich auch schon folgendes versucht:

C++:
short getWindowLeftFrameWidth(void)
{
	return (SET.STG_FULLSCREEN) ? 0 : GetSystemMetrics(SM_CXBORDER);
}
short getWindowTopFrameHeight(void)
{
	return (SET.STG_FULLSCREEN) ? 0 : //GetSystemMetrics(SM_CYCAPTION) + 
	GetSystemMetrics(SM_CYBORDER) + GetSystemMetrics(SM_CYMENU);
}

Als Näherung nicht schlecht, aber passt auch nicht ganz (die Y-Komponente)... habe ich doch einen anderen Rahmen? Das Fenster wird so "erzeugt":
C++:
	 if(SET.STG_FULLSCREEN)
	{
	    SET.SCREEN_WIDTH = GetSystemMetrics(SM_CXSCREEN);
	    SET.SCREEN_HEIGHT = GetSystemMetrics(SM_CYSCREEN);
	    SetWindowLongPtr(g_hwnd,GWL_STYLE,WS_VISIBLE |WS_POPUP| WS_EX_TOPMOST);
	}
	else
	{
	    SET.SCREEN_WIDTH = GetSystemMetrics(SM_CXSCREEN)/3*2;
	    SET.SCREEN_HEIGHT = GetSystemMetrics(SM_CYSCREEN)/3*2;
	    SetWindowLongPtr(g_hwnd,GWL_STYLE,WS_VISIBLE |WS_OVERLAPPEDWINDOW);
	}

Habt ihr Vorschläge? (Außer DirectInput verwenden, was nicht mal mehr Microsoft empfiehlt).


Danke wie immer und viele Grüße
kickerxy
 
Zuletzt bearbeitet:
Schreib dir einen "WindowHandler" und speicher einfach die X- und Y-Offsets.
C++:
        case WM_CREATE:
        case WM_SIZE:
        {
             pass
        }

        case WM_WINDOWPOSCHANGING:
        case WM_WINDOWPOSCHANGED:
        {
            pass
        }
 
GetMessagePos liefert dir die Position der letzten Nachricht (warum verwendest du überhaupt so etwas?) gemäss MSDN. Praktisch alle Mausnachrichten (mousemove, lbuttondown, lbuttonup, ...) liefern Koordinaten relativ zum Fenster.
 
ScreenToClient wäre genau das richtige, falls du dir wirklich die Arbeit mit den Screen-Koordinaten machen willst. Das tut normalerweise auch problemlos, ist g_hWnd auch dein Fenster?
 
Danke für die Antworten.
Zunächst einmal habe ich einen Fehler selbst gefunden:
C++:
DWORD r = GetMessagePos(); 
    pos = MAKEPOINTS(r);
    if(!ScreenToClient(g_hwnd, (POINT*)&pos)){...}
ist falsch. Die Konvertierung POINTS->POINT kann ja auch gar nicht gelingen (wegen short/long) ... Daher habe ich meinen Code geändert:
C++:
DWORD r = GetMessagePos(); 
    pos = MAKEPOINTS(r);
POINT posP;
posP.x = pos.x;
posP.y = pos.y;
    if(!ScreenToClient(g_hwnd, &posP)){...}
Danach erhalte ich endlich sinnvolle Werte. Das heißt, dass egal wie ich das Fenster verschiebe, oben links in der Ecke des gemalten Bereichs auch wirklich 0|0 als Koordinaten erhalte. Wirklich komisch wird es jedoch, wenn ich andere Bereiche im Fenster nachstelle. So hat der Punkt unten rechts im Fenster eine Abweichung im Ergebnis von 16Px in der X und 52Px in der Y-Koordinate. Ebenfalls seltsam: Wenn ich auf die obere Bildschirmkante gehe und den betragsmäßig mit der unteren Bildschirmkante verrechne, dann kommt durch ScreenToClient ein Wert von 648Px heraus, die Auflösung beträgt jedoch in der Höhe 768px, einer Abweichung von 120px.
Das heißt zudem auch, dass die Abweichung, die ich beobachte proportional zur Entfernung zunimmt.

Hat irgendjemand eine Idee, woran das liegen könnte?
Ich werde auch testweise die Windows Messages mal ausprobieren. Idealer fände ich aber die Verwendung von ScreenToClient, da mein Spiel (später) mehrere Monitore supporten soll und auch auf mehreren Unterschiedliches anzeigen soll. Da fände ich eine solche Berechnung besser (also an einer zentralen Stelle die Maus für alle Windows verwalten). Zumal derzeit die Maussteuerung in einem anderen Kontext steht als die Windows Messages.

Danke soweit,
kickerxy
 
Zurück