Eigenschaften einer zur Laufzeit erzeugten Form innerhalb eines Packages

Rund um die LCL und andere Komponenten
Antworten
EUP
Beiträge: 19
Registriert: Fr 18. Jul 2014, 23:07

Eigenschaften einer zur Laufzeit erzeugten Form innerhalb eines Packages

Beitrag von EUP »

Hallo,

habe hier einen mehr kosmetischen Nebenkriegsschauplatz, technisch funktioniert im Prinzip alles.

Umgebung: Lazarus 4.2 unter Kubuntu 25.04.

Aus einem Package heraus wird zur Laufzeit eine Form erstellt und aufgerufen.

Nun möchte ich dieser Form bestimmte Eigenschaften zuweisen, was jedoch nur teilweise funktioniert.

Zuweisung der Eigenschaften per

Code: Alles auswählen

  ...

  inherited CreateNew(AOwner);

  Self.Caption := fCap;
  Self.Width := 647;
  Self.Height := 544;
  Self.Position := poDesktopCenter;

  Self.BorderStyle := bsDialog; //nicht alle möglichen Eigenschaften werden unterstützt
  Self.BorderIcons := [biSystemMenu]; //hat überhaupt keinen Einfluß auf das Resultat
  Self.Icon.LoadFromResourceName(HInstance, 'PIP_16'); //wird nicht umgesetzt, es bleibt beim üblichen Tatzen-Icon

  ...
Es gibt keinerlei Fehlermeldungen.

Was mache ich falsch?

Dank schon mal im Voraus.

Benutzeravatar
theo
Beiträge: 11029
Registriert: Mo 11. Sep 2006, 19:01

Re: Eigenschaften einer zur Laufzeit erzeugten Form innerhalb eines Packages

Beitrag von theo »

Unter Linux ist es halt so, dass diese Dinge dem Fenstermanager unterstellt sind und nicht direkt dem GUI-Toolkit.
https://de.wikipedia.org/wiki/Fenstermanager
https://de.wikipedia.org/wiki/GUI-Toolkit
Wenn der Fenstermanager gewisse Dinge nicht zulässt, dann wird es schwierig.
Bei mir haben z.B. auch Änderungen im Objektinspektor bei den BorderIcons keinen Effekt in der Anwendung.

P.S. Das Icon lädt eigentlich schon, wird aber durch "Self.BorderStyle := bsDialog;" ausgehebelt.
Lass diese Zeile weg, oder setze bsSingle, dann kommt das Icon.

Mathias
Beiträge: 7068
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Eigenschaften einer zur Laufzeit erzeugten Form innerhalb eines Packages

Beitrag von Mathias »

theo hat geschrieben: So 19. Okt 2025, 11:59 Unter Linux ist es halt so, dass diese Dinge dem Fenstermanager unterstellt sind und nicht direkt dem GUI-Toolkit.
https://de.wikipedia.org/wiki/Fenstermanager
https://de.wikipedia.org/wiki/GUI-Toolkit
Wenn der Fenstermanager gewisse Dinge nicht zulässt, dann wird es schwierig.
Bei mir haben z.B. auch Änderungen im Objektinspektor bei den BorderIcons keinen Effekt in der Anwendung.
Genau aus diesem Grund greifen viele ToolKits wie GTK4 in eigene Trickkisten.
Die zeichnen nackte Fenster und setzen dann ihre System-Buttons selbst hinein.
Auch bei Chrome sieht man das gut, da sehen die Ikonen sogar anders aus, aus die von Fenster-Manager.
Wen man dies Effekte extrem gut sehen will, dann installiert man einen veralteten Fenstermanager wie FVWM2,

Theoretisch wäre dies mit der LCL auch zu machen, aber dies ist mit sehr viel Know-how und Arbeit verbunden.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Warf
Beiträge: 2215
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64

Re: Eigenschaften einer zur Laufzeit erzeugten Form innerhalb eines Packages

Beitrag von Warf »

Ein paar Fragen kommen da auf:
1. Welches Widgetset wird verwendet? GTK2, QT5, QT6, irgendwas exotisches? Nicht alle Funktionen werden durch alle Widgetsets gleichermaßen unterstützt.
2. Wie erstellst du die Form? Forms werden normalerweise über Application.CreateForm(Klasse, Variable) erzeugt. Wenn es kein SplashScreen oder die Main Form ist sollte das zwar keinen unterschied machen, aber man weiß ja nie.
3. Funktioniert das denn wenn die Form nicht Teil des Packages ist? Also wenn du die Unit einfach direkt ins Projekt ziehst?
4. Hast du irgendwelche speziellen Einstellungen im Package?

EUP
Beiträge: 19
Registriert: Fr 18. Jul 2014, 23:07

Re: Eigenschaften einer zur Laufzeit erzeugten Form innerhalb eines Packages

Beitrag von EUP »

Hallo,

eine Menge Antworten, vielen Dank für die Mühen.

Das Icon sehe ich jetzt. Wenn der Min- & Max-Button nicht auszublenden ist, dann ist es halt so, nicht optimal, aber damit kann ich leben.

@theo

P.S. Das Icon lädt eigentlich schon, wird aber durch "Self.BorderStyle := bsDialog;" ausgehebelt.
Lass diese Zeile weg, oder setze bsSingle, dann kommt das Icon.

Stimmt, klappt - Danke, da hätte ich wirklich selber drauf kommen können.

Aber wieso zeigt er bei bsDialog das Tatzen-Icon? Zu erwarten wäre dann gar kein Icon.


@Warf

Welches Widgetset wird verwendet?

Da habe ich keinerlei Änderung an der Voreinstellung vorgenommen, also GTK2.

Wie erstellst du die Form?

Dynamisch zur Laufzeit, also nicht über den Form-Editor.

In Kurzform

Code: Alles auswählen

type
    XCForm = class(TForm)

    public
        constructor CreateNew(AOwner: TComponent; Dummy: Integer = 0); override;
        procedure SetPanCol(p: TPanel; oParent: TComponent; iTop, iLeft, iCol, iTab: Integer; sHint: string);
        procedure PanOnClick(Sender: TObject);
        procedure btnOKClick(Sender: TObject);
        procedure btnCancelClick(Sender: TObject);
    end;

...

Code: Alles auswählen

{ XCForm }

constructor XCForm.CreateNew(AOwner: TComponent; Dummy: Integer = 0);
var
  fCap, fFrame: string;

  btnOk, btnCancel: TButton;
  Shape1: TShape;
  GroupBox1: TGroupBox;
  txName, txRGB: TEdit;

  panWahl,
  panSnow, panFloralWhite, panLavenderBlush, // usw. gekürzt, sind über 100


begin
  if FormCaption = '' then
    fCap := 'Farbauswahl'
  else
    fCap := FormCaption;

  if FrameCaption = '' then
    fFrame := 'Auswahl'
  else
    fFrame := FrameCaption;

  DialogSelectedName := '';
  DialogSelectedColor := -1;


  inherited CreateNew(AOwner);

  Self.Caption := fCap;
  Self.Width := 647;
  Self.Height := 544;
  Self.Position := poDesktopCenter;
  Self.BorderStyle := bsSingle; 
  Self.BorderIcons := [biSystemMenu]; 
  Self.Icon.LoadFromResourceName(HInstance, 'PIP_16'); 


  //btnCancel
  btnCancel := TButton.Create(Self);
  btnCancel.Parent := Self;

  if FormBtnOKLeft = false then
    btnCancel.Left := 392
  else
    btnCancel.Left := 520;

  btnCancel.Height := 40;
  btnCancel.Width := 120;
  btnCancel.Top := 488;
  btnCancel.Caption := 'Abbrechen';
  btnCancel.Cancel := true;
  btnCancel.TabOrder := 1;
  btnCancel.OnClick := @btnCancelClick;


  //btnOK
  btnOk := TButton.Create(Self);
  btnOk.Parent := Self;

  if FormBtnOKLeft = false then
    btnOk.Left := 520
  else
    btnOk.Left := 392;

  btnOk.Height := 40;
  btnOk.Width := 120;
  btnOk.Top := 488;
  btnOk.Caption := '&Ok';
  btnOk.Default := true;
  btnOk.OnClick := @btnOKClick;
  btnOk.TabOrder := 0;


  //TShape
  Shape1 := TShape.Create(Self);
  Shape1.Parent := Self;
  Shape1.Left := 8;
  Shape1.Height := 2;
  Shape1.Top := 472;
  Shape1.Width := 632;


  //GroupBox1
  GroupBox1 := TGroupBox.Create(Self);
  GroupBox1.Parent := Self;
  GroupBox1.Left := 8;
  GroupBox1.Height := 77;
  GroupBox1.Top := 379;
  GroupBox1.Width := 632;
  GroupBox1.Caption := fFrame;
  GroupBox1.TabOrder := 142;


  //txName
  txname := TEdit.Create(GroupBox1);
  txName.Parent := GroupBox1;
  txName.Left := 120;
  txName.Height := 35;
  txName.Top := 10;
  txName.Width := 328;
  txName.Alignment := taCenter;
  txName.AutoSize := False;
  txName.ReadOnly := True;
  txName.TabOrder := 0;
  oName := txName;


  //txRGB
  txRGB := TEdit.Create(GroupBox1);
  txRGB.Parent := GroupBox1;
  txRGB.Left := 464;
  txRGB.Height := 35;
  txRGB.Top := 10;
  txRGB.Width := 160;
  txRGB.Alignment := taCenter;
  txRGB.AutoSize := False;
  txRGB.ReadOnly := True;
  txRGB.TabOrder := 1;
  oRGB := txRGB;


  //panWahl
  panWahl := TPanel.Create(GroupBox1);
  panWahl.Parent := GroupBox1;
  panWahl.Left := 8;
  panWahl.Height := 35;
  panWahl.Top := 10;
  panWahl.Width := 96;
  panWahl.BevelOuter := bvNone;
  panWahl.BorderStyle := bsSingle;
  panWahl.Color := clNone;
  panWahl.ParentBackground := False;
  panWahl.ParentColor := False;
  panWahl.ParentShowHint := False;
  panWahl.TabOrder := 2;
  oWahl := panWahl;


  //SetPanCols
  SetPanCol(panSnow, Self, 8, 8, 16448255, 2, 'Snow ($FAFAFF)');
  SetPanCol(panFloralWhite, Self, 8, 48, 15792895, 3, 'FloralWhite ($F0FAFF)');
  
  // Das kürze ich jetzt mal ab, sind über 100

end;
        
procedure XCForm.SetPanCol(p: TPanel; oParent: TComponent; iTop, iLeft, iCol, iTab: Integer; sHint: string);
begin
  p := TPanel.Create(oParent);
  p.Parent := TWinControl(oParent);
  p.Left := iLeft;
  p.Height := 32;
  p.Hint := sHint;
  p.Top := iTop;
  p.Width := 32;
  p.BevelInner := bvRaised;
  p.BevelWidth := 2;
  p.Color := iCol;
  p.ParentBackground := False;
  p.ParentColor := False;
  p.ParentShowHint := False;
  p.ShowHint := True;
  p.TabOrder := iTab;
  p.Tag := 1;
  p.OnClick := @PanOnClick;
end;

// Die Ereignisauswertung unterschlage ich jetzt mal.
Funktioniert das denn wenn die Form nicht Teil des Packages ist?

Bei der Gelegenheit stelle ich gerade fest, dass der unerwünschte Minimieren- & Maximieren Button sich auch aus der Vorlage nicht entfernen lässt, wird also wohl eine KDE-Eigenheit sein.

Hast du irgendwelche speziellen Einstellungen im Package?

Nein, eigentlich nicht.

Warf
Beiträge: 2215
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64

Re: Eigenschaften einer zur Laufzeit erzeugten Form innerhalb eines Packages

Beitrag von Warf »

Modernes KDE und GTK2 ist keine sonderlich gute Kombination. KDE ist ein QT Dekstop, das heißt GTK ist sowieso schon eher mäßig supported. Dazu kommt das GTK2 auf X11 basiert, während modernes KDE dir vermutlich Wayland aufgedrückt hat (was nicht unbedingt was schlechtes ist) und dann werden x11 Anwendungen durch den xWayland Kompatibilitätslayer ausgeführt, der weitere Inkompatibilitäten haben kann.

Das summiert sich zusammen ganz schön auf und führt dazu das einige Features von GTK2 einfach nicht richtig funktionieren. Dazu kommt das GTK2 seit 4 Jahren mittlerweile tot ist und keinerlei Updates mehr bekommt und auch Anwendungen wie KDE oder selbst xWayland weniger rücksicht auf die Kompatibilität mit GTK2 geben. Das führt dazu das mit jedem Update von KDE und Wayland GTK2 anwendungen immer schlechter funktionieren.

Das ist mir vor ein paar tagen ganz direkt aufgefallen als ich eine alte Anwendung von mir nochmal neu kompiliert hab und dinge von denen ich wusste das sie vor 5 Jahren oder so gingen jetzt nicht mehr gehen. Und das wird durch das EOL von GTK2 vermutlich jedes Jahr schlimmer.
Das mit den Borderstyles ist mir aufgefallen, aber auch ein paar sachen bezüglich Canvas zeichnen und Mausposition sowie Desktop Größenerkennung war irgendwie kaputt.

Am besten versuchst du als erstes mal obs auf QT5 oder QT6 funktioniert.

Benutzeravatar
theo
Beiträge: 11029
Registriert: Mo 11. Sep 2006, 19:01

Re: Eigenschaften einer zur Laufzeit erzeugten Form innerhalb eines Packages

Beitrag von theo »

@Warf: Ich bin auf Qt6/X11 und es ist genau das Gleiche.
Das Icon wird angezeigt, aber nicht bei bsDialog.
Die BorderIcons Einstellung hat keinen Einfluss auf die Anwendung.
Einziger Unterschied: Mit bsDialog zeigt bei mir GTK2 ein "X" Icon an und nicht das des Hauptformulars (Bild).

Ich habe mir schon lange abgewöhnt, unter Linux die Titelleiste bearbeiten zu wollen.
In der Gastro-Küche sagt man: Der Tellerrand gehört der Bedienung. :wink:
Dateianhänge
laz_xicon.png
laz_xicon.png (36.83 KiB) 475 mal betrachtet

Mathias
Beiträge: 7068
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Eigenschaften einer zur Laufzeit erzeugten Form innerhalb eines Packages

Beitrag von Mathias »

Am besten versuchst du als erstes mal obs auf QT5 oder QT6 funktioniert.
Alles hat sein vor und Nachteile.
QTx ist sicher recht Zeitgemäss, dafür hat man eine Wrapper. LCL -> QTpas -> libQTx -> X11/Wayland. Alles Zwischenschichten, wo sich Fehler einschleichen können.
Bei GTK sieht es ein wenig besser aus, dafür wird das heillos veraltete GTK2 verwendet.
Wen man zeitgemäss bleiben will, kommt GTK4 in Frage, dafür muss man auf die LCL verzichten.
Bei Windows sieht es besser aus, die LCL und die WinAPI sind ein sehr gutes Gespann.

Ich persönlich würde es am besten finden, wen Lazarus voll auf Custom-Widget setzen würde, dann ist man unabhängig von QT und GTK.
Viele andere nicht Pacsal Coder machen dies auch und machen voll auf Custom-Widget. Als Beispiel: Java, EFL-UI, Blender, Mozilla, Tk.

Was mir dabei bewusst ist, dies ist mit sehr viel Arbeit und tiefsten LCL Kenntnissen verbunden.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Warf
Beiträge: 2215
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64

Re: Eigenschaften einer zur Laufzeit erzeugten Form innerhalb eines Packages

Beitrag von Warf »

Mathias hat geschrieben: Mo 20. Okt 2025, 13:40 Ich persönlich würde es am besten finden, wen Lazarus voll auf Custom-Widget setzen würde, dann ist man unabhängig von QT und GTK.
Viele andere nicht Pacsal Coder machen dies auch und machen voll auf Custom-Widget. Als Beispiel: Java, EFL-UI, Blender, Mozilla, Tk.

Was mir dabei bewusst ist, dies ist mit sehr viel Arbeit und tiefsten LCL Kenntnissen verbunden.
Das sind aber nicht unbedingt gute Beispiele. Java ist sehr bekannt dafür das es vom "look and feel" immer sehr seltsam ist. Blender hat den Vorteil das es einge ganz eigene Grafikengine hat, das haben auch viele Spiele Engines, wo dann das UI der Engine in der Engine selbst gebaut wird. Und das Verhalten von einigen Komponenten und das die Menüführung und Workflow komplett eigen ist ist tatsächlich auch immer der größte Kritikpunkt an Blender gewesen.
Mozilla baut für Firefox was eigenes weil es HTML und CSS Stylable sein muss, was auch ganz andere Anforderungen sind. Kaum eine Website benutzt Plain Controls.

TK und EFL-UI sind einfach kleinere UI Bibliotheken und machen im grunde das gleiche wie GTK oder QT, nur mit weniger Features und auch etwas weniger Kompatibilität.
QT und GTK zu nutzen ist schon keine schlechte Idee, da die in der Linux Welt einfach sehr verbreitet sind, die System Styles verwenden und damit die quasi nativen APIs sind.
Das Problem ist eher das soweit ich weiß GTK und QT in Lazarus von einer einzelnen Person gemacht wird und zum anderen das sich nicht alle LCL Konzepte 1-1 auf diese Bibliotheken abbilden lassen (was vor allem bei GTK ein größeres Problem ist da GTK die API mit GTK3 extrem umgeworfen hat)

Wenn man was selbst Zeichnet kommt sowas wie FireMonkey in Delphi raus, das einfach extrem fremdartig aussieht auf allen systemen und sich auch nicht überall so verhält wie man es erwartet und die Systemstyles nicht unterstützt.
Selbst zeichnen ist eigentlich nur eine gute Idee wenn man große Grafische Ansprüche hat (wie Blender oder Firefox), und man sowieso nicht das System Theme verwenden will. Dafür gibt man aber Natives Aussehen und Workflow auf.

Mathias
Beiträge: 7068
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Eigenschaften einer zur Laufzeit erzeugten Form innerhalb eines Packages

Beitrag von Mathias »

Das Problem ist eher das soweit ich weiß GTK und QT in Lazarus von einer einzelnen Person gemacht wird und zum anderen das sich nicht alle LCL Konzepte 1-1 auf diese Bibliotheken abbilden lassen (was vor allem bei GTK ein größeres Problem ist da GTK die API mit GTK3 extrem umgeworfen hat)
Genau GTK3 ist schon eine Problem, bei GTK4 ist es noch viel extremer. Bei GTK4 ist sogar die ComboBox als veraltet deklariert.

Wen man das Fenster im Anhang anguckt, zeigt, das man mit GTK4 dafür andere recht schönes Sachen machen kann. Man kann eigene Elemente in die Titelleiste eines Fensters einfügen.
Dateianhänge
Bildschirmfoto vom 2025-10-20 14-19-35.png
Bildschirmfoto vom 2025-10-20 14-19-35.png (5.67 KiB) 438 mal betrachtet
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

EUP
Beiträge: 19
Registriert: Fr 18. Jul 2014, 23:07

Re: Eigenschaften einer zur Laufzeit erzeugten Form innerhalb eines Packages

Beitrag von EUP »

Hallo nochmal,

GTK2 ist sicherlich nicht aktuell, aber Vorgabe. Normalerweise ändere ich so etwas nur wenn es einen besonderen Grund gibt.

Verstehe auch spontan nicht, wieso Lazarus mit derart altem Wasser kocht.

Das Minimieren- / Maximieren-Problem habe ich gelöst.

Code: Alles auswählen

procedure XCForm.FormWindowStateChange(Sender: TObject);
begin
  if Self.WindowState <> wsNormal then begin
    Self.WindowState := wsNormal;
    Self.SetFocus;
  end;
end;
Also das Icon ist da und die Größe kann nicht mehr geändert werden.

Mit dem Ergebnis kann ich leben.

Vielen Dank allen Helfenden.

Antworten