[WinAPI] Rysowanie poza oknem

0

Cześć,

mam parę pytań do swojego programu rysującego po ekranie. Przechwytuje on myszkę za pomocą SetCapture() i ustawia kontekst urządzenia na cały ekran (czyli GetDC(NULL)).

  1. Przy wyłączaniu programu zostają mi śmieci poza oknem. Jak się ich pozbyć? http://img16.imageshack.us/img16/8506/80525544.jpg
  2. Jak zrobić tak, aby nie trzeba było rozpoczynać rysowania od formularza, żeby narysować coś poza oknem?

Pozdrawiam i dzięki za pomoc.

0

Hi,

  1. InvalidateRect(0, 0, TRUE) działa na wszystkie widoczne okna, przynajmniej pod XP.

  2. Albo zrób SetCapture zaraz po otwarciu okna, albo jako pierwsze otwórz dodatkowe okno o rozmiarze aktualnego pulpitu lub o wielkości obszaru roboczego (SPI_GETWORKAREA), ale bez captiona, bordera i ze stylem WS_EX_TOOLWINDOW, które będzie "zjadało" WM_ERASEBKGND oraz WM_PAINT (w tym celu, by nie było widać że takie okno jest otwarte).

To dodatkowe okno rozwiąże też pierwszy problem.

0

bardzo fajny pomysł z tym oknem :)

użyję do tego WS_POPUP.

a te "zjadanie" tych komunikatów to miałeś na myśli coś takiego? (bo w sumie takie coś działa)

case WM_PAINT :
	return 0;
case WM_ERASEBKGND :
	return 0;
0

WM_PAINT nie można w taki sposób ignorować bo zarżniesz procesor. Musisz opróżnić stos funkcjami BeginPaint i EndPaint. A co do WM_ERASEBKGND, to zwróć wartość niezerową i zerknij do dokumentacji dlaczego.

0

ok, wyczytałem, że musi zwrócić niezerową żeby wymazać okno.

a żeby opróżnić stos to po prostu ma być puste pole między BeginPaint i EndPaint? Czy jak się opróżnia stos? Pierwsze słyszę o tej metodzie w takim kontekście.

case WM_PAINT :
	PAINTSTRUCT ps;
	hdc = BeginPaint( hWnd, &ps );

	EndPaint( hWnd, &ps );
	break;

tak przy okazji zauważyłem, że można się obejść bez tych komunikatów dając po prostu tło hbrBackground na NULL (choć nie wiem czy takie coś jest poprawne).

0

Stos gdi, czy też lista, tablica - można to dowolnie nazwać nie znając dokładnej organizacji - jest to obszar pamieci gdzie system zapisuje koordynaty wycinków okna które wymagają odrysowania. Jeżeli przesuniesz okno A nad oknem B do system dopisze tam jedną lub dwie pozycje (zależnie czy ruch był ukośny czy nie) i będzie tak długo wysyłał WM_PAINT, póki nie wywołasz BeginPaint/EndPaint. Przypisanie zmiennej hdc nie jest ani obowiązkowe ani potrzebne, jest nawet zbyteczne bo to samo hdc jest w paintstruct.
Pole hbrBackground wypełniasz wtedy, gdy nie chcesz obsługiwać komunikatu WM_ERASEBKGND, ale przekazujesz go do DefWindowProc - wtedy ta funkcja pobiera hbrBackground i wypełnia nim cały obszar okna, co bardzo często jest niewskazane bo wszystko miga. Jeżeli zwrócisz zero, to system to zapamięta i będzie się "domagał" wymazania podczas kolejnego WM_PAINT, ustawiając paintstruct.fErase.

Możesz usunać obsługę WM_ERASEBKGND i ustawić hbrBackground na NULL, ale będziesz musiał zarejestrować dodatkową klasę okna, co opłaca się dopiero gdy używasz jednej klasy okna z wieloma różnymi WndProc (flaga GWL_WNDPROC).

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