double buffer die 2te
-
Moins,
vor einiger zeit hatte ich schon mal ein ähnliches problem beschrieben, hier habe ich aber mal konkreten source.Erstmal zum source:
Es wird ein fenster mit drei TrackBar's erstellt, die TrackBars können werte zwischen 0-255 annhemne und repräsentieren Farbwerte in RGB. Links neben jeder TrackBar wird ein RoundRect mit der Jeweiligen Farbe und einen hellblauen Rahmen gezeichnet.Jetzt zum Bug:
Scrollt man mit der Maus die TrackBars (mal verschiedene, mal reicht eine) sehr schnell hin und her, so kommt es nach einiger zeit reproduzierbar dazu, das der double buffering bereich Weiß gezeichnet wird, die Rahmen der RoundRect Schwarz. Der zustand verbleibt bis zum neustart des Programms.
In einem anderen ähnlichen Fall kam es sogar dazu das die Captionbar des Windows beim Vergrößern sich nicht neu gezeichnet hat.
Leider weiß ich mal überhaut nicht woran das liegen könnte.
Ich werde hier den kompletten source einfügen:
#include <windows.h> #include <commctrl.h> /* Declare Windows procedure */ HINSTANCE hGlobalInstance; LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM); /* Make the class name into a global variable */ char szClassName[ ] = "WindowsApp"; int WINAPI WinMain (HINSTANCE hThisInstance, HINSTANCE hPrevInstance, LPSTR lpszArgument, int nFunsterStil) { HWND hwnd; /* This is the handle for our window */ MSG messages; /* Here messages to the application are saved */ WNDCLASSEX wincl; /* Data structure for the windowclass */ /* The Window structure */ wincl.hInstance = hThisInstance; wincl.lpszClassName = szClassName; wincl.lpfnWndProc = WindowProcedure; /* This function is called by windows */ wincl.style = CS_DBLCLKS; /* Catch double-clicks */ wincl.cbSize = sizeof (WNDCLASSEX); /* Use default icon and mouse-pointer */ wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION); wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION); wincl.hCursor = LoadCursor (NULL, IDC_ARROW); wincl.lpszMenuName = NULL; /* No menu */ wincl.cbClsExtra = 0; /* No extra bytes after the window class */ wincl.cbWndExtra = 0; /* structure or the window instance */ /* Use Windows's default color as the background of the window */ wincl.hbrBackground = (HBRUSH) COLOR_BACKGROUND; /* Register the window class, and if it fails quit the program */ if (!RegisterClassEx (&wincl)) return 0; /* The class is registered, let's create the program*/ hwnd = CreateWindowEx ( 0, /* Extended possibilites for variation */ szClassName, /* Classname */ "Windows App", /* Title Text */ WS_OVERLAPPEDWINDOW, /* default window */ CW_USEDEFAULT, /* Windows decides the position */ CW_USEDEFAULT, /* where the window ends up on the screen */ 544, /* The programs width */ 375, /* and height in pixels */ HWND_DESKTOP, /* The window is a child-window to desktop */ NULL, /* No menu */ hThisInstance, /* Program Instance handler */ NULL /* No Window Creation data */ ); /* Make the window visible on the screen */ ShowWindow (hwnd, nFunsterStil); hGlobalInstance=hThisInstance; /* Run the message loop. It will run until GetMessage() returns 0 */ while (GetMessage (&messages, NULL, 0, 0)) { /* Translate virtual-key messages into character messages */ TranslateMessage(&messages); /* Send message to WindowProcedure */ DispatchMessage(&messages); } /* The program return-value is 0 - The value that PostQuitMessage() gave */ return messages.wParam; }LRESULT CALLBACK WindowProcedure (HWND hWnd, UINT message, WPARAM wParam,LPARAM lParam) { static HWND hTrackRed; static HWND hTrackGreen; static HWND hTrackBlue; static HWND hChildRed; static HWND hChildGreen; static HWND hChildBlue; UINT iMin=0; UINT iMax=255; UINT iSelMin=0; UINT iSelMax=255; switch(message) { case WM_CREATE: { //system("pause"); /* ostringstream res; res<<*(This->lpCol); MessageBox(hWnd,res.str().c_str(), "About...", MB_OK | MB_ICONINFORMATION); */ InitCommonControls(); // loads common control's DLL hTrackRed = CreateWindowEx(0, TRACKBAR_CLASS, "Red", WS_CHILD | WS_VISIBLE | TBS_ENABLESELRANGE | TBS_NOTICKS, 20, 10, 200, 20, hWnd, NULL, hGlobalInstance, NULL); hTrackGreen = CreateWindowEx(0, TRACKBAR_CLASS, "Green", WS_CHILD | WS_VISIBLE | TBS_ENABLESELRANGE | TBS_NOTICKS, 20, 35, 200, 20, hWnd, NULL, hGlobalInstance, NULL); hTrackBlue = CreateWindowEx(0, TRACKBAR_CLASS, "Blue", WS_CHILD | WS_VISIBLE | TBS_ENABLESELRANGE | TBS_NOTICKS, 20, 60, 200, 20, hWnd, NULL, hGlobalInstance, NULL); SendMessage(hTrackRed, TBM_SETRANGE, (WPARAM) TRUE, // redraw flag (LPARAM) MAKELONG(iMin, iMax)); // min. & max. positions SendMessage(hTrackRed, TBM_SETPAGESIZE, 0, (LPARAM) 4); // new page size SendMessage(hTrackRed, TBM_SETSEL, (WPARAM) FALSE, // redraw flag (LPARAM) MAKELONG(iSelMin, iSelMax)); SendMessage(hTrackGreen, TBM_SETRANGE, (WPARAM) TRUE, // redraw flag (LPARAM) MAKELONG(iMin, iMax)); // min. & max. positions SendMessage(hTrackGreen, TBM_SETPAGESIZE, 0, (LPARAM) 4); // new page size SendMessage(hTrackGreen, TBM_SETSEL, (WPARAM) FALSE, // redraw flag (LPARAM) MAKELONG(iSelMin, iSelMax)); SendMessage(hTrackBlue, TBM_SETRANGE, (WPARAM) TRUE, // redraw flag (LPARAM) MAKELONG(iMin, iMax)); // min. & max. positions SendMessage(hTrackBlue, TBM_SETPAGESIZE, 0, (LPARAM) 4); // new page size SendMessage(hTrackBlue, TBM_SETSEL, (WPARAM) FALSE, // redraw flag (LPARAM) MAKELONG(iSelMin, iSelMax)); //ShowWindow( //SetFocus(hwndTrack); /* ostringstream res; res<<tempCol; MessageBox(hWnd,res.str().c_str(), "About...", MB_OK | MB_ICONINFORMATION); */ int tempCol=0x00ff3a56; SendMessage(hTrackRed, TBM_SETPOS, (WPARAM) TRUE, // redraw flag (LPARAM) GetRValue(tempCol)); SendMessage(hTrackGreen, TBM_SETPOS, (WPARAM) TRUE, // redraw flag (LPARAM) GetGValue(tempCol)); SendMessage(hTrackBlue, TBM_SETPOS, (WPARAM) TRUE, // redraw flag (LPARAM) GetBValue(tempCol)); return DefWindowProc(hWnd,message,wParam,lParam); }jetzt der Paint case:
case WM_PAINT: { RECT rect; GetWindowRect(hWnd,&rect); int width=rect.right-rect.left; int height=rect.bottom-rect.top; int bkgCol=0x00d8e9ec; int frmCol=0x00b99d7f; COLORREF RedCol=RGB(SendMessage(hTrackRed,TBM_GETPOS,(WPARAM)NULL,(LPARAM)NULL),0,0); COLORREF GreenCol=RGB(0,SendMessage(hTrackGreen,TBM_GETPOS,(WPARAM)NULL,(LPARAM)NULL),0); COLORREF BlueCol=RGB(0,0,SendMessage(hTrackBlue,TBM_GETPOS,(WPARAM)NULL,(LPARAM)NULL)); PAINTSTRUCT ps; HDC hDC=BeginPaint(hWnd,&ps); HDC hMemDC=CreateCompatibleDC(hDC); HBITMAP hBm = CreateCompatibleBitmap(hDC, width+1, height+1); SelectObject(hMemDC, hBm); //Draw background HBRUSH hOldBrush = (HBRUSH)SelectObject(hMemDC,CreateSolidBrush(bkgCol)); HPEN hOldPen=(HPEN)SelectObject(hMemDC,CreatePen(1,1,bkgCol)); RoundRect(hMemDC,0,0,400+1,200+1+1,0,0); hOldBrush=(HBRUSH)SelectObject(hMemDC, CreateSolidBrush(bkgCol)); hOldPen=(HPEN)SelectObject(hMemDC,CreatePen(PS_DOT,2,frmCol)); // COLORREF MixedCol=RedCol|GreenCol|BlueCol; hOldBrush = (HBRUSH)SelectObject(hMemDC,CreateSolidBrush(RedCol)); hOldPen=(HPEN)SelectObject(hMemDC,CreatePen(1,1,frmCol)); RoundRect(hMemDC,5,10,15,30,15,15); hOldBrush = (HBRUSH)SelectObject(hMemDC,CreateSolidBrush(GreenCol)); hOldPen=(HPEN)SelectObject(hMemDC,CreatePen(1,1,frmCol)); RoundRect(hMemDC,5,35,15,55,15,15); hOldBrush = (HBRUSH)SelectObject(hMemDC,CreateSolidBrush(BlueCol)); hOldPen=(HPEN)SelectObject(hMemDC,CreatePen(1,1,frmCol)); RoundRect(hMemDC,5,60,15,80,15,15); BitBlt(hDC, 0, 0, 400, 200, hMemDC, 0, 0, SRCCOPY); DeleteDC(hMemDC); DeleteObject(hBm); DeleteObject(hOldBrush); DeleteObject(hOldPen); EndPaint(hWnd,&ps); //DeleteDC(hDC); return DefWindowProc (hWnd, message, wParam, lParam); }und jetzt der rest:
case WM_HSCROLL: { switch (LOWORD(wParam)) { case TB_ENDTRACK:{ DWORD dwPos = SendMessage(hTrackRed, TBM_GETPOS, 0, 0); if (dwPos > iSelMax) SendMessage(hTrackRed, TBM_SETPOS, (WPARAM) TRUE, (LPARAM) iSelMax); else if (dwPos < iSelMin) SendMessage(hTrackRed, TBM_SETPOS, (WPARAM) TRUE, (LPARAM) iSelMin); dwPos = SendMessage(hTrackGreen, TBM_GETPOS, 0, 0); if (dwPos > iSelMax) SendMessage(hTrackGreen, TBM_SETPOS, (WPARAM) TRUE, (LPARAM) iSelMax); else if (dwPos < iSelMin) SendMessage(hTrackGreen, TBM_SETPOS, (WPARAM) TRUE, (LPARAM) iSelMin); dwPos = SendMessage(hTrackBlue, TBM_GETPOS, 0, 0); if (dwPos > iSelMax) SendMessage(hTrackBlue, TBM_SETPOS, (WPARAM) TRUE, (LPARAM) iSelMax); else if (dwPos < iSelMin) SendMessage(hTrackBlue, TBM_SETPOS, (WPARAM) TRUE, (LPARAM) iSelMin); } } RECT rect; GetWindowRect(hWnd,&rect); InvalidateRect(hWnd,NULL,FALSE); return 0; } case WM_ERASEBKGND: {return 1;} case WM_DESTROY: {//PostQuitMessage (0); return 0; } default: /* for messages that we don't deal with */ return DefWindowProc (hWnd, message, wParam, lParam); } return 0; };(Manche stellen sind durch hin und her probieren vlt. etwas unsauber programmiert,)
Danke im Vorhinein für eure meinung und hilfe
-
zeusosc schrieb:
[...]vlt. etwas unsauber programmiert
richtig erkannt, der codingstyle geht ja noch aber dein einrücken..

hab mehrmals diese schließende klammer gesucht.schließende kommen immer in die selbe spalte wie öffnende, eine öffnende wird
in eineeigene
zeilegeschrieben und ein [tab] weiter eingerückt als die letzte.
{ { } }hab den code mal umgeschrieben, der ist besser lesbar. und du hattest
#include "stdafx.h" #include <windows.h> #include <commctrl.h> #pragma comment (lib, "comctl32.lib") HINSTANCE hGlobalInstance; LRESULT CALLBACK WindowProcedure(HWND, UINT, WPARAM, LPARAM); int WINAPI WinMain (HINSTANCE hThisInstance, HINSTANCE, char *, int) { HWND hWnd; MSG msg; WNDCLASS wc; // WNDCLASS reicht ZeroMemory(&wc, sizeof(wc)); // kürzer wc.hInstance = hGlobalInstance = hThisInstance; wc.lpfnWndProc = WindowProcedure; wc.lpszClassName = "WindowsApp"; wc.hIcon = LoadIcon (0, IDI_APPLICATION); wc.hCursor = LoadCursor (0, IDC_ARROW); wc.hbrBackground = reinterpret_cast<HBRUSH>(GetStockObject(WHITE_BRUSH)); wc.style = CS_DBLCLKS; // COLOR_BACKGROUND ist durchsichtig ! if (!RegisterClass(&wc)) return 0; hWnd = CreateWindow(wc.lpszClassName, "Windows App", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 544, 375, 0, 0, hThisInstance, 0); // warum den so komische werte? ShowWindow(hWnd, SW_SHOWNORMAL); UpdateWindow(hWnd); while (GetMessage (&msg, 0, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return msg.wParam; } LRESULT CALLBACK WindowProcedure(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { static HWND hTrackRed; static HWND hTrackGreen; static HWND hTrackBlue; static HWND hChildRed; static HWND hChildGreen; static HWND hChildBlue; HWND *hWnds[] = {&hTrackRed, &hTrackGreen, &hTrackBlue}; UINT iMin = 0; UINT iMax = 255; UINT iSelMin = 0; UINT iSelMax = 255; switch(message) { case WM_CREATE: { InitCommonControls(); char *names[] = {"Red", "Green", "Blue"}; COLORREF tempCol=0x00ff3a56; COLORREF cols[] = {GetRValue(tempCol), GetGValue(tempCol), GetBValue(tempCol)}; unsigned long style = WS_CHILD | WS_VISIBLE | TBS_ENABLESELRANGE | TBS_NOTICKS; for (unsigned i = 0; i < sizeof(names) / sizeof(names[0]); ++i) { HWND wnd = CreateWindow(TRACKBAR_CLASS, names[i], style, 20, 10 + 25 * i, 200, 20, hWnd, 0, hGlobalInstance, 0); SendMessage(wnd, TBM_SETRANGE, (WPARAM) TRUE, (LPARAM)MAKELONG(iMin, iMax)); SendMessage(wnd, TBM_SETPAGESIZE, 0, (LPARAM)4); SendMessage(wnd, TBM_SETSEL, 0, (LPARAM) MAKELONG(iSelMin, iSelMax)); SendMessage(wnd, TBM_SETPOS, (WPARAM)TRUE, (LPARAM)cols[i]); *hWnds[i] = wnd; } // kürzer :P } break; case WM_PAINT: { RECT rect; GetWindowRect(hWnd,&rect); int width=rect.right-rect.left; int height=rect.bottom-rect.top; int bkgCol = 0x00d8e9ec; int frmCol = 0x00b99d7f; COLORREF RedCol = RGB(SendMessage(*hWnds[0],TBM_GETPOS, 0, 0), 0, 0); COLORREF GreenCol = RGB(0, SendMessage(*hWnds[1],TBM_GETPOS, 0, 0), 0); COLORREF BlueCol = RGB(0, 0, SendMessage(*hWnds[2],TBM_GETPOS, 0, 0)); PAINTSTRUCT ps; HDC hDC = BeginPaint(hWnd,&ps); HDC hMemDC = CreateCompatibleDC(hDC); HBITMAP hBm = CreateCompatibleBitmap(hDC, width + 1, height + 1); HGDIOBJ oldbm = SelectObject(hMemDC, hBm); HBRUSH bkgbrush = CreateSolidBrush(bkgCol); HBRUSH redbrush = CreateSolidBrush(RedCol); HBRUSH greenbrush = CreateSolidBrush(GreenCol); HBRUSH bluebrush = CreateSolidBrush(BlueCol); HPEN pen1 = CreatePen(1, 1, bkgCol); HPEN pen2 = CreatePen(1, 1, frmCol); // achtung speicherlecks !! VIELE speicherlecks, SEHR VIELE !!! :( { //Draw background HBRUSH hOldBrush = (HBRUSH)SelectObject(hMemDC, bkgbrush); HPEN hOldPen = (HPEN)SelectObject(hMemDC, pen1); RoundRect(hMemDC, 0, 0, 400 + 1, 200 + 1 + 1, 0, 0); // COLORREF MixedCol=RedCol|GreenCol|BlueCol; SelectObject(hMemDC, redbrush); SelectObject(hMemDC, pen2); // einmal reicht RoundRect(hMemDC, 5, 10, 15, 30, 15, 15); SelectObject(hMemDC, greenbrush); RoundRect(hMemDC, 5, 35, 15, 55, 15, 15); SelectObject(hMemDC, bluebrush); RoundRect(hMemDC, 5, 60, 15, 80, 15, 15); BitBlt(hDC, 0, 0, 400, 200, hMemDC, 0, 0, SRCCOPY); SelectObject(hMemDC, hOldBrush); SelectObject(hMemDC, hOldPen); // am ende das anfangsobjekt wieder zurückselektieren, vorher muss nicht sein } DeleteObject(pen1); DeleteObject(pen2); DeleteObject(bkgbrush); DeleteObject(redbrush); DeleteObject(greenbrush); DeleteObject(bluebrush); SelectObject(hMemDC, oldbm); DeleteObject(hBm); DeleteDC(hMemDC); EndPaint(hWnd,&ps); //DeleteDC(hDC); // bloß nicht !! } break; case WM_HSCROLL: { switch (LOWORD(wParam)) { case TB_ENDTRACK: { for (unsigned i = 0; i < 3; ++i) { HWND hTrack = *hWnds[i]; DWORD dwPos = SendMessage(hTrack, TBM_GETPOS, 0, 0); if (dwPos > iSelMax) SendMessage(hTrack, TBM_SETPOS, (WPARAM) TRUE, (LPARAM) iSelMax); else if (dwPos < iSelMin) SendMessage(hTrack, TBM_SETPOS, (WPARAM) TRUE, (LPARAM) iSelMin); } } } RECT rect; GetWindowRect(hWnd, &rect); InvalidateRect(hWnd, 0, 0); } break; //case WM_ERASEBKGND: {return 1;} // warum diese nachricht ? case WM_DESTROY: PostQuitMessage(0); } return DefWindowProc (hWnd, message, wParam, lParam); }den fehler konnte ich nicht reproduzieren
-
Hi, danke erstmal,
Ich habe ja gesagt ist unsauber
Ok danke erstmal, ich habe deine verbesserungung ausprobiert, der bug lässt sich nicht reproduzieren. Dann habe ich deine WM_PAINT durch meine ersetzt, der bug taucht wieder auf.
Kann es sein das (wie Du sagst) die Speicher lecks bei dieser zuweisung
hOldBrush = (HBRUSH)SelectObject(hMemDC,CreateSolidBrush(RedCol)); hOldPen=(HPEN)SelectObject(hMemDC,CreatePen(1,1,frmCol));daran schuld sind??
Danke nochmal dass Du dir mein gemüse von heute angetan hast.
Der source war von sehr früher stunde
-----------------
Edit:
Ich habe gerade gesehen das ich mich ganz schön viel bedanke *hehehehe*,...
-
hehe kein problem

ich vermute der fehler trat durch den speicherleck auf.
die maus, die jazeusosc schrieb:
sehr schnell hin und her
bewegt wird, und das auch noch länger, produziert
bei jeder mausbewegung eine WM_PAINT nachricht.bei dieser nachricht entstehen
helferlein schrieb:
SEHR VIELE !!!
speicherlecks.
unterm strich verbrauchst du so viel speicher, das du die GDI bzw windows
in die knie zwingst.vllt trat das problem bei dir so früh auf, weil du wenig RAM übrig hast.
MfG helferlein
ps. PostQuitMessage ist wichtig

-
Hallo !
So ein ähnliches Problem hatte ich auch mal.
Es liegt daran das Windows nur eine begrenzet Anzahl an HBRUSH HPENS etc. öffnen kann.
Du hast zwar mit deleteObject(..) die Handles versucht zu löschen, aber sie waren noch immer geladen, deswegen wurden sie gar nicht gelöscht, du hättest vorher select(..hOldPen) und dann deleteObject(hPen) machen müssen.
zB:
hOldBrush = (HBRUSH)SelectObject(hMemDC,CreateSolidBrush(GreenCol)); hOldPen=(HPEN)SelectObject(hMemDC,CreatePen(1,1,frmCol)); RoundRect(hMemDC,5,35,15,55,15,15); hOldBrush = (HBRUSH)SelectObject(hMemDC,CreateSolidBrush(BlueCol)); hOldPen=(HPEN)SelectObject(hMemDC,CreatePen(1,1,frmCol)); RoundRect(hMemDC,5,60,15,80,15,15);In der 2. Zeile weist du hOldPen ein Handle zu, weiter unten weist du hOldPen erneut ein Handle zu, das erste Handle wird nie gelöscht, du kannst es auch nicht mehr löschen weil du den Zeiger zu dem Handle nicht mehr hast.