Editor de componentes e propriedades Delphi
(1) Prefácio
Este artigo usará um exemplo para descrever o desenvolvimento de componentes e o editor de propriedades.
O exemplo (TdsWaitDialogEx) é um componente visual que exibe um Dialog após chamar seu método show.
Ele contém um TAnimate, duas mensagens de prompt (ou seja, TLabel) e uma barra de progresso (TGauge).
Propriedades de enumeração: DialogStyle, AViposition
Propriedades do registro: Opções
O objeto da coleção de propriedades herda de TPersistent Neste exemplo, a coleção de propriedades AVISource contém TAnimate.
Propriedades de animação CommonAVI, FileName
O editor de propriedades é aplicado com a propriedade FileName do AVISource, ou seja, uma String FileName aparece durante a edição.
TOpenDialog, seu filtro de filtragem é *.avi
(2) Pacote de componentes dsDlgPack.dpk
Para facilitar a publicação, instalação, etc., deve ser utilizado o pacote de componentes .dpk.
Nas versões posteriores ao Delphi6 (não sei das versões anteriores ao D5), existem vários arquivos que o Delphi não lançou, como PRoxies.
Se esses arquivos forem usados ao instalar um componente, você poderá ignorá-los e usar o pacote que os contém.
Neste exemplo, o editor de propriedades usa o arquivo DesignEditors, e o arquivo Proxies é necessário no DesignEditors, portanto, este componente é publicado
O pacote (.dpk) contém designide, que resolve o problema da inexistência de Proxies, para que a instalação do componente seja bem-sucedida.
pacote dsDlgPack;
...
requer
rtl,
vcl,
VclSmp,
designide;
contém
dsDlgWaitEx em 'dsDlgWaitEx.pas' {DlgWaitEx},
dsDlgWaitExReg em 'dsDlgWaitExReg.pas';
fim.
(3) Arquivo de registro de componente dsDlgWaitExReg.pas
Pergunta: Por que precisamos usar esse arquivo com mais frequência? Porque:
Se o código em dsDlgWaitExReg.pas for mesclado em dsDlgWaitEx.pas, embora designide esteja incluído em dsDlgPack.dpk
Resolvido o problema de Proxies não existentes na instalação do componente, mas o problema de Proxies não existentes ainda ocorre quando a aplicação chama este componente.
Como os arquivos Proxies são necessários em DesignEditors, o código a seguir é formado em um arquivo separado e o aplicativo chama esse grupo;
O arquivo não precisa usar dsDlgWaitExReg.pas e pode ignorar Proxies sem nenhum problema.
unidade dsDlgWaitExReg;
interface
usa Classes, Diálogos, Formulários, dsDlgWaitEx, DesignIntf, DesignEditors;
tipo
TdsAVIFileNameProperty = class(TSringProperty) //O editor de propriedades usa o arquivo DesignEditors
público
function GetAttributes:TPropertyAttributes;override; //Substituição do método
procedimento Editar;override; //substituição do método
fim;
Cadastro de procedimentos;
implementação
Cadastro de procedimentos;
começar
//Registra este componente na página do componente Delisoft
RegisterComponents('Delisoft', [TdsWaitDialogEx]);
//Registra este editor de propriedades
RegisterPropertyEditor(TypeInfo(string), TdsAVISource, 'NomeArquivo', TdsAVIFileNameProperty);
fim;
{TdsAVIFileNameProperty}
função TdsAVIFileNameProperty.GetAttributes:TPropertyAttributes;
começar
resultado:=[paDialog];
fim;
procedimento TdsAVIFileNameProperty.Edit;
começar
com TOpenDialog.Create(aplicativo) faça
tentar
Filtro:='Arquivos AVI(*.avi)|*.avi|Todos os arquivos(*.*)|*.*';
se Executar então SetStrValue(FileName);
finalmente
livre;
fim;
fim;
fim.
(4) Arquivo de componente dsDlgWaitEx.pas
unidade dsDlgWaitEx;
{Defina todas as propriedades e métodos deste componente; entre eles, a propriedade BorderStyle do formato TDlgWaitEx é bsDialog, que é herdada diretamente do TPersistent, e o objeto de propriedade AVISource usa TdsAVISource. propriedades de enumeração são usadas (DialogStyle, AVIPosition) e propriedades de registro (Opções), etc.
}
interface
usa
Windows, Mensagens, SysUtils, Variantes, Classes, Gráficos, Controles, Formulários,
Diálogos, StdCtrls, Medidores, ComCtrls;
tipo
TDialogStyle = (dlgNormal, dlgStayOnTop);
TAVIPosition = (aviLeft, aviTop, aviBottom);
TDlgOptions = conjunto de (showAVI,showCaption,showMessage1,showMessage2,showProgress,ShowProgressText);
TDlgWaitEx = classe(TForm)
Animar1: TAnimate;
Medidor1: TGauge;
Rótulo1: TLabel;
Etiqueta2: TLabel;
procedimento FormClose(Sender: TObject; var Action: TCloseAction);
privado
FCloseAfter: DWord;
FUserFormClose: TCloseEvent;
público
propriedade UserFormClose: TCloseEvent lê FUserFormClose escreve FUserFormClose;
propriedade CloseAfter: DWORD lê FCloseAfter escreve FCloseAfter;
fim;
TdsAVISource = classe(TPersistente)
privado
FCommonAVI: TCommonAVI;
FFileName: string;
procedimento SetCommonAVI(const Valor: TCommonAVI);
procedimento SetFileName (const Valor: string);
protegido
público
publicado
propriedade CommonAVI: TCommonAVI lê FCommonAVI escreve SetCommonAVI padrão aviNone;
propriedade FileName: string lida FfileName escreve SetFileName;
fim;
TdsWaitDialogEx=class(TComponent)
privado
//Forma
FDlgForm:TDlgWaitEx;
FMessage1: string;
FMessage2: string;
FMessage1Font:TFont;
FMessage2Font:TFont;
FClegenda: string;
FDislogStyle:TDialogStyle;
FwordWrap:booleano;
FOptions:TDlgOptions;
FShowMessage1,FShowMessage2:booleano;
//AVI
Posição Favi: Posição TAVI;
FAviActive:booleano;
FshowAVI:booleano;
FAVIFonte: TdsAVIFonte;
//progresso
FProgressMax:inteiro;
FProgressMin:inteiro;
FProgressPos:inteiro;
FProgressStep:inteiro;
FShowProgress: Booleano;
FShowProgressText: Booleano;
//Evento
FOnPosChange: TNotifyEvent;
FOnShow: TNotifyEvent;
FOnFormHide: TCloseEvent;
procedimento SetProgressMax(const Valor: inteiro);
procedimento SetProgressMin(const Valor: inteiro);
procedimento SetProgressPos(const Valor: inteiro);
procedimento SetProgressStep(const Valor: inteiro);
procedimento DrawForm;
função setLableHeight(sCaption:string):integer;
procedimento setOptions(const valor:TDlgOptions);
procedimento setMessage1(const valor:string);
procedimento setMessage2(const valor:string);
procedimento setCaption(const valor:string);
procedimento SetMessage1Font(valor const:TFont);
procedimento SetMessage2Font(valor const:TFont);
função IsMessage1FontStored: Boolean;
função IsMessage2FontStored: Boolean;
procedimento setAVIPosition(const Valor: TAVIPosition);
procedimento SetAVISource(const Valor: TdsAVISource);
procedimento SetOnFormHide(const Valor: TCloseEvent);
protegido
procedimento DoPosChange virtual;
procedimento DoShow virtual;
público
construtor Criar (AOwner: substituição de TComponent);
substituição do destruidor;
procedimento FormShow;
procedimento FormHide;
procedimento FormUpdate;
procedimento ProgressStepIt;
publicado
//Forma
propriedade Mensagem1: string lida FMessage1 escreve setMessage1;
propriedade Mensagem2: string lida FMessage2 escreve setMessage2;
propriedade Message1Font: TFont lê FMessage1Font escreve SetMessage1Font armazenado IsMessage1FontStored;
propriedade Message2Font: TFont lê FMessage2Font escreve SetMessage2Font armazenado IsMessage2FontStored;
propriedade Legenda: string lida FCaption write setCaption;
propriedade DislogStyle:TDialogStyle leitura FDislogStyle gravação FDislogStyle;
propriedade wordWrap: boolean leitura FwordWrap gravação FwordWrap;
propriedade Opções:TDlgOptions ler FOptions escrever setOptions;
//AVI
propriedade AviActive: booleano leitura FAviActive gravação FAviActive;
propriedade AviPosition: TAVIPosition leitura FaviPosition gravação setAVIPosition;
propriedade AviSource: TdsAVISource lê FAVISource escreve SetAVISource;
//Progresso
propriedade ProgressMax: leitura de inteiro FProgressMax gravação SetProgressMax;
propriedade ProgressMin: inteiro lido FProgressMin gravação SetProgressMin;
propriedade ProgressPos: leitura de inteiro FProgressPos gravação SetProgressPos;
propriedade ProgressStep:inteiro leitura FProgressStep gravação SetProgressStep;
//Evento
propriedade OnPosChange: TNotifyEvent lê FOnPosChange escreve FOnPosChange;
propriedade OnShow: TNotifyEvent lê FOnShow escreve FOnShow;
propriedade OnHide: TCloseEvent lê FOnFormHide escreve SetOnFormHide;
fim;
implementação
{$R *.DFM}
{TdsAVISource}
procedimento TdsAVISource.SetCommonAVI(const Valor: TCommonAVI);
começar
se Valor = FCommonAVI então saia;
FCommonAVI := Valor;
NomeDoArquivo:='';
fim;
procedimento TdsAVISource.SetFileName(valor const: string);
começar
se Valor = FfileName então saia;
NomeArquivo:=valor;
FCommonAVI:=aviNone;
fim;
{TdsWaitDialogEx}
procedimento TdsWaitDialogEx.DoShow;
começar
se atribuído(FOnShow) então FOnShow(Self);
fim;
procedimento TdsWaitDialogEx.DoPosChange;
começar
se Atribuído(FOnPosChange) então FOnPosChange(Self);
fim;
procedimento TdsWaitDialogEx.SetAVISource(const Valor: TdsAVISource);
começar
se FAVISource=valor então saia;
FAVISource.Assign(Valor);
se (FAVISource.FFileName='')e(FAVISource.FCommonAVI=aviNone) então FshowAVI:=false;
se atribuído (FDlgForm) então
começar
FDlgForm.Animate1.Active:=falso;
FDlgForm.Animate1.FileName := '';
FDlgForm.Animate1.CommonAVI := aviNone;
se FshowAVI então
começar
se FAVISource.FfileName='' então
FDlgForm.Animate1.CommonAVI := FAVISource.FCommonAVI
outro
FDlgForm.Animate1.FileName := FAVISource.FfileName;
FDlgForm.Animate1.Active:=true;
fim;
DrawForm; //Animate1->Após alterações no AVI, o tamanho do Animate1 pode mudar ==> DrawForm
FDlgForm.Update;
fim;
fim;
função TdsWaitDialogEx.IsMessage1FontStored: Boolean;
começar
com FMessage1Font faça
Resultado :=
(Nome <> 'MS Sans Serif') ou
(Estilo <> []) ou
(Tamanho <> 8) ou
(Cor <> clWindowText) ou
(Conjunto de caracteres <> DEFAULT_CHARSET) ou
(Pitch <> fpDefault);
fim;
função TdsWaitDialogEx.IsMessage2FontStored: Boolean;
começar
com FMessage2Font faça
Resultado :=
(Nome <> 'MS Sans Serif') ou
(Estilo <> []) ou
(Tamanho <> 8) ou
(Cor <> clWindowText) ou
(Conjunto de caracteres <> DEFAULT_CHARSET) ou
(Pitch <> fpDefault);
fim;
procedimento TdsWaitDialogEx.SetMessage1Font (valor const: TFont);
começar
FMessage1Font.Assign(Valor);
se atribuído (FDlgForm) então
começar
FDlgForm.Label1.Font.Assign(Valor);
FDlgForm.Update;
fim;
fim;
procedimento TdsWaitDialogEx.SetMessage2Font (valor const: TFont);
começar
FMessage2Font.Assign(Valor);
se atribuído (FDlgForm) então
começar
FDlgForm.Label2.Font.Assign(Valor);
FDlgForm.Update;
fim;
fim;
procedimento TdsWaitDialogEx.setCaption(const valor:string);
começar
se valor=FCaption então saia;
FCCaption:=valor;
se não (showCaption em FOptions) então
começar
FCCaption:='';
saída;
fim;
se atribuído (FDlgForm) então
começar
FDlgForm.Caption := valor;
FDlgForm.atualização;
fim;
fim;
procedimento TdsWaitDialogEx.setMessage1(valor const:string);
var i:inteiro;
começar
se valor=FMessage1 então saia;
FMessagem1:=valor;
se atribuído (FDlgForm) então
começar
se não (showMessage1 em FOptions), então saia;
FDlgForm.Label1.Caption := valor;
i:=setLableHeight(FMessage1)+13;
se i<>FDlgForm.Label1.Height então DrawForm;
FDlgForm.atualização;
fim;
fim;
procedimento TdsWaitDialogEx.setMessage2(valor const:string);
var i:inteiro;
começar
se valor=FMessage2 então saia;
FMessagem2:=valor;
se atribuído (FDlgForm) então
começar
se não (showMessage2 em FOptions), então saia;
FDlgForm.Label2.Caption := valor;
i:=setLableHeight(FMessage2)+13;
se i<>FDlgForm.Label2.Height então DrawForm;
FDlgForm.atualização;
fim;
fim;