Flackern bei Fenster neu Zeichnen



  • Hi @ All.

    ich habe ein fenster, dass sich per SetTimer aktualisieren soll.
    nun möchte ich aber, dass der alte inhalt nicht unter dem Neuen liegt. wie soll ich das tun? das flackert dauernt!!!

    // At first define for including the windows headers
    #define _WIN32_WINNT 0x0500
    #include <windows.h>
    
    // C RunTime Header Files
    #include <stdlib.h>
    #include <malloc.h>
    #include <memory.h>
    #include <tchar.h>
    
    #include <math.h>
    
    // Local Header Files
    
    #include <commdlg.h>
    #include <ocidl.h>
    #include <olectl.h>
    #include <crtdbg.h>
    
    float Angle = 0;
    
    // The spiral draw function
    BOOL Spiral(HDC hdc, int x, int y, int cx, int cy, int rot, int repeat)
    {
    	float angle = rot;
    	float radius;
    	float quality;
    
    	if (cx >= cy) 
    	{
    		quality = (float)cx/(float)400*(float)600;
    	}
    	else
    	{
    		 quality = (float)cy/(float)400*(float)600;
    	}
    	int px,py;
    
    	MoveToEx(hdc,x,y,NULL);
    
    	for (radius = 0; radius <= 1; radius += (float)1/(float)quality)
    	{
    		px = (float)x+(float)sin((float)angle*(float)3.14159265358979323846/(float)180)*(float)radius*(float)cx/(float)2;
    		py = (float)x-(float)cos((float)angle*(float)3.14159265358979323846/(float)180)*(float)radius*(float)cy/(float)2;
    		LineTo(hdc,px,py);
    		angle = rot + ((float)radius/(float)1*(float)repeat*(float)360);
    	}
    	return true;
    }
    
    // The Window Procedure
    LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
    {
    	PAINTSTRUCT ps;
    	HBRUSH hBrush;
    	HPEN hPen;
    	HDC hdc;
    	RECT rect;
    
    	switch (msg)
    	{
    	case WM_CREATE:
    		break;
    	case WM_PAINT:
    		GetClientRect(hwnd,&rect);
    		hdc = BeginPaint(hwnd, &ps);
    		hBrush = CreateSolidBrush(RGB(255,255,255));
    		hPen = CreatePen(PS_SOLID,15,RGB(0,0,0));
    
    		SelectObject(hdc,hBrush);
    		SelectObject(hdc,hPen);
    
    		Spiral(hdc,rect.left+(rect.right-rect.left)/2,rect.top+(rect.bottom-rect.top)/2,(rect.right-rect.left)*1.5,(rect.bottom-rect.top)*1.5,Angle,10);
    
    		EndPaint(hwnd, &ps);
    		break;
    	case WM_TIMER:
    		Angle += 10;
    		InvalidateRect(hwnd,NULL,true);
    		break;
    	case WM_CLOSE:
    		DestroyWindow(hwnd);
    		break;
    	case WM_DESTROY:
    		PostQuitMessage(0);
    		break;
    	default:
    		return DefWindowProc(hwnd, msg, wParam, lParam);
    	}
    	return 0;
    }
    
    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
    					LPSTR lpCmdLine, int nCmdShow)
    {
    	WNDCLASSEX wc;
    	HWND hwnd;
    	MSG Msg;
    	static char appName[] = "Your Application";
    
    	// Registering the Window Class
    	wc.cbSize		 = sizeof(WNDCLASSEX);
    	wc.style		 = CS_HREDRAW | CS_VREDRAW;
    	wc.lpfnWndProc	 = WndProc;
    	wc.cbClsExtra	 = 0;
    	wc.cbWndExtra	 = 0;
    	wc.hInstance	 = hInstance;
    	wc.hIcon		 = LoadIcon(NULL, IDI_APPLICATION);
    	wc.hCursor		 = LoadCursor(NULL, IDC_ARROW);
    	wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
    	wc.lpszMenuName  = NULL;
    	wc.lpszClassName = appName;
    	wc.hIconSm		 = LoadIcon(NULL, IDI_APPLICATION);
    
    	if (!RegisterClassEx(&wc))
    	{
    		MessageBox(NULL, "Window Registration Failed!", "Error!",
    			MB_ICONERROR | MB_OK);
    		return 0;
    	}
    	// Creating the Window
    	hwnd = CreateWindowEx(
    		//WS_EX_OVERLAPPEDWINDOW,
    		WS_EX_CLIENTEDGE | WS_EX_TOPMOST,
    		appName,
    		"Hypnotic",
    		//WS_OVERLAPPEDWINDOW,
    		WS_BORDER,
    		CW_USEDEFAULT, CW_USEDEFAULT, 800, 800,
    		NULL, NULL, hInstance, NULL);
    
    	if (hwnd == NULL)
    	{
    		MessageBox(NULL, "Window Creation Failed!", "Error",
    			MB_ICONERROR | MB_OK);
    		return 0;
    	}
    
    	ShowWindow(hwnd, nCmdShow);
    
    	SetTimer(hwnd,NULL,25,NULL);
    
    	UpdateWindow(hwnd);
    
    	// The Message Loop
    	while (GetMessage(&Msg, NULL, 0, 0) > 0)
    	{
    		TranslateMessage(&Msg);
    		DispatchMessage(&Msg);
    	}
    	return int(Msg.wParam);
    }
    

    danke..



  • hab da mal ne eigene Methode entwickelt für die GDI, damit das nich so flackert.
    hab dafür nen Doublebuffer verwendet.

    guck dir einfach mal den Code an:

    #if defined _M_IX86 
    #pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"") 
    #elif defined _M_IA64 
    #pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='ia64' publicKeyToken='6595b64144ccf1df' language='*'\"") 
    #elif defined _M_X64 
    #pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='amd64' publicKeyToken='6595b64144ccf1df' language='*'\"") 
    #else 
    #pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"") 
    #endif
    
    #pragma comment(lib, "comctl32.lib")
    
    #pragma warning(disable: 4244)
    #pragma warning(disable: 4311)
    #pragma warning(disable: 4312)
    
    #include <windows.h>
    #include <commctrl.h>
    
    #define IDC_BALL 500
    #define IDT_BALL 501
    
    typedef struct _ELLIPSE_DESC
    {
    	COORD cUpperLeft;
    	COORD cLowerRight;
    	int cx, cy;
    } SEllipseDesc, *PEllipseDesc;
    
    BOOL CALLBACK ChildEnumProc(HWND hWnd, LPARAM lParam)
    {
    	InvalidateRect(hWnd, NULL, TRUE);
    	return TRUE;
    }
    
    HDC BeginScene(HWND hWnd, HBITMAP* pBitmap)
    {
    	RECT r = { 0 };
    	GetClientRect(hWnd, &r);
    	r.right -= r.left;
    	r.bottom -= r.top;
    	HDC hWindowDC = GetDC(hWnd);
    	HDC hDoubleBufferDC = CreateCompatibleDC(hWindowDC);
    	*pBitmap = CreateCompatibleBitmap(hWindowDC, r.right, r.bottom);
    	SelectObject(hDoubleBufferDC, (*pBitmap));
    	ReleaseDC(hWnd, hWindowDC);
    	wchar_t szClassName[1024];
    	GetClassName(hWnd, szClassName, 1024);
    	WNDCLASSEX wce = { 0 };
    	GetClassInfoEx(GetModuleHandle(NULL), szClassName, &wce);
    	FillRect(hDoubleBufferDC, &r, wce.hbrBackground);
    	return hDoubleBufferDC;
    }
    
    void EndScene(HWND hWnd, HDC hDoubleBufferDC, HBITMAP hBitmap)
    {
    	RECT r = { 0 };
    	GetUpdateRect(hWnd, &r, FALSE);
    	if ((r.bottom == 0) && (r.left == 0) && (r.right == 0) && (r.top == 0))
    		GetClientRect(hWnd, &r);
    	PAINTSTRUCT ps = { 0 };
    	HDC hWindowDC = BeginPaint(hWnd, &ps);
    	StretchBlt(hWindowDC, r.left, r.top, r.right, r.bottom, hDoubleBufferDC, r.left, r.top, r.right, r.bottom, SRCCOPY);
    	EndPaint(hWnd, &ps);
    	DeleteObject(hBitmap);
    	DeleteDC(hDoubleBufferDC);
    	ValidateRect(hWnd, &r);
    	EnumChildWindows(hWnd, ChildEnumProc, 0);
    }
    
    LRESULT CALLBACK ChildProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
    {
    	switch (msg)
    	{
    	case WM_CREATE:
    		{
    			PEllipseDesc pED = new SEllipseDesc;
    			pED->cUpperLeft.X = 0;
    			pED->cUpperLeft.Y = 0;
    			pED->cLowerRight.X = 40;
    			pED->cLowerRight.Y = 40;
    			pED->cx = 1;
    			pED->cy = 1;
    			SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR)pED);
    			SetTimer(hWnd, IDT_BALL, 1, NULL);
    			return 0;
    		} break;
    	case WM_TIMER:
    		{
    			if (wParam == IDT_BALL)
    			{
    				PEllipseDesc pED = (PEllipseDesc)GetWindowLongPtr(hWnd, GWLP_USERDATA);
    				pED->cUpperLeft.X += pED->cx;
    				pED->cUpperLeft.Y += pED->cy;
    				pED->cLowerRight.X += pED->cx;
    				pED->cLowerRight.Y += pED->cy;
    				if (pED->cUpperLeft.X <= 0)
    					pED->cx = 1;
    				if (pED->cUpperLeft.Y <= 0)
    					pED->cy = 1;
    				if (pED->cLowerRight.X >= 774)
    					pED->cx = -1;
    				if (pED->cLowerRight.Y >= 554)
    					pED->cy = -1;
    				InvalidateRect(hWnd, NULL, TRUE);
    				return 0;
    			}
    		} break;
    	case WM_PAINT:
    		{
    			HBITMAP hBmp = NULL;
    			HDC hDC = BeginScene(hWnd, &hBmp);
    			PEllipseDesc pED = (PEllipseDesc)GetWindowLongPtr(hWnd, GWLP_USERDATA);
    			HBRUSH hOldBrush = (HBRUSH)SelectObject(hDC, CreateSolidBrush(RGB(10, 120, 220)));
    			Ellipse(hDC, pED->cUpperLeft.X, pED->cUpperLeft.Y, pED->cLowerRight.X, pED->cLowerRight.Y);
    			DeleteObject(SelectObject(hDC, hOldBrush));
    			EndScene(hWnd, hDC, hBmp);
    			return 0;
    		} break;
    	case WM_ERASEBKGND:
    		{
    			return 1;
    		} break;
    	case WM_DESTROY:
    		{
    			KillTimer(hWnd, IDT_BALL);
    			PEllipseDesc pED = (PEllipseDesc)GetWindowLongPtr(hWnd, GWLP_USERDATA);
    			delete pED;
    			return 0;
    		} break;
    	}
    	return DefWindowProc(hWnd, msg, wParam, lParam);
    }
    
    LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
    {
    	switch (msg)
    	{
    	case WM_CREATE:
    		{
    			LPCREATESTRUCT pCS = (LPCREATESTRUCT)lParam;
    			HWND hBallWnd = CreateWindowEx(0, L"BALL_CHILD_24DC66A6_09DC_4001_A30D_2C3F050F04FE", L"Ball", WS_CHILD|WS_BORDER|WS_VISIBLE, 10, 10, 774, 554, hWnd, (HMENU)IDC_BALL, pCS->hInstance, NULL);
    			if (IsWindow(hBallWnd) == FALSE)
    			{
    				MessageBox(hWnd, L"Fehler: Ball Fenster konnte nicht erstellt werden!", L"Fehler!", MB_OK|MB_ICONERROR);
    				DestroyWindow(hWnd);
    				return 0;
    			}
    			ShowWindow(hBallWnd, SW_SHOW);
    			UpdateWindow(hBallWnd);
    			return 0;
    		} break;
    	case WM_PAINT:
    		{
    			HBITMAP hBmp = NULL;
    			HDC hDC = BeginScene(hWnd, &hBmp);
    			EndScene(hWnd, hDC, hBmp);
    			return 0;
    		} break;
    	case WM_CLOSE:
    		{
    			DestroyWindow(hWnd);
    			return 0;
    		} break;
    	case WM_DESTROY:
    		{
    			PostQuitMessage(0);
    			return 0;
    		} break;
    	case WM_ERASEBKGND:
    		{
    			return 1;
    		} break;
    	}
    	return DefWindowProc(hWnd, msg, wParam, lParam);
    }
    
    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLine, int iShowCmd)
    {
    	InitCommonControls();
    	WNDCLASSEX wce;
    	wce.cbClsExtra = 0;
    	wce.cbSize = sizeof(WNDCLASSEX);
    	wce.cbWndExtra = 0;
    	wce.hbrBackground = GetSysColorBrush(COLOR_BTNFACE);
    	wce.hCursor = LoadCursor(NULL, IDC_ARROW);
    	HICON hIcon = LoadIcon(NULL, IDI_WINLOGO);
    	wce.hIcon = hIcon;
    	wce.hIconSm = hIcon;
    	wce.hInstance = hInstance;
    	wce.lpfnWndProc = WndProc;
    	wce.lpszClassName = L"BALL_MAIN_D39C6525_0C87_486D_ABB3_35F15D359F91";
    	wce.lpszMenuName = NULL;
    	wce.style = CS_OWNDC|CS_DBLCLKS|CS_BYTEALIGNWINDOW|CS_BYTEALIGNCLIENT|CS_HREDRAW|CS_VREDRAW;
    	RegisterClassEx(&wce);
    	wce.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
    	wce.lpszClassName = L"BALL_CHILD_24DC66A6_09DC_4001_A30D_2C3F050F04FE";
    	wce.cbClsExtra = sizeof(PEllipseDesc);
    	wce.cbWndExtra = sizeof(PEllipseDesc);
    	wce.lpfnWndProc = ChildProc;
    	RegisterClassEx(&wce);
    	HWND hMainWindow = CreateWindowEx(0, L"BALL_MAIN_D39C6525_0C87_486D_ABB3_35F15D359F91", L"Ball Version 1.0", WS_OVERLAPPED|WS_POPUP|WS_SYSMENU|WS_CAPTION|WS_MINIMIZEBOX|WS_VISIBLE, (GetSystemMetrics(SM_CXSCREEN) - 800) / 2, (GetSystemMetrics(SM_CYSCREEN) - 600) / 2, 800, 600, GetDesktopWindow(), NULL, hInstance, NULL);
    	if (IsWindow(hMainWindow) == FALSE)
    	{
    		MessageBox(GetDesktopWindow(), L"Fehler: Hauptfenster konnte nicht erstellt werden!", L"Fehler!", MB_OK|MB_ICONERROR);
    		return 0;
    	}
    	ShowWindow(hMainWindow, SW_SHOW);
    	UpdateWindow(hMainWindow);
    	MSG msg;
    	while (GetMessage(&msg, NULL, 0, 0))
    	{
    		TranslateMessage(&msg);
    		DispatchMessage(&msg);
    	}
    	return (int)(msg.wParam);
    }
    

    der Ball springt absolut Flackerfrei...
    dank dem Doublebuffer.

    nochmal die Teile, auf die es ankommt:

    BOOL CALLBACK ChildEnumProc(HWND hWnd, LPARAM lParam)
    {
    	InvalidateRect(hWnd, NULL, TRUE);
    	return TRUE;
    }
    
    HDC BeginScene(HWND hWnd, HBITMAP* pBitmap)
    {
    	RECT r = { 0 };
    	GetClientRect(hWnd, &r);
    	r.right -= r.left;
    	r.bottom -= r.top;
    	HDC hWindowDC = GetDC(hWnd);
    	HDC hDoubleBufferDC = CreateCompatibleDC(hWindowDC);
    	*pBitmap = CreateCompatibleBitmap(hWindowDC, r.right, r.bottom);
    	SelectObject(hDoubleBufferDC, (*pBitmap));
    	ReleaseDC(hWnd, hWindowDC);
    	wchar_t szClassName[1024];
    	GetClassName(hWnd, szClassName, 1024);
    	WNDCLASSEX wce = { 0 };
    	GetClassInfoEx(GetModuleHandle(NULL), szClassName, &wce);
    	FillRect(hDoubleBufferDC, &r, wce.hbrBackground);
    	return hDoubleBufferDC;
    }
    
    void EndScene(HWND hWnd, HDC hDoubleBufferDC, HBITMAP hBitmap)
    {
    	RECT r = { 0 };
    	GetUpdateRect(hWnd, &r, FALSE);
    	if ((r.bottom == 0) && (r.left == 0) && (r.right == 0) && (r.top == 0))
    		GetClientRect(hWnd, &r);
    	PAINTSTRUCT ps = { 0 };
    	HDC hWindowDC = BeginPaint(hWnd, &ps);
    	StretchBlt(hWindowDC, r.left, r.top, r.right, r.bottom, hDoubleBufferDC, r.left, r.top, r.right, r.bottom, SRCCOPY);
    	EndPaint(hWnd, &ps);
    	DeleteObject(hBitmap);
    	DeleteDC(hDoubleBufferDC);
    	ValidateRect(hWnd, &r);
    	EnumChildWindows(hWnd, ChildEnumProc, 0);
    }
    

    die Funktionen kannst du direkt übernehmen und an Stelle von BeginPaint und EndPaint einsetzen.
    die ChildEnumProc ist ganz wichtig, da ohne sie die EndScene() nicht funzt xD
    wenn du nur ein Fenster hast geht es auch, in dem du die Zeil in EndScene löschst (EnumChildWindow(...)),
    aber sobald dein Fenster ein Child hast, musst du die Funktion haben, da sonst die Child Fentser nicht
    neugezeichnet werden und das unschöne Effekte mit sich bringt.

    dann is noch wichtig:

    case WM_ERASEBKGND:
        {
    	return 1;
        } break;
    

    damit wird der Hintergrund nicht immer gelöscht -> flackern fällt flach 😃

    und verwendet wird das ganze in der WM_PAINT:

    case WM_PAINT:
    		{
    			HBITMAP hBmp = NULL;
    			HDC hDC = BeginScene(hWnd, &hBmp);
    			// ... hier kann mit in den hDC gezeichnet werden
    			EndScene(hWnd, hDC, hBmp);
    			return 0;
    		} break;
    

    hoffe das war eingermaßen verständlich 😉

    MfG DrakoXP



  • Es gibt zahlreiche Möglichkeiten, ein Flackern zu verhindern... ➡ google, Forumsuche!



  • Meine find ich am schönsten 👍


Anmelden zum Antworten