revista the club megazine - 12/ · pdf filedelphi é marca registrada da borland...

30

Upload: danghuong

Post on 22-Mar-2018

226 views

Category:

Documents


1 download

TRANSCRIPT

Page 1: Revista The Club Megazine - 12/ · PDF fileDelphi é marca registrada da Borland International, as ... DBGrid - Como fazer quebra de ... clique no checkbox “Create a new form
Page 2: Revista The Club Megazine - 12/ · PDF fileDelphi é marca registrada da Borland International, as ... DBGrid - Como fazer quebra de ... clique no checkbox “Create a new form

Revista The Club Megazine - 12/2003A utilização, reprodução, apropriação, armazenamento em banco de dados,sob qualquer forma ou meio, de textos, fotos e outras criações intelectuaisem cada publicação da revista “The Club” são terminantemente proibidos

sem autorização escrita dos titulares dos direitos autorais.Copyright© The Club® 2003

Page 3: Revista The Club Megazine - 12/ · PDF fileDelphi é marca registrada da Borland International, as ... DBGrid - Como fazer quebra de ... clique no checkbox “Create a new form

MeGAZINEMeGAZINEMeGAZINEMeGAZINEMeGAZINE 33333

EDITORIALEDITORIALEDITORIALEDITORIALEDITORIAL

EditorialEditorialEditorialEditorialEditorial

Celso Jefferson PaganelliPresidente - The Club

Editorial ............................................................................ 03Dicas & Truques ................................................................. 04Papel Personalizado (Windows XP/NT/2000) ...................... 07LiveUpdate - Atualizando aplicações via Web .................... 12Retrospectiva .................................................................... 16Rave Report - Imprimindo Etiquetas .................................. 18Trabalhando com Procedures e Funções ............................ 23

THE CLUBAv. Celso Ferreira da Silva, 190

Jd. Europa - Avaré - SP - CEP 18.707-150Informações: (0xx14) 3732-3689

Suporte: (0xx14) 3733-1588 - Fax: (0xx14) 3732-0987

Internethttp://www.theclub.com.br

Cadastro: [email protected]: [email protected]ções: [email protected]

DúvidasCorrespondência ou fax com dúvidas devem serenviados ao - THE CLUB, indicando "Suporte".

OpiniãoSe você quer dar a sua opinião sobre o clube em

geral, mande a sua correspondência para a seção"Tire sua dúvida".

ReproduçãoA utilização, reprodução, apropriação,

armazenamento em banco de dados, sob qualquerforma ou meio, de textos, fotos e outras criações

intelectuais em cada publicação da Revista“The Club” são terminantemente proibidos sem

autorização escrita dos titulares dos direitosautorais.

Copyright© The Club® 2003

Impressão e acabamento:Impressos Gril - Gril Gráfica e Repr. Ind. Ltda.

Tel.: (0xx14) 3762.1345 - Fax: (0xx14) 3762.1259Rua São Paulo, 447 - Cep 18.740-000

Taquarituba - SPTiragem: 5.000 exemplares

Diretor - Presidente

Celso Jefferson M. Paganelli

Diretor Técnico

Mauro Sant’Anna

Delphi é marca registrada da Borland International, asdemais marcas citadas são registradas pelos seus

respectivos proprietários.

Olá amigos,

Nos aproximamos de mais um final de ano e neste momento é tempo de fazermosum balanço de tudo que fizemos durante 2003. Com certeza muitos obstáculos foramvencidos, muita informação e conhecimento foi adquirida e 2004 vem abrir as portaspara novos desafios que juntos iremos superar um a um, mantendo esta nossa parceriade sucesso! Assim sendo, queremos agradecer a você que esteve conosco o ano todo ouque se juntou agora ao The Club, fazendo de nós por mais um ano o "Maior Clube deProgramadores do Brasil", sinceramente, muito obrigado, um Feliz Natal e um 2004cheio de sucesso!

Enquanto 2004 não chega, confira o que preparamos para esta edição, começandocom algumas das dicas mais solicitadas ao suporte técnico. Continuando, temos umartigo sobre configuração de papel no Windows XP, assunto este que "vinha" causandopreocupação entre muitos programadores, mas agora, considere como resolvido.

Aproveitando tudo de bom que a intenet nos proporciona, elaboramos um pequenoartigo sobre como atualizar aplicações via web, isso com certeza dará um toque aindamais profissional ao seu produto.

E atendendo várias solicitações, estamos publicando mais um artigo sobre o RaveReports, desta vez demonstrando como gerar etiquetas.

E para finalizar, quem nunca teve dúvidas sobre funções e procedures no Delphi?Bem, pensando nisso estamos publicando um artigo onde procuramos expor várias daspossibilidades que o object pascal nos oferece.

Boa leitura e sucesso à todos,

Page 4: Revista The Club Megazine - 12/ · PDF fileDelphi é marca registrada da Borland International, as ... DBGrid - Como fazer quebra de ... clique no checkbox “Create a new form

MeGAZINEMeGAZINEMeGAZINEMeGAZINEMeGAZINE44444

Retornar as contas de EmailRetornar as contas de EmailRetornar as contas de EmailRetornar as contas de EmailRetornar as contas de Email

Nesta dica iremos demonstrar como obter as contas de emailregistradas na Máquina, verificando as informaçõesarmazenadas do registrador do Windows.

Neste exemplo iremos utilizar um componente TListBox e umTButton...

implementation

uses Registry;

{$R *.DFM}

{ Evento OnShow do Formulário }

procedure TForm1.FormShow(Sender: TObject);

var Reg: TRegistry;

begin

Reg := TRegistry.Create;

try

Reg.RootKey := HKEY_CURRENT_USER;

Reg.OpenKey(‘\Software\Microsoft\Internet

Account Manager\Accounts’, False);

Reg.GetKeyNames(ListBox1.Items);

finally

Reg.CloseKey;

Reg.Free;

end;

end;

{ evento OnClick do TButton }

procedure TForm1.Button1Click(Sender: TObject);

var Reg: TRegistry;

sKey : String;

begin

if ListBox1.ItemIndex = -1 then

Exit;

Reg := TRegistry.Create;

try

Reg.RootKey := HKEY_CURRENT_USER;

sKey := ‘\Software\Microsoft\Internet Account

Manager\Accounts\’;

sKey := sKey +

ListBox1.Items[ListBox1.ItemIndex];

Reg.OpenKey(sKey, False);

if Reg.ValueExists(‘SMTP Server’) then

ShowMessage( ‘O SMTP da conta selecionada é

:’+#13+ Reg.ReadString(‘SMTP Server’) )

else

ShowMessage(‘SMTP não existe para esta

conta’);

finally

Reg.CloseKey;

Reg.Free;

end;

end;

Dicas & TDicas & TDicas & TDicas & TDicas & Truquesruquesruquesruquesruques

Page 5: Revista The Club Megazine - 12/ · PDF fileDelphi é marca registrada da Borland International, as ... DBGrid - Como fazer quebra de ... clique no checkbox “Create a new form

MeGAZINEMeGAZINEMeGAZINEMeGAZINEMeGAZINE 55555

Obter papéis disponíveis noObter papéis disponíveis noObter papéis disponíveis noObter papéis disponíveis noObter papéis disponíveis noWindowsWindowsWindowsWindowsWindows

Existem APIs que possibilitam listar os papéis disponíveispara uma impressora instalada no Windows...

implementation

uses Printers, WinSpool;

{$R *.dfm}

procedure GetPaperNames(List: TStrings);

type

TPaperName = Array [0..63] of Char;

TPaperNameArray = Array [1..High(Integer) div

Sizeof(TPaperName)] of TPaperName;

PPapernameArray = ^TPaperNameArray;

Var

Device, Driver, Port: Array [0..255] of Char;

hDevMode: THandle;

i, numPaperformats: Integer;

pPaperFormats: PPapernameArray;

begin

Printer.PrinterIndex := -1;

Printer.GetPrinter(Device, Driver,

Port, hDevmode);

numPaperformats := WinSpool.DeviceCapabilities

( Device, Port, DC_PAPERNAMES, Nil, Nil );

If numPaperformats > 0 Then

Begin

GetMem( pPaperformats, numPaperformats * Sizeof(

TPapername ));

try

WinSpool.DeviceCapabilities( Device, Port,

DC_PAPERNAMES, Pchar( pPaperFormats ), Nil);

List.clear;

For i:= 1 To numPaperformats Do

List.add( pPaperformats^[i] );

finally

FreeMem( pPaperformats );

end;

End;

End;

{ Mostra os papéis em um componente Memo }

procedure TForm1.Button1Click(Sender: TObject);

begin

GetPaperNames(Memo1.Lines);

End;

External Error 46External Error 46External Error 46External Error 46External Error 46 Aplicações escritas em Delphi 2 ao 7 que usem ou não acesso

a banco de dados ou arquivos de qualquer natureza, podem a vircongelar a máquina apresentando este erro.

Foi possível simular este erro em algumas máquinas, em

outras apenas congela e em outras é apresentada a famosa telaazul do Windows.

Isso acontece porque as placas mãe que estão sendo

produzidas a algum tempo foram “otimizadas” para rodarem como Windows XP. Sendo assim caso estejamos rodando o Delphinestas placas com Windows 98 o hardware pode retornar umainstrução diferente da esperada pelo sistema operacional e peloDelphi ocasionando o erro.

Nas mesmas máquinas que apresentavam o erro bastou

substituir o sistema operacional para Windows XP que o sistemavoltou a rodar sem maiores problemas.

Informação enviada pelo sócio Wellington Eugênio Miguel de Goiânia – GO.

Array – Deletar elemento peloArray – Deletar elemento peloArray – Deletar elemento peloArray – Deletar elemento peloArray – Deletar elemento peloíndiceíndiceíndiceíndiceíndice

Demonstraremos aqui como implementar uma rotina paradeletar elementos de um array dinâmico através de seu índices.

uses Types;

private

{ Private declarations }

Matrix: TStringDynArray;

public

{ Public declarations }

end;

var

Form1: TForm1;

implementation

{$R *.dfm}

{ TStringDynArray = array of String, unit Types }

procedure DeleteFromIndex(var S: TStringDynArray;

Element: integer);

var

Dicas & TDicas & TDicas & TDicas & TDicas & Truquesruquesruquesruquesruques

Page 6: Revista The Club Megazine - 12/ · PDF fileDelphi é marca registrada da Borland International, as ... DBGrid - Como fazer quebra de ... clique no checkbox “Create a new form

MeGAZINEMeGAZINEMeGAZINEMeGAZINEMeGAZINE66666

Idx: integer;

begin

for Idx := Element to High(S)-1 do

S[Idx] := S[Idx+1];

SetLength(S, High(S)-1) ;

end;

{Preenche o Array }

procedure TForm1.btnPreencheClick(Sender: TObject);

var

i: Integer;

begin

{ Ajusta array }

SetLength(Matrix, 9);

{ Preenche }

for i := Low(Matrix) to High(Matrix) do

begin

Matrix[i] := Format(‘Elemento n. %d’, [i]);

{ mostra no ListBox }

ListBox1.items.Add(Matrix[i]);

end;

end;

{ Deleta elemento e mostra novamente }

procedure TForm1.Button2Click(Sender: TObject);

var

i: integer;

begin

{ Delete elemento 5 }

DeleteFromIndex(Matrix, 5);

{ mostra no ListBox }

ListBox1.Clear;

for i := Low(Matrix) to High(Matrix) do

ListBox1.items.Add(Matrix[i]);

end;

Dicas & TDicas & TDicas & TDicas & TDicas & Truquesruquesruquesruquesruques

DBGrid - Como fazer quebra deDBGrid - Como fazer quebra deDBGrid - Como fazer quebra deDBGrid - Como fazer quebra deDBGrid - Como fazer quebra delinhaslinhaslinhaslinhaslinhas

Iremos demonstrar aqui como fazer quebra de linhas no textoapresentado em um DBGrid. Para isso, será necessáriodeclararmos um tipo para poder acessar propriedades protegidasdo mesmo.

{ tipo para acessar propriedades protegidas }

type

TGrid = class(TCustomDBGrid);

{ Flags de alinhamento }

const

AlignFlags : array [TAlignment] of Integer =

( DT_LEFT or DT_WORDBREAK or DT_EXPANDTABS or

DT_NOPREFIX, DT_RIGHT or DT_WORDBREAK or

DT_EXPANDTABS or DT_NOPREFIX, DT_CENTER or

DT_WORDBREAK or DT_EXPANDTABS or

DT_NOPREFIX );

RTL: array [Boolean] of Integer = (0,

DT_RTLREADING);

var

Form1: TForm1;

implementation

{$R *.dfm}

{

Evento OnDrawColumnCell do DBGrid.

}

procedure TForm1.DBGrid1DrawColumnCell(Sender:

TObject; const Rect: TRect;

DataCol: Integer; Column: TColumn; State:

TGridDrawState);

var

R: TRect;

begin

with DBGrid1 do

begin

if DataCol = 1 then { Verifica se é a 2ª coluna}

begin

CopyRect(R, Rect);

Canvas.FillRect(Rect);

{

Ajusta limite para Quebrar o texto, neste caso,

verifica a largura da coluna

}

R.Right := R.BottomRight.X;

{ desenha o texto na "área" determinada em "R" }

DrawText(Canvas.Handle,

PChar(Column.Field.AsString),

StrLen(PChar(Column.Field.AsString)), R,

DT_EXPANDTABS or DT_WORDBREAK );

end;

end;

end;

{ Evento OnCreate do Form }

procedure TForm1.FormCreate(Sender: TObject);

begin

{ Ajusta altera padrão para as linhas }

TGrid(DBGrid1).DefaultRowHeight := 50;

end;

Page 7: Revista The Club Megazine - 12/ · PDF fileDelphi é marca registrada da Borland International, as ... DBGrid - Como fazer quebra de ... clique no checkbox “Create a new form

MeGAZINEMeGAZINEMeGAZINEMeGAZINEMeGAZINE 77777

IntroduçãoFrequentemente deparamo-nos com necessidades de

imprimir em um tipo de papel diferentes do tipos pré-definidos noWindows (A4, Carta, Oficio), e isso, no caso do Windows 9x éfacilmente resolvido bastando definir e configurar o tipo de papelPersonalizado, informando sua altura e largura e pronto, bastaráenviar a impressão via nosso aplicativo que tudo irá funcionarperfeitamente. Contudo, o mesmo não ocorre o Windows XP, NTe 2000. Nestes SOs a “coisa” funciona um pouco diferente e nestepequeno artigo estaremos apresentado algumas soluções simples,porém, eficazes.

Trabalhando com FormuláriosNo Windows XP, NT e 2000, se adentrarmos as propriedades

da impressora e procurarmos pelo tipo de papel Personalizado nãoiremos encontrar. Isso na realidade, não é nenhuma deficiênciadestes SOs e muito menos do driver da referida impressora, massim, a forma de trabalho é baseada em formulários que podem serdefinidos pelo usuário, ou seja, você poderá ter N especificações detamanhos personalizados de papel, definindo um nome ecaracterísticas diferentes à cada um deles. Assim sendo, ao invésde apenas um tipo de Papel Personalizado (como ocorre no Windows9x), você pode ter N tipos.

Vamos primeiro, criar um formulário manualmente paramelhor entendermos este conceito. Para isso, acesse o menu deimpressoras do Windows, conforme demonstra a figura 1.

Papel PersonalizadoPapel PersonalizadoPapel PersonalizadoPapel PersonalizadoPapel PersonalizadoSolucionando problemas emSolucionando problemas emSolucionando problemas emSolucionando problemas emSolucionando problemas em

Windows XP, NT e 2000Windows XP, NT e 2000Windows XP, NT e 2000Windows XP, NT e 2000Windows XP, NT e 2000

por Alessandro Ferreira, [email protected]

Figura 1 – Painel de Impressoras

Importante: Ao acessar o painel de impressoras, não selecionenenhuma impressora, apenas, vá direto ao menu e escolha o

ítem “Server Properties”.

DelphiDelphiDelphiDelphiDelphi

Page 8: Revista The Club Megazine - 12/ · PDF fileDelphi é marca registrada da Borland International, as ... DBGrid - Como fazer quebra de ... clique no checkbox “Create a new form

MeGAZINEMeGAZINEMeGAZINEMeGAZINEMeGAZINE88888

DelphiDelphiDelphiDelphiDelphi

Após acessar o ítem “Server Properties”, irá visualizar uma telaparecida com a apresentada na figura 2.

Figura 2 – Server Properties.

Bem, a criação do formulário é bastante simples. Para isso,clique no checkbox “Create a new form”. Ao clicar, observe queautomaticamente serão habilitados os campos “Form name”, e oscampos de configuração de tamanho e margem. O primeiro passoé informar um nome ao nosso novo formulário, como por exemploTheClub20x20, o qual iremos ajustar com as medidas de20x20cm. Então, configure os parâmetros Height (Altura), Width(Largura), ambos para 20cm. Ajuste também os parâmetros Left,Right, Top e Bottom, todos para 1cm. Após isso, clique no botão “SaveForm”. O resultado final será semelhante ao apresentado da figura3.

Com isso, finalizamos a criação de nosso formulário personalizadono Windows XP, NT e 2000. Para utiizá-lo, bastará você acessaras propriedades de sua impressora e definir este formulário sendo opapel padrão.

Imprimindo via DelphiAté agora vimos apenas como criar e definir o formulário,

contudo, tudo de forma manual e acredito que isso não váatender 100% das necessidades de nós, programadores, pois,deixar este tipo de configuração para o usuário final fazer, com

Figura 3 – Server Properties com novo papel criado

certeza irá causar grandes “dores de cabeça”, e pensando nisso,vamos demonstrar como fazer todas estas configuraçõesdiretamente via Delphi, desde a criação do formulário personalizadoaté a sua definição como padrão nas propriedades da impressora.

Primeiramente, vamos implementar uma rotinagenérica capaz de criar os formulários no Windows, setando asdefinições desejadas... Acompanhe o código na listagem 1.

implementation

uses Printers, WinSpool, unQuickReport, QrPrNtr;

{$R *.dfm}

procedure SetCustomForm(FormName: string; ax,ay

:integer);

type

TFormInfos = Array [1..1024] of Form_Info_1;

PFormInfos = ^TFormInfos;

var

DevMode: PDeviceMode;

DeviceMode, hPrinter: THandle;

Device, Driver, Port: Array[0..255] of Char;

FormInfos: PFormInfos;

pForm: ^Form_Info_1;

cbNeeded, cReturned: DWORD;

Page 9: Revista The Club Megazine - 12/ · PDF fileDelphi é marca registrada da Borland International, as ... DBGrid - Como fazer quebra de ... clique no checkbox “Create a new form

MeGAZINEMeGAZINEMeGAZINEMeGAZINEMeGAZINE 99999

DelphiDelphiDelphiDelphiDelphi

pFormName: PChar;

begin

{ se não existir nenhuma impressora instalada }

if Printer.Printers.Count <= 0 then

Exit;

{ pega configurações da impressora corrente }

Printer.GetPrinter(Device, Driver, Port,

DeviceMode);

{ se OK }

if DeviceMode>0 then

begin

DevMode := PDeviceMode(GlobalLock(DeviceMode));

if OpenPrinter(Device, hPrinter, nil) then

begin

{ Pega lista de formulários disponíveis }

EnumForms(hPrinter, 1, Nil, 0,

cbNeeded, cReturned);

{ Aloca memória }

FormInfos := AllocMem(cbNeeded);

if EnumForms(hPrinter, 1, FormInfos,

cbNeeded, cbNeeded, cReturned) then

begin

pFormName := PChar(FormName);

{ apaga se o formulário especificado

já existir }

if DeleteForm(hPrinter, pFormName) then

{ decresce contador de formulários }

Dec(cReturned);

{ ponteiro para o novo formulário }

New(pForm);

Fillchar(pForm^, Sizeof(pForm^), 0);

pForm^.pName := PChar(FormName);

{ Configurações de tamanho e margens }

pForm^.Size.cx := ax*10000;

{ milésimos de milímitros }

pForm^.Size.cy := ay*10000;

{ milésimos de milímitros }

pForm^.ImageableArea.Left := 0;

pForm^.ImageableArea.Top := 0;

pForm^.ImageableArea.Right :=

pForm^.Size.cx;

pForm^.ImageableArea.Bottom :=

pForm^.Size.cy;

{ Adiciona formulário }

if not AddForm(hPrinter, 1, pForm) then

raise Exception.Create

( SysErrorMessage( GetLastError));

{ define novo formulário como corrente }

DevMode^.dmFields := DevMode^.dmFields

or DM_FORMNAME;

StrPCopy(DevMode^.dmFormName,pFormName);

DevMode^.dmFields := DevMode^.dmFields

or DM_PAPERSIZE;

DevMode^.dmPaperSize := cReturned+1;

end

else

raise Exception.Create

( SysErrorMessage( GetLastError));

{ Libera memória }

FreeMem(FormInfos);

end;

GlobalUnlock(DeviceMode);

end;

{ Aplica novo formulário }

Printer.SetPrinter(Device, Driver, Port,

DeviceMode);

end;

Listagem 1 – Código completo da procedure para criar o formulário

Importante: Não esqueça de declarar as units Printers eWinSpool na lista de units.

Comentamos os pontos mais importantes da procedureSetCustomForm a fim de facilitar o entendimento. A seguir, iremosdemonstrar o código da procedure responsável em setar oformulário como padrão nas propriedades da impressora, veja aListagem 2.

procedure SetFormToPrinter(FormName: string);

var

hPrinter : THandle;

dwNeeded : Integer;

printerInfo2 : PPrinterInfo2A;

printerDefaults: TPrinterDefaultsA;

FDevice: array[0..255] of char;

FDriver: array[0..255] of char;

FPort: array[0..255] of char;

FHandle: THandle;

begin

{ Pega Configurações atuais }

Printer.GetPrinter(FDevice, FDriver, FPort,

Page 10: Revista The Club Megazine - 12/ · PDF fileDelphi é marca registrada da Borland International, as ... DBGrid - Como fazer quebra de ... clique no checkbox “Create a new form

MeGAZINEMeGAZINEMeGAZINEMeGAZINEMeGAZINE1 01 01 01 01 0

DelphiDelphiDelphiDelphiDelphi

FHandle);

{ Permissões para alteração }

with PrinterDefaults do

begin

pDatatype := nil;

pDevMode := nil;

DesiredAccess := PRINTER_ALL_ACCESS;

end;

{ tenta acessar a impressora }

if not OpenPrinter(fDevice, hPrinter,

@PrinterDefaults)

then Exception.Create(‘OpenPrinter() failed.’);

{ Pega configurações atuais }

GetPrinter(hPrinter, 2, nil, 0, @dwNeeded);

if dwNeeded = 0 then

Exception.Create(‘Falha no GetPrinter!’);

{ Aloca memória }

GetMem(PrinterInfo2, dwNeeded);

{ Pega configurações adicionais }

if not GetPrinter(hPrinter, 2,

PrinterInfo2, dwNeeded, @dwNeeded) then

Exception.Create

(‘Falha no segundo GetPrinter().’);

with PrinterInfo2.pDevMode^ do

begin

StrPCopy( dmFormName, FormName);

dmFields := dmFields or DM_FORMNAME;

dmFields := dmFields and ( not ( DM_PAPERSIZE

or DM_PAPERLENGTH or DM_PAPERWIDTH));

if DocumentProperties( Application.Handle,

hPrinter, fDevice,PrinterInfo2.pDevMode^,

PrinterInfo2.pDevMode^,

DM_IN_BUFFER or DM_OUT_BUFFER) <> IDOK then

Exception.Create(‘Falha no

DocumentProperties().’);

if not WinSpool.SetPrinter(hPrinter, 2,

PrinterInfo2, 0) then

Exception.Create

(‘Falha no WinSpool.SetPrinter().’);

Printer.SetPrinter(FDevice, FDriver, FPort, 0);

FreeMem(PrinterInfo2, dwNeeded);

ClosePrinter(hPrinter)

end;

end;

Listagem 2 – Código completo da procedure para setar o formlário como padrão

Também efetuamos comentários na procedureSetFormToPrinter para facilitar a compreensão da mesma. Ambas aprocedures, SetCustomForm e SetFormToPrinter serão utilizadas emconjunto antes das chamadas de impressão na aplicação, e seestas necessitarem trabalhar com um tipo personalizado depapel.

Dando continuidade, iremos demonstrar a aplicação dasprocedures acima com três das mais importantes ferramentas deimpressão disponibilizadas pelo Delphi, ou seja, TPrinter, QuickReporte RaveReport (somente a paritr Delphi 7),

TPrinterPara quem não conhece, este é o principal objeto de impressão

disponível no Delphi, o qual permite implementar ótimas rotinasde impressão, porém, exigindo um pouco mais de trabalho econhecimento do programador. Existem várias abordagens quepodem ser utilizadas com o TPrinter para definir o tamanho depágina para impressão, mas, felizmente “ele” também assume asconfigurações de um formulário definido no Windows XP, NT e2000 e com isso, não precisamos nos preocupar em ter umarotina de ajuste de página para cada abordagem de impressão.Não vamos entrar em detalhes específicos sobre o TPrinter, pois ofoco deste artigo é outro, contudo, caso necessite obter maioresinformações a respeito do mesmo poderá consultar o artigo“Usando o TPrinter” publicando em nossa revista de Março/2000.Na listagem 3 demonstramos um pequeno fragmento de códigocom o TPrinter.

procedure TfmPrincipal.btnTPrinterClick

(Sender: TObject);

var

Linha:integer;

Tamanho:integer;

Coluna:integer;

begin

SetCustomForm(‘TheClub20x20’,

SpinEdit_Largura.Value, SpinEdit_Altura.Value);

Printer.BeginDoc;

Printer.Canvas.Font.Name := ‘Draft 10cpi’;

{ —— Rotinas de impressão —— }

Printer.EndDoc;

end;

Listagem 3 – Fragmento de código TPrinter

Page 11: Revista The Club Megazine - 12/ · PDF fileDelphi é marca registrada da Borland International, as ... DBGrid - Como fazer quebra de ... clique no checkbox “Create a new form

MeGAZINEMeGAZINEMeGAZINEMeGAZINEMeGAZINE 1 11 11 11 11 1

DelphiDelphiDelphiDelphiDelphi

No caso de impressão via TPrinter, não é necessário setar oformulário como padrão nas propriedades da impressora, bastaráapenas, antes de iniciar a impressão ajustar as configurações doreferido formulário para a medidas que necessitar e efetuar aimpressão que as definições do usuário serão respeitadas.

QuickReportA impressão via QuickReport também é bastante simples!

Um detalhe muito importante é em relação ao tipo de papelconfigurado no QuickReport, o qual deverá estar definido como“Default”, pois, este tipo de papel tem a finalidade de assumir otipo de papel padrão definido nas propriedades da impressora.Outro detalhe, no caso do QuickReport, obrigatóriamente nossoformulário deverá estar definido como padrão nas propriedades daimpressora, basicamente, nosso código no caso do QuickReportficará parecido com a listagem 4.

procedure TfmPrincipal.btnQuickReportClick

(Sender: TObject);

begin

{

Ajusta/Cria formulário para tamanho especificado

TheClub20x20, é o nome do formulário

}

SetCustomForm(‘TheClub20x20’,

SpinEdit_Largura.Value, SpinEdit_Altura.Value);

{

Importante: O tipo de papel configurado no QReport

deve estar = “Default”

Este novo formulário (TheClub20x20),

deve ser definido como

padrão nas propriedades da impressora.

}

SetFormToPrinter(‘TheClub20x20’);

{ Imprime o relatório }

with fmQuickReport do

begin

QuickRep1.Prepare;

QuickRep1.Print;

end;

end;

Listagem 4 – Chamada do relatório via QuickReport.

Rave ReportFinalizando, iremos fazer a chamada de um relatório

construído via Rave Report. No caso do Rave, as regras aplicadassão as mesmas que vimos anteriormente para o QuickReport, ouseja, o tipo do papel configurado no Rave deverá ser o “Default” eantes de executarmos o relatório, deveremos definir o formulário

como padrão nas propreidades da impressora, veja a listagem 5.

procedure TfmPrincipal.btnRaveClick

(Sender: TObject);

begin

{Ajusta/Cria formulário para tamanho especificado }

SetCustomForm(‘TheClub20x20’,

SpinEdit_Largura.Value,

SpinEdit_Altura.Value);

{Importante: O tipo de papel configurado no Rave

deve estar = “Default” .Este novo formulário

(TheClub20x20), deve ser definido como padrão nas

propriedades da impressora. }

SetFormToPrinter(‘TheClub20x20’);

{ Imprime o relatório }

with RvProj do

begin

Open;

Execute;

end;

end;

ConclusãoEfetuamos testes com as abordagens demonstradas neste

artigo, utilizando o seguinte ambiente: Delphi 7, Windows XPProfessional e uma impressora Epson FX-1170, onde obtivemosêxito em todos os testes, dando um destaque especial ao TPrintere ao QuickReport, visto que em ambos conseguimos utilizar afonte de letra “draft 10cpi”, permitindo assim aumentar avelocidade de impressão na referida impressora. Gostaríamosainda de deixar bem claro, que esta abordagem aplica-se apenasao Windows XP, NT e 2000, visto o Windows 9x possuir um tipoespecífico para configuração de papel com tamanhopersonalizado, e devido as inúmeras solicitações de suporte arespeito deste tema, resolvemos publicar este artigo, oferecendoassim uma solução para o problema de impressão nestes SOs,visto estarem sendo utilizados cada dia mais, principalmente oWindows XP.

Forte abraço e sucesso à todos,

DownloadO projeto de exemplo completo a respeito deste artigo está

disponível para download em:http://www.theclub.com.br/revista/download/AddFormXP.zip

Sobre o autorAlessandro Ferreira,Consultor Técnico do The [email protected]

Page 12: Revista The Club Megazine - 12/ · PDF fileDelphi é marca registrada da Borland International, as ... DBGrid - Como fazer quebra de ... clique no checkbox “Create a new form

MeGAZINEMeGAZINEMeGAZINEMeGAZINEMeGAZINE1 21 21 21 21 2

DelphiDelphiDelphiDelphiDelphi

IntroduçãoEntre as muitas facilidades que a internet vêm nos

proporcionando, atualizar aplicações em tempo real, sem dúvidasnenhuma, além de ser algo bastante profissional, propicia asolução de muitos problemas de forma bastante eficaz.

Neste pequeno artigo, iremos demonstrar uma dasabordagens possíveis para este tipo de implementação, ondeiremos disponbilizar a nova versão e um pequeno arquivo textoque irá conter informações relevantes sobre nossa aplicação e, viacomponentes da palheta Indy iremos acessar as referidasinformações.

Aqui, iremos considerar que você possuauma conexão internet já estabelecida e nãoabordaremos este tópico no decorrer do artigo,contudo, ao final do mesmo, indicaremos umcomponente gratuíto que possibilitará efetuar aconexão internet via Delphi.

Estrutura NecessáriaPartindo do princípio que a atualização será

via web, você irá necessitar possuir um servidorweb para efetuar os testes, ou pelo menos, o IISinstalado em sua máquina no caso de Windows2000 ou XP, ou o PWS (Personal Web Server)para Windows 9x.

Feito isso, crie uma pasta no servidor webonde iremos disponibilizar os arquivos deatualização e texto que irá conter as informaçõesda aplicação.

Estamos implementando este exemploutilizando o Delphi 7, contudo, poderá serimplementado em Delphi 6 sem problemas. Nocaso do Delphi 5, também é possível, contudo você

irá necessitar instalar a suíte de componentes Indy, a qual estádisponível para download gratuítamente em:

http://www.indyproject.org/.

ImplementaçãoBom, vamos começar a implementar nossa aplicação. Para

iniciar, crie um novo projeto, File | New | Application. Verifiquena figura 1 o layout sugerido para o formulário do projeto deexemplo.

por Alessandro Ferreira, [email protected]

Figura 1 – Layout sugerido

LiveUpdateLiveUpdateLiveUpdateLiveUpdateLiveUpdateAtualizando Aplicações via Web

Page 13: Revista The Club Megazine - 12/ · PDF fileDelphi é marca registrada da Borland International, as ... DBGrid - Como fazer quebra de ... clique no checkbox “Create a new form

MeGAZINEMeGAZINEMeGAZINEMeGAZINEMeGAZINE 1 31 31 31 31 3

DelphiDelphiDelphiDelphiDelphi

Por enquanto, apenas salve o projeto, pois iremosimplementar mais nada no formulário de nossa aplicação.Continuando, adicione uma nova unit em nosso projeto, menuFile | New | Unit. Neste unit, iremos implementar os códigosnecessários para a verificação da versão e demais informações naweb. Acompanha na listagem 1 a codificação completa.

unit VersionCheck;

interface

{ utilizada apenas aqui nesta unit }

procedure GetVersionFromWeb(const Host,

FileName: string;

var Version: string; var DateStr: string;

var FileSize: Integer);

{ Utiliza na aplicação para retornar a

informações sobre a versão na web }

procedure GetRemoteVersion(Host: string;

var Version,

DateStr: string; var Size: Integer);

{ efetuar Download caso solicitado }

function DownloadFile(aURL, aLocal: String):

Boolean;

implementation

{ Units utilizadas }

uses SysUtils, Forms, IdBaseComponent, IdComponent,

IdTCPConnection, IdTCPClient, IdHTTP, UrlMon;

{

Nomeamos o arquivo que está na web de “version.txt”.

cgi-bin indica uma pasta dentro do host especificado

}

procedure GetRemoteVersion(Host: string; var

Version,

DateStr: string; var Size: Integer);

begin

GetVersionFromWeb(Host, ‘/cgi-bin/version.txt’,

Version,

DateStr, Size);

end;

{

Procedure responsável em verificar e retornar as

informações.

}

procedure GetVersionFromWeb(const Host,

FileName: string;

var Version: string; var DateStr: string;

var FileSize: Integer);

var

Browser: TIdHTTP; { Indy } { Variáveis auxiliares }

Response, TempStr: string;

P: PChar;

{

retorna valores:

Version, DateStr e FileSize.

}

procedure IncP(var Variable: string);

begin

while ( (P <> nil) and not (P^ in

[#10, #13, #0]) ) do

begin

Variable := Variable + P^;

Inc(P);

end;

while ( (P <> nil) and (P^ in [#10, #13, #0]) )

do

Inc(P);

end;

begin

Browser := TIdHTTP.Create(nil);

try

{ endereço na web, não deve conter HTTP. }

Browser.Host := Host;

{ carrega o arquivo texto existente na web }

Response := Browser.Get(FileName);

{ inicializa variáveis }

Version := ‘’;

DateStr := ‘’;

FileSize := 0;

{ se retornou alguma coisa... }

if Length(Response) > 0 then

begin

{ Copia ponteiro }

P := @Response[1];

{ Pega valores }

IncP(Version);

IncP(DateStr);

IncP(TempStr);

{ se encontrou o tamanho, converte

para inteiro }

if TempStr <> ‘’ then

FileSize := StrToInt(TempStr);

end;

Page 14: Revista The Club Megazine - 12/ · PDF fileDelphi é marca registrada da Borland International, as ... DBGrid - Como fazer quebra de ... clique no checkbox “Create a new form

MeGAZINEMeGAZINEMeGAZINEMeGAZINEMeGAZINE1 41 41 41 41 4

DelphiDelphiDelphiDelphiDelphi

finally

{ Libera }

Browser.Free;

end;

end;

{

Efetuar download

}

function DownloadFile(aURL, aLocal: String):

Boolean;

begin

{

Download da nova versão

Indique o nome de sua nova versão no lugar

de “version.txt” para que o download seja

efetuado.

}

try

Application.ProcessMessages;

Result := UrlDownloadToFile(nil, PChar

(aURL + ‘/cgi-bin/version.txt’),

PChar(aLocal), 0, nil) = 0;

except

Result := False;

end;

end;

end.

Listagem 1 – código completo referente aos procedimentos de verificação de versão e download.

Como pode ser observado, procuramos comentar o códigopara facilitar o entendimento. A idéia básica é a utilização docomponente TIdHttp (Indy) onde informamos uma URL e onome do arquivo texto e o memo retorna o texto referente oarquivo disponível no servidor web. Após isso, armazenamos oretorno do componente TIdHttp em uma variável string, ondefazemos a leitura separando as informações de versão, data etamanho, respectivamente.

Ainda nesta mesma unit, adicionamos uma função que seráutilizada para efetuar o download da atualização disponível naweb. Esta função recebe como parâmetros a URL (path e nomedo arquivo remoto) e o path local onde o arquivo deverá serdescarregado.

Bem, voltando ao nosso formulário (figura 1), vamos adicionaras instruções aos botões “Download” e “Verifica Versão”,respectivamente.

procedure TForm1.sbtnDownloadClick(Sender: TObject);

begin

{

Efetuar download.

}

anima.Enabled := not anima.Enabled;

try

if SaveDlg.Execute then

if DownloadFile(‘http://’ + EdHost.Text,

SaveDlg.FileName) then

MessageDlg(‘Download efetuado com sucesso!’,

mtInformation, [mbOk], 0)

else

MessageDlg(‘Falha no download!’,

mtInformation, [mbOk], 0);

finally

anima.Enabled := not anima.Enabled;

end;

end;

Listagem 2 – Botão “Download”.

procedure TForm1.sbtnVersaoClick(Sender: TObject);

{ Variáveis que irão receber as informações }

var

Version, DateStr: string;

Size: Integer;

begin

{ Pega versão na WEB }

GetRemoteVersion(EdHost.Text, Version,

DateStr, Size);

{ Adiciona informações no Memo }

with MInfo.Lines do

begin

Add(Format(‘Versão atual na web: %s’ ,

[Version]));

Add(Format(‘Data versão na web : %s’ ,

[DateStr]));

Add(Format(‘Tamnho em Bytes : %d’ , [Size]));

end;

end;

Listagem 3 – Botão “Verificar Versão”.

Com isso, finalizamos a implementação em nosso projeto deexemplo.

Apenas a título de testes, disponibilizamos o arquivo“version.txt” para que você possa executar e testar o projeto deexemplo deste artigo.

Page 15: Revista The Club Megazine - 12/ · PDF fileDelphi é marca registrada da Borland International, as ... DBGrid - Como fazer quebra de ... clique no checkbox “Create a new form

MeGAZINEMeGAZINEMeGAZINEMeGAZINEMeGAZINE 1 51 51 51 51 5

DelphiDelphiDelphiDelphiDelphi

Algumas dicasEm nossa revista de Agosto/2003, publicamos um artigo

entitulado “Criando aplicativos auto-atualizáveis”, o qual permiteque ao executar um aplicativo em uma rede local, o mesmoverifique se a versão que está rodando está ou não atualizadatendo como base uma versão disponibilizada no servidor da rede.Assim sendo, você poderá utilizar o exemplo demonstrado aquipara baixar a nova versão e implementando as sugestões doartigo anterior, disponibilizá-la na rede e quando o usuário forcarregar o aplicativo, automaticamente terá seu EXE atualizado.

Como você pôde observar, disponibilizamos informações sobrea versão, data e tamanho. Contudo, você poderá adicionar apenas osdados que achar relevante no arquivo texto, lembrando que cada“ítem” deverá ficar em um linha do mesmo.

Como mencionado no início do artigo, nosso foco aqui édemonstrar a possibilidade de verificar informações sobreatualizações disponíveis na web.

Contudo, para que uma aplicação possa ter acesso a estasinformações, é necessário que a mesma esteja conectado ainternet. Assim sendo, junto ao projeto de exemplo estamos

adicionando um componente gratuíto chamado “TDialup” o qualirá possibilitar fazer a conexão com base em uma conexão dialupexistente, tudo via Delphi mesmo.

ConclusãoDemonstramos neste simples artigo uma das abordagens

possíveis para checagem de versão via web. O exemplo aqui ébastante simples, contudo, tendo este como base, você poderáutilizar sua criatividade e dar um toque ainda mais profissionalao seu aplicativo. Comentários e sugestões serão benvindos paraque possamos estar publicando assuntos que facilitem o dia-a-diado programador Delphi!

Forte abraço e sucesso à todos,

Download: http://www.theclub.com.br/revista/download/VersionCheckWeb.zip

Sobre o autorAlessandro Ferreira,Consultor Técnico do The [email protected]

Page 16: Revista The Club Megazine - 12/ · PDF fileDelphi é marca registrada da Borland International, as ... DBGrid - Como fazer quebra de ... clique no checkbox “Create a new form

MeGAZINEMeGAZINEMeGAZINEMeGAZINEMeGAZINE1 61 61 61 61 6

RetrospectivaRetrospectivaRetrospectivaRetrospectivaRetrospectiva

RetrospectivaRetrospectivaRetrospectivaRetrospectivaRetrospectiva

Nossa retrospectiva continua, chegando ao ano de 1999!

Destaca-se nesta edição, uma série de artigos que forampublicados sobre os arquivos Paradox, desmistificando asua utilização, ampliando a condição de usabilidade, etambém resolvendo uma série de problemas que muitosprogramadores enfrentavam.

Esta série de artigos foi bem detalhada, esmiuçando oParadox nos mínimos detalhes.

Também nesta edição, começamos a tratar da utilizaçãode APIs com Delphi, aumentando o poder de programaçãoe abrindo possibilidades ao programador que uma simplesutilização do Delphi não permitiria.

Merece destaque também o artigo do Mauro Sant'Annaque nos ensinou como selecionar uma impressora atravésdo programa, mesmo com a utilização do QuickReport.

No mês que vem continuaremos nossa retrospectiva como ano de 1998. Até lá.

Page 17: Revista The Club Megazine - 12/ · PDF fileDelphi é marca registrada da Borland International, as ... DBGrid - Como fazer quebra de ... clique no checkbox “Create a new form
Page 18: Revista The Club Megazine - 12/ · PDF fileDelphi é marca registrada da Borland International, as ... DBGrid - Como fazer quebra de ... clique no checkbox “Create a new form

MeGAZINEMeGAZINEMeGAZINEMeGAZINEMeGAZINE1 81 81 81 81 8

DelphiDelphiDelphiDelphiDelphi

Neste artigo irei descrever como podemos montar umrelatório para a impressão de etiquetas no Rave Report. Para oexemplo que iremos montar tomaremos como base um modelo deetiqueta com apenas uma coluna, mas ao final da matériaindicarei como controlar a impressão com mais colunas.

Iniciando os trabalhosIniciaremos o nosso trabalho criando o projeto no Delphi, pois

através desse projeto iremos fazer a conexão a base de dados etambém iremos chamar o relatório quando este estiver pronto.Para esse exemplo iremos utilizar o alias DBDEMOS do BDE eacessaremos a tabela Vendors.DB.

Estando com o novo projeto criado, coloquem no form osseguintes componentes:

RvProject, RvSystem, RvTableConnection, Table,DataSource, DBGrid e Button.

Em seguida iremos configurar nesses componentes asseguintes propriedades:

RvProjectName = RvProject1Engine = RvSystem1 ( Selecione o componente RvSystem )ProjectFile = C:\Exemplo\Rave_Etiqueta\RvEtiqueta.rav( Nome do projeto do relatório a ser criado no Rave Designer )

RvSystemName = RvSystem1TitlePreview = Impressão de etiquetas no Rave Report

RvTableConnectionName = RvTableConnection1Table = Table1

TableName = Table1DataBaseName = DBDEMOSTableName = Vendors.dbActive = TRUE

DataSourceName = DataSource1DataSet = Table1

DBGridName = DBGrid1DataSource = DataSource1

ButtonName = Button1Caption = Visualiza EtiquetasNo evento onclick do Button1 coloque a seguinte instrução:

procedure TForm1.Button1Click(Sender: TObject);

begin

RvProject1.Execute;

end;

Após montar o form o nosso projeto ficará parecido com aFigura 1.

Rave ReportRave ReportRave ReportRave ReportRave ReportImprimindo etiquetas.Imprimindo etiquetas.Imprimindo etiquetas.Imprimindo etiquetas.Imprimindo etiquetas.

por André Colavite - [email protected]

Page 19: Revista The Club Megazine - 12/ · PDF fileDelphi é marca registrada da Borland International, as ... DBGrid - Como fazer quebra de ... clique no checkbox “Create a new form

MeGAZINEMeGAZINEMeGAZINEMeGAZINEMeGAZINE 1 91 91 91 91 9

DelphiDelphiDelphiDelphiDelphi

Figura 1

Agora que estamos com o projeto no Delphi criado e com atabela já conectada, então iremos acessar o Rave Report Designerpara montarmos o relatório para impressão de etiquetas.Portanto neste momento dê duplo click no componenteRvProject1 para assim abrir o Rave Report Designer.

Criando o relatório no Rave ReportDentro do Rave Report Designer, selecione o menu File e a

opção New, para criar um novo relatório. Em seguida vamossalvar esse novo relatório para que assim já fique criado oarquivo que conterá a estrutura do relatório.

Sendo assim selecione novamente o menu File e a opção Save,em seguida coloque o nome do arquivo como RvEtiqueta.rav, nãose esqueça de verificar se o diretório selecionado é o mesmo doprojeto do Delphi, e pressione Ok.

A criação deste relatório de Etiquetas é bastante simples, poisseguem os mesmos passos usados na criação de um relatórionormal e são exatamente esses passos que seguiremos a partirdeste ponto.

Criando um DataViewO primeiro passo será criar um DataView, pois assim

poderemos visualizar a estrutura da tabela e os dados que iremosimprimir. Para criar esse DataView clique sobre o botão “NewData Object”, ao qual abrirá uma janela igual a figura 2.

Figura 2

Page 20: Revista The Club Megazine - 12/ · PDF fileDelphi é marca registrada da Borland International, as ... DBGrid - Como fazer quebra de ... clique no checkbox “Create a new form

MeGAZINEMeGAZINEMeGAZINEMeGAZINEMeGAZINE2 02 02 02 02 0

DelphiDelphiDelphiDelphiDelphi

Nesta janela selecione a opção “Direct Data View” e cliquesobre o botão “Next”.

Em seguida selecione o RvTableConnection1 e clique sobre obotão Finish. Conforme figura 3:

Figura 3

Neste momento um DataView foi criado com o nomeDataView1.

Montando a estrutura do relatórioNos passos seguintes iremos determinar o tamanho e

posicionamento da área de impressão dos dados, seguindo otamanho das etiquetas da folha de impressão. Portanto voudescrever abaixo o tamanho da etiqueta que estou utilizando noexemplo:

Tamanho da folha: A4Borda: 1,2 cm

Medidas da Etiqueta:Horizontal: 9 cmVertical: 2,3 cm

Para facilitar um pouco o nosso trabalho iremos trabalharcom o Rave em CM, portanto selecione no treeview existente nadireita do Rave Design a opção “RaveProject” e em seguida alterea sua propriedade “Units” para o valor “unCM”.

Agora podemos montar a estrutura do relatório, sendo assimselecione na aba Report o componente Region e o coloque sobre apágina que estamos construindo.

Neste componente Region iremos configurar as seguintes

propriedades:Top = 0,100Left = 1,400Width = 9,000 ( Corresponde ao tamanho da etiqueta na

horizontal )Height = 28,000 ( Corresponde ao tamanho da folha de

etiquetas )

Em seguida coloque um DataBand dentro desse Region, esseDataBand também pode ser encontrado na aba Report, econfigure as seguintes propriedades:

BandStyle = selecione as opções Detail e FirstDataView = DataView1Height = 2,400

Coloque dentro deste DataBand 6 componentes DataText, osquais serão ligados aos campos do DataView para a impressãodos dados. Esses DataText ficarão configurados da seguinteforma:

Para finalizar o relatório de etiquetas irei incluir uma novaBand ao qual irá controlar o espaçamento existente entre asetiquetas. Portanto pegue na aba Report uma Band, veja bemnão é DataBand e sim Band, e a coloque dentro do Region. Paraesta Band configure as seguintes propriedades:

BandStyle = Detail e FirstControllerBand = DataBand1Height = 0,150 ( Corresponde ao espaço existente entre as

etiquetas no papel )

Após configurar todos os componentes o seu relatório deveestar parecido com a figura 4.

Salve o relatório.

Neste momento vamos verificar o resultado do nossotrabalho. Ainda dentro do Rave Designer faça um teste norelatório pressionando o botão “Execute Report” e poderá

Page 21: Revista The Club Megazine - 12/ · PDF fileDelphi é marca registrada da Borland International, as ... DBGrid - Como fazer quebra de ... clique no checkbox “Create a new form

MeGAZINEMeGAZINEMeGAZINEMeGAZINEMeGAZINE 2 12 12 12 12 1

DelphiDelphiDelphiDelphiDelphi

Figura 4

verificar que as etiquetas são impressas corretamente, umaabaixo da outra.

Aí você pergunta, e se eu utilizar um formulário de etiquetascom 2 colunas, como criar a segunda coluna?

Controlando a impressão das colunas

O Rave Report nos traz duas formas para controlar aimpressão das colunas, uma forma que faz igual ao QuickReport,isso é, imprime os registros preenchendo toda a primeira coluna equando chega ao final da página salta para a segunda coluna.

A outra forma é a mais escolhida, pois imprime os registrosintercalados entre as colunas, por exemplo, imprime o primeiroregistro na primeira coluna, o segundo registro na segundacoluna, volta para a primeira coluna e imprime o terceiro registroe assim sucessivamente.

Abaixo vamos verificar como configurar os doiscasos.

A primeira forma funciona igual ao Quickreport e aquantidade de colunas será indicada através da propriedadeColumns existente no Region.

Faça o teste colocando o valor 2 nesta propriedade Columns eexecute o relatório, neste momento a impressão das etiquetasserá dividida em 2 colunas.

Observação importante, não se esqueça deaumentar o tamanho do Region para podermosvisualizar as colunas e não salve o relatório nesteteste, pois assim poderemos voltar ao normal paraefetuar o segundo teste.

O Region tem outra propriedade importante chamadaColumnSpacing.

Essa propriedade como o próprio nome diz, irá configurarexatamente o espaço existente entre as colunas das etiquetas.

Depois de efetuado o teste acima, vamos voltar o relatório naforma como ele foi gravado, isso é, com apenas uma coluna.

Para isso selecione no menu File a opção Open e depoisselecione o arquivo do projeto e clique sobre o Open.

Na janela da pergunta se desejamos salvar as alterações,selecione o botão No.

Neste momento podemos testar a segunda forma de coluna epara essa segunda forma indique a quantidade de colunas napropriedade Columns do componente DataBand.

Observação importante, para este teste funcionar deixe embranco a propriedade ControllerBand da Band.

Também não podemos esquecer de aumentar o tamanho doRegion para podermos visualizar as colunas e de não salvar orelatório, pois assim poderemos voltar o relatório ao normal.

Neste DataBand também existe a propriedadeColumnSpacing explicada acima.

Para voltar o projeto do relatório ao normal execute os passosindicados acima.

Finalizando o relatório de etiquetas

Neste momento como o relatório já está pronto, entãopodemos fechar o Designer do Rave Report e voltar ao projeto doDelphi para testá-lo.

Execute o projeto do Delphi e para visualizar o relatório bastaclicar sobre o botão “Visualizar Etiquetas”.

O Preview do relatório ficará igual à figura 5.

Page 22: Revista The Club Megazine - 12/ · PDF fileDelphi é marca registrada da Borland International, as ... DBGrid - Como fazer quebra de ... clique no checkbox “Create a new form

MeGAZINEMeGAZINEMeGAZINEMeGAZINEMeGAZINE2 22 22 22 22 2

DelphiDelphiDelphiDelphiDelphi

Figura 5.

Conclusão

Neste artigo verificamos o quanto é simples criar umrelatório de etiquetas no Rave Report, o mais trabalhoso mesmo éconfigurar o tamanho das etiquetas conforme o formulário queestamos utilizando.

Um grande abraço a todos e até a próxima.

Sobre o autorAndré ColaviteConsultor Técnico do The [email protected]

O exemplo está disponível para download em nosso site:http://www.theclub.com.br/revista/download/RvEtiquetas.zip

Estamos chegando ao final de mais um ano. Esperamos que nossosserviços tenham atendido as expectativas de todos vocês, e que o trabalho detodos tenha sido produtivo.

Agora neste final de ano, vamos aproveitar dois feriados para darmosférias para nossos consultores.

O suporte técnico não atenderá no período de 22/12/2003 até 04/01/2004,voltando as suas atividades normais a partir do dia 05/01/2004.

ATENÇÃO

Page 23: Revista The Club Megazine - 12/ · PDF fileDelphi é marca registrada da Borland International, as ... DBGrid - Como fazer quebra de ... clique no checkbox “Create a new form

MeGAZINEMeGAZINEMeGAZINEMeGAZINEMeGAZINE 2 32 32 32 32 3

DelphiDelphiDelphiDelphiDelphi

Trabalhando comprocedures e funções.

Por Claudinei Rodrigues

Procedures e funções são chamadas de uma forma geral derotinas, blocos de códigos que podem ser chamados de diversaspartes do seu programa. Uma função é uma rotina que retornaum valor quando é executada, já uma procedure não tem umvalor de retorno. Por exemplo:

I := MinhaFuncao(Y);

Aqui chamamos a função MinhaFunção e atribuímos oretorno para a variável I. Já em uma procedure podemos fazer oseguinte:

MinhaProcedure;

Declarando procedures e funçõesQuando você declara uma procedure ou uma função você

especifica o seu nome, o número e tipo dos parâmetros e no casode uma função, o tipo do retorno. Esta parte da declaraçãoalgumas vezes é chamada de prototype, heading ou header.Então você escreve um bloco de código que executa sempre queuma procedure ou função for chamada; esta parte é chamada decorpo da rotina ou bloco de código.

Declaração de procedureUma declaração de procedure que tem no form

procedure NomeDaProcedure(ListadeParametros);diretivas; declarações locaisbegin instruçõesend;

Onde NomeDaProcedure é um identificador válido, instruçõesé a seqüência de códigos que serão executados quando aprocedure for chamada e (ListadeParametros) e diretivas sãoopcionais.

Veja aqui um exemplo de procedure:

procedure NumString(N: Integer; var S: string);var V: Integer;begin

V := Abs(N); S := ‘’; repeat S := Chr(V mod 10 + Ord(‘0’)) + S; V := V div 10; until V = 0; if N < 0 then S := ‘-’ + S;end;

Conhecendo esta rotina você poderá chamá-la da seguinteforma:

NumString(17, MyString);

Dentro desta procedure você pode declarar variáveis e outrosidentificadores na parte declarações locais dentro da procedure.Você também pode usar nome de parâmetros a partir de umalista de parâmetros, como mostrado na procedure NumStringque recebe dois parâmetros. A lista de parâmetros define umconjunto de variáveis locais, assim você não pode redeclarar osparâmetros na seção declarações locais.

Declarando funçõesA declaração de uma função é igual a uma declaração de

procedure exceto que é informado um parâmetro de retorno. Vejacomo é uma função.

function NomedaFuncao(ListadeParametros):TipodoRetorno; diretivas; declarações locais;begin instruçõesend;

Onde NomedaFuncao é um identificador válido,TipodeRetorno é o tipo de retorno, instruções é a seqüência decódigos que serão executados quando a função for chamada e(ListadeParametros), diretivas e declarações locais são opcionais.

O bloco de instruções de uma função trabalha da mesmaforma do bloco de instruções de uma procedure. Dentro do blocode código pode-se usar variáveis e outros identificadores queforam declarados na seção declarações locais.

Page 24: Revista The Club Megazine - 12/ · PDF fileDelphi é marca registrada da Borland International, as ... DBGrid - Como fazer quebra de ... clique no checkbox “Create a new form

MeGAZINEMeGAZINEMeGAZINEMeGAZINEMeGAZINE2 42 42 42 42 4

DelphiDelphiDelphiDelphiDelphi

Além disso, o próprio nome da função atua como umavariável especial que armazena o valor de retorno, como faz avariável pré-definida Result.

Enquanto a sintaxe {$X+} está habilitada o Result estáimplicitamente declarada em qualquer função. Não tenteredeclará-la. No exemplo a seguir defina uma função constantechamada WF que não tenha nenhum parâmetro de entrada esempre retorne um valor inteiro 17.

function WF: Integer;begin WF := 17;end;

Por exemplo, a rotina anterior define uma função constantechamada WF que não tenha nenhum parâmetro de entrada esempre retorne um valor inteiro 17. O próximo exemplo éequivalente ao anterior.

function WF: Integer;begin Result := 17;end;

Agora veja o próximo exemplo que uma função um poucomais complexa,

function Max(A: array of Real; N: Integer): Real;var X: Real; I: Integer;begin X := A[0]; for I := 1 to N - 1 do if X < A[I] then X := A[I]; Max := X;end;

Você pode determinar um valor para a variável Result oupara o nome da função dentro de uma instrução. Quando aexecução de uma função termina, seja qual for o valor que foideterminado para a variável Result ou para o nome da função,torna-se o resultado da função. Veja o exemplo a seguir:

function Power(X: Real; Y: Integer): Real;var I: Integer;begin Result := 1.0; I := Y; while I > 0 do begin if Odd(I) then Result := Result * X; I := I div 2; X := Sqr(X); end;end;

A variável Result e o nome da função sempre representam omesmo valor. Então, veja rotina anterior que retorna o valor 11.Mas a variável Result não é completamente passível de troca como nome da função.

Quando o nome da função aparece no lado esquerdo de umainstrução, o compilador assume que ela está sendo usada, como avariável Result, para retornar o valor. Quando o nome da funçãoaparece em qualquer lugar além do bloco de instrução, ocompilador a interpreta como uma chamada recursiva para aprópria função. A variável Result, por outro lado, pode ser usadacomo uma variável em operações, typecasts, conjunto deconstructors, índices e chamadas para outras rotinas. Se afunção existe sem estar determinando um valor para Result oupara o nome da função então a função retorna um valorindefinido.

Tipo de chamadasQuando você declara uma procedure ou uma função você

pode especificar um tipo de chamada informando uma dasdiretivas register, pascal, cedcl, stdcall e safecall. Por exemplo,function MyFunction(X, Y: Real): Real; cdecl;

Os tipos de chamadas determinam a ordem na qual osparâmetros são passados para a rotina. Os tipos register e pascalpassam parâmetros da esquerda para a direita, quer dizer, oparâmetro mais a esquerda é avaliado e passado primeiro e oparâmetro mais a direita é avaliado e passado por último. Ostipos cdecl, stdcall e safecall passam parâmetros da direita para aesquerda.

Para todas as formas, exceto cdecl, os procedimentos efunções removem seus parâmetros da pilha quando a funçãotermina a sua execução e retorna ao código que chamou. Naforma cdecl o chamador é responsável por remover da pilha osparâmetros de retorno das funções. A forma register, que édefault, usa até três registadores da CPU para passar seusparâmetros.

A forma safecall implementa exceções “firewalls”. A formacdecl é útil quando você chama funções de bibliotecascompartilhadas escritas em C ou C++, enquanto stdcall e safecallsão recomendados em geral para chamadas de códigos externos.No Windows, o sistema de operações da API são stdcall e safecall.Outro sistema operacional geralmente usa cdecl. Note que stdcallé mais eficiente que cdecl. A forma safecall deve ser usada paradeclaração de métodos dual-interface. A forma pascal está sendomantida apenas por questões de compatibilidade. As diretivasnear, far e export referem-se a tipos de chamadas paraambientes de programação 16 bit. Eles não tem efeito emambiente 32 bit e são mantidos apenas por questões decompatibilidade.

Fazendo uma sobrecarga de procedures e funçõesVocê pode declarar uma procedure ou uma função mais de

uma vez com o mesmo nome. Isto é chamado de sobrecarga. Parafazer uma sobrecarga de uma rotina você deve incluir na suadeclaração a diretiva overload e também deve distinguir a listade parâmetros.

Veja a seguir um exemplo:

Page 25: Revista The Club Megazine - 12/ · PDF fileDelphi é marca registrada da Borland International, as ... DBGrid - Como fazer quebra de ... clique no checkbox “Create a new form

MeGAZINEMeGAZINEMeGAZINEMeGAZINEMeGAZINE 2 52 52 52 52 5

DelphiDelphiDelphiDelphiDelphi

function Divide(X, Y: Real): Real; overload;begin Result := X/Y;end;

function Divide(X, Y: Integer): Integer; overload;begin Result := X div Y;end;

Aqui nós criamos duas funções, ambas com o mesmo nome,mas que recebem parâmetros diferentes. Quando você chamaesta função o compilador determina qual delas deve ser chamadade acordo com os parâmetros passados na sua chamada. Porexemplo, se você chamar da seguinte forma:

Divide(6.0,3.0), então a primeira função será chamada, istoacontece devido ao tipo dos parâmetros. Você pode passar parauma rotina do tipo overload parâmetros de tipos que não sejamidênticos a sua declaração, mas que sejam compatíveis com osparâmetros em mais de uma declaração. Isto acontece com maisfreqüência quando uma rotina é sobrecarregada com diferentestipos inteiros, diferentes tipos reais, por exemplo:

procedure Store(X: Longint); overload;procedure Store(X: Shortint); overload;

Nestes casos, quando é possível fazer sem ambigüidade, ocompilador invoca a rotina em que os parâmetros tenham tipo demenor variação, para que acomode o parâmetro atual nachamada.

As rotinas de sobrecarga devem ser distinguidas pelo númeroou tipo de parâmetros de entrada. Como você pode ver, o exemploa seguir causa um erro:

function Cap(S: string): string; overload;procedure Cap(var Str: string); overload;

Mas este outro não.

function Func(X: Real; Y: Integer): Real; overload;function Func(X: Integer; Y: Real): Real; overload;

O tipo Variant também pode ser usada como parâmetro emdeclaração de funções sobrecarregadas. Variant é consideradamais comum que qualquer tipo simples. A preferência é sempredada para o tipo exato sobre tipos variantes. Se uma variant épassada em uma situação de sobrecarga e uma sobrecarga quetem uma variant como parâmetro, então o tipo variant éconsiderada como um tipo exato.

Isto pode causar alguns pequenos efeitos colaterais com tiposfloat. Os tipos float são verificados pelo tamanho. Se não existenenhum tipo compatível para a variável float passada para asobrecarga chamada, mas uma variant estiver disponível, avariant é elevada sobre qualquer tipo de flutuação menor.

Vamos supor que você tenha três rotinas declaradas daseguinte forma:

procedure teste(i: integer); overload;procedure teste(d: double); overload;procedure teste(v: variant); overload;

Agora veja alguns tipos de chamadas para esta nossa rotina:

var v: variant;begin teste(1); // passando um valor inteiro teste(v); // passando uma variável variant teste(1.2); // passando um valor flutuanteend;

Este exemplo chama a versão variant da rotina teste, não aversão double. Porque o valor 1.2 está implicitamente em um tipoextended e extended não é exatamente compatível com double.Extended também não é exatamente compatível com variant,mas variant é considerada um tipo geral, enquanto que double éum tipo mais baixo que extended.

Você pode utilizar uma constante. Por exemplo:

const d: double = 1.2;begin teste(d);end;

O código acima trabalha corretamente, e chama a variáveldouble.

O código a seguir também chama a versão double da rotinateste.

const s: single = 1.2;begin teste(s);end;

O tipo Single é mais adequado para double do que paravariant. Quando se declara um conjunto de rotinassobrecarregadas, o melhor caminho é evitar a conversão deflutuante para variant de sua função sobrecarregada para cadatipo float (Single, Double, Extended) junto com a função variant.

Se você usa os parâmetros default em rotinassobrecarregadas, cuidado para não utilizar parâmetrosambíguos. Vamos ver sobre parâmetros default mais a diante.

Declarações locaisO corpo de uma função ou procedure algumas vezes contém

outras funções e procedures dentro da seção de declaração local.Por exemplo, veja a declaração da procedure MinhaProcedureque contém uma procedure aninhada.

procedure MinhaProcedure(S: string);

Page 26: Revista The Club Megazine - 12/ · PDF fileDelphi é marca registrada da Borland International, as ... DBGrid - Como fazer quebra de ... clique no checkbox “Create a new form

MeGAZINEMeGAZINEMeGAZINEMeGAZINEMeGAZINE2 62 62 62 62 6

var X, Y: Integer; procedure OutraProcedure(S: string); begin {instruções} end;begin OutraProcedure(S);end;

A rotina aninhada está limitada para a procedure ou funçãoa qual ela foi declarada. Em nosso exemplo, OutraProcedure,pode ser chamada apenas de dentro da procedureMinhaProcedure. Se você quiser ver mais exemplo dê umaolhada na função DateTimeToString que está na unit SysUtils.

ParâmetrosA maior parte das procedures e funções recebem uma lista de

parâmetros. Uma lista de parâmetros é uma seqüência dedeclarações de parâmetros separadas por ponto e vírgula eenvolvidas entre parênteses. Quando você faz uma declaração emsérie, os parâmetros são separados por uma vírgula seguidos emmuitos casos por dois pontos e o tipo identificador e em muitoscasos também pelo sinal de igual e o valor default. Os nomes dosparâmetros devem ter identificadores válidos. Qualquerdeclaração pode ser precedida de var, const ou out.

Por exemplo:

(X, Y: Real)(var S: string; X: Integer)(HWnd: Integer; Text, Caption: PChar; Flags:Integer)(const P; I: Integer)

A lista de parâmetros especifica o número, ordem e tipo deparâmetros que devem ser passados para a rotina quando ela échamada. Se a rotina não tem nenhum parâmetro, omita a listade identificadores e os parênteses em sua declaração.

Por exemplo:

procedure Teste;begin {instruções}end;

Dentro do corpo da procedure ou função, o nome dosparâmetros, X e Y no nosso primeiro exemplo, podem ser usadascomo variáveis locais. Não redeclare os parâmetros na seção dedeclarações locais da procedure ou função.

Semântica de parâmetrosOs parâmetros são agrupados de diversas formas.

· Qualquer parâmetro é classificado como value, variable,const e out. Parâmetros Value são os default, as palavrasreservadas var, const e out indicam variáveis, constantes eparâmetros de saída, respectivamente.

· Os parâmetros Value são sempre tipados, enquanto

constantes, variáveis e parâmetros de saída podem ser cada umtipados ou não tipados.

· Regras especiais aplicam-se para arrays

Vamos ver sobre arrays mais adiante.

Parâmetros Variable e ValueA maioria dos parâmetros tem um dos dois, Variable ou

Value. Os parâmetros Value são passados por valor, enquanto osparâmetros Variable são passados por referência. Para ver o queisto significa, considere as seguintes funções:

function DoubleByValue(X: Integer): Integer; // X éum parâmetro valuebegin X := X * 2; Result := X;end;

function DoubleByRef(var X: Integer): Integer; // Xé um parâmetro variablebegin X := X * 2; Result := X;end;

Estas duas funções retornam o mesmo resultado, masapenas a segunda ou seja a DoubleByRef, pode modificar o valorque foi passado. Vamos supor que chamemos a função daseguinte forma:

varI, J, V, W: Integer;begin I := 4; V := 4; J := DoubleByValue(I); // J = 8, I = 4 W := DoubleByRef(V); // W = 8, V = 8end;

Depois que este código for executado, a variávei I, a qual foipassada para a função DoubleByValue, tem o mesmo valor quenós passamos inicialmente para ela. Mas a variável V a qual foipassada para a função DoubleByRef, terá um valor diferente.

Um parâmetro Value atua como uma variável local que éinicializada quando o valor é passado para a procedure oufunção. Se você passar uma variável como um parâmetro Value,a procedure ou função cria uma cópia dela. As modificações sãofeitas na cópia sem afetar a original. O parâmetro Variable, poroutro lado, atua como um ponteiro em lugar de uma cópia.Mudanças feitas para o parâmetro dentro do corpo de umafunção ou procedure persistem depois que a rotina é chamada.

Mesmo se alguma variável for passada em dois ou maisparâmetros var, nenhuma cópia será modificada. O código aseguir ilustra o nosso exemplo.

procedure AddOne(var X, Y: Integer);begin

DelphiDelphiDelphiDelphiDelphi

Page 27: Revista The Club Megazine - 12/ · PDF fileDelphi é marca registrada da Borland International, as ... DBGrid - Como fazer quebra de ... clique no checkbox “Create a new form

MeGAZINEMeGAZINEMeGAZINEMeGAZINEMeGAZINE 2 72 72 72 72 7

X := X + 1; Y := Y + 1;end;

var I: Integer;begin I := 1; AddOne(I, I);end;

Depois que este código executar, o valor de I será igual a 3.

Se a declaração da rotina especificar um parâmetro var, vocêdeve passar uma expressão transferível, isto é, uma variável,constante tipada, campo ou variável indexada para a rotinaquando você chamá-la. Para usar nosso exemplo anterior,DoubleByRef(7) produz um erro, embora DoubleByValue(7) énormal.

Parâmetro constanteUm parâmetro constante, const, é como uma constante local

ou variável read-only. Parâmetros constantes são similares aparâmetros Value, exceto que você não pode determinar um valorpara o parâmetro constante dentro do corpo de uma procedure oufunção, nem pode passar uma como parâmetro var para outrarotina. Mas quando você passa uma referência de objeto comoum parâmetro constante, você ainda pode modificar aspropriedades deste objeto.

Utilizar const fornece uma proteção contra a passagem semintenção de parâmetros por referência para outra rotina.

Aqui por exemplo, está o cabeçalho da função CompareStrque pode ser encontrada na unit SysUtils.

function CompareStr(const S1, S2: string): Integer;

Porque S1 e S2 não são modificadas no corpo de CompareStr,elas podem ser declaradas como parâmetros constantes.

Parâmetros OutUm parâmetro out, como um parâmetro Variable, é passado

por referência. Com um parâmetro out, de qualquer forma, ovalor inicial de uma variável referenciada é descartada pelarotina para a qual ela foi passada. O parâmetro out é do tipooutput apenas, ou seja, ele fala para a procedure ou função ondearmazenar a saída, mas não fornece a entrada.

Vamos analisar o seguinte exemplo:

procedure PegaInfo(out Info: QualquerTipo);

Quando você chama a procedure PegaInfo você deve passaruma variável de qualquer tipo.

var MinhaVariavel: QualquerTipo;PegaInfo(MinhaVariavel);

Mas você não está usando MinhaVariavel para passarqualquer informação para a procedure PegaInfo. MinhaVariavelé apenas um recipiente onde você quer que PegaInfo armazene a

informação que ele mesmo vai gerar. A chamada para PegaInfoimediatamente libera a memória usada por MinhaVariavel,antes do programa de controle passar para a procedure.

O parâmetro Out é usado com freqüência com modelos deobjetos distribuídos como COM e CORBA.

Parâmetros não tipadosVocê pode omitir tipos de especificações quando declara

parâmetros var, const e out. (Parâmetros Value devem sertipados.) Por exemplo,

procedure Teste(const C);

Declare uma procedure chamada Teste que recebe umparâmetro de qualquer tipo. Quando você chama como umarotina, você não pode passar para ela número ou constantenumérica não tipada. Dentro do corpo de uma procedure oufunção, parâmetros não tipados são incompatíveis com qualquertipo. Para trabalhar com um parâmetro não tipado, você devemoldá-lo. De uma forma geral, o compilador não pode verificarquais operações em parâmetros não tipados são válidos.

O exemplo a seguir usa parâmetros não tipados em umafunção chamada Equal que compara um número específico debytes de qualquer uma das duas variáveis.

function Equal(var Source, Dest; Size: Integer):Boolean;type TBytes = array[0..MaxInt - 1] of Byte; var N: Integer; begin N := 0; while (N < Size) and (TBytes(Dest)[N] =

TBytes(Source)[N]) do Inc(N); Equal := N = Size; end;

Determinando as declarações

type TVector = array[1..10] of Integer; TPoint = record X, Y: Integer;end;var Vec1, Vec2: TVector; N: Integer; P: TPoint;

Você poderia fazer as seguintes chamadas para Equal:

Equal(Vec1, Vec2, SizeOf(TVector))// compare Vec1 to Vec2Equal(Vec1, Vec2, SizeOf(Integer) * N)// compara primeiro N elementos de Vec1 e Vec2Equal(Vec1[1], P, 4)

DelphiDelphiDelphiDelphiDelphi

Page 28: Revista The Club Megazine - 12/ · PDF fileDelphi é marca registrada da Borland International, as ... DBGrid - Como fazer quebra de ... clique no checkbox “Create a new form

MeGAZINEMeGAZINEMeGAZINEMeGAZINEMeGAZINE2 82 82 82 82 8

// compara Vec1[1] para P.X e Vec1[2] para P.Y

Parâmetros StringQuando você declara uma rotina que tem parâmetros short-

string, você não pode incluir um tamanho específico nadeclaração dos parâmetros. Veja esta declaração:

procedure Check(S: string[20]); // syntax error

Ela causa um erro de compilação. Mas,

type TString20 = string[20];procedure Check(S: TString20);

não causa erro. O identificador OpenString pode ser usadopara declarar rotinas que tem parâmetros short-string detamanhos variáveis.

procedure Check(S: OpenString);

Quando se está utilizando as diretivas de compilação {$H-} e{$P+} a palavra reservada string é equivalente a OpenString nadeclaração de parâmetros. Strings curtas, OpenString, $H e $Psão suportadas apenas para manter a compatibilidade. Em novoscódigos, você pode ignorar estas informações, pois vocêtrabalhará com strings longas.

Parâmetros ArrayQuando você declara rotinas que tenham parâmetros array,

você não pode incluir tipos indexados na declaração deparâmetros, como por exemplo:

procedure Sort(A: array[1..10] of Integer);// sintaxe errada

A declaração anterior irá provocar um erro de sintaxe. Masfazendo da seguinte forma:

type TDigits = array[1..10] of Integer;procedure Sort(A: TDigits);

O erro não acontecerá. Para a maioria dos propósitos,entretanto, a próxima seção mostra uma melhor solução.

Desde então a linguagem Delphi, não implementa um valorsemântico para arrays dinâmicos. Parâmetros Value nas rotinasnão representam uma cópia total do array dinâmico.

Veja neste exemplo:

type TDynamicArray = array of Integer; procedure p(Value: TDynamicArray); begin Value[0] := 1; end; procedure Run; var a: TDynamicArray;

begin SetLength(a, 1); a[0] := 0; p(a); Writeln(a[0]); // Prints “1”! end;

Note que a tarefa de Value[0] na rotina P modificará oconteúdo do array dinâmico do chamador..

Parâmetro Array abertoParâmetros de array aberto permite arrays de diferentes

tamanhos serem passados para a procedure ou função. Paradefinir uma rotina com parâmetros de array aberto, use asintaxe array of type na declaração do parâmetro. Por exemplo:

function Find(A: array of Char): Integer;

Isto é uma declaração de uma função chamada Find quepega um array de char de qualquer tamanho e retorna uminteiro.

Atenção: A sintaxe de declaração de array aberto se parececom tipos de arrays dinâmicos, mas eles não significam a mesmacoisa. O exemplo anterior cria uma função que pega qualquerelemento de array de char. Para declarar parâmetros que devemser arrays dinâmicos, você precisa informar o tipo doidentificador.

type TDynamicCharArray = array of Char;function Find(A: TDynamicCharArray): Integer;

Dentro do corpo de uma rotina, os parâmetros de arrayaberto são controlados pelas seguintes regras.

1 – O primeiro elemento é 0, o segundo elemento é 1 e assimpor diante. As funções Low e High retornam 0 e -1respectivamente. A função SizeOf informa o tamanho atual doarray passado para a rotina.

2 – Eles podem ser acessados apenas pelo elemento. Tarefaspara um array aberto completo não é permitido.

3 – Eles podem ser passados para outras procedures efunções apenas com um parâmetro de array aberto ouparâmetros var não tipados.

Quando você passa um array como um parâmetro arrayaberto, o compilador cria uma cópia local do array dentro darotina. Cuidado para não sobrecarregar passando arrays muitograndes.

O exemplo a seguir mostra o uso de parâmetros de arrayaberto para definir uma procedure Zera que informa zero paracada elemento do array de real e uma função Sum que calcula asoma dos elementos em um array de real.

procedure Zera(var A: array of Real);var I: Integer;begin

DelphiDelphiDelphiDelphiDelphi

Page 29: Revista The Club Megazine - 12/ · PDF fileDelphi é marca registrada da Borland International, as ... DBGrid - Como fazer quebra de ... clique no checkbox “Create a new form

MeGAZINEMeGAZINEMeGAZINEMeGAZINEMeGAZINE 2 92 92 92 92 9

for I := 0 to High(A) do A[I] := 0;end;function Sum(const A: array of Real): Real;var I: Integer; S: Real;begin S := 0; for I := 0 to High(A) do S := S + A[I]; Sum := S;end;

Quando você usa rotinas que usam parâmetros de arraysaberto, você pode passar constructors de arrays abertos, quevemos mais adiante.

Parâmetros Variant Array abertosOs parâmetros Variant Array aberto permite você passar um

array de expressão diferentemente tipado para uma simplesfunção ou procedure. Para definir uma rotina com umparâmetro Variant Array aberto, especifique array of const comotipo do parâmetro. Desta forma,

procedure teste(A: array of const);

declara uma procedure chamada teste que pode trabalharcom arrays heterogêneos. A construção array of const éequivalente a array of TVarRec. TVarRec, declarado na unitSystem, representa um registro com uma parte variante quearmazena valores de tipos integer, Boolean, character, real,string, pointer, class, class reference, interface e variant.

O campo VType indica o tipo de cada elemento no array.Alguns tipos são passados como ponteiros, em particular, stringslongas são passadas como Pointer e devem ser convertidas parastring.

O exemplo a seguir usa um parâmetro array variant abertoem uma função que cria uma representação string de cadaelemento passado para ele e concatena o resultado em uma stringsimples. A rotina que controla a string chamada nesta funçãoestão definidas em SysUtils.

function MakeStr(const Args: array of const):string;var I: Integer;begin Result := ‘’;for I := 0 to High(Args) do with Args[I] do case VType of vtInteger: Result :=

Result + IntToStr(VInteger); vtBoolean: Result :=

Result + BoolToStr(VBoolean); vtChar: Result := Result + VChar; vtExtended: Result :=

Result + FloatToStr(VExtended^); vtString: Result := Result + VString^; vtPChar: Result := Result + VPChar; vtObject: Result :=

Result + VObject.ClassName; vtClass: Result := Result + VClass.ClassName; vtAnsiString: Result := Result +string(VAnsiString); vtCurrency: Result := Result +CurrToStr(VCurrency^); vtVariant: Result := Result +string(VVariant^); vtInt64: Result := Result + IntToStr(VInt64^); end;end;

Parâmetros DefaultVocê pode especificar um valor de parâmetro default no

cabeçalho de uma procedure ou função. Os valores default sãopermitidos apenas para tipos const e parâmetros Value. Parafornecer um valor default, vá até o final da declaração doparâmetro acrescente o sinal de igual e depois o valor. Veja umexemplo:

procedure FillArray(A: array of Integer;Value: Integer = 0);

Ambas as próximas chamadas são equivalentes.

FillArray(MyArray);FillArray(MyArray, 0);

Na declaração de vários parâmetros você não pode declararum valor default. Desta forma, a declaração

function MyFunction(X: Real = 3.5; Y: Real = 3.5):Real;

é correta, mas desta forma

function MyFunction(X, Y: Real = 3.5): Real;

é errada.

Os parâmetros com valor default devem ficar no final da listade parâmetros.

Isto é, todos os parâmetros seguindo o primeiro valor defaultdeclarado deve ter também valores default.

Veja a declaração a seguir:

procedure MyProcedure(I: Integer = 1; S: string);

Ela está errada.

Os parâmetros defaults são limitados para valores que podemser especificados por uma expressão constante.

DelphiDelphiDelphiDelphiDelphi

Page 30: Revista The Club Megazine - 12/ · PDF fileDelphi é marca registrada da Borland International, as ... DBGrid - Como fazer quebra de ... clique no checkbox “Create a new form

MeGAZINEMeGAZINEMeGAZINEMeGAZINEMeGAZINE3 03 03 03 03 0

ParâmetrosOs parâmetros de array dinâmicos, procedural, classes,

classes-reference ou tipo interface podem não ter valor ou possuiro valor nil com default.

Parâmetros de tipo record, variant, file, static-array ou objectnão podem ter valor default para todos.

Parâmetros default e rotinas sobrecarregadasSe você usa parâmetros com valores default em uma rotina

sobrecarregada, evite parâmetros ambíguos. Considere oseguinte:

procedure Confused(I: Integer); overload;procedure Confused(I: Integer; J: Integer = 0);

overload;

Ao chamarmos esta rotina

Confused(X);

Qual procedure será chamada?De fato, nenhuma das procedures foi chamada. Este código

gera um erro de compilação.

Chamando procedures e funçõesQuando você chama uma procedure ou função, o programa

controla os passos a partir do ponto onde a chamada é feita. Vocêpode fazer a chamada usando o nome declarado da rotina. Se arotina for declarada com parâmetros, você deve passar osparâmetros na chamada respeitando a ordem e o tipo declarados.Os parâmetros que você passa para a rotina são chamados deparâmetros atuais, enquanto os parâmetros que estão declaradossão chamados de parâmetros formais.

Quando chamar uma rotina se lembre que:· expressões usadas para passar uma constante tipada e um

valor devem ser compatíveis com os parâmetros formaiscorrespondentes.

· As expressões usadas para passar var e out devem seridênticas aos parâmetros formais, a menos que o parâmetroformal não seja tipado.

· Apenas expressões transferíveis podem ser usadas parapassar os parâmetros var e out

· Se os parâmetros formais da rotina não são tipados,numerais e constantes verdadeiras, não podem ser usados comoparâmetros atuais.

Quando você chama uma rotina que utiliza parâmetrosdefault, todos os parâmetros seguintes ao primeiro aceitam eusam valor default. Chamar uma rotina da seguinte forma:

Teste(,,X);

é errado. Você só pode omitir os parênteses se forem todos eapenas o parâmetro default. Veja o exemplo da nossa rotina.

procedure teste(X: Real = 1.0; I: Integer =0; S: string = ‘’);

Você pode chamar da seguinte forma:

Teste();Teste;

Constructors de arrays abertosContructors de arrays abertos permite a você construir

arrays diretamente dentro da função ou procedure chamada.Um constructor de array aberto, como um conjunto de

constructor, é uma seqüência de expressões separadas porvírgulas e fechadas entre colchetes.

var I, J: Integer;procedure Add(A: array of Integer);

Você poderia chamar a procedure Add com a seguinteinstrução.

Add([5, 7, I, I + J]);

Isto é equivalente a:

var Temp: array[0..3] of Integer;Temp[0] := 5;Temp[1] := 7;Temp[2] := I;Temp[3] := I + J;Add(Temp);

Constructors de arrays abertos podem ser passados apenascomo valor ou constante. As expressões em um constructordevem ser compatíveis com o tipo base do array. Neste caso deum constructor de array aberto, as expressões podem ser de tiposdiferentes.

ConclusãoO intuito deste artigo foi mostrar alguns recursos do Delphi

que nem sempre encontramos em livros ou apostilas. Itens quepodem nos ajudar muito no dia a dia. Aproveitando aoportunidade eu gostaria de agradecer a todos aqueles sócios quenos acompanharam durante todo este ano. Quero desejar a todosum Feliz Natal e um fantástico 2004. No ano que vem estaremosaqui, firmes na luta diária trazendo para vocês muitasinformações úteis para o seu dia a dia, principalmente sobre oDelphi 8.

Até o próximo ano e boas festas.

Sobre o autorClaudinei Rodrigues,Consultor Técnico do The [email protected]

DelphiDelphiDelphiDelphiDelphi