Sign in Join
Wiki copytemporary

How To Write Lazarus Component/it: what changed

Revision 2 to 3. Removed lines have a minus sign; added lines have a plus sign.

OldNewLine
11## Introduzione
22
33Questa è una guida di base su come costruire componenti. È stata testata su Lazarus 0.9.30 eseguito in Windows 7.
44
55## Passo 1: Creare il Package
66
77- Nel menu di Lazarus IDE, click su **Package \> Nuovo Package** per eseguire il Package Manager.
88
99![](/wiki-images/c/c2/Package_menu_it.png)
1010
1111- Apparirà la **finestra di dialog Salva file**. Scegli una cartella e un nome e salva. Se l'IDE propone di utilizzare le minuscole per il nome file, premi 'OK'.
1212
1313- Congratulazioni: hai appena creato il tuo primo Package!
1414
1515![](/wiki-images/0/0d/Nuovo_package.png)
1616
1717## Passo 2: Creare la Unit
1818
1919Puoi creare una nuova unit o usare un file esistente.
2020
2121### Crea una Nuova Unit
2222
2323- Usa il pulsante **Aggiungi \> Nuovo componente**.
2424
2525![](/wiki-images/6/6e/Nuovo_componente.png)
2626
2727- Scegli un componente come TComboBox.
2828- Scegli *customcontrol1.pas* come mome file.
2929- Clicca OK.
3030
3131``` pascal
3232unit CustomControl1;
3333
3434{$mode objfpc}{$H+}
3535
3636interface
3737
3838uses
3939 Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs, StdCtrls;
4040
4141type
4242 TCustomControl1 = class(TComboBox)
4343 private
4444 { Private declarations }
4545 protected
4646 { Protected declarations }
4747 public
4848 { Public declarations }
4949 published
5050 { Published declarations }
5151 end;
5252
5353procedure Register;
5454
5555implementation
5656
5757procedure Register;
5858begin
5959 RegisterComponents('Standard',[TCustomControl1]);
6060end;
6161
6262end.
6363```
6464
6565- Installa il package cliccando il bottone 'install' in alto nel package editor.
6666
6767![](/wiki-images/9/93/Package_install_it.png)
6868
6969- Quindi l'IDE chiederà se si vuole che venga fatto il rebuild dell'IDE. Cliccare yes.
7070
7171![](/wiki-images/1/16/Package_rebuild_it.png)
7272
7373- Riavviato Lazarus potrete vedere il vostro nuovo componente nella component palette. Congratulazioni: Avete appena installato il vostro primo package con il vostro primo componente.
7474
7575![](/wiki-images/d/d1/Componente_installato.png)
7676
7777*Nota:* Se non vedete il vostro nuovo componente nella palette dei componenti, molto probabilmente state eseguendo una versione non ricompilata di Lazarus. Potete impostare dove Lazarus effettua il build in: Strumenti -\> Opzioni -\> File -\> Cartella di Lazarus. Invece di eseguire lazarus direttamente, potete anche usare startlazarus, che esegue lazarus più recentemente compilato, per esempio l'eseguibile di lazarus nella cartella ~/.lazarus, se non avete i diritti di scrittura nella cartella in cui è installato lazarus.
7878
7979### Aggiungi una Unit esistente
8080
8181Se avete già una unit potete aggiungerla al package:
8282
8383![](/wiki-images/1/13/Package_add_unit_it.png)
8484
8585- Fate Click sul pulsante **Aggiungi**, andate sul tab **Aggiungi File**. Cliccato il pulsante Esplora, cercate il vostro file. Fate Click su **Aggiungi file al pacchetto**. Se il gestore pacchetti lamenta che la unit non è nella cartella, accettate di aggiungere la directory al percorso nel unit path.
8686- Fate Click ancora su **Aggiungi** , andate sul tab **Aggiungi File** e cercate il file *.lrs*, quindi fate click su OK (Vedete il Passo 3 per creare il file dell'icona ).
8787- Fate Click di nuovo su **Aggiungi**, andate sul tab **Nuovo requisito**, selezionate **LCL** in Nome pacchetto e fate click su OK.
8888
8989Il risultato finale dovrebbe assomigliare a questo:
9090
91-![`Package Maker`](/wiki-images/d/d9/How_to_write_lazarus_component_package_maker_done.png)
91+```text
92+Package Maker
93+```
9294
9395- Click on under the Files tree in the Package Manager. In the File Properties, make sure *Register unit* is checked.
9496- Click the Options button. Select the IDE Integration tab. At the Package Type make sure Designtime and Runtime is selected.
9597- Click the Compile button to check to see if the files compile without errors.
9698- Click the Install button, Lazarus will rebuild and restart automatically.
9799
98100The component is created and ready to be used:
99101
100-![`Component Created`](/wiki-images/3/3c/How_to_write_lazarus_component_created.png)
102+```text
103+Component Created
104+```
101105
102106## Passo 3: Creare Icone Per Il Package
103107
104108La dimensione del file PNG dovrebbe essere 24x24. Il formato icona utilizzato è *.lrs*.
105109
106110### Usa Lazarus Image Editor
107111
108112Puoi usare [[Lazarus Image Editor]] per creare le icons nel formato .lrs.
109113
110114### Usa lazres
111115
112116Potresti aver bisogno di compilare lazres al primo utilizzo. Semplicemente apri *lazres.lpi* nell'IDE e scegli nel menu **run \> build**.
113117
114118**Crea file lrs**
115119
116120Per creare il file lrs esegui:
117121
118122`~/lazarus/tools/lazres samplepackage.lrs TMyCom.png`
119123
120124Dove *samplepackage* è il nome del tuo package e *TMyCom* è il nome del tuo componente.
121125
122126You can add more than one image to the lrs file by appending the image filename at the end. Eg. ~/lazarus/tools/lazres samplepackage.lrs TMyCom.png TMyOtherCom.png ...
123127
124128**Sample**
125129
126130Following is a sample of the resulting *samplepackage.lrs* file.
127131
128132 LazarusResources.Add('TMyCom','PNG',[
129133 #137'PNG'#13#10#26#10#0#0#0#13'IHDR'#0#0#0#24#0#0#0#24#8#2#0#0#0'o'#21#170#175
130134 +#0#0#0#4'gAMA'#0#0#177#143#11#252'a'#5#0#0#0'|IDAT8O'#237#212#209#10#192' '#8
131135 +#5'P'#247#231#251's'#215#138#133#164#166'\'#220#195'`'#209'c'#157'L'#173#131
132136 +#153#169'd4'#168'dP'#137'r_'#235'5'#136'@Zmk'#16'd9'#144#176#232#164'1'#247
133137 +'I'#8#160'IL'#206'C'#179#144#12#199#140'.'#134#244#141'~'#168#247#209'S~;'#29
134138 +'V+'#196#201'^'#10#15#150'?'#255#18#227#206'NZ>42'#181#159#226#144#15'@'#201
135139 +#148#168'e'#224'7f<@4'#130'u_YD'#23#213#131#134'Q]'#158#188#135#0#0#0#0'IEND'
136140 +#174'B`'#130
137141 ]);
138142
139143## Recompiling Packages
140144
141145You need to rebuild the package everytime you make changes to the *mycom.pas* file. To rebuild the package, open the *samplepackage.lpk* file in the Package Manager and click the Install button.
142146
143147## Removing Packages
144148
145149- To remove installed components, on the IDE menu, click Package \> Configure installed packages. The following image shows the Installed Packages tool.
146150
147-![`Installed Components`](/wiki-images/0/0e/How_to_write_lazarus_component_installed_components.png)
151+```text
152+Installed Components
153+```
148154
149155- Select the package you want to uninstall and click Uninstall selection.
150156
151157If something goes wrong with a package (e.g. package directory is deleted without first uninstalling it), Lazarus may not allow you to uninstall packages. To fix the problem, at the IDE menu click Tools \> Build Lazarus. Lazarus will rebuild all packages and restart. You should now be able to uninstall problematic packages.
152158
153159## Enhancing mycom.pas
154160
155161- The codes in *mycom.pas* above gives you the basics on what you need to create a component. The following is an enhanced version with some tips on how to write procedures and events for components.
156162- The *OnChange2* shows how to create events
157163- The *OnSample* shows how to create custom events
158164- *MyText* and *MyText2* shows different ways to write properties.
159165- You can use TComboBox instead of TCustomComboBox as the base class, which publishes all properties as TComboBox.
160166- If TCustomComboBox is used as the base class, you'll notice a lot of properties and events will be missing at the Object Inspector in the IDE. To add those properties and events just copy and paste the properties as listed below *// properties from TComboBox*. These list of properties can be got from the TComboBox declaration in the StdCtrls unit. Omit any property which you want to handle yourself.
161167
162168``` pascal
163169unit mycom;
164170
165171{$mode objfpc}{$H+}
166172
167173interface
168174
169175uses
170176 Classes, SysUtils, StdCtrls, Forms, Dialogs,
171177 LCLType,LCLIntf,lresources,LCLProc;
172178
173179type
174180
175181 TSampleEvent = procedure(MyText: String) of Object;
176182
177183 TMyCom = class (TCustomComboBox)
178184 private
179185 FMyText: String;
180186 FOnChange2: TNotifyEvent;
181187 FOnSample: TSampleEvent;
182188 public
183189 constructor Create(TheOwner: TComponent); override;
184190 procedure CreateWnd; override;
185191 procedure Change; override;
186192 protected
187193 function GetMyText2: String;
188194 procedure SetMyText2(MyText: String);
189195 published
190196 property MyText: String read FMyText write FMyText;
191197 property MyText2: String read GetMyText2 write SetMyText2;
192198 property OnChange2: TNotifyEvent read FOnChange2 write FOnChange2;
193199 property OnSample: TSampleEvent read FOnSample write FOnSample;
194200
195201 // properties from TComboBox
196202 property Align;
197203 property Anchors;
198204 property ArrowKeysTraverseList;
199205 property AutoComplete;
200206 property AutoCompleteText;
201207 property AutoDropDown;
202208 property AutoSelect;
203209 property AutoSize;
204210 property BidiMode;
205211 property BorderSpacing;
206212 property CharCase;
207213 property Color;
208214 property Ctl3D;
209215 property Constraints;
210216 property DragCursor;
211217 property DragMode;
212218 property DropDownCount;
213219 property Enabled;
214220 property Font;
215221 property ItemHeight;
216222 property ItemIndex;
217223 property Items;
218224 property ItemWidth;
219225 property MaxLength;
220226 property OnChange;
221227 property OnChangeBounds;
222228 property OnClick;
223229 property OnCloseUp;
224230 property OnContextPopup;
225231 property OnDblClick;
226232 property OnDragDrop;
227233 property OnDragOver;
228234 property OnDrawItem;
229235 property OnEndDrag;
230236 property OnDropDown;
231237 property OnEditingDone;
232238 property OnEnter;
233239 property OnExit;
234240 property OnGetItems;
235241 property OnKeyDown;
236242 property OnKeyPress;
237243 property OnKeyUp;
238244 property OnMeasureItem;
239245 property OnMouseDown;
240246 property OnMouseMove;
241247 property OnMouseUp;
242248 property OnStartDrag;
243249 property OnSelect;
244250 property OnUTF8KeyPress;
245251 property ParentBidiMode;
246252 property ParentColor;
247253 property ParentCtl3D;
248254 property ParentFont;
249255 property ParentShowHint;
250256 property PopupMenu;
251257 property ReadOnly;
252258 property ShowHint;
253259 property Sorted;
254260 property Style;
255261 property TabOrder;
256262 property TabStop;
257263 property Text;
258264 property Visible;
259265 end;
260266
261267procedure Register;
262268
263269implementation
264270
265271procedure Register;
266272begin
267273 RegisterComponents('Sample',[TMyCom]);
268274end;
269275
270276constructor TMyCom.Create(TheOwner: TComponent);
271277begin
272278 inherited Create(TheOwner);
273279 Self.Style := csDropDownList;
274280end;
275281
276282procedure TMyCom.CreateWnd;
277283begin
278284 inherited CreateWnd;
279285 Items.Assign(Screen.Fonts);
280286end;
281287
282288procedure TMyCom.Change;
283289begin
284290 inherited;
285291 if Assigned(FOnChange2) then FOnChange2(Self);
286292 if Assigned(FOnSample) then FOnSample(FMyText);
287293end;
288294
289295function TMyCom.GetMyText2: String;
290296begin
291297 Result:=FMyText;
292298end;
293299
294300procedure TMyCom.SetMyText2(MyText: String);
295301begin
296302 FMyText:=MyText;
297303end;
298304
299305initialization
300306 {$I samplepackage.lrs}
301307
302308end.
303309```
304310
305311## Using embedded (visual) components
306312
307313It's possible to use standard components embedded in your own components (look for example at TLabeledEdit or TButtonPanel). Let's say you want to create a custom panel with a TLabel on it. With the steps described above the base package and source files can be created. Now to add a TLabel to the component, do the following:
308314
309315- Add a private attribute for the label component (FEmbeddedLabel: TLabel;).
310316- Add a published read-only property for the label component (property EmbeddedLabel: TLabel read FEmbeddedLabel;)
311317- Create the label in the component's (overridden) constructor (FEmbeddedLabel := TLabel.Create(self); )
312318- Set the parent of the component (FEmbeddedLabel.Parent := self;)
313319- If the component to be embedded is not a 'subcomponent' by default (like TBoundLabel, TPanelBitBtn etc.) then add the call to SetSubComponent. This is necessary for the IDE so it knows that it has to store the properties of the embedded component as well. TLabel is not a subcomponent by default so the call to the method must be added (FEmbeddedLabel.SetSubComponent(true);).
314320
315321To sum it up you would get something like this (only the essential parts are shown):
316322
317323``` pascal
318324TEnhancedPanel = class(TCustomControl)
319325private
320326 { The new attribute for the embedded label }
321327 FEmbeddedLabel: TLabel;
322328
323329public
324330 { The constructor must be overriden so the label can be created }
325331 constructor Create(AOwner: TComponent); override;
326332
327333published
328334 { Make the label visible in the IDE }
329335 property EmbeddedLabel: TLabel read FEmbeddedLabel;
330336end;
331337
332338implementation
333339
334340constructor TEnhancedPanel.Create(AOwner: TComponent);
335341begin
336342 inherited Create(AOwner);
337343
338344 // Set default width and height
339345 with GetControlClassDefaultSize do
340346 SetInitialBounds(0, 0, CX, CY);
341347
342348 // Add the embedded label
343349 FEmbeddedLabel := TLabel.Create(Self); // Add the embedded label
344350 FEmbeddedLabel.Parent := self; // Show the label in the panel
345351 FEmbeddedLabel.SetSubComponent(true); // Tell the IDE to store the modified properties
346352 FLabel.Name := 'EmbeddedLabel';
347353 FLabel.Caption := 'Howdy World!';
348354
349355 // Make sure the embedded label can not be selected/deleted within the IDE
350356 FLabel.ControlStyle := FLabel.ControlStyle - [csNoDesignSelectable];
351357
352358 // Set other properties if necessary
353359 //...
354360
355361end;
356362```
357363
358364## Using custom paint procedure
359365
360366You can always subclass a component inside your program. For example, this implements a custom Paint procedure to a TLabel:
361367
362368``` pascal
363369type
364370 TMyLabel = class(TLabel)
365371 public
366372 procedure Paint; override;
367373 end;
368374{...}
369375implementation
370376{...}
371377procedure TMyLabel.Paint;
372378begin
373379 // your code to implement Paint, for example
374380 Canvas.TextOut(0,0,Caption);
375381end;
376382```
377383
378384Now you can create a MyLabel inside your program, at run time, with that overridden Paint procedure instead of the standard one.
379385
380386For most components, and for most methods, it would be recommendable to call inherited procedure iniside it:
381387
382388``` pascal
383389procedure TMyLabel.Paint;
384390begin
385391
386392 inherited Paint; /////////////////////
387393
388394 // your code to implement Paint, for example
389395 Canvas.TextOut(0,0,Caption);
390396end;
391397```
392398
393399But inherited behavior is not desirable in this case, since the second writing action would overlap the first (inherited) one.
394400
395401## Integrating the Component with the IDE
396402
397403### Property Editors
398404
399405Property editors provide custom dialogs to edit properties in the object inspector. For most properties, like strings, string lists, images, enumerated types and others, there are already default property editors, but if a custom component has a special kind of property it may require a custom dialog to edit the property. Each property editor is a class, which should descend from TPropertyEditor or one of it's descendents and implement methods from this base class. They should be registered in the 'Register' procedure by using the function RegisterPropertyEditor from the unit PropEdits. It is a standard to name property editors with the property name followed by 'Property', for example TFieldProperty for the property editor of the TField property.
400406
401407``` pascal
402408 TPropertyEditor = class
403409 public
404410 function AllEqual: Boolean; Virtual;
405411 function AutoFill: Boolean; Virtual;
406412 procedure Edit; Virtual; // Activated by double-clicking the property value
407413 procedure ShowValue; Virtual; // Activated by control-clicking the property value
408414 function GetAttributes: TPropertyAttributes; Virtual;
409415 function GetEditLimit: Integer; Virtual;
410416 function GetName: ShortString; Virtual;
411417 procedure GetProperties(Proc: TGetPropEditProc); Virtual;
412418 function GetHint(HintType: TPropEditHint; x, y: integer): String; Virtual;
413419 function GetDefaultValue: AnsiString; Virtual;
414420 procedure GetValues(Proc: TGetStrProc); Virtual;
415421 procedure SetValue(const NewValue: AnsiString); Virtual;
416422 procedure UpdateSubProperties; Virtual;
417423 function SubPropertiesNeedsUpdate: Boolean; Virtual;
418424 function IsDefaultValue: Boolean; Virtual;
419425 function IsNotDefaultValue: Boolean; Virtual;
420426 // ... shortened
421427 end;
422428```
423429
424430A good example for a property editor is the TFont property editor.
425431
426432One of the most common cases for property editors is properties which are classes, because classes have many fields and can have a variety of formats, it's not possible for Lazarus to have the object inspector edit field able to edit it, like is done for strings and numeric types. For classes a convention is to have the value field show permanently the name of the class in parentheses, for example „(TFont)“ and the „...“ button shows a dialog to edit this class. This behavior, except for the dialog, is implemented by a standard property editor for classes called TClassPropertyEditor, which can be inherited from when writing property editors for classes:
427433
428434``` pascal
429435TClassPropertyEditor = class(TPropertyEditor)
430436public
431437 constructor Create(Hook: TPropertyEditorHook; APropCount: Integer); Override;
432438 function GetAttributes: TPropertyAttributes; Override;
433439 procedure GetProperties(Proc: TGetPropEditProc); Override;
434440 function GetValue: AnsiString; Override;
435441 property SubPropsTypeFilter: TTypeKinds Read FSubPropsTypeFilter
436442 Write SetSubPropsTypeFilter
437443 Default tkAny;
438444end;
439445```
440446
441447Going back to the TFont example, inheriting from TClassPropertyEditor already offers part of the desired behavior and then the TFontPropertyEditor class only needs to implement showing the dialog in the Edit method and set the attributes for the editor:
442448
443449``` pascal
444450 TFontPropertyEditor = class(TClassPropertyEditor)
445451 public
446452 procedure Edit; Override;
447453 function GetAttributes: TPropertyAttributes; Override;
448454 end;
449455
450456procedure TFontPropertyEditor.Edit;
451457var
452458 FontDialog: TFontDialog;
453459begin
454460 FontDialog := TFontDialog.Create(NIL);
455461 try
456462 FontDialog.Font := TFont(GetObjectValue(TFont));
457463 FontDialog.Options := FontDialog.Options + [fdShowHelp, fdForceFontExist];
458464 if FontDialog.Execute then SetPtrValue(FontDialog.Font);
459465 finally
460466 FontDialog.Free;
461467 end;
462468end;
463469
464470function TFontPropertyEditor.GetAttributes: TPropertyAttributes;
465471begin
466472 Result := [paMultiSelect, paSubProperties, paDialog, paReadOnly];
467473end;
468474```
469475
470476### Component Editors
471477
472478Component editors control the behavior of right-clicking and double clicking components in the form designer. Each component editor is a class, which should descend from TComponentEditor or one of it's descendents and implement methods from this base class. They should be registered in the 'Register' procedure by using the function RegisterComponentEditor from the unit ComponentEditors. It is a standard to name component editors with the component name followed by 'Editor', for example TStringGridComponentEditor for the property editor of the TStringGrid component. Although user component editors should be based in TComponentEditor, most of it's methods are actually from an ancestor, so it is necessary to also know TBaseComponentEditor:
473479
474480``` pascal
475481 TBaseComponentEditor = class
476482 protected
477483 public
478484 constructor Create(AComponent: TComponent;
479485 ADesigner: TComponentEditorDesigner); Virtual;
480486 procedure Edit; Virtual; Abstract;
481487 procedure ExecuteVerb(Index: Integer); Virtual; Abstract;
482488 function GetVerb(Index: Integer): String; Virtual; Abstract;
483489 function GetVerbCount: Integer; Virtual; Abstract;
484490 procedure PrepareItem(Index: Integer; const AnItem: TMenuItem); Virtual; Abstract;
485491 procedure Copy; Virtual; Abstract;
486492 function IsInInlined: Boolean; Virtual; Abstract;
487493 function GetComponent: TComponent; Virtual; Abstract;
488494 function GetDesigner: TComponentEditorDesigner; Virtual; Abstract;
489495 function GetHook(out Hook: TPropertyEditorHook): Boolean; Virtual; Abstract;
490496 procedure Modified; Virtual; Abstract;
491497 end;
492498```
493499
494500The most important method of a component editor is Edit, which is called when the component is double clicked. When the context menu for the component is invoked the GetVerbCount and GetVerb methods are called to build the menu. If one of the verbs (which means menu items in this case) are selected, ExecuteVerb is called. There is a default component editor (TDefaultEditor) which implements Edit to search the properties of the component for the most appropriate one to be edited. It usually chooses an event, which is edited by adding it's skeleton code in the code editor and setting the cursor to be in place to add code for it.
495501
496502Other important methods from TBasComponentEditor are: ExecuteVerb(Index), which executes one of the extra menu items placed on the right-click popup menu; GetVerb – To return the name of each extra popup menu item. Note that t is the responsibility of the component editor to place special menu item caption characters like & to create a keyboard accelerator and “-” to create a separator; GetVerbCount – Returns the amount of items to be added to the popup menu. The index for the routines GetVerb and ExecuteVerb is zero based, going from 0 to GetVerbCount – 1; PrepareItem – Called for each verb after the menu item was created. Allows the menu item to be customized such as by adding subitems, adding a checkbox or even hiding it by setting Visible to false; Copy - Called when the component is being copied to the clipboard. The component data for use by Lazarus will always be added and cannot be modified. This method is instead for adding a different kind of clipboard information to paste the component in other applications, but which won't affect the Lazarus paste.
497503
498504A simple and interesting example is the TCheckListBox component editor which creates a dialog to edit. More convenient then implementing all methods from TBaseComponentEditor is inheriting from TComponentEditor, and this is what TCheckListBoxEditor does. This base class adds empty implementations for most methods and some default ones for others. For Edit it calls ExecuteVerb(0), so if the first item will be identical to the double-click action, which is a convention for editor, there is no need to implement Edit. This basic action for the double-click and first menu item is often a dialog, and for TCheckListBox this is also done:
499505
500506``` pascal
501507 TCheckListBoxComponentEditor = class(TComponentEditor)
502508 protected
503509 procedure DoShowEditor;
504510 public
505511 procedure ExecuteVerb(Index: Integer); override;
506512 function GetVerb(Index: Integer): String; override;
507513 function GetVerbCount: Integer; override;
508514 end;
509515
510516procedure TCheckGroupComponentEditor.DoShowEditor;
511517var
512518 Dlg: TCheckGroupEditorDlg;
513519begin
514520 Dlg := TCheckGroupEditorDlg.Create(NIL);
515521 try
516522 // .. shortened
517523 Dlg.ShowModal;
518524 // .. shortened
519525 finally
520526 Dlg.Free;
521527 end;
522528end;
523529
524530procedure TCheckGroupComponentEditor.ExecuteVerb(Index: Integer);
525531begin
526532 case Index of
527533 0: DoShowEditor;
528534 end;
529535end;
530536
531537function TCheckGroupComponentEditor.GetVerb(Index: Integer): String;
532538begin
533539 Result := 'CheckBox Editor...';
534540end;
535541
536542function TCheckGroupComponentEditor.GetVerbCount: Integer;
537543begin
538544 Result := 1;
539545end;
540546```
541547
542548## Reference
543549
544550- [[Extending the IDE]]
545551- [[Lazarus Packages]] - A guide for creating a package under Lazarus
546552- [[Components and Code examples]]
547553- [[Lazarus Components]]
548554- [[IDE Window: Add to Package]]
549555
550556You can post questions regarding this page [here](http://forum.lazarus.freepascal.org/index.php/topic,5789.0.html)
551557
552558# Questa pagina
553559
554560Questa pagina è in corso di traduzione dalla [[How To Write Lazarus Component|corrispondente pagina inglese]]
555561
556562## Author
557563
558-[[User talk:Tpglemur|Original Author]]
564+```text
565+ Original Author
566+```
559567
560568Tradotta da User:JohnCat
561569
562570---
563571*From the Free Pascal wiki, page "How To Write Lazarus Component/it", as it stood on 2020-02-17 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