[VC++6] Malowanie obszaru okna

0

Witam... pisze program w ktorym okno ma niestandardowy wyglad. I narysowanie obszaru okna powierzylem funkcji do ktorej przekazuje uchwyt okna. Funkcja pobiera uchwyt kontekstu malowania i robi pare dupereli (GetDC i ReleaseDC). Nastepnie obslugujac komunikat WM_PAINT pisze w oknie tekst. Wszystko do tej pory wydaje sie w porzadku. Gdy przesuwam okno poza ekran to tekst wyswietlany podczas obslugi WM_PAINT znika :/. Przerobilem program tak ze malowanie okna nie bylo powierzone funkcji lecz bylo wykonywane w trakcie obslugi komunikatu WM_PAINT, i problem zniknal... Jednak takie rozwiazanie mnie nie zadowala, nie chce umieszczac tyle kodu w obsludze WM_PAINT... co robie zle i jak to naprawic ?

0

w obsludze tego zdazenia mozna zrobic wiele, najlepiej (i najtrudniej) jest odswiezac tylko zamazane kawalki, przy pomocy regionow itd, ale sa tez proste rozwiazania np.

Jesli twoje okno jest robione na podstawie jkaiejs bitmapki to:

		case WM_PAINT:
			{
				PAINTSTRUCT PaintStruct = {0};
				HDC hDC = NULL;
				BITMAP bBitmap = {0};
				GetObject(g_hBitmapSkin, sizeof(BITMAP), &bBitmap);
				hDC = BeginPaint(hWnd, &PaintStruct);
					BitBlt(hDC, 0, 0, bBitmap.bmWidth, 
						   bBitmap.bmHeight, g_hMemDC, 0, 0, SRCCOPY);
				EndPaint(hWnd, &PaintStruct);
			}

lub jesli np uzywasz DX lub OGL

		case WM_PAINT:
			{
				FlipBuffer();
			}

g_hBitmapSkin to zmienna globalna pod ktora msz bitmape okna

flip buffer to funckja ktora wkleja ponownie na powierzchnie glowna grafike (ale to juz zalezy od tego jak masz napisany program...)

Natomiast problem z tekstem, podejrzewam ze tekst wyswietlasz gdzies osobno, poza WM_PAINT i kiedy on to odswieza bierze tylko bitmapke ale bez tekstu na niej...

0

rzerobilem program tak ze malowanie okna nie bylo powierzone funkcji lecz bylo wykonywane w trakcie obslugi komunikatu WM_PAINT, i problem zniknal... Jednak takie rozwiazanie mnie nie zadowala, nie chce umieszczac tyle kodu w obsludze WM_PAINT

No ale w czym problem??? Przecież możesz sobie zrobić funkcję rysującą oddzielnie i wywoływać ją podczas obsługi komunikatu WM_PAINT:

case WM_PAINT:
{
 PAINTSTRUCT PaintStruct = {0}; 
 HDC hDC = NULL; 
 hDC = BeginPaint(hWnd, &PaintStruct);

 this->PaintMyWindow(hDC); //<--- twoja funkcja

 EndPaint(hWnd, &PaintStruct);
}

Osobiście polecam rozwiązanie, które podał juras9 ;)

0

widze ze calkowicie sie nie rozumiemy dlatego zalaczam kod :

	case WM_PAINT:
		CreateWindowStyle ( hwnd ) ;

		hdc = BeginPaint ( hwnd , &ps ) ;
		{
			SetBkMode ( hdc , TRANSPARENT ) ;

			GetTextMetrics ( hdc , &tm ) ;
			iYChar = tm.tmAscent ;
			
			SelectObject ( hdc , hFontBold ) ;
			SetTextColor ( hdc , colorFontBold ) ;

			wsprintf ( szBuffer , TEXT ( "Witaj" ) ) ;
			TextOut ( hdc, 10 , 2 * iYChar , szBuffer , strlen ( szBuffer ) ) ;

			SelectObject ( hdc , hFontDefault ) ;
			SetTextColor ( hdc , colorFontDefault ) ;

			wsprintf ( szBuffer , TEXT ( "Witaj" ) ) ;
			TextOut ( hdc, 10 , 3 * iYChar , szBuffer , strlen ( szBuffer ) ) ;
		}
		EndPaint ( hwnd, &ps ) ;
		return 0 ;

i definicja funkcji CreateWindowStyle()

BOOL CreateWindowStyle ( HWND hwnd )
{
	if ( !hwnd ) // Jeśli uchwyt okna jest pusty kończymy wykonywanie funkcji
	{
		return FALSE ;
	}

	RECT rectWindow ;
	GetWindowRect ( hwnd , &rectWindow ) ; // Pobranie rozmiaru okna

	int iXWindow = rectWindow.right - rectWindow.left ; // Szerokość okna
	int iYWindow = rectWindow.bottom - rectWindow.top ; // Wysokość okna

	HDC hdc ;
	hdc = GetDC ( hwnd ) ; // Pobranie uchwytu kontekstu malowania
	{
		/* Rysowanie ramki wokół okna */

		HPEN hPen = CreatePen ( PS_SOLID , 1 , RGB ( 131 , 105 , 61 ) ) ; // Utworzenie pióra
		SelectObject ( hdc , hPen ) ; // Wybranie pióra w kontekscie

		SelectObject ( hdc , GetStockObject ( NULL_BRUSH ) ) ; // Ustawienie pędzla na pusty

		Rectangle ( hdc , 
					0 , 
					0 , 
					iXWindow , 
					iYWindow ) ; // Malowanie ramki

		DeleteObject ( hPen ) ; // Usuwanie pędzla

		/* Rysowanie paska tytułowego */

		hPen = CreatePen ( PS_SOLID , 1 , RGB ( 248 , 203 , 164 ) ) ; // Utworzenie pióra
		SelectObject ( hdc , hPen ) ; // Wybranie pióra w kontekscie

		// Malowanie lewej i górnej lini
		MoveToEx ( hdc , 1   , 1 , NULL ) ;
		LineTo   ( hdc , 1   , 14 ) ;
		MoveToEx ( hdc , 1   , 1 , NULL ) ;
		LineTo   ( hdc , ( iXWindow - 2 ) , 1 ) ;

		DeleteObject ( hPen ) ; // Usuwanie pędzla

		hPen = CreatePen ( PS_SOLID , 1 , RGB ( 160 , 93 , 39 ) ) ; // Utworzenie pióra
		SelectObject ( hdc , hPen ) ; // Wybranie pióra w kontekscie

		// Malowanie prawej i dolnej lini
		MoveToEx ( hdc , ( iXWindow - 2 ) , 1 , NULL ) ;
		LineTo   ( hdc , ( iXWindow - 2 ) , 15 ) ;
		MoveToEx ( hdc , 1   , 14 , NULL ) ;
		LineTo   ( hdc , ( iXWindow - 2 ) , 14 ) ;

		DeleteObject ( hPen ) ; // Usuwanie pędzla

		// Wyświetlanie gradientu paska tytulowego i gradientu tla okna
		HINSTANCE hInstance = ( HINSTANCE ) GetWindowLong ( hwnd , GWL_HINSTANCE ) ;
		HBITMAP hBitmap ;

		HDC hdcImage ;
		hdcImage = CreateCompatibleDC ( hdc ) ;
		{
			hBitmap = LoadBitmap ( hInstance, TEXT ( "TitleBar" ) ) ;
			SelectObject ( hdcImage , hBitmap ) ;
			StretchBlt ( hdc , 2, 2, ( iXWindow - 4 ) , 12, hdcImage , 0 , 0 , 1 , 12 , SRCCOPY ) ;
			hBitmap = LoadBitmap ( hInstance, TEXT ( "WindowGradient" ) ) ;
			SelectObject ( hdcImage , hBitmap ) ;
			StretchBlt ( hdc , 1, 15, ( iXWindow - 2 ) , 115, hdcImage , 0 , 0 , 1 , 100 , SRCCOPY ) ;
		}
		DeleteDC ( hdc ) ;
	}
	ReleaseDC ( hwnd , hdc ) ;

	return TRUE ;
}

Aha i nie chce wykonywac wszystkich czynnosci rysujacych w tej funkcji, wyswietlanie tekstu chce zrobic normalnie podczas obslugi komunikatu WM_PAINT tak jak jest na gorze w kodzie. Zauwazylem jeszcze jedna rzecz, gdy przesuwam okno poza ekran to tekst nie znika ale gdy okno ponownie wsuwam na ekran to tekst znika. Teraz gdy okno zminimalizuje i z powrotem przywroce tekst ponownie sie pojawia :/ pomotane to, przydalo by sie lepiej poznac mechanizm odswiezania okna, ale przeczytalem o tym wszystko co sie dalo...

0

Dobra, posluchalem sie was i zrobilem obsluge WM_PAINT w jednej funkcji i nawet dobrze to dziala, myslalem ze bedzie mi trudniej sie poslugiwac danymi ale nie jest lepiej niz myslalem :P

A co do tego bledu to chyba wiem w czym byl problem, w funkcji rysujacej tworzylem kontekst "hdc" i pozniej kontekst kompatybilny "hdcImage" ale przy usuwaniu usunalem dwa razy kontekst "hdc" zas "hdcImage" pozostawal nie usuniety. Być może to było powodem, ale nie chce mi sie tego sprawdzać :P

UPDATE : Jednak sprawdzilem, lepiej wiedziec :P No i jednak to nie tego wina...

0

Witam, nie chcę zakładać nowego wątku więc piszę tutaj.
Niedawno zacząłem programować w VC++ (zaznaczam że z c++ w trybie textowym mam już do czynienia ponad rok więc i proceduralne i obiektowe już nieco znam). Chę narysować na formie okna jakąś figurę (np kreskę) i nie wiem za bardzo od czego zacząć. Wrzucałem już rysowanie różnych firur do zdarzenia OnPaint głównej formy, ale jak próbowałem te same procedury włożyć do np. obsługi naciśnięcia przycisku, to już nie działało. W skrócie chodzi o to, że jak np klikne na przycisk, to na formie narysowana zostanie np kreska. Poświęciłem już cały dzień na znalezienie odpowiedzi, ale nic konkretnego nie wyszukałem. Program ten muszę oddać na zaliczenie kursu, zależy mi więc bardzo. Bardzo proszę pomóżcie, bo już nie wiem co powinienem zrobić.

0

dooh, dla początkujących (czyli dla Ciebie) i starych pryków (jak ja) polecam gotową klasę która ułatwia zabawę w okienka
(vc++6) http://rapidshare.de/files/20352419/gui.zip.html
takie custom CWindow - malutki wycinek z aurory.

Cała sprawa polega na pamiętaniu okna w dodatkowej bitmapie,
wszelkie funkcje graficzne rysują na oknie i na tej bitmape, więc w WM_PAINT wystarczy bitblt().

Aby narysować kreskę robisz tylko Line(...) albo LineTo(...), a klasa za Ciebie robi resztę.
Okręgi, kwadraty i inne bajery trzeba sobie samemu dopisać

0

Dziękuję za odzew. Jednak jestem bardziej zielony niż myślałem :/ . Próbowałem zdziałać coś z tą klasą którą mi poleciłeś, ale nie za bardzo wiem o co chodzi. Podpowiedz proszę jak tego używać np. dla jakiegoś zdarzenia (co gdzie wpisać). Wiem, brzmi to całkiem laicko, jednak od czegoś trzeba zacząć. Byłbym bardzo wdzięczny za wszelkie wskazówki.

1 użytkowników online, w tym zalogowanych: 0, gości: 1