Linien und Schriften verlieren nach kurzer Zeit Formatierung
-
Hallo zusammen,
ich bin relativer Windows-Programmierungs-Anfänger und nutze Visual C++ Express 2010 und Windows 7.
Mein Programm erstellt ein Fenster, und in diesem Fenster nochmals ein Fenster, das 100 mal pro Sekunde durch einen Timer per WM_PAINT neu gezeichnet wird.
In dem inneren Fenster wird eine rote Linie gezeichnet, aber nach 2 Minuten und 34 Sekunden (bzw. wenn das Fenster nur 50 mal pro Sekunde gezeichnet wird nach 5 Minuten und 8 Sekunden, also genau der doppelten Zeit), "vergisst" Windows die Linienfarbe sowie Schriftarten (aus Arial wird in dem Fenster dann die Standardschrift) und es werden auch keine Messageboxes mehr ausgegeben.
Ich habe den Code mal stark gekürzt, ist aber funktionsfähig und der Fehler tritt auf.
Lösche ich die evtl. die Objekte nicht richtig?
Hier der Code, in dem ich den Fehler vermute (ganz unten der komplette Code):
case WM_PAINT: hdc_map = BeginPaint(hwnd, &ps_map); // begin painting hPaintColorGrey = SelectObject(hdc_map, CreatePen(PS_SOLID, 0, RGB(255, 50, 50))); // creating a handle for a red color MoveToEx(hdc_map, 0, 96, NULL); // move cursor to position, end line of a block LineTo(hdc_map, 488, 96); // draw line DeleteObject(hPaintColorGrey); // delete brush and color handles DeleteObject(CreatePen(PS_SOLID, 0, RGB(255, 50, 50))); // delete brush and color handles DeleteObject(SelectObject(hdc_map, CreatePen(PS_SOLID, 0, RGB(255, 50, 50)))); // delete brush and color handles EndPaint(hwnd, &ps_map); // end painting return(0);Hier noch der komplette Code:
#include <windows.h> // Definition of the functions for window-handling LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); // declaration of the main window proc function LRESULT CALLBACK ChildWndProc(HWND, UINT, WPARAM, LPARAM); // declaration of the map window proc function static HWND hwndChild_map; // handle for the map window // Hauptfenster int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) { static TCHAR szAppName[] = TEXT("CDROID"); // Name des Hauptfenster HWND hwnd; MSG msg; WNDCLASS wndclass; // Definition der Fensterklasse für das Hauptfenster wndclass.style = CS_HREDRAW | CS_VREDRAW; // Bei Größenänderung neuzeichnen wndclass.lpfnWndProc = WndProc; // Bezeichner der Fensterklasse, über den festgelegt wird, welche Callback-Funktion welche Klasse benutzt, unabhängig davon, wann die Klasse mit RegisterClass registriert wurde wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; // wieviele Byte für das Fenster zusätzlich reserviert werden sollen wndclass.hInstance = hInstance; wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION); // Es wird kein Fenstericon geladen wndclass.hCursor = LoadCursor(NULL, IDC_ARROW); // Der Standardcursor wird verwendet wndclass.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH); // Das Fenster wird mit einer weißen Hintergrundfarbe gefüllt wndclass.lpszMenuName = NULL; // Es wird kein Menü verwendet wndclass.lpszClassName = szAppName; // Der Name der Fensterklasse RegisterClass(&wndclass); // definition of window class for map window wndclass.lpfnWndProc = ChildWndProc; wndclass.cbWndExtra = sizeof(long); // wieviele Byte für das Fenster zusätzlich reserviert werden sollen (in diesem Fall 4) wndclass.hIcon = NULL; wndclass.lpszClassName = TEXT("Map"); // class name RegisterClass(&wndclass); hwnd = CreateWindow(szAppName, TEXT("CDROID"), // Name des Fensters in der Titelleiste WS_DLGFRAME | WS_MINIMIZEBOX, // ohne Schaltflächen, minimierbar, feste Größe 10, // Startposition des Fensters von links 10, // Startposition des Fensters von rechts 1400, // Breite 1000, // Höhe NULL, // Übergeordnetes Fenster NULL, // Instanzname für Rückmeldungen an das übergeordnete Fenster hInstance, NULL); // Fenster anzeigen ShowWindow(hwnd, iCmdShow); // Inhalt anzeigen UpdateWindow(hwnd); // Nachrichtenverarbeitung while(GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return(0); } HDC hdc_hwnd; // Handle auf den Anzeigebereich (Gerätekontext) PAINTSTRUCT ps_hwnd; // Befehlsverarbeitung für das Hauptfenster LRESULT CALLBACK WndProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { switch(message) { case WM_CREATE: // creation of the main window hwndChild_map = CreateWindow( TEXT("Map"), NULL, WS_CHILDWINDOW | WS_BORDER, 10, 10, 490, 490, hwnd, (HMENU) (13), (HINSTANCE) GetWindowLong(hwnd, GWL_HINSTANCE), NULL); ShowWindow(hwndChild_map, SW_SHOW); // show map window SetTimer(hwnd, 1, 10, NULL); // set timmer; 100 times per second for calculating the movement case WM_TIMER: switch(wParam) { case 1: InvalidateRect(hwndChild_map, NULL, TRUE); // invalidate the map window area break; } return(0); case WM_DESTROY: KillTimer(hwnd, 1); // kill timer PostQuitMessage(0); // Schließen des Hauptfensters return(0); } return(DefWindowProc(hwnd, message, wParam, lParam)); } HDC hdc_map; PAINTSTRUCT ps_map; HGDIOBJ hPaintColorGrey; LRESULT CALLBACK ChildWndProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { switch(message) { case WM_CREATE: return(0); case WM_PAINT: hdc_map = BeginPaint(hwnd, &ps_map); // begin painting hPaintColorGrey = SelectObject(hdc_map, CreatePen(PS_SOLID, 0, RGB(255, 50, 50))); // creating a handle for a red color MoveToEx(hdc_map, 0, 96, NULL); // move cursor to position, end line of a block LineTo(hdc_map, 488, 96); // draw line DeleteObject(hPaintColorGrey); // delete brush and color handles DeleteObject(CreatePen(PS_SOLID, 0, RGB(255, 50, 50))); // delete brush and color handles DeleteObject(SelectObject(hdc_map, CreatePen(PS_SOLID, 0, RGB(255, 50, 50)))); // delete brush and color handles EndPaint(hwnd, &ps_map); // end painting return(0); } return(DefWindowProc(hwnd, message, wParam, lParam)); }
-
hdc_map = BeginPaint(hwnd, &ps_map); // begin painting hPaintColorGrey = SelectObject(hdc_map, CreatePen(PS_SOLID, 0, RGB(255, 50, 50))); // SelectObject liefert den alten Pen MoveToEx(hdc_map, 0, 96, NULL); // move cursor to position, end line of a block LineTo(hdc_map, 488, 96); // draw line DeleteObject(hPaintColorGrey); // löscht den alten Pen DeleteObject(CreatePen(PS_SOLID, 0, RGB(255, 50, 50))); // ??? wozu DeleteObject(SelectObject(hdc_map, CreatePen(PS_SOLID, 0, RGB(255, 50, 50)))); // ??? wozu EndPaint(hwnd, &ps_map); // end paintingDu wollstest wahrscheinlich Folgendes machen
hdc_map = BeginPaint(hWnd, &ps_map); // begin painting HPEN hPaintColorGrey = CreatePen(PS_SOLID, 0, RGB(255, 50, 50)); // creating a handle for a red color HGDIOBJ hpenOld = SelectObject(hdc_map, hPaintColorGrey); // hPaintColorGrey in den Device-Kontext MoveToEx(hdc_map, 0, 96, NULL); // move cursor to position, end line of a block LineTo(hdc_map, 488, 96); // draw line DeleteObject(SelectObject(hdc_map,hpenOld)); // alten Pen setzen, hPaintColorGrey löschen EndPaint(hWnd, &ps_map); // end painting
-
Um das noch einmal klar zu stellen:
Du erstellst jeweils einen neuen Pen (im ersten Sel.Obj), löschst ihn aber nicht mehr, da du nur den zuvor eingewählten (Default-) Pen zerstörst. Windows stellt diesen zwar immer wieder her, ist aber wahrscheinlich alles andere als glücklich dabei.
Du solltest einmal im Taskmanager beobachten, wie sich die Anzahl der GDI-Objekte bei jedem Neuzeichnen erhöht. Die letzte beiden DeleteObjects führen natürlich zu nichts (sind aber auch nicht das Problem).
-
Hallo,
vielen Dank für deine Hilfe!
Jetzt kapier ich das
Viele Grüße!