Button mit BS_OWNERDRAW Style "spinnt" wenn ein Timer läuft

michbach

Grünschnabel
Hallo Zusammen,

ich habe einen Button mit einem Aussschnitt vom Calculator(calc.exe) und einen Button mit einem wechselnden Bild wenn man drauf klickt. Beide Buttons habe ich mit dem Style BS_OWNERDRAW erstellt und in der DRAWITEM Funktion werden die Eigenschaften zugewiesen. Eigentlich klappt es soweit gut wenn ich das Programm starte aber nach ca. 1-2 Minuten verschwindet das Bild auf dem Button und wenn man das Main-Fenster verschiebt dann wird der Desktop auch noch neu gezeichnet.

Irgenwie hängt es mit der Timer-Funktion zusammen denn Ohne Timer scheint es nämlich zu klappen (zumindest scheint es mir so). Irgendeine Timer-Funktion brauche ich aber weil der Button mit dem Ausschnitt vom Calculator automatisch (also ohne anklicken) refreshed werden soll. Hmmm, ich komm nicht mehr weiter wo das Problem liegt! Vieleicht kann jemand weiter helfen? Gruss und danke im Voraus, michbach

Code:
#include <windows.h>
#include <stdio.h>
#include <tchar.h>

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
LPCSTR lpszAppName			= "AppName";
char szNewButtonClassName[] = "newbutton";
HINSTANCE hInstance;

HWND hWnd;
HWND *btn					= new HWND[100];
HWND hwndcalc;
HDC hdccalc;
HDC CopyDC;

const UINT Timer1			= 1;
TCHAR title[2];
HBITMAP bmpcalc;

// ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ
// XXXXXX										Sub`s															XXXXXXXX
// XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
int DrawItem(UINT wParam,LPARAM lParam)
{
	LPDRAWITEMSTRUCT lpdis = (DRAWITEMSTRUCT*)lParam;
	HDC hdca = ((LPDRAWITEMSTRUCT)(lParam))->hDC;
	HDC hdcMem = CreateCompatibleDC(hdca);
	HBITMAP hBitmap;

	//XXX Buttons sunken und raise 
	DrawEdge(lpdis->hDC, &lpdis->rcItem,(lpdis->itemState & ODS_SELECTED ? EDGE_SUNKEN : EDGE_RAISED ), BF_RECT);


	if (((LPDRAWITEMSTRUCT)(lParam))->itemState & ODS_SELECTED){}
	else
	{
		switch(lpdis->CtlID)		//XXXX Abfrage Kontroll-ID
		{
			default:

				if( lpdis->CtlID == 0)	// Button mit Bild
				{
					ZeroMemory(title, sizeof(title));
					GetWindowText(btn[lpdis->CtlID], title, sizeof(title)/sizeof(title[0]));
					if(_tcsstr(title, _T("F")))
					{
						hBitmap = (HBITMAP)LoadImage(0,"c:\\F.bmp",IMAGE_BITMAP,0,0,LR_LOADFROMFILE);
						SelectObject (hdcMem, hBitmap);
						BitBlt (hdca, 0, 0, 30, 30, hdcMem, 0, 0, SRCCOPY) ;
					}
					else if (_tcsstr(title, _T("X")))
					{
						hBitmap = (HBITMAP)LoadImage(0,"c:\\X.bmp",IMAGE_BITMAP,0,0,LR_LOADFROMFILE);
						SelectObject (hdcMem, hBitmap);
						BitBlt (hdca, 0, 0, 30, 30, hdcMem, 0, 0, SRCCOPY) ;
					}
				break;
				}
				else if( lpdis->CtlID == 1 )	// Button mit dem Calc-Ausschnitt
				{
					BitBlt (hdca,20,10,70,25,hdccalc,180, 40,SRCCOPY);	
				}

			break;
		}
	}
return 1;
}


void refresh()
{
	InvalidateRect(hWnd, NULL, TRUE);
}

// ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ
// XXXXXX										Main															XXXXXXXX
// XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,PSTR szCmdLine, int iCmdShow)
{
	//XXXX für den Button mit dem Calculator-Ausschnitt
	hwndcalc = FindWindow( 0, "Rechner");
	hdccalc = GetWindowDC(hwndcalc);
	CopyDC = CreateCompatibleDC (hdccalc);
	bmpcalc = CreateCompatibleBitmap (hdccalc,70 ,25 );
	SelectObject (CopyDC, bmpcalc);

	//XXXX Button-Klasse (Doppel-Klick etc. modifiziert)
	WNDCLASS ClassNewButton;
	if( GetClassInfo(hInstance, "button",&ClassNewButton) )
	{
		ClassNewButton.hCursor = LoadCursor(NULL, IDC_HAND);
		ClassNewButton.lpszClassName = szNewButtonClassName;
		ClassNewButton.style &= ~((UINT)CS_DBLCLKS);// ****** turn off CS_DBLCLKS style
		RegisterClass(&ClassNewButton);
	}

	//XXXXX Main-Klasse
    MSG         msg;
    WNDCLASSEX  wc;

    wc.cbSize        =  sizeof(WNDCLASSEX);
    wc.style         =  CS_HREDRAW | CS_VREDRAW;
    wc.lpfnWndProc   =  WndProc;
    wc.cbClsExtra    =  0;
    wc.cbWndExtra    =  0;
    wc.hInstance     =  hInstance;
    wc.hCursor       =  LoadCursor(NULL,IDC_ARROW);
    wc.hIcon         =  LoadIcon(NULL, IDI_APPLICATION);
    wc.hbrBackground =  (HBRUSH)GetStockObject(WHITE_BRUSH);
    wc.lpszClassName =  lpszAppName;
    wc.lpszMenuName  =  lpszAppName;
    wc.hIconSm       =  LoadIcon(NULL, IDI_APPLICATION);
    if( RegisterClassEx(&wc) == 0) return 0;

	//XXXX Erstell das Haupt-Fenster
	hWnd = CreateWindowEx(WS_EX_COMPOSITED,lpszAppName,"Main",WS_OVERLAPPEDWINDOW,200,200,208,126,NULL,NULL,hInstance,NULL);
	ShowWindow(hWnd, iCmdShow);
	UpdateWindow(hWnd);

	//XXXX Erstell die Buttons
	btn[0] = CreateWindow(szNewButtonClassName,"F",WS_CHILD|WS_VISIBLE|BS_OWNERDRAW,0,0,100,100,hWnd,(HMENU)0,hInstance,NULL);
	btn[1] = CreateWindow(szNewButtonClassName,"C",WS_CHILD|WS_VISIBLE|BS_OWNERDRAW,100,0,100,100,hWnd,(HMENU)1,hInstance,NULL);

    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return msg.wParam;
}

// ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ
// XXXXXX										Callback Main													XXXXXXXX
// XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
LRESULT CALLBACK WndProc(HWND hWnd, UINT umsg, WPARAM wParam, LPARAM lParam)
{
	PAINTSTRUCT ps;
    switch (umsg)
    {
		//_________________________________________
		case WM_CREATE:
		{
				SetTimer(hWnd, Timer1, 20, NULL);
		}return 0;
		//_________________________________________
		case WM_TIMER:
		{
			refresh();
		}break;
		//_________________________________________    
		case WM_DESTROY:
        {
			KillTimer(hWnd, Timer1);
            PostQuitMessage(0);
        }return 0;
		//_________________________________________
		case WM_DRAWITEM:
		{
				DrawItem(wParam,lParam);
		}break;
		//_________________________________________
		case WM_COMMAND:
		{
			switch(LOWORD(wParam))
            {
				default:
				{
					//XXX Statusabfrage des Buttons mit dem Bild
					if( lParam == (LPARAM)btn[wParam])
					{
						ZeroMemory(title, sizeof(title));
						GetWindowText(btn[wParam], title, sizeof(title)/sizeof(title[0]));

						if(_tcsstr(title, _T("X"))){SetWindowText(btn[wParam],"F");}
						else{SetWindowText(btn[wParam],"X");}
					}
				}break;
			}
		}
		//_________________________________________
		case WM_PAINT:
		{
			BeginPaint(hWnd, &ps);
				// mach was
			EndPaint(hWnd, &ps);

		}break;

    }return DefWindowProc(hWnd, umsg, wParam, lParam);
}
 
Hallo,

der Timer ist nicht die Ursache, aber er beschleunigt das Desaster :)
Du musst in DrawItem() die verwendeten Resourcen (hdcMem, hBitmap) auch wieder aufräumen, sonst geht dir irgendwann der Resourcen-Speicher aus, was recht überraschende grafische Effekte produzieren kann.

Gruß
MCoder
 
Hallo MCoder,

danke für die Hilfe! Aufräumen hab ich vergessen. Ich habe jetzt "DeleteDC(hdcMem)" und "DeleteObject(hBitmap)" in die Funktion DrawItem() eingebaut. Na immerhin läuft es jetzt schon 2,5 Minuten ohne Probleme :) Aber nach 2,5 Minuten kommt das Grauen wieder...

gruss, michbach
 
Jetzt bins ich nochmal. Jetzt hab ich hdca, hdcMem u. hBitmap global deklariert und wie schon gesagt alle in der Funktion DrawItem zum Schluss deleted und jetzt scheint es zu funktionieren. Ist zumindest schon mal 30 Minuten ohne Probleme gelaufen :)

Danke und gruss, michbach
 

Neue Beiträge

Zurück