Sign in Join
Wiki copytemporary

LCL Tips/de: what changed

Revision 0 to 1. Removed lines have a minus sign; added lines have a plus sign.

Title: LCL Tips/de

OldNewLine
1+## GUI Anwendung per Code erstellen
2+
3+Es ist möglich eine [[Overview of Free Pascal and Lazarus/de|GUI Anwendung]] (Graphical User Interface) vollständig durch Pascalcode in Lazarus zu erstellen. Alles, was von der IDE aus möglich ist, ist auch per Code umsetzbar. Die nachfolgenden Beispieldateien für die Programm- und Unitdateien (codegui.lpr und mainform.pas) können Sie als Vorlage verwenden, die Sie anpassen können. Das wichtigste ist, nicht zu vergessen die [[Parent/de|Parent]]-Eigenschaft der Komponenten festzulegen. Die Erstellung von Steuerelementen innerhalb des Formulars erfolgt am besten im Konstruktor des Formulars:
4+
5+Hauptprogrammdatei:
6+
7+``` pascal
8+program codedgui;
9+
10+{$MODE DELPHI}{$H+}
11+
12+uses
13+ Interfaces, Forms, StdCtrls,
14+ MainForm;
15+
16+var
17+ MyForm: TMyForm;
18+begin
19+ Application.Initialize;
20+ Application.CreateForm(TMyForm, MyForm);
21+ Application.Run;
22+end.
23+```
24+
25+Die Unit, die das Formular beinhaltet:
26+
27+``` pascal
28+unit mainform;
29+
30+{$MODE DELPHI}{$H+}
31+
32+interface
33+
34+uses Forms, StdCtrls;
35+
36+type
37+ TMyForm = class(TForm)
38+ public
39+ MyButton: TButton;
40+ procedure ButtonClick(ASender: TObject);
41+ constructor Create(AOwner: TComponent); override;
42+ end;
43+
44+implementation
45+
46+procedure TMyForm.ButtonClick(ASender:TObject);
47+begin
48+ Close;
49+end;
50+
51+constructor TMyForm.Create(AOwner: TComponent);
52+begin
53+ inherited Create(AOwner);
54+ //Hint: FormCreate() is called BEFORE Create() !
55+ //so You can also put this code into FormCreate()
56+ //(This is not the case when creating components ..)
57+
58+ Position := poScreenCenter;
59+ Height := 400;
60+ Width := 400;
61+
62+ VertScrollBar.Visible := False;
63+ HorzScrollBar.Visible := False;
64+
65+ MyButton := TButton.Create(Self);
66+ with MyButton do
67+ begin
68+ Height := 30;
69+ Left := 100;
70+ Top := 100;
71+ Width := 100;
72+ Caption := 'Close';
73+ OnClick := ButtonClick;
74+ Parent := Self;
75+ end;
76+
77+ // Erstellen Sie hier noch weitere Komponenten
78+end;
79+
80+end.
81+```
82+
83+## Bedienelemente manuell erzeugen ohne Overhead
84+
85+### Parent zuletzt setzen
86+
87+**Für Delphianer**: Im Gegensatz zu Delphi erlaubt die LCL beinahe alle Eigenschaften in beliebiger Reihenfolge zu setzen. Zum Beispiel unter Delphi können sie ein Bedienelement nicht ohne a parent positionieren. Die LCL erlaubt dies und dieses Feature kann benutzt werden, den Overhead zu reduzieren.
88+
89+` with TButton.Create(Form1) do begin`\
90+`   // 1. Erzeugen eines button setzt die Vorgabegröße`\
91+`   // 2. Ändern der Position. Keine Randeffekte, weil Parent=nil`\
92+`   SetBounds(10,10,Width,Height);`\
93+`   // 3. Ändern der Größe abhängig vom Thema. Noch nicht, weil Parent=nil`\
94+`   AutoSize:=true;`\
95+`   // 4. Ändern der Größe wegen AutoSize=true. Noch nicht, weil Parent=nil`\
96+`   Caption:='Ok';`\
97+`   // 5. Setzen sie Parent. Jetzt geschieht all das obige, aber in einer einzigen Aktion.`\
98+`   Parent:=Form1;`\
99+` end;`
100+
101+Wenn ein Bedienelement a Parent hat, dann werden alle Eigenschaften unverzüglich wirksam. Ohne a Parent tun viele Eigenschaften nicht mehr, als den Wert zu speichern. Und sobald the Parent gesetzt ist, wird jede Eigenschaft angewendet. Das trifft besonders für grand children zu:
102+
103+` GroupBox1:=TGroupBox.Create(Self);`\
104+` with GroupBox1 do begin`\
105+`   with TButton1.Create(Self) do begin`\
106+`     AutoSize:=true;`\
107+`     Caption:='Click me';`\
108+`     Parent:=GroupBox1;`\
109+`   end;`\
110+`   Parent:=Form1;`\
111+` end;`\
112+` Form1.Show;`
113+
114+Autosizing startet nicht bevor jeder parent eingerichtet ist und das Formular sichtbar wird.
115+
116+### Vermeiden sie eine frühe Handle Erzeugung
117+
118+Sobald das Handle eines TWinControl erzeugt ist, ändert jede Änderung einer Eigenschaft the visual thing (called the widget), sogar wenn ein Bedienelement nicht sichtbar ist. Wenn es ein Handle hat, sind Änderungen dennoch aufwändig.
119+
120+### Verwenden sie SetBounds anstelle von Left, Top, Width, Height
121+
122+Anstelle von
123+
124+` with Button1 do begin`\
125+`   Left:=10;`\
126+`   Top:=10;`\
127+`   Width:=100;`\
128+`   Height:=25;`\
129+` end;`
130+
131+verwenden sie
132+
133+` with Button1 do begin`\
134+`   SetBounds(10,10,100,25);`\
135+` end;`
136+
137+Left, Top, Width, Height rufen SetBounds auf. Und jede Änderung der Position oder Größe ruft die Neuberechnung aller sibling Bedienelemente und eventuell rekursiv die der parent und/oder der grandchild Bedienelemente auf.
138+
139+## DisableAlign / EnableAlign
140+
141+Wenn sie viele Bedienelemente positionieren, ist es eine gute Idee, die Neuberechnungvon all auto sizing, aligning, anchoring zu deaktivieren.
142+
143+` DisableAlign;`\
144+` try`\
145+`   ListBox1.Width:=ClientWidth div 3;`\
146+`   ListBox2.Width:=ClientWidth div 3;`\
147+`   ListBox3.Width:=ClientWidth div 3;`\
148+` finally`\
149+`   EnableAlign;`\
150+` end;`
151+
152+**Anmerkung**: Jeder DisableAlign Aufruf benötigt einen EnableAlign Aufruf. Zum Beispiel wenn sie DisableAlign zweimal aufrufen, müssen sie auch EnableAlign zweimal aufrufen.
153+
154+**Für Delphianer**: Dies funktioniert rekursiv. Das bedeutet, DisableAlign stoppt aligning in allen childs und grand childs.
155+
156+## Ein nicht-rechteckiges Fenster oder Steuerelement erstellen
157+
158+Sie können mit Lazarus recht einfach nicht rechteckige Fenster oder Steuerelemente erstellen. Hierzu können Sie einfach TWinControl.SetShape aufrufen, mit den sichtbaren Bereichen als ein Parameter. Hinweis: dies funktioniert für Fenster und Steuerelemente, wie TCustomForm und TCustomControl, die von TWinControl abgeleitet sind. Sie können LCLIntf-Routine SetWindowRgn aufrufen, die vollständig dem Aufruf der SetShape-Methode entspricht.
159+
160+Mit SetWindowRgn wird der Code wie folgt aussehen:
161+
162+``` pascal
163+uses LCLIntf, LCLType;
164+
165+procedure TForm1.FormCreate(Sender: TObject);
166+var
167+ MyRegion: HRGN;
168+begin
169+ MyRegion := CreateRectRgn(0, 0, 100, 100);
170+ SetWindowRgn(Handle, MyRegion, True);
171+ DeleteObject(MyRegion);
172+end;
173+```
174+
175+Nachfolg ein entsprechender Code, welcher ein, eine Ebene höheres, TRegion-Objekt verwendet, verfügbar in Lazarus 0.9.31+ (Hinweis: auch die vorherige Vorgehensweise wird in Zukunft weiterhin unterstützt werden):
176+
177+``` pascal
178+uses Graphics;
179+
180+procedure TForm1.FormCreate(Sender: TObject);
181+var
182+ MyRegion: TRegion;
183+begin
184+ MyRegion := TRegion.Create;
185+ try
186+ MyRegion.AddRectangle(0, 0, 100, 100);
187+ Self.SetShape(MyRegion);
188+ finally
189+ MyRegion.Free;
190+ end;
191+end;
192+```
193+
194+Ein Ergebnis dieses Vorgehens, bei einem Fenster auf einem Mac OS X, welches das Qt Widgetset genutzt hat, sehen Sie hier:
195+
196+<figure>
197+<img src="non_rectangular_window.png" title="non_rectangular_window.png" />
198+<figcaption>non_rectangular_window.png</figcaption>
199+</figure>
200+
201+Beachten Sie, dass SetShape auch ein TBitmap nutzen kann, um eine transparente Region zu beschreiben.
202+
203+Siehe auch:
204+
205+- [[LCL Internals|LCL_Internals#Shaped_Windows]]
206+
207+Dokumentationen:
208+
209+- <http://lazarus-ccr.sourceforge.net/docs/lcl/lclintf/setwindowrgn.html>
210+- <http://lazarus-ccr.sourceforge.net/docs/lcl/controls/twincontrol.setshape.html>
211+
212+Einschränkungen:
213+
214+In Gtk2 kann eine Region erst festgelegt werden, nachdem ein Fenster erstellt wurde. SetWindowRgn im OnShow-Ereignishandler aufzurufen funktioniert nicht, die einzige Möglichkeit scheint der Einsatz eines Timers zu sein, der nach einem Intervall von 1 ms aufgerufen wird. Aktivieren Sie den Timer in Form.OnShow und deaktivieren Sie ihn im OnTimer-Handler.
215+
216+## Simulation von Maus- and Tastatureingaben
217+
218+Sie können sehr einfach Maus- und Tastatureingaben mit der LCL simulieren. Nutzen Sie dazu einfach die Routinen aus der Unit LCLMessageGlue wie es alle Widgetset Schnittstellen tun. Diese Unit verfügt über Routinen wie:
219+
220+``` pascal
221+unit LCLMessageGlue;
222+
223+function LCLSendMouseMoveMsg(const Target: TControl; XPos, YPos: smallint;
224+ ShiftState: TShiftState = []): PtrInt;
225+function LCLSendMouseDownMsg(const Target: TControl; XPos, YPos: smallint;
226+ Button: TMouseButton; ShiftState: TShiftState = []): PtrInt;
227+function LCLSendMouseUpMsg(const Target: TControl; XPos, YPos: smallint;
228+ Button: TMouseButton; ShiftState: TShiftState = []): PtrInt;
229+function LCLSendMouseWheelMsg(const Target: TControl; XPos, YPos, WheelDelta: smallint;
230+ ShiftState: TShiftState = []): PtrInt;
231+function LCLSendCaptureChangedMsg(const Target: TControl): PtrInt;
232+function LCLSendSelectionChangedMsg(const Target: TControl): PtrInt;
233+function LCLSendClickedMsg(const Target: TControl): PtrInt;
234+function LCLSendMouseEnterMsg(const Target: TControl): PtrInt;
235+function LCLSendMouseLeaveMsg(const Target: TControl): PtrInt;
236+...
237+function LCLSendKeyDownEvent(const Target: TControl; var CharCode: word;
238+ KeyData: PtrInt; BeforeEvent, IsSysKey: boolean): PtrInt;
239+function LCLSendKeyUpEvent(const Target: TControl; var CharCode: word;
240+ KeyData: PtrInt; BeforeEvent, IsSysKey: boolean): PtrInt;
241+```
242+
243+## Die virtuelle Tastatur auf Smartphones/Tablets zeigen
244+
245+Um die virtuelle Tastatur anzuzeigen, wenn ein Steuerelement den Fokus erhält, können Sie einfach csRequiresKeyboardInput ControlStyle hinzufügen:
246+
247+``` pascal
248+constructor TMyTextEditor.Create(AOwner : TComponent);
249+begin
250+ inherited Create(AOwner);
251+ ControlStyle := ControlStyle + [csRequiresKeyboardInput];
252+...
253+end;
254+```
255+
256+<figure>
257+<img src="Virtual_keyboard.png" title="Virtual_keyboard.png" />
258+<figcaption>Virtual_keyboard.png</figcaption>
259+</figure>
260+
261+## Alle untergeordneten Controls von einem TWinControl durchlaufen
262+
263+Dies ist sehr einfach zu realisieren. Benutzen Sie einfach eine Schleife. Der Index ist nullbasiert, TWinControl.ControlCount gibt die Anzahl an und TWinControl.Controls\[Index\] das entspechende Steuerelement.
264+
265+``` pascal
266+procedure TWinControl.WriteLayoutDebugReport(const Prefix: string);
267+var
268+ i: Integer;
269+begin
270+ inherited WriteLayoutDebugReport(Prefix);
271+ for i:=0 to ControlCount-1 do
272+ Controls[i].WriteLayoutDebugReport(Prefix+' ');
273+end;
274+```
275+
276+---
277+*From the Free Pascal wiki, page "LCL Tips/de", as it stood on 2020-02-19 after a change by Trev, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).*

Back to history