Device Context manipuliert!
-
Hallo ihr!
In diesem einfachen Programm wird nach einiger Zeit der Kreis und die horizontale Linie manipuliert, sodass diese schwarz werden. auch Fehlermeldungsfenster anderer Programme werden ziemlich verzerrt. Ich konnte den Fehler eingrenzen aber nicht lösen. Der Code:
#include <windows.h> #include <windowsx.h> #include <commctrl.h> #include <string.h> #define IDM_EXIT 300 #define IDACCEL 10000 HINSTANCE hInst; HWND hwndMain; LRESULT CALLBACK MainWndProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam); static BOOL InitApplication(void) { WNDCLASS wc; memset(&wc,0,sizeof(WNDCLASS)); wc.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS; wc.lpfnWndProc = (WNDPROC)MainWndProc; wc.hInstance = hInst; wc.hbrBackground = (HBRUSH) (COLOR_BACKGROUND); wc.lpszClassName = "windowWndClass"; wc.lpszMenuName = NULL; wc.hCursor = LoadCursor(NULL,IDC_ARROW); wc.hIcon = LoadIcon(NULL,IDI_APPLICATION); if (!RegisterClass(&wc)) return 0; return 1; } HWND CreatewindowWndClassWnd(void) { return CreateWindow("windowWndClass","window", WS_MINIMIZEBOX | WS_CAPTION | WS_SYSMENU | WS_OVERLAPPED, GetSystemMetrics(SM_CXSCREEN) / 2 - 320, GetSystemMetrics(SM_CYMAXIMIZED) / 2 - 230, 640, 453, NULL, NULL, hInst, NULL); } void MainWndProc_OnCommand(HWND hwnd, int id, HWND hwndCtl, UINT codeNotify) { switch(id) { case IDM_EXIT: PostMessage(hwnd,WM_CLOSE,0,0); break; } } LRESULT CALLBACK MainWndProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam) { HDC hdc; PAINTSTRUCT ps; HPEN hPen; switch (msg) { case WM_COMMAND: HANDLE_WM_COMMAND(hwnd,wParam,lParam,MainWndProc_OnCommand); break; case WM_DESTROY: PostQuitMessage(0); break; case WM_PAINT: //Ab hier hdc = BeginPaint(hwnd, &ps); MoveToEx(hdc, 1, 0, NULL); hPen = CreatePen(PS_SOLID, 1, RGB(128, 128, 128)); SelectObject(hdc, hPen); LineTo(hdc, 633, 0); MoveToEx(hdc, 1, 1, NULL); hPen = CreatePen(PS_SOLID, 1, RGB(255, 255, 255)); SelectObject(hdc, hPen); LineTo(hdc, 633, 1); hPen = CreatePen(PS_SOLID, 1, RGB(255, 255, 255)); SelectObject(hdc, hPen); Arc(hdc, 256, 16, 621, 381, 256, 16, 257, 17); hPen = CreatePen(PS_SOLID, 1, RGB(128, 128, 128)); SelectObject(hdc, hPen); Arc(hdc, 255, 15, 620, 380, 255, 15, 256, 16); EndPaint (hwnd, &ps) ;//Bis hier return 0; default: return DefWindowProc(hwnd,msg,wParam,lParam); } return 0; } int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, INT nCmdShow) { MSG msg; HANDLE hAccelTable; hInst = hInstance; if (!InitApplication()) return 0; hAccelTable = LoadAccelerators(hInst,MAKEINTRESOURCE(IDACCEL)); if ((hwndMain = CreatewindowWndClassWnd()) == (HWND)0) return 0; ShowWindow(hwndMain,SW_SHOW); while (GetMessage(&msg,NULL,0,0)) { if (!TranslateAccelerator(msg.hwnd,hAccelTable,&msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } } return msg.wParam; }Lasst das Programm einfach eine Zeit lang offen oder bewegt sein Fenster.
Was habe ich bloß falsch gemacht?Gruß
Dragan(Bitte das nächste mal code-tags verwenden. thx - CMatt)
-
Du rufst bei jeder WM_PAINT x mal CreatePen auf, ohne DeleteObject. Windows hat nicht beliebig viele resourcen, irgendwann ist schluss und dann wirds schwarz weil die farben fertig sind.
-
CMatt schrieb:
Du rufst bei jeder WM_PAINT x mal CreatePen auf, ohne DeleteObject. Windows hat nicht beliebig viele resourcen, irgendwann ist schluss und dann wirds schwarz weil die farben fertig sind.
DeleteObject(hPen) habe ich auch schon ausprobiert, jedes mal als LineTo(...) oder Arc(...) fertig war. Das geht auch schief

-
Ebelcrom schrieb:
DeleteObject(hPen) habe ich auch schon ausprobiert, jedes mal als LineTo(...) oder Arc(...) fertig war. Das geht auch schief

selbstverständlich und zwar schlägt dabei die Funktion fehl, da der Stift nicht freigegeben werden kann, solange er noch im DC ist. Am besten machst du das in der Art:
WM_PAINT:{ hdc = BeginPaint(hwnd, &ps); HPEN oldPen=SelectObject(hdc, CreatePen(0)); //mit Pen0 irgendwas zeichnen DeleteObject(SelectObject(hdc, CreatePen(1))); //mit Pen1 irgendwas zeichnen //. //. //. DeleteObject(SelectObject(hdc, CreatePen(n))); //mit Pen(n) irgendwas zeichnen DeleteObject(SelectObject(hdc, oldPen)); EndPaint (hwnd, &ps); return 0; }
-
Auch mal interessant...
Ich habe den Code von Ebelcrom mal bei mir compiliert, gibt eine Fehlermeldung (cannot convert void* to Haccel oder so), ist ja auch schnell behoben, dann compilierts wunderbar. Gestartet, Fenster zigtausendmal hin- und hergeschoben, dass es auch ja schön WM_PAINT-Messages empfängt, und siehe da: absolut kein Problem...
Hab auch mit DeleteObject vor jedem neuen CreatePen ausprobiert, meckert auch kein Compiler und kein Windows rum. Stellt sich mir die Frage: Wo liegt das Problem? Grafikkartenspeicher viel kleiner als bei meiner? keine Ahnung.
bin gespannt auf eure Erklärungen!Gruß
Deadlef
-
Tipp: Mit dem Taskmanager kann man leicht erkennen ob ein Programm GDI-Ressourcen leckt. (Ansicht->Spalten auswählen...)
-
Yo, yo, da wars! Die Kombi von Select- und DeleteObject klappt und laut Taskmanager vermehren sich die GDI-Objekte nicht mehr. VIELEN DANK!
