Mauskoordinaten anzeigen
-
Hallo,
ich bin seit einigen Tagen dabei C zu lernen und damit ich auch praktische Übungen machen kann hab ich mich entschlossen mit der WinAPI zu programmieren.Ich habe ein Programm geschrieben, dass ein Fenster ausgibt, welches die aktuellen Mauskoordinaten anzeigt. Das Fenster erneuert sich 10mal pro Sekunde.
Hier ist der komplette Code:
/*------------------------------------------ mcoordsgui3.c --------------------------------------------*/ #include <windows.h> #define ID_TIMER 1 LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM); int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) { static TCHAR szAppName[] = TEXT ("MCoordsGUI"); HWND hwnd; MSG msg; WNDCLASS wndclass; wndclass.style = CS_HREDRAW | CS_VREDRAW; wndclass.lpfnWndProc = WndProc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.hInstance = hInstance; wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION); wndclass.hCursor = LoadCursor (NULL, IDC_ARROW); wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH); wndclass.lpszMenuName = NULL; wndclass.lpszClassName = szAppName; if (!RegisterClass (&wndclass)) { MessageBox (NULL,TEXT ("Programm konnte Windowklasse nicht reggen"), szAppName, MB_ICONERROR); return 0; } hwnd = CreateWindow (szAppName, TEXT ("MCoordsGUI"), WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_BORDER, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL); ShowWindow (hwnd, iCmdShow); while (GetMessage (&msg, NULL, 0, 0)) { TranslateMessage (&msg); DispatchMessage (&msg); } return msg.wParam; } LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { static HDC hdcScreen; HDC hdc; PAINTSTRUCT ps; POINT pt; RECT rc; HBRUSH hBrush; TCHAR szBuffer [16]; static int nx = 0; static int ny = 0; switch (message) { case WM_CREATE: hdcScreen = CreateDC (TEXT ("DISPLAY"), NULL, NULL, NULL); SetTimer (hwnd, ID_TIMER, 100, NULL); return 0; case WM_TIMER: GetCursorPos (&pt); InvalidateRect(hwnd, NULL, FALSE); return 0; case WM_PAINT: hdc = BeginPaint (hwnd, &ps); GetClientRect (hwnd, &rc); hBrush = CreateSolidBrush(RGB(255,255,255)); FillRect(hdc, &rc, hBrush); nx = pt.x; ny = pt.y; sprintf (szBuffer, TEXT("X:%i Y:%i"), nx,ny); DrawText (hdc, szBuffer, -1, &rc, DT_SINGLELINE | DT_CENTER | DT_VCENTER); EndPaint (hwnd, &ps); DeleteObject (hBrush); return 0; case WM_DESTROY: DeleteDC (hdcScreen); KillTimer (hwnd, ID_TIMER); PostQuitMessage (0); return 0; } return DefWindowProc (hwnd, message, wParam, lParam); }
Das Programm lässt sich mit MinGW ohne Probleme kompilieren.
Sobald ich das Programm starte zeigt er erstmal in der Mitte des Fenster folgendes an:"X: 1992271069 Y:5767606"
Wo diese Werte herkommen weiss ich schonmal nicht ^^. Wenn man dann mit der Maus rumwandert gibt das Programm noch andere komische Werte aus. Die wirklichen Koordinaten zeigt er erst an, während man das Fenster verschiebt.
Ich bin da mit meinem Latein am Ende. Meiner Meinung nach müsste das Programm 10mal in der Sekunde die aktuelle Cursor-Position über
GetCursorPos (&pt);
abfragen, das aktuelle Fenster als ungültig deklarieren und deshalb über eine WM_PAINT Message das Fenster neuzeichnen.
Tatsächlich funktionieren tut das Programm aber nur wenn man das Fenster die ganze Zeit verschiebt.
Soweit ich weiss legt das Betriebsystem bei Verschiebung oder Verändern des Fenster dauernd WM_PAINT Messages in die Warteschleife.. zumindest dann scheint mein Programm ja zu funktionieren.. aber eben nicht von alleine über die WM_TIMER Message.Ich hoffe jemand weiss Rat.
-
Der Werte bekommst du vermutlich weil du pt nicht richtig initialisierst. Ausserdem muss pt irgendwo gehalten werden wo die gelesenen Werte nicht ständig wieder kaputt gemacht werden (auto storage), z.B. könntest du die Variable statisch machen:
static POINT pt = {0}; // initialisieren & static
Die eingelesenen Koordinaten solltest du ausserdem noch in Client-Koordinaten konvertieren, um die korrekte Position im Fenster zu bekommen:
case WM_TIMER: GetCursorPos (&pt); ScreenToClient(hwnd, &pt); // screen coords to client coords InvalidateRect(hwnd, NULL, FALSE); return 0;
-
Der erste Fehler ist schon mal folgender: in den Zeilen 84,85 wird pt verwendet, ist aber noch gar nicht mit Werten initialisiert. Da steht dann also irgendein Müll drin. Als Folge schreibst du eventuell in der folgenden Zeile über den gültigen Bereich von szBuffer hinaus, weil die Werte einfach so groß sind.
EDIT:
Probier es mal so: mach pt static (damit überdauern die darin enthaltenen Werte das Ende von WndProc). Außerdem kannst du szBuffer ruhig großzügiger dimensionieren. Speicher hast du ja sicher mehr als genug im Rechner, um die paar Bytes zu halten.EDIT: Ach, hatte David_pb's Posting gar nicht bemerkt...
-
Cool, vielen Dank für die Hilfe. Jetzt funktioniert das Programm so, wie es soll.
Die seltsame Verhaltensweise lag, wie von euch gesagt, der falschen Deklaration der POINT Struktur zugrunde.