TnmpThumbView – Designer-Crash beim Platzieren der Komponente

Für Probleme bezüglich Grafik, Audio, GL, ACS, ...
Antworten
Nora Madeleine
Beiträge: 7
Registriert: Mo 5. Jan 2026, 16:44
OS, Lazarus, FPC: Linux Lazarus (L 4.4.0 FPC 3.2.2)
CPU-Target: AMD

TnmpThumbView – Designer-Crash beim Platzieren der Komponente

Beitrag von Nora Madeleine »

FIX: TnmpThumbView – Designer-Crash beim Platzieren der Komponente

TnmpThumbView – Designer-Crash beim Platzieren der Komponente (Canvas.TextHeight ohne Handle)

Beschreibung des Problems
-------------------------
Beim Platzieren meiner Komponente TnmpThumbView im Lazarus-Designer kam es zu folgendem Fehler:

Control "nmpThumbView1" has no parent window.
TWinControl.CreateWnd ... ERROR WndParent=0
Canvas.TextHeight → HandleNeeded → CreateWnd

Der Designer brach sofort ab mit:
"Fehler beim Verschieben der Komponente TnmpThumbView…"

Zur Laufzeit funktionierte die Komponente einwandfrei. Der Fehler trat ausschließlich beim Erzeugen im Designer auf.


Ursache
-------
Der Lazarus-Designer erzeugt Komponenten in mehreren Schritten:

1. Instanz wird erstellt
2. Bounds werden gesetzt
3. Resize wird aufgerufen
4. UpdateScrollBar wird aufgerufen
5. CalcLayoutPerfectFit wird aufgerufen
6. ABER: das Fensterhandle existiert zu diesem Zeitpunkt noch nicht

In meiner Komponente wurden jedoch in CalcLayoutPerfectFit und Paint folgende Canvas-Operationen ausgeführt:

- Canvas.Font.Assign(...)
- Canvas.TextHeight(...)
- Canvas.TextWidth(...)
- Canvas.StretchDraw(...)

Diese Operationen benötigen ein gültiges Fensterhandle. Da der Designer das Handle erst später erzeugt, führte das zu einem Crash.


Fix
---
Ich habe die Komponente design-sicher gemacht, indem ich Canvas-Zugriffe blockiere, solange:

- csDesigning in ComponentState ODER
- not HandleAllocated

gilt.

Fix in CalcLayoutPerfectFit (kompletter Block):

if (csDesigning in ComponentState) or (not HandleAllocated) then
begin
TotalWidth := ClientWidth - FScrollBarWidth - (FThumbSpacing * 2);

Cols := TotalWidth div (FThumbWidth + FThumbSpacing);
if Cols < 1 then
Cols := 1;

AvailableWidth := TotalWidth - (Cols - 1) * FThumbSpacing;
ThumbWidthEff := AvailableWidth div Cols;

CaptionHeight := 20; // feste Höhe im Designer
Exit;
end;


Fix in UpdateScrollBar:

if (csDesigning in ComponentState) or (not HandleAllocated) then Exit;


Fix in Resize:

if (csDesigning in ComponentState) or (not HandleAllocated) then Exit;


Fix in Paint:

if not HandleAllocated then Exit;


Ergebnis
--------
- Die Komponente lässt sich wieder problemlos im Designer platzieren
- Keine Canvas-Exceptions mehr
- Dummy-Thumbnails werden wieder nebeneinander angezeigt
- Laufzeitverhalten unverändert
- Komponente ist jetzt vollständig design-sicher


Hinweis
-------
Der Fix ist unabhängig von Lazarus-Version und GTK-Version.

Getestet unter:
- Lazarus 4.2 und 4.4
- Linux Mint 21.x und Mint 22 „Tera“
- GTK2

Wenn jemand denselben Fehler hat:
Canvas niemals benutzen, bevor das Handle existiert. Das gilt besonders für TextHeight, TextWidth, Font.Assign, StretchDraw usw.
Zuletzt geändert von Nora Madeleine am Sa 10. Jan 2026, 12:06, insgesamt 1-mal geändert.

wp_xyz
Beiträge: 5343
Registriert: Fr 8. Apr 2011, 09:01

Re: TnmpThumbView – Designer-Crash beim Platzieren der Komponente

Beitrag von wp_xyz »

Nora Madeleine hat geschrieben: Do 8. Jan 2026, 17:18 Canvas niemals benutzen, bevor das Handle existiert. Das gilt besonders für TextHeight, TextWidth, Font.Assign, StretchDraw usw.
Genau. Als Ausweg kann man ein temporäres Bitmap erzeugen, dessen Canvas den gewünschten Font zuweisen und dann Bitmap.Canvas.TextHeight und Bitmap.Canvas.TextWidth verwenden.

Antworten