Cassic

Criando um Componente Visual

Autor: Tadeu Pereira


  Iremos criar um componente semelhante ao TEdit, mas o nosso componente só aceitará valores numéricos. Ele também terá métodos como o Extenso que nos trará o valor digitado escrito por extenso.

  Repita todos os procedimentos do componente anterior mudando apenas as opções abaixo:

  Ancestor Component: TCustomEdit
  Class Name: TNumEdit
  Pallete Page: CursoDelphi
  Unit File Name: NumEdit.pas

  Inclua o código abaixo:

01
unit NumEdit;
02
 
03
interface
04
 
05
uses
06
  SysUtils, Classes, Controls, StdCtrls, Dialogs;
07
 
08
type
09
  TNumEdit = class(TCustomEdit)
10
  private
11
      { Private declarations }
12
      procedure cmEnter(var message: TcmEnter); message cm_Enter;
13
      procedure cmExit(var message: TcmExit); message cm_Exit;
14
      procedure FormatarValor;
15
      procedure DesformatarValor;
16
      function VrCentena(I_Valor: Integer): string;
17
      function GetExtenso: string;
18
  protected
19
      { Protected declarations }
20
      procedure KeyPress(var Key: Char); override;
21
  public
22
      { Public declarations }
23
      constructor Create(AOwner: TComponent); override;
24
  published
25
      { Published declarations }
26
      property Decimal: Integer;
27
      property Moeda: string;
28
      property Valor: Currency;
29
      property Extenso: string;
30
      property Monetario: Boolean;
31
      property OnChange;
32
      property OnClick;
33
      property OnContextPopup;
34
      property OnDblClick;
35
      property OnDragDrop;
36
      property OnDragOver;
37
      property OnEndDock;
38
      property OnEndDrag;
39
      property OnEnter;
40
      property OnExit;
41
      property OnKeyDown;
42
      property OnKeyPress;
43
      property OnKeyUp;
44
      property OnMouseDown;
45
      property OnMouseMove;
46
      property OnMouseUp;
47
      property OnStartDock;
48
      property OnStartDrag;
49
  end;
50
 
51
procedure Register;
52
 
53
Implementation
54
 
55
procedure Register;
56
begin
57
  RegisterComponents('CursoDelphi', [TNumEdit]);
58
end;
59
 
60
end.

     Nas linha 12 e 13 temos duas mensagens de componente, nestas linhas temos o cm_Enter que corresponde ao evento OnEnter do componente, enquanto que cm_Exit corresponde ao evento OnExit do mesmo.  Após este esclarecimento pressione Ctrl+Shift+C e continue entrando com o código mostrado:

001
unit NumEdit;
002
 
003
interface
004
 
005
uses
006
  SysUtils, Classes, Controls, StdCtrls, Dialogs;
007
 
008
type
009
  TNumEdit = class(TCustomEdit)
010
  private
011
      FValor: Currency;
012
      // FExtenso: string;
013
      FMoeda: string;
014
      FDecimal: Integer;
015
      FMonetario: Boolean;
016
      procedure SetDecimal(const Value: Integer);
017
      // procedure SetExtenso(const Value: string);
018
      procedure SetMoeda(const Value: string);
019
      procedure SetMonetario(const Value: Boolean);
020
      procedure SetValor(const Value: Currency);
021
      { Private declarations }
022
      procedure cmEnter(var message: TcmEnter); message cm_Enter;
023
      procedure cmExit(var message: TcmExit); message cm_Exit;
024
      procedure FormatarValor;
025
      procedure DesformatarValor;
026
      function VrCentena(I_Valor: Integer): string;
027
      function GetExtenso: string;
028
  protected
029
      { Protected declarations }
030
      procedure KeyPress(var Key: Char); override;
031
  public
032
      { Public declarations }
033
      constructor Create(AOwner: TComponent); override;
034
  published
035
      { Published declarations }
036
      property Decimal: Integer read FDecimal write SetDecimal;
037
      property Moeda: string read FMoeda write SetMoeda;
038
      property Valor: Currency read FValor write SetValor;
039
      // property Extenso: string read FExtenso write SetExtenso;
040
      property Extenso: string read GetExtenso;
041
      property Monetario: Boolean read FMonetario
042
          write SetMonetario;
043
      property OnChange;
044
      property OnClick;
045
      property OnContextPopup;
046
      property OnDblClick;
047
      property OnDragDrop;
048
      property OnDragOver;
049
      property OnEndDock;
050
      property OnEndDrag;
051
      property OnEnter;
052
      property OnExit;
053
      property OnKeyDown;
054
      property OnKeyPress;
055
      property OnKeyUp;
056
      property OnMouseDown;
057
      property OnMouseMove;
058
      property OnMouseUp;
059
      property OnStartDock;
060
      property OnStartDrag;
061
  end;
062
 
063
procedure Register;
064
 
065
implementation
066
 
067
procedure Register;
068
begin
069
    RegisterComponents('CursoDelphi', [TNumEdit]);
070
end;
071
 
072
{ TNumEdit }
073
 
074
procedure TNumEdit.cmEnter(var message: TcmEnter);
075
begin
076
  DesformatarValor;
077
  Self.SelectAll;
078
  inherited;
079
end;
080
 
081
procedure TNumEdit.cmExit(var message: TcmExit);
082
begin
083
  Self.Text := Trim( Self.Text );
084
  if ( Self.Text = '-' ) or ( Self.Text = '+' )
085
      then Self.Text := Self.Text + '0';
086
  if ( Self.Text = '' ) then Self.FValor := 0
087
  else Self.FValor := StrToFloat( Self.Text );
088
  FormatarValor;
089
  inherited;
090
end;
091
 
092
constructor TNumEdit.Create(AOwner: TComponent);
093
begin
094
  inherited;
095
  Self.FDecimal := CurrencyDecimals;
096
  Self.FMoeda := CurrencyString;
097
  Self.FValor := 0;
098
  Self.FMonetario := True;
099
  Self.Text := '0';
100
  FormatarValor;
101
end;
102
 
103
procedure TNumEdit.DesformatarValor;
104
var
105
  Formato: string;
106
begin
107
  Formato := '%.' + IntToStr(Self.FDecimal) + 'f';
108
  Self.Text := Format(Formato, [Self.FValor]);
109
end;
110
 
111
procedure TNumEdit.FormatarValor;
112
var
113
  Formato: string;
114
begin
115
  Formato := '%.' + IntToStr(Self.FDecimal) + 'n';
116
  Self.Text := Format(Formato, [Self.FValor]);
117
end;
118
 
119
function TNumEdit.GetExtenso: string;
120
var
121
  Cifra: array[1..4, 1..2] of string;
122
  S_Valor, Retorno, PosNeg: string;
123
  IValor: integer;
124
begin
125
  S_Valor := Format('%f', [Self.FValor]);
126
  if ( StrToFloat(S_Valor) < 0 ) then PosNeg := ' - Negativo'
127
  else PosNeg := '';
128
  S_Valor := StringReplace(S_Valor, '-', '', [rfReplaceAll]);
129
  Result := 'Zero';
130
  if ( StrToFloat( S_Valor ) = 0 ) then Exit;
131
  if( Length( S_Valor ) > 12 ) then
132
      begin
133
          MessageDlg('Valor máximo válido "999.999.999,99"',
134
              mtError, [mbOk], 0);
135
          Exit;
136
      end;
137
  Cifra[01,01] := ' Milhão';
138
  Cifra[01,02] := ' Milhões';
139
  Cifra[02,01] := ' Mil';
140
  Cifra[02,02] := ' Mil';
141
  Cifra[03,01] := ' Real';
142
  Cifra[03,02] := ' Reais';
143
  Cifra[04,01] := ' Centavo';
144
  Cifra[04,02] := ' Centavos';
145
  Retorno := '';
146
  S_Valor := Copy('000000000,00', 1, 12 -
147
      Length( S_Valor )) + S_Valor;
148
  if ( StrToFloat( Copy(S_Valor, 11, 2) ) > 0 ) then
149
      begin
150
          IValor := StrToInt( Copy(S_Valor, 11, 2) );
151
          Retorno := VrCentena( IValor );
152
          if ( IValor = 1 ) then Retorno := Retorno + Cifra[04,01]
153
          else Retorno := Retorno + Cifra[04,02];
154
      end;
155
  if ( StrToFloat( Copy(S_Valor, 1, 9) ) <> 0 ) then
156
      begin
157
          if ( Length( Retorno ) > 0 )
158
              then Retorno := ' e ' + Retorno;
159
          if ( FMonetario ) then
160
              begin
161
                  if ( StrToFloat( Copy(S_Valor, 1, 9) ) = 1 )
162
                      then Retorno := Cifra[03,01] + Retorno;
163
                  if ( StrToFloat( Copy(S_Valor, 1, 9) ) > 1 )
164
                      then Retorno := Cifra[03,02] + Retorno;
165
              end;
166
      end;
167
  if ( StrToFloat( Copy(S_Valor, 7, 3) ) > 0 ) then
168
      begin
169
          IValor := StrToInt( Copy(S_Valor, 7, 3) );
170
          Retorno := VrCentena( IValor ) + Retorno;
171
      end;
172
  if ( StrToFloat( Copy(S_Valor, 4, 6) ) >= 1000 ) then
173
      begin
174
          IValor := StrToInt( Copy(S_Valor, 4, 3) );
175
          if ( StrToFloat( Copy(S_Valor, 7, 3) ) > 0 )
176
              then Retorno := ' e ' + Retorno;
177
          Retorno := VrCentena( IValor ) + Cifra[02,01] + Retorno;
178
      end;
179
  if ( StrToFloat( Copy(S_Valor, 1, 9) ) >= 1000000 ) then
180
      begin
181
          IValor := StrToInt( Copy(S_Valor, 1, 3) );
182
          if ( StrToFloat( Copy(S_Valor, 4, 6) ) > 0 )
183
              then Retorno := ' e ' + Retorno;
184
          if ( IValor = 1 ) then Retorno := Cifra[01,01] + Retorno
185
          else Retorno := Cifra[01,02] + Retorno;
186
          Retorno := VrCentena( IValor ) + Retorno;
187
      end;
188
  Result := Retorno + PosNeg;
189
end;
190
 
191
procedure TNumEdit.KeyPress(var Key: Char);
192
begin
193
  inherited;
194
  if ( Key in [',','.'] ) then
195
      begin
196
          Key := DecimalSeparator;
197
          if ( Pos(DecimalSeparator, Self.Text) > 1 ) then Key := #0;
198
      end
199
  else if ( Key in [#43, #45] ) then Self.Text := ''
200
  else if not( Key in ['0'..'9', #8, #13, #43, #45] )
201
      then Key := #0;
202
end;
203
 
204
procedure TNumEdit.SetDecimal(const Value: Integer);
205
begin
206
  FDecimal := Value;
207
end;
208
 
209
{
210
procedure TNumEdit.SetExtenso(const Value: string);
211
begin
212
  FExtenso := Value;
213
end;
214
}
215
 
216
procedure TNumEdit.SetMoeda(const Value: string);
217
begin
218
  FMoeda := Value;
219
end;
220
 
221
procedure TNumEdit.SetMonetario(const Value: Boolean);
222
begin
223
  FMonetario := Value;
224
end;
225
 
226
procedure TNumEdit.SetValor(const Value: Currency);
227
begin
228
  FValor := Value;
229
end;
230
 
231
function TNumEdit.VrCentena(I_Valor: Integer): string;
232
var
233
  IValor: array[1..3] of Integer;
234
  Unidade, Dezena, DezVinte, Centena: array[1..9] of string;
235
  SValor, Retorno: string;
236
begin
237
  Result := '';
238
  if ( I_Valor = 0 ) then Exit;
239
  if ( I_Valor = 100 ) then
240
      begin
241
          Result := 'Cem';
242
          Exit;
243
      end;
244
  SValor := Copy( '000', 1, 3 - Length(
245
      IntToStr( I_Valor ) ) ) + IntToStr( I_Valor );
246
  IValor[01] := StrToInt( Copy( SValor, 1, 1 ) );
247
  IValor[02] := StrToInt( Copy( SValor, 2, 1 ) );
248
  IValor[03] := StrToInt( Copy( SValor, 3, 1 ) );
249
  Unidade[01] := 'Um';
250
  Unidade[02] := 'Dois';
251
  Unidade[03] := 'Três';
252
  Unidade[04] := 'Quatro';
253
  Unidade[05] := 'Cinco';
254
  Unidade[06] := 'Seis';
255
  Unidade[07] := 'Sete';
256
  Unidade[08] := 'Oito';
257
  Unidade[09] := 'Nove';
258
  Dezena[01] := 'Dez';
259
  Dezena[02] := 'Vinte';
260
  Dezena[03] := 'Trinta';
261
  Dezena[04] := 'Quarenta';
262
  Dezena[05] := 'Cinqüenta';
263
  Dezena[06] := 'Sessenta';
264
  Dezena[07] := 'Setenta';
265
  Dezena[08] := 'Oitenta';
266
  Dezena[09] := 'Noventa';
267
  DezVinte[01] := 'Onze';
268
  DezVinte[02] := 'Doze';
269
  DezVinte[03] := 'Treze';
270
  DezVinte[04] := 'Quatorze';
271
  DezVinte[05] := 'Quinze';
272
  DezVinte[06] := 'Dezeseis';
273
  DezVinte[07] := 'Dezesete';
274
  DezVinte[08] := 'Dezoito';
275
  DezVinte[09] := 'Dezenove';
276
  Centena[01] := 'Cento';
277
  Centena[02] := 'Duzentos';
278
  Centena[03] := 'Trezentos';
279
  Centena[04] := 'Quatrocentos';
280
  Centena[05] := 'Quinhentos';
281
  Centena[06] := 'Seiscentos';
282
  Centena[07] := 'Setecentos';
283
  Centena[08] := 'Oitocentos';
284
  Centena[09] := 'Novecentos';
285
  Retorno := '';
286
  if ( IValor[01] > 0 ) then
287
      begin
288
          Retorno := Centena[ IValor[01] ];
289
          if ( IValor[02] + IValor[03] > 0 ) then Retorno :=
290
              Retorno + ' e ';
291
      end;
292
  if ( IValor[02] = 1 ) and ( IValor[03] <> 0 )
293
      then Retorno := Retorno + DezVinte[ IValor[03] ]
294
  else
295
      begin
296
          if ( IValor[02] > 0 ) then
297
              begin
298
                  Retorno := Retorno + Dezena[ IValor[02] ];
299
                  if( IValor[03] > 0 ) then Retorno := Retorno + ' e ';
300
              end;
301
          if ( IValor[03] > 0 ) then Retorno :=
302
              Retorno + Unidade[ IValor[03] ];
303
      end;
304
  Result := Retorno;
305
end;
306
 
307
end.

     Entre com um arquivo DCR e um bitmap para o novo componente (Figura 1). Depois acrescente este componente ao nosso pacote dê um Build. Não é preciso chamar o Install do pacote uma vez que o mesmo já está instalado.


Figura 1 – Imagem do componente TNumEdit