Sign in Join
Wiki copytemporary

How To Write Lazarus Component/es: what changed

Revision 4 to 5. 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
77![](/wiki-images/7/7c/Package_menu.png)
88
99- 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í'.
1010
1111- Felicidades: Has creado tu primer paquete.
1212
1313![](/wiki-images/3/37/How_to_write_lazarus_component_package_maker.png)
1414
1515## Paso 2: Crear la unidad
1616
1717Puedes crear una nueva unidad o usar un archivo existente. Las dos opciones son desarrolladas debajo.
1818
1919### Crear una nueva unidad
2020
2121- Usa el botón **Add \> Nuevo componente**.
2222
2323![](/wiki-images/5/56/Package_new_component.png)
2424
2525- Escoge un componente tal como TComboBox.
2626- Escoge *customcontrol1.pas* como **Nombre de fichero para la unit** y *CustomControl1* como **Nombre de la unit**.
2727- Ahora ya puedes asignar al componenete un icono y determinar en que solapa de la paleta del IDE de Lazarus aparecera el componente.
2828- Click en **Crear Nuevo Componente**.
2929
3030``` pascal
3131unit CustomControl1;
3232
3333{$mode objfpc}{$H+}
3434
3535interface
3636
3737uses
3838 Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs, StdCtrls;
3939
4040type
4141 TCustomControl1 = class(TComboBox)
4242 private
4343 { Declaraciones Privadas}
4444 protected
4545 { Declaraciones Protegidas }
4646 public
4747 { Declaraciones Públicas }
4848 published
4949 { Declaraciones Publicadas }
5050 end;
5151
5252procedure Register;
5353
5454implementation
5555
5656procedure Register;
5757begin
5858 RegisterComponents('Standard',[TCustomControl1]);
5959end;
6060
6161end.
6262```
6363
6464- Instala el paquete haciendo clic en el botón **Use -\> Install** arriba del editor del paquete.
6565
6666![](/wiki-images/3/36/Package_install.png)
6767
6868- Ahora el IDE te preguntará ¿Desea reconstruir ahora Lazarus?, le indicamos que \[Si\].
6969
7070![](/wiki-images/9/9b/Package_rebuild.png)
7171
7272- 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.
7373
7474![](/wiki-images/3/35/Package_installed.png)
7575
7676### Añadir una unidad existente
7777
7878Si ya tienes una unidad creada la puedes añadir al paquete:
7979
8080![](/wiki-images/1/11/Package_existing_unit.png)
8181
8282- 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.
8383- 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).
8484- Click the **Add** button again, go to the **New Requirement** tab. In the Package name select **LCL** and click OK.
8585
8686El resultado final debería parecerse a esto:
8787
8888![](/wiki-images/d/d9/How_to_write_lazarus_component_package_maker_done.png)
8989
9090- Click bajo el árbol de ficheros en el Gestor de Paquetes. En Propiedades de Fichero, asegúrate que la *Register unit* se encuentra chequeada.
9191- 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.
9292- Click en el pulsador de Compilar para chequearque todo se compile sin errores.
9393- Click en el pulsador de Instalar. Lazarus se reconstruirá y reiniciará automáticamente.
9494
9595El componente se ha creado y está listo para ser utilizado:
9696
9797![](/wiki-images/3/3c/How_to_write_lazarus_component_created.png)
9898
9999## Paso 3: Crear iconos para el paquete
100100
101101Se deben crear iconos con dimensiones 24x24 píxeles y formato de fichero PNG.
102102
103103FPC 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]]
104104
105105Por hacer: escribir la descripción de creación de iconos utilizando recursos FPC.
106106
107107Los `.lrs`: ver más abajo.
108108
109109### Utilizando el Editor de Imágen de Lazarus
110110
111111Puedes utilizar el [[Lazarus Image Editor|Editor de Imágenes de Lazarus]] para crear los iconos en formato ".lrs".
112112
113113### Utilizando lazres
114114
115115`lazres` se encuentra habitualmente en el directorio tools de Lazarus.
116116
117117Se 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.
118118
119119**Create lrs file**
120120
121121Para crear el fichero lrs arranca:
122122
123123`~/lazarus/tools/lazres samplepackage.lrs TMyCom.png`
124124
125125Donde:
126126
127127- *samplepackage* es el nombre de tu paquete.
128128- *TMyCom* es el nombre de tu componente. **El nombre de la imagen debe coincidir con el nombre de tu componente**.
129129
130130Puedes 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**
131131
132132El siguiente es un ejemplo del fichero *samplepackage.lrs* resultante.
133133
134134 LazarusResources.Add('TMyCom','PNG',[
135135 #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
136136 +#0#0#0#4'gAMA'#0#0#177#143#11#252'a'#5#0#0#0'|IDAT8O'#237#212#209#10#192' '#8
137137 +#5'P'#247#231#251's'#215#138#133#164#166'\'#220#195'`'#209'c'#157'L'#173#131
138138 +#153#169'd4'#168'dP'#137'r_'#235'5'#136'@Zmk'#16'd9'#144#176#232#164'1'#247
139139 +'I'#8#160'IL'#206'C'#179#144#12#199#140'.'#134#244#141'~'#168#247#209'S~;'#29
140140 +'V+'#196#201'^'#10#15#150'?'#255#18#227#206'NZ>42'#181#159#226#144#15'@'#201
141141 +#148#168'e'#224'7f<@4'#130'u_YD'#23#213#131#134'Q]'#158#188#135#0#0#0#0'IEND'
142142 +#174'B`'#130
143143 ]);
144144
145145Asegú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**.
146146
147147``` pascal
148148initialization
149149 {$I samplepackage.lrs}
150150```
151151
152152### Utilizando glazres
153153
154154**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.
155155
156156## Recompilando paquetes
157157
158158Es 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.
159159
160160## Eliminando paquetes
161161
162162- 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.
163163
164-![`Installed Components`](/wiki-images/0/0e/How_to_write_lazarus_component_installed_components.png)
164+```text
165+Installed Components
166+```
165167
166168- Selecciona el paquete que necesitas desinstalar y haz Click en Desinstalar Selección.
167169
168170Si 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.
169171
170172## Mejorando mycom.pas
171173
172174- 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.
173175- El*OnChange2* muestra como crear eventos.
174176- El *OnSample* muestra como crear eventos personlizados.
175177- *MyText* y *MyText2* muestran caminos diferentes de escribir propiedades.
176178- Puedes utilizar TComboBox en lugar de TCustomComboBox como clase base, la cual publica todas las propiedades como TComboBox.
177179- 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.
178180
179181``` pascal
180182unit mycom;
181183
182184{$mode objfpc}{$H+}
183185
184186interface
185187
186188uses
187189 Classes, SysUtils, StdCtrls, Forms, Dialogs,
188190 LCLType,LCLIntf,lresources,LCLProc;
189191
190192type
191193
192194 TSampleEvent = procedure(MyText: String) of Object;
193195
194196 TMyCom = class (TCustomComboBox)
195197 private
196198 FMyText: String;
197199 FOnChange2: TNotifyEvent;
198200 FOnSample: TSampleEvent;
199201 public
200202 constructor Create(TheOwner: TComponent); override;
201203 procedure CreateWnd; override;
202204 procedure Change; override;
203205 protected
204206 function GetMyText2: String;
205207 procedure SetMyText2(MyText: String);
206208 published
207209 property MyText: String read FMyText write FMyText;
208210 property MyText2: String read GetMyText2 write SetMyText2;
209211 property OnChange2: TNotifyEvent read FOnChange2 write FOnChange2;
210212 property OnSample: TSampleEvent read FOnSample write FOnSample;
211213
212214 // properties from TComboBox
213215 property Align;
214216 property Anchors;
215217 property ArrowKeysTraverseList;
216218 property AutoComplete;
217219 property AutoCompleteText;
218220 property AutoDropDown;
219221 property AutoSelect;
220222 property AutoSize;
221223 property BidiMode;
222224 property BorderSpacing;
223225 property CharCase;
224226 property Color;
225227 property Ctl3D;
226228 property Constraints;
227229 property DragCursor;
228230 property DragMode;
229231 property DropDownCount;
230232 property Enabled;
231233 property Font;
232234 property ItemHeight;
233235 property ItemIndex;
234236 property Items;
235237 property ItemWidth;
236238 property MaxLength;
237239 property OnChange;
238240 property OnChangeBounds;
239241 property OnClick;
240242 property OnCloseUp;
241243 property OnContextPopup;
242244 property OnDblClick;
243245 property OnDragDrop;
244246 property OnDragOver;
245247 property OnDrawItem;
246248 property OnEndDrag;
247249 property OnDropDown;
248250 property OnEditingDone;
249251 property OnEnter;
250252 property OnExit;
251253 property OnGetItems;
252254 property OnKeyDown;
253255 property OnKeyPress;
254256 property OnKeyUp;
255257 property OnMeasureItem;
256258 property OnMouseDown;
257259 property OnMouseMove;
258260 property OnMouseUp;
259261 property OnStartDrag;
260262 property OnSelect;
261263 property OnUTF8KeyPress;
262264 property ParentBidiMode;
263265 property ParentColor;
264266 property ParentCtl3D;
265267 property ParentFont;
266268 property ParentShowHint;
267269 property PopupMenu;
268270 property ReadOnly;
269271 property ShowHint;
270272 property Sorted;
271273 property Style;
272274 property TabOrder;
273275 property TabStop;
274276 property Text;
275277 property Visible;
276278 end;
277279
278280procedure Register;
279281
280282implementation
281283
282284procedure Register;
283285begin
284286 RegisterComponents('Sample',[TMyCom]);
285287end;
286288
287289constructor TMyCom.Create(TheOwner: TComponent);
288290begin
289291 inherited Create(TheOwner);
290292 Self.Style := csDropDownList;
291293end;
292294
293295procedure TMyCom.CreateWnd;
294296begin
295297 inherited CreateWnd;
296298 Items.Assign(Screen.Fonts);
297299end;
298300
299301procedure TMyCom.Change;
300302begin
301303 inherited;
302304 if Assigned(FOnChange2) then FOnChange2(Self);
303305 if Assigned(FOnSample) then FOnSample(FMyText);
304306end;
305307
306308function TMyCom.GetMyText2: String;
307309begin
308310 Result:=FMyText;
309311end;
310312
311313procedure TMyCom.SetMyText2(MyText: String);
312314begin
313315 FMyText:=MyText;
314316end;
315317
316318initialization
317319 {$I samplepackage.lrs}
318320
319321end.
320322```
321323
322324Ademá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:
323325
324326``` pascal
325327Published
326328...
327329 property Height: Integer;
328330 property Width: Integer;
329331...
330332```
331333
332334## Utilizando componentes (visuales) embebidos
333335
334336Puedes utilizar componenetes estandar embebidos dentro de tus propios componentes (mira por ejemplo en TLabeledEdit o TButtonPanel).
335337
336338Digamos 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.
337339
338340Ahora haz lo siguiente para añadir un TLabel al componente:
339341
340342- Añade un atributo para el componente label(FEmbeddedLabel: TLabel;).
341343- Añade una propiedad publicada de solo lectura para el componente label (property EmbeddedLabel: TLabel read FEmbeddedLabel;)
342344- Create the label in the component's (overridden) constructor (FEmbeddedLabel := TLabel.Create(self); )
343345- Set the parent of the component (FEmbeddedLabel.Parent := self;)
344346- 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);).
345347
346348To sum it up you would get something like this (solamente se muestran las partes esenciales):
347349
348350``` pascal
349351TEnhancedPanel = class(TCustomControl)
350352private
351353 { El nuevo atributo para el label embebido }
352354 FEmbeddedLabel: TLabel;
353355
354356public
355357 { El contructor debe ser overriden para que el label pueda crearse }
356358 constructor Create(AOwner: TComponent); override;
357359
358360published
359361 { Hacer el label visible en el IDE }
360362 property EmbeddedLabel: TLabel read FEmbeddedLabel;
361363end;
362364
363365implementation
364366
365367constructor TEnhancedPanel.Create(AOwner: TComponent);
366368begin
367369 inherited Create(AOwner);
368370
369371 // Establece el ancho y alto por defecto
370372 with GetControlClassDefaultSize do
371373 SetInitialBounds(0, 0, CX, CY);
372374
373375 // Add the embedded label
374376 FEmbeddedLabel := TLabel.Create(Self); // Add the embedded label
375377 FEmbeddedLabel.Parent := self; // Show the label in the panel
376378 FEmbeddedLabel.SetSubComponent(true); // Tell the IDE to store the modified properties
377379 FLabel.Name := 'EmbeddedLabel';
378380 FLabel.Caption := 'Howdy World!';
379381
380382 // Make sure the embedded label can not be selected/deleted within the IDE
381383 FLabel.ControlStyle := FLabel.ControlStyle - [csNoDesignSelectable];
382384
383385 // Establecer otras propiedades si es neceario
384386 //...
385387
386388end;
387389```
388390
389391## Using custom paint procedure
390392
391393You can always subclass a component inside your program. For example, this implements a custom Paint procedure to a TLabel:
392394
393395``` pascal
394396type
395397 TMyLabel = class(TLabel)
396398 protected
397399 procedure Paint; override;
398400 end;
399401{...}
400402implementation
401403{...}
402404procedure TMyLabel.Paint;
403405begin
404406 // your code to implement Paint, for example
405407 Canvas.TextOut(0,0,Caption);
406408end;
407409```
408410
409411Now you can create a MyLabel inside your program, at run time, with that overridden Paint procedure instead of the standard one.
410412
411413For most components, and for most methods, it would be recommendable to call inherited procedure inside it:
412414
413415``` pascal
414416procedure TMyLabel.Paint;
415417begin
416418
417419 inherited Paint; /////////////////////
418420
419421 // your code to implement Paint, for example
420422 Canvas.TextOut(0,0,Caption);
421423end;
422424```
423425
424426However, inherited behavior is not desirable in this case, since the second writing action would overlap the first (inherited) one.
425427
426428## Integrando el componente con el IDE
427429
428430### Editores de propiedades
429431
430432Los 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.
431433
432434Cada 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.
433435
434436``` pascal
435437 TPropertyEditor = class
436438 public
437439 function AllEqual: Boolean; Virtual;
438440 function AutoFill: Boolean; Virtual;
439441 procedure Edit; Virtual; // Activated by double-clicking the property value
440442 procedure ShowValue; Virtual; // Activated by control-clicking the property value
441443 function GetAttributes: TPropertyAttributes; Virtual;
442444 function GetEditLimit: Integer; Virtual;
443445 function GetName: ShortString; Virtual;
444446 procedure GetProperties(Proc: TGetPropEditProc); Virtual;
445447 function GetHint(HintType: TPropEditHint; x, y: integer): String; Virtual;
446448 function GetDefaultValue: AnsiString; Virtual;
447449 procedure GetValues(Proc: TGetStrProc); Virtual;
448450 procedure SetValue(const NewValue: AnsiString); Virtual;
449451 procedure UpdateSubProperties; Virtual;
450452 function SubPropertiesNeedsUpdate: Boolean; Virtual;
451453 function IsDefaultValue: Boolean; Virtual;
452454 function IsNotDefaultValue: Boolean; Virtual;
453455 // ... shortened
454456 end;
455457```
456458
457459Un buen ejemplo para un editor de propiedades es el de TFont.
458460
459461Uno 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.
460462
461463Para 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:
462464
463465``` pascal
464466TClassPropertyEditor = class(TPropertyEditor)
465467public
466468 constructor Create(Hook: TPropertyEditorHook; APropCount: Integer); Override;
467469 function GetAttributes: TPropertyAttributes; Override;
468470 procedure GetProperties(Proc: TGetPropEditProc); Override;
469471 function GetValue: AnsiString; Override;
470472 property SubPropsTypeFilter: TTypeKinds Read FSubPropsTypeFilter
471473 Write SetSubPropsTypeFilter
472474 Default tkAny;
473475end;
474476```
475477
476478Volviendo 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:
477479
478480``` pascal
479481 TFontPropertyEditor = class(TClassPropertyEditor)
480482 public
481483 procedure Edit; Override;
482484 function GetAttributes: TPropertyAttributes; Override;
483485 end;
484486
485487procedure TFontPropertyEditor.Edit;
486488var
487489 FontDialog: TFontDialog;
488490begin
489491 FontDialog := TFontDialog.Create(NIL);
490492 try
491493 FontDialog.Font := TFont(GetObjectValue(TFont));
492494 FontDialog.Options := FontDialog.Options + [fdShowHelp, fdForceFontExist];
493495 if FontDialog.Execute then SetPtrValue(FontDialog.Font);
494496 finally
495497 FontDialog.Free;
496498 end;
497499end;
498500
499501function TFontPropertyEditor.GetAttributes: TPropertyAttributes;
500502begin
501503 Result := [paMultiSelect, paSubProperties, paDialog, paReadOnly];
502504end;
503505```
504506
505507### Editores de componentes
506508
507509Los editores de componentes controlan el comportamiento de los mismos en cuanto a clickeo derecho y doble click en el diseñador de formularios.
508510
509511Cada 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:
510512
511513``` pascal
512514 TBaseComponentEditor = class
513515 protected
514516 public
515517 constructor Create(AComponent: TComponent;
516518 ADesigner: TComponentEditorDesigner); Virtual;
517519 procedure Edit; Virtual; Abstract;
518520 procedure ExecuteVerb(Index: Integer); Virtual; Abstract;
519521 function GetVerb(Index: Integer): String; Virtual; Abstract;
520522 function GetVerbCount: Integer; Virtual; Abstract;
521523 procedure PrepareItem(Index: Integer; const AnItem: TMenuItem); Virtual; Abstract;
522524 procedure Copy; Virtual; Abstract;
523525 function IsInInlined: Boolean; Virtual; Abstract;
524526 function GetComponent: TComponent; Virtual; Abstract;
525527 function GetDesigner: TComponentEditorDesigner; Virtual; Abstract;
526528 function GetHook(out Hook: TPropertyEditorHook): Boolean; Virtual; Abstract;
527529 procedure Modified; Virtual; Abstract;
528530 end;
529531```
530532
531533El 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.
532534
533535Otros 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.
534536
535537Un 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:
536538
537539``` pascal
538540 TCheckListBoxComponentEditor = class(TComponentEditor)
539541 protected
540542 procedure DoShowEditor;
541543 public
542544 procedure ExecuteVerb(Index: Integer); override;
543545 function GetVerb(Index: Integer): String; override;
544546 function GetVerbCount: Integer; override;
545547 end;
546548
547549procedure TCheckGroupComponentEditor.DoShowEditor;
548550var
549551 Dlg: TCheckGroupEditorDlg;
550552begin
551553 Dlg := TCheckGroupEditorDlg.Create(NIL);
552554 try
553555 // .. shortened
554556 Dlg.ShowModal;
555557 // .. shortened
556558 finally
557559 Dlg.Free;
558560 end;
559561end;
560562
561563procedure TCheckGroupComponentEditor.ExecuteVerb(Index: Integer);
562564begin
563565 case Index of
564566 0: DoShowEditor;
565567 end;
566568end;
567569
568570function TCheckGroupComponentEditor.GetVerb(Index: Integer): String;
569571begin
570572 Result := 'CheckBox Editor...';
571573end;
572574
573575function TCheckGroupComponentEditor.GetVerbCount: Integer;
574576begin
575577 Result := 1;
576578end;
577579```
578580
579581## Depurando un componente en tiempo de diseño
580582
581583Para detectar errores en tiempo de diseño en un (nuevamente creado) *dbgcomponent*:
582584
583585- Abrir proyecto `C:\lazarus\ide\lazarus.lpi`;
584586- Ejecutar proyecto;
585587- Establecer punto de interrupción en *dbgcomponent* in main (1st) app;
586588- use *dbgcomponent* pascal code in second app;
587589- step through design-time component code in debug-session; do whatever is necessary;
588590
589591## See also
590592
591593- [[Extending the IDE]]
592594- [[Lazarus Packages]] - A guide for creating a package under Lazarus
593595- [[Components and Code examples]]
594596- [[Lazarus Components]]
595597- [[IDE Window: Add to Package]]
596598
597599You can post questions regarding this page [here](http://forum.lazarus.freepascal.org/index.php/topic,5789.0.html)
598600
599601---
600602*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