Selbstgezeichnete ProgressBar flackert...



  • Hallo zusammen!

    Zuerst einmal die Prozedur, die die ProgressBar steuert inkl. Zeichencode:

    LRESULT CALLBACK MENCODER::ProgressProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
    {
    	UNREFERENCED_PARAMETER(lParam);
    	HDC hdc;
    	PAINTSTRUCT ps;
    
    	HBRUSH hbrBcknd = CreateSolidBrush(RGB(224,224,224));
    	HBRUSH hbrFill = CreateSolidBrush(RGB(255,127,0));
    	RECT rPB;
    	RECT rFill;
    	int iStatus;
    
    	switch (message)
    	{
    	case WM_PAINT:
    		{
    			iStatus = (int) wParam;
    			GetClientRect(hDlg, &rPB);
    			hdc = BeginPaint(hDlg, &ps);
    			FillRect(hdc, &rPB,hbrBcknd);
    			char cStatusText[10];
    			sprintf(cStatusText, "%d%%", iStatus);
    
    			float fStep = (rPB.right - rPB.left) / 100.0f;
    			rFill = rPB;
    			rFill.right = fStep * iStatus;
    			FillRect(hdc, &rFill, hbrFill);
    
    			SetBkMode(hdc, TRANSPARENT);
    			//DrawText(hdc, cStatusText, strlen(cStatusText), &rPB, DT_CENTER);
    			EndPaint(hDlg, &ps);
    			DeleteObject(hdc);
    			DeleteObject(hbrBcknd);
    			DeleteObject(hbrFill);
    			return 0;
    		}break;
    
    	case WM_ERASEBKGND:
    		{
    			return 1;
    		}break;
    	}
    	return TRUE;
    }
    

    Das Problem an der Sache ist nun, dass die ProgressBar ständig flackert, bzw einfach nur weiß wird, wenn der Status für einen kleinen Zeitraum nicht fortschreitet. Kann mir jemand sagen, wie ich das vermeiden kann?

    Grüße veryxRV



    1. Backbuffer verwenden
    2. WM_PAINT nur auslösen, wenn sich der Balken überhaupt weiter bewegt
    3. DeleteObject(hdc); ist falsch: Wenn dann DeleteDC(), was aber auch falsch ist da EndPaint() das schon übernimmt.

    Würde es nicht Sinn machen die HBRUSH-Dinger static zu deklarieren und nur z.B. bei WM_CREATE zu initialisieren?



  • Danke für deine Antwort!

    Leider scheint auch ein Backbuffer das Problem nicht zu lösen. Da die ProgressBar in einem ListView gezeichnet wird, das sich ständig ändert, muss auch die PB mit jeder Änderung des ListView neu gezeichnet werden, es reicht also nicht, sie nur dann neu zu zeichnen, wenn sich der Status ändert.

    Gibt es vielleicht noch andere Möglichkeiten?



  • Es vermindert zumindest schonmal das flackern das dir FillRect() produziert, und du verkürzt dadurch bei keiner Änderung die Zeit zum neu zeichnen, da du lediglich den backbuffer blitten musst statt 2x FillRect und DrawtText().



  • Ja, das ist schon mal gut, nur wie bekomme ich das Flackern ganz weg?



  • Dann musst du irgendwie die ListView dazu bringen die Stelle wo dein Control sitzt nicht neu zu zeichnen.



  • Gibt es da nicht irendeinen Wert, den ich der ProgressBar mitgeben kann, der Bewirkt, dass sie sich sozusagen "im Vordergrund" befindet, also das ListView "darunter" gezeichnet wird?



  • Kann es evtl sein, dass das ParentWindow neu gezeichnet wird, sobald man das ChildWindow neu zeichnet?


Anmelden zum Antworten