<<__O-O undefinierbares Problem Bitmap flackert und verschwindet
-
Hi,
Ich hab da so ein Problem mit folgender Anwendung:#include <windows.h> #include <windef.h> #define SCREENWIDTH 800 #define SCREENHEIGHT 600 int mouse_X, mouse_Y; bool LBUTTONPRESSED = FALSE; HDC hdc; HWND main_window_handle; void func(void) { PAINTSTRUCT ps; HDC tmphdc; HBITMAP bmp; /*Rectangle(hdc, 0, 0, SCREENWIDTH, SCREENHEIGHT);*/ if(LBUTTONPRESSED) { hdc = GetDC(main_window_handle); tmphdc = CreateCompatibleDC(NULL); bmp = (HBITMAP)LoadImage((HINSTANCE)GetWindowLong(main_window_handle, GWL_HINSTANCE), "Bild.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE); SelectObject(tmphdc, bmp); BitBlt(hdc, mouse_X, mouse_Y, 100, 100, tmphdc, 0, 0, SRCCOPY); DeleteObject(bmp); } return; } HRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); int WINAPI WinMain(HINSTANCE hI, HINSTANCE hPI, LPSTR lpCmdLine, int iCmdShow) { WNDCLASSEX wc; char szName[] = "Win32"; wc.cbClsExtra = NULL; wc.cbSize = sizeof(WNDCLASSEX); wc.cbWndExtra = NULL; wc.hbrBackground= (HBRUSH)GetStockObject(GRAY_BRUSH); wc.hCursor = LoadCursor(hI, IDC_ARROW); wc.hIcon = LoadIcon(hI, IDI_WINLOGO); wc.hIconSm = NULL; wc.hInstance = hI; wc.lpfnWndProc = WndProc; wc.lpszClassName= szName; wc.lpszMenuName = NULL; wc.style = CS_HREDRAW | CS_VREDRAW; RegisterClassEx(&wc); HWND hWnd = CreateWindowEx(WS_EX_OVERLAPPEDWINDOW, szName, "Puzzle", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, SCREENWIDTH, SCREENHEIGHT, 0, 0, hI, NULL); main_window_handle = hWnd; ShowWindow(hWnd, iCmdShow); UpdateWindow(hWnd); MSG msg; while(true) { if(msg.message == WM_QUIT) { break; } if(PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); } } return msg.wParam; } HRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { RECT rect; rect.top = 0; rect.left= 0; rect.bottom=SCREENHEIGHT; rect.right=SCREENWIDTH; PAINTSTRUCT ps; switch(message) { case WM_PAINT: hdc = BeginPaint(hWnd, &ps); func(); EndPaint(hWnd, &ps); return 0; case WM_LBUTTONDOWN: LBUTTONPRESSED = TRUE; return 0; case WM_LBUTTONUP: LBUTTONPRESSED = FALSE; return 0; case WM_MOUSEMOVE: if(LBUTTONPRESSED) { mouse_X = LOWORD(lParam); mouse_Y = HIWORD(lParam); InvalidateRect(hWnd, &rect, 1); } return 0; case WM_DESTROY: PostQuitMessage(0); return 0; } return DefWindowProc(hWnd, message, wParam, lParam); }Wenn ich nun die linke Maustaste gedrückt halte und die Maus bewege erscheint ein flackerndes Bitmap, das hätte ich erstens gerne weg außerdem verschwindet nach geraumen hin und herbewegen das Bitmap für immer.
-
<windef.h> bitte niemals direkt einbinden. <windows.h> bindet diesen Header ganz von alleine ein.
Zum Flackern:
Du übergibst InvalidateRect als letzten Parameter eine 1, also TRUE. Dann malt Windows das Fenster erst mit der Hintergrundfarbe an und schickt dann ein WM_PAINT. Durch diesen ständigen Wechsel zwischen deiner Grafik und Hintergrundfarbe entsteht das Flackern.
Übergib mal als letzten Parameter FALSE.Außerdem: Die Zeile "hdc = GetDC(main_window_handle);" ist func() ist unnötig, hdc wird doch schon in WM_PAINT gesetzt. Was sagt zudem die Doku zu GetDC bzw. CreateCompatibleDC?
After painting with a common DC, the ReleaseDC function must be called to release the DC. Class and private DCs do not have to be released. ReleaseDC must be called from the same thread that called GetDC. The number of DCs is limited only by available memory.
When you no longer need the memory DC, call the DeleteDC function.
Du hast doch bestimmt das Platform SDK installiert. Dort gibt es eine ziemlich ausführliche Dokumentation zu diesen Funktionen. Die solltest du dir ansehen, bevor du postest.
p.s.: und entfern das "#include <windef.h>" aus deinem Code.
-
Außerdem gibst du bei dener func() tmphdc nicht wieder frei.
Und DeleteObject() soll man glaube ich auch nicht aufrufen, wenn das Objekt noch in einen DeviceContext selektiert ist.
SelectObject() gibt immer das alte Objekt vom selben Typ zurück, dass vorher selektiert war und das alte Objekt sollte vor DeleteDC() wieder in den DeviceContext rein-selektiert werden...CreateCompatibleDC() erzeugt z.B. eine 1x1 Pixel große schwarz-weiss Bitmap und selektiert die automatisch in das zurückgegeben DC.
Vor DeleteDC() muss diese Monochrom-Bitmap daher wieder rein-selektiert werden damit die Bitmap und der DC gescheit freigegeben werden.
Sonst geht die Anzahl der GDI-Objekte hoch und ab nen paar tausend wird deine Anwendung nichts mehr richtig darstellen.(GDI-Objekte lassen sich bei WinXP via taskmanager, Ansicht, Spalten auswählen, 'GDI-Objekte' für die einzelnen Prozesse anzeigen)