PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : WM_PAINT Problem


Kennung Eins
2004-06-16, 21:18:07
Ich hab hier ein kleines Problem.
(was auch sonst :D )

Eine kurze Beschreibung, was ich will:
Ich lade ein Bitmap (LoadImage), dies bildet den Hintergrund eines CreateWindowEx-Fensters. (Dann ist da noch eine Region, die eine lustige Form definiert)
Auf dieses Grund-Fenster will ich ein paar kleine Bilder (.bmp) legen:
Ebenfalls mittels loadimage laden - nun mache ich diese kleinen Bilder Transparent (Punkt unten links definiert transparente Farbe, dann über BitBlt mit SRCAND und SRCPAINT) und klebe die auf das Hintergrundbild.

Damit sollen Buttons definiert werden (ich will keine CreateWindow-Standard-Buttons nutzen), die bei einem Klick ihr Aussehen verändern.

Ich fange also bei einem klick in das Fenster nun die Koordinaten ab und schaue in einer Liste nach, ob in diesen Koordinaten ein Button liegt. Dann soll das neue Bild angezeigt werden, was sozusagen den "button pressed"-Status anzeigt.

Jetzt das Problem:
In meiner WM_PAINT-Messageschleife lasse ich nun das zweite Bild malen. Doch dieses zweite Bild wird NICHT direkt nach dem Klick angezeigt, sondern erst, wenn das Fenster neu gezeichnet werden muß (i.e. Fenster in Hintergrund und dann wieder in Vordergrund).
Das heißt, ich müsste immer erst mein Fenster verstecken und wieder vorholen, damit ich meine Änderung (Button drücken) auch wirklich sehe.

Wenn ich jetzt UpdateWindow oder RedrawWindow oder einfach nur Sendmessage(hwnd,WM_PAINT,0,0) mache, hilft dies nichts! Das Fenster wird einfach nicht geupdated ....


kann mir jemand versuchen zu erklären, warum das nicht funktioniert? Warum kann ich kein manuelles WM_Paint aufrufen? Wie kriege ich diese Änderung sichtbar?

Ich hoffe da hat jemand Ahnung ... *hoff*

Danke im Vorraus!

D-Swat
2004-06-16, 22:50:05
Hast du es schonmal mit InvalidateRect probiert?

Kennung Eins
2004-06-16, 23:53:20
Also ein invalidateRect hab ich noch nicht, aber ein invalidateRgn, was ja die gleiche Wirkung haben sollte ... oder?
Ich hab im WM_LBUTTONDOWN meine toggleimg-Funktion aufgerufen - diese ruft folgendes auf:

// invalidateRgn(h_wnd,hRegion1,false);
// Sendmessage(h_wnd,WM_PAINT,0,0);
// RedrawWindow(h_wnd,0,hregion1,RDW_UPDATENOW);
// UpdateWindow(h_wnd);

Keins davon funzt, wenn es aktiv ist. :(

Obligaron
2004-06-17, 09:10:11
CRect ClientRect;
this->GetClientRect(ClientRect);
::RedrawWindow(this->m_hWnd,ClientRect,NULL,RDW_ERASE|RDW_UPDATENOW|RDW_INVALIDATE);

Bei mir hat das so funktioniert. Hab aber MFC benützt und nur die Windows API aufgerufen.

MfG,
Obligaron

Kennung Eins
2004-06-17, 23:47:08
ui geil, mit
GetClientRect(h_wnd,t_rect);
RedrawWindow(h_wnd,@t_rect,0,RDW_ERASE or RDW_UPDATENOW or RDW_INVALIDATE);
funktioniert es!
Aber dann flackert immer kurz mein Fenster auf. (Wohl weil er es komplett löscht und dann wieder neu zeichnet?)

Danke soweit erstmal :)

Kennung Eins
2004-06-18, 19:14:00
mäh jetzt muß ich wohl doch noch so eine art double-buffer implementieren, jeder klick flackert wie sau. Mist.

RDW_NOERASE anstatt RDW_ERASE hilft schonmal ein bisschen, aber es flackert noch immer ...

gibts da noch eine bessere Möglichkeit als doublebuffering?

Demirug
2004-06-18, 19:55:37
WM_ERASEBKGND bzw OnEraseBkgnd (MFC) bearbeiten und dort einfach nichts tun.

Allerdings musst du dann in WM_PAINT dafür sorgen das wirklich die gesamte Fläche gezeichnet wird.

Kennung Eins
2004-06-18, 20:26:19
Aber wenn ich RDW_NOERASE nehme, sollte er doch garnicht den Background neu zeichnen (was er anscheinend ja auch nicht macht: mit RDW_ERASE wurde mein Fenster für ne Millisekunde weiß und dann das Bild neu gezeichnet [also der Background gelöscht == WM_ERASEBKGND], doch mit NOERASE malt er einfach das Bild nochmal neu, kein weißes Flackern. Quasi wie ohne VSYNC.) oder?

Demirug
2004-06-18, 21:21:27
Also von RedrawWindow würde ich für diesen Zweg die Finger weglassen. Es ist bei einer Windows Applikation völlig unmöglich zu verhindern das Invalidates (die dann auch ein WM_ERASEBKGND auslössen) ausgeführt werden.

Der übliche Weg um flackern zu verhindern ist daher immer das abfangen von WM_ERASEBKGND und am besten noch das Zeichnen über einen Bitmap als Zwischenbuffer zu erledigen.

Und immer wenn sich was verändert einen InvalidateRect ausführen.

Kennung Eins
2004-06-18, 23:45:23
also doch dblbuffering ... na jut. danke erstmal!
Jetzt muß ich nur noch rausrkiegen, an welcher stelle in meinem Programm ich in ein Bild male. Bei den vielen SelectObjects ...

BTW: Was ist der Unterschied zwischen RedrawWindow(blah, RDW_INVALIDATE) und InvaliateRect?