|
Creación de un componente paso a paso. IX | ||||||||||||
'Clavos'. Propiedad BitmapAnteriormente dijimos que íbamos a utilizar dos tipos de objetos de imagen, TPicture ya utilizado y uno TBitmap. Éste último lo utilizaremos para dibujar 4 clavos alrededor del control cuando éste tiene el foco (que se muestren estos 'clavos' va a ser opcional dependiendo de otra propiedad). Por lo tanto definiremos dos propiedades Screw y ShowScrew, la primera será el bitmap que queremos utilizar como 'clavo' y la segunda si queremos mostrarlos o no. Los pasos a seguir con los de siempre, definir dos variables en la parte 'Private' de nuestro componente, definir las propiedades basadas 'manejadoras' de las variables anteriores. En el constructor crearemos el objeto imagen, que destruiremos en el destructor. Pero queremos algo más, por defecto y en el caso de que no se elija ninguna imagen como 'clavo' haremos que aparezca uno por defecto (sólo si ShowCrew es true, claro). Para conseguir esto, vanos a crear un archivo de tipo recurso(.res) que añadiremos en nuestro componente, para ello utilizaremos ImageEdit, que es una herramienta que se encuentra en directorio Bin de delphi : "C:\Archivos de programa\Borland\Delphi6\Bin\imagedit.exe" : Al fichero los llamaremos "panselre.res" y lo guardaremos en el mismo directorio que el código de nuestro componente. Después creamos el bitmap (de 8x8) en este fichero de recursos, al bitmap le pondremos de nombre 'CLAVO':
Ahora, para que al compilar se incluya el recurso dentro del código compilado, habrá que añadir la directiva : {$R panresel} para cargar un recurso de bitmap dentro de un objeto usaremos el método de la Clase TBitmap : LoadFromResourceName (FScrew.LoadFromResourceName(Hinstance,'CLAVO');). (El código completo del componente después del siguiente apartado) Icono para la paleta de componentes.Una vez completado el componente (o si se prefiere en cualquier momento de la creación del mismo) deberíamos dibujar un icono que represente a nuestro componente en la paleta de componentes de delphi :
Nosotros cuando en la definición de nuestro componente escribimos en el procedimiento Register el siguiente código : RegisterComponents('Ejemplo', [TPanelSel]); estamos diciendo al entorno de Delphi que añada nuestro componente a la carpetilla (pestaña) 'Ejemplo' de la paleta de componentes, en caso de no existir, el entorno (IDE) de delphi creará una con dicho nombre y dentro de ella aparecerá un icono como representación de nuestro componente :
El icono mostrado es que que el IDE de delphi asigna por defecto cuando no le hemos indicado otro. Para crear uno propio debemos seguir los siguientes pasos : 1.- Mediante ImageEdit debéis crear un archivo nuevo de tipo .dcr (Component Resource File) que debe llamarse igual que la unidad de nuestro componente (PanelSel.dcr), y dentro de este fichero crear un recurso Bitmap de 24x24 pixels y cuyo nombre debe ser el del tipo de nuestro componente en mayúsculas : TPANELSEL : Edite el bitmap y haga el dibujo que crea que mejor representa al componente, guarde el archivo en el mismo directorio que nuestro componente. Para que el IDE acepte esto cambios debemos añadir al paquete dentro del cual definimos nuestro componente (figura 1), para ello lo mejor es que eliminemos nuestro componente del paquete y después volvamos a añadirlo, con esto conseguimos que los ficheros PanelSel.pas y PanelSel.dcr se incorporen al paquete, después compilar y 'voilá' en la pestaña ejemplo aparecerá nuestro bitmap :
Código Completo.unit PanelSel; interface uses Windows, Messages, SysUtils, Classes, Controls, Graphics; type TPanelSel = class(TCustomControl) private FPicture:TPicture; FColors:array[0..5] of TColor; FOnMouseEnter, FOnMouseLeave:TNotifyEvent; FBorder:Boolean; FBorderWidth:Integer; FOver:Boolean; FPosXPicture:Word; FText:TCaption; FTextFont:TFont; FPosXText:Word; FAlignment, FTextAlign: TAlignment; FScrew:TBitmap; FShowScrew:Boolean; procedure SetPicture(Value:TPicture); procedure SetColors(Index:Integer;Value:TColor); function GetColors(Index:integer):TColor; procedure SetBorder(Value:Boolean); procedure SetBorderWidth(Value:integer); procedure SetPosXPicture(Value:Word); procedure SetText(Value:TCaption); procedure SetPosXText(Value:Word); procedure SetTextFont(Value:TFont); procedure FontChanged(Sender: TObject); procedure SetAlignment(Value: TAlignment); procedure SetTextAlign(Value: TAlignment); procedure SetScrew(Value:TBitmap); { Private declarations } protected procedure WMSetFocus(var Message: TWMSetFocus); message WM_SETFOCUS; procedure WMKillFocus(var Message: TWMSetFocus); message WM_KILLFOCUS; procedure CMMouseEnter(var Message: TMessage); message CM_MOUSEENTER; procedure CMMouseLeave(var Message: TMessage); message CM_MOUSELEAVE; procedure CMTextChanged(var Message: TMessage); message CM_TEXTCHANGED; procedure Paint; override; procedure KeyPress(var Key: Char);override; procedure Click;override; { Protected declarations } public constructor Create(AOwner:TComponent);override; destructor Destroy;override; property Colors[Index:Integer]:TColor read GetColors Write SetColors; Procedure SetAllTexts(S:String); { Public declarations } published property Alignment: TAlignment read FAlignment write SetAlignment default taLeftJustify; property TextAlign: TAlignment read FTextAlign write SetTextAlign default taLeftJustify; property Picture:TPicture read FPicture Write SetPicture; property Border:Boolean read FBorder Write SetBorder default True; property BorderWidth:integer read FBorderWidth Write SetBorderWidth default 1; property Color:TColor Index 0 read GetColors Write SetColors default clBtnFace; property BorderColor:TColor Index 1 read GetColors Write SetColors default clBlack; property FocusedColor:TColor Index 2 read GetColors Write SetColors default clBtnHighlight; property FocusedBorderColor:TColor Index 3 read GetColors Write SetColors default clBlack; property OverColor:TColor Index 4 read GetColors Write SetColors default clBtnShadow; property OverBorderColor:TColor Index 5 read GetColors Write SetColors default clBlack; property PosXPicture:Word read FPosXPicture Write SetPosXPicture default 10; property PosXText:Word read FPosXText Write SetPosXText default 50; property Caption; property Text:TCaption read FText Write SetText; property TextFont:TFont read FTextFont Write SetTextFont; property Screw:TBitmap read FScrew Write SetScrew; property ShowScrew:Boolean read FShowScrew Write FShowScrew default false; property Font; property Tabstop; property BiDiMode; property TabOrder; property Action; property Align; property Anchors; property Visible; property Enabled; property Constraints; property DragCursor; property DragKind; property DragMode; property ParentBiDiMode; property ParentFont; property ParentShowHint; property PopupMenu; property ShowHint; property OnMouseEnter:TNotifyEvent read FOnMouseEnter Write FOnMouseEnter; property OnMouseLeave:TNotifyEvent read FOnMouseLeave Write FOnMouseLeave; property OnClick; property OnContextPopup; property OnDblClick; property OnDragDrop; property OnDragOver; property OnEndDock; property OnEndDrag; property OnMouseDown; property OnMouseMove; property OnMouseUp; property OnStartDock; property OnStartDrag; property OnEnter; property OnExit; { Published declarations } end; Function _BiDiMode(Alignment: TAlignment;BiDi:TBiDiMode):TAlignment; procedure Register; implementation {$R panselre} Function _BiDiMode(Alignment: TAlignment;BiDi:TBiDiMode):TAlignment; begin Result :=Alignment; if (SysLocale.MiddleEast) and (BiDi= bdRightToLeft) then case Alignment of taLeftJustify: Result := taRightJustify; taRightJustify: result := taLeftJustify; end; end; Procedure TPanelSel.SetAllTexts(S:String); begin if S='' then begin Caption:=''; Text:=''; end else if pos('|',S)>0 then begin caption:=copy(S,1,pos('|',S)-1); text:=copy(S,pos('|',S)+1,length(S)); end else Caption:=S; end; constructor TPanelSel.Create(AOwner:TComponent); begin inherited; FScrew:=TBitmap.Create; FScrew.LoadFromResourceName(Hinstance,'CLAVO'); FShowScrew:=False; FOver:=False; Tabstop:=True; FBorder:=True; FBorderWidth:=1; FColors[0]:= clBtnFace; FColors[1]:=clBlack; FColors[2]:=clBtnHighlight; FColors[3]:=clBlack; FColors[4]:= clBtnShadow; FColors[5]:=clBlack; FPicture:=TPicture.Create; FTextFont:=TFont.Create; FTextFont.OnChange:=FontChanged; FPosXPicture:=10; FPosXText:=50; FText:=''; Font.Style:=[fsBold]; FAlignment:=taLeftJustify; FTextAlign:=taLeftJustify; end; destructor TPanelSel.Destroy; begin FTextFont.Free; FPicture.Free; inherited; end; procedure TPanelSel.SetScrew(Value:TBitmap); begin if Assigned(Value) then begin if (Value.Width>8) or (Value.Height>8) then raise Exception.Create('La imagen debe ser como máximo de 8x8 pixels') else FScrew.Assign(Value); end else FScrew.LoadFromResourceName(Hinstance,'CLAVO'); Invalidate; end; procedure TPanelSel.CMTextChanged(var Message: TMessage); begin inherited; invalidate; end; procedure TPanelSel.WMSetFocus(var Message: TWMSetFocus); begin inherited; Invalidate; end; procedure TPanelSel.WMKillFocus(var Message: TWMSetFocus); begin inherited; Invalidate; end; procedure TPanelSel.CMMouseEnter(var Message: TMessage); begin inherited; if Assigned(FOnMouseEnter) then FOnMouseEnter(Self); FOver:=True; Invalidate; end; procedure TPanelSel.CMMouseLeave(var Message: TMessage); begin inherited; if Assigned(FOnMouseLeave) then FOnMouseLeave(Self); FOver:=False; Invalidate; end; procedure TPanelSel.SetPicture(Value:TPicture); begin FPicture.Assign(Value); repaint; end; procedure TPanelSel.SetPosXPicture(Value:Word); begin if FPosXPicture<>Value then if value>0 then begin FPosXPicture:=Value; invalidate; end; end; procedure TPanelSel.SetPosXText(Value:Word); begin if FPosXText<>Value then if Value>0 then begin FPosXText:=Value; invalidate; end; end; procedure TPanelSel.SetText(Value: TCaption); begin if FText<>Value then begin FText:=Value; invalidate; end; end; procedure TPanelSel.SetTextFont(Value:TFont); begin FTextFont.Assign(Value); end; procedure TPanelSel.FontChanged(Sender: TObject); begin invalidate; end; procedure TPanelSel.SetBorder(Value:Boolean); begin if FBorder<>Value then begin FBorder:=Value; Invalidate; end; end; procedure TPanelSel.SetBorderWidth(Value:integer); begin if FBorderWidth<>Value then begin if Value>0 then FBorderWidth:=Value; Invalidate; end; end; procedure TPanelSel.SetColors(Index:Integer;Value:TColor); begin if FColors[Index]<>Value then begin FColors[Index]:=Value; Invalidate; end; end; Function TPanelSel.GetColors(Index:Integer):TColor; begin Result:=FColors[Index]; end; procedure TPanelSel.Click; begin inherited; SetFocus; end; procedure TPanelSel.KeyPress(var Key: Char); begin if (Key=#13) or (Key=#32) then Click; Key:=#0; end; procedure TPanelSel.SetAlignment(Value: TAlignment); begin if FAlignment<>Value then begin FAlignment:=Value; Invalidate; end; end; procedure TPanelSel.SetTextAlign(Value: TAlignment); begin if FTextAlign<>Value then begin FTextAlign:=Value; Invalidate; end; end; procedure TPanelSel.Paint; const AAlignment : array[taLeftJustify..taCenter] of uchar=(DT_LEFT,DT_RIGHT,DT_CENTER); var X, Y, W, H: Integer; r:TRect; Flags:Cardinal; despv,desph:Integer; begin despv:=3; Desph:=0; if border then begin despv:=despv+BorderWidth; Desph:=BorderWidth-1; end; with Canvas do begin setbkmode(Handle,TRANSPARENT); Pen.Width:=BorderWidth; Pen.Color:=BorderColor; Brush.Style:=bsSolid; Brush.Color:=Color; X := Pen.Width div 2; Y := X; W := Width - Pen.Width + 1; H := Height - Pen.Width + 1; if Focused then begin Pen.Color:=FocusedBorderColor; Brush.Color:=FocusedColor; end; if FOver then begin Pen.Color:=OverBorderColor; Brush.Color:=OverColor; end; FillRect(ClientRect); Brush.Style:=bsClear; if Assigned(Picture.Graphic) then begin Picture.Graphic.Transparent:=true; Draw(BorderWidth+PosXPicture,((Height-Picture.Graphic.Height) div 2),Picture.Graphic); end; if Border then Rectangle(X, Y, X + W, Y + H); Flags:=AAlignment[_BiDiMode(Alignment,BiDiMode)] or DT_NOPREFIX or DT_END_ELLIPSIS; R:=Rect(posxText+desph,despv,width-desph,height-despv); Font:=self.Font; Drawtext(handle,PChar(caption),-1,R,flags); Flags:=DT_WORDBREAK or AAlignment[_BiDiMode(TextAlign,BiDiMode)] or DT_NOPREFIX; R:=Rect(posxText+desph,TextHeight(Caption)+despv,width-despv,height-despv); Font:=self.TextFont; DrawText(Handle, PChar(Text), -1, R, Flags); if Focused and ShowScrew then begin FScrew.Transparent:=True; FScrew.TransparentMode:=tmAuto; Draw(desph+2,desph+2,FScrew); Draw(Width-desph-2-FScrew.Width,desph+2,FScrew); Draw(desph+2,Height-desph-2-FScrew.Height,FScrew); Draw(Width-desph-2-FScrew.Width,Height-desph-2-FScrew.Height,FScrew); end; end; end; procedure Register; begin RegisterComponents('Ejemplo', [TPanelSel]); end; end. |