Sign in Join
Wiki copytemporary

How To Write Lazarus Component/es: what changed

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

OldNewLine
11Esta es una guía sobre como construir componentes.
22
33## Paso 1: Crear el paquete
44
55- En el menú de Lazarus, clic en **Paquete \> Nuevo Paquete** para ejecutar el administrador de paquetes.
66
7-<figure>
8-<img src="package_menu.png" title="package_menu.png" />
9-<figcaption>package_menu.png</figcaption>
10-</figure>
7+![](/wiki-images/7/7c/Package_menu.png)
118
129- Un dialogo **Guardar** aparecerá. Elije una carpeta y un nombre y presiona guardar. Si el IDE pregunta por usar nombres de archivo en minúsculas presiona 'sí'.
1310
1411- Felicidades: Has creado tu primer paquete.
1512
16-<figure>
17-<img src="How_to_write_lazarus_component_package_maker.png" title="Package Maker" />
18-<figcaption>Package Maker</figcaption>
19-</figure>
13+![](/wiki-images/3/37/How_to_write_lazarus_component_package_maker.png)
2014
2115## Paso 2: Crear la unidad
2216
2317Puedes crear una nueva unidad o usar un archivo existente. Las dos opciones son desarrolladas debajo.
2418
2519### Crear una nueva unidad
2620
2721- Usa el botón **Add \> Nuevo componente**.
2822
29-<figure>
30-<img src="package_new_component.png" title="package_new_component.png" />
31-<figcaption>package_new_component.png</figcaption>
32-</figure>
23+![](/wiki-images/5/56/Package_new_component.png)
3324
3425- Escoge un componente tal como TComboBox.
3526- Escoge *customcontrol1.pas* como **Nombre de fichero para la unit** y *CustomControl1* como **Nombre de la unit**.
3627- Ahora ya puedes asignar al componenete un icono y determinar en que solapa de la paleta del IDE de Lazarus aparecera el componente.
3728- Click en **Crear Nuevo Componente**.
3829
3930``` pascal
4031unit CustomControl1;
4132
4233{$mode objfpc}{$H+}
4334
4435interface
4536
4637uses
4738 Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs, StdCtrls;
4839
4940type
5041 TCustomControl1 = class(TComboBox)
5142 private
5243 { Declaraciones Privadas}
5344 protected
5445 { Declaraciones Protegidas }
5546 public
5647 { Declaraciones Públicas }
5748 published
5849 { Declaraciones Publicadas }
5950 end;
6051
6152procedure Register;
6253
6354implementation
6455
6556procedure Register;
6657begin
6758 RegisterComponents('Standard',[TCustomControl1]);
6859end;
6960
7061end.
7162```
7263
7364- Instala el paquete haciendo clic en el botón **Use -\> Install** arriba del editor del paquete.
7465
75-<figure>
76-<img src="package_install.png" title="package_install.png" />
77-<figcaption>package_install.png</figcaption>
78-</figure>
66+![](/wiki-images/3/36/Package_install.png)
7967
8068- Ahora el IDE te preguntará ¿Desea reconstruir ahora Lazarus?, le indicamos que \[Si\].
8169
82-<figure>
83-<img src="package_rebuild.png" title="package_rebuild.png" />
84-<figcaption>package_rebuild.png</figcaption>
85-</figure>
70+![](/wiki-images/9/9b/Package_rebuild.png)
8671
8772- Una vez reiniciado el IDE de Lazarus deberiamos poder ver el nuevo componente en la paleta dentro de la solapa adecuada. Felicidades, ya tienes instalado tu primer paquete con tu primer paquete de componente.
8873
89-<figure>
90-<img src="package_installed.png" title="package_installed.png" />
91-<figcaption>package_installed.png</figcaption>
92-</figure>
74+![](/wiki-images/3/35/Package_installed.png)
9375
9476### Añadir una unidad existente
9577
9678Si ya tienes una unidad creada la puedes añadir al paquete:
9779
98-<figure>
99-<img src="package_existing_unit.png" title="package_existing_unit.png" />
100-<figcaption>package_existing_unit.png</figcaption>
101-</figure>
80+![](/wiki-images/1/11/Package_existing_unit.png)
10281
10382- Click the **Add** button, go to the **Add Files** tab. At the Unit file name, browse to your existing file. Click **Add files to package**. If the package manager complains that the unit is not in the unit path, click yes to add the directory to the unit path.
10483- Click the **Add** button again, go to the **Add Files** tab, browse to the *.lrs* file and click OK (See Step 3 about creating this icon file).
10584- Click the **Add** button again, go to the **New Requirement** tab. In the Package name select **LCL** and click OK.
10685
10786El resultado final debería parecerse a esto:
10887
109-<figure>
110-<img src="How_to_write_lazarus_component_package_maker_done.png" title="Package Maker" />
111-<figcaption>Package Maker</figcaption>
112-</figure>
88+![](/wiki-images/d/d9/How_to_write_lazarus_component_package_maker_done.png)
11389
11490- Click bajo el árbol de ficheros en el Gestor de Paquetes. En Propiedades de Fichero, asegúrate que la *Register unit* se encuentra chequeada.
11591- Click en el pulsador de Opciones. Selecciona la solapa de Integración del IDE. En Tipo de Paquete, asegúrate que están seleccionados Designtime y Runtime.
11692- Click en el pulsador de Compilar para chequearque todo se compile sin errores.
11793- Click en el pulsador de Instalar. Lazarus se reconstruirá y reiniciará automáticamente.
11894
11995El componente se ha creado y está listo para ser utilizado:
12096
121-<figure>
122-<img src="How_to_write_lazarus_component_created.png" title="Component Created" />
123-<figcaption>Component Created</figcaption>
124-</figure>
97+![](/wiki-images/3/3c/How_to_write_lazarus_component_created.png)
12598
12699## Paso 3: Crear iconos para el paquete
127100
128101Se deben crear iconos con dimensiones 24x24 píxeles y formato de fichero PNG.
129102
130103FPC es capaz de utilizar ficheros de recurso estandar `.rc` y recursos compilados `.res` desde la versión 2.6. Ver [[Lazarus Resources|Lazarus_Resources#FPC_resources]]
131104
132105Por hacer: escribir la descripción de creación de iconos utilizando recursos FPC.
133106
134107Los `.lrs`: ver más abajo.
135108
136109### Utilizando el Editor de Imágen de Lazarus
137110
138111Puedes utilizar el [[Lazarus Image Editor|Editor de Imágenes de Lazarus]] para crear los iconos en formato ".lrs".
139112
140113### Utilizando lazres
141114
142115`lazres` se encuentra habitualmente en el directorio tools de Lazarus.
143116
144117Se necesita compilarlo para su primer uso [[lazres]]. Simplemente abre el fichero *lazres.lpi* en el IDE y haz click en **run \> build** en el menu.
145118
146119**Create lrs file**
147120
148121Para crear el fichero lrs arranca:
149122
150123`~/lazarus/tools/lazres samplepackage.lrs TMyCom.png`
151124
152125Donde:
153126
154127- *samplepackage* es el nombre de tu paquete.
155128- *TMyCom* es el nombre de tu componente. **El nombre de la imagen debe coincidir con el nombre de tu componente**.
156129
157130Puedes añadir más de una imagen al fichero lrs añadiendo el nombre del fichero de imagen al final. E.g. ~/lazarus/tools/lazres samplepackage.lrs TMyCom.png TMyOtherCom.png ... Y **Ejemplo**
158131
159132El siguiente es un ejemplo del fichero *samplepackage.lrs* resultante.
160133
161134 LazarusResources.Add('TMyCom','PNG',[
162135 #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
163136 +#0#0#0#4'gAMA'#0#0#177#143#11#252'a'#5#0#0#0'|IDAT8O'#237#212#209#10#192' '#8
164137 +#5'P'#247#231#251's'#215#138#133#164#166'\'#220#195'`'#209'c'#157'L'#173#131
165138 +#153#169'd4'#168'dP'#137'r_'#235'5'#136'@Zmk'#16'd9'#144#176#232#164'1'#247
166139 +'I'#8#160'IL'#206'C'#179#144#12#199#140'.'#134#244#141'~'#168#247#209'S~;'#29
167140 +'V+'#196#201'^'#10#15#150'?'#255#18#227#206'NZ>42'#181#159#226#144#15'@'#201
168141 +#148#168'e'#224'7f<@4'#130'u_YD'#23#213#131#134'Q]'#158#188#135#0#0#0#0'IEND'
169142 +#174'B`'#130
170143 ]);
171144
172145Asegúrate de incluir tu fichero de recursos en la fuente de tu nuevo componente añadiendo lo siguiente al fondo de la unit del componente e incluyendo **"LResources"** en la claúsula **uses**.
173146
174147``` pascal
175148initialization
176149 {$I samplepackage.lrs}
177150```
178151
179152### Utilizando glazres
180153
181154**GLazRes** is the graphical version of `lazres` that can assemble files into a Lazarus resource file (.lrs). It can be found in the tools directory of a Lazarus installation.
182155
183156## Recompilando paquetes
184157
185158Es necesario reconstruir el paquete cada vez que se realizan cambios en el fichero *mycom.pas* . Para reconstruir el paquete ve a Paquete -\> Abrir Archivo de Paquete (.lpk)...-\> Seleccionar el fichero *samplepackage.lpk* en el gestor de paquetes y hacer click en el pulsador Usar -\> Instalar.
186159
187160## Eliminando paquetes
188161
189162- Para eliminar componentes instalados: en el menú del IDE hacer Click en Paquete -\> \> Instalar/Desinstalar Paquetes. La siguiente imagen muestra la utilidad de Paquetes Instalados.
190163
191164![`Installed Components`](/wiki-images/0/0e/How_to_write_lazarus_component_installed_components.png)
192165
193166- Selecciona el paquete que necesitas desinstalar y haz Click en Desinstalar Selección.
194167
195168Si algo va mal con un paquete (e.g. el directorio del paquete se ha borrado sin que primeramente se haya desinstalado), entonces Lazarus no permitirá desinstalar los paquetes. Para solucionar el problema se procede a seleccionar Herramientas en el menú del IDE y a continuación Construir Lazarus, lo cual hará que Lazarus reconstruya todos los paquetes y reinicie. A partir de ahí ya debería permitirte desinstalar los paquetes problemáticos.
196169
197170## Mejorando mycom.pas
198171
199172- El código en *mycom.pas* te muestra lo básico que necesitas para crear un componente. Lo siguiente es una mejora con algunos tips sobre como escribir procedimientos y eventos para componentes.
200173- El*OnChange2* muestra como crear eventos.
201174- El *OnSample* muestra como crear eventos personlizados.
202175- *MyText* y *MyText2* muestran caminos diferentes de escribir propiedades.
203176- Puedes utilizar TComboBox en lugar de TCustomComboBox como clase base, la cual publica todas las propiedades como TComboBox.
204177- Si se utiliza TCustomComboBox como la clase base, notarás que se pierden un montón de propiedades y eventos en el Inspector de Objetos del IDE. Para añadir estas propiedades y eventos, simplemente copia y pega las propiedades tal como se listan abajo.*// properties from TComboBox*. Esta lista de propiedades se pueden obtener desde la declaración de TComboBox en la unidad StdCtrls. Omite cualquier propiedad que necesites manegar por ti mismo.
205178
206179``` pascal
207180unit mycom;
208181
209182{$mode objfpc}{$H+}
210183
211184interface
212185
213186uses
214187 Classes, SysUtils, StdCtrls, Forms, Dialogs,
215188 LCLType,LCLIntf,lresources,LCLProc;
216189
217190type
218191
219192 TSampleEvent = procedure(MyText: String) of Object;
220193
221194 TMyCom = class (TCustomComboBox)
222195 private
223196 FMyText: String;
224197 FOnChange2: TNotifyEvent;
225198 FOnSample: TSampleEvent;
226199 public
227200 constructor Create(TheOwner: TComponent); override;
228201 procedure CreateWnd; override;
229202 procedure Change; override;
230203 protected
231204 function GetMyText2: String;
232205 procedure SetMyText2(MyText: String);
233206 published
234207 property MyText: String read FMyText write FMyText;
235208 property MyText2: String read GetMyText2 write SetMyText2;
236209 property OnChange2: TNotifyEvent read FOnChange2 write FOnChange2;
237210 property OnSample: TSampleEvent read FOnSample write FOnSample;
238211
239212 // properties from TComboBox
240213 property Align;
241214 property Anchors;
242215 property ArrowKeysTraverseList;
243216 property AutoComplete;
244217 property AutoCompleteText;
245218 property AutoDropDown;
246219 property AutoSelect;
247220 property AutoSize;
248221 property BidiMode;
249222 property BorderSpacing;
250223 property CharCase;
251224 property Color;
252225 property Ctl3D;
253226 property Constraints;
254227 property DragCursor;
255228 property DragMode;
256229 property DropDownCount;
257230 property Enabled;
258231 property Font;
259232 property ItemHeight;
260233 property ItemIndex;
261234 property Items;
262235 property ItemWidth;
263236 property MaxLength;
264237 property OnChange;
265238 property OnChangeBounds;
266239 property OnClick;
267240 property OnCloseUp;
268241 property OnContextPopup;
269242 property OnDblClick;
270243 property OnDragDrop;
271244 property OnDragOver;
272245 property OnDrawItem;
273246 property OnEndDrag;
274247 property OnDropDown;
275248 property OnEditingDone;
276249 property OnEnter;
277250 property OnExit;
278251 property OnGetItems;
279252 property OnKeyDown;
280253 property OnKeyPress;
281254 property OnKeyUp;
282255 property OnMeasureItem;
283256 property OnMouseDown;
284257 property OnMouseMove;
285258 property OnMouseUp;
286259 property OnStartDrag;
287260 property OnSelect;
288261 property OnUTF8KeyPress;
289262 property ParentBidiMode;
290263 property ParentColor;
291264 property ParentCtl3D;
292265 property ParentFont;
293266 property ParentShowHint;
294267 property PopupMenu;
295268 property ReadOnly;
296269 property ShowHint;
297270 property Sorted;
298271 property Style;
299272 property TabOrder;
300273 property TabStop;
301274 property Text;
302275 property Visible;
303276 end;
304277
305278procedure Register;
306279
307280implementation
308281
309282procedure Register;
310283begin
311284 RegisterComponents('Sample',[TMyCom]);
312285end;
313286
314287constructor TMyCom.Create(TheOwner: TComponent);
315288begin
316289 inherited Create(TheOwner);
317290 Self.Style := csDropDownList;
318291end;
319292
320293procedure TMyCom.CreateWnd;
321294begin
322295 inherited CreateWnd;
323296 Items.Assign(Screen.Fonts);
324297end;
325298
326299procedure TMyCom.Change;
327300begin
328301 inherited;
329302 if Assigned(FOnChange2) then FOnChange2(Self);
330303 if Assigned(FOnSample) then FOnSample(FMyText);
331304end;
332305
333306function TMyCom.GetMyText2: String;
334307begin
335308 Result:=FMyText;
336309end;
337310
338311procedure TMyCom.SetMyText2(MyText: String);
339312begin
340313 FMyText:=MyText;
341314end;
342315
343316initialization
344317 {$I samplepackage.lrs}
345318
346319end.
347320```
348321
349322Además notarás que existen en el Inspector de Objetos del IDE algunos elementos no declarados y posiblemente innecesarios. Para removerlos, los que no necesites, puedes declararlos en la sección *Published* como simples variables. Por ejemplo:
350323
351324``` pascal
352325Published
353326...
354327 property Height: Integer;
355328 property Width: Integer;
356329...
357330```
358331
359332## Utilizando componentes (visuales) embebidos
360333
361334Puedes utilizar componenetes estandar embebidos dentro de tus propios componentes (mira por ejemplo en TLabeledEdit o TButtonPanel).
362335
363336Digamos que necesitas crear un panel personalizado con un TLabel en el mismo. Con los pasos descritos se pueden crear el paquete base y los ficheros fuente.
364337
365338Ahora haz lo siguiente para añadir un TLabel al componente:
366339
367340- Añade un atributo para el componente label(FEmbeddedLabel: TLabel;).
368341- Añade una propiedad publicada de solo lectura para el componente label (property EmbeddedLabel: TLabel read FEmbeddedLabel;)
369342- Create the label in the component's (overridden) constructor (FEmbeddedLabel := TLabel.Create(self); )
370343- Set the parent of the component (FEmbeddedLabel.Parent := self;)
371344- 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);).
372345
373346To sum it up you would get something like this (solamente se muestran las partes esenciales):
374347
375348``` pascal
376349TEnhancedPanel = class(TCustomControl)
377350private
378351 { El nuevo atributo para el label embebido }
379352 FEmbeddedLabel: TLabel;
380353
381354public
382355 { El contructor debe ser overriden para que el label pueda crearse }
383356 constructor Create(AOwner: TComponent); override;
384357
385358published
386359 { Hacer el label visible en el IDE }
387360 property EmbeddedLabel: TLabel read FEmbeddedLabel;
388361end;
389362
390363implementation
391364
392365constructor TEnhancedPanel.Create(AOwner: TComponent);
393366begin
394367 inherited Create(AOwner);
395368
396369 // Establece el ancho y alto por defecto
397370 with GetControlClassDefaultSize do
398371 SetInitialBounds(0, 0, CX, CY);
399372
400373 // Add the embedded label
401374 FEmbeddedLabel := TLabel.Create(Self); // Add the embedded label
402375 FEmbeddedLabel.Parent := self; // Show the label in the panel
403376 FEmbeddedLabel.SetSubComponent(true); // Tell the IDE to store the modified properties
404377 FLabel.Name := 'EmbeddedLabel';
405378 FLabel.Caption := 'Howdy World!';
406379
407380 // Make sure the embedded label can not be selected/deleted within the IDE
408381 FLabel.ControlStyle := FLabel.ControlStyle - [csNoDesignSelectable];
409382
410383 // Establecer otras propiedades si es neceario
411384 //...
412385
413386end;
414387```
415388
416389## Using custom paint procedure
417390
418391You can always subclass a component inside your program. For example, this implements a custom Paint procedure to a TLabel:
419392
420393``` pascal
421394type
422395 TMyLabel = class(TLabel)
423396 protected
424397 procedure Paint; override;
425398 end;
426399{...}
427400implementation
428401{...}
429402procedure TMyLabel.Paint;
430403begin
431404 // your code to implement Paint, for example
432405 Canvas.TextOut(0,0,Caption);
433406end;
434407```
435408
436409Now you can create a MyLabel inside your program, at run time, with that overridden Paint procedure instead of the standard one.
437410
438411For most components, and for most methods, it would be recommendable to call inherited procedure inside it:
439412
440413``` pascal
441414procedure TMyLabel.Paint;
442415begin
443416
444417 inherited Paint; /////////////////////
445418
446419 // your code to implement Paint, for example
447420 Canvas.TextOut(0,0,Caption);
448421end;
449422```
450423
451424However, inherited behavior is not desirable in this case, since the second writing action would overlap the first (inherited) one.
452425
453426## Integrando el componente con el IDE
454427
455428### Editores de propiedades
456429
457430Los editores de propiedades proveen diálogos personalizados para editar propiedades en el Inspector de Objetos. Para la mayor parte de las propiedades, tales como cadenas, listados de cadenas, imágenes, tipos enumerados y otros, hay ya editores de propiedades por defecto, pero pero si un componente personalizado tiene cualquier tipo de propiedad especial se hace necesario un diálogo personalizado para editar la propiedad.
458431
459432Cada editor de propiedad es una clase, la cual debe descender de TPropertyEditor o de uno de sus descendientes e implementar métodos de esta clase base. Deberían registrase en el procedimiento 'Register' utilizando la función RegisterPropertyEditor de la unidad PropEdits. Es un estandar nombrar a los editores de propiedades con el nombre de la propiedad seguido por 'Property', por ejemplo TFieldProperty para el editor de propiedades de la propiedad TField.
460433
461434``` pascal
462435 TPropertyEditor = class
463436 public
464437 function AllEqual: Boolean; Virtual;
465438 function AutoFill: Boolean; Virtual;
466439 procedure Edit; Virtual; // Activated by double-clicking the property value
467440 procedure ShowValue; Virtual; // Activated by control-clicking the property value
468441 function GetAttributes: TPropertyAttributes; Virtual;
469442 function GetEditLimit: Integer; Virtual;
470443 function GetName: ShortString; Virtual;
471444 procedure GetProperties(Proc: TGetPropEditProc); Virtual;
472445 function GetHint(HintType: TPropEditHint; x, y: integer): String; Virtual;
473446 function GetDefaultValue: AnsiString; Virtual;
474447 procedure GetValues(Proc: TGetStrProc); Virtual;
475448 procedure SetValue(const NewValue: AnsiString); Virtual;
476449 procedure UpdateSubProperties; Virtual;
477450 function SubPropertiesNeedsUpdate: Boolean; Virtual;
478451 function IsDefaultValue: Boolean; Virtual;
479452 function IsNotDefaultValue: Boolean; Virtual;
480453 // ... shortened
481454 end;
482455```
483456
484457Un buen ejemplo para un editor de propiedades es el de TFont.
485458
486459Uno de los casos más habituales de editores de propiedades es el de propiedades que son clases. Debido a que classes tiene bastantes campos y puede tener una variedad de formatos no es posible para Lazarus tener el campo de edición del inspector de objetos capaz de editarlo, tal como es realizado para cadenas y tipos numéricos.
487460
488461Para clases, una convención es tener el valor del campo mostrado permanentemente de la clase entre paréntesis, por ejemplo "(TFont)" y el pulsador "..." muestra un diálogo para editar esta clase. Este comportamiento, excepto para el diálogo, se implementa por medio de un editor estandar de de propiedades para clases llamado TClassPropertyEditor, del cual puede heredar cuando se escriben editores de propiedades para clases:
489462
490463``` pascal
491464TClassPropertyEditor = class(TPropertyEditor)
492465public
493466 constructor Create(Hook: TPropertyEditorHook; APropCount: Integer); Override;
494467 function GetAttributes: TPropertyAttributes; Override;
495468 procedure GetProperties(Proc: TGetPropEditProc); Override;
496469 function GetValue: AnsiString; Override;
497470 property SubPropsTypeFilter: TTypeKinds Read FSubPropsTypeFilter
498471 Write SetSubPropsTypeFilter
499472 Default tkAny;
500473end;
501474```
502475
503476Volviendo al ejemplo de TFont, heredando desde 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:
504477
505478``` pascal
506479 TFontPropertyEditor = class(TClassPropertyEditor)
507480 public
508481 procedure Edit; Override;
509482 function GetAttributes: TPropertyAttributes; Override;
510483 end;
511484
512485procedure TFontPropertyEditor.Edit;
513486var
514487 FontDialog: TFontDialog;
515488begin
516489 FontDialog := TFontDialog.Create(NIL);
517490 try
518491 FontDialog.Font := TFont(GetObjectValue(TFont));
519492 FontDialog.Options := FontDialog.Options + [fdShowHelp, fdForceFontExist];
520493 if FontDialog.Execute then SetPtrValue(FontDialog.Font);
521494 finally
522495 FontDialog.Free;
523496 end;
524497end;
525498
526499function TFontPropertyEditor.GetAttributes: TPropertyAttributes;
527500begin
528501 Result := [paMultiSelect, paSubProperties, paDialog, paReadOnly];
529502end;
530503```
531504
532505### Editores de componentes
533506
534507Los editores de componentes controlan el comportamiento de los mismos en cuanto a clickeo derecho y doble click en el diseñador de formularios.
535508
536509Cada componente del editor es una clase, la cual debería descender de TComponentEditor o uno de sus descendientes e implementar métodos para esta clase base. Se deberían registrar en el procedimiento 'Register' utilizando la función RegisterComponentEditor de la unidad ComponentEditors. Es un estandar para nombrar los editores de componentes con el nombre del componente seguido por 'Editor', por ejemplo TStringGridComponentEditor para la propiedad de editior del componente TStringGrid. Although user component editors deberían estar basados en TComponentEditor, la mayoría de sus métodos son actualmente un ancestor, por lo que es necesario conocer además TBaseComponentEditor:
537510
538511``` pascal
539512 TBaseComponentEditor = class
540513 protected
541514 public
542515 constructor Create(AComponent: TComponent;
543516 ADesigner: TComponentEditorDesigner); Virtual;
544517 procedure Edit; Virtual; Abstract;
545518 procedure ExecuteVerb(Index: Integer); Virtual; Abstract;
546519 function GetVerb(Index: Integer): String; Virtual; Abstract;
547520 function GetVerbCount: Integer; Virtual; Abstract;
548521 procedure PrepareItem(Index: Integer; const AnItem: TMenuItem); Virtual; Abstract;
549522 procedure Copy; Virtual; Abstract;
550523 function IsInInlined: Boolean; Virtual; Abstract;
551524 function GetComponent: TComponent; Virtual; Abstract;
552525 function GetDesigner: TComponentEditorDesigner; Virtual; Abstract;
553526 function GetHook(out Hook: TPropertyEditorHook): Boolean; Virtual; Abstract;
554527 procedure Modified; Virtual; Abstract;
555528 end;
556529```
557530
558531El método más importante de un editor componente es Edit, el cual se llama cuando se hace doble click sobre el componente. Cuando se invocael menú contextual del componente se realiza la llamada a los métodos GetVerbCount y GetVerb para construir el menú. Si se selecciona uno de los verbs (que significa elementos del menú en este caso) entonces se llama a ExecuteVerb. Existe un componente de editor por defecto (TDefaultEditor) el cual implementa Edit para buscar en las propiedades del componente la más apropiada para ser editada. Usualmente escoge un evento, el cual se edita añadiendo su estructura de código en el editor de código y estableciendo el cursor a ubicar al cual añadir código.
559532
560533Otros métodos importantes para TBasComponentEditor son:: ExecuteVerb(Index), el cual ejecuta uno de los elementos extra del menú ubicado en el menu popup del click derecho; GetVerb – Para retornar el nombre de cada elemento extra del menú popup. Ten en cuenta que es responsabilidad del editor de componente ubicar 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.
561534
562535Un simple e interesante ejemplo es el editor de componente TCheckListBox el cual crea un diálogo de edición. Más conveniente que implementar todos los métodos desde TBaseComponentEditor es heredarlos desde TComponentEditor, y esto es lo que TCheckListBoxEditor hace. Esta clase base añade implementaciones vacía para la mayor parte de los métodos y agunos por defecto para otros. Para Edit llama a ExecuteVerb(0), por lo que si el primer elemento es idéntico a la acción doble click, la cual es una convención para editor, no habrá necesidad de implementar Edit. Esta acción básica para doble-click y el primer elemento de del menú es a menudo un diálogo, y para TCheckListBox se realiza además:
563536
564537``` pascal
565538 TCheckListBoxComponentEditor = class(TComponentEditor)
566539 protected
567540 procedure DoShowEditor;
568541 public
569542 procedure ExecuteVerb(Index: Integer); override;
570543 function GetVerb(Index: Integer): String; override;
571544 function GetVerbCount: Integer; override;
572545 end;
573546
574547procedure TCheckGroupComponentEditor.DoShowEditor;
575548var
576549 Dlg: TCheckGroupEditorDlg;
577550begin
578551 Dlg := TCheckGroupEditorDlg.Create(NIL);
579552 try
580553 // .. shortened
581554 Dlg.ShowModal;
582555 // .. shortened
583556 finally
584557 Dlg.Free;
585558 end;
586559end;
587560
588561procedure TCheckGroupComponentEditor.ExecuteVerb(Index: Integer);
589562begin
590563 case Index of
591564 0: DoShowEditor;
592565 end;
593566end;
594567
595568function TCheckGroupComponentEditor.GetVerb(Index: Integer): String;
596569begin
597570 Result := 'CheckBox Editor...';
598571end;
599572
600573function TCheckGroupComponentEditor.GetVerbCount: Integer;
601574begin
602575 Result := 1;
603576end;
604577```
605578
606579## Depurando un componente en tiempo de diseño
607580
608581Para detectar errores en tiempo de diseño en un (nuevamente creado) *dbgcomponent*:
609582
610583- Abrir proyecto `C:\lazarus\ide\lazarus.lpi`;
611584- Ejecutar proyecto;
612585- Establecer punto de interrupción en *dbgcomponent* in main (1st) app;
613586- use *dbgcomponent* pascal code in second app;
614587- step through design-time component code in debug-session; do whatever is necessary;
615588
616589## See also
617590
618591- [[Extending the IDE]]
619592- [[Lazarus Packages]] - A guide for creating a package under Lazarus
620593- [[Components and Code examples]]
621594- [[Lazarus Components]]
622595- [[IDE Window: Add to Package]]
623596
624597You can post questions regarding this page [here](http://forum.lazarus.freepascal.org/index.php/topic,5789.0.html)
625598
626599---
627600*From the Free Pascal wiki, page "How To Write Lazarus Component/es", 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