Bereich eines Control neu zeichnen: Invalidate, Paint usw.

Für Fragen von Einsteigern und Programmieranfängern...
Antworten
Martin V
Beiträge: 142
Registriert: Sa 30. Jan 2010, 19:35
OS, Lazarus, FPC: Linux64, Wiindows32, MacOS, Lazarus 1.8.2
CPU-Target: xxBit

Bereich eines Control neu zeichnen: Invalidate, Paint usw.

Beitrag von Martin V »

Auf den ersten Blick hört sich meine Frage banal an, aber ich sitze jetzt seit 2 Tagen an diesem Problem und bin kein Lazarus-Anfänger mehr.
Mein Problem trifft nur bei MacOS (Carbon) auf und ich weiß, dass man bei MacOS alle Zeichenoperationen innerhalb eines OnPaint Events bzw. innerhalb der überschriebenen Paint Prozedur unter dem "inherited paint" machen muß. Bei anderen OS funktioniert das Zeichnen auch außerhalb, es wird aber trotzdem empfohlen, es nur im OnPaint zu machen.

Erstes Problem: Wenn das System durch entsprechende durch die lcl ausgelöste Events Paint aufruft, und laut Canvas.Cliprect nur ein Teil neu gezeichnet wird, dann wird an der Stelle, wo OnPaint neu zeichnen soll, zwar ein weißes Rechteck gezeichnet (also der alte Inhalt gelöscht), aber es erscheint nichts vom neu gezeichneten, obwohl innerhalb des OnPaint Events gezeichnet wird und der Code definitiv ausgeführt wird. Nur bei bestimmten Events, z. B. Resize, wo sich Cliprect über den gesamten Bereich des Controls erstreckt, und möglicherweise noch andere, mir nicht bekannte Bedingungen erfüllt sind, hat OnPaint auch die gewünschte Wirkung.

Zweites Problem: Wenn ich aus meinem Programm heraus neu zeichnen möchte und selbst also den OnPaint Event anstoßen möchte, dann hat der Programmcode in OnPaint nur dann eine Wirkung, wenn er über Invalidate angestoßen wurde. RePaint und Update wirkt nicht. Das wäre jetzt kein Problem, weil Invalidate ja klappt, aber Invalidate löscht wieder den ganzen Control Inhalt, auch wenn ich vor dem Invalidate den Canvas.Cliprect setze, bzw. ignoriert den Cliprect.

Kann es sein, dass ich irgendwelche Properties setzen muß, damit es klappt, oder statt Canvas.Cliprect den neu zu zeichnenden Bereich anders setzen muß? ControlStyle bsOpaque habe ich auch ausprobiert, ohne Wirkung. Es wäre viel geholfen, wenn ich verhindern könnte, dass er bei jedem Paint Event erst den ganzen Control-Inhalt mit weißer Farbe bzw. mit der Farbe Control.Color überschreibt und somit löscht.

Mein Control ist ein Editor mit einem Textcursor (lclintf.tCaret), der mit jedem Cursorblinken ein OnPaint Event für einen kleinen Bereich losfeuert (bei Windows funktioniert das anders). Das ist echt wichtig, dass nicht zweimal pro Sekunde der ganze Inhalt neu geschrieben wird... Ich habe auch schon versucht, aus SynEdit (IDE Editor) etwas herauszufinden, der Programmcode ist aber derart riesig, dass das zu aufwendig wäre.

Auf anderen OS als MacOS könnt ihr das Verhalten nicht reproduzieren. Evtl. hilft uns aber die Theorie über das Zeichnen im OnPaint Event weiter, deswegen habe ich die Frage nicht in ein OS-spezifisches Unterforum geschrieben.

Martin V
Beiträge: 142
Registriert: Sa 30. Jan 2010, 19:35
OS, Lazarus, FPC: Linux64, Wiindows32, MacOS, Lazarus 1.8.2
CPU-Target: xxBit

Re: Bereich eines Control neu zeichnen: Invalidate, Paint us

Beitrag von Martin V »

Ich habe jetzt herausgefunden, dass man statt Invalidate schreiben kann:

Code: Alles auswählen

InvalidateRect (Handle, @Rect, boolean_Hintergrund_Loeschen)


(Ich hatte das schon probiert, wegen eines anderen Fehlers hatte es aber dann nicht funktioniert.)

Dass ich in der von lclintf.tCaret angestoßenen Paint Prozedur nichts zeichnen kann, scheint wohl ein Bug zu sein. Ich werde erst einmal einen Hack schreiben, damit das Programm wieder geht, indem ich eine Message poste und dann erneut ein InvalidateRect anstoße. Das sollte gehen. Wenn keiner eine schlauere Antwort hat, werde ich nach einigen Tagen dann das als Fehler im Bugtracker melden.

Antworten