Você está na página 1de 175

Delphi 3.

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

Delphi 1. Introduo Delphi uma ferramenta grfica para voc poder utilizar toda a potencialidade do Object Pascal. Logo aps executar o Delphi, voc tem disposio o IDE (Integrated Development Environment), o ambiente Integrado de desenvolvimento. Atravs dele, lhe ser poupada muita digitao, pois atravs do recurso de arrastar-e-soltar voc estar na realidade construindo cdigo-fonte sem tocar no teclado. Estes ambientes integrados, alis, nos poupou bastante trabalho em termos de digitao, porm, a lgica continua cabendo ao programador. 2. O IDE (Integrated Development Environment) Abaixo mostrado o IDE. Nele voc pode ver trs reas principais: Object Inspector (Inspetor de Objetos) Component Palette (Palheta de Componentes, agregado a uma barra de teclas de atalho) Form (Form em branco)

Object Inspector

Component

Palette

Form

Minimizando o Form (como qualquer janela do Windows), voc poder notar ainda uma outra rea que o Code Editor (Editor de Cdigo-Fonte):

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

Nesta rea, iremos digitar o cdigo adicional necessrio execuo dos nossos programas. 3. Construindo um projeto Quando voc executa o Delphi, j tem sua disposio uma janela com todos as propriedades bsicas (de uma janela): estilo da borda (Border Style), altura (Height), largura (Width), ttulo (Caption), etc. , alm das aes caractersticas passveis a uma janela do ambiente Windows: arraste, minimizao, maximizao, fechamento, etc. Isto tudo para dizer que voc no precisa reinventar a roda, ou seja, programar tudo aquilo que j deve estar contido por default numa janela. Porm, no considere isto como uma camisa-de-foras, pois voc poder personalizar a sua janela de acordo com as suas necessidades. Para entender como ser construdo o nosso aplicativo, vamos entender como construdo um aplicativo Delphi. Antes de iniciar a construo de um aplicativo Delphi, vamos entender como que se constri um aplicativo executvel qualquer: 3.1. Cdigo-fonte: a parte que contm os comandos digitados pelo usurio ou, inseridos pelo ambiente de desenvolvimento 3.2. Cdigo-objeto: o resultado da compilao do cdigo-fonte. Toda linguagem de programao contm um compilador que, ao ser executado, verifica se o cdigo-fonte contm erros de sintaxe (por exemplo, o comando Close escrito com "z" como em Cloze). Caso os tenha, o compilador acusa o(s) erro(s), permitindo que voc o(s) corrija. Ao trmino de todas as correes, o compilador ento "traduz" todo o cdigo-fonte linha-a-linha em linguagem de mquina (cdigo-binrio), ao qual chamamos de cdigo-objeto. 3.3. Cdigo-executvel: uma vez terminada a compilao, o cdigo-objeto deve sofrer ento uma linkedio. Isto se faz necessrio devido ao cdigo-objeto ser

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

cdigo binrio porm "solto", isto , no temos como "dizer" ao programa a ordem de execuo das rotinas. O linkeditor (do ingls: to link : unir, ligar) tem por funo unir as rotinas do cdigo-objeto na seqncia de execuo. Devido a estarmos trabalhando num ambiente integrado de desenvolvimento, teremos todas essas ferramentas (editor de cdigo-fonte, grfico e texto, compilador, linkeditor) disponveis ao mesmo tempo, diferentemente do que precisvamos em algumas outras linguagens. Agora que sabemos os passos necessrios para gerar um aplicativo (programa executvel) qualquer, precisamos entender como constru-lo com o Delphi. Em primeiro lugar, vamos entender como composto um cdigo-fonte em Delphi: PROJETO

UNIT 1

UNIT 2

UNIT n

Voc pode trabalhar com mais de uma janela (criar mais de uma janela no seu aplicativo) podendo, atravs de comandos por voc digitados, alternar entre essas janelas. Mas voc ter que ter um lugar onde esteja escrito quais so as janelas constituintes do seu aplicativo. Dito isto, podemos dizer que voc deve construir um projeto que contenha quais so as janelas contidas neste projeto. Alm disto, cada janela poder ter um cdigo diferente de outra janela (imagine um sistema que contenha uma janela para senha, uma janela para funcionar com uma calculadora, e uma janela para clculo de taxas de juros), pois as caractersticas bsicas o Delphi j escreveu para voc, mas as modificaes subseqentes so sua responsabilidade. Assim sendo, podemos dizer, numa primeira anlise que, o cdigo-fonte de cada janela adicionada ao seu projeto ser escrito numa UNIT, e que o projeto conter os nomes de todas as units que compe o seu sistema.

4. Construindo o primeiro aplicativo

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

4.1. Executando a aplicativo Como voc j tem um cdigo-fonte disposio, execute-o clicando no boto RUN:

Veja agora o aplicativo sendo executado: uma janela em branco, com o ttulo Form1 (observe que os pontinhos de alinhamento no mais aparecem, somente estando presentes na fase de projeto), alm do boto RUN desabilitado e a palavra Running:

Arraste-a, redimensione-a e depois a feche. Voc retorna automaticamente ao IDE.

4.2. Verificando o cdigo-fonte

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

Vamos examinar, sem maiores preocupaes em entender, ainda, o cdigo-fonte produzido pelo Delphi para o projeto no qual voc est trabalhando. Minimize a janela e verifique que o cdigo escrito para a janela : unit Unit1; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs; type TForm1 = class(TForm) private { Private declarations } public { Public declarations } end; var Form1: TForm1; implementation {$R *.DFM} end. Podemos ver preliminarmente que, a unit UNIT1 possui uma varivel (var) denominada Form1, que igual ao ttulo da janela. No vemos mais informao relevante para essa janela. Vamos verificar agora o cdigo-fonte do projeto. Para isto, d um clique em View-Project Source:

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

O cdigo o seguinte: program Project1; uses Forms, Unit1 in 'Unit1.pas' {Form1}; {$R *.RES} begin Application.Initialize; Application.CreateForm(TForm1, Form1); Application.Run; end. O cdigo nos informa que o projeto cujo nome Project1, possui uma janela (Form1) na unit UNIT1, que por sua vez est contida no arquivo Unit1.pas. A janela criada (visualmente) na linha Application.CreateForm(TForm1, Form1); e o aplicativo comea a rodar (executar) com a linha Application.Run; (uma maneira de informar ao Windows que o aplicativo est apto para comear a sua execuo. Mais tarde, em manipulando eventos, ser explicado o porqu disto). Para retornar ao form Form1: - d um clique no boto Select form from list, - clique no nome do form Form1 - d um clique em OK

4.3. Adicionando um boto

Para adicionar um boto, voc deve dar um clique no objeto correspondente no Component Palette

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

e em seguida dar um clique sobre janela, mais ou menos na posio onde voc acha que o boto deve ficar. (Preste bem ateno: no precisa ser o local exato onde voc deseja que o boto esteja, pois voc poder depois de adicionado o boto arrast-lo para qualquer lugar dentro da janela qual voc adicionou o boto). Veja que agora o form contm um boto, cujo ttulo Button1:

Podemos alterar esse ttulo (caption) sem sentido por algo mais explicativo, como por exemplo Fechar. O que voc est querendo fazer ento alterar uma das propriedades do objeto, que o seu caption. Algumas propriedades podem ser alteradas no Object Inspector. Assim, d um clique no Object Inspector no lado direito onde aparece a propriedade Caption:

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

Digite a palavra Fechar. Verifique que o caption do boto vai sendo alterado automaticamente. Isto significa que, voc acaba de alterar a propriedade Caption do componente Button1.

Mas como Button1, se voc alterou o caption de Button1 para Fechar? Veja bem, voc alterou o ttulo (caption) do boto de Button1 para Fechar, mas o nome (propriedade Name) do componente continua Button1 (olhe o Object Inspector e verifique que o nome propriedade Name - do componente Button1 mas sua propriedade Caption Fechar). Para alterar o caption da janela, d um clique (simples) no form ou ento d um clique no ComboBox do Object Inspector: e selecione

Form1. Altere o Caption para: A primeira janela a gente nunca esquece. Note que o ttulo da janela (Caption) alterado. Execute novamente o aplicativo. D um clique no boto. Observe que no acontece coisa alguma. 4.4. Manipulando eventos No item 4.2, verificando o cdigo-fonte do projeto, voc pde ver a linha Application.Run; . Esta linha "aciona" o manipulador de eventos do Windows para a sua aplicao.

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

O Windows um sistema operacional multitarefa, e como tal, deve poder gerenciar vrias atividades ocorrendo de maneira "simultnea" (para ns parece ser simultneo o ecoar de uma letra na tela aps o pressionar de uma tecla, mas entre uma e outra ao decorre uma frao de tempo). Isto significa dizer que, se antigamente o usurio de um programa interagia com o mesmo, agora, o usurio interage com o Windows, e o mesmo que tem que notificar o aplicativo sofrendo a ao (um pressionar de uma tecla, um clique do mouse, uma ordem de fechamento), enviando junto notificao qual o tipo de ao (ou evento) ocorrido. Bem, se o seu aplicativo contiver cdigo que trate (manipule) o evento acontecido, esse cdigo executado; caso contrrio, o aplicativo "pede" ao Windows que manipule o evento com uma ao default. Para exemplificar, voc viu que ao pressionar o boto na janela do seu aplicativo no aconteceu nada. Foi executada uma manipulao padro pelo Windows. Vamos ento escrever cdigo para manipular o evento do clique do boto pelo mouse. D um clique em cima do boto, selecionando-o. Agora, d um clique na aba Events , seguido de um clique duplo no lado direito do evento OnClick:

Aparece para ns o editor de cdigo com uma estrutura pr-criada, de tal maneira que precisamos somente escrever o cdigo da manipulao de evento para o componente selecionado.

Voc pode notar que a estrutura, comentada acima, a seguinte: procedure TForm1.Button1Click(Sender: TObject); begin end;

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

10

Isto significa dizer que, um aplicativo Windows funciona manipulando eventos externos, por exemplo os causados por uma pessoa (digitando, deslocando o mouse ou clicando um de seus botes), um outro aplicativo (quando voc copia uma coisa num aplicativo e cola em outro) ou o prprio Windows (fechando o seu aplicativo por um determinado motivo, ou qualquer outra ao). A maior parte das manipulaes de evento tratadas pelo Delphi tero a seguinte estrutura bsica: procedure Tipo_Form.Nome_ComponenteNomeEvento (Sender:Tobject); begin end; Para finalizar: antes de executar novamente seu aplicativo, digite o cdigo abaixo, entre as linhas begin e end; : procedure TForm1.Button1Click(Sender: TObject); begin Close ; end; O comando Close o comando de fechamento de uma janela. E se essa janela for a janela principal do aplicativo, o prprio aplicativo fechado. Execute o aplicativo novamente e d um clique no boto. Veja que o aplicativo encerrado e h o retorno ao IDE. 4.5. Trabalhando com duas janelas Ao executar um aplicativo voc, em determinados momentos, desejar executar aes diferentes em janelas diferentes. Para resolver esta questo, precisamos trabalhar com dois forms no nosso projeto, sendo que um deles ser o form principal e o outro o form que ser "chamado" pelo primeiro form. O form principal aparecer em primeiro lugar sempre que o aplicativo for executado, e a ele sempre se dever retornar para uma ao inicial. Geralmente, esse form o form que deve estar ativo para que encerremos a aplicao. Um form pode "chamar" outro de duas maneiras: - no-modal: voc pode alternar entre as janelas, clicando e selecionando tanto a janela chamadora, como a janela chamada - modal: voc s pode selecionar a janela chamadora caso voc feche a janela chamada. Voc tem diversos exemplos de janelas chamadas (invocadas) de uma das maneiras acima. Por exemplo, ao utilizar o Windows para Localizar Arquivos ou Pastas (Ferramentas-Localizar-Arquivos ou Pastas...), voc pode num momento clicar sobre o Windows Explorer e torn-lo ativo, e logo aps pode clicar na janela Localizar e torn-la ativa novamente. Esta a maneira no-modal de invocar uma janela. J para visualizar a maneira modal, clique em Ferramentas-Ir Para... e , aps surgir a janela

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

11

Ir para a Pasta tente tornar a janela do Windows Explorer ativa. Note que a ordem no obedecida, e somente ser caso voc feche a janela ativa. 4.5.1. No-Modal

Comece um novo projeto: File - New Application (Caso aparea uma janela de dilogo perguntando se voc deseja salvar as alteraes para o projeto Project1, clique no boto No). Voc j tem em seu projeto um form (Form1) Adicione um novo form ao seu projeto: File - New Form Visualize os Forms do projeto: View - Forms... D um clique sobre o nome do Form1 e depois clique em OK Adicione um boto ao Form1: clique no componente Button (vide item 4.3) da palheta de componentes (Component Palette) Estando o boto selecionado (verifique no Object Inspector), clique na aba Events e em seguida d um duplo clique no lado direito do evento OnClick. Digite o comando Form2.Show; entre os comandos begin e end; como mostrado abaixo (no esquea de separar o nome do componente Form2 do comando Show por um ponto): procedure TForm1.Button1Click(Sender: TObject); begin Form2.Show ; end; Execute a sua aplicao: Run - Run (item 4.1) . Ao aparecer a mensagem: Form 'Form1' references form 'Form2' declared in unit 'Unit2' which is not in your USES list. Do you wish to add it? D um clique no boto Yes e rode novamente a aplicao. Isto se faz necessrio porque o projeto conhece todos os forms que fazem parte da aplicao, mas os forms no se "conhecem" individualmente. Ao invocar o Form2 a partir do Form1, voc precisa "explicar ao form1: utilize o Form2 cujo cdigo encontrase na unit Unit2 deste projeto. A maneira correta de se fazer isto, adicionar a clusula USES Unit2; ao cdigo-fonte da Unit1, e o Delphi faz isto por voc automaticamente. Aparece o Form1 (verifique o ttulo - Caption - da janela). D um clique no boto: aparece agora o Form2 (verifique novamente o Caption). D um clique no Form1 (caso voc no esteja vendo o Form1, arraste um pouco o Form2 at que voc visualize o Form1). Voc pode verificar tambm se um form o form ativo, verificando se a sua barra de ttulos (onde encontra-se o Caption) est numa cor destacada. Feche o Form2 e depois o Form1, retornando ao IDE. 4.5.2. Modal Clique novamente no boto, selecionando-o Clique na aba Events do Object Inspector e d um duplo clique no evento OnClick (vamos manipular o evento OnClick de Button1)

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

12

Altere o cdigo-existente de: Form2.Show ; Para (adicione a palavra Modal ao comando Show ): Form2.ShowModal ; Execute novamente a aplicao. Clique o boto e veja aparecer o Form2. Tente selecionar o Form1 clicando sobre ele! Voc no consegue faz-lo, a menos que feche o Form2. Feche o Form1 para retornar ao Delphi (IDE) 4.6. Componentes Label e Edit Box O componente Label aquele que usamos para conter um texto curto (de uma linha geralmente) indicativo sobre um determinado boto ou ao que deva ser efetuada ou algo a ser digitado. Por exemplo, quando voc utiliza o Bloco de Notas do Windows e deseja localizar determinada ocorrncia de texto, voc clica em Pesquisar - Localizar... e, ao surgir a janela de pesquisa voc observa que, antecedendo ao local onde voc deve escrever o trecho a localizar, h a palavra Localizar: . Esta palavra est contida em um componente Label e o local onde digitaremos o trecho a localizar estar contido num componente Edit Box. Vamos criar algo parecido: File - New Application Adicione um boto ao form Manipule o evento OnClick do boto com: Form2.ShowModal Adicione um novo Form ao projeto Adicione um componente Label e um componente Edit Box ao Form2

Arraste os componentes de tal maneira que o Form fique com a aparncia final abaixo:

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

13

Apague a palavra Edit1 da propriedade Text do componente Edit Box (cujo nome - propriedade Name Edit1. No deixe a propriedade Name vazia, pois certamente o Delphi ficar perdido sem essa informao, fazendo com que voc tenha que abandonar o projeto e recomear outro). Esta propriedade, Text, tem por funo conter a palavra que aparece no componente. D agora um clique no componente Label e altere a sua propriedade Caption de Label1 para Localizar: (verifique no Object Inspector se o componente ativo o componente Label. Caso seja e voc no esteja conseguindo visualizar a propriedade Caption, utilize a barra de rolagem vertical). Observe que, toda a vez que voc coloca um componente no Form, a propriedade Caption ou Text, dependendo do componente, igual ao nome do mesmo, seguido de um nmero que indica quantos componentes daquele tipo esto contidos naquele form. Por enquanto, ns no vamos alterar a propriedade Name dos componentes. Execute a aplicao e d um clique no boto: aparece o Form2. Veja que voc pode selecionar e digitar o que quiser no componente Edit Box, porm o componente Label s pode ser visto, mas no pode ser alterado. Feche o Form2 e depois o Form1, retornando ao Delphi. Manipule o evento OnDblClick do componente Edit1 com a linha de comando seguinte (preste ateno: no h espao em branco entre o caractere dois pontos e o sinal de igual ): Label1.Caption

:= Edit1.Text ;

Execute a aplicao novamente, chame o Form2, digite alguma coisa no Edit Box e depois d um clique duplo nele. Verifique que o Caption do componente Label1 passa a conter o mesmo que Edit1. Feche o Form2 e depois o Form1, retornando ao Delphi.

A partir de agora, partirei do princpio que voc j sabe:

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

14

Comear uma nova aplicao: File - New Application Adicionar um componente ao Form: d um clique no componente desejado, selecionando-o, seguido de um clique no form. O componente aparece no form. Adicionar mltiplas cpias de um mesmo componente ao Form: mantenha a tecla shift pressionada e d um clique no componente desejado (o componente fica envolto por uma caixa de lados pontilhados azuis); libere a tecla shift e v clicando no Form, nas posies onde voc deseja adicionar o componente. Ao adicionar o nmero desejado do componente, d um clique na seta branca (no incio do component palette). Isto faz com que seja cancelada a seleo do componente. Alterar as dimenses do componente: para os componentes que permitem tal operao, voc deve dar um clique (simples) no componente, selecionando-o (o componente fica delimitado por pequenos quadrados nas suas reas limtrofes. Quando o cursor do mouse aproximado de um destes quadradinhos, sua forma alterada para uma seta dupla. Neste ponto voc pode, mantendo o boto esquerdo do mouse pressionado, redimensionar o componente. Apagar um componente: d um clique no componente, selecionando-o, e d um toque na tecla Del (ou Delete) do teclado. Operaes em mltiplos componentes: digamos que, por exemplo, voc tenha um componente Button, um componente Label e um componente Edit Box no form. Por hiptese, voc deseja mover todos os componentes para a esquerda, de uma s vez. Isto se faz necessrio porque digamos voc deseja manter as distncias entre os mesmos. Realize essa operao, mantendo a tecla shift pressionada, seguido de um clique em cada componente desejado. Libere a tecla shift. Os quadradinhos de delimitao ficam acinzentados. Arraste um dos componentes e observe que todos os componentes se movem. Para cancelar a seleo mltipla, d um clique num componente no selecionado (por exemplo, no Form).Os componentes selecionados podem ser excludos em grupo tambm. Verificar o componente atualmente selecionado: v ao Object Inspector e verifique o nome do componente na caixa de listagem (logo abaixo de onde se l: Object Inspector). Manipular um evento do componente: d um clique na aba Events do Object Inspector (certifique-se que o componente selecionado o componente desejado) e d um clique duplo no evento correspondente, escrevendo o cdigo necessrio sua manipulao.

4.7. Componente Image Comece uma nova aplicao Clique na aba ADDITIONAL

Adicione o componente Image ao form

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

15

Clique na propriedade Picture deste componente; em seguida, d um clique no boto reticncias Aparece o Picture Editor

Clique em Load Na caixa

Examinar: selecione uma pasta que contenha qualquer um dos arquivos de desenho (cujas extenses aparecem na caixa Arquivos do tipo:). Voc pode pesquisar a pasta: DELPHI3\IMAGES\SPLASH\16COLOR, assumindo uma instalao padro do Delphi. Clique o boto Abrir. Clique em OK . Como a imagem muito grande para caber no componente Image, altere a propriedade Autosize deste componente de False para True (d um clique na seta que se encontra ao lado direito da propriedade Autosize, e depois d um clique em True), como mostrado abaixo:

Adicione um componente Label (aba STANDARD) ao form e altere a sua propriedade Caption com qualquer texto que voc deseje. Adicione um componente Button (aba STANDARD) ao form e, no evento OnClick, escreva o comando "Close ; ", como mostrado abaixo:

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

16

procedure Tform1.Button1Click(Sender: Tobject); begin Close ; end; Execute a aplicao (Run - Run). D um clique no boto para fechar a aplicao (encerrar a execuo). 4.8. Janela de Mensagem: ShowMessage Comece uma nova aplicao. Adicione um boto ao form Altere o Caption do boto para MSG. Na manipulao do evento OnClick do boto, escreva: ShowMessage ( ' Isto uma janela de mensagem! ' ) ; Caso acontea um erro de compilao, tente alterar os apstrofes (aspas simples) utilizados na delimitao do texto (utilize os mesmos apstrofes, tanto no incio, como no final do texto). Adicione outro boto, altere o Caption para &Fechar e manipule o evento OnClick para fechar a aplicao (comando Close). Execute a aplicao (rode o programa) e d um clique no boto MSG. Feche a aplicao. 4.9. Janela de Mensagem: MessageDlg Para que voc possa utilizar essa janela de mensagem, voc ter que digitar quatro parmetros entre parnteses (separados por vrgula): Mensagem : delimitada por apstrofes Tipo de janela: Janela de mensagem contendo um ponto de exclamao amarelo mtError Janela de mensagem contendo um sinal de pre (STOP) vermelho. mtInformation Janela de mensagem contendo a letra "I" azul. mtConfirmation Janela de mensagem contendo uma marca verde. mtCustom Janela de mensagem sem bitmap (figura). O Caption da janela de mensagem, o nome do arquivo executvel da aplicao. Tipo de boto utilizado na janela. Selecione qual (ou quais) boto (ou botes) que aparecer (ou aparecero) na sua janela de mensagem: mtWarning

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

17

mbYes mbNo mbOK mbCancel mbHelp mbAbort mbRetry mbIgnore mbAll

Um boto com o texto 'Yes' na sua face Um boto com o texto 'No' na sua face Um boto com o texto 'OK' na sua face Um boto com o texto 'Cancel' na sua face Um boto com o texto 'Help' na sua face Um boto com o texto 'Abort' na sua face Um boto com o texto 'Retry' na sua face Um boto com o texto 'Ignore' na sua face Um boto com o texto 'All' na sua face

Obs1: Ao definir o tipo (ou tipos) de boto, voc estar definindo, na realidade, um conjunto de botes. Caso voc deseje utilizar um dos botes acima, digite o tipo desejado entre colchetes., pois o Delphi s reconhece um conjunto se os elementos do conjunto estiverem delimitados por colchetes. Caso voc deseje utilizar mais de um boto na sua janela, os tipos desejados devem ser separados por vrgula. Obs2: Os conjuntos pr-definidos abaixo dispensam a utilizao de colchetes (por serem eles prprios um conjunto): mbYesNoCancel mbOkCancel mbAbortRetryIgnore Coloca os botes Yes, No e Cancel na janela de mensagem Coloca o boto OK e Cancel na janela de mensagem Coloca os botes Abort, Retry e Ignore na janela de mensagem

HelpCtx : ligao (link) ao tpico de ajuda. Caso no haja ajuda (e no nosso caso no h), utilize o parmetro 0 (zero).

Vamos ento testar algumas janelas de mensagem: Comece uma nova aplicao Coloque cinco botes no form Altere os caption para: Aviso , Erro , Informao , Confirmao e Fechar Manipule o evento OnClick dos botes da seguinte forma:

boto Aviso: MessageDlg ('Aviso' , mtWarning , [mbOK] , 0 ) ; boto Erro : MessageDlg ('Erro' , mtError , [mbRetry,mbCancel] , 0 ) ; boto Informao: MessageDlg ('Informao' , mtInformation , [mbOK] , 0 ) ; boto Confirmao: MessageDlg ('Confirmao' , mtConfirmation, mbOKCancel , 0 ) ; boto Fechar: MessageDlg ('Fechar' , mtCustom, [mbYes] , 0 ) ; Obs3.: Mais uma vez: no boto Confirmao, mbOKCancel no est delimitado por colchetes por ser ele prprio um conjunto pr-definido. 4.10. Componente Timer

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

18

O componente Timer (aba System do Component Palette) gera uma chamada ao seu aplicativo em intervalos de tempo programveis, como se fosse um despertador. Vamos construir um relgio simples, que mostra, a cada segundo, a hora correta. Para isso, necessitaremos de um componente Label (o relgio mostrar a hora; no faz sentido deixar o usurio escrever algo diferente da informao que mostrada. Voc pode ver um relgio idntico na barra de tarefas do Windows), alm de um componente Timer, programado para gerar eventos OnTimer a cada 1000 ms (1000 ms = 1s). A funo NOW retorna a data e a hora do sistema operacional e TimeToStr formatar o valor de retorno de NOW para gerar um conjunto de caracteres representando a hora. File - New Application Adicione um componente Label e um componente Timer (aba System) ao Form1

Com o componente Timer1 selecionado (verifique no Object Inspector; caso no seja o componente Timer1, d um clique simples sobre ele, selecionando-o), verifique se a sua propriedade Enabled est em True e a propriedade Interval est com o valor 1000, como abaixo:

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

19

Agora, precisamos manipular seu evento OnTimer. Clique na aba Events do Object Inspector e d um clique duplo no lado direito do evento (que o nico evento que um componente Timer pode gerar), escrevendo o cdigo Label1.Caption := TimeToStr (NOW) ; como mostrado abaixo (preste ateno: no h espao em branco entre o caractere dois pontos e o sinal de igual ): procedure Tform1.Timer1Timer(Sender: Tobject); begin Label1.Caption := TimeToStr (NOW) ; end; Execute o aplicativo e veja a cada segundo o relgio sendo atualizado. Feche a janela

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

20

5. Linguagem Pascal Para desenvolver aplicativos em Delphi, precisamos conhecer o Object Pascal, que baseada na linguagem Pascal com adies inerentes ao ambiente Windows. 5.1. Estrutura bsica de um programa Delphi Basicamente, ns iremos manipular os eventos dos objetos que componham nosso projeto. No todos, mas somente aqueles que forem necessrios. A cada instante, o usurio poder clicar (com o mouse) sobre um determinado form, ou um objeto nesse form, ou chamar um outro form, ou mesmo fech-lo. Ao mesmo tempo que isso possa estar acontecendo, o form pode estar recebendo um evento OnTimer, alm de "n" outras situaes possveis dentro do ambiente Windows. Aqui ento iremos considerar a estrutura mais simples possvel, que aquela utilizada pela rotina tratadora do evento do objeto considerado. Para manipular um evento, o Delphi faz uso de uma pequena rotina, dentro de uma rotina maior, que chamamos de programa principal, isto , o programa principal chama, a cada gerao de evento, a rotina correta para tratar aquele evento. Assim, quando voc d o clique duplo no lado direito do evento do componente, aparece uma estrutura semi-montada com a palavra reservada procedure: procedure Tnome_Form Nome_Componente_Nome_Evento (Sender : Tobject) ; begin end ; Esta pequena estrutura segue a estrutura bsica de um programa Pascal e, sendo assim, poderemos utilizar a estrutura descrita abaixo: procedure Tnome_Form Nome_Componente_Nome_Evento (Sender : Tobject) ; Const Const1 = Valor1 ; Const2 = Valor2 ; Type Tipo1 = Tipo_ObjectPascal1_Modificado ; Tipo2 = Tipo_ObjectPascal2 _Modificado ; Var Var1 : Tipo1 ; Var2 : Tipo2 ; Var3 : Tipo3 ; begin Comando1 ; Comando2 ; ComandoN ; end ;

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

21

5.2. Constantes So smbolos (nomes) que voc associa a valores (numricos, letras, etc.), e que se tornam invariveis durante a execuo da procedure, ou seja, uma vez que eu associe a constante ao valor desejado, no poder haver entre os comandos begin e end qualquer alterao no valor do smbolo em questo, e ele sempre valer o que foi definido na clusula Const. Caso voc queira alterar esse valor, precisar editar o cdigo-fonte e recompilar o programa. Por exemplo, a seguir foi associado o valor 1000 constante Num_Maximo_Dados: Const Num_Maximo_Dados = 1000 ; Sempre finalize a declarao de uma constante com o caractere ponto-e-vrgula (; ). Voc poder utilizar a constante, dentro do seu programa, em substituio ao valor numrico 1000. Imagine a hiptese de voc ter a manipulao de um evento com 550 linhas, e que destas 550 linhas, 43 linhas referem-se impresso do valor 1000. Caso voc queira alterar esse valor para 3900, precisar alterar as 43 linhas do cdigofonte que fazem referncia ao valor 1000. Caso voc trabalhe com a constante Num_maximo_Dados, precisar alterar apenas a linha Const Num_Maximo_Dados = 1000 ; para, Const Num_Maximo_Dados = 3900 ; o que certamente lhe trar flexibilidade e rapidez. 5.3. Tipos Para que voc possa utilizar valores no-constantes no seu programa (que esto armazenados na memria RAM de seu computador), voc precisa declarar variveis de memria, ou simplesmente, variveis, que so os smbolos que permitem a voc manipular um determinado valor de acordo com certas caractersticas. Por exemplo, voc precisa ter uma varivel para armazenar idades de pessoas. Essa varivel conter, ento, um valor numrico que poder ser incrementado de 1 unidade ou diminudo de outro valor , etc. , coisas que so relativas a valores numricos. Voc poderia querer utilizar outra varivel para armazenar nomes pessoais. Nesse caso, no convm operar aritmeticamente sobre os dados. Ou seja, na etapa de criao de um programa, voc desejar declarar quantas variveis forem necessrias para resolver o problema proposto. E cada varivel desta ter um tipo de comportamento correspondente. Podemos definir as caractersticas de uma varivel pela definio de seu tipo.

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

22

5.3.1. Tipos Ordinais: tm predecessor e sucessor Numricos: ShortInt SmallInt (ou Integer) LongInt Byte : 0 .. 255 Word Char (caracter): AnsiChar (ou Char) WideChar : conjunto de caracter ANSI : conjunto de caracter UNICODE sem sinal : 8 bits sem sinal : 16 bits : -128 .. 127 : -32768 .. 32767 : -2147483648 .. 2147483647 sem sinal : 0 .. 65535 sinal sinal sinal : 8 bits sem sinal : 8 bits : 16 bits : 32 bits : 16 bits

Obs1.: Todo caractere em Pascal deve estar delimitado por apstrofe ( ' ). Obs2.: Os 256 primeiros caracteres do conjunto UNICODE correspondem aos caracteres do conjunto ANSI. Enumerados:

Tipos enumerados definem conjuntos de valores que enumeram os identificadores que denotam esses valores. Por exemplo, podemos criar o tipo enumerado Cartao com os valores: CREDICARD, AMEX, VISA, OUTROS, associando-os pelo sinal de igual, como mostrado abaixo: Type Cartao = (CREDICARD, AMEX, VISA, OUTROS) ; Sendo que CREDICARD uma constante do conjunto Cartao. Mais tarde construiremos uma aplicao que faz uso de tipos enumerados. Boolean: Tipos que somente contm dois valores: True (verdadeiro) e False (falso). SubRange:

Tipos que somente contm os valores delimitados pelos valores inicial e final separados por dois pontos ( . . ) , indicando tratar-se de um limite, que tem como base o tipo chamado hospedeiro (ou tipo host), que deve ser do tipo ordinal. Por exemplo, se voc declara o seguinte tipo: Type idade = 1 .. 90 ;

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

23

Significa que o tipo idade um conjunto de valores Byte dentro do limite inicial 1 e limite final 90. 5.3.2. Tipo Real: contm um subconjunto do conjunto dos nmeros reais Real : 2.9 x 10-39 .. 1.7 x 1038 sinal: 6 bytes

Obs1.: O tipo Real foi mantido devido compatibilidade com o Delphi 1 e o Turbo Pascal Single Double Extended Comp Currency : 1.5 x 10-45 .. 3.4 x 1038 : 5.0 x 10-324 .. 1.7 x 10308 : 3.4 x 10-4932 .. 1.1 x 104932 : -263 + 1 .. 263 + 1 : -922337203685477.5808 .. 922337203685477.5807 sinal: sinal: sinal: sinal: sinal: 4 bytes 8 bytes 10 bytes 8 bytes 8 bytes

Obs2.: Nas nossas aplicaes, utilizaremos o tipo Extended para valores com casas decimais. 5.3.3. Tipo String: cadeia de caracteres Strings servem para armazenar caracteres alfanumricos e simblicos, de maneira mista ou no. Isto depender da sua necessidade no momento. Toda string em Pascal deve ser delimitada pelo caractere apstrofe. Exemplos de string so: 'Curso de Delphi - Professor Jos Luiz A. Rosa - 1998' 'Delphi um Ambiente Visual que Utiliza Pascal Orientado a Objeto!' '20.541-130' Observe que a terceira string contm, no uma operao aritmtica (subtrao de dois valores numricos), mas um cdigo de CEP (dos Correios). Assim sendo, strings servem tambm para armazenar nmeros que no necessitam de operaes aritmticas, como CEP, CPF, CGC, etc., onde os caracteres no-numricos so utilizados apenas para formatao. O Delphi suporta trs tipos de strings: ShortString , AnsiString e WideString . - ShortString : string esttica e comprimento mximo de 255 caracteres. mantido por razes de compatibilidade com o Delphi1. - AnsiString : string dinamicamente alocada com um comprimento mximo limitado somente pela memria disponvel. Obs1.: Quando voc declara uma varivel como sendo do tipo String, na realidade voc est declarando uma varivel AnsiString (vide no Help a diretiva de compilao $H). - WideString : string dinamicamente alocada com um comprimento mximo limitado somente pela memria disponvel. Utiliza 16 bits de representao (caracteres UNICODE). A verso 32-bits de OLE utiliza UNICODE para todas as strings.

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

24

Obs2.: Vrias propriedades so do tipo string, como, por exemplo, a propriedade Caption do form ou do componente Label e a propriedade Text do componente Edit Box. 5.4. Variveis J lhe foi dito que para manipular valores no seu programa (que esto armazenados na memria RAM de seu computador), voc precisa declarar variveis de memria, ou simplesmente, variveis, que so os smbolos que permitem a voc manipular um determinado valor de acordo com certas caractersticas. Como voc j estudou tambm alguns dos tipos disponveis no Object Pascal, chegou a hora de se declarar as variveis. Isto pode ser feito na seo de declarao de variveis, logo aps a palavra reservada Var . Por exemplo, abaixo voc v a declarao de 6 variveis: Var A B,C D,E,F G : Integer ; : Real ; : Boolean ; : String ;

A varivel de nome A do tipo inteiro; as variveis B e C so reais; as variveis D, E e F so Boolean (variveis lgicas - s aceitam os valores True e False) e a varivel G string. Voc pode utilizar as estruturas estudadas acima para auxiliar na declarao das variveis. Por exemplo, caso voc deseje declarar uma varivel de nome Taxa que, por um motivo qualquer somente necessite armazenar valores entre 10 e 100, voc faria como: Type Limite = 10 .. 100 ; Var Taxa : Limite ; O que idntico a: Var Taxa : 10 .. 100 ; Assim feito, a varivel Taxa uma varivel ordinal (inteira) que somente armazena valores entre 10 e 100 (vide no Help a diretiva de compilao $R).

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

25

5.5. Operadores Declaradas todas as constantes, tipos e variveis de que voc necessita, precisamos saber agora como manipular esses valores dentro do programa. Na realidade, j utilizamos o operador atribuio ( := ) em exemplos anteriores, quando por exemplo voc atribuiu ao Caption de Label1 a hora retornada pela funo NOW, ou quando voc atribuiu ao Caption de Label1, o contedo da propriedade Text do componente Edit Box. 5.5.1. Operadores Aritmticos 5.5.1.1. Binrios (requerem dois operandos para sua execuo) Operador + * / div mod Operandos Tipo de Resultado inteiro + inteiro inteiro inteiro (ou real) + real real Subtrao inteiro - inteiro inteiro inteiro (ou real) - real real Multiplicao inteiro * inteiro inteiro inteiro (ou real) * inteiro (ou real) real Diviso (real) inteiro / inteiro real inteiro (ou real) / real real Diviso (inteira) inteiro div inteiro inteiro Resto da Diviso (inteira) inteiro mod inteiro inteiro Operao Adio

5.5.1.2. Unrios (requerem um operando apenas para sua execuo) Operador + Operao Identificador de sinal Negativao Operandos + inteiro + real - inteiro - real Tipo de Resultado inteiro real inteiro real

5.5.2. Operadores Bitwise (operao a nvel de bits - bitwise operations) Operador Operao not Negao (unrio) and Lgica "e" or Lgica "ou" xor Lgica "ou-exclusivo" shl Rotao (shift) esquerda shr Rotao (shift) direita Operandos not inteiro inteiro e inteiro inteiro or inteiro inteiro xor inteiro inteiro shl inteiro inteiro shr inteiro Tipo de Resultado inteiro inteiro inteiro inteiro inteiro inteiro

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

26

5.5.3. Operadores Lgicos Operador not and or xor Operao Inverso (unrio) Lgica "e" Lgica "ou" Lgica "ou-exclusivo" Operandos not lgico lgico e lgico lgico or lgico lgico xor lgico Tipo de Resultado lgico lgico lgico lgico

5.5.4. Operador de String Operador + Operao Concatenao Operandos Tipo de Resultado char (ou string) + char (ou string) string

5.5.5. Operadores Relacionais Operador = <> < > <= >= Operao Igual Diferente (no igual) Menor que Maior que Menor que ou igual a Maior que ou igual a Operandos tipo = mesmo tipo tipo <> mesmo tipo tipo < mesmo tipo tipo > mesmo tipo tipo <= mesmo tipo tipo >= mesmo tipo Tipo de Resultado lgico lgico lgico lgico lgico lgico

5.6. Exemplos 10 10.0 10.0 10 10 10 10.0 10 +5 +5 + 5.0 *5 * 5.0 / 5 / 5 div mod resulta resulta resulta resulta resulta resulta resulta 3 3 15 15.0 15.0 50 50.0 2.0 2.0 resulta resulta resulta and or 00110001 00110001

3 1 False resulta resulta

(pois: 1 (pois: 1

10 3 10 3

3 3

) )

- 10 -

not True 11010010 11010010

00010000 11110011

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

27

'Al ' + 'Voc!' resulta '012345678' + '9'

'Al Voc!' resulta '0123456789'

5.7. Execuo Condicional 5.7.1. IF / THEN / ELSE Sintaxe: IF <condio> THEN begin comando11 ; comando12 ; comando1N ; end ELSE begin comando21 ; comando12 ; comando2N ; end ; Isto significa que: se (IF) a condio ( <condio> ) verdadeira (True) ento ( THEN ) todos os comandos "1i" (i =1,2,..,N) entre o primeiro bloco begin / end so executados; seno ( ELSE ) se (IF) a condio ( <condio> ) falsa todos os comandos " 2i" (i =1,2,..,N) entre o segundo bloco begin / end so executados. Obs1.: O bloco de comandos entre o begin e o end pode ser constitudo somente de um nico comando. Neste caso, o uso do begin / end opcional. Obs2.: O uso da clusula ELSE opcional. Caso no seja utilizada e a condio entre o IF e o THEN resulte num valor lgico False, nenhum comando executado. Obs3.: A prtica de se escrever estruturas hierarquicamente inferiores a outras chamada de IDENTAO, e serve apenas para melhorar a visibilidade do seu cdigo-fonte, nada afetando em termos de performance do compilador. Obs4.: Cada linha de comando separada de outra pelo caractere ponto-e-vrgula, conforme mostrado acima. No entanto, no se pode utilizar ponto-e-vrgula antes de um comando ELSE, sob pena de o compilador acusar erro de "statement" (erro na estrutura). Obs5.: Comandos If sucessivos podem ser "aninhados", ou seja, o bloco de comandos que segue o Then pode ser um outro comando If, e assim sucessivamente. Isto se faz necessrio, quando precisamos aps uma primeira filtragem, executar processamentos diferentes. Por exemplo, aps selecionar todos os funcionrios que tm matrcula comeando pelo caractere ' v ' (funcionrios da seo de

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

28

vendas), somente recebero aumento de 10% no salrios os que ganhem menos de 500,00 e de 7.5% os que ganhem mais de 500,00. No exemplo abaixo, atribuiremos o valor 10 varivel A e compararemos o contedo dessa varivel ao valor 10. Como eles so iguais, a varivel B receber o valor True; caso eles fossem diferentes, a varivel C receberia 'So diferentes': Var A : Integer ; B : Boolean ; C : String ; begin A := 10 ; If A = 10 Then { Compara o contedo da varivel A com o valor 10 } B := True Else C := 'So diferentes' ; Obs6.: O texto entre chaves um comentrio do programador, sendo ignorado pelo compilador (no compilado). No exemplo abaixo, construiremos uma calculadora. Comece uma nova aplicao Coloque dois componentes Label no form Altere o Caption do primeiro para Calculadora e o Caption do segundo para = Coloque quatro componentes Edit Box , os alinhe (utilize os pontinhos do form) pelo topo e apague a propriedade Text dos quatro, deixando-as em branco Coloque um boto no form e altere seu Caption para &Operar A aparncia do form deve ser a seguinte:

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

29

Voc dever entrar com um valor numrico inteiro no primeiro Edit Box (Edit1), com um operador aritmtico no segundo Edit Box (Edit2), com outro valor numrico inteiro no terceiro Edit Box (Edit3) e dar um clique no boto, verificando o resultado da operao no quarto Edit Box. Mas antes de executar a nossa aplicao, vamos continuar com a nossa tarefa. Manipule o evento OnClick de Button1 com a linha de comando abaixo: procedure TForm1.Button1Click(Sender: TObject); Var N1, N2 : Integer ; begin N1 := StrToInt (Edit1.Text) ; N2 := StrToInt (Edit3.Text) ; If Edit2.Text = '+' Then { Se o operador for igual a + } Edit4.Text := IntToStr (N1 + N2) {Soma os nmeros} Else {Seno, se no for igual a +} If Edit2.Text = '-' Then { Se for igual a - } Edit4.Text := IntToStr (N1 - N2) {Subtrai} Else {Seno, se no igual a -} If Edit2.Text = '*' Then {Se for igual a *} Edit4.Text := IntToStr (N1 * N2) {multiplica} Else {Seno, se no for igual a *} If Edit2.Text = '/' Then {divide} Edit4.Text := IntToStr (N1 div N2); end; Obs7.: Como N1 uma varivel do tipo inteiro e Text uma propriedade do tipo String, antes de efetuar a atribuio do valor contido em Text varivel N1, precisamos convert-lo de String para Integer ( bvio que a string a ser convertida somente dever conter caracteres numricos). A funo StrToInt converte a string (Str) entre seus parnteses para (To) o valor inteiro (Int) correspondente. A mesma explicao se aplica varivel N2. Processo inverso (IntToStr) efetuado para atribuir o resultado numrico da operao aritmtica entre os dois operandos (N1 e N2) para a propriedade Text de Edit4. Execute a aplicao, digite o valor 10 no primeiro Edit Box, digite o operador de diviso encontrado em mquinas de calcular ( / ) no segundo Edit Box e digite 7 no terceiro Edit Box. D um clique no boto Operar ou tecle Alt-O e veja que aparece o valor 1 no quarto Edit Box (resultante da diviso inteira de 10 por 7). Altere o operador (no segndo Edit Box) para * e clique o boto Operar. Veja que o quarto Edit Box passa agora a conter 70. Apague o contedo do quarto Edit Box e altere o contedo do segundo Edit Box de * para @ e clique o boto Operar. Veja que nada aconteceu. Como a manipulao OnClick do boto Operar efetua a adio se Edit2.Text for igual a '+' , subtrai se Edit2.Text for igual a '-', multiplica se Edit2.Text for igual a '*' e divide (diviso inteira) se Edit2.Text for igual a '/', mas nada diz a respeito (no contm clusula ELSE) caso o operador no seja um desses quatro citados, nada acontece, pois nenhum comando executado.

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

30

Obs8.: bvio que poderamos cercar todas as possibilidades com comandos IF/THEN/ELSE. Mas o programa ficaria por demais complexo, com uma identao que tenderia a ultrapassar o limite do editor de textos do Delphi. Poderia voc me perguntar se obrigatrio utilizar identao. No, no obrigatrio, mas verifique abaixo o mesmo cdigo com e sem identao: Com identao: procedure TForm1.Button1Click(Sender: TObject); Var N1, N2 : Integer ; begin N1 := StrToInt (Edit1.Text) ; N2 := StrToInt (Edit3.Text) ; If Edit2.Text = '+' Then Edit4.Text := IntToStr (N1 + N2) Else If Edit2.Text = '-' Then Edit4.Text := IntToStr (N1 - N2) Else If Edit2.Text = '*' Then Edit4.Text := IntToStr (N1 * N2) Else If Edit2.Text = '/' Then Edit4.Text := IntToStr (N1 div N2); end; Sem identao: procedure TForm1.Button1Click(Sender: TObject); Var N1, N2 : Integer ; begin N1 := StrToInt (Edit1.Text) ; N2 := StrToInt (Edit3.Text) ; If Edit2.Text = '+' Then Edit4.Text := IntToStr (N1 + N2) Else If Edit2.Text = '-' Then Edit4.Text := IntToStr (N1 - N2) Else If Edit2.Text = '*' Then Edit4.Text := IntToStr (N1 * N2) Else If Edit2.Text = '/' Then Edit4.Text := IntToStr (N1 div N2);

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

31

end; E responda qual o cdigo que mais legvel? 5.7.2. CASE / OF Sintaxe: CASE <varivel_ordinal> OF valor1 : comando1 ; valor2 : begin comando21 ; comando22 ; comando2N ; end ; valorN : begin comandoN ; end ELSE begin comandoE1 ; comandoE2 ; comandoEN ; end ; END ; Isto significa que: caso (CASE) o valor da varivel ordinal ( <varivel_ordinal> ) seja igual a ( OF ): valor1 execute o comando1 valor2 execute os comandos entre o bloco begin / end (comando21, comando22, ... ,comando2N) valorN execute o comandoN Caso no seja nenhum dos valores acima (ELSE), execute todos os comandos "Ei" (i =1,2,..,N) entre o ltimo bloco begin / end . Obs1.: O primeiro valor que satisfaa a igualdade proposta (valor este que seja igual varivel ordinal) executado, finalizando-se o comando CASE / OF (END do CASE).

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

32

Obs2.: O uso da clusula ELSE opcional. Caso no seja utilizada e nenhum dos valores de teste seja igual ao da varivel ordinal, nenhum comando executado. Obs3.: Note que o comando CASE / OF possui um comando END; finalizador . Obs4.: Note a IDENTAO aqui utilizada. Obs5.: Voc pode comparar a varivel ordinal com qualquer valor ordinal, ou com qualquer varivel ordinal (cujo tipo seja compatvel, por exemplo, varivel ordinal do tipo Integer e valor - ou outra varivel ordinal - do tipo Byte, desde que os valores mximo e mnimo dos tipo utilizados seja respeitado) Obs6.: Voc tambm pode comparar a varivel ordinal com um conjunto de valores ordinais ou com um limite de valores tambm ordinal. Por exemplo, caso voc queira comparar uma varivel ordinal com os valores 1, 2 , 3 e 57 , faa como abaixo: CASE <varivel_ordinal> OF 1, 2, 3, 57 : comando1 ; Caso essa comparao seja com um limite ininterrupto de valores, como, por exemplo, de 1 a 100, de 1 em 1 (1, 2, 3, 4, 5, 6, 7, ..., 98, 99, 100), utilize os dois pontos ( .. ) para definir um subrange (limite) ordinal, como mostrado abaixo: CASE <varivel_ordinal> OF 1 .. 100 : comando1 ; Obs7.: O bloco de comandos entre o begin e o end pode ser constitudo somente de um nico comando, como nos casos dos valores "valor1" e "valorN". Neste caso, o uso do begin / end opcional (aqui foram utilizados os comandos begin e end em "valorN" apenas para efeito didtico, podendo, como j foi dito, ser retirados). Reescreva o exemplo anterior (da calculadora) com o comando Case: procedure TForm1.Button1Click(Sender: TObject); Var N1, N2 : Integer ; Operador : Char ; begin N1 := StrToInt (Edit1.Text) ; N2 := StrToInt (Edit3.Text) ; Operador := Edit2.Text [1] ; {Atribua varivel Operador, o primeiro caractere da String contida em Edit2.Text} Case Operador Of '+' : Edit4.Text := IntToStr (N1 + N2) ; '-' : Edit4.Text := IntToStr (N1 - N2) ;

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

33

'*' : Edit4.Text := IntToStr (N1 * N2) ; '/' : Edit4.Text := IntToStr (N1 Div N2) ; End ; end; Obs8.: Utilizamos uma varivel do tipo Char porque o tipo String no tipo ordinal. 5.8. Execuo de Repetio 5.8.1. FOR / DO Sintaxe: FOR varivel_ordinal_numrica := valor_inicial TO valor_final DO begin comando1 ; comando2 ; comandoN ; end ; Isto significa que: a varivel ordinal recebe (:= ) um valor (numrico) inicial e, se esse valor for menor ou igual ao valor final, todos os comandos entre o bloco begin / end so executados; ao final dessa primeira execuo, a varivel ordinal incrementada de 1 unidade e, se o seu valor aps o incremento for menor ou igual ao valor final, todos os comandos entre o bloco begin / end so novamente executados; ao final dessa segunda execuo, a varivel ordinal incrementada de 1 unidade e, se o seu valor aps o incremento for menor ou igual ao valor final, todos os comandos entre o bloco begin / end so novamente executados; e assim por diante, at que o valor da varivel ordinal seja maior do que o valor final Obs1.: O bloco de comandos entre o begin e o end pode ser constitudo somente de um nico comando. Neste caso, o uso do begin / end opcional. Obs2.: Se o valor inicial for maior do que o valor final nada executado. Porm, caso voc precise utilizar um decremento ao invs de um incremento, altere o TO por DOWNTO (observe o comentrio no programa do exemplo abaixo). Neste caso o valor inicial deve ser maior do que o valor final para o bloco ser executado. A cada passo, o valor da varivel ordinal decrementado de 1 unidade. Por exemplo, vamos criar uma tabela de converso de centmetros (cm) para polegadas (pol) , sendo: 2,54 cm = 1 pol . Comece uma nova aplicao Coloque no Form, um componente Memo (aba Standard):

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

34

um boto ao Form Manipule o evento OnClick deste boto com o cdigo abaixo:

Adicione

procedure TForm1.Button1Click(Sender: TObject); Var Pol : Integer ; Cm : Extended ; Valor : String ; begin For Pol := 1 To 100 Do {Para decrementar use: For Pol := 100 DownTo 1 Do } begin Cm := 2.54 * Pol ; Valor := IntToStr (Pol ) + ' = ' + FloatToStr ( Cm ) ; Memo1.Lines.Append ( Valor ) ; end ; end; Execute a aplicao, clique o boto e, depois de examinar a tabela de valores convertidos, feche a aplicao. Um componente Memo tem uma propriedade chamada Lines, que contm linhas de strings. Voc pode adicionar strings ao componente Memo em tempo de execuo, atravs do comando Append, como no cdigo acima: Memo1.Lines.Append ( Valor ) ; O comando Append ir adicionar uma string ao final da lista de strings do componente Memo. No caso estudado, temos a concatenao de trs valores: a. A string resultante da converso do valor inteiro contido na varivel Cm b. A string ' = ' (caractere espao, caractere igual, caractere espao) c. A string resultante da converso do valor real (Float) contido na varivel Pol

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

35

Voc pode inicializar a sua aplicao sem a palavra Memo1 da tabela. Para isto, utilize o String List Editor, clicando no boto reticncias da propriedade Lines do componente Memo1 (apague a palavra Memo1 e clique em OK):

5.8.2. Sintaxe: WHILE <condio> DO begin comando1 ; comando2 ; comandoN ; end ;

WHILE / DO

Isto significa que: enquanto (WHILE ) a condio ( <condio> ) for verdadeira faa ( DO ) a execuo de todos os comandos entre o bloco begin / end; ao final dessa primeira execuo, o programa retorna para testar novamente a condio e, se ela resultar em True (continuar verdadeira) , todos os comandos entre o bloco begin / end so novamente executados; e assim por diante, at que a condio seja falsa. Obs1.: O bloco de comandos entre o begin e o end pode ser constitudo somente de um nico comando. Neste caso, o uso do begin / end opcional. Obs2.: Se a condio resultar inicialmente em False (seja uma condio falsa), nenhum comando executado. Obs3.: Apesar do comando Break quebrar a execuo de um loop While / Do (bem como do loop For / Do), uma boa prtica evit-lo, sob pena de voc perder o controle do seu programa. Utilize-o somente em ocasies muito especiais, onde no puder ser evitado, o que difcil de acontecer, pois um comando If / Then aninhado dentro do comando While / Do resolve boa parte dos nossos problemas de execuo indesejada. Por exemplo, vamos refazer a tabela de converso de centmetros (cm) para polegadas (pol) , sendo: 2,54 cm = 1 pol .

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

36

Comece uma nova aplicao Coloque no Form, um componente Memo (aba Standard):

Adicione um boto ao Form OnClick deste boto com o cdigo abaixo:

Manipule evento

procedure TForm1.Button1Click(Sender: TObject); Var Pol : Integer ; Cm : Extended ; Valor : String ; begin Pol := 1 ; While Pol <= 100 Do begin Cm := 2.54 * Pol ; Valor := IntToStr (Pol ) + ' = ' + FloatToStr ( Cm ) ; Memo1.Lines.Append ( Valor ) ; Pol := Pol + 1 ; end ;

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

37

end; Execute a aplicao, clique o boto e, depois de examinar a tabela de valores convertidos, feche a aplicao. Obs4.: Observe que a varivel utilizada como controle ( Pol) inicializada com 1 e, depois da execuo de todos os comandos do loop, a varivel tem seu contedo antigo incrementado de 1, antes que o controle retorne ao teste da condio. Isto se faz necessrio para evitar um "loop infinito", que aquele que no acaba nunca, devido condio sempre resultar verdadeira. Obs5.: O comando While / Do no exige que a condio seja ordinal (nem muito menos numrica). Qualquer condio que resulte em um valor True (verdadeiro) ou False (falso) serve como condio para este comando. Assim sendo, examine o trecho de programa abaixo:
Var Op : Char ; begin Op := 'S' ; While Op = 'S' Do {Enquanto a varivel Op for igual a 'S' faa} begin {Incio do bloco} If MessageDlg ('Deseja Continuar?',mtInformation, [mbYes,mbNo],0) = mrNo Then Op := 'N' end ; {Fim do bloco} end;

A seguinte pergunta feita na execuo da condio: Op igual a 'S'. Isto verdadeiro (True) ou falso (False)? Se for True executa o bloco; se for False, pula todo o bloco e executa o(s) comando(s) aps o end do bloco . 5.8.3. REPEAT / UNTIL Sintaxe: REPEAT comando1 ; comando2 ; comandoN ; UNTIL <condio> ; Isto significa que: repita (REPEAT) todos os comandos que seguem (entre o REPEAT e o UNTIL) at (UNTIL) que a condio ( <condio> ) seja verdadeira. Obs1.: Como o bloco de comandos inicia com o comando REPEAT e termina com o comando UNTIL, se faz desnecessrio utilizar os comandos begin e end.

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

38

Obs2.: Todos os comandos sero executados pelo menos uma vez, mesmo que a condio resulte inicialmente em True (seja uma condio verdadeira). Obs3.: Observe que a lgica de teste da condio para o comando Repeat / Until contrria logica da condio para o comando While / Do. Obs4.: Apesar do comando Break quebrar a execuo de um loop Repeat / Until (bem como do loop For / Do ou do loop While / Do), uma boa prtica evit-lo, sob pena de voc perder o controle do seu programa. Utilize-o somente em ocasies muito especiais, onde no puder ser evitado, o que difcil de acontecer, pois um comando If / Then aninhado dentro do comando Repeat / Until resolve boa parte dos nossos problemas de execuo indesejada. Por exemplo, vamos refazer a tabela de converso de centmetros (cm) para polegadas (pol) , sendo: 2,54 cm = 1 pol . Comece uma nova aplicao Coloque no Form, um componente Memo (aba Standard):

Adicione um boto ao Form

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

39

Manipule o evento OnClick deste boto com o cdigo abaixo: procedure TForm1.Button1Click(Sender: TObject); Var Pol : Integer ; Cm : Extended ; Valor : String ; begin Pol := 1 ; Repeat Cm := 2.54 * Pol ; Valor := IntToStr (Pol ) + ' = ' + FloatToStr ( Cm ) ; Memo1.Lines.Append ( Valor ) ; Pol := Pol + 1 ; Until Pol > 100 ; end; Execute a aplicao, clique o boto e, depois de examinar a tabela de valores convertidos, feche a aplicao. Obs5.: Observe que a varivel utilizada como controle inicializada com 1 e, depois da execuo de todos os comandos do loop, a varivel tem seu contedo antigo incrementado de 1, antes que o controle v ao teste da condio. Isto se faz necessrio para evitar um "loop infinito", que aquele que no acaba nunca, devido condio sempre resultar falsa (neste caso). Obs6.: O comando Repeat / Until no exige que a condio seja ordinal (nem muito menos numrica). Qualquer condio que resulte em um valor True (verdadeiro) ou False (falso) serve como condio para este comando. Assim sendo, examine o trecho de programa abaixo:
Var Op : Char ; begin Op := 'S' ; Repeat { repita todos os comandos abaixo} If MessageDlg ('Deseja Continuar?',mtInformation, [mbYes,mbNo],0) = mrNo Then Op := 'N' Until Op = 'N' {at que Op seja igual a 'N'} end;

A seguinte pergunta feita na execuo da condio: Op igual a 'N'. Isto verdadeiro (True) ou falso (False)? Se for True finaliza a repetio; se for False, retorna ao comando Repeat e reinicia a execuo dos comandos. 5.9. Componente StringGrid

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

40

Comece uma nova aplicao Coloque um StringGrid (aba Additional) e um boto (aba Standard) no Form

Altere (no Object Inspector) as propriedades abaixo: Boto (Button1): Caption : Contador StringGrid (StringGrid1): Name : sgTab ColCount : 6 RowCount : 6 Reposicione e redimensione SgTab (o novo nome de StrinGrid1) de tal maneira que todas as clulas fiquem visveis na tela (no aparea barra de rolamento alguma) Obs1.: Para dar ajustes finos, voc pode trabalhar com as setas de posicionamento do cursor (no seu teclado) e as teclas Shift e Ctrl. Mantendo a tecla Shift pressionada e pressionando uma das setas, voc poder redimensionar o seu componente. Mantendo a tecla Ctrl pressionada e pressionando uma das setas, voc poder reposicionar o seu componente.

Manipule o evento OnClick de Button1 com o seguinte cdigo:

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

41

procedure TForm1.Button1Click(Sender: TObject); Var Col : Byte ; begin For Col := 1 To 5 Do sgTab.Cells [Col,1] := IntToStr (Col) ; end; Obs2.: Observe a propriedade Cells de sgTab (o novo nome do componente StringGrid). Esta propriedade possui a string contida na clula cuja coluna no grid o primeiro parmetro e cuja linha no grid o segundo parmetro. Isto significa dizer que, nem todas as propriedades de um componente vo estar localizadas o Object Inspector, necessitando-se, em alguns casos, contar com a ajuda do Help online do Delphi. Por exemplo, selecione sgTab (d um clique no StringGrid) e pressione a tecla F1. Aparece o Help do Delphi:

D um clique em Properties e veja as propriedades deste componente. Voc pode repetir este processo com qualquer componente do Delphi. Execute a aplicao e d um clique no boto. Obs3.: A primeira clula de um StringGrid tem coordenadas [0,0] ou seja a primeira clula Cells [0,0]. Feche o aplicativo e altere a manipulao OnClick acima para:

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

42

procedure TForm1.Button1Click(Sender: TObject); Var Lin, Col : Byte ; begin sgTab.Cells [0,0] := 'Grade de Strings' ; sgTab.Cells [1,0] := 'Coluna 1' ; sgTab.Cells [2,0] := 'Coluna 2' ; sgTab.Cells [3,0] := 'Coluna 3' ; sgTab.Cells [4,0] := 'Coluna 4' ; sgTab.Cells [5,0] := 'Coluna 5' ; sgTab.Cells [0,1] := 'Linha 1' ; sgTab.Cells [0,2] := ' Linha 2' ; sgTab.Cells [0,3] := ' Linha 3' ; sgTab.Cells [0,4] := ' Linha 4' ; sgTab.Cells [0,5] := ' Linha 5' ; For Lin := 1 To 5 Do For Col := 1 To 5 Do sgTab.Cells [Col,Lin] := IntToStr (5 * (Lin -1) + Col) ; end; Execute novamente o aplicativo. D um clique no boto e feche o aplicativo. Obs4.: Preste ateno nos comandos For / Do aninhados. Aqui, para cada valor da varivel Col, ser executada a linha de comando sgTab.Cells [Col,Lin] := IntToStr (5 * (Lin -1) + Col) ; como j foi explicado anteriormente. Porm, o For / Do com a varivel Col repetida 5 vezes devido linha de comando For Lin := 1 To 5 Do mais acima. Isto significa dizer que, a linha de comando envolvendo sgTab ir ser repetida por 25 vezes (5 vezes 5). 5.10. Clusula: WITH / DO Sintaxe: WITH <nome_do_objeto> DO begin propriedade1 := valor1 ; propriedade2 := valor2 ; propriedadeN := valorN ; end ; Assim, as propriedades entre o begin e o end pertencem ao objeto <nome_do_objeto> (entre os comandos With e Do). Por exemplo, reescreva a manipulao OnClick acima com o cdigo abaixo:

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

43

procedure TForm1.Button1Click(Sender: TObject); Var Lin, Col : Byte ; begin With sgTab Do begin Cells [0,0] := 'Grade de Strings' ; Cells [1,0] := 'Coluna 1' ; Cells [2,0] := 'Coluna 2' ; Cells [3,0] := 'Coluna 3' ; Cells [4,0] := 'Coluna 4' ; Cells [5,0] := 'Coluna 5' ; Cells [0,1] := 'Linha 1' ; Cells [0,2] := ' Linha 2' ; Cells [0,3] := ' Linha 3' ; Cells [0,4] := ' Linha 4' ; Cells [0,5] := ' Linha 5' ; For Lin := 1 To 5 Do For Col := 1 To 5 Do Cells [Col,Lin] := IntToStr ( 5 * (Lin -1) + Col) ; end ; end; Aproveite a aplicao acima e adicione um componente Label no Form. Manipule o evento OnClick de sgTab, com o seguinte cdigo: procedure TForm1.sgTabClick(Sender: TObject); begin Label1.Caption := IntToStr (sgTab.Col) ; end; Execute o aplicativo. Aconteceu um erro de compilao. Sabe o por qu disto? V ao form e d um clique sobre SgTab, e pressione em seguida a tecla F1. Aparecendo o Help online do Delphi, d um clique em Properties (em verde) e verifique que um componente do tipo TStringGrid tem uma propriedade chamada Col. Como o begin / end do With / Do engloba o For / Do que utiliza a varivel Col, h um conflito, pois varivel e propriedade tm o mesmo nome, e isto no pode ocorrer. Assim sendo na manipulao OnClick do boto , renomeie a varivel de Col para Coluna e voc eliminar o erro. Execute o aplicativo novamente e v dando cliques em clulas diferentes de sgTab. Veja que o Caption de Label1 vai sendo alterado toda a vez que voc clica em uma clula no fixa (em cor cinza). Obs.: FixedCols e FixedRows contm a quantidade de clulas fixas de um StringGrid.

5.11. Janela de Senha e a propriedade ModalResult

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

44

Comece uma nova aplicao Clique em File - New

Ao surgir a janela de Templates (New Items) clique na aba Dialogs e em

seguida selecione uma PasswordDlg (Password Dialog) Altere o Caption de Label1 de Enter password: para Digite sua senha Veja no Object Inspector que a propriedade PasswordChar do componente Password (TEdit) o caractere *, ou seja, quando voc digitar algo no Edit Box de Password, ir aparecer um * ao invs da digitao real

Manipule o evento OnClick do boto OkBtn com o cdigo abaixo:

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

45

procedure TPasswordDlg.OKBtnClick(Sender: TObject); begin Form1.Label1.Caption := Password.Text ; end; Obs1.: Note que o componente Label (cujo Caption ser alterado) encontra-se no Form1 e no em PasswordDlg. Retorne ao Form1 e adicione um Label e um Boto Manipule o evento OnClick do boto Button1 com o cdigo abaixo: procedure TForm1.Button1Click(Sender: TObject); begin PasswordDlg.ShowModal ; end; Execute a aplicao e clique em Sim nas duas vezes que o compilador alertlo sobre a colocao dos cabealhos das Unit1 e Unit2. Execute a aplicao novamente. Clique em Button1, digite algo no Edit Box da janela de senha, d um clique no boto OKBtn e veja que o Caption de Label1 do Form1 alterado. Feche o aplicativo. Obs2.: Voc tem colocado vrios botes no Form, sem que um clique num deles feche a janela, a no ser com o uso do comando Close. Por que, ento, a janela de senha fechada com um clique num dos botes: OK ou Cancel? Quando voc chama uma janela de forma Modal, voc pode utilizar em conjunto a propriedade ModalResult do boto:

Aqui, os botes OkBtn e CancelBtn possuem a propriedade ModalResult igual a mrOk (modal result Ok) e mrCancel (modal result Cancel), respectivamente.

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

46

Uma vez que o boto clicado, transfere ao Form um resultado modal de fechamento, que pode ser um dos tipos abaixo: mrNone mrOk mrCancel mrAbort mrRetry mrIgnore mrYes mrNo mrAll mrNoToAll mrYesToAll

A razo ento de anteriormente voc no ter fechado o Form com um clique de boto, porque ou o boto possuia um ModalResult igual a mrNone ou porque o Form no foi chamado de maneira Modal. Adicione outro componente Label a Form1 Manipule o evento OnClose de PasswordDlg com o seguinte cdigo: procedure TPasswordDlg.FormClose(Sender: TObject; var Action: CloseAction); begin If PasswordDlg.ModalResult = mrOk Then Form1.Label2.Caption := 'mrOk' ; If PasswordDlg.ModalResult = mrCancel Then Form1.Label2.Caption := 'mrCancel' end; Execute o aplicativo, clique o boto, digite algo no Edit Box e d um clique no boto OK. Veja que o Caption de Label2 alterado para mrOK, que o modo de fechamento da janela (ModalResult) da janela PasswordDlg . Clique o boto novamente, e depois d um clique no boto Cancel. Verifique agora que Label1 tem seu Caption alterado para mrCancel. Feche o aplicativo. Obs3.: Note que a propriedade ModalResult do Form no aparece no Object Inspector, porque esta propriedade intrnseca do seu fechamento e s alterada em tempo de execuo (run-time), no estando disponvel em tempo de design. Obs4.: Uma janela de senha nada mais do que um Form normal com um Label, um Edit Box (com PasswordChar diferente de #0 = caractere nulo = ASCII 0) e dois botes (com a propriedade ModalResult de cada um alterada de mrNone para um dos tipos explicitados acima). Ao fechar a janela de senha, voc pode permitir o acesso do usurio (caso a senha dele seja vlida) ou mesmo fechar o aplicativo, caso o usurio clique o boto de cancelar.

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

47

5.12. Janela de Senha sem usar o Template Vamos construir a mesma janela de senha do exerccio anterior, utilizando os componentes direto do Object Inspector. Comece uma nova aplicao Adicione Form1 um Label e um Button Manipule o evento OnClick do boto com: procedure TForm1.Button1Click(Sender: TObject); begin PasswordDlg.ShowModal ; end; Adicione ao projeto outro Form Redimensione Form2 de modo que ele ocupe cerca de 20% da rea de Form1, como mostrado abaixo:

Adicione a Form2, um Label, um Edit Box e um Botton Altere as propriedades abaixo: Form2 - Name: PasswordDlg - Caption: Password Dialog Label1

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

48

Caption: Digite sua senha

Edit1 - Name: Password - PasswordChar: @ - apague a propriedade Text (deixe-a em branco) Button1 - Name: OKBtn - Caption: OKBtn - ModalResult: mrOK

Manipule o evento OnClick de OKBtn com: procedure TPasswordDlg.OKBtnClick(Sender: TObject); begin Form1.Label1.Caption := Password.Text ; end; Execute a aplicao. Clique em Yes para inserir Uses Unit2 ; no cabealho da Unit1. Execute novamente aplicao e clique o boto. Aps digitar a sua senha (observe que voc s consegue ver o caractere @), d um clique em OKBtn. Form2 ento fechado e Form1 torna a ficar ativo. Feche a aplicao.

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

49

5.13. Botes de Bitmap e SpeedButtons Comece uma nova aplicao Adicione ao Form um SpeedButton (aba Additional)

Clique no boto reticncias da propriedade Glyph e carregue uma imagem de bitmap (da mesma maneira como voc j fez com o componente Image) Manipule o evento OnClick com: procedure TForm1.SpeedButton1Click(Sender: TObject); begin Form2.ShowModal ; end; Adicione um segundo Form ao projeto

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

50

Agora, adicione a Form2, um BitBtn

para bkOk (bitbtn kind Ok)

Altere a sua propriedade Kind

Obs1.: Como voc deve ter observado, esses dois botes tm em comum, alm da capacidade de conter um Caption, conter tambm uma "picture", uma imagem que tenha algum significado til para o contexto do boto, como os botes de atalho que voc v no menu do Word, entre tantos outros aplicativos. Obs2.: A propriedade Kind de BitBtn j seleciona uma imagem padro para o tipo escolhido. Porm, caso voc deseje, clicando no boto reticncias da propriedade Glyph, voc pode alterar este bitmap por outro mais conveniente. Obs3.: Observe que SpeedButton no contm propriedade ModalResult, no podendo fechar um Form, a no ser que voc na manipulao de um dos eventos deste boto, digite o comando Close. Execute o aplicativo e d um clique em SpeedButton1 Aparecendo o Form2, d um clique em BitBtn1 Feche Form1 para retornar ao Delphi Altere a propriedade Flat de SpeedButton1 de False para True Execute o aplicativo Passe com o cursor do mouse sobre SpeedButton1 e veja a aparncia idntica ao Internet Explorer Feche tudo e retorne ao Delphi Adicione mais 2 SpeedButton a Form2 Altere a propriedade GroupIndex de todos os SpeedButton para 1 (ou qualquer valor diferente de 0 ) Altere a propriedade Down do 1 SpeedButton para True (ele fica "abaixado") Execute a aplicao. Clique no 2 SpeedButton e depois no 3 SpeedButton. Veja que a cada clique num deles, o outro do mesmo grupo que estava "abaixado" "levantado". Feche o aplicativo e retorne ao Delphi.

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

51

5.14. Menus Comece um novo projeto Adicione 2 Botes ao Form Adicione um componente MainMenu ao Form

D um duplo clique em MainMenu1 ou ento d um clique no boto reticncias da sua propriedade Items (voc ter acesso ao Menu Designer)

Obs1.: Vamos denominar cada palavra na horizontal como "Menu" e cada palavra na vertical como "Item de Menu". Por exemplo, no Delphi voc tem no Menu File o Item de Menu New Application .

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

52

Observe que j h um menu (em branco) no Menu Designer:

menu para Boto&1 Pressione a tecla Enter. Observe o nome do componente: Boto11

Altere o Caption do

Obs2.: O Caption Boto1 mas o nome (propriedade Name) Boto11, pois o Delphi no reconhece, como constituinte do nome de um componente, caracteres acentuados. Da decorre a ausncia do "" no nome do Menu. A razo do "11" porque o Delphi coloca um nmero de contagem em cada nome de menu. Como o nome Boto1, o Delphi o renomeia para Boto11. Se tivesse outro Boto1, seu nome seria Boto12. D um clique no menu ao lado e altere seu caption para Boto&2 Pressione a tecla Enter D um clique no menu ao lado e altere seu Caption para Sai&r Obs3.: Caso voc deseje retirar algum Menu do Menu Designer, basta dar um clique nele e pressionar a tecla Del (ou Delete). D um clique no Menu Boto11 Aparece ento um espao para voc criar Itens de Menu D um clique no primeiro item e altere seu Caption para Visvel Pressione a tecla Enter D um clique no item abaixo do item de menu Visvel1 Altere seu Caption para No-Visvel

Obs4.: O nome do Menu ou do Item de Menu, por enquanto, no um ponto crtico da nossa aplicao, pois o que nos interessa a manipulao do evento OnClick dos mesmos.

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

53

Obs5.: D um clique com o boto direito do mouse no Menu Designer (na rea cinza) e voc poder carregar menus j prontos ou salvar o seu menu no Menu Template. O seu Menu deve estar com a seguinte aparncia:

Manipule o evento OnClick de cada um dos itens de menu (janela vertical) de Boto11 com os cdigos abaixo (respectivos a cada item): procedure TForm1.Visvel1Click(Sender: TObject); begin Button1.Visible := True ; end; procedure TForm1.NoVisvel1Click(Sender: TObject); begin Button1.Visible := False ; end;

Manipule o evento OnClick de Boto21 com: procedure TForm1.Boto21Click(Sender: TObject); begin If Button2.Left < 50 Then Button2.Left := 100 Else Button2.Left := 10 ; end; Por ltimo, manipule o evento OnClick Do menu Sair1 com: procedure TForm1.Sair1Click(Sender: TObject); begin Close ;

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

54

end; Execute a aplicao e experimente o seu menu. Feche-o e retorne ao Delphi. D um clique duplo no componente MainMenu1 e, no Menu Designer, d um clique no Item Visvel1 (Item de Menu cujo Caption Visvel). Pressione a tecla Ins (ou Insert). Digite o caractere hfen ( - ) no Caption do novo Item (digite apenas um caractere hfen) e pressione a tecla Enter. Voc acaba de criar uma diviso. Pressione novamente a tecla Ins (ou Insert) e Altere o Caption para Estado. Pressione a tecla Enter. D um clique no Item Estado1. Mantenha a tecla Ctrl pressionada e d um toque na tecla seta direita ( ) do seu teclado. Libere as teclas. Aparece um Sub-item de Menu. D um clique no Sub-item e altere o seu Caption para Habilitado. Pressione a tecla Enter. D um toque no Sub-item abaixo de Habilitado1 e altere o seu Caption para Desabilitado. Manipule cada evento OnClick desses Sub-itens de Menu com os cdigos: procedure TForm1.Habilitado1Click(Sender: TObject); begin Button1.Enabled := True ; end; procedure TForm1.Desabilitado1Click(Sender: TObject); begin Button1.Enabled := False ; end; Execute o aplicativo e teste seu novo Menu. Feche o aplicativo e retorne ao Delphi. D um clique no Item Visvel e, em seguida, selecione a tecla de atalho (ShortCut) Ctrl-V para este item:

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

55

A figura acima mostra o Item j associado a tecla de atalho Ctrl-V.

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

56

6. Procedimentos e Funes de Usurio Um projeto constitudo de units, que por sua vez so divididas em pequenos trechos de programa, aos quais chamamos genericamente de sub-programas ou subrotinas. s vezes, digitamos trechos de cdigo-fonte idntico em vrias manipulaes de evento, simplesmente porque sua execuo num determinado momento da manipulao necessria. Se tivermos 1000 linhas de cdigo em digamos 10 manipulaes de evento veremos que algumas manipulaes acabam tendo 1 ou mais trechos repetidos. Ento, para que no seja necessrio reescrever vrias vezes um determinado cdigo que esteja repetido em vrios trechos do programa, implementamos uma subrotina no programa e damos-lhe um nome. Toda vez que for necessria a execuo das linhas de comando l contidas, simplesmente digitamos o nome da sub-rotina em questo. A isto damos o nome: invocar a sub-rotina. Essas sub-rotinas podem ser divididas em duas classes principais: - procedimento : executa as linhas de comando e retorna ao ponto de chamada - funo : executa as linhas de comando e retorna ao ponto de chamada com um "valor de retorno", que deve ser atribudo a uma varivel ou utilizado em uma condio IF/THEN, WHILE/DO, REPEAT/UNTIL ou outro comando que permita esta utilizao. Vamos exemplificar o uso de procedures: Comece uma nova aplicao Coloque um Boto e um Edit Box em Form1 Manipule o evento do boto com: procedure TForm1.Button1Click(Sender: TObject); begin Close ; end; Manipule o evento OnActivate de Form1 com: procedure TForm1.FormActivate(Sender: TObject); begin Edit1.SetFocus ; end; Execute a aplicao. Verifique que ao ser ativado, a aplicao transfere o foco (componente ativo) para Edit1, atravs da procedure SetFocus. Alm disso, quando voc clica o boto, a procedure Close fecha o aplicativo simplesmente. Voc no precisa reescrever todo o cdigo-fonte referente a essas rotinas, porque basta digitar seus nomes para "invoc-las". Feche o aplicativo (clique o boto).

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

57

Vamos exemplificar o uso de functions: Comece uma nova aplicao Coloque um Boto e dois Edit Box em Form1 Manipule o evento do boto com: procedure TForm1.Button1Click(Sender: TObject); Var A, B : Extended ; begin A := StrToFloat ( Edit1.Text ) ; B := SQRT ( A ) ; Edit2.Text := FloatToStr (B ) ; end; Execute a aplicao. Digite um nmero qualquer em Edit1 e clique o boto. Veja surgir em Edit2 a raiz quadrada ( SQuare (RooT ) do nmero por voc digitado. Feche a aplicao. O que voc fez foi utilizar uma funo prdefinida pelo Delphi que a funo SQRT, que "retorna" ao ponto chamador (a linha de comando onde aconteceu a chamada funo) com um valor de retorno (neste caso, a raiz quadrada do valor contido em Edit1.Text). Voc utilizou tambm as funes de converso de string para real, pois A e B so variveis Extended e Text uma propriedade String. Assim, StrToFloat retorna ao ponto de chamada com um valor em ponto flutuante (Float = contm casas decimais e ponto separador; ponto separador e no vrgula, pois a notao utilizada pelo Delphi a notao americana) resultante da converso da string entre parnteses. Este valor atribudo ento varivel A. Da mesma forma, no poderamos atribuir um valor Extended propriedade Text de Edit2. Por isso, voc utilizou a funo FloatToStr que retorna ao ponto de chamada com uma string contendo os dgitos numricos, o ponto decimal e o sinal (se for nmero negativo) do valor em ponto flutuante entre parnteses. Essas sub-rotinas so pr-definidas pelo Delphi e voc pode utiliz-las vontade. Bem como, voc tambm pode definir suas sub-rotinas, com caractersticas prprias, utilizando, dentro delas, as sub-rotinas do Delphi. A utilizao de uma sub-rotina nem sempre para evitar cdigo repetido, mas tambm para organizar melhor o cdigo-fonte, permitindo a reutilizao de um mesmo cdigo em vrias partes diferentes de um programa. Vamos desenvolver uma aplicao cujo form contenha cinco edit box. Voc ter que digitar um valor numrico no primeiro edit box, um outro valor numrico no segundo edit box, uma operao aritmtica no terceiro edit box e um valor numrico no quarto edit box. H, porm, uma condio: o segundo valor numrico dever ser menor do que o primeiro valor numrico, caso contrrio, os edit box devero ter seus contedos apagados, recomeando a entrada de dados do incio. Caso a condio acima seja satisfeita, um clique no boto dever calcular o fatorial da subtrao dos dois primeiros nmeros, esse resultado dever ser operado aritmeticamente com o terceiro valor numrico, cujo operador encontra-se no terceiro edit box, e o resultado final dever mostrado no quinto edit box.

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

58

Por exemplo, caso tenhamos a seguinte situao:

10

Ao clique do boto, teremos: 10 - 6 = 4 4! = 4 x 3 x 2 x 1 = 24 24 / 2 = 12 (fatorial de 4 igual a 24)

O que resultaria em (resultado no quinto edit box): 10 6 / 2 12

Obs1.: Lembremos que s existe fatorial de nmero inteiro positivo . Obs2.: Por definio, o fatorial de zero igual a um: 0! = 1 . Agora, se voc digitar o valor zero para o terceiro edit box e pedir a sua diviso, tambm acontece um erro (erro de diviso por zero), e nesse caso, precisaramos tambm recomear a entrada de dados, apagando todos os edit box ( obvio que s precisaramos digitar um valor no nulo no quarto edit box, mas finja que isto necessrio). Comece uma nova aplicao Coloque cinco Edit Box e um Boto no Form:

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

59

Apague a propriedade Text dos cinco edit box. Manipule os eventos abaixo: OnClick de Edit3: procedure TForm1.Edit3Click(Sender: TObject); Var A, B : Integer ; begin A := StrToInt (Edit1.Text) ; B := StrToInt (Edit2.Text) ;

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

60

If A < B Then begin Edit1.Clear ; Edit2.Clear ; Edit3.Clear ; Edit4.Clear ; Edit5.Clear ; Edit1.SetFocus ; end ; end;

{D o foco a Edit1: coloca o cursor em Edit1}

OnClick de Edit4: procedure TForm1.Edit4Click(Sender: TObject); Var A, B : Integer ; begin A := StrToInt (Edit1.Text) ; B := StrToInt (Edit2.Text) ; If A < B Then begin Edit1.Clear ; Edit2.Clear ; Edit3.Clear ; Edit4.Clear ; Edit5.Clear ; Edit1.SetFocus ; end ; end;

OnClick de Button1:

procedure TForm1.Button1Click(Sender: TObject); Var A, B, C, Fat : Integer ; begin A := StrToInt (Edit1.Text) ; B := StrToInt (Edit2.Text) ; If A > B Then begin Fat := 1 ; For C := (A - B) DOWNTO 1 Do

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

61

Fat := Fat * C ; {O novo valor de Fat o seu valor antigo vezes C} Case Edit3.Text [1] Of {Edit3.Text [1] = caractere na posio 1 de Edit3} '+' : C := Fat + StrToInt (Edit4.Text) ; '-' : C := Fat - StrToInt (Edit4.Text) ; '*' : C := Fat * StrToInt (Edit4.Text) ; '/' : C := Fat Div StrToInt (Edit4.Text) ; End ; Edit5.Text := IntToStr (C) ; end Else begin Edit1.Clear ; Edit2.Clear ; Edit3.Clear ; Edit4.Clear ; Edit5.Clear ; Edit1.SetFocus ; end ; end; Execute a aplicao e digite a seqncia abaixo: 1. 2. 3. 4. Edit1: Edit2: Edit3: Edit4: 10 6 / 2

Clique o boto. Veja o resultado ( 12 ) em Edit5. Digite agora a seqncia: 1. Edit1: 2. Edit2: 6 10

Verifique que, ao clicar em Edit3, todos os edit box so apagados (Clear) e o controle retorna a Edit1. Feche o aplicativo e retorne ao Delphi. Vamos analisar o cdigo acima. a. O trecho: A := StrToInt (Edit1.Text) ; B := StrToInt (Edit2.Text) ; repete-se por trs vezes (uma em cada manipulao de evento). b. O trecho: Edit1.Clear ;

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

62

Edit2.Clear ; Edit3.Clear ; Edit4.Clear ; Edit5.Clear ; Edit1.SetFocus ; repete-se tambm por trs vezes (uma em cada manipulao de evento). Isto significa dizer que: qualquer alterao a ser feita em uma das linhas de comando, demandar no mnimo trs alteraes no cdigo. Por exemplo, se o foco a partir de agora passar para Edit2 em vez de Edit1, teremos que refazer as trs partes do cdigo-fonte. E se quisermos processar o cdigo da manipulao Onclick de Button1 no click de Edit4, teremos que reescrever o cdigo desta manipulao. Mas eu posso copiar e colar com Ctrl-C e Ctrl-V, dir voc. Realmente voc pode, mas toda a vez que voc altera de alguma maneira o seu cdigo, seja digitando, seja copiando/colando, erros podem ser introduzidos no cdigo-fonte, sem que voc consiga descobrir onde est esse erro (ou erros). Porm, caso voc tenha uma estrutura que lhe fornea o cdigo repetido, e o execute a cada chamada, uma modificao no cdigo da estrutura no nosso caso, diminui em 67% a introduo de bugs (erros), pois s haver uma modificao, e no trs modificaes, como no cdigo apresentado. Para isso, vamos agregar o cdigo que utiliza o comando Clear dos edit box repetido numa procedure, cuja sintaxe : procedure Nome_da_procedure ; begin end; Muito parecido com o cabealho de uma manipulao de evento. E o cdigo que obtm o primeiro caractere da string contida em Edit3.Text ir para uma function, cuja sintaxe geral a seguinte: function Nome_da_function : Tipo_da_function ; begin end; Assim sendo, altere o cdigo anterior adicionando o cdigo que segue abaixo (preste ateno aos trechos em negrito): implementation {$R *.DFM} procedure Limpa ; begin

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

63

Form1.Edit1.Clear ; Form1.Edit2.Clear ; Form1.Edit3.Clear ; Form1.Edit4.Clear ; Form1.Edit5.Clear ; Form1.Edit1.SetFocus ; end ;

function Obtem_Operador : Char ; begin Result := Form1.Edit3.Text [1] ; end ;

procedure TForm1.Edit3Click(Sender: TObject); Var A, B : Integer ; begin A := StrToInt (Edit1.Text) ; B := StrToInt (Edit2.Text) ; If A < B Then Limpa ; end; procedure TForm1.Edit4Click(Sender: TObject); Var A, B : Integer ; begin A := StrToInt (Edit1.Text) ; B := StrToInt (Edit2.Text) ; If A < B Then Limpa ; end; procedure TForm1.Button1Click(Sender: TObject); Var A, B, C, Fat : Integer ; begin A := StrToInt (Edit1.Text) ; B := StrToInt (Edit2.Text) ; If A > B Then begin Fat := 1 ; For C := (A - B) DOWNTO 1 Do Fat := Fat * C ; Case Obtem_Operador Of

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

64

'+' : C := Fat + StrToInt (Edit4.Text) ; '-' : C := Fat - StrToInt (Edit4.Text) ; '*' : C := Fat * StrToInt (Edit4.Text) ; '/' : C := Fat Div StrToInt (Edit4.Text) ; End ; Edit5.Text := IntToStr (C) ; end Else Limpa ; end; end. Execute a aplicao e repita as entradas (10 , 6 , / e 2) e verifique que o programa processa o problema da mesma maneira. Feche a aplicao e retorne ao Delphi. Mas por que voc no "enxugou" a aplicao poupando a digitao das linhas de comando IntToStr e StrToInt e poupou a linha que "pega" o primeiro caractere de Edit3.Text? Bom, tudo isto se resume em estilo de cada programador. Ento, se voc gosta de empanturrar o seu programa com procedures e functions, sinta-se vontade. Mas no v abusar, pois voc tem sempre que pensar: Se eu colocar este ou aquele trecho em uma sub-rotina estarei simplificando o meu cdigo? Ser que eu pouparei digitao? Ser que o cdigo ficar um pouco mais complicado, mas se acontecer um erro, eu o acharei mais facilmente? So todas perguntas, em determinados momentos, difceis de responder. Vamos conversar mais sobre procedures e functions.

6.1. Procedimentos de Usurio At agora voc utilizou procedures nas manipulaes de evento, mas essas procedures so "escritas" pelo Delphi, no por voc. As procedures que voc escreve so comumente chamadas de: procedures de usurio. Uma procedure pode conter parmetros, que so valores e/ou variveis que voc envia para ser processada na rotina local procedure. Por exemplo, qualquer manipulao de evento contm o parmetro Sender, que uma varivel que indica o objeto que est sofrendo o evento naquele momento. A sintaxe geral de uma procedure a seguinte: procedure Nome_da_procedure (p1 : tipo1 ; p2 , p3 : tipo2 ; Var p3 : tipo3 ) ;

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

65

Const Declarao das constantes Type Definio de tipos Var Declarao das variveis begin comandos da procedure end ; Assim, quando a procedure Nome_da_procedure for invocada, dever conter entre parnteses quatro variveis de tipos iguais a: tipo1, tipo2, tipo2 e tipo3, nesta ordem. Isso significa que voc deseja processar os comandos da procedure com determinados valores especficos e, os parmetros serviro de variveis locais procedure, o que significa que s sero visveis dentro da procedure (somente existiro enquanto a procedure estiver sendo executada, sendo destrudas ao trmino da procedure). Voc deve ter observado que: - a declarao dos parmetros idntica declarao das variveis: nome_da_varivel : tipo - podemos declarar parmetros de tipos diferentes: s separ-los por ponto-evrgula - podemos declarar mais de um parmetro do mesmo tipo: s separ-los por vrgula - o ltimo parmetro tem a palavra reservada Var antes de seu nome: isto chamado passagem de parmetro por referncia (os trs primeiros so passagem de parmetros por valor). Isto significa que, qualquer alterao no contedo do parmetro durante a execuo da procedure, altera o contedo da varivel que foi passada por referncia procedure Vamos fazer uma modificao no cdigo anterior para exemplificar o uso de procedures. A modificao que ser feita, visa passar uma string que servir de texto janela de mensagem ShowMessage indicando o tipo de erro acontecido. Como ser passada uma string, a varivel parmetro que receber a string tambm deve ser do tipo string. implementation {$R *.DFM} procedure Limpa ( Mensagem : String) ; begin Form1.Edit1.Clear ; Form1.Edit2.Clear ; Form1.Edit3.Clear ; Form1.Edit4.Clear ; Form1.Edit5.Clear ; Form1.Edit1.SetFocus ;

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

66

ShowMessage (Mensagem) ; end ; function Obtem_Operador : Char ; begin Result := Form1.Edit3.Text [1] ; end ; procedure TForm1.Edit3Click(Sender: TObject); Var A, B : Integer ; begin A := StrToInt (Edit1.Text) ; B := StrToInt (Edit2.Text) ; If A < B Then Limpa ( 'Edit1 no pode ser menor do que Edit2' ) ; end; procedure TForm1.Edit4Click(Sender: TObject); Var A, B : Integer ; begin A := StrToInt (Edit1.Text) ; B := StrToInt (Edit2.Text) ; If A < B Then Limpa ( 'Edit1 no pode ser menor do que Edit2' ) ; end;

procedure TForm1.Button1Click(Sender: TObject); Var A, B, C, Fat : Integer ; begin A := StrToInt (Edit1.Text) ; B := StrToInt (Edit2.Text) ; If A > B Then begin Fat := 1 ; For C := (A - B) DOWNTO 1 Do Fat := Fat * C ; Case Obtem_Operador Of

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

67

'+' : C := Fat + StrToInt (Edit4.Text) ; '-' : C := Fat - StrToInt (Edit4.Text) ; '*' : C := Fat * StrToInt (Edit4.Text) ; '/' : C := Fat Div StrToInt (Edit4.Text) ; Else Limpa ( 'Operador Invlido' ) End ; Edit5.Text := IntToStr (C) ; end Else Limpa ( 'Edit1 no pode ser menor do que Edit2' ) ; end; end. Execute a aplicao e tente, numa primeira vez, entrar com um valor menor em Edit1 do que em Edit2. Depois, tente entrar com o operador @ em Edit3. Veja as mensagens de erro "sensveis" ao contexto. Outra coisa que voc deve ter notado, que o cdigo manipulado em Edit4Click idntico ao cdigo manipulado em Edit3Click. ser que no podemos simplificar essa chamada com uma procedure? Vamos fazer melhor: remova a manipulao OnClick de Edit4, deixando apenas o cabealho inicial , como abaixo: procedure TForm1.Edit4Click(Sender: TObject); begin end; Recompile o programa (Project - Compile) e veja que no h mais a manipulao deste evento (observe na aba Events do Oject Inspector que a manipulao OnClick de Edit4 est em branco). D um clique na setinha preta contida aps a parte branca da manipulao

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

68

e depois d um clique na manipulao Edit3Click. Note que a manipulao OnClick de Edit4 contm agora o nome da manipulao OnClick de Edit3. Isto significa dizer que: qualquer alterao introduzida em Edit3Click ser executada por Edit4Click tambm, evitando que cdigos desnecessrios sejam digitados. Mas preste bem ateno: o que foi realizado aqui vale apenas para a manipulao de eventos. 6.2. Funes de Usurio A diferena bsica entre uma chamada a uma procedure e a uma function que a segunda retorna um valor para o ponto de chamada, podendo (esse valor de retorno da funo) ser atribudo a uma varivel ou ser utilizado em uma condio de um dos comandos de controle: IF/THEN, WHILE/DO, REPEAT/UNTIL ou como valor de um CASE/OF, entre tantos outros usos. J uma procedure chamada de maneira independente no tendo valor de retorno e, por conseqncia, no podendo ser utilizado como condio de comando algum, e nem ser atribuda varivel alguma. importante observar que, o tipo de parmetro (ou parmetros) nada tem haver com o tipo do valor de retorno da funo, podendo em alguns casos serem iguais. Vamos mais uma vez alterar o cdigo anterior, modificando a funo Obtem_Operador que conter como parmetros uma string e um valor numrico indicando qual a posio em que se deve extrair o caractere da string passada como parmetro.

Altere a funo Obtem_Operador com o cdigo abaixo: function Obtem_Operador ( M : String ; Posicao : Integer ) : Char ; begin

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

69

Result := M [ Posicao ] ; end ; Altere tambm o cdigo OnClick de Button1: procedure TForm1.Button1Click(Sender: TObject); Var A, B, C, Fat : Integer ; begin A := StrToInt (Edit1.Text) ; B := StrToInt (Edit2.Text) ; If A > B Then begin Fat := 1 ; For C := (A - B) DOWNTO 1 Do Fat := Fat * C ; Case Obtem_Operador ( Edit3.Text , 1) Of '+' : C := Fat + StrToInt (Edit4.Text) ; '-' : C := Fat - StrToInt (Edit4.Text) ; '*' : C := Fat * StrToInt (Edit4.Text) ; '/' : C := Fat Div StrToInt (Edit4.Text) ; Else Limpa ( 'Operador Invlido' ) End ; Edit5.Text := IntToStr (C) ; end Else Limpa ( 'Edit1 no pode ser menor do que Edit2' ) ; end; end. Execute a aplicao e repita os passos anteriores para testar o novo cdigo. Feche a aplicao. Aqui, voc invocou a funo Obtem_Operador mandando dois parmetros entre parnteses: um string e outro inteiro, que so recebidos nas variveis locais M e Posicao, respectivamente. Isto nos faz concluir que, as variveis declaradas como parmetro so inicializadas com os valores passados entre parnteses quando da chamada da subrotina, o que nos obriga a passar valores de tipos compatveis na ordem em que so declarados no cabealho da funo. Uma outra observao a ser feita, que os parmetros passados (string e integer) tm tipos diferentes do tipo do valor de retorno da funo (tipo char). 6.3. Passagem de Parmetro por Referncia A passagem de parmetro por referncia, no importa se numa procedure ou numa function, faz com que a varivel recebedora utilize a mesma posio de memria da

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

70

varivel que passa o dado na chamada da sub-rotina. Isto impe que, numa passagem de parmetros por referncia, utilizemos somente variveis, ou seja, no podemos neste caso utilizar uma constante, coisa que fizemos quando invocamos a funo Obtem_Operador. Observe que o segundo parmetro a constante numrica 1). Vejamos um exemplo: Comece uma nova aplicao Digite a seguinte procedure no seu cdigo ( abaixo da diretiva de compilao {$R *.DFM}): procedure Altera_Valor ( X : Integer ; Var Y : Integer ; Z,W : Integer ) ; begin ShowMessage ( 'Durante a chamada procedure' + Chr(13) + '(antes da alterao):' + Chr(13) + Chr(13) + 'X = ' + IntToStr(X) + Chr(13) + 'Y = ' + IntToStr(Y) + Chr(13) + 'Z = ' + IntToStr(Z) + Chr(13) + 'W = ' + IntToStr(W) ) ; X := 10 ; Y := 20 ; Z := 30 ; W := 40 ; ShowMessage ( 'Durante a chamada procedure' + Chr(13) + '(aps a alterao):' + Chr(13) + Chr(13) + 'X = ' + IntToStr(X) + Chr(13) + 'Y = ' + IntToStr(Y) + Chr(13) + 'Z = ' + IntToStr(Z) + Chr(13) + 'W = ' + IntToStr(W) ) ; end ; Veja que o segundo parmetro ser passado por referncia.

Coloque um boto no form Manipule o evento OnClick deste boto com o seguinte: procedure TForm1.Button1Click(Sender: TObject);

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

71

Var A, B, C, D : Integer ; begin A := 3 ; B := 5 ; C := 7 ; D := 9 ; ShowMessage ( 'Antes da chamada procedure:' + Chr(13) + 'A = ' + IntToStr(A) + Chr(13) + 'B = ' + IntToStr(B) + Chr(13) + 'C = ' + IntToStr + Chr(13) + 'D = ' + IntToStr(D) ) ; Altera_Valor (A, B, C, D) ; ShowMessage ( 'Aps chamada `a procedure:' + Chr(13) + 'A = ' + IntToStr (A) + Chr(13) + 'B = ' + IntToStr (B) + Chr(13) + 'C = ' + IntToStr (C) + Chr(13) + 'D = ' + IntToStr (D) ) ; end; Execute a aplicao e clique o boto. Aparece o primeiro MessageBox com os valores das variveis. Quando voc entrou na manipulao do evento OnClick do boto, foi alocada memria RAM para armazenar os valores contidos nas variveis A, B, C e D, como mostra abaixo:

A memria da varivel A B varivel B varivel C varivel D C D 7 5

endereo de

endereo de memria da endereo de memria da

9 endereo de memria da

Quando a procedure invocada, mais memria alocada para as variveis que recebem os parmetros, com exceo da varivel Y, que compartilha a mesma posio de memria da varivel B , pois essa passagem feita por referncia e as demais por valor.

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

72

Isto quer dizer que: com exceo da varivel B, as outras variveis passam o contedo que cada uma delas tem para as variveis recebedoras. J a varivel B, fornece o endereo na memria para Y, e elas passam a coexistir nessa mesma posio:

A memria da varivel A B=Y variveis B e Y varivel C varivel D varivel X X Z W 3 C D 7 9 5

3 endereo de

endereo de memria das

endereo de memria da endereo de memria da endereo de memria da

7 endereo de memria da varivel Z 9 endereo de memria da varivel W

Quando voc imprime os contedos das variveis X, Y, Z e W, voc imprime o contedo de cada uma das posies de memria acima. Ao alterar o contedo de cada uma dessas variveis, acontece o seguinte:

A memria da varivel A B=Y variveis B e Y varivel C varivel D varivel X X Z W 10 C D 7 9

3 20 endereo de

endereo de memria das

endereo de memria da endereo de memria da endereo de memria da

30 endereo de memria da varivel Z 40 endereo de memria da varivel W

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

73

E a, quando voc imprime o contedo de cada uma delas, aparecem os novos valores: X = 10, Y = 20, Z = 30 e W = 40. Porm, quando a procedure chega ao fim, as variveis locais so destrudas, e h o retorno ao ponto de chamada da procedure. O que acontece com o contedo de cada posio de memria: A memria da varivel A B varivel B varivel C varivel D C D 7 endereo de memria da 20 endereo de memria da 3 endereo de

9 endereo de memria da

isso mesmo, o contedo da posio de memria ocupada pela varivel B, que era compartilhado pela varivel Y, ficou modificada. Isso porque houve passagem por referncia, e no por valor, como foi o caso das outras variveis. 6.4. InputBox Esta funo faz surgir uma janela de dilogo e retorna a string digitada no edit box da janela. Envolve trs parmetros: function InputBox(const ACaption, APrompt, ADefault: string): string; O primeiro (Acaption) o ttulo da janela; o segundo (Aprompt) o texto informativo do que o usurio deve digitar; e o terceiro (Adefault), o valor default que estar contido inicialmente no edit box da janela de dilogo. A palavra const para indicar que os valores passados no sofrero alterao nos seus contedos. Isso otimiza a memria e d maior velocidade de processamento. Comece uma nova aplicao Adicione um Label ao form Manipule o evento OnActivate de Form1 com o cdigo: procedure TForm1.FormActivate(Sender: TObject); begin Label1.Caption := InputBox ('Janela de Login' , 'Login Name:' ,'aluno') ; end; Execute a aplicao e clique em OK.

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

74

Feche e execute novamente a aplicao e clique em Cancel. Feche e execute novamente a aplicao, digite o seu nome e clique em OK. Feche e execute novamente a aplicao, digite o seu nome e clique em Cancel. Feche a aplicao 6.5. InputQuery Esta funo faz surgir uma janela de dilogo e retorna True se for clicado o boto OK e False se for clicado o boto Cancel . Envolve trs parmetros, com as mesmas finalidades descritas para InputBox: function InputQuery(const ACaption, APrompt: string; var Value: string): Boolean; Observe que o terceiro parmetro passado por referncia. Assim, qualquer alterao no edit box seguido de um clique no boto OK, altera o contedo da varivel Value, que conter o que foi digitado pelo usurio. Comece uma nova aplicao Adicione um Label ao form Manipule o evento OnActivate de Form1 com o cdigo: procedure TForm1.FormActivate(Sender: TObject); Var Mens : String ; begin If InputQuery ('Janela de Login' , 'Login Name:' , Mens) Then Label1.Caption := Mens ; end; Execute a aplicao e clique em OK. Feche e execute novamente a aplicao e clique em Cancel. Feche e execute novamente a aplicao, digite o seu nome e clique em OK. Feche e execute novamente a aplicao, digite o seu nome e clique em Cancel. Feche a aplicao

6.6. A funo Format Comece uma nova aplicao Coloque no Form, um componente Memo (aba Standard):

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

75

Adicione um boto ao Form OnClick deste boto com o cdigo abaixo:

Manipule evento

procedure TForm1.Button1Click(Sender: TObject); Var Pol : Integer ; Cm : Extended ; Valor : String ; begin Pol := 1 ; Repeat Cm := 2.54 * Pol ; Valor := Format ( '%3d = %6.2f ' , [ Pol , Cm ] ) ; Memo1.Lines.Append ( Valor ) ; Pol := Pol + 1 ; Until Pol > 100 ; end; Execute a aplicao, clique o boto e, depois de examinar a tabela de valores convertidos, feche a aplicao. Obs.: Para um detalhamento dos parmetros da funo Format Strings, utilize o Help online do Delphi.

6.7. O parmetro Sender Este parmetro um parmetro especial, e indica qual o tipo de objeto que est sofrendo o evento. Para testar se isso ocorre, faa o seguinte: Comece um novo aplicativo Coloque um edit box, um label e um memo no form Manipule o evento OnKeyPress de Edit1 com: procedure TForm1.Edit1KeyPress(Sender: TObject; var Key: Char); begin

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

76

Label1.Caption := Sender.ClassName ; end; Selecione esta manipulao de evento para os componentes Button1 e Memo1 Execute a aplicao, d um clique no edit box e digite algo; verifique que o Caption de Label1 alterou para TEdit. D um clique no boto e pressione uma tecla. Agora, o Caption alterou para TButton. D um clique no componente Memo1 e digite algo. Verifique a alterao do Caption de Label1 de TButton para TMemo. Feche a aplicao 7. Matrizes Comece uma nova aplicao Coloque um boto e um memo no form Manipule o evento OnActivate do form com: procedure TForm1.FormActivate(Sender: TObject); begin Memo1.Clear ; {Apaga tudo o que estiver escrito em Memo1} end; Manipule o evento OnClick de Button1 com: procedure TForm1.Button1Click(Sender: TObject); Var v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, Linha, Total_Linhas, Soma : Integer ; begin Total_Linhas := Memo1.Lines.Count ; {Quantidade de linhas de Memo1} Linha := 1 ; v1 := 0 ; v2 := 0 ; v3 := 0 ; v4 := 0 ; v5 := 0 ; v6 := 0 ; v7 := 0 ; v8 := 0 ; v9 := 0 ; v10 := 0 ; If Linha <= Total_Linhas Then begin v1 := StrToInt ( Memo1.Lines.Strings [ 0 ] ) ; Inc (Linha) ; {Incremente a varivel Linha de 1, ou seja: Linha := Linha + 1} end ; If Linha <= Total_Linhas Then begin v2 := StrToInt ( Memo1.Lines.Strings [ 1 ] ) ; Inc (Linha) ;

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

77

end ; If Linha <= Total_Linhas Then begin v3 := StrToInt ( Memo1.Lines.Strings [ 2 ] ) ; Inc (Linha) ; end ; If Linha <= Total_Linhas Then begin v4 := StrToInt ( Memo1.Lines.Strings [ 3 ] ) ; Inc (Linha) ; end ; If Linha <= Total_Linhas Then begin v5 := StrToInt ( Memo1.Lines.Strings [ 4 ] ) ; Inc (Linha) ; end ; If Linha <= Total_Linhas Then begin v6 := StrToInt ( Memo1.Lines.Strings [ 5 ] ) ; Inc (Linha) ; end ; If Linha <= Total_Linhas Then begin v7 := StrToInt ( Memo1.Lines.Strings [ 6 ] ) ; Inc (Linha) ; end ; If Linha <= Total_Linhas Then begin v8 := StrToInt ( Memo1.Lines.Strings [ 7 ] ) ; Inc (Linha) ; end ; If Linha <= Total_Linhas Then begin v9 := StrToInt ( Memo1.Lines.Strings [ 8 ] ) ; Inc (Linha) ; end ; If Linha <= Total_Linhas Then begin v10 := StrToInt ( Memo1.Lines.Strings [ 9 ] ) ; Inc (Linha) ; end ; Soma := v1 + v2 + v3 + v4 + v5 + v6 + v7 + v8 + v9 + v10 ; Memo1.Lines.Append ( Format ( 'Total = %d' , [ Soma ] ) ) ; end ; Execute a aplicao Digite o nmero 10 e pressione Enter Digite o nmero 15 e pressione Enter Digite o nmero 30 e pressione Enter

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

78

Digite o nmero 100 e pressione Enter D um clique no boto e veja o Total = 155. Feche a aplicao Obs1.: A funo Memo1.Lines.Count retorna o nmero de linhas contidas no componente Memo. No caso acima, no clique do boto, Total_Linhas conter quatro, pois teremos quatro strings em Memo1. Obs2.: A procedure Inc ( Nome_Var , quant ) passa Nome_Var por referncia e a incrementa de quant vezes. Quando quant igual a 1, pode-se omiti-la. Isto significa dizer que Linha := Linha + 1 o mesmo que Inc (Linha) . Obs3.: A procedure Dec ( Nome_Var , quant ) passa Nome_Var por referncia e a decrementa de quant vezes. Quando quant igual a 1, pode-se omiti-la. Isto significa dizer que X := X - 5 o mesmo que Dec (X , 5) . O problema com o cdigo acima, a grande quantidade de variveis, do mesmo tipo, envolvidas no clculo do total. Como podemos evitar manipular grande quantidade de variveis de um mesmo tipo, e como podemos automatizar o processo de manipulao, uma vez que se tivermos que alterar a quantidade de valores envolvidos, digamos de 10 valores para 50 valores, teremos um bom trabalho de digitao? Podemos utilizar matrizes, que so variveis que suportam vrios valores diferentes (porm do mesmo tipo), e nos permite referenciar cada valor por um ndice, que corresponde posio da matriz, na qual encontra-se o valor desejado. Para utilizar matrizes no Delphi, utilizamos a palavra reservada Array e definimos a dimenso da matriz entre colchetes. Por exemplo, 1 1 2 2 3 5 4 14 5 857 6 29 7 31 8 18 9 77 10 34 V

um vetor de nome V com 10 posies, sendo que a primeira posio possui o contedo 1, a segunda posio o contedo 2, a terceira posio o contedo 5, a quarta posio o contedo 14, e assim por diante. Abaixo voc tem a declarao da varivel Array e a inicializao dos valores conforme o esquema acima: Var V : Array begin V [ 1 ] := V [ 2 ] := V [ 3 ] := V [ 4 ] := V [ 5 ] := V [ 6 ] := V [ 7 ] := V [ 8 ] := V [ 9 ] := V [ 10 ] := end ; [ 1 .. 10 ] Of Integer ; 1; 2; 5; 14 ; 857 ; 29 ; 31 ; 18 ; 77 ; 34 ;

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

79

Note que a quantidade de elementos que o vetor possui, a diferena entre o primeiro valor e o ltimo valor mais 1 (so dez elementos: 10 - 1 + 1 = 10). Esses valores tambm dizem qual o ndice inicial e qual o ndice final (s podemos utilizar valores ordinais para definir os limites inicial e final de um array). H casos em que temos que definir um ndice inicial diferente da unidade. Para declarar, por exemplo, uma tabela de temperatura que varie de -37C 135C e, que em cada uma das 173 posies da tabela (135 - (-37) + 1 = 173) contenha o nome de uma localidade (com 50 caracteres), faa: Var Temp : Array [ -37 .. 135 ] Of String [ 50 ] ; Obs4.: Os dois pontos ( .. ) indicam que os valores em questo tratam-se de um limite. Vamos reescrever o cdigo anterior: procedure TForm1.Button1Click(Sender: TObject); Var K, Linha, Total_Linhas, Soma : Integer ; V : Array [ 1 .. 10 ] Of Integer ; begin Total_Linhas := Memo1.Lines.Count ; Linha := 1 ; For K := 1 To 10 Do V [ K ] := 0 ; While Linha <= Total_Linhas Do begin V [ Linha ] := StrToInt ( Memo1.Lines.Strings [ Linha - 1 ] ) ; Inc (Linha) ; end ; Soma := 0 ; For K := 1 To 10 Do Soma := Soma + V [ K ] ; Memo1.Lines.Append ( Format ( 'Total = %d' , [Soma] ) ) ; end ; Verifique que o cdigo ficou mais "suave". Mas e se voc deseja trabalhar com matrizes com mais de uma dimenso? Simples, s definir as dimenses (e seus limites) dentro dos colchetes, separados por vrgula. Por exemplo, para declarar a varivel array Mat de elementos reais (matriz 3 x 5): Coluna 1 Linha 1 Linha 2 Linha 3 Coluna 2 Coluna 3 Coluna 4 Coluna 5

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

80

Faa como abaixo: Type Matriz = Array [ 1 .. 3 , 1 .. 5 ] Of Extended ; Var Mat : Matriz ; Preste bem ateno: no obrigatrio o uso da clusula Type, porm torna o cdigo mas "elegante". E para inicializar os elementos da matriz acima com zero, podemos fazer como j fizemos para o StringGrid: For Linha := 1 To 3 Do For Coluna := 1 To 5 Do Mat [ Linha , Coluna ] := 0 ; Obs5.: Podemos utilizar as sees Const e Type para tornar o cdigo acima mais elegante ainda: Const Tot_Linhas = 3 ; Tot_Colunas = 5 ; Type Dimensao1 = 1 .. Tot_Linhas ; Dimensao2 = 1 .. Tot_Colunas ; Matriz = Array [ Dimensao1 , Dimensao2 ] Of Extended ; Var Mat : Matriz ; Linha : Dimensao1 ; Coluna : Dimensao2 ; begin For Linha := 1 To Tot_Linhas Do For Coluna := 1 To Tot_Colunas Do Mat [ Linha , Coluna ] := 0 ; Assim, qualquer alterao nas dimenses da matriz, acarretar a modificao apenas de pouca linhas de cdigo. Podemos ento definir a sintaxe geral de declarao de um tipo Array de "n" dimenses: Nome_Var_Array : Array [ li1 .. lf1 , li2 .. lf2 , .... , lin .. lfn ] Of Tipo_Array ;

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

81

Obs6.: Tome cuidado com a quantidade de memria alocada, pois um Array de strings pode chegar a alocar alguns MegaByte, dependendo das strings que voc venha a manipular. Obs7.: Como se pode trabalhar ento com dados de diferentes tipos? Caso voc queira trabalhar com as notas de vrios alunos de uma turma, calculando a mdia de cada aluno, a mdia da turma, etc., voc pode declarar uma matriz de strings para armazenar os nomes de cada aluno e declarar duas outras matrizes reais, para armazenar as notas da primeira prova e da segunda prova (considere somente estas duas notas). Assim sendo, o aluno que estiver na posio 1 da matriz de strings, ter sua primeira nota armazenada na posio 1 da primeira matriz real e ter sua segunda nota armazenada na segunda matriz real, e assim por diante, como esquematizado abaixo: Matriz de strings (Contm os nomes dos alunos) 1 Matriz real (Notas da primeira prova) 2 Matriz real (Notas da segunda prova)

Nome do Aluno n 1

Nome do Aluno n 2

Nome do Aluno n 3

Nome do Aluno n n

1 Nota do Aluno n 1 2 Nota do Aluno n 1

1 Nota do Aluno n 2 2 Nota do Aluno n 2

1 Nota do Aluno n 3 2 Nota do Aluno n 3

1 Nota do Aluno n n 2 Nota do Aluno n n

Caso o nome da matriz de strings seja igual a Nome, a primeira matriz real seja N1 e a segunda matriz real seja igual a N2, implicar em: Nome [ 1 ] = Nome do aluno 1 N1 [ 1 ] = Nota da primeira prova do aluno 1 N2 [ 1 ] = Nota da segunda prova do aluno 1 Nome [ 2 ] = Nome do aluno 2 N1 [ 2 ] = Nota da primeira prova do aluno 2 N2 [ 2 ] = Nota da segunda prova do aluno 2 Nome [ 3 ] = Nome do aluno 3 N1 [ 3 ] = Nota da primeira prova do aluno 3 N2 [ 3 ] = Nota da segunda prova do aluno 3 Nome [ n ] = Nome do aluno n N1 [ n ] = Nota da primeira prova do aluno n N2 [ n ] = Nota da segunda prova do aluno n

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

82

Vamos agora fazer uma aplicao que leia o nome de todos os alunos de uma classe, as respectivas notas das duas provas realizadas (assuma que a falta do aluno considerada nota zero) e no final imprima a mdia de cada aluno e a mdia da turma. Comece uma nova aplicao Coloque trs labels, trs edit box e um boto no form Altere o caption de: Label1: Nome do aluno Label2: Nota 1 Label3: Nota 2 Button1: &Incluir Apague a propriedade Text de todos os edit box Altere a propriedade CharCase de Edit1 para ecUpperCase

A l tere a propriedade Name de: Edit1: ebNome Edit2: ebN1 Edit3: ebN2 Insira logo abaixo da diretiva de compilao {$R *.DFM} linhas de cdigo contendo uma seo Const, uma seo Type e uma seo Var, como mostrado abaixo: implementation {$R *.DFM} Const

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

83

Num_Alunos = 5 ; Type Limite = 1 .. Num_Alunos ; Tipo_Nome = String [ 15 ] ; Mat_Nomes = Array [ Limite ] Of Tipo_Nome ; Mat_Notas = Array [ Limite ] Of Extended ; Var Nome : Mat_Nomes ; N1 , N2 : Mat_Notas ; i : Limite ; end. Manipule o evento OnClick de Button1 com: procedure TForm1.Button1Click(Sender: TObject); Var k : Limite ; Soma1 , Soma2 : Extended ; begin Nome [ i ] := ebNome.Text ; N1 [ i ] := StrToFloat ( ebN1.Text ) ; N2 [ i ] := StrToFloat ( ebN2.Text ) ; Inc ( i ) ; ebNome.SetFocus ; If i > Num_Alunos Then begin Memo1.Clear ; Memo1.Visible := True ; Soma1 := 0 ; Soma2 := 0 ; For k := 1 To Num_Alunos Do begin Soma1 := Soma1 + N1 [ k ] ; Soma2 := Soma2 + N2 [ k ] ;
Memo1.Lines.Add ( Format ( ' Aluno = %15s - Nota1 = %4.1f Nota2 = %4.1f Mdia = %4.1f ' , [ Nome [ k ] , N1 [ k ] , N2 [ k ], ( N1 [ k ] + N2 [ k ] ) / 2 ] ) ) ;

end ; Soma1 := Soma1 / Num_Alunos ; Soma2 := Soma2 / Num_Alunos ;


Memo1.Lines.Add ( Format ( ' Mdia da Turma = %4.1f ' , [ ( Soma1 + Soma2 ) / 2 ] ) ) ;

end ; end ; Obs8.: As linhas de comando: "Memo1.Lines.Add ( Format ... " foram diminudas devido ao seu tamanho exceder os limites da pgina na qual a apostila est sendo escrita. No Delphi, voc dever digitar a linha de comando sem se preocupar em alterar o tamanho da fonte. A funo Format contm o seguinte:

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

84

primeira ocorrncia: Format ( ' Aluno = %15s - Nota1 = %4.1f Nota2 = %4.1f Mdia = %4.1f ' , [ Nome [ k ] , N1 [ k ] , N2 [ k ] , ( N1 [ k ] + N2 [ k ] ) / 2 ] ) ) ; segunda ocorrncia: Format ( ' Mdia da Turma = %4.1f ' , [ ( Soma1 + Soma2 ) / 2 ] ) ) ; Coloque um componente Memo no form, de tal maneira que ele encubra os edit box e o boto Altere a propriedade Visible do componente Memo1 para False

Execute o aplicativo. Digite vrios nomes e vrias notas e veja o resultado quando aparecer o componente Memo1. Voc deve ter observado que os dados do primeiro aluno no aparecem, enquanto que um sexto aluno (o array contm 5 elementos) aparece nas estatsticas. Por que? Porque o aplicativo no sabe qual o valor inicial da varivel "i". Feche o aplicativo. Adicione antes do "end." da unit as seguintes linhas de comando: Initialization i := 1 ; Tudo que se encontra na rea de inicializao de uma unit executada antes que qualquer comando ou manipulao de evento. Assim fazendo, quando voc manipula o click de Button1 pela primeira vez, a varivel "i" igual a 1. Execute novamente o aplicativo e veja agora o resultado correto aparecer na tela. Feche o aplicativo. Obs9.: O porqu de se ter declarado a constante, os tipos e as variveis aps a diretiva de compilao e no dentro de uma manipulao de evento, deveu-se necessidade

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

85

de termos essas declaraes com um aspecto global (vlido por toda a unit e no somente dentro da manipulao de um determinado evento). Quando uma manipulo de evento executada, tudo aquilo que declarado nela (constantes, tipos e variveis) criado e, ao trmino da manipulao do evento, tudo aquilo que foi declarado destrudo, desalocando a memria requerida. Porm, como era de interesse armazenar at o final da execuo do aplicativo os dados armazenados nas matrizes (nomes e notas), foi preciso criar estruturas globais, e no locais a uma determinada manipulao de evento. Obs10.: A funo Add faz o mesmo que a procedure Append porm, a funo Add retorna um valor inteiro que significa qual o ndice da nova string (qual a posio da string no componente memo). 8. Registros So estruturas que servem para armazenar, sob uma mesma varivel, valores de tipos diferentes, mas que so correlacionados. A sintaxe geral : Var Nome_Var_Registro : Record Campo1 : Tipo1 ; Campo2 : Tipo2 ; Campon : Tipon ; end ; Podemos utilizar tambm a clusula Type: Type TNome_Var_Registro : Record Campo1 : Tipo1 ; Campo2 : Tipo2 ; Campon : Tipon ; end ; Var Nome_Var_Registro : TNome_Var_Registro ;

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

86

Adotando a notao do Delphi de sempre comear um tipo pela letra T (maiscula). Uma vez declarada a varivel Record, podemos atribuir valores aos seus campos utilizando a notao: Nome_Var_Registro.Nome_do_Campo := Valor ; ou seja, para referenciarmos um campo de Record, digitamos o nome da varivel e o nome do campo em questo, separados por um ponto (. ).

No exemplo anterior, onde foi necessrio o armazenamento de um nome e duas notas, poderamos ter utilizado o tipo Record, o que nos aumentaria a performance: Type TDados_Aluno : Record Nome : String [ 15 ] ; N1 : Extended ; N2 : Extended ; end ; Var Aluno : T Dados_Aluno ; Feito isto, o aluno Fulano de Tal cuja nota na primeira prova foi 8,5 e cuja segunda nota foi 7,3 , pode ter seus dados armazenados da seguinte forma: Aluno.Nome := ' Fulano de Tal ' ; Aluno.N1 := 8.5 ; Aluno.N2 := 7.3 ;

Obs1.: Observe que a notao americana para separao de casas decimais utiliza o ponto decimal, e no a vrgula. Por isso, um nmero real denominado: valor em ponto-flutuante. Voc tambm pode utilizar a clusula With / Do para referenciar os campos de um registro: With Aluno Do begin Nome := ' Fulano de Tal ' ;

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

87

N1 := 8.5 ; N2 := 7.3 ; end ; Mas no adianta muito, armazenar somente os dados de um aluno. Se reescrevssemos o programa anterior, precisaramos de 5 variveis record para representar todos os alunos da turma, o que no faz muito sentido, pois a digitao seria muito grande (imagine para uma turma de 100 alunos!). Como ns precisamos armazenar os dados dos alunos de uma turma inteira, precisamos declarar um Array de registros, para que possamos manipular os vrios dados envolvidos, sem nos preocuparmos com os n Arrays necessrios para essa implementao. Para tanto, observe a declarao abaixo: Const Num_Alunos = 5 ; Type Limite = 1 .. Num_Alunos ; TDados_Aluno = Record Nome : String [ 15 ] ; N1 : Extended ; N2 : Extended ; end ; TAluno = Array [ Limite ] Of TDados_Aluno ; Var Aluno : TAluno ; i : Limite ; Aqui, a cada click do boto, em vez de fazer: Nome [ i ] N1 [ i ] N2 [ i ] Inc ( i ) ; := ebNome.Text ; := StrToFloat ( ebN1.Text ) ; := StrToFloat ( ebN2.Text ) ;

para armazenar os vrios dados em diferentes arrays, declarado o array de record poderamos fazer: Aluno[i].Nome := ebNome.Text ; Aluno[i].N1 := StrToFloat ( ebN1.Text ) ; Aluno[i].N2 := StrToFloat ( ebN2.Text ) ; Inc ( i ) ; Ou, utilizando a clusula With / Do :

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

88

With Aluno[i] Do begin Nome := ebNome.Text ; N1 := StrToFloat ( ebN1.Text ) ; N2 := StrToFloat ( ebN2.Text ) ; end ; Inc ( i ) ;

Vamos alterar o programa (unit1) anterior. Altere a manipulaao de Button1: procedure TForm1.Button1Click(Sender: TObject); Var k : Limite ; Soma1 , Soma2 : Extended ; begin With Aluno[i] Do begin Nome := ebNome.Text ; N1 := StrToFloat ( ebN1.Text ) ; N2 := StrToFloat ( ebN2.Text ) ; end ; Inc ( i ) ; ebNome.SetFocus ; If i > Num_Alunos Then begin Memo1.Clear ; Memo1.Visible := True ; Soma1 := 0 ; Soma2 := 0 ; For k := 1 To Num_Alunos Do With Aluno [ k ] Do begin Soma1 := Soma1 + N1 ; Soma2 := Soma2 + N2 ;
Memo1.Lines.Add ( Format ( ' Aluno = %15s - Nota1 = %4.1f Nota2 = %4.1f Mdia = %4.1f ' , [ Nome, N1 , N2, ( N1 + N2 ) / 2 ] ) ) ;

end ; Soma1 := Soma1 / Num_Alunos ; Soma2 := Soma2 / Num_Alunos ;


Memo1.Lines.Add ( Format ( ' Mdia da Turma = %4.1f ' , [ ( Soma1 + Soma2 ) / 2 ] ) ) ;

end ; end ;

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

89

Obs2.: Mais uma vez importante lembrar que: as linhas de comando: "Memo1.Lines.Add ( Format ... " foram diminudas devido ao seu tamanho exceder os limites da pgina na qual a apostila est sendo escrita. No Delphi, voc dever digitar a linha de comando sem se preocupar em alterar o tamanho da fonte. A funo Format contm o seguinte: primeira ocorrncia: Format ( ' Aluno = %15s - Nota1 = %4.1f Nota2 = %4.1f Mdia = %4.1f ' , [ Nome , N1 , N2 , ( N1 + N2 ) / 2 ] ) ) ; segunda ocorrncia: Format ( ' Mdia da Turma = %4.1f ' , [ ( Soma1 + Soma2 ) / 2 ] ) ) ; Altere agora as declaraes globais: implementation {$R *.DFM} Const Num_Alunos = 5 ; Type Limite = 1 .. Num_Alunos ; Tipo_Nome = String [ 15 ] ; TDados_Aluno = Record Nome : Tipo_Nome ; N1 : Extended ; N2 : Extended ; end ; TAluno = Array [ Limite ] Of TDados_Aluno ; Var Aluno : TAluno ; i : Limite ; Execute o aplicativo e depois o feche. Obs3.: A unit1, ao final, dever ser igual ao cdigo que segue:
unit Unit1; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm1 = class(TForm) ebNome: TEdit;

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

90

Label1: TLabel; Label2: TLabel; ebN1: TEdit; Label3: TLabel; ebN2: TEdit; Button1: TButton; Memo1: TMemo; procedure Button1Click(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form1: TForm1; implementation {$R *.DFM} Const Num_Alunos = 5 ; Type Limite = 1 .. Num_Alunos ; Tipo_Nome = String [ 15 ] ; TDados_Aluno = Record Nome : Tipo_Nome ; N1 : Extended ; N2 : Extended ; end ; TAluno = Array [ Limite ] Of TDados_Aluno ; Var Aluno : TAluno ; i : Limite ; procedure TForm1.Button1Click(Sender: TObject); Var k : Limite ; Soma1 , Soma2 : Extended ; begin With Aluno[i] Do begin Nome := ebNome.Text ; N1 := StrToFloat ( ebN1.Text ) ; N2 := StrToFloat ( ebN2.Text ) ; end ; Inc ( i ) ; ebNome.SetFocus ; If i > Num_Alunos Then begin Memo1.Clear ; Memo1.Visible := True ; Soma1 := 0 ; Soma2 := 0 ; For k := 1 To Num_Alunos Do With Aluno [ k ] Do begin Soma1 := Soma1 + N1 ;

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

91

Soma2 := Soma2 + N2 ; Memo1.Lines.Add ( Format ( ' Aluno = %15s - Nota1 = %4.1f Nota2 = %4.1f Mdia = %4.1f ' , [ Nome, N1 , N2, ( N1 + N2 ) / 2 ] ) ) ; end ; Soma1 := Soma1 / Num_Alunos ; Soma2 := Soma2 / Num_Alunos ; Memo1.Lines.Add ( Format ( ' Mdia da Turma = %4.1f ' , [ ( Soma1 + Soma2 ) / 2 ] ) ) ; end ; end ; Initialization i := 1 ; end.

9. Ponteiros Quando voc declara uma varivel (varivel de memria), voc na realidade est alocando memria para armazenar valores compatveis com o tipo da varivel, isto , se voc declara uma varivel do tipo Byte, voc est alocando 1 byte de memria para armazenar valores entre 0 e 255. Se voc declara uma varivel do tipo Word, voc est alocando 2 bytes de memria para armazenar valores entre 0 e 65535, e assim por diante. Quando voc quiser manipular o valor armazenado em uma determinada posio de memria, basta que voc utilize a varivel correspondente, declarada na seo Var. Na realidade, nem lembramos que, ao manipular uma varivel, estamos na verdade manipulando uma dada poro de memria. Para grandes quantidades de memria, podemos utilizar um Array de n posies. Mas e se voc no souber a quantidade de dados que sero manipulados? Por exemplo, imagine que voc todo dia digita uma quantidade de informaes (como as informaes contidas em cheques) para dar entrada em um processamento contbil. Num dia voc s digita 200 informaes, mas no outro dia voc chega a digitar 1500 informaes. O que voc faria? Delimitaria, com certeza, um Array com 1500 posies. Mas e se um outro dia voc precisasse manipular 2300 informaes? E assim por diante. Para resolver casos como esse, podemos trabalhar com a memria diretamente, alocando ou desalocando memria, de acordo com as nossas necessidades. Variveis que, ao invs de armazenarem um valor qualquer, armazenam um endereo de memria so chamadas Ponteiros de Memria ou simplesmente Ponteiros. Imagine a memria como sendo uma longa fila, onde voc pode armazenar valores em posies de memria, como mostrado abaixo: 12 endereo 1 - varivel V1 456 endereo 2 - varivel V2 -20 endereo 3 - varivel V3 endereo 4 - varivel V4 endereo 5 - varivel V5 endereo 6 - varivel V6 33 1054 220 0 758 36

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

92

endereo 7 - varivel V7 endereo 8 - varivel V8 endereo 9 - varivel V9 Isto significa que, a varivel V1, que est associada posio de memria endereo 1, contm o valor numrico 12, ou seja, quando foi realizada a operao: V1 := 12 ; na realidade foi atribudo o valor 12 quela posio de memria, como mostrado acima. E temos a mesma explicao para as demais variveis. Para declarar uma varivel ponteiro, voc digita o caractere circunflexo antes do tipo desejado, ou seja, voc cria uma varivel para conter a posio de memria alocada para um tipo Pascal conhecido. Por exemplo, para criar um ponteiro para inteiro: Var Var_Ponteiro : ^Integer ; E para atribuir um valor posio de memria apontada pela varivel ponteiro, voc utiliza o mesmo circunflexo aps o nome da varivel. Por exemplo, para atribuir o valor 1023 varivel ponteiro acima, faa: Var_Ponteiro^ := 1023 ; O operador @ atribui a um ponteiro o endereo de memria de uma varivel. Por exemplo, Comece uma nova aplicao Coloque um memo e um boto no form Manipule o evento OnClick do boto com: procedure TForm1.Button1Click(Sender: TObject); Var Num : Integer ; P1 , P2 : ^Integer ; begin Num := 1025 ; P1 := @Num ; P2 := P1 ; P2^ := 50 ; Memo1.Lines.Append ( IntToStr ( Num ) ) ; Memo1.Lines.Append ( IntToStr ( P1^ ) ) ; Memo1.Lines.Append ( IntToStr ( P2^ ) ) ; end; Isto significa dizer que P1 recebeu o endereo de memria da varivel Num e que P2 recebeu o contedo de P1, que em ltima anlise o endereo de

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

93

memria da varivel Num. Ao alterar o contedo de memria apontada por P2, voc alterou o contedo da varivel Num, como atesta a listagem de Memo1. Esquematicamente teramos: P1 1025 P2 Feche a aplicao. Na realidade, trabalhar com ponteiros em Pascal no uma tarefa das mais simples, se comparada ao uso de ponteiros na linguagem C. Uma forma razoavelmente simples de trabalhar com ponteiros no Pascal, fazer o uso de listas ligadas, para o que voc pode seguir os passos abaixo: 1. Idealizar a estrutura de um registro (o nome e os campos) 2. Seo Type: Definir um tipo ponteiro para esse registro 3. Seo Type: Definir um registro que contenha, alm dos campos idealizados em "1." , um campo que seja do tipo ponteiro definido em "2.", com o nome Prox 4. Seo Var: Declarar trs variveis ponteiro do tipo definido em " 2." : uma de nome P, outra de nome Inicio e a outra de nome Anterior. Por exemplo, vamos redefinir o record que armazena dados dos alunos: Type TAluno = ^TDados_Aluno ; TDados_Aluno = Record Nome : String ; N1 : Extended ; N2 : Extended ; Prox : TAluno ; end ; Var P , Inicio, Anterior : TAluno ; Pedir alocao de memria para a varivel ponteiro, atravs da procedure New e atribuir o valor Nil ao campo Prox (sendo Nil o equivalente ao valr nulo para variveis ponteiros, isto , um ponteiro que contenha o valor Nil no aponta para lugar nenhum): New ( P ) ; P^.Prox := Nil ; 6. Guardar o endereo inicial na varivel ponteiro Inicio: Inicio := P ; 7. Guardar o endereo de P na varivel Anterior: Anterior := P ; 8. Armazenar informaes sobre um aluno nos campos do registro atualmente apontado por P : P^.Nome := Edit1.Text ;
5.

Num

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

94

9.

10. 11. 12.

P^.N1 := StrToFloat (Edit2.Text ) ; P^.N2 := StrToFloat (Edit3.Text ) ; Para armazenar um novo aluno, alocar mais memria para P ( como se voc estivesse incrementando de 1 o ndice final do Array de registros): New ( P ) ; P^.Prox := Nil ; Como Anterior possui o endereo de memria anterior nova alocao, atualize o campo Prox do registro anterior: Anterior^.Prox := P ; Atualize o ponteiro Anterior com o novo endereo de P: Anterior := P ; Retorne ao item "8." at no ser mais necessria a entrada de dados.

At este ponto, temos vrios registros na memria, sendo que o endereo do primeiro registro est armazenado na varivel Inicio. Graficamente, o que voc fez com os passos anteriores foi: item 5. : Nome N1 N2 Prox endereo do 1 registro: E1

Nil

item 6. :

Nome N1 N2 Prox

endereo do 1 registro: E1

Nil

Inicio

item 7. :

Nome N1 N2 Prox

endereo do 1 registro: E1

Nil

Inicio

Anterior

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

95

Por hiptese, vamos supor que os edit box contenham os dados: AL1 , 10 e 8.2 : item 8. : Nome AL1 N1 10.0 N2 8.2 Prox Nil endereo do 1 registro: E1

Inicio

Anterior

item 9. :

Nome N1 N2 Prox Nome N1 N2 Prox

AL1 10.0 8.2 Nil

endereo do 1 registro: E1

Anterior Inicio endereo do 2 registro: E2

Nil

Observe que P aponta para o novo registro, mas Anterior ainda aponta para o registro anteriormente criado. item 10. : endereo do 1 registro: E1

Nome N1 N2 Prox Nome N1 N2 Prox

AL1 10.0 8.2 E2

Anterior Inicio endereo do 2 registro: E2

Nil P

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

96

O campo Prox do primeiro registro contm o endereo do prximo registro que, neste caso, o endereo de memria que contm o segundo registro. S nos falta agora, antes de alterar os campos do registro corrente (2 registro), atualizar a varivel ponteiro Anterior para, num prximo passo, repetir as aes acima (a partir do item "8.").

item 11. :

Nome N1 N2 Prox Nome N1 N2 Prox

AL1 10.0 8.2 E2

endereo do 1 registro: E1

Inicio endereo do 2 registro: E2

Nil

Anterior

Retornando ao item 8: Vamos supor que, dados: AL2 , 6.2 item 8. : Nome N1 N2 Prox Nome N1 N2 Prox AL1 10.0 8.2 E2 AL2 6.2 7.5 Nil agora, os edit box contenham os seguintes e 7.5 : endereo do 1 registro: E1

Inicio

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

97

endereo do 2 registro: E2

Anterior

item 9. :

Nome N1 N2 Prox Nome N1 N2 Prox Nome N1 N2 Prox Nome N1 N2 Prox Nome N1 N2 Prox Nome N1 N2 Prox

AL1 10.0 8.2 E2 AL2 6.2 7.5 Nil

endereo do 1 registro: E1

Inicio endereo do 2 registro: E2 Anterior endereo do 3 registro: E3

Nil AL1 10.0 8.2 E2 AL2 6.2 7.5 E3

endereo do 1 registro: E1

item 10. :

Inicio endereo do 2 registro: E2 Nil

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

98

Anterior endereo do 3 registro: E3 P

E mais uma vez Anterior atualizado com o endereo contido em P e h o retorno ao item 8, at no mais ser necessria a alocao de mais memria. Agora ns vamos fazer o oposto: vamos recuperar as informaes armazenadas na memria, como mostra os demais passos:
13. 14.

Atribuir P o contedo da varivel Inicio: P := Inicio ; Enquanto o campo Prox for diferente de Nil faa: 14.1. Visualizar os dados armazenados no registro (nos campos do registro):
Memo1.Lines.Add ( ' Format ( ' %s - N1 = %4.1f N2 = %4.1f ' , [ P^.Nome , P^.N1 , P^.N2 ] ) ; 14.2.

Atualizar o contedo de P com o endereo do prximo registro ( que est armazenado no campo Prox do registro atual): P := P^.Prox ;

15.

Liberar a memria alocada por P (por Anterior e por Inicio): Dispose ( P ) ;

Vamos criar um aplicao que realize os passos acima. Comece uma nova aplicao Adicione ao form trs label, trs edit box, um boto e um memo Apague o Text dos edit box e altere o Caption de Button1 para &Incluir Alterar a propriedade CharCase de Edit1 para ecUpperCase Aps a diretiva de compilao {$R *.DFM} e antes do end. da unit, digite as linhas abaixo para criar os tipos e variveis globais e a seo de inicializao (digite apenas o que estiver dentro do retngulo, pois o resto o Delphi j fez): {$R *.DFM}

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

99

Type TAluno = ^TDados_Aluno TDados_Aluno = Record Nome : N1 : N2 : Prox : End ; Var P , Inicio , Anterior : TAluno ; Initialization New ( P ) ; Inicio := P ; Anterior := P ; P^.Prox := Nil ; ; String ; Extended ; Extended ; TAluno ;

end. Manipule o evento OnClick de Button1 com: procedure TForm1.Button1Click(Sender: TObject); begin

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

100

With P^ Do begin Nome := Edit1.Text ; N1 := StrToFloat ( Edit2.Text ) ; N2 := StrToFloat ( Edit3.Text ) ; end ; New ( P ) ; P^.Prox := Nil ; Anterior^.Prox := P ; Anterior := P ; Edit1.SetFocus ; end; Manipule o evento OnDblClick de Memo1 com: procedure TForm1.Memo1DblClick(Sender: TObject); begin P := Inicio ; While P^.Prox <> Nil Do begin Memo1.Lines.Add ( Format ( ' %S N1 = %4.1f N2 = %4.1f ' , [ P^.Nome , P^.N1 , P^.N2 ] ) ) ; P := P^.Prox ; end ; end; Manipule o evento OnClose de Form1 com: procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction); begin Dispose ( P ) ; end; Execute o aplicativo Digite um nome e duas notas ; clique no boto Repita esse procedimento para quantos alunos voc desejar D um clique duplo em Memo1 e veja o relatrio Feche o aplicativo

Agora, se ns quisermos imprimir ao contrrio da ordem de entrada, precisamos de mais um campo no nosso registro, que o campo ponteiro Antes , que como o prprio nome diz, conter o endereo do registro anterior.

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

101

Aqui nos preocuparemos tambm em armazenar o endereo anterior ao endereo atualmente apontado por P. Observe que o endereo anterior ao primeiro endereo alocado ser igual a Nil, ou seja, no apontar para lugar algum, pois no h endereo que esteja alocado pelo ponteiro P. Outra coisa que voc ir notar, que podemos escrever os nomes dos campos de mesmo tipo, separados por vrgulas, e ao final digitar os dois pontos e o tipo dos campos. Comece uma nova aplicao Adicione ao form trs label, trs edit box, um boto, um memo e dois RadioButton (aba Standard):

Obs1.

: Os componentes RadioButton so mutuamente exclusivos, o que significa dizer que, uma vez que um deles clicado, o outro deixa de ser selecionado (sua propriedade Checked passa para False), como so os botes de um rdio. Por isso seu nome RadioButton. Altere a propriedade Caption de RadioButton1 para Crescente Altere a propriedade Name de RadioButton1 para rbC Altere tambm a propriedade Checked deste componente para True Altere a propriedade Caption de RadioButton2 para Decrescente Altere a propriedade Name de RadioButton2 para rbD Apague a propriedade Text dos edit box Altere o Caption de Button1 para &Incluir Alterar a propriedade CharCase de Edit1 para ecUpperCase

Aps a diretiva de compilao {$R *.DFM} e antes do end. da unit, digite as linhas abaixo para criar os tipos e variveis globais e a seo de inicializao:

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

102

Type TAluno = ^TDados_Aluno ; TDados_Aluno = Record Nome : String ; N1 : Extended ; N2 : Extended ; Antes , Prox : TAluno ; End ; Var P , Inicio , Anterior : TAluno ; Initialization New ( P ) ; Inicio := P ; Fim := P ; Anterior := P ; P^.Prox := Nil ; P^.Antes := Nil ; Obs2.: Note a varivel Fim, que armazena o ltimo endereo. Manipule o evento OnClick de Button1 com: procedure TForm1.Button1Click(Sender: TObject); begin With P^ Do begin Nome := Edit1.Text ; N1 := StrToFloat ( Edit2.Text ) ; N2 := StrToFloat ( Edit3.Text ) ; end ; Fim := P ; {Atualiza Fim, pois aqui esto os dados do ltimo aluno} New ( P ) ; {Aloca mais memria para outro registro} P^.Prox := Nil ; P^.Antes := Anterior ; Anterior^.Prox := P ; Anterior := P ; Edit1.SetFocus ; end; Obs3.: Note que foi adicionada a linha: P^.Antes := Anterior ; a esta manipulao de evento, pois agora precisamos armazenar, no novo endereo, o endereo anterior, que est armazenado na varivel Anterior. Manipule o evento OnDblClick de Memo1 com:

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

103

procedure TForm1.Memo1DblClick(Sender: TObject); begin Memo1.Clear ; If rbC.Checked Then begin P := Inicio ; While P^.Prox <> Nil Do begin Memo1.Lines.Add ( Format ( ' %S N1 = %4.1f N2 = %4.1f ' , [ P^.Nome , P^.N1 , P^.N2 ] ) ) ; P := P^.Prox ; end ; end Else begin P := Fim ; While P^.Antes <> Nil Do begin Memo1.Lines.Add ( Format ( ' %S N1 = %4.1f N2 = %4.1f ' , [ P^.Nome , P^.N1 , P^.N2 ] ) ) ; P := P^.Antes ; end ; { Quando o campo P^.Antes for igual a Nil, porque foi alcanado o primeiro registro, ento devem ser impressos os dados desse primeiro aluno } Memo1.Lines.Add ( Format ( ' %S N1 = %4.1f N2 = %4.1f ' , [ P^.Nome , P^.N1 , P^.N2 ] ) ) ; end ; end;

Execute o aplicativo Digite os dados do primeiro aluno e clique o boto Digite os dados do segundo aluno e clique o boto Digite os dados do terceiro aluno e clique o boto D um duplo clique em Memo1 D um clique em rbD (radiobutton cujo Caption Decrescente) D novo duplo clique em Memo1 Feche o aplicativo

10. Proteo Contra Erros em Tempo de Execuo

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

104

Comece uma nova aplicao Coloque trs Edit box e um Boto no Form Manipule o evento OnClick de Button1 com: procedure TForm1.Button1Click(Sender: TObject); Var A , B , C : ^Extended ; begin New (A) ; New (B) ; New (C) ; C^ := -1 ; A^ := StrToFloat (Edit1.Text) ; B^ := StrToFloat (Edit2.Text) ; C^ := A^ / B^ ; Edit3.Text := FloatToStrF (C^ , ffFixed , 1 , 2) ; Dispose (A) ; Dispose (B) ; Dispose (C) ; end; Execute a aplicao e digite os valores: 10 e 2 , e d um clique em seguida no boto. Digite agora os valores: 10 e 0 (zero) e d um clique no boto. Veja que o programa interrompido com uma mensagem de erro e o resultado em Edit3 ainda possui o valor anterior: 5.00. Feche a aplicao. Obs1.: A funo FloatToStrF retorna uma string formatada da transformao do valor Extended entre parnteses. Para uma obteno dos parmetros, vide o Help online do Delphi. Para evitar quebras do programa pela execuo de uma "exceo", utilizamos blocos de proteo contra erros em tempo de execuo (Run-Time Errors). Nas lies anteriores, voc trabalhou com ponteiros de memria, e viu que, para utiliz-los, preciso alocar memria atravs da procedure New, mas ao final do seu uso, preciso "devolver" essa memria alocada ao Sistema Operacional, sob pena de uma reduo drstica nos recursos do sistema. Esta desalocao se faz com a procedure Dispose. Agora suponha que, aps alocar 10 MB de RAM para a utilizao de uma varivel ponteiro, voc executa uma operao ilegal, semelhante quela realizada acima (diviso por zero). No h como desalocar a memria utilizada pelo ponteiro. A no ser que voc utilize o bloco de proteo: TRY / FINALLY / END.

Sua sintaxe geral :

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

105

Try Comando 1 ; Comando 2 ; Comando n ; Finally ComandoFinal1 ; ComandoFinal2 ; ComandoFinalm ; End ; Assim, independente de haver ou no um erro em tempo de execuo (desde que no haja, obviamente, o desabamento do Sistema Operacional), os ComandoFinali sero executados normalmente. Reescreva a manipulao de evento acima com: procedure TForm1.Button1Click(Sender: TObject); Var A , B , C : ^Extended ; begin Try New (A) ; New (B) ; New (C) ; C^ := -1 ; A^ := StrToFloat (Edit1.Text) ; B^ := StrToFloat (Edit2.Text) ; C^ := A^ / B^ ; Finally Edit3.Text := FloatToStrF (C^ , ffFixed , 1 , 2) ; Dispose (A) ; Dispose (B) ; Dispose (C) ; End ; end; Execute a aplicao Digite os valores: 10 e 2 e clique o boto. Veja o resultado: 5.00 . Digite agora os valores: 10 e 0 (zero) e clique o boto. Veja que o resultado apresentado igual a -1, pois independente de ter havido o erro de diviso por zero, impresso o contedo de memria alocada por C (como houve erro de

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

106

diviso por zero, este contedo no alterado pela diviso de A por B, pois a atribuio cancelada no momento do erro). feche a aplicao. Um outro bloco de proteo que pode ser usado o bloco TRY / EXCEPT / END, que difere-se do bloco anterior por no executar um bloco de cdigo de maneira incondicional, e sim, na ocorrncia de uma exceo. Sua sintaxe geral : Try Comando1 ; Comando2 ; Comandon ; Except ComandoExceo 1 ; ComandoExceo 2 ; ComandoExceo m ; End ; Reescreva o cdigo OnClick acima com (substitua Finally por Except): procedure TForm1.Button1Click(Sender: TObject); Var A , B , C : ^Extended ; begin Try New (A) ; New (B) ; New (C) ; C^ := -1 ; A^ := StrToFloat (Edit1.Text) ; B^ := StrToFloat (Edit2.Text) ; C^ := A^ / B^ ; Edit3.Text := FloatToStrF (C^ , ffFixed , 1 , 2) ; Dispose (A) ; Dispose (B) ; Dispose (C) ; Except ShowMessage ( ' O denominador no pode ser zero! ' ) ; End ; end; Execute a aplicao, repita a digitao dos valores como voc j fez acima. Feche o aplicativo.

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

107

Neste caso, qualquer execuo que gere um erro em tempo de execuo ser protegido pelo bloco TRY / EXCEPT / END. Voc pode estar se perguntando neste momento: Por que no utilizar o If / Then para testar se o valor do denominador igual a zero, antes de executar a diviso? Simples: porque toda a vez que a manipulao for executada, o comando If / Then testar se a condio ou no verdadeira. Isso significa que a performance do cdigo diminuda. Ao contrrio, se voc utilizar o bloco TRY / EXCEPT / END, no haver condio a ser testada, aumentando a performance do cdigo. O cdigo acima ainda necessita de uma alterao pois, se houver uma diviso por zero, a procedure ShowMessage executada, porm no impresso o valor -1 como resultado final, e nem os ponteiros sofrem o Dispose. Para corrigir tal problema, vamos aninhar o bloco TRY / EXCEPT / END num bloco TRY / FINALLY / END. Reescreva o cdigo OnClick acima com: procedure TForm1.Button1Click(Sender: TObject); Var A , B , C : ^ Extended ; begin Try Try New (A) ; New (B) ; New (C) ; C^ := -1 ; A^ := StrToFloat (Edit1.Text) ; B^ := StrToFloat (Edit2.Text) ; C^ := A^ / B^ ; Except ShowMessage ( ' O denominador no pode ser zero! ' ) ; End ; Finally Edit3.Text := FloatToStrF (C^ , ffFixed , 1 , 2) ; Dispose (A) ; Dispose (B) ; Dispose (C) ; End ; end;

Execute a aplicao Digite os valores: 10 e 2 e clique o boto. Veja o resultado: 5.00 . Digite agora os valores: 10 e 0 (zero) e clique o boto. Feche o aplicativo.

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

108

O bloco de proteo TRY / EXCEPT / END utiliza a RTL (Run-Time Library), que contm excees definidas na unit SysUtils, sendo que essas excees descendem de Exception, uma exceo de carter genrico. Exception prov uma string para a mensagem cuja exceo foi enviada pela RTL. Quando voc simplesmente utiliza TRY / EXCEPT / END como mostrado acima, voc perde um pouco do refinamento possvel no tratamento de uma exceo, isto , voc pode saber, num dado momento, qual o tipo de exceo que est ocorrendo, alertar o usurio sobre o tipo de erro que o mesmo est cometendo, ou que est acontecendo no sistema. E essa mensagem de alerta pode ser sensvel ao contexto da exceo (ser uma mensagem descritiva do problema e uma possvel soluo). Para tratar uma exceo como dito acima, devemos conhecer os tipos de exceo enviadas por RTL: 1. 2. 3. 4. 5. 6. 7. E/S Heap Matemtica Inteira Matemtica de Ponto-Flutuante Tipos Incompatveis Converso Hardware

1) E / S (Entrada / Sada - ou I / O - Input / Output) Ocorrre por exemplo quando se tenta acessar um arquivo ou um dispositivo de sada. - EIntOutError: contm uma propriedade denominada ErrorCode que indica qual o tipo de erro ocorrido 2) Heap Ocorre quando se tenta alocar ou acessar memria dinmica. - EOutOfMemory: indica que no h espao suficiente no Heap (memria global, onde so alocadas as variveis dinmicas) para completar a operao requisitada. - EInvalidPointer: indica que a aplicao tentou dispor de um ponteiro que est fora do Heap. Geralmente este ponteiro j sofreu um comando Dispose. 3) Matemtica Inteira (EIntError) - EDivByZero: diviso por zero - ERangeError: nmero ou expresso fora do limite (vide no Help online do Delphi, a diretiva de compilao {$R} - coloque o cursor sobre a letra R e pressione a tecla F1) - EIntOverflow: overflow numa operao inteira (por exemplo: o valor atribudo a uma varivel inteira extrapola o limite que ela pode conter)

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

109

4) Matemtica de Ponto-Flutuante (EMathError) - EZeroDivide: diviso por zero - EInvalidOp: operao invlida - EOverflow: overflow - EUnderFlow: underflow (o inverso do overflow) 5) Tipos Incompatveis - EInvalidCast: ocorre quando voc tenta ligar um objeto a um tipo diferente do dele com o operador AS. 6) Converso - EConvertError: ocorre quando voc tenta converter dados com as funes: IntToStr, StrToInt, StrToFloat etc. 7) Hardware (EFault) -EGPFault: General Protection Fault, geralmente causado por um ponteiro ou um objeto no inicializado. -EStackFault: acesso ilegal a um segmento da pilha -EPageFault: o gerenciador de memria do Windows no foi capaz de usar o arquivo de swap corretamente -EInvalidOpCode: instruo indefinida, como dado ou memria no inicializada. -EBreakPoint: interrupo por Breakpoint -ESingleStep: interrupo por passo simples Assim sendo, na diviso por zero da manipulao acima, poderamos utilizar um dos cdigos abaixo: Try Except trata a exceo End ; Try Except On Exception Try Try

Except Except On On EZeroDivide Do EMathError Do Do trata a exceo trata a exceo trata a exceo End ; End ; End ;

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

110

Vamos reescrever novamente a manipulao OnClick anterior: procedure TForm1.Button1Click(Sender: TObject); Var A , B , C : ^ Extended ; begin Try Try New (A) ; New (B) ; New (C) ; A^ := StrToFloat (Edit1.Text) ; B^ := StrToFloat (Edit2.Text) ; C^ := A^ / B^ ; Except On EZeroDivide Do begin ShowMessage ( ' O denominador no pode ser zero! ' ) ; C^ := -1 ; end ; End ; Finally Edit3.Text := FloatToStrF (C^ , ffFixed , 1 , 2) ; Dispose (A) ; Dispose (B) ; Dispose (C) ; End ; end; Execute a aplicao e repita os passos acima para a digitao de valores Feche a aplicao. Para que fique clara a explicao deste captulo, vamos refazer mais uma vez a manipulao OnClick anterior, alterando a parte de tratamento das excees (Except) com o cdigo abaixo: Except On EZeroDivide Do ShowMessage ( ' O denominador no pode ser zero! ' ) ; On EConvertError Do ShowMessage ( ' Operao Invlida! ' ) ; End ; Execute a aplicao Digite os valores: 10 e 2 e clique o boto Digite os valores: 10 e 0 e clique o boto. Veja a mensagem de erro. Digite no primeiro edit box o valor: 10 e no outro edit box algo que no seja um nmero (uma letra por exemplo). Veja a mensagem de erro. Feche a aplicao

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

111

Algumas vezes, voc necessitar enviar uma mensagem de erro mais tcnica ao usurio. Nestes casos, voc ir "instanciar" um objeto temporrio de exceo e utilizar a propriedade Messsage dele. Altere a manipulao de evento OnClick acima (somente o trecho de Except) com o cdigo: Except On E : Exception Do MessageDlg ( ' Aconteceu o seguinte erro: ' + Chr (13) + E.Message , mtError , [mbOK] , 0 ) ; End ; Execute a aplicao Digite os valores: 10 e 2 e clique o boto Digite os valores: 10 e 0 e clique o boto. Veja a mensagem de erro. Digite no primeiro edit box o valor: 10 e no outro edit box algo que no seja um nmero (uma letra por exemplo). Veja a mensagem de erro. Feche a aplicao Obs2.: Nunca destrua um objeto temporrio de exceo, pois a aplicao faz o mesmo, e neste caso ocorre um erro fatal. H casos em que voc ter que manipular de maneira especfica uma determinada exceo, e prever os casos em que outras excees possam ocorrer. Neste caso, voc pode utilizar a clusula ELSE, como mostrado abaixo: Except On E : EZeroDivide Do MessageDlg ( ' Aconteceu o seguinte erro: ' + Chr (13) + E.Message , mtError , [mbOK] , 0 ) ; Else ShowMessage ( ' Erro Ignorado ! ' ) ; End ; E nos casos em que voc precise parar uma operao sem enviar mensagem de erro (exceo silenciosa, como chamada), voc utilizar a procedure Abort , como mostrado abaixo: For i := 1 To 100 Do If i > StringGrid1.RowCount Then Abort Else begin

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

112

H tambm a possibilidade de voc gerar um erro em tempo de execuo, como por exemplo: procedure TForm1.Button1Click (Sender : Tobject) ; Var SenhaCorreta : String ; Begin SenhaCorreta := '123456' ; If Edit1.Text <> SenhaCorreta Then Raise ESenhaErrada.Create ( ' Senha Incorreta ' ) ; A palavra reservada Raise tem por funo "levantar" a exceo criada (Create) com a mensagem 'Senha Incorreta'. Note que, levantar uma exceo diferente de utilizar um comando If / Then, pois com esse comando no h interrupo do cdigo, o que ocorre com a exceo, e essa interrupo pode ser tratada com um dos blocos de proteo estudados acima. Obs3.: Para fazer este cdigo funcionar, voc tem que declarar ESenhaErrada como uma classe descendente da classe Exception (a declarao deve vir aps o end; da declarao de TForm1), como mostrado abaixo: unit Unit1; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm1 = class(TForm) Edit1: TEdit; private { Private declarations } public { Public declarations } end; ESenhaErrada = Class (Exception) ; var Form1: TForm1;

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

113

11. Listas de Strings Trabalha-se com listas de strings quando manipula-se: Itens de um ListBox ou ComboBox Linhas e um texto num Memo Lista de fontes suportadas pelo vdeo Linha ou coluna de um StringGrid Em tempo de execuo voc utiliza listas de strings para: Manipular strings Carregar e salvar strings Criar uma nova lista de strings

11.1. Manipulando strings a) Contando o nmero de strings: Comece uma nova aplicao Coloque um Label e altere seu caption para: Total de Fontes Coloque um Edit Box ao lado do Label e apague a sua propriedade Text Coloque um Button e manipule seu evento OnClick com: procedure TForm1.Button1Click (Sender : TObject) ; begin Edit1.Text := IntToStr ( Screen.Fonts.Count ) ; end; Execute a aplicao e d um clique no boto Feche a aplicao Como voc pode ver pelo Help online do Delphi, a propriedade Fonts do tipo TStrings, e tem a quantidade de strings na sua lista apontada pela propriedade Count. b) Acessando strings: Voc pode acessar cada string de uma lista atravs da propriedade Strings, especificando, entre colchetes, a posio onde a mesma encontra-se , observando que este ndice baseado em zero, ou seja, a posio da primeira string da lista igual a zero, e no, igual a um.

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

114

Comece uma nova aplicao Coloque um Memo, entre em Lines e apague a palavra Memo1 Coloque um Button e manipule seu evento OnClick com: procedure TForm1.Button1Click (Sender : TObject) ; Var i : Integer ; begin For i := 0 To Screen.Fonts.Count - 1 Do Memo1.Lines.Add ( Format ( '%d - %s ' , [ i+1 , Screen.Fonts.Strings [ i ] ] ) ) ; end; Execute a aplicao e d um clique no boto Feche a aplicao c) Determinar a posio da string

A funo IndexOf devolve um inteiro referente posio onde encontra-se a string desejada, que deve ser especificada por inteiro, pois IndexOf no procura trechos de strings. Caso a string no seja encontrada, IndexOf retorna o valor -1. Comece uma nova aplicao Coloque um Memo, entre em Lines e apague a palavra Memo1 Coloque dois Button e manipule os eventos OnClick deles com: procedure TForm1.Button1Click ( Sender: TObject ) ; Var i : Integer ; begin For i := 0 To Screen.Fonts.Count - 1 Do Memo1.Lines.Add ( Format ( ' %s ' , [ Screen.Fonts.Strings [ i ] ] ) ) ; end; procedure TForm1.Button2Click ( Sender: TObject ) ; begin Edit1.Text := IntToStr ( Memo1.Lines.IndexOf ( ' Symbol ' ) ) ; end; Obs1.: Como IndexOf exige que a string seja escrita por inteiro, no utilize espao em branco entre os apstrofes do parmetro da funo IndexOf ou da funo Format. Execute a aplicao e d um clique no boto

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

115

Feche a aplicao d) Adicionando uma string a uma lista i) Adicionando uma string S na posio P: Insert ( ( P - 1 ) , S ) . Lembre-se que a posio de uma lista baseada em zero. Por exemplo, para inserir a string 'Alo!' na posio 3 posio de uma lista, faa: Insert ( 2 , 'Alo!' ) . ii) Adicionando uma string S ao final da lista: Add ( S ) e Append ( S ) . Add uma funo que retorna a posio (baseada em zero) onde a string adicionada. A procedure Append faz o mesmo que Add sem retornar a posio. Comece uma nova aplicao Coloque um Label , dois Botes e um Memo no Form Apague a palavra Memo1 do componente Memo1 (propriedade Lines) Manipule o evento OnClick dos botes com: procedure TForm1.Button1Click ( Sender: TObject ) ; Var i : Integer ; begin For i := 0 To Screen.Fonts.Count - 1 Do Memo1.Lines.Add ( Format ( '%d - %s ' , [ i+1 , Screen.Fonts.Strings [ i ] ] ) ) ; end; procedure TForm1.Button2Click(Sender: TObject); begin Label1.Caption := IntToStr ( Memo1.Lines.Add ( ' Nenhuma ' ) ) ; end; Execute a aplicao D um clique em Button1 D um clique em Button2 Feche a aplicao

e)

Movendo uma string

Especifique o ndice corrente e o ndice destino. Por exemplo, para mover a 1 string para a 3 posio, faa: Move ( 0 , 2 ) Altere a manipulao OnClick de Button2 acima para: procedure TForm1.Button2Click(Sender: TObject);

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

116

f)

begin Memo1.Lines.Move ( 0 , 2 ) ; end; Execute a aplicao D um clique em Button1 D um clique em Memo1 e pressione Ctrl-Home (para ir ao incio da listagem) D um clique em Button2 D novo clique em Button2 Feche a aplicao

Apagando uma string

Passe para a procedure Delete a posio (baseada em zero) da string a apagar. Por exemplo, para apagar a terceira string de um Memo, faa: Delete ( 2 ). Outro exemplo, para apagar a fonte Arial (ou qualquer outra fonte que esteja instalada em seu sistema), faa: Comece uma nova aplicao Coloque um Memo, entre em Lines e apague a palavra Memo1 Coloque dois Button e manipule os eventos OnClick deles com: procedure TForm1.Button1Click ( Sender: TObject ) ; Var i : Integer ; begin For i := 0 To Screen.Fonts.Count - 1 Do Memo1.Lines.Add ( Format ( '%s' , [ Screen.Fonts.Strings [ i ] ] ) ) ; end;

procedure TForm1.Button2Click(Sender: TObject); begin With Memo1.Lines Do If IndexOf ( 'Arial' ) > -1 Then Delete ( IndexOf ( 'Arial' ) ) ; end; Obs2.: Como IndexOf exige que a string seja escrita por inteiro, no utilize espao em branco entre os apstrofes do parmetro da funo IndexOf ou da funo Format. Execute a aplicao

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

117

D um clique em Button1 D um clique em Memo1 e pressione Ctrl-Home (para ir ao incio da listagem) D um clique em Button2. A fonte Arial ( ou a fonte escolhida por voc apagada da listagem de Memo1) Feche a aplicao g) Copiando uma lista de strings para outra Comece uma nova aplicao Coloque um Memo, entre em Lines e apague a palavra Memo1 Coloque um ComboBox (aba Standard)

Apague a palavra ComboBox1 na propriedade Text

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

118

Coloque um Button e manipule o evento OnClick dele com: procedure TForm1.Button1Click ( Sender: TObject ) ; begin ComboBox1.Items := Memo1.Lines ; end;

Obs3.: Preste bem ateno: o plural de Item, em ingls, Items (com "m") e no Itens (com "n"). Execute a aplicao D um clique na seta preta de ComboBox1. Veja que no h qualquer item Digite em Memo1 o seguinte: vista (Dinheiro ou cheque) Carto de Crdito Carn D um clique em Button1 D novo clique em ComboBox1. A lista de strings de Memo1 foi copiada para a lista de strings de ComboBox1. Feche a aplicao Obs4.: D um clique no componente ComboBox1 e depois d um clique na propriedade Items. Como voc pode ver, esta propriedade tambm do tipo TSTrings. Assim, quando voc atribui propriedade Lines (do tipo TStrings) de Memo1 a propriedade Items (do tipo TStrings), voc est copiando todas as strings daquela propriedade para esta. h) Adicionando itens adicionais ao final de uma lista: Para adicionar uma lista de strings ao final de uma lista, utilize a procedure Adicione um segundo Boto ao Form Manipule seu evento OnClick com procedure TForm1.Button2Click(Sender: TObject); begin ComboBox1.Items.AddStrings ( Memo1.Lines ) ; end;

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

119

Execute a aplicao Digite em Memo1 o seguinte: vista (Dinheiro ou cheque) Carto de Crdito Carn D um clique em Button1 Agora, digite em Memo1 o seguinte (coloque 5 espaos em branco no incio de cada item): 30 dias 60 dias 90 dias D um clique em Button2 D novo clique em ComboBox1. A segunda lista de strings de Memo1 foi copiada para o final da lista de strings de ComboBox1. Feche a aplicao i) Manipulando item a item Altere a manipulao OnClick de Button1 acima com: procedure TForm1.Button1Click ( Sender: TObject ) ; Var i : Integer ; begin For i := 0 To Memo1.Lines.Count - 1 Do Memo1.Lines [ i ] := UpperCase ( Memo1.Lines [ 1 ] ) ; ComboBox1.Items := Memo1.Lines ; end; Execute a aplicao Digite em Memo1 o seguinte: vista (Dinheiro ou cheque) Carto de Crdito Carn D um clique em Button1 D novo clique em ComboBox1. Os itens de Memo1 foram convertidos para maiscula antes de serem copiados para a lista de strings de ComboBox1. Feche a aplicao

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

120

11.2. Carregando e salvando strings a) Carregando uma lista de strings de um arquivo: LoadFromFile ( 'Nome_do_Arquivo' ) b) Salvando uma lista de strings em um arquivo: SaveToFile ( 'Nome_do_Arquivo' ) Vamos fazer uma aplicao que faa o backup do arquivo Autoexec.bat, supondo existir este arquivo no diretrio raiz do drive C: . Comece uma nova aplicao Coloque dois Botes e um Memo no Form Altere a propriedade WordWrap de Memo1 de True para False Manipule o evento OnClick dos botes com: procedure TForm1.Button1Click(Sender: TObject); begin Memo1.Clear ; Memo1.Lines.LoadFromFile ( 'C:\Autoexec.bat' ) ; end; procedure TForm1.Button2Click(Sender: TObject); begin Memo1.Lines.SaveToFile ( 'Meu Autoexec.bat' ) ; end; Execute a aplicao D um clique em Button1. Voc passa a visualizar o arquivo Autoexec.bat Altere algumas linhas de Memo1 D um clique em Button2. Voc salvou o arquivo modificado no diretrio corrente com o novo nome: Meu Autoexec.bat. Feche a aplicao Obs5.: Verifique no Windows Explorer que o arquivo: Meu Autoexec.bat encontra-se no diretrio corrente. Se voc estiver executando o projeto de dentro do Delphi, encontrar o arquivo Meu Autoexec.bat no diretrio onde gerado o arquivo executvel da sua aplicao: C:\Arquivos de Programas\Borland\Delphi 3\Bin .

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

121

Caso voc queira salvar o arquivo num diretrio diferente deste, basta especificar junto ao nome, o diretrio desejado, por exemplo: C:\Temp\Meu Autoexec.bat , faz com que o arquivo seja salvo no diretrio C:\Temp (caso exista, obviamente). 12. Janelas de Dilogo Comece uma nova aplicao Adicione um Memo e um PopupMenu ao Form

D um clique duplo em PopupMenu1 (ou um clique simples nas reticncias da sua propriedade Items) Altere o primeiro item de menu: - Caption: &Abrir - SortCut: Ctrl+A Altere o segundo item de menu: - Caption: &Salvar - SortCut: Ctrl+B Altere o terceiro item de menu: - Caption: Salvar &como ... Altere o quarto item de menu (lembre que o hfen o trao separador) : - Caption: Altere o quinto item de menu: - Caption: Sai&r Altere a propriedade PopupMenu de Form1 para PopupMenu1 Adicione ao Form um componente OpenDialog (Aba Dialogs)

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

122

Adicione ao Form um componente SaveDialog (Aba Dialogs) D um clique nas reticncias da propriedade Filter de OpenDialog1:

Aparecendo o Filter Editor, digite os filtros desejados, como abaixo:

D um clique no boto OK . Repita a operao acima para o componente SaveDialog1

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

123

Altere a propriedade Title de OpenDialog1 para Abrir Altere a propriedade Title de SaveDialog1 para Salvar como... Manipule o evento OnClick do item de menu Abrir com: procedure TForm1.Abrir1Click(Sender: TObject); begin Try If OpenDialog1.Execute Then Memo1.Lines.LoadFromFile (OpenDialog1.FileName) ; Except ShowMessage ('Erro ao carregar o arquivo!') ; End ; end; Manipule o evento OnClick do item de menu Salvar com: procedure TForm1.Salvar1Click(Sender: TObject); begin Try Memo1.Lines.SaveToFile (OpenDialog1.FileName) ; Except ShowMessage ('Erro ao salvar o arquivo!') ; End ; end; Manipule o evento OnClick do item de menu Salvar como... com: procedure TForm1.Salvarcomo1Click(Sender: TObject); begin Try If SaveDialog1.Execute Then Memo1.Lines.SaveToFile (SaveDialog1.FileName) ; Except ShowMessage ('Erro ao salvar o arquivo!') ; End ; end; Manipule o evento OnClick do item de menu Sair com: procedure TForm1.Sair1Click(Sender: TObject); begin Close ; end; Manipule o evento OnCloseQuery de Form1 com: procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean); begin

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

124

CanClose := MessageDlg ('Sair!',mtConfirmation,[mbYes,mbNo],0) = mrYes ; end; Execute a aplicao, d um clique com o boto direito do mouse Abra um arquivo, salve-o com nome diferente (Salvar como...) Feche a aplicao Obs1.: O parmetro CanClose tem por funo permitir o fechamento da janela (CanClose igual a True) ou no (CanClose igual a False). Sendo assim, o valor de retorno da funo MessageDlg quem vai decidir o fechamento da janela. Se esse valor de retorno for igual a mrYes, CanClose recebe True e a janela ento fechada; caso contrrio, CanClose recebe False e o fechamento cancelado. de se observar que, toda janela que est para ser fechada, gera um evento OnCloseQuery daquela janela. Obs2.: Caso voc queira, altere a propriedade DefaultExt de SaveDialog1 para txt, o que far com que os arquivos sejam salvos com essa extenso, caso voc no especifique extenso diferente. Para salvar o arquivo com extenso diferente de txt, selecione Todos os Arquivos (*.*) no combobox Salvar como tipo: e digite o nome do arquivo seguido da extenso desejado. Por exemplo, para salvar o arquivo hipottico C:\JANELAS DE DILOGO.TXT como C:\Delphi 3\JANELAS DE DILOGO.DAT faa como abaixo:

Obs3.: A manipulao do item de menu Salvar utiliza o FileName de OpenDialog1 pois supe-se que o usurio queira salvar o arquivo com o mesmo nome com o qual ele foi aberto. O que pode (e deve) ser feito aqui, desabilitar este item de menu

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

125

enquanto no tiver um arquivo carregado (para no salvar uma tela em branco num arquivo existente). Consulte a funo FileExists no Help online do Delphi. 13. Grficos H trs maneiras de se obter imagens grficas no Delphi: a. inserir desenhos em tempo de design b. cri-los em tempo de design c. cri-los em tempo de execuo Quando voc desenha, voc o faz por meio da propriedade CANVAS do objeto. O prprio Canvas um objeto, e possui quatro importantes propriedades: a. b. c. d. Pen : desenho de linhas Brush : preenchimento de desenhos Font : escrita de texto e escolha da fonte Array de pixels : representao da imagem

Voc deve ter em mente que, em um ambiente grfico, no existe sentido em se falar em caracteres pura e simplesmente, mas nos pixels que formam determinado caractere. Isto definido pela fonte, pelo seu tamanho, suas caractersticas (negrito, itlico, sublinhado, etc.). Por isso, toda a vez que voc estiver observando uma janela, raciocine que so pixels arranjados em diferentes cores o que voc, na verdade, tem. 13.1. Manipulando pixels a. Ler: Cada pixel corresponde a uma cor Comece uma nova aplicao Coloque um Edit Box e um boto no Form Manipule evento OnClick do boto com: procedure TForm1.Button1Click(Sender: TObject); begin Edit1.Font.Color := Canvas.Pixels [10,15] ; end ; Execute a aplicao Escreva algo em Edit1 e verifique a cor da fonte (clWindowText, que deve ser igual a preto) D um clique em Button1 e observe a nova cor da fonte (clBtnFace, que deve ser igual a cinza) Feche a aplicao.

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

126

Obs1.: Quando voc clica o boto, a cor da fonte de Edit1 alterada com a cor do pixel que est na posio: coluna = 10 e linha = 15. Aqui ns estamos utilizando a propriedade Canvas do Form. b. Escrever Comece uma nova aplicao Coloque um boto no Form Manipule evento OnClick do boto com: procedure TForm1.Button1Click(Sender: TObject); Var N : Integer ; begin Randomize ; For N := 1 To 10 Do Canvas.Pixels [ Random ( ClientWidth ) , Random ( ClientHeight ) ] := clRed ; end; Execute a aplicao D um clique em Button1 e observe a alterao da cor de vrios pixels na tela D vrios cliques no boto, maximize a janela e observe a rea sem "pontos vermelhos". D novos cliques no boto e observe. Feche a aplicao. Obs2.: A funo Random gera valores aleatrios entre 0 e um limite inteiro, tal que: X := Random ( Limite ) ; gera valores entre 0 e o Limite, ou seja: 0 X < Limite Caso no seja especificado um limite, o valor retornado por Random, um valor Real entre 0 e 1, ou seja: X := Random ; gera valores entre 0 e o 1, ou seja: 0X<1 Obs3.: A procedure Randomize inicializa o gerador de nmeros aleatrios.

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

127

Obs4.: ClientWidth o comprimento (em pixels) e ClientHeight a altura (em pixels) da rea do Form cliente, sendo essa rea a rea utilizvel dentro dos limites formados pela borda da janela.

13.2. Manipulando a caneta com Pen TPen descreve os atributos de uma caneta quando se desenha uma imagem em Canvas. a. Movendo a caneta com MoveTo Comece uma nova aplicao Coloque um boto no Form Manipule evento OnClick do boto com: procedure TForm1.Button1Click(Sender: TObject); begin Canvas.MoveTo ( 0 , 0 ) ; { 0 , 0 o canto superior esquerdo } end; Execute a aplicao D um clique em Button1 e observe que aparentemente nada acontece. Feche a aplicao. b. Desenhando uma linha com LineTo Comece uma nova aplicao Coloque um boto no Form Manipule evento OnClick do boto com: procedure TForm1.Button1Click(Sender: TObject); begin Canvas.MoveTo ( 0 , 0 ) ; Canvas.LineTo ( 300 , 80 ) ; end; Execute a aplicao D um clique em Button1 e observe a linha formada. Feche a aplicao. c. Desenhando vrias linhas com LineTo Comece uma nova aplicao Manipule evento OnMouseMove de Form1 com: procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X,

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

128

Y: Integer); begin Canvas.LineTo ( X , Y ) ; end; Execute a aplicao e veja que, para onde voc movimenta o mouse, uma linha contnua desenhada. Feche a aplicao. d. Configurando a caneta TPen tem 4 propriedades : - Color - Width - Style - Mode A cor da caneta pode ser qualquer cor vlida para o ambiente (vide a propriedade Color de Form1). A espessura da caneta deve ser um valor Integer maior ou igual a 1. O estilo da caneta pode ser um dos seguintes: psSolid: linha slida psDash: linha cheia de tracinhos psDot: linha cheia de pontinhos psDashDot:linha alternando tracinhos e pontinhos psDashDotDot: linha que alterna uma combinao dos estilos psDash e psDot psClear: linha transparente (nenhuma linha desenhada) psInsideFrame: linha slida, porm podendo utilizar uma cor no contida na tabela de cores vlidas para o ambiente

So vrios os modos possveis para a caneta, e que iro influenciar a cor da caneta. Abaixo so listados alguns desses modos: pmBlack: sempre preto pmWhite: sempre branco pmNop: sem caneta (No Pen) pmNot: cor inversa "cor de fundo" de Canvas pmCopy: cor especificada na propriedade Color pmNotCopy: cor inversa cor especificada na propriedade Color

Comece uma nova aplicao Coloque 6 RadioButton no Form, sem se preocupar em alinh-los, como mostrado abaixo (preste bem ateno nas posies dos componentes):

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

129

Selecione RadioButton1, RadioButton2 e RadioButton3 (um debaixo do outro, como mostrado acima). Obs5.: Para selecionar os trs componentes, mantenha a tecla Shift pressionada e d um clique em cada componente ou, ento, posicione o cursor do mouse numa posio prxima radioButton1 e, com o boto esquerdo do mouse pressionado, arraste-o em torno dos trs componentes, de tal forma que uma caixa pontilhada englobe os componentes. Clique sobre um deles com o boto direito do mouse e depois no item Align No groupbox Horizontal clique em Left sides No groupbox Vertical clique em Space equally Clique o boto OK. Verifique que os componentes esto agora alinhados D um clique no Form para cancelar a seleo dos componentes Selecione RadioButton4, RadioButton5 e RadioButton6 Repita a operao acima apenas para o alinhamento horizontal (Left sides), no se preocupando com o alinhamento vertical D um clique no Form para cancelar a seleo dos componentes Selecione RadioButton1 e RadioButton4 (que devem estar na mesma linha) Clique sobre um deles com o boto direito do mouse e depois no item Align No groupbox Vertical clique em Tops Clique em Ok Repita a operao acima para os demais, alinhando-os dois a dois pelo topo Altere os captions dos RadioButton para: RadioButton1: pmBlack RadioButton2: pmWhite RadioButton3: pmNop RadioButton4: pmNot RadioButton5: pmCopy

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

130

RadioButton6: pmNotCopy

Manipule o evento OnClick de cada um deles com: procedure TForm1.RadioButton1Click(Sender: TObject); begin Canvas.Pen.Mode := pmBlack ; end; procedure TForm1.RadioButton2Click(Sender: TObject); begin Canvas.Pen.Mode := pmWhite ; end; procedure TForm1.RadioButton3Click(Sender: TObject); begin Canvas.Pen.Mode := pmNop ; end; procedure TForm1.RadioButton4Click(Sender: TObject); begin Canvas.Pen.Mode := pmNot ; end; procedure TForm1.RadioButton5Click(Sender: TObject); begin Canvas.Pen.Mode := pmCopy ; end; procedure TForm1.RadioButton6Click(Sender: TObject); begin Canvas.Pen.Mode := pmNotCopy end; Manipule o evento OnActivate de Form1 com: procedure TForm1.FormActivate(Sender: TObject); begin Canvas.Pen.Style := psDash ; Canvas.Pen.Width := 5 ; Canvas.Pen.Color := clRed ; end; Manipule o evento OnMouseMove de Form1 com: procedure TForm1.FormMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); begin Canvas.LineTo ( X , Y ) ;

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

131

end; Execute a aplicao e movimente o mouse Clique num dos RadioButton (para alterar o modo da caneta) e movimente novamente o mouse. Experimente os outros modos da caneta Feche a aplicao. e. Desenhando retngulos com Rectangle Comece uma nova aplicao Coloque um boto no Form Manipule evento OnClick do boto com: procedure TForm1.Button1Click(Sender: TObject); begin Canvas.Rectangle ( 10 , 10 , ClientWidth Div 2 , ClientHeight Div 2 ) ; end; Execute a aplicao D um clique em Button1 e observe a formao do retngulo. Feche a aplicao. f. Desenhando retngulos de quinas arredondadas com RoundRect Comece uma nova aplicao Coloque um boto no Form Manipule evento OnClick do boto com: procedure TForm1.Button1Click(Sender: TObject); begin Canvas.RoundRect ( 10 , 10 , ClientWidth Div 2 , ClientHeight Div 2 , 50 , 50 ) ; end; Execute a aplicao D um clique em Button1 e observe a formao do novo retngulo. Feche a aplicao. Obs6.: O 5 e o 6 parmetros informam a RoundRect que "arredonde" as quinas como sees de um crculo com 50 pixels de dimetro. Experimente outros valores. g. Desenhando elipses com Ellipse Comece uma nova aplicao Coloque um boto no Form Manipule evento OnClick do boto com:

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

132

procedure TForm1.Button1Click(Sender: TObject); begin Canvas.Ellipse ( 10 , 10 , ClientWidth Div 2 , ClientHeight Div 2 ) ; end; Execute a aplicao D um clique em Button1 e observe a formao da elipse. Feche a aplicao. h. Desenhando polgonos com Polygon Comece uma nova aplicao Coloque um boto no Form Manipule evento OnClick do boto com: procedure TForm1.Button1Click(Sender: TObject); begin Canvas.Polygon ( [ Point ( 10 , 10 ) , Point ( 150 , 10 ) , Point ( 10 , 100 ) ] ) ; end; Execute a aplicao D um clique em Button1 e observe a formao do tringulo. Feche a aplicao. i. Desenhando grfico de pizza com Pie Comece uma nova aplicao Coloque um boto no Form Manipule evento OnClick do boto com: procedure TForm1.Button1Click(Sender: TObject); begin Canvas.Pie ( 10 , 10 , 200 , 200 , 61 , 3 , 200 , 61 ) ; end; Execute a aplicao D um clique em Button1 e observe a formao de uma "fatia gorda" da pizza. Feche a aplicao. Obs7.: Na verdade, se voc quiser montar um grfico de pizza, voc tem que mont-la fatia a fatia. A procedure Pie tem como argumentos: Canvas.Pie ( X1, Y1, X2, Y2, X3, Y3, X4, Y4 ) ; - X1, Y1, X2, Y2 : coordenadas do retngulo delimitador da elipse - X3, Y3, X4, Y4 : coordenadas das linhas que, cruzadas, definem o centro

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

133

da elipse j. Escrevendo no Form com TextOut Comece uma nova aplicao Coloque um boto no Form Manipule evento OnClick do boto com: procedure TForm1.Button1Click(Sender: TObject); begin Canvas.TextOut ( 10 , 10 , ' Alo Voc! ' ) ; end; Execute a aplicao D um clique em Button1 e observe a string 'Alo Voc!' escrita em Form1. Feche a aplicao. Obs8.: Canvas tem ainda muitas propriedades teis para a parte grfica. Pesquise mais no Help online do Delphi. 14. Classe e Objeto At o momento, voc j manipulou eventos, alterou propriedades e executou aes com a sua aplicao. Voc est manipulando caractersticas de um objeto. Vamos entender mais um pouco sobre isso. Quando voc est criando um programa, e voc quer armazenar um valor de salrio (com duas casas decimais), voc declara uma varivel do tipo real. Este tipo, real, permite a voc: somar subtrair dividir multiplicar imprimir os resultados com nenhuma, uma ou vrias casas decimais

E tudo o mais que um tipo real permita. Mas preste ateno: o tipo real permite isto, e somente isto. Voc no pode, por exemplo, criar uma linha de comando deste tipo: Real := 3.0 ; E por que no? Porque real um tipo que voc associa a uma varivel. A varivel, que for do tipo real, ela sim, poder receber um valor, como mostra abaixo: Var X : Real ; Begin X := 3.0 ;

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

134

Assim sendo, uma varivel serve para armazenar valores compatveis com o tipo utilizado na sua declarao, e esta varivel tem o conjunto de operaes restrito ao tipo especificado, ou seja, variveis do tipo string, digamos, no podem sofrer a operao de multiplicao, e assim por diante.

14.1. Classe Pode-se definir Classe como sendo uma estrutura que contm um nmero fixo de atributos, quais sejam: propriedades, campos e mtodos. Sua visibilidade deve ser global (no pode ser declarada em uma procedure). Isto significa dizer "a grosso modo" que Classe uma definio de caractersticas e comportamentos, semelhante idia do Tipo explicada acima. So vrias, entretanto, as diferenas entre Tipo e Classe, mas a maior delas que Tipo uma definio esttica e Classe pode ser alterada atravs do recurso de Herana. Com isso, uma Classe que seja criada por herana de outra, "herda" toda a estrutura da Classe Ancestral e, se necessrio, pode implementar novas caractersticas, fazendo-se diferente da Classe Ancestral. Ou seja: uma vez inventada uma Classe, no ser preciso reinventar a roda, pois essa Classe pode servir de Classe Bsica para outras. Por exemplo: toda a vez que voc comea uma aplicao, o Delphi cria a seguinte estrutura: type TForm1 = class(TForm) private { Private declarations } public { Public declarations } end; Ou seja, j existe uma Classe Ancestral denominada TForm que ser a Classe Bsica. Obs1.: O Delphi comea o nome de todas as classes com a letra T, pois para o Delphi uma Classe um tipo de dado (um tipo especial), e ns seguiremos essa notao. Ela possui, maneira resumida, o seguinte: Propriedades: Caption Color Height Width Name Menu

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

135

PopupMenu Visible Procedures e Functions: Fechamento (Close) Minimizao Maximizao Redimensionamento Arraste

Eventos: OnActivate OnClose OnCloseQuery OnMouseMove

Sendo assim, TForm1 possui tambm todas essas caractersticas, pois ela uma Classe Herdada da Classe TForm, atravs clusula Class, como mostrado abaixo: TForm1 = class ( TForm ) Por hiptese, vamos considerar que voc colocou no seu form (Form1) um componente Edit Box e um componente Label. Analise novamente o cdigo-fonte: type TForm1 = class(TForm) Edit1: TEdit; Label1: TLabel; private { Private declarations } public { Public declarations } end; Voc pode observar que, alm de todas as caractersticas citadas acima, TForm1 possui agora duas novas caractersticas que a diferencia da Classe Ancestral (TForm). E voc vai agregando tantas modificaes TForm1 quantas forem necessrias. E toda a vez que voc precisar comear uma aplicao ou, adicionar um novo Form ao projeto, a Classe Bsica TForm estar l para ser herdada, evitando que voc escreva cdigo-fonte para definir o bvio, como, por exemplo: uma janela deve ser retangular, deve ter as propriedade tais e tais, deve sofrer fechamento, etc. 14.2. Objeto Uma vez definida a Classe, para que voc possa manipular propriedades, rotinas e eventos, voc tem que instanciar a Classe, isto , voc tem que criar um Objeto dessa

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

136

Classe. A "grosso modo", um Objeto est para a sua Classe, como uma Varivel est para seu Tipo. Retorne ao cdigo-fonte anterior e veja a clusula: var Form1: TForm1; Neste trecho de cdigo, foi criado o Objeto Form1 da Classe TForm1. Relembrando o incio do captulo, voc viu que no se pode realizar a operao: Real := 3.0 ; porque real um tipo que voc associa a uma varivel. Mas o cdigo abaixo vlido: Var X : Real ; Begin X := 3.0 ; Analogamente, o cdigo abaixo um cdigo invlido: TForm1.Color := clBlue ; pois TForm1 uma classe que voc associa a um objeto. J o cdigo abaixo vlido: Form1.Color := clBlue ; pois o objeto Form1 "existe" em tempo de execuo e se comporta de acordo com as caractersticas definidas pela sua Classe (Form1 um objeto da classe TForm1). 14.3. Mtodo Uma Classe tem uma estrutura muito parecida com um registro, mas a maior diferena entre os dois tipos, que uma Classe alm de definir campos, pode definir, tambm, sub-rotinas (procedures e/ou functions) que atuem sobre esses campos. Aos campos damos o nome de Propriedades e s rotinas damos o nome de Mtodo. Assim sendo, quando voc utiliza a rotina Close para fechar Form1, voc est utilizando, na verdade, o mtodo Close de Form1. Por exemplo, executar o comando: Close ; equivale a utilizar: Form1.Close ; Por que ambas as verses? Porque se voc no especificar o objeto "proprietrio" do mtodo, o Delphi assume como objeto "proprietrio" o Form declarado na Unit sendo editada (neste caso, Unit1 e, por conseqncia, Form1).

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

137

Isto significa dizer que, um mtodo age sobre as propriedades pertencentes ao seu objeto, somente, sendo especfico a ele, quer dizer, um mtodo Clear de Edit1 apagar somente o campo Text de Edit1, no realizando qualquer operao sobre o campo Text de Edit2, ou sobre qualquer outra propriedade de qualquer outro objeto. Esta caracterstica til para que voc possa realizar certas operaes apenas em dados que so preparados para receb-las. Vamos supor que voc est desenvolvendo um sistema comercial, que necessita de um mdulo contbil, que embuta, entre outras tarefas, o clculo mensal da folha de pagamentos. Geralmente, o que ns temos uma firma que comercializa determinada gama de produtos, e que em funo da apurao mensal das vendas, calcula o salrio de parte dos funcionrios (geralmente vendedores). J a gerncia ganha um adicional de gratificao de chefia, calculado em cima de um salrio bsico (salrio do pessoal administrativo) ou de um salrio fixo e mais adicionais. Os demais, ganham somente o salrio bsico, sem gratificaes ou adicionais. Outra observao a ser feita, que a matrcula dos funcionrios so calculadas pelo seu nmero de entrada, consistindo de 3 dgitos numricos, e um 4 dgito, calculado pelo resto da diviso por 10 da soma dos 3 primeiros dgitos. As regras explicadas acima so, ento: Administrativo: clculo simples, igual a um padro de 100 valores monetrios Gerncia: inicialmente igual ao administrativo, porm ganha n % sobre esse valor, sendo n varivel a cada ms - Vendas: inicialmente igual ao administrativo, porm ganha adicional de 25% sobre as vendas efetuadas individualmente Comece uma nova aplicao Clique em File - New Selecione Unit e d um clique em OK -

Aparece o seguinte cabealho: unit Unit2;

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

138

interface implementation end. Clique em File - Save All Digite: uExemplo_de_Classe quando aparecer o quadro: Save Unit1 As

e clique o boto Salvar, para salvar Unit1 com o novo nome. S al ve a Unit2 com o nome: uClasses Salve o projeto (Project1) com o nome: pExemplo_de_Classe Na unit uClasses, voc deve declarar as classes definidas anteriormente, abaixo da clusula Interface: unit uClasses; interface type TFuncionario = Class (TObject) private FNome : String ; FMat : String ; FSalario : Extended ; function Confere_Matricula ( Const M : String ) : Boolean ; function GetMat : String ; procedure SetMat ( Const Value : String ) ; public property Nome : String Read FNome Write FNome ; property Matricula : String Read GetMat Write SetMat ;

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

139

property Salario end ;

: Extended Read FSalario Write FSalario ;

TAdministrativo = Class (TFuncionario) private public procedure Calcula_Salario ; end ; TGerencia = Class (TFuncionario) private FAdicional : Extended ; public property Adicional : Extended Read FAdicional Write FAdicional ; procedure Calcula_Salario ; end ; TVenda = Class (TFuncionario) private public procedure Calcula_Salario ( Vendas_Efetuadas : Extended ) ; end ;

implementation function TFuncionario.Confere_Matricula ( Const M : STring ): Boolean ; Var Dv, i : Integer ; begin Dv := 0 ; For i := 1 To 3 Do Dv := Dv + StrToInt ( M [ i ] ) ; Dv := Dv Mod 10 ; Result := M [ 4 ] = IntToStr ( Dv ) ; end ; function TFuncionario.GetMat : String ; begin Result := FMat ; end ; procedure TFuncionario.SetMat ( Const Value : String ) ; begin If Confere_Matricula ( Value ) Then FMat := Value

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

140

Else begin ShowMessage ( 'Matrcula Invlida! ' ) ; FSalario := -1 ; FMat := '' ; end ; end ; procedure TAdministrativo.Calcula_Salario ; begin FSalario := FSalario ; end ; procedure TGerencia.Calcula_Salario ; begin FSalario := FSalario * ( 1 + fAdicional / 100 ) ; end ; procedure TVenda.Calcula_Salario ( Vendas_Efetuadas : Extended ) ; begin FSalario := FSalario + Vendas_Efetuadas * 0.25 ; end ; end.

Retorne ao Form1 Coloque, nele, os componentes abaixo, com as respectivas alteraes: - Form1: - Label1: - Edit1: - Label2: - Edit2: - Label3: - Edit3: - Label4: - Edit4: - Label5: Caption: Exemplo de uso de classes Name: fmClasses Caption: Nome do empregado Text: deixar em branco CharCase: ecUpperCase Name: edbNome Caption: Matrcula Text: deixar em branco Name: edbMatricula Caption: Salrio-Base ( R$ ) Text: deixar em branco Name: edbSal_Base Caption: deixar em branco Text: deixar em branco Name: edbProdutividade Visible: False Caption: Salrio ( R$ )

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

141

- Edit5:

Text: deixar em branco Name: edbSalario

- RadioButton1: Caption : Administrativo Name: rbAdm - RadioButton2: Caption : Gerncia Name: rbGer - RadioButton3: Caption : Vendas Name: rbVen - Button1: Caption: Salrio O Form deve estar parecido com:

Manipule OnClick rbAdm com: procedure TfmClasses.rbAdmClick(Sender: TObject); begin If Sender = rbAdm Then begin Label4.Caption := '' ; edbProdutividade.Visible := False ; end Else begin edbProdutividade.Visible := True ; If Sender = rbGer Then Label4.Caption := 'Adicional ( % ) ' Else If Sender = rbVen Then Label4.Caption := 'Vendas Efetuadas ( R$ ) ' end ; end;

o evento de

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

142

D um clique na setinha preta da manipulao OnClick de rbGer e, logo em seguida, d um clique na manipulao de evento rbAdmClick

Repita a mesma operao para rbVen nipule o evento OnClick de Button1 com:

Ma

procedure TfmClasses.Button1Click(Sender: TObject); Var Admin : TAdministrativo ; Ger : TGerencia ; Ven : TVenda ; VEfet : Extended ; begin If rbAdm.Checked Then begin Try Admin := TAdministrativo.Create ; Admin.Nome := edbNome.Text ; Admin.Matricula := edbMatricula.Text ; Admin.Salario := StrToFloat ( edbSal_Base.Text ) ; Admin.Calcula_Salario ; edbSalario.Text := Format (' %1.2f ' , [ Admin.Salario ] ) ; Finally Admin.Free ; End ; end Else

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

143

If rbGer.Checked Then begin Try Ger := TGerencia.Create ; Ger.Nome := edbNome.Text ; Ger.Matricula := edbMatricula.Text ; Ger.Salario := StrToFloat ( edbSal_Base.Text ) ; Ger.Adicional := StrToFloat ( edbProdutividade.Text ) ; Ger.Calcula_Salario ; edbSalario.Text := Format (' %1.2f ' , [ Ger.Salario ] ) ; Finally Ger.Free ; End ; end Else If rbVen.Checked Then begin Try Ven := TVenda.Create ; Ven.Nome := edbNome.Text ; Ven.Matricula := edbMatricula.Text ; Ven.Salario := StrToFloat ( edbSal_Base.Text ) ; VEfet := StrToFloat ( edbProdutividade.Text ) ; Ven.Calcula_Salario ( VEfet ) ; edbSalario.Text := Format (' %1.2f ' , [ Ven.Salario ] ) ; Finally Ven.Free ; End ; end ; end ;

Abaixo da clusula Implementation da unit uExemplo_de_classe, digite: uses uClasses ; Execute a aplicao Acontece um erro de compilao na linha que contm a funo IntToStr. D um clique sobre a funo e de um toque na tecla F1 (invocando o Help online do Delphi). Veja que esta funo est na unit SysUtils e para utiliz-la, voc deve digitar: uses SysUtils ; abaixo da clusula Implementation . Execute novamente a aplicao Novo erro de compilao, agora na procedure ShowMessage que, pelo Help online voc verifica estar na unit Dialogs. Altere a clusula uses acima para adicionar a unit Dialogs .

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

144

Obs1.: Neste ponto, deveremos ter a clasula uses igual a: implementation uses SysUtils , Dialogs ; Digite seu nome e a matrcula 1236 (1+2+3 = 6 ; o resto da diviso de 6 por 10 igual a 6) Digite 100 no campo Salrio-base Clique no radiobutton Administrativo Clique o boto e observe que aparece o valor 100,00 no campo Salrio Clique agora o radiobutton Gerncia Digite o valor 200 no campo Adicional Clique o boto Salrio e observe o valor que aparece: 300,00, pois 100,00 aumentado 200% igual a 300,00 . Clique agora o radiobutton Vendas Clique o boto Salrio e observe agora o novo valor do campo Salrio: 150,00 pois 25% de 200,00 (contedo do campo Vendas Efetuadas) igual a 50,00 que somados aos 100,00 de Salrio-Base perfazem 150,00. Altere agora a matrcula para 1234 Clique o boto Salrio. Observe que aps o clique no boto da janela com a mensagem de erro efetuado o clculo normal do salrio (operao que deveria ser interrompida com uma entrada invlida de matrcula) Feche a aplicao Vamos comentar o cdigo-fonte desde o incio. a. Definindo a classe bsica (ancestral de todas as outras, pois independente do cargo ocupado pelo empregado: administrativo, gerncia ou venda, ele um funcionrio da firma, e possui pelo menos: nome, matrcula e salrio). TFuncionario = Class (TObject) private FNome : String ; FMat : String ; FSalario : Extended ; function Confere_Matricula ( Const M : String ) : Boolean ; function GetMat : String ; procedure SetMat ( Const Value : String ) ; public property Nome : String Read FNome Write FNome ; property Matricula : String Read GetMat Write SetMat ; property Salario : Extended Read FSalario Write FSalario ; end ; Podemos ver que define-se uma propriedade pela palavra reservada property seguido do nome e de duas clusulas: Read , que dever ser seguida de um nome de

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

145

varivel de manipulao (a qual chamada de campo) de atribuio propriedade ou de uma funo de entrada, seguido da clusula Write , que dever ser seguida de um nome de varivel de manipulao (tambm chamada de campo) de leitura do contedo da propriedade ou de uma procedure de sada. Propriedades so declaradas na seo public, pois supe-se querer utilizar essas propriedades fora do escopo da unit declaradora da classe. A propriedade em si, no manipulvel nesta parte, e por isso se faz necessrio utilizar campos para ler / escrever valores na / da propriedade. E esses campos devero ter o mesmo tipo da propriedade, sendo declarados na seo private da classe, pois somente a classe ancestral, e seus descendentes, podero visualizar e manipular os campos. Outras units somente tero acesso propriedade do objeto que ser instanciado. Tudo que declarado na seo private no visvel fora do escopo da unit declaradora da classe. Por conveno, o nome do campo (Field, em ingls) inicia pela letra F seguido do nome da propriedade. Assim, o campo FNome manipula os valores da propriedade Nome, bem como, FMat manipula os valores da propriedade Matricula. Quando utilizar um campo para manipular o valor da propriedade diretamente, e quando utilizar uma sub-rotina para manipular esse valor? Quando voc for simplesmente manipular o valor da propriedade, utilize o campo, ao invs de declarar uma sub-rotina. Porm, se voc tiver que realizar a verificao da consistncia do valor sendo entrado (por exemplo, a verificao da matrcula), utilize a sub-rotina. obvio que voc, independente de ter ou no que verificar a consistncia do valor atribudo propriedade, pode utilizar a sub-rotina para entrada e sada desse valor. No exemplo acima, GetMat e SetMat tero por funo manipular o valor de FMat que o valor associado propriedade Matricula. Observe que, tanto o campo FMat como os cabealhos das sub-rotinas (GetMat e SetMat) so declarados na seo private, pois outras units devem ter acesso propriedade, no implementao interna do que faz GetMat ou SetMat, caso contrrio, algum pode burlar o sistema de segurana e inventar uma senha falsa. Por isso, o desenvolvedor pode atribuir o valor do edit box edbMatricula propriedade Matricula, mas no tem acesso ao clculo interno para saber se a matrcula ou no verdadeira. Pelo mesmo motivo, a funo Confere_Matricula tem seu cabealho declarado na seo private. Observe que o parmetro tem a clusula Const precedendo o nome do parmetro. Isto foi feito, porque o parmetro no precisa ser alterado e, por isso, a utilizao de um parmetro Const faz com que o processamento seja muito mais veloz do que se tivssemos utilizado a clusula. b. Definindo a classe descendente: TAdministrativo TAdministrativo = Class (TFuncionario) private public procedure Calcula_Salario ; end ; Aqui, somente declaramos o mtodo que ir computar o salrio do funcionrio, pois as propriedades requeridas por esta classe j foram definidas em TFuncionario. c. Definindo a classe descendente: TGerencia

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

146

TGerencia = Class (TFuncionario) private FAdicional : Extended ; public property Adicional : Extended Read FAdicional Write FAdicional ; procedure Calcula_Salario ; end ; Esta classe, TGerencia, alm das propriedades herdadas de TFuncionario, declara tambm a propriedade Adicional, alm do mtodo Calcula_Salario, que ir computar o salrio da gerncia, utilizando metodologia diferente da metodologia utilizada pela classe TAdministrativo. d. Definindo a classe descendente: TVenda TVenda = Class (TFuncionario) private public procedure Calcula_Salario ( Vendas_Efetuadas : Extended ) ; end ; Vemos aqui, uma modificao do mtodo Calcula_Salario que, ao invs de trabalhar com uma propriedade, utiliza um parmetro para a implementao do mtodo. O ideal que voc trabalhe de maneira padronizada, utilizando somente um modelo de programao, ou seja, se voc declarou o mtodo de um jeito, utilize o mesmo jeito para outras classes que implementem o mtodo com o mesmo nome. e. Implementando os mtodos: a seo Implementation A seo Interface, como o nome diz, serve de interface para outras units e aplicaes, sendo uma rea considerada global pelo projeto. E, por isso, a classe deve ser declarada nessa seo. pois uma classe no pode ter escopo local, e sim, global. J a seo Implementation serve para implementar cdigo-fonte visvel apenas localmente (invisvel para as outras units), quais sejam mtodos ou sub-rotinas (no necessariamente atreladas a uma classe). Cada mtodo deve ser implementado utilizando cabealho idntico ao contido na declarao da classe, com a adio do nome da classe ao nome do mtodo, separados pelo caractere ponto ( . ), como mostrado abaixo: function TFuncionario.Confere_Matricula ( Const M : STring ): Boolean ; Observe novamente o uso da clusula Const antecedendo o nome do parmetro, fazendo com que a performance do mtodo seja melhorado em termos de velocidade. A implementao do mtodo TFuncionario.Confere_Matricula muito simples, pois ele nada mais faz do que somar os trs primeiros dgitos da matrcula e comparar o resto da diviso desta soma por 10 com o quarto caractere da matrcula (que na funo

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

147

chamada de dgito verificador: Dv), e se eles foram diferentes, retornar o valor booleano False, caso contrrio, True: function TFuncionario.Confere_Matricula ( Const M : STring ): Boolean ; Var Dv, i : Integer ; begin Dv := 0 ; For i := 1 To 3 Do Dv := Dv + StrToInt ( M [ i ] ) ; Dv := Dv Mod 10 ; Result := M [ 4 ] = IntToStr ( Dv ) ; end ; J o mtodo TFuncionario.GetMat simplesmente atribui propriedade Matricula o contedo do campo FMat . Mtodos que so declarados na seo Read da clusula property utilizam, por notao, a palavra Get seguido do nome da propriedade: function TFuncionario.GetMat : String ; begin Result := FMat ; end ; O mtodo SetMat o oposto do mtodo GetMat, pois sua funo atribuir ao campo de manipulao do contedo da propriedade. Por notao, seu nome inicia pela palavra Set seguido do nome da propriedade: procedure TFuncionario.SetMat ( Const Value : String ) ; begin If Confere_Matricula ( Value ) Then FMat := Value Else begin ShowMessage ( ' Matrcula Invlida! ' ) ; FSalario := -1 ; FMat := '' ; end ; end ; Aqui voc pode ver a utilizao do mtodo Confere_Matricula, impedindo o usurio de digitar um valor invlido de matrcula. Neste ponto, lembramos que o cdigo produziu o salrio normalmente, independente de a matrcula estar ou no correta, o que convenhamos no pode ocorrer. Altere o bloco do Else de: Else begin

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

148

ShowMessage ( ' Matrcula Invlida! ' ) ; FSalario := -1 ; FMat := '' ; end ; para: Else Raise Erro.Create ( ' Matrcula Invlida! ' ) ; Neste caso, acontecer um erro em tempo de execuo, e o processamento terminar. Execute novamente a aplicao Acontece o erro de compilao: Undeclared identifier , alertando para o fato que voc no declarou a varivel de exceo. Como visto acima, tente alterar o cabealho da procedure para: procedure TFuncionario.SetMat ( Const Value : String ) ; type Erro = class ( Exception ) ; begin If Confere_Matricula ( Value ) Then FMat := Value Else Raise Erro.Create ( ' Matrcula Invlida! ' ) ; end ; Execute novamente a aplicao. Veja o novo erro do compilador. Isto significa que voc no pode declarar uma classe com escopo local. Classes devem ser declaradas na seo Interface da unit. Assim sendo, retire as linhas de declarao da classe da seo de declarao de tipos locais procedure, fazendo com que a mesma fique igual a: procedure TFuncionario.SetMat ( Const Value : String ) ; begin If Confere_Matricula ( Value ) Then FMat := Value Else Raise Erro.Create ( ' Matrcula Invlida! ' ) ; end ; e reescreva essas linhas abaixo da clusula type na seo Interface (acima da declarao da classe TFuncionario), como mostrado abaixo: interface type Erro = class ( Exception ) ; TFuncionario = Class (TObject)

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

149

private Execute novamente a aplicao Acontece novamente o erro de compilao: Undeclared identifier , desta vez porque voc no declarou a unit que contm a definio da classe ancestral Exception. Pelo Help online do delphi, podemos ver que a unit responsvel por Exception SysUtils. Escreva, ento, logo aps a clusula Interface, a linha de comando: uses SysUtils ; e tente nova compilao. Acontece ento o erro de compilao: Identifier redeclared, sugerindo o fato de voc j ter declarado um identificador (varivel, tipo, constante, units, etc.) e estar tentando declarar alguma outra coisa com o mesmo nome da primeira. E isto acontece, porque voc j declarou a unit SysUtils na clusula uses da rea de Implementation, no podendo haver declarao da mesma unit na rea de Interface: interface uses SysUtils ; e implementation uses SysUtils , Dialogs ; Altere a clusula uses da seo Implementation para: implementation uses Dialogs ; e deixe a clusula uses de Interface do jeito que ela est, pois o que declarado em Interface (rea global) visto por toda a unit (isto significa que IntToStr poder ser utilizada na seo Implementation normalmente, pois as rotinas da unit SysUtils sero visveis por toda a unit, tanto da rea global - Interface - como da rea local - Implementation). Execute novamente a aplicao Digite a matrcula 1234 e observe que, aps o aviso de erro, nada mais processado. Feche a aplicao Continuando a explicao inicial, o mtodo TAdministrativo.Calcula_Salario no realiza clculo algum, atribuindo ao campo FSalario (que manipula o contedo da propriedade Salario) o mesmo valor do campo. Mas por que? Porque, apesar de no haver clculo, pode ser que no futuro venha a ter, e isso facilitar sobremaneira o

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

150

clculo. Alm disso, o programador deixa de se preocupar como calculado o salrio do pessoal administrativo, e se por ventura alguma modificao tiver que ser feita, s ser no mtodo abaixo: procedure TAdministrativo.Calcula_Salario ; begin FSalario := FSalario ; end ; O pessoal da gerncia utiliza o salrio-base como piso de clculo e, em cima este salrio, acresce-se n % de adicional: procedure TGerencia.Calcula_Salario ; begin FSalario := FSalario * ( 1 + fAdicional / 100 ) ; end ; E o pessoal de vendas, ganha porcentagem (25%) de comisso: procedure TVenda.Calcula_Salario ( Vendas_Efetuadas : Extended ) ; begin FSalario := FSalario + Vendas_Efetuadas * 0.25 ; end ; f. Simplificando a manipulao de eventos Voc deve estar lembrado que ns utilizamos como base a manipulao de evento OnClick de rbAdm para os radiobutton rbGer e rbVen. O que o cdigo faz, evitar que voc tenha que escrever cdigo espalhado por vrias manipulaes, evitando que uma mudana de cdigo-fonte nas vrias manipulaes envolvidas, demande um grande trabalho de clique de mouse e digitao. O uso do parmetro Sender aqui, para que o cdigo a ser manipulado dependa do objeto que est sofrendo a manipulao: procedure TfmClasses.rbAdmClick(Sender: TObject); begin If Sender = rbAdm Then begin Label2.Caption := '' ; edbProdutividade.Visible := False ; end Else begin edbProdutividade.Visible := True ; If Sender = rbGer Then Label2.Caption := 'Adicional ( % ) ' Else If Sender = rbVen Then

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

151

Label2.Caption := 'Vendas Efetuadas ( R$ ) ' end ; end; g. Utilizando as classes em outras units Esta a hora de verificar se o que voc declarou, produz resultados satisfatrios: a hora de instanciar o objeto. Note que, o objeto declarado como sendo de uma determinada classe, mas s existe (memria s alocada para ele) quando voc invoca o mtodo Create (esse mtodo herdado de TObject). Uma vez criado o objeto, voc pode utilizar procedure TfmClasses.Button1Click(Sender: TObject); Var Admin : TAdministrativo ; Ger : TGerencia ; Ven : TVenda ; VEfet : Extended ; begin If rbAdm.Checked Then begin Try Admin := TAdministrativo.Create ; Aps utilizar o objeto, voc deve desaloc-lo da memria (sim, objetos so ponteiros de memria, que voc cria em tempo de execuo, e destri tambm em tempo de execuo). Utilize, para isso, o mtodo Free (no utilize o mtodo Destroy, pois se o ponteiro estiver apontando para Nil, haver um erro em tempo de execuo, e seu sistema "desabar") : procedure TfmClasses.Button1Click(Sender: TObject); Var Admin : TAdministrativo ; Ger : TGerencia ; Ven : TVenda ; VEfet : Extended ; begin If rbAdm.Checked Then begin Try Admin := TAdministrativo.Create ; Admin.Nome := edbNome.Text ; Admin.Matricula := edbMatricula.Text ; Admin.Salario := StrToFloat ( edbSal_Base.Text ) ; Admin.Calcula_Salario ; edbSalario.Text := Format (' %1.2f ' , [ Admin.Salario ] ) ; Finally Admin.Free ;

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

152

End ; end Else If rbGer.Checked Then Cdigo semelhante utilizado para instanciar o objeto Ger e o objeto Ven.

h. Cdigo-fonte completo: h1. Unit uClasses:


unit uClasses ; interface uses SysUtils ; type Erro = class ( Exception ) ; TFuncionario = Class ( TObject ) private fNome : String ; fMat : String ; fSalario : Extended ; function Confere_Matricula ( Const M : String ) : Boolean ; function GetMat : String ; procedure SetMat ( Const Value : String ) ; public property Nome : String Read fNome Write fNome ; property Matricula : String Read GetMat Write SetMat ; property Salario : Extended Read fSalario Write fSalario ; end ; TAdministrativo = Class ( TFuncionario ) private public procedure Calcula_Salario ; end ; TGerencia = Class ( TFuncionario ) private fAdicional : Extended ; public property Adicional : Extended Read fAdicional Write fAdicional ; procedure Calcula_Salario ; end ;

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

153

TVenda = Class (TFuncionario) private public procedure Calcula_Salario ( Vendas_Efetuadas : Extended ) ; end ; implementation uses Dialogs ; function TFuncionario.Confere_Matricula ( Const M : STring ) : Boolean ; Var Dv, i : Integer ; begin Dv := 0 ; For i := 1 To 3 Do Dv := Dv + StrToInt ( M [ i ] ) ; Dv := Dv Mod 10 ; Result := M [ 4 ] = IntToStr ( Dv ) ; end ; function TFuncionario.GetMat : String ; begin Result := fMat ; end ; procedure TFuncionario.SetMat ( Const Value : String ) ; begin If Confere_Matricula ( Value ) Then FMat := Value Else Raise Erro.Create ( ' Matrcula Invlida! ' ) ; end ; procedure TAdministrativo.Calcula_Salario ; begin fSalario := fSalario ; end ; procedure TGerencia.Calcula_Salario ; begin fSalario := fSalario * ( 1 + fAdicional / 100 ) ; end ; procedure TVenda.Calcula_Salario ( Vendas_Efetuadas : Extended ) ; begin fSalario := fSalario + Vendas_Efetuadas * 0.25 ; end ; end .

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

154

h2. Unit uExemplo_de_classe:


unit uExemplo_de_Classe; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls ; type TfmClasses = class (TForm) edbNome: TEdit; edbMatricula: TEdit; rbAdm: TRadioButton; rbGer: TRadioButton; rbVen: TRadioButton; Label1: TLabel; Label2: TLabel; Label3: TLabel; edbSal_Base: TEdit; Button1: TButton; edbProdutividade: TEdit; edbSalario: TEdit; Label4: TLabel; Label5: TLabel; procedure Button1Click(Sender: TObject); procedure rbAdmClick(Sender: TObject); private { Private declarations } public { Public declarations } end; var fmClasses: TfmClasses; implementation uses uClasses ; {$R *.DFM} procedure TfmClasses.Button1Click(Sender: TObject); Var Admin : TAdministrativo ; Ger : TGerencia ; Ven : TVenda ; VEfet : Extended ; begin If rbAdm.Checked Then begin Try

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

155

Admin := TAdministrativo.Create ; Admin.Nome := edbNome.Text ; Admin.Matricula := edbMatricula.Text ; Admin.Salario := StrToFloat ( edbSal_Base.Text ) ; Admin.Calcula_Salario ; edbSalario.Text := Format (' %1.2f ' , [ Admin.Salario ] ) ; Finally Admin.Free ; End ; end Else If rbGer.Checked Then begin Try Ger := TGerencia.Create ; Ger.Nome := edbNome.Text ; Ger.Matricula := edbMatricula.Text ; Ger.Salario := StrToFloat ( edbSal_Base.Text ) ; Ger.Adicional := StrToFloat ( edbProdutividade.Text ) ; Ger.Calcula_Salario ; edbSalario.Text := Format (' %1.2f ' , [ Ger.Salario ] ) ; Finally Ger.Free ; End ; end Else If rbVen.Checked Then begin Try Ven := TVenda.Create ; Ven.Nome := edbNome.Text ; Ven.Matricula := edbMatricula.Text ; Ven.Salario := StrToFloat ( edbSal_Base.Text ) ; VEfet := StrToFloat ( edbProdutividade.Text ) ; Ven.Calcula_Salario ( VEfet ) ; edbSalario.Text := Format (' %1.2f ' , [ Ven.Salario ] ) ; Finally Ven.Free ; End ; end end; procedure TfmClasses.rbAdmClick(Sender: TObject); begin If Sender = rbAdm Then begin Label2.Caption := '' ; edbProdutividade.Visible := False ; end Else begin edbProdutividade.Visible := True ; If Sender = rbGer Then Label2.Caption := 'Adicional ( % ) '

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

156

Else If Sender = rbVen Then Label2.Caption := 'Vendas Efetuadas ( R$ ) ' end ; end; end.

h3. Projeto pExemplo_de_classe:


program pExemplo_de_Classe; uses Forms, uClasses in 'uClasses.pas', uExemplo_de_Classe in 'uExemplo_de_Classe.pas' {fmClasses}; {$R *.RES} begin Application.Initialize; Application.CreateForm(TfmClasses, fmClasses); Application.Run; end.

i. Distribuindo a unit: J lhe foi explicado que, os aplicativos construdos em Delphi, so compostos por um projeto (.DPR) e vrias units (.PAS). Uma unit pode ou no ser uma base de um form (voc construiu acima uma unit sem form: uClasses.PAS ; ela serviu apenas para declarar as classes). Quando voc compilou o programa, o Delphi gerou para voc um arquivo de nome: uClasses.DCU. Como mostra sua extenso: Delphi Compiled Unit , este arquivo o resultado da compilao de uClasse.PAS. este arquivo que voc entregar ao usurio (desenvolvedor). Na documentao voc deve explicar que, para utilizar a sua unit, o usurio (desenvolvedor) dever declarar na clusula uses o nome da sua unit: uses uClasses ; como voc fez no captulo anterior. Utilizando o Windows Explorer, voc pode ver que so vrios os arquivos envolvidos na confeco do aplicativo:

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

157

Arquivos temporrios: so aqueles que tm um til ( ~ ) como primeiro caractere da extenso, como: uExemplo_de_Classe. df . Estes arquivos, aps a concluso do projeto, podem ser apagados para livrar espao em disco. Arquivo executvel (Aplicativo): tem o mesmo nome do projeto, porm com extenso .EXE , como: pExemplo_de_Classe.exe. Units compiladas (Delphi Compiled Unit): so o cdigo-objeto (equivalente) do Delphi. Uma unit compilada tem extenso: .DCU , como: uClasses.dcu e o mesmo nome da unit que contm o cdigo-fonte (units Pascal). Podem ser distribudas comercialmente, permitindo ao usurio-desenvolvedor utilizar as rotinas por voc criadas, sem ter acesso ao cdigo-fonte. Bem como, permite o desenvolvimento de uma ou mais rotinas muito utilizadas em seus projetos, sem a necessidade de reescrever cdigo.
~

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

158

Arquivo de Definio de Formulrio (Delphi Form File): o arquivo que contm uma definio de tudo aquilo que o form contm: nome do form, componentes, manipulaes de evento, etc. Tem o mesmo nome da unit que contm o cdigo-fonte (unit Pascal), porm com extenso .DFM , como: uExemplo_de_Classe.dfm. Units (Delphi Pascal Unit): so os arquivos que contm o cdigo-fonte da unit. Tm extenso .PAS , como: uClasses.pas . O nome do arquivo o mesmo nome utilizado no cabealho unit no cdigo-fonte. Por exemplo, o arquivo uClasses.pas inicia pelo cabealho: unit uClasses; fazendo com que a distribuio seja facilitada, pois o usurio-desenvolvedor que utilizar a sua unit, poder faz-lo apenas declarando na clausula uses o nome do arquivo .DCU que ele obtiver. Projeto (Delphi Project File): o elo de ligao entre as vrias units que compe o projeto. Tem extenso .DPR , como: pExemplo_de_Classe.dpr , sendo esse nome utilizado para nomear o cdigo-executvel, alm de servir como caption para vrias janelas de dilogo (execute novamente o aplicativo desenvolvido no captulo anterior e digite uma matrcula invlida, 1234, por exemplo. Clique o boto e observe que a janela de dilogo traz em seu caption, o nome pExemplo_de_Classe. Arquivo de Recursos (Resources): o arquivo que contm as definies dos recursos utilizados pelo projeto, tais como: cones, bitmaps e cursores. Tem o mesmo nome do projeto, porm com a extenso: .RES , como: pExemplo_de_Classe.res. Arquivo de Opes do Projeto (Delphi Options File): um arquivo texto que contm as opes utilizadas pelo Delphi no gerenciamento do projeto. Tem o mesmo nome do projeto, porm com extenso .DOF, como: pExemplo_de_Classe.dof . Voc pode alterar esse arquivo de dentro do Delphi, clicando em Project - Options...

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

159

Na janela de opes, voc pode selecionar o form principal do seu projeto (main form), ou seja, o form que aparece inicialmente quando o aplicativo executado (no nosso caso, s temos um form, e por isso somente seu nome aparece: fmClasses):

Clicando na aba Application, voc pode configurar o cone do seu aplicativo:

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

160

Clicando na aba VersionInfo, voc pode introduzir informaes pessoais ao seu projeto. D um clique no checkbox Include version information in project :

Na chave (Key) Comments digite: Exemplo de utilizao de Classes no campo valor (Value). Clique o boto OK e recompile a aplicao. No Windows Explorer, v at a pasta que contm o aplicativo que voc acaba de produzir, e clique com o boto direito do mouse sobre o cone deste aplicativo. Clique no item Propriedades e depois clique na aba Verso. Veja que as informaes por voc alteradas, aparecem no quadro de informao da verso do aplicativo. Utilize o Help online do Delphi para maiores detalhes. 14.4. Mtodos estticos, virtuais e dinmicos - Polimorfismo

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

161

Mtodos que so simplesmente declarados em uma classe, so ditos estticos. Se uma classe declara um mtodo esttico e uma classe descendente declara o mesmo mtodo, o cdigo executado pode no ser o esperado, como ilustra o exemplo abaixo: Comece uma nova aplicao Altere a unit1 com o cdigo abaixo (no reescreva o cdigo em itlico):
unit Unit1; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm1 = class(TForm) Button1: TButton; procedure Button1Click(Sender: TObject); private { Private declarations } public { Public declarations } end;

TClasse1 = class (TObject) procedure Mostra ; end; TClasse2 = class (TClasse1) procedure Mostra ; end;
var Form1: TForm1; implementation {$R *.DFM}

procedure TClasse1.Mostra ; begin ShowMessage ( 'Mtodo da classe 1' ) ; end ; procedure TClasse2.Mostra ; begin ShowMessage ( 'Mtodo da classe 2' ) ; end ;
end.

Coloque um boto no form

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

162

Manipule o evento OnClick do boto com:


procedure TForm1.Button1Click(Sender: TObject);

Var Classe : TClasse1 ; begin Try Classe := TClasse1.Create ; Classe.Mostra ; Finally Classe.Free ; End ; Try Classe := TClasse2.Create ; Classe.Mostra ; Finally Classe.Free ; End ; end; Obs1.: Na declarao das classes TClasse1 e TClasse2 voc notou a ausncia das clusulas private e public. Isso significa dizer que, na ausncia dessas clusulas, o que est declarado tem escopo igual a "public". Obs2.: Como TClasse2 descendente de TClasse1, voc pode declarar uma varivel como sendo uma instncia de TClasse1 e instanci-la de TClasse2, como mostra o cdigo acima. Execute a aplicao Clique o boto e observe que as janelas de mensagem trazem como aviso: Mtodo da Classe1. Feche a aplicao O que ocorreu poderia ter sido evitado de duas maneiras: Utilizando uma varivel Classe1 para instanciar TClasse1 e uma varivel Classe2 para instanciar TClasse2. Utilizar override de mtodo

a. Variveis diferentes Para tanto, basta alterar a seo Var da manipulao OnClick de Button1para: Var Classe1 : TClasse1 ; Classe2 : TClasse2 ;

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

163

e instanciar cada classe com sua varivel, ou seja:


procedure TForm1.Button1Click(Sender: TObject);

Var Classe1 : TClasse1 ; Classe2 : TClasse2 ; begin Try Classe1 := TClasse1.Create ; Classe1.Mostra ; Finally Classe1.Free ; End ; Try Classe2 := TClasse2.Create ; Classe2.Mostra ; Finally Classe2.Free ; End ; end; b. Override de mtodo: Polimorfismo Outra soluo fazer override de mtodo. Para tanto, coloca-se aps a declarao do mtodo na classe ancestral, a diretiva virtual (ou dynamic). Na classe descendente, aps a declarao do mtodo, coloca-se a diretiva override, fazendo o que chamado de polimorfismo, isto , um mesmo mtodo comportando-se de maneira diferente dependendo da classe a qual ele pertence. Na seo interface da unit1, altere a declarao das classes com: TClasse1 = class (TObject) procedure Mostra ; virtual ; end; TClasse2 = class (TClasse1) procedure Mostra ; override ; end; Execute novamente a aplicao e observe que, agora, as janelas demensagem trazem os avisos corretos. Feche a aplicao. Obs3.: Mtodos virtual e dynamic so idnticos, a no ser pelo fato que, mtodos virtuais causam aumento no cdigo-executvel, ao passo que mtodos dinmicos causam um aumento no tempo de processamento. Em geral, mtodos virtuais so mais eficientes num "override"; porm, se a declarao da classe (ou das classes) envolver muitos mtodos virtuais, deve-se utilizar mtodos dinmicos.

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

164

Obs4.: H tambm a situao que, ao invs de substituir o mtodo da classe ascendente, o mtodo da classe descendente tem que executar tambm aquele cdigo. Por exemplo, se o mtodo da classe ascendente realiza um determinado clculo, e o mtodo da classe descendente realiza no s aquele clculo, como tambm outros dois clculos, voc tem que utilizar a diretiva inherited. Vamos modificar o cdigo acima: Coloque entre chaves (comentrio), a instanciao de TClasse1, como mostrado abaixo:
procedure TForm1.Button1Click(Sender: TObject); Var Classe : TClasse1 ; begin

{
Try Classe := TClasse1.Create ; Classe.Mostra ; Finally Classe.Free ; End ;

}
Try Classe := TClasse2.Create ; Classe.Mostra ; Finally Classe.Free ; End ; end;

Execute a aplicao D um clique no boto. Observe que s aparece o aviso: Mtodo da Classe 2 Feche a aplicao Adicione a palavra inherited ao mtodo Mostra da TClasse2: procedure TClasse2.Mostra ; begin Inherited ; ShowMessage ( 'Mtodo da classe 2' ) ; end ;

Execute a aplicao D um clique no boto e observe que os avisos: Mtodo da Classe 1 e Mtodo da Classe 2 aparecem, um aps o outro, comprovando que o cdigo escrito em TClasse1.Mostra foi executado tambm. Feche a aplicao

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

165

14.5. TypeCasting e operadores de Classe: IS e AS O Operador IS compara um objeto e uma classe, e resulta True (verdadeiro) se o objeto daquela classe; caso contrrio, retorna False (falso). Geralmente utilizado com o comando If / Then. J o operador AS referencia um objeto como sendo de uma determinada classe. Por exemplo, o cdigo abaixo faz com que o pressionar da tecla Enter passe de um componente TEdit para outro. Para isso, seguiremos os seguintes passos: a. Verificar se o controle ativo (ActiveControl) um edit box (TEdit) b. Se for, verificar se a tecla Enter, cujo cdigo ASCII 13 foi pressionada c. Se foi, armazenar na varivel "i" a ordem do componente no form (todo componente tem uma propriedade denominada TabOrder; verifique no Object Inspector). O primeiro TabOrder igual a 0 (zero). d. Incrementar i at que o componente naquela ordem seja um TEdit. Se o valor de i for igual ao nmero de componentes do form, inicializar i com 0 (lembre que para n componentes, TabOrder vai de 0 at ComponentCount - 1, pois o TabOrder do primeiro componente 0) e. Dar o foco ao componente naquela posio Vamos ento colocar isto em prtica. Comece uma nova aplicao Coloque um memo e 6 edit box no form Altere a propriedade KeyPreview de Form1 para True Obs5.: Isto garante que, ao pressionar de uma tecla, independente do controle ativo, Form1 receber o cdigo ASCII na varivel Key. Manipule seu evento OnKeyPress com: procedure TForm1.FormKeyPress(Sender: TObject; var Key: Char); Var i : Integer ; begin If ActiveControl is tEdit Then If Key = #13 Then begin i := ActiveControl.TabOrder ; Repeat Inc ( i ) ; If i = ComponentCount Then i := 0 ; Until Components [ i ] is TEdit ; Components [ i ].SetFocus ; end ; end;

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

166

Execute a aplicao. Acontece um erro em tempo de compilao, pois Components do tipo TComponents que por sua vez no possui um mtodo SetFocus. Para solucionar o problema, voc relizar um TypeCasting, fazendo uma referenciao do objeto apontado por Components [i] como sendo da classe TEdit que, este sim, possui um mtodo denominado SetFocus. Altere a manipulao de evento acima para:
procedure TForm1.FormKeyPress(Sender: TObject; var Key: Char); Var i : Integer ; begin If ActiveControl is tEdit Then If Key = #13 Then begin i := ActiveControl.TabOrder ; Repeat Inc ( i ) ; If i = ComponentCount Then i := 0 ; Until Components [ i ] is TEdit ;

(Components [ i ] as TEdit ).SetFocus ;


end ; end;

Execute a aplicao, d um clique em Memo1, digite alguma coisa e pressione a tecla Enter. D um clique em Edit1, digite alguma coisa e pressione a tecla Enter. Pressione a teclaa Enter novamente. Verifique que, se o componente ativo for um edit box, o controle passa para o prximo edit box. Feche a aplicao Obs6.: Uma maneira rpida de alterar o TabOrder dos componentes do form, clicando com o boto direito do mouse sobre o form e depois clicando no item TabOrder

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

167

Quando aparecer o Tab Order Editor, voc poder ordenar os componentes no form da forma como voc achar mais conveniente (isto far voc alterar a propriedade TabOrder de todos os componentes envolvidos, j que dois componentes no podem ter o mesmo TabOrder):

Diminui o TabOrder do componente selecionado

Aumenta o TabOrder do componente selecionado

Obs7.: Para que um componente possa ser acessado com a tecla Tab, a sua propriedade TabStop deve ser True; caso contrrio, o componente s ser acessvel atravs do mouse. Independente de TabStop estar com True ou False, todo componente continua tendo um TabOrder. Obs8.: TypeCast direto tambm pode ser feito, de tal maneira que a linha de comando: (Components [ i ] as TEdit ).SetFocus ; poderia ter sido substituda pela linha de comando: TEdit (Components [ i ]).SetFocus ; Recomenda-se no utilizar a segunda forma, pois em outras situaes onde seja necessrio um TypeCasting, se o objeto que est sendo referenciado no seja da classe respectiva, nada acontecer, podendo ser desastroso o resultado de tal operao. J a primeira forma (com o operador as), na hiptese de uma converso impossvel, acontece o erro EInvalidCast (em tempo de execuo). Obs9.: Como o padro estabelecido pela Microsoft para alternar entre componentes a tecla Tab, utilize esta alterao do padro com certa cautela, pois o sistema que voc fizer poder produzir resultados catastrficos (ou no produzir resultado algum) caso, numa atualizao hipottica do sistema operacional, a Microsoft destine nova funo para a tecla Enter.

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

168

15. Arquivos em disco Para voc poder trabalhar com um arquivo em disco, voc tem que declarar uma varivel que seja de um dos tipos: TextFile, File Of <tipo> ou File. Aps isso, voc tem que associar a varivel a um arquivo em disco, iniciar o uso dessa varivel (o que equivale a abrir o arquivo em disco para manipulao) e, finalmente, fechar o arquivo. 15.1. Arquivos TextFile So arquivos que armazenam linhas de caracteres ASCII. Comece uma nova aplicao Coloque um memo no form e apague o contedo da propriedade Lines Coloque um boto no form e manipule o evento OnClick com: procedure TForm1.Button1Click(Sender: TObject); Var Arq : TextFile ; i : Integer ; begin AssignFile ( Arq , 'C:\Leia.txt' ) ; Try Rewrite ( Arq ) ; For i := 0 To ( Memo1.Lines.Count - 1 ) Do Writeln ( Arq , Memo1.Lines.Strings [ i ] ) ; Finally CloseFile ( Arq ) ; End ; end; Execute a aplicao Digite algumas linhas em Memo1 Clique o boto Feche a aplicao V ao Windows Explorer e veja que o arquivo Leia.txt est armazenado na pasta C:\ , com o contedo daquilo que voc digitou em Memo1.

Obs1.: A procedure Rewrite cria o arquivo em disco, caso o mesmo no exista no momento da execuo da procedure. Obs2.: Para abrir um arquivo existente em disco, utilize a procedure Reset . Porm, se no momento da execuo de Reset o arquivo a ser aberto no exista na pasta especificada, acontece um erro em tempo de execuo. Esse problema pode ser resolvido de dois modos: bloco TRY / EXCEPT / END ou atravs da funo IORESULT (da unit System).

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

169

a. Bloco de proteo Voc deve alterar a manipulao acima para: procedure TForm1.Button1Click(Sender: TObject); Var Arq : TextFile ; i : Integer ; begin AssignFile ( Arq , 'C:\Leia.txt' ) ; Try Try Reset ( Arq ) ; Except Rewrite ( Arq ) ; End ; For i := 0 To ( Memo1.Lines.Count - 1 ) Do Writeln ( Arq , Memo1.Lines.Strings [ i ] ) ; Finally CloseFile ( Arq ) ; End ; end; b. Funo IORESULT Essa funo retorna um valor inteiro que identifica o status da ltima operao de E / S (Entrada / Sada) realizada. Caso no tenha ocorrido erro algum, IORESULT retorna o valor 0 (zero). Deve-se utilizar com IORESULT, a diretiva de compilao {$I}, que "desliga" erros de E / S, como mostrado abaixo: procedure TForm1.Button1Click(Sender: TObject); Var Arq : TextFile ; i : Integer ; begin AssignFile ( Arq , 'C:\Leia.txt' ) ; Try { $I- } Reset ( Arq ) ; { $I+ } If IORESULT <> 0 Then Rewrite ( Arq ) ; For i := 0 To ( Memo1.Lines.Count - 1 ) Do Writeln ( Arq , Memo1.Lines.Strings [ i ] ) ; Finally CloseFile ( Arq ) ; End ;

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

170

end; Comece uma nova aplicao Coloque um memo, um boto e um opendialog (aba Dialogs) no form Altere o filtro de OpenDialog1 para ler arquivos texto e todos os arquivos Manipule o evento OnClick de Button1 com: procedure TForm1.Button1Click(Sender: TObject); Var Arq : TextFile ; Linha : String ; i : Integer ; begin If OpenDialog1.Execute Then AssignFile ( Arq , OpenDialog1.FileName ) ; Try Try Reset ( Arq ) ; Except Rewrite ( Arq ) ; End ; i := 0 ; While Not EOF ( Arq ) Do begin Readln ( Arq , Linha ) ; Memo1.Lines.Strings [ i ] := Linha ; Inc ( i ) ; end ; Finally CloseFile ( Arq ) ; End ; end;

Obs3.: Todo arquivo aberto em disco tem, alm de um nmero de manipulao (este nmero chamado Handle do arquivo), um ponteiro que indica em que ponto do arquivo o aplicativo que o abriu encontra-se. A cada leitura de uma linha, o ponteiro deslocado para a posio seguinte. Quando esse ponteiro alcana uma posio alm do fim (end) do arquivo (file), a funo Eof retorna o valor booleano True. Sendo assim, a linha de comando: While Not EOF ( Arq ) Do garante que o processamento continua enquanto no for fim de arquivo (EOF = End Of File). Utilize o Help online do Delphi para maiores detalhes sobre a manipulao de arquivos de texto.

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

171

15.2. Arquivos File Of So arquivos que armazenam dados de um mesmo tipo (registros do aquivo), em um formato prprio do Object Pascal, podendo ser File Of: Integer, Real, Record etc. Arquivos File Of ao contrrio dos arquivos texto, arquivos typed esto abertos para operaes de leitura e escrita (gravao) ao mesmo tempo, utilizando a procedure Seek para acessar um determinado registro do arquivo, alm de utilizar as procedures Read para ler e Write para escrever. Comece uma nova aplicao Coloque um memo, trs botes e um opendialog (aba Dialogs) no form Coloque trs edit box (para escrever nome, endereo e salrio) Altere o filtro de OpenDialog1 para ler arquivos .DAT e todos os arquivos Manipule o evento OnClick de Button1 com: procedure TForm1.Button1Click(Sender: TObject); begin If Not OpenDialog1.Execute Then OpenDialog1.FileName := 'Sem Nome.DAT' ; end; Manipule o evento OnClick de Button2 com: procedure TForm1.Button2Click(Sender: TObject); Type Reg = Record Nome : String [50] ; Endereco : String [100] ; Salario : Extended ; End ; Var Arq : File Of Reg; R : Reg ; Linha : String ; i : Integer ; begin AssignFile ( Arq , OpenDialog1.FileName ) ; Try Try Reset ( Arq ) ; Except Rewrite ( Arq ) ; End ; R.Nome := Edit1.Text ; R.Endereco := Edit2.Text ; R.Salario := StrToFloat ( Edit3.Text ) ;

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

172

Seek ( Arq, FileSize ( Arq ) ) ; Write ( Arq , R ) ; Finally CloseFile ( Arq ) ; End ; end; Manipule o evento OnClick de Button3 com: procedure TForm1.Button3Click(Sender: TObject); Type Reg = Record Nome : String [50] ; Endereco : String [100] ; Salario : Extended ; End ; Var Arq : File Of Reg; R : Reg ; Linha : String ; i : Integer ; begin AssignFile ( Arq , OpenDialog1.FileName ) ; Try Try Reset ( Arq ) ; Except Rewrite ( Arq ) ; End ; i := 0 ; While Not EOF ( Arq ) Do begin Read ( Arq , R ) ; Memo1.Lines.Add ( 'Nome: ' + R.Nome ) ; Memo1.Lines.Add ( 'Endereo: ' + R.Endereco ) ; Memo1.Lines.Add ( 'Salario: R$ ' + FloatToStr (R.Salario) ) ; Memo1.Lines.Add ( '' ) ; // Pula uma linha Inc ( i ) ; end ; Finally CloseFile ( Arq ) ; End ; end; Clique em button1 e digite um nome no campo Nome do Arquivo: da janela de dilogo Abrir. Rode o aplicativo. Digite n1 em edit1, e1 em edit2 e 1,00 em edit3 e clique em button1. Repita este procedimento mais duas vezes.

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

173

Clique em button3. Verifique que s aparece a ltima digitao. Feche a aplicao. Obs.: Cada vez que voc abre o arquivo para escrita e leitura, o ponteiro do arquivo posicionado no primeiro registro, o que faz com que a cada entrada voc sobrescreva o dado anterior. Para evitar que isso acontea, voc pode: Criar o arquivo Arq como sendo uma varivel global e abriando-a somente uma vez (conseqentemente, fechando-a a penas uma vez), o que faz com que a cada operao de escrita, o ponteiro avance uma posio frente. Para ler do incio, deve-se executar a procedure Seek, especificando a posio 0 (zero), correspondente ao primeiro registro do arquivo: Seek (Arq, 0) A cada clique em button2, executa-se o a procedure Seek, especificando o final do arquivo com a funo FileSize (que retorna o tamanho de registros do arquivo): Seek (Arq, FileSize (Arq)) como mostrado abaixo: procedure TForm1.Button2Click(Sender: TObject); Type Reg = Record Nome : String [50] ; Endereco : String [100] ; Salario : Extended ; End ; Var Arq : File Of Reg; R : Reg ; Linha : String ; i : Integer ; begin AssignFile ( Arq , OpenDialog1.FileName ) ; Try Try Reset ( Arq ) ; Except Rewrite ( Arq ) ; End ; R.Nome := Edit1.Text ; R.Endereco := Edit2.Text ; R.Salario := StrToFloat ( Edit3.Text ) ; Seek ( Arq, FileSize ( Arq ) ) ; Write ( Arq , R ) ; Finally CloseFile ( Arq ) ; End ; end;

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

174

15.3. Arquivos File Arquivo Untyped no muito usado em programas aplicativos, mas pode ser til em operaes de cpia de arquivos (como em cpias de segurana ou, backup). Vamos supor que voc esteja trabalhandoem C:\Diretorio com dois arquivos de dados de nomes: CADASTRO.DB e CADASTRO.PX . Para fazer um backup dos dois arquivos voc pode manipular o evento OnClick do boto com: Var oCadDB, oCadPX, dCadDB, dCadPX : File ; QIL,QIE:Integer ; { QIL = Quant_Info_Lida ; QIE = Quant_Info_Escrita } Buffer : Array [1..1024] of Byte; begin Screen.Cursor := crHourGlass ; AssignFile (oCadDB , 'C:\Diretorio\Cadastro.Db') ; // oCad.Db Origem AssignFile (oCadPX , 'C:\Diretorio\Cadastro.Px') ; AssignFile (dCadDB , 'C:\Diretorio\Cadastro.Dbk') ; // dCad.Dbk Destino AssignFile (dCadPX , 'C:\Diretorio\Cadastro.Pxk') ; Try Reset (oCadDB,1) ; Reset (oCadPX,1) ; Rewrite (dCadDB,1) ; Rewrite (dCadPX,1) ; BlockRead (oCadDB, Buffer,SizeOf(Buffer),QIL) ; While QIL > 0 Do begin BlockWrite (dCadDB, Buffer, QIL, QIE) ; BlockRead (oCadDB, Buffer,SizeOf(Buffer),QIL) ; end ; BlockRead (oCadPX, Buffer,SizeOf(Buffer),QIL) ; While QIL > 0 Do begin BlockWrite (dCadPX, Buffer, QIL, QIE) ; BlockRead (oCadPX, Buffer,SizeOf(Buffer),QIL) ; end ; Finally CloseFile (oCadDB) ; CloseFile (oCadPX) ; CloseFile (dCadDB) ; CloseFile (dCadPX) ; Screen.Cursor := crDefault ; End ; end ; Obs1.: Com essa rotina, cada byte do arquivo de origem vai sendo lido e escrito no arquivo de destino, at que a quantidade de bytes lidos do arquivo de origem

Delphi 3.0

- Apostila registrada para: Professor Jos Luiz A. Rosa - 1998 - Universidade Estcio de S Todos os direitos reservados.

175

(QIL) seja igual a zero, quando ento finalizado que no h mais informao a ser lida. Obs2.: Altere C:\Diretorio com o nome do diretrio que contm os arquivos de dados.