Sei sulla pagina 1di 296

1997, 1998, 1999 GRIAULE

Delphi 4 Total

1997, 1998, 1999 GRIAULE

Delphi Total
Direitos Autorais 1997, 1998 para Griaule (razo social: I.A. Pesquisa & Desenvolvimento de Sistemas Ltda.) Nenhuma parte desta publicao poder ser reproduzida ou transmitida, no todo ou em parte, em qualquer forma ou meio, seja eletrnica ou mecnica, seja qual for o propsito, sem a expressa autorizao por escrito da Griaule. Delphi, Borland, ReportSmith, dBASE e InterBase so marcas registradas da Borland International, Inc. Microsoft, MS, Windows, Windows 95, Microsoft SQL Server so marcas comerciais ou marcas registradas da Microsoft Corporation. Paradox uma marca registrada da Ansa Software, uma empresa da Borland. TrueType uma marca registrada da Apple Corporation. Oracle uma marca registrada da Oracle Corporation. Todas as outras marcas e nomes de produtos so de propriedade de seus respectivos portadores. Contedo: Mrcio Pontes Marla C. vila Converso para mdia eletrnica: Renato de A. Martins

Delphi 4 Total

1997, 1998, 1999 GRIAULE

Captulo 1 Iniciando o Delphi ___________________________________________________ 1


Princpios da Programao Windows _________________________________________________ 2 Iniciando o Delphi _________________________________________________________________ 3 Criando um Primeiro Programa _____________________________________________________ 5
Propriedades do Formulrio _________________________________________________________________5 Colocando Componentes ___________________________________________________________________5 Alterando as Propriedades dos Componentes____________________________________________________7 Respondendo a Eventos ____________________________________________________________________7 Testando o Programa ______________________________________________________________________8 Salvando o Programa ______________________________________________________________________8

Captulo 2 Noes Bsicas______________________________________________________ 9


Ambiente de Programao _________________________________________________________ 10
Programao Orientada a Objeto (POO) ______________________________________________________10

Eventos e Procedimentos __________________________________________________________ 11 Componentes ____________________________________________________________________ 12


Viso Geral dos Componentes ______________________________________________________________12

Propriedades ____________________________________________________________________ 14 Mtodos ________________________________________________________________________ 15 Object Pascal e Bibliotecas _________________________________________________________ 16 VCL - Visual Component Library___________________________________________________ 17 Objetos _________________________________________________________________________ 18 Resumo _________________________________________________________________________ 19 Projetos_________________________________________________________________________ 20
Salvando o Projeto em Disco _______________________________________________________________20 Comandos para trabalhar com Projetos _______________________________________________________21

Grupos de Projetos _______________________________________________________________ 23


Comandos para tabalhar com grupos de projetos ________________________________________________23

Edies do Delphi ________________________________________________________________ 24

Captulo 3 Exemplos Adicionais ________________________________________________ 25


Exemplo: Calculadora ____________________________________________________________ 26
Criando os Componentes __________________________________________________________________26 Tratando os Eventos ______________________________________________________________________27 Executando o Programa ___________________________________________________________________29 Melhoras de Interface _____________________________________________________________________29 Salvando o Projeto _______________________________________________________________________30

Captulo 4 Variveis e Tipos de Dados ___________________________________________ 31


Tipos de Dados___________________________________________________________________ 32
Tipos Numricos_________________________________________________________________________32 Delphi 4 Total

1997, 1998, 1999 GRIAULE O tipo Char _____________________________________________________________________________34 O tipo String ____________________________________________________________________________35 O tipo Boolean __________________________________________________________________________36 O tipo TDateTime________________________________________________________________________37

Funes de Converso_____________________________________________________________ 38 Operaes Aritmticas ____________________________________________________________ 40 Tipos Ordinais ___________________________________________________________________ 42 Escopo de Variveis_______________________________________________________________ 44
Variveis Locais _________________________________________________________________________44 Variveis Globais da Unidade ______________________________________________________________44 Variveis Globais do Projeto _______________________________________________________________45

Constantes ______________________________________________________________________ 46

Captulo 5 Estruturas de Controle_______________________________________________ 48


Inserindo comandos com o CodeInsight ______________________________________________ 49 Estruturas de Deciso _____________________________________________________________ 50
O Comando if...then...else... ________________________________________________________________50 O Comando case...of... ____________________________________________________________________51

Estruturas de Laos_______________________________________________________________ 53
O comando for __________________________________________________________________________53 O comando while...do... ___________________________________________________________________54 O comando repeat..until ___________________________________________________________________54

Outros Comandos ________________________________________________________________ 55


Comandos para sair de laos________________________________________________________________55 O comando exit__________________________________________________________________________55

Captulo 6 Propriedades e Eventos Comuns_______________________________________ 56


Tipos de Propriedades_____________________________________________________________ 57 Propriedades Mais Usadas _________________________________________________________ 59
Propriedades para Todos os Componentes _____________________________________________________59 Propriedades de Tamanho e Posio _________________________________________________________59 Propriedades do Formulrio ________________________________________________________________59 Propriedades de Controles _________________________________________________________________61

Eventos Comuns _________________________________________________________________ 63


Eventos de Mouse________________________________________________________________________63 Eventos de Teclado_______________________________________________________________________63 Eventos do Formulrio ____________________________________________________________________65 Outros Eventos __________________________________________________________________________65

Detalhes do Tratamento de Eventos _________________________________________________ 67


Tratando um Evento para Vrios Controles: OnKeyPress _________________________________________67 Renomeando um Procedimento de Evento _____________________________________________________68 Associando um Procedimento Existente_______________________________________________________68 Eliminando um Procedimento de Evento ______________________________________________________69 Delphi 4 Total

1997, 1998, 1999 GRIAULE

Captulo 7 Usando Vrios Formulrios __________________________________________ 70


Caixas de Dilogo ________________________________________________________________ 71 Funes de Mensagem_____________________________________________________________ 72
Mensagens Informativas___________________________________________________________________72 Mensagens de Confirmao ________________________________________________________________72

Exemplo: CalcData _______________________________________________________________ 75


Pedindo Confirmao ao Usurio ____________________________________________________________76 Criando um Novo Formulrio ______________________________________________________________77 Salvando o Projeto _______________________________________________________________________78 Executando um Arquivo ___________________________________________________________________78

Gerenciando os Arquivos do Projeto_________________________________________________ 81


Usando a Speedbar ou Menus_______________________________________________________________81 Usando o Project Manager _________________________________________________________________82

Definindo o Formulrio Principal ___________________________________________________ 85

Captulo 8 Estrutura das Unidades ______________________________________________ 86


Estrutura Geral das Unidades ______________________________________________________ 87 O Cdigo Gerado pelo Delphi ______________________________________________________ 88
Seo de Interface________________________________________________________________________88

Unidades Associadas e Independentes________________________________________________ 90 Compilao de Unidades___________________________________________________________ 91 Usando uma Unidade _____________________________________________________________ 92 Resolvendo Conflitos de Nomes _____________________________________________________ 94 Arquivo de Projeto _______________________________________________________________ 95

Captulo 9 Outros Tipos de Dados e Depurao____________________________________ 97


Tipos Enumerados________________________________________________________________ 98
Operaes com Ordinais___________________________________________________________________98 Tipos Enumerados no Delphi _______________________________________________________________99

Tipos Faixa_____________________________________________________________________ 100


Opo "Range Checking" _________________________________________________________________100

Vetores ________________________________________________________________________ 102


Vetores Estticos _______________________________________________________________________102 Verificao de Faixa para Vetores __________________________________________________________102 Usando Outros Tipos de ndice ____________________________________________________________103 Vetores Dinmicos ______________________________________________________________________104 Vetores Multidimensionais________________________________________________________________104

Exemplo: Clculo de Mdia _______________________________________________________ 106


Declarando o Vetor______________________________________________________________________106 Adicionando um Elemento ________________________________________________________________107 Limpando a Lista _______________________________________________________________________107 Calculando a Mdia dos Elementos _________________________________________________________107 Delphi 4 Total

1997, 1998, 1999 GRIAULE Testando o Programa ____________________________________________________________________108 Salvando o Projeto ______________________________________________________________________108

Conjuntos ______________________________________________________________________ 109


Verificando Elementos ___________________________________________________________________109 Operaes com Conjuntos ________________________________________________________________110 Propriedades de Conjunto_________________________________________________________________111

Depurao _____________________________________________________________________ 112


Colocando um Ponto de Parada ____________________________________________________________112 Executando Passo a Passo ________________________________________________________________112 Executando At o Cursor _________________________________________________________________113 Vendo Valores de Variveis _______________________________________________________________113 Monitorando o Valor de uma Varivel Dinamicamente __________________________________________114 Forando a Finalizao do Programa ________________________________________________________115 Outras Ferramentas de Depurao __________________________________________________________115

Captulo 10 Procedimentos e Funes __________________________________________ 116


Procedimentos Gerais ____________________________________________________________ 117
Criando um Procedimento Geral ___________________________________________________________117

Unidades Independentes __________________________________________________________ 119


Criando uma Unidade Independente_________________________________________________________119 Transferindo o Procedimento ______________________________________________________________119 Usando a Unidade no Mesmo Projeto _______________________________________________________120 Usando a Unidade em Outros Projetos _______________________________________________________120 Gerenciando um Projeto com Unidades Independentes __________________________________________121 Criando uma Biblioteca de Rotinas _________________________________________________________121

Funes________________________________________________________________________ 123
Criando uma Funo_____________________________________________________________________123 Retornando um Valor ____________________________________________________________________123 Chamando a Funo _____________________________________________________________________124

Passagem de Parmetros _________________________________________________________ 125


Declarao de Parmetros e Argumentos _____________________________________________________125 Tipos de Passagem ______________________________________________________________________126

Captulo 11 Objetos _________________________________________________________ 128


O Que Contm um Objeto ________________________________________________________ 129 Classes e Objetos ________________________________________________________________ 130 Herana _______________________________________________________________________ 131
Hierarquia de Classes do Delphi____________________________________________________________131 O Object Browser _______________________________________________________________________132 Simplificando o Acesso aos Campos ________________________________________________________132

Formulrios como Objetos ________________________________________________________ 133


A Classe de Formulrio __________________________________________________________________133 Procedimentos na classe de formulrio_______________________________________________________134

Variveis de Objeto ______________________________________________________________ 136 Listas de Strings ________________________________________________________________ 140


Delphi 4 Total

1997, 1998, 1999 GRIAULE Propriedades da String List________________________________________________________________140 Mtodos da String List ___________________________________________________________________140 Criando String Lists Independentes _________________________________________________________141

Objetos Predefinidos _____________________________________________________________ 143


O Objeto Application ____________________________________________________________________143 O Objeto Clipboard _____________________________________________________________________143 O Objeto Screen ________________________________________________________________________144

Code Explorer __________________________________________________________________ 145 Programao Orientada a Objetos _________________________________________________ 147

Captulo 12 Aplicaes de Banco de Dados ______________________________________ 149


Termos Usados__________________________________________________________________ 150 Desktop x Cliente/Servidor________________________________________________________ 151 Formatos de Bancos de Dados _____________________________________________________ 153 Criando Tabelas ________________________________________________________________ 154
Definindo um Diretrio de Trabalho ________________________________________________________154 Definindo a Estrutura dos Campos __________________________________________________________154 Salvando a Tabela_______________________________________________________________________155 Entrando com Dados ____________________________________________________________________155

Exemplo: Criando um Formulrio "Manualmente"___________________________________ 157


A Pgina Data Access____________________________________________________________________157 Criando os Controles de Dados ____________________________________________________________157 Adicionando o DBNavigator ______________________________________________________________159 Ativando a Tabela_______________________________________________________________________160 Testando o Programa ____________________________________________________________________160

Exemplo: Usando o Database Form Wizard__________________________________________ 162


Criando um campo autoincremento _________________________________________________________162 Criando um Formulrio para Acessar a Tabela com Form Wizard _________________________________162 Testando o Programa ____________________________________________________________________163 Salvando o Projeto ______________________________________________________________________164

Resumo dos Componentes de Dados ________________________________________________ 165 Apelidos de Bancos de Dados ______________________________________________________ 166

Captulo 13 Recursos Adicionais_______________________________________________ 169


Definindo Tabelas _______________________________________________________________ 170
Reestruturando a Tabela "Cliente" __________________________________________________________171 Criando um ndice Secundrio _____________________________________________________________171 Criando a Tabela "Venda" ________________________________________________________________172 Criando Integridade Referencial____________________________________________________________172 Criando a Tabela de Itens _________________________________________________________________173 Criando a tabela Fornecedores _____________________________________________________________173

Criando o Menu Principal ________________________________________________________ 175


O MenuDesigner: criando menus ___________________________________________________________175 Tratando Eventos de Menus _______________________________________________________________178 Delphi 4 Total

1997, 1998, 1999 GRIAULE Teclas de Acesso e Teclas de Atalho ________________________________________________________179

Alterando o Menu Principal_______________________________________________________ 181


Alterando Propriedades __________________________________________________________________181 Acrescentando os formulrios anteriores _____________________________________________________181 Associando os formulrios aos itens de menu _________________________________________________181

Usando o Controle DBGrid _______________________________________________________ 183


Criando os Componentes de Dados _________________________________________________________183 Manipulando dados no DBGrid ____________________________________________________________183 Usando o Editor de Campos _______________________________________________________________184 Alterando a Mscara de Edio ____________________________________________________________185

Captulo 14 Validao e Pesquisas _____________________________________________ 186


Exemplo: Cliente por Estado ______________________________________________________ 187 Exemplo: Clientes - Alterando _____________________________________________________ 189 Validao de Campos e Registros __________________________________________________ 190
Validando Campos ______________________________________________________________________190 Validando Registros _____________________________________________________________________192

Tratamento de Excees __________________________________________________________ 194


Visualizando Informaes sobre Excees____________________________________________________195 Classes de Excees _____________________________________________________________________196

Pesquisas na Tabela _____________________________________________________________ 197


Adicionando um DBGrid _________________________________________________________________197 Utilizando um ndice Secundrio ___________________________________________________________198 Pesquisando pelo Nome __________________________________________________________________199 Pesquisando pelo Cdigo _________________________________________________________________199

Blocos Protegidos________________________________________________________________ 201 Usando Outros Controles de Dados_________________________________________________ 202


Usando o DBComboBox _________________________________________________________________202

Captulo 15 Acesso s/ Controle de Dados ________________________________________ 204


Estados de uma Tabela ___________________________________________________________ 205 Mtodos para Percorrer Dados ____________________________________________________ 206
Mtodos de Abertura e Fechamento _________________________________________________________206 Mtodos para Percorrer Registros___________________________________________________________206 Exemplo: Percorrendo a Tabela de Itens _____________________________________________________208

Mtodos para Modificar Dados ____________________________________________________ 210


Editando Registros ______________________________________________________________________210 Acrescentando Registros _________________________________________________________________211 Excluindo Registros _____________________________________________________________________212 Outros Mtodos ________________________________________________________________________212

Eventos dos Componentes de Dados ________________________________________________ 214


Eventos do Componente Table _____________________________________________________________214

Manipulao de Datas____________________________________________________________ 216


Delphi 4 Total

1997, 1998, 1999 GRIAULE

Exemplo: Criando formulrio sem utilizar o dbNavigator ______________________________ 218 Tratamento do Erro 'Key violation.' ________________________________________________ 224 Usando um Controle DBLookupComboBox__________________________________________ 225

Captulo 16 Utilizando Mestre/Detalhe__________________________________________ 227


Criando um Formulrio Mestre/Detalhe ____________________________________________ 228
Usando o DFW para criar o formulrio ______________________________________________________228 Testando o Formulrio Gerado _____________________________________________________________229 Analisando o Formulrio _________________________________________________________________230 Alterando Propriedades do Formulrio_______________________________________________________231 Salvando o Projeto ______________________________________________________________________232

Usando Trs Tabelas no Formulrio ________________________________________________ 233


Ligando os Componentes de Dados _________________________________________________________233 Criando Controles de Dados_______________________________________________________________233 Criando Campos Calculados_______________________________________________________________234 Usando um campo Lookup________________________________________________________________236 Testando e Salvando o Projeto _____________________________________________________________237 Atualizando Quantidade em Estoque________________________________________________________238

Captulo 17 Consultas e SQL__________________________________________________ 241


Exemplo: Usando Consultas_______________________________________________________ 242
Criando o Formulrio ____________________________________________________________________242 Obtendo um Resultado Modificvel _________________________________________________________243 Simplificando o Select ___________________________________________________________________244 Alterando a Consulta ____________________________________________________________________244 Alterando a Consulta Dinamicamente _______________________________________________________244 Alterando Outras Partes da Consulta ________________________________________________________247

Exemplo: Consultando Vrias Tabelas ______________________________________________ 249


Consulta com Duas Tabelas _______________________________________________________________249 Consultando Trs Tabelas_________________________________________________________________250 Usando Campos Calculados no SQL ________________________________________________________250 Usando Funes de Resumo_______________________________________________________________251

Outros Comandos SQL___________________________________________________________ 253


Testando Comandos SQL _________________________________________________________________253 Alterando Registros _____________________________________________________________________253 Excluindo Registros _____________________________________________________________________254 Inserindo e Copiando Registros ____________________________________________________________254 Executando um Comando de Atualizao ____________________________________________________255

Consultas num Ambiente Cliente/Servidor___________________________________________ 256 Mtodos e Eventos do Componente Query ___________________________________________ 257

Captulo 18 Instalador e Alias Local____________________________________________ 258


Usando um Alias Local ___________________________________________________________ 259
Usando o Componente Database ___________________________________________________________259 Alterando os Componentes de Dados________________________________________________________260 Alterando o Caminho em Tempo de Execuo ________________________________________________261 Delphi 4 Total

1997, 1998, 1999 GRIAULE

Criando um programa instalador __________________________________________________ 262


Iniciando o InstallShield __________________________________________________________________262 Criando um Instalador ___________________________________________________________________263 Definindo as Opes de Instalao __________________________________________________________263 Definindo os Arquivos Utilizados __________________________________________________________264 Escolhendo as caixas de dilogo____________________________________________________________265 Definindo os cones do Programa___________________________________________________________266 Gerando os disquetes de instalao _________________________________________________________267

A Configurao do BDE __________________________________________________________ 268

Captulo 19 Relatrios _______________________________________________________ 269


Conceitos do QuickReport ________________________________________________________ 270
A pgina QReport_______________________________________________________________________270 Construindo o Relatrio __________________________________________________________________271

Usando o QuickReport Wizard ____________________________________________________ 273


Imprimindo o Relatrio __________________________________________________________________274 Analisando o Relatrio Gerado_____________________________________________________________274

Criando um Relatrio com Vrias Tabelas___________________________________________ 276


Inserindo um Nmero de Pgina ___________________________________________________________278 Visualizando o Relatrio _________________________________________________________________278 Acrescentando Vrias Tabelas ao Relatrio ___________________________________________________279 Conectando as Tabelas ___________________________________________________________________279 Criando Sub-detalhes para Vendas __________________________________________________________280 Criando Sub-detalhes para Itens de Venda ____________________________________________________281 Formatando os Campos __________________________________________________________________282 Criando um Campo Calculado _____________________________________________________________283 Criando um Sub-total ____________________________________________________________________284 Chamando o Relatrio a Partir do Menu _____________________________________________________285

Delphi 4 Total

1997, 1998, 1999 GRIAULE

Captulo 1 Iniciando o Delphi


Princpios da Programao Windows Iniciando o Delphi Criando um Primeiro Programa

Delphi 4 Total

1997, 1998, 1999 GRIAULE

Princpios da Programao Windows


Antes de comear a trabalhar com o Delphi, importante ter algumas noes do que est envolvido na programao Windows e no Delphi em particular. Algumas coisas tornam a tarefa de programao no Windows bem diferente de outros ambientes: Independncia do Hardware:No Windows, o acesso aos dispositivos de hardware feito com intermdio de drivers fornecidos pelo fabricante de hardware, o que evita que o programador tenha que se preocupar com detalhes especficos do hardware. Configurao Padro: O Windows armazena centralmente as configuraes de formato de nmeros, moeda, datas e horas, alm da configurao de cores, livrando o programador de se preocupar com esses detalhes especficos. Multitarefa: No DOS, um programa geralmente toma o controle da mquina s para si, e outros programas no rodam enquanto isso. J no Windows vrios programas so executados de maneira simultnea e no h como evitar isso. Controle da Tela: No DOS geralmente um programa ocupa todo o espao de telas, e o usurio v e interage apenas com aquele programa. J no Windows [janelas], toda informaes mostradas e todas entradas recebidas do usurio so feitas por meio de uma janela, uma rea separada da tela que pode ser sobreposta por outras janelas (de outros programas por exemplo). Padres de Interface: No Windows, todos os elementos de interface aparecem para o usurio e interagem da mesma forma. Alm disso, existem padres definidos pela Microsoft que so recomendados para conseguir a consistncia entre aplicativos. Falaremos de alguns deles no curso, mas a melhor forma de aprend-los praticar com os aplicativos Windows mais usados do mercado. Cooperao com o Sistema: Num programa DOS, a execuo segue uma ordem prestabelecida pelo programador, e o programa s chama o sistema operacional quando precisa de alguma coisa dele. J no Windows, o programa deve responder a eventos, que so ativados pelo Windows quando alguma coisa acontece externamente (ou seja, uma ao do usurio, ou uma aviso do sistema). Isso, como veremos, afeta radicalmente o estilo de programao e a forma de pensar no programa. A sequncia de execuo do programa depende da sequencia de eventos.

Delphi 4 Total

1997, 1998, 1999 GRIAULE

Iniciando o Delphi
Inicie o Delphi atravs do seu cone no Windows, se voc j tiver um atalho para o do Windows e depois em programa na sua rea de trabalho. Seno, clique no menu Programas|Borland Delphi 4|Delphi 4. A tela bsica do Delphi tem os seguintes elementos:

Ao pressionar F12 ir aparecer a seguinte tela:

Delphi 4 Total

1997, 1998, 1999 GRIAULE

Nota: para criar um atalho para o Delphi, consulte a documentao do Windows. Localize o arquivo executvel DELPHI32.EXE sob o diretrio de instalao. Formulrio (Form1): Um formulrio a janela do seu programa, o local onde voc projeta a sua interface com o usurio. Durante o projeto, o formulrio aparece de forma praticamente idntica ao que o usurio final ver, mas permite que voc faa alteraes no posicionamento dos componentes (elementos de tela) e em suas propriedades (caractersticas); Speedbar: Uma barra de botes na janela principal do Delphi, que contm botes para executar os comandos mais usados do Delphi; Paleta de Componentes: Tambm na janela principal, dividida em vrias pginas, onde cada uma contm vrios tipos de componentes que voc pode escolher para colocar no formulrio; Object Inspector: [inspetor de objeto]: Dividido em duas pginas, onde uma contm as propriedades do componente selecionado, e a outra uma lista de eventos associados a este componente, que define as aes externas as quais voc pode tratar; Menu Principal: Contm os comandos do ambiente de programao do Delphi, por exemplo, para tratamento de arquivos, definio de opes, etc. Code Editor: (Aparece atrs do formulrio, inicialmente). Contm o cdigo-fonte do projeto. Com ele, voc pode facilmente mudar entre os vrios arquivos utilizados no projeto ou mesmo abrir um arquivo de texto qualquer.

Delphi 4 Total

1997, 1998, 1999 GRIAULE

Criando um Primeiro Programa


No Delphi voc inicia o projeto da sua aplicao escolhendo componentes, que so os objetos de interface com o usurio e alterando as caractersticas desses componentes como por exemplo, cor, tamanho, fonte de caracteres, atravs das propriedades. Por ltimo, voc decide quais eventos voc quer tratar e escreve o cdigo de programa que executado por esses eventos. Nosso primeiro programa ir mostrar uma lista de nomes e permitir ao usurio adicionar itens na lista, limpar a lista e ordenar a lista em ordem alfabtica. O programa ter uma interface como a seguir, com uma lista de itens, um quadro de texto que permite digitar o prximo item da lista, e botes para manipular a lista:

Para cri-lo, precisamos alterar propriedades do formulrio e colocar componentes em cima dele.

Propriedades do Formulrio
Propriedades do formulrio so as caractersticas que definem sua aparncia, e algumas vezes, seu comportamento. O Object Inspector lista todas as propriedades do formulrio, que so inicializadas com valores padro quando o projeto criado. Por exemplo, o ttulo que aparece no formulrio (inicialmente Form1) uma propriedade que voc pode alterar no Object Inspector. Selecione a propriedade Caption no Object Inspector. Clique na coluna da direita (que contm o valor da propriedade) e digite o texto Primeiro Programa Delphi. medida que voc digita, o formulrio reflete essa alterao na sua barra de ttulo.

Colocando Componentes
Um formulrio vazio no muito til, portanto vamos colocar componentes nesse formulrio. A Paleta de Componentes contm vrios cones, onde cada um representa um Delphi 4 Total 5

1997, 1998, 1999 GRIAULE tipo de componente que voc pode colocar no formulrio. Ela tambm dividida em pginas, que podem ser acessadas clicando no marcador de pgina correspondente. Quando voc passa o cursor do mouse por cima de um cone, ela mostra o nome daquele componente. Clique na pgina Standard e depois clique no cone (Edit). Agora clique no formulrio. Vai aparecer um quadro de edio chamado "Edit1". Depois iremos alterar esse nome padro. Para mud-lo de posio no formulrio, posicione o cursor em cima dele, pressione e segure o boto do mouse, e arraste-o para outra posio, ao arrastar o componente ser mostrado as coordenadas (x, y) indicando a posio do componente no formulrio . Ou, se preferir, usando o teclado, segure a tecla [Ctrl] e use as teclas de seta para moviment-lo. Agora precisamos de um quadro de lista. Clique no cone (ListBox) da paleta de componentes, na mesma pgina Standard, depois clique no formulrio, um pouco abaixo do quadro de texto (no se preocupe com alinhamento). Para aumentar seu tamanho lateral, clique na ala mais direita, segure o boto do mouse e arraste-o para a direita. Ou, usando o teclado, segure [Shift] e pressione a seta para a direita. Vamos colocar trs botes no formulrio. Como so vrios controles do mesmo tipo, podemos fazer o seguinte: segure [Shift] e clique no cone (Button) da paleta de componentes. Agora clique trs vezes no formulrio, colocando um boto abaixo do outro. No se preocupe com o alinhamento por enquanto Depois clique no cone do ponteiro ( . O formulrio deve ficar parecido com o seguinte: )

Clique no boto (Run) da SpeedBar. O Delphi ir compilar o programa, gerando um arquivo executvel e vai iniciar sua execuo. Durante a execuo, voc pode digitar texto no quadro de texto, e clicar nos botes. Depois tecle [Alt+F4] para terminar o programa (ou feche a janela com o mouse). Repare que o Delphi cuida de toda a parte de interface com o usurio. Voc no precisa escrever cdigo para mostrar uma janela na tela nem seus componentes. Mas para definir o que o programa vai fazer, isto , como ele reage aos eventos externos, voc precisa escrever cdigo. Delphi 4 Total 6

1997, 1998, 1999 GRIAULE

Alterando as Propriedades dos Componentes


Para mudar a aparncia dos componentes, alteraremos suas propriedades. importante notar que o Object Inspector disponibiliza as propriedades do componente que estiver selecionado, ou seja, com as alas de marcao. Quando voc clica em um componente com o mouse, ele selecionado e voc pode alterar suas propriedades. Quando voc clica numa regio vazia do formulrio (ou pressiona [Esc]), voc pode alterar as propriedades do formulrio. Selecione o quadro de texto e depois clique na propriedade Text no Object Inspector. Apague o valor atual (que Edit1). Assim esse componente no vai mais comear mostrando "Edit1" no seu contedo. Agora clique no primeiro boto (Button1) e altere sua propriedade Caption para Adicionar. Isso define o texto do boto. Clique no segundo boto (Button2) e altere Caption para "Ordenar" e no terceiro boto, altere Caption para "Limpar".

Respondendo a Eventos
Todo o cdigo no Delphi executado, direta ou indiretamente, em resposta a eventos. Quando voc (ou o usurio) clica em um boto por exemplo, isso provoca um evento. Se existir um trecho de programa associado a esse evento (um procedimento de evento), esse trecho ser executado. Seno, o evento no vai fazer nada. Clique no boto Adicionar para selecion-lo. No Object Inspector, clique no marcador de pgina "Events". Essa pgina lista quais eventos so reconhecidos pelo componente. O primeiro deles, OnClick, acontece quanto o boto recebe um clique do mouse. Clique duas vezes na coluna da direita, e o Delphi vai abrir o editor de cdigo, contendo o seguinte texto:

procedure TForm1.Button1Click(Sender: TObject); begin end;


O cursor est posicionado entre os delimitadores begin e end, indicando onde voc deve escrever o cdigo, que ser executado ao clicar no boto Adicionar. Escreva o seguinte (diferenas entre maisculas e minsculas no importam):

ListBox1.Items.Add(Edit1.Text); Edit1.Clear;
Pressione a tecla [F12] para voltar ao formulrio. Clique no boto Ordenar e depois clique duas vezes no valor do evento OnClick. Isso vai gerar um tratador de evento para o boto Ordenar. Escreva o seguinte entre o begin e o end: Delphi 4 Total 7

1997, 1998, 1999 GRIAULE

ListBox1.Sorted := True;
Finalmente retorne ao formulrio, selecione o boto Limpar e siga o mesmo processo. Digite o seguinte cdigo:

ListBox1.Clear; ListBox1.Sorted := False;

Testando o Programa
Agora execute o programa clicando no boto . Voc pode digitar um valor no quadro de texto, e clicar no boto Adicionar (ou teclar [Enter]). O item digitado ser acrescentado lista. Depois de acrescentar alguns itens, clique em Ordenar. A lista ser colocada em ordem alfabtica. Para esvaziar a lista, clique em Limpar.

Salvando o Programa
Para que voc possa usar esse programa mais tarde, clique em File|Save All (menu File, item Save All) ou no boto da SpeedBar. O Delphi vai pedir um nome para o arquivo do formulrio. Digite AULA1 e clique Ok. Depois o Delphi vai perguntar o nome do arquivo de projeto. Digite AULA1P e clique Ok (no use o mesmo nome que o formulrio). Nota: Voc tambm pode clicar no formulrio ou no editor de cdigo com o mouse, mas geralmente o mtodo mais rpido de alternar entre os dois usar a tecla [F12].

Delphi 4 Total

1997, 1998, 1999 GRIAULE

Captulo 2 Noes Bsicas


Ambiente de Programao Eventos e Procedimentos Componentes Propriedades Mtodos Object Pascal e Bibliotecas VCL- Visual Component Library Objetos Resumo Projetos Grupos de Projetos Edies do Delphi

Delphi 4 Total

1997, 1998, 1999 GRIAULE

Ambiente de Programao
O Delphi possui um ambiente integrado de desenvolvimento (IDE - Integrated Development Environment) onde voc utiliza a maioria das funes de desenvolvimento. Nesse ambiente voc projeta o programa e depois executa o programa para testar o seu funcionamento. Sempre que voc executa o programa, o Delphi compila o programa, isto , gera um programa executvel com cdigo de mquina a partir do programa fonte que voc criou. Esses programas executveis se tornam independentes do Delphi e podem rodar separadamente.

Programao Orientada a Objeto (POO)


Para compreendermos melhor ambiente de desenvolvimento do Delphi necessrio que voc entenda os conceitos de Programao Orientada a Objetos(POO). A POO um forma de gerenciar a complexidade do programa, de forma que facilite a manuteno e a reutilizaco de partes do programa. O programa dividido em partes relativamente isoladas que podem ser alteradas de forma independente e podem ser reutilizadas mais facilmente em outros programas.Estas partes so chamadas de Classes (Iremos discutir em Objetos).

Delphi 4 Total

10

1997, 1998, 1999 GRIAULE

Eventos e Procedimentos
Programas DOS convencionais seguem um fluxo seqencial, em que um comando segue o outro de forma definida pelo programador. O usurio deve agir de acordo com os "modos" de operao do programa e saber o momento certo para entrar com comandos. Programas em uma interface multitarefa, como o Windows, apresentam todas as opes ao usurio, para que ele possa selecion-los na ordem em que desejar. O Windows intercepta as aes realizadas pelo usurio e informa ao programa onde, como e quando elas acontecem. O programa deve reagir de forma apropriada nos momentos determinados pelo usurio. Cada resultado de uma ao do usurio chamada de evento, por exemplo: clique do mouse, digitao de uma tecla, etc. Como conseqncia, o programa no mais um bloco nico, mas dividido em pequenas sees, cada uma responsvel pela tarefa a realizar em resposta a um determinado evento. Essas sees so os procedimentos de evento do Delphi. Cada evento associado a um componente e cada componente tem uma lista de eventos que so acionados por ele em situaes especficas (o Object Inspector mostra esta lista na pgina Events). Com isso, o projeto de um programa feito iniciando pelo projeto de sua interface (seus componentes) e depois escrevendo-se os procedimentos de evento. No obrigatrio definir todos os eventos para um componente. Se no existe um procedimento para um evento especfico, simplesmente no acontece nada para aquele evento. Como veremos mais tarde, alm dos procedimentos de evento, voc pode dividir o seu programa, usando rotinas auxiliares. Nota: para melhor utilizao do ambiente de programao e da linguagem, consulte o help do Delphi. Os procedimentos de evento so armazenados na unidade, que um arquivo de texto associado ao formulrio. Voc pode editar todas as unidades no editor de cdigo do Delphi.

Delphi 4 Total

11

1997, 1998, 1999 GRIAULE

Componentes

A paleta de componentes lista tipos de componentes que podem ser utilizados no programa, como botes de pressionar, barras de rolagem, grades de dados e editores de texto. Para criar um componente, voc seleciona o cone correspondente e depois clica no formulrio para coloc-lo. Voc tambm pode cri-lo j com o tamanho desejado, pressionando o boto do mouse sobre o formulrio e arrastando para definir o tamanho. Nota: todos os componentes so descritos em detalhe no Help do Delphi, com todas suas propriedades, mtodos e eventos. Clique em um cone de componente e pressione F1 para ver o texto de help sobre ele. Note que h mais pginas do que cabe na tela em dado momento. Para ver as pginas restantes, como Dialogs, Midas, Win 3.1, Samples e ActiveX, clique nos botes ficam na extremidade direita da janela do Delphi. que

Alguns componentes no aparecem para o usurio durante a execuo do programa, apesar de aparecer no formulrio, e serem manipulados pelo cdigo do programa. So os componentes no-visuais (veremos alguns deles no decorrer do curso). Mas a maioria aparece como um objeto de interface durante a execuo. So os controles (ou componentes visuais). importante lembrar que todo controle um componente, mas nem todo componente um controle. O prprio formulrio tambm considerado um componente, embora seja tratado de forma diferente, e geralmente contm vrios outros componentes.

Viso Geral dos Componentes


A paleta de componentes se divide em vrias pginas para facilitar a organizao. Ns veremos alguns deles no curso, mas importante ter uma noo geral do contedo dessas pginas. Standard: componentes padro da interface do Windows, usados para barras de menu, exibio de texto, edio de texto, seleo de opes, iniciar aes de programa, exibir listas de itens etc. Geralmente so os mais usados. Additional: componentes especializados que complementam os da pgina Standard. Contm botes com capacidades adicionais, componentes para exibio e edio de tabelas, exibio de imagens, grficos etc.

Delphi 4 Total

12

1997, 1998, 1999 GRIAULE Win32: componentes comuns de interface que so fornecidos pelo Windows 95/NT para os programas. Contm componentes para dividir um formulrio em pginas, edio de texto formatado, barras de progresso, exibio de animaes, exibio de dados em rvore ou em forma de cones, barras de status e de ferramentas etc. System: componentes que utilizam funes avanadas do sistema operacional, como temporizao, multimdia, OLE e DDE. Internet: componentes para acesso aos recursos e protocolos da Internet, como criao de pginas Web dinmicas, acesso aos protocolos FTP, NNTP, POP, SMTP, TCP, UDP. Data Access: componentes para acesso a banco de dados. Data Controls: componentes visuais para mostrar dados em aplicaes de bancos de dados. So semelhantes aos componentes padro (Standard). Decision Cube (apenas Delphi Client/Server): componentes para anlise multidimensional de dados, com capacidades de tabulao cruzada [crosstab], criao de tabelas e grficos etc. QReport: QuickReport um gerador de relatrios que acompanha o Delphi. Os componentes desta pgina permitem desenhar o seu relatrio dentro do Delphi. Dialogs: O Windows tem caixas de dilogo comuns, como veremos, que facilitam mostrar uma interface padro dentro do seu programa para as tarefas comuns, como abrir e salvar arquivos, impresso, configurao de cores e fontes etc. Esta pgina tem componentes que permitem utilizar essas caixas de dilogo comuns. Midas (apenas Delphi Client/Server e Enterprise) : componentes utilizados para criar aplicaes multi-tiered. Win3.1: Esta pgina contm controles considerados obsoletos, que esto disponveis apenas para compatibilidade com programas antigos. No crie programas novos que utilizam esses controles. Samples: contm exemplos de componentes para que voc possa estud-los e aprender a criar seus prprios componentes. O cdigo fonte desses exemplos est no subdiretrio SOURCE\SAMPLES do diretrio de instalao do Delphi. ActiveX: um componente ActiveX um tipo de componente que pode ser criado em outra linguagem e utilizado no Delphi. Esta pgina contm alguns exemplos de componentes ActiveX prontos para utilizar, que tm funes de grficos, planilha, etc.

Delphi 4 Total

13

1997, 1998, 1999 GRIAULE

Propriedades
Componentes tm propriedades [properties], que definem suas caractersticas especficas e eventos, que so acontecimentos externos, geralmente relacionados com aes do usurio. Por exemplo o formulrio tem como propriedades o ttulo da janela (Caption), sua cor (Color), sua posio na tela (Left e Top). Um quadro de texto tem uma propriedade que define o texto que este contm (Text), entre outras. Quando o usurio clica com o mouse em um controle, isso causa um evento OnClick, e quando ele pressiona uma tecla, causa um evento OnKeyDown (entre outros). Para alterar propriedades durante o projeto da interface, voc seleciona o componente desejado (por exemplo Edit1), depois seleciona a propriedade desejada (por exemplo, Text) no Object Inspector e digita seu valor. Durante a execuo do programa, o cdigo pode alterar uma propriedade dinamicamente (em resposta a um evento). Para isso, basta inserir no cdigo de programa um comando como o seguinte:

Edit1.Text := 'Bem-vindo ao Delphi';


Nota: se voc clicar em uma propriedade e teclar [F1], o Delphi mostrar o texto de help relacionado quela propriedade.

Delphi 4 Total

14

1997, 1998, 1999 GRIAULE

Mtodos
Mtodos so nomes para aes executadas por um componente. No programa anterior, por exemplo, usamos o mtodo Clear, que quando executado, limpa o contedo de um controle. Por exemplo, no programa anterior, o procedimento de evento do boto Adicionar faz:

Edit1.Clear;
Quando esse comando executado, o controle esvaziado. Repare que todo mtodo chamado usando-se primeiro o nome do componente, depois o nome do mtodo, da mesma forma que uma propriedade. Mtodos s tem utilidade no cdigo do programa, por isso no aparecem no Object Inspector (mas veremos mais tarde que possvel consultar a lista de mtodos disponveis).

Delphi 4 Total

15

1997, 1998, 1999 GRIAULE

Object Pascal e Bibliotecas


Todo cdigo de programa no Delphi escrito em Object Pascal, que a linguagem de programao usada por ele. Essa linguagem derivada da linguagem Pascal original, e tem sido aperfeioada pela Borland por vrios anos, nas diversas verses do Turbo Pascal. A definio da linguagem contm as regras de sintaxe e os tipos de dados bsicos que voc pode usar. A maioria das rotinas teis do Delphi no fazem parte da linguagem em si, mas so implementados pela biblioteca de tempo de execuo [run-time library] do Delphi.

Delphi 4 Total

16

1997, 1998, 1999 GRIAULE

VCL - Visual Component Library


Os componentes, suas propriedades, eventos e mtodos so implementados pela biblioteca visual de componentes [Visual Component Library], tambm chamada VCL. O cdigo fonte da VCL fornecido com o Delphi e permite voc modificar os componentes ou estudar como eles foram feitos. Voc tambm pode criar novos componentes, escrevendo-os em Object Pascal. O prprio Delphi foi criado em Delphi, utilizando-se a linguagem Object Pascal e verses sucessivas do ambiente. Nota: se voc digitar apenas o nome do componente e um ponto, o CodeInsight do Delphi mostrar a lista das propriedades e mtodos disponveis. Ao continuar digitando, feita uma busca incremental nessa lista. Nota: para obter ajuda sobre qualquer elemento do Object Pascal ou da VCL, clique na palavra desejada, no editor de cdigo e pressione a tecla [F1].

Delphi 4 Total

17

1997, 1998, 1999 GRIAULE

Objetos
Componentes so apenas um tipo de objetos, que um termo bastante utilizado no Delphi. O prprio nome Object Pascal indica que se trata de uma linguagem orientada a objetos. Um objeto, numa definio prtica, uma rea de memria separada, contendo dados (variveis) e o cdigo que manipula esses dados. No caso de um componente, os dados aparecem como propriedades e o cdigo que os manipula composto de mtodos. Basicamente todo objeto contm propriedades e mtodos, mesmo que ele no possa ser colocado num formulrio e editado. Mais tarde veremos vrios exemplos de objetos que no so componentes.

Delphi 4 Total

18

1997, 1998, 1999 GRIAULE

Resumo
Para dominar a programao em Delphi, preciso conhecer os componentes da VCL, os objetos das bibliotecas do Delphi e a linguagem Object Pascal, que o fundamento no qual tudo se baseia.

Delphi 4 Total

19

1997, 1998, 1999 GRIAULE

Projetos
O Delphi trata cada aplicativo que voc cria como um projeto, que uma lista dos arquivos necessrios para construir um programa. Para saber quais so os formulrios, as unidades correspondentes, etc., o Delphi nos fornece o Project Manager, que pode ser acessado atravs do Menu View, opo Project Manager. A janela de ttulo do Delphi sempre tem, no ttulo, o nome Delphi - Nome do projeto. Um projeto em Delphi se compe de: Formulrios: um formulrio uma janela que projetamos no Delphi. Normalmente toda aplicao contm um ou mais formulrios. Cada formulrio tem uma unidade associada, que um arquivo contendo todo o cdigo associado a eventos; Unidades independentes: uma unidade independente contm cdigo do Delphi que no est necessariamente associado a nenhum formulrio ou controle em particular. Unidades independentes geralmente contm variveis e rotinas usadas por toda aplicao. Lembre-se que um projeto apenas uma lista dos arquivos usados para construir o programa, mas no os contm propriamente.

Salvando o Projeto em Disco


Ao gravar o projeto em disco, o Delphi cria vrios arquivos: dois para o projeto em si, e outros para cada formulrio e cada unidade independente usada. Os arquivos tm as seguintes extenses: Projeto: Formulrios: Unidades independentes: .DPR e .OPT (opes) .DFM e .PAS (unidade associada) .PAS

Alm disso, o Delphi gera outros arquivos no diretrio do projeto, a maioria deles quando voc compila o programa (por exemplo, automaticamente ao executar): Unidade compilada: Arquivo de recursos: Programa compilado: Arquivos de backup: nome-da-unit.DCU nome-do-projeto.RES nome-do-projeto.EXE *.~PA, *.~DF, *.~DP

Para salvar o projeto, juntamente com seus arquivos, use o item de menu File|Save All do Delphi. Da primeira vez que voc salva o projeto, o Delphi pede o nome do arquivo de formulrio (o padro "Unit1.PAS") e o nome do arquivo de projeto (o padro "Project1.dpr"). No necessrio digitar as extenses, pois o Delphi cuida de acrescentlas. Delphi 4 Total 20

1997, 1998, 1999 GRIAULE Quando voc salva um arquivo de formulrio, o Delphi salva dois arquivos: a unidade associada ao arquivo [unit], com uma extenso .PAS, que um arquivo contendo todo o cdigo de programa associado aos eventos, bem como todo o cdigo gerado pelo Delphi, e outro arquivo contendo as propriedades do formulrio e de todos os componentes, com o mesmo nome de arquivo, mas com a extenso .DFM. O arquivo de projeto um arquivo .DPR, que corresponde ao cdigo principal do programa executvel. A partir desse arquivo, o Delphi localiza os outros arquivos necessrios. Nota: o nome do arquivo de projeto deve ser diferente de qualquer unidade do projeto.

Comandos para trabalhar com Projetos


Vrios comandos do menu File do Delphi so usados para trabalhar com os projetos e os arquivos que fazem parte deles: New Cria um novo projeto vazio Application New Form Cria um novo formulrio e sua unidade Open... Reopen Abre um projeto ou unidade existente. Mostra os arquivos utilizados recentemente e permite reabrir qualquer um deles. Salva o arquivo atual (unidade). Se esta a primeira vez que est sendo salvo, pergunta pelo nome.

Save

Save As... Salva uma cpia do arquivo atual com outro nome ou em outro diretrio. Save Project As... Save All Close Close All

Salva o arquivo de projeto. Sempre pede o nome.

Salva todos os arquivos do projeto e o prprio arquivo de projeto. S pede nomes de arquivos para os que no foram salvos ainda. Fecha o arquivo atual. Fecha todos os arquivos e o projeto atual.

Alm desses comandos, existem cones na SpeedBar que podem ser usados para essas tarefas: (Open project) Equivale a File|Open, mas mostra apenas os arquivos de projeto.

Delphi 4 Total

21

1997, 1998, 1999 GRIAULE (Save all) (Open Project) (Save ) (Add file to project) (Remove file from project) O mesmo que File|Save all O mesmo que File|Open Project... O mesmo que File|Save Adiciona um arquivo ao projeto atual.

Remove um arquivo do projeto atual.

Delphi 4 Total

22

1997, 1998, 1999 GRIAULE

Grupos de Projetos
O delphi 4.0 permite trabalhar com mais de um projeto aberto, esses projetos podem ser definidos em um grupo. No menu View|Project Manager informado os projetos que pertencem a um determinado grupo.O arquivo de um grupo tem a extenso ".BPG"

Comandos para tabalhar com grupos de projetos


Vrios comandos do menu Project so usados para trabalhar com grupos de projetos , os principais so: Add New Project Add Existing Project Adiciona um novo projeto ao grupo.

Adiciona um projeto existente ao grupo

Compile Compila somente as units que foram modificadas, do projeto ativo. (Projeto Atual) Build ( Projeto Atual) Compile All Projects Build All Projects Compila todas as units do projeto ativo, independente se foram ou no modificadas. Compila somente as units que foram modificadas, dos projetos pertencentes ao grupo. Compila todas as units dos projetos pertencentes ao grupo, independente se foram ou no modificadas.

Delphi 4 Total

23

1997, 1998, 1999 GRIAULE

Edies do Delphi
O Delphi est atualmente na verso 4. Essa verso geralmente compatvel com programas desenvolvidos nas verses anteriores, embora alguns necessitem de modificao para funcionar, especialmente os feitos para a verso 1.0. importante saber tambm que existem vrias edies diferentes do Delphi, desde a Standard (a mais simples), passando pela Professional, que tem mais recursos, at a edio Client/Server Suite, mais sofisticada e com recursos teis para grandes empresas: Standard: muito limitada em recursos. Indicada apenas para quem tem interesse em desenvolvimento de pequenos programas ou para fins de aprendizado. Professional: inclui mais recursos que a edio Standard. Recomendada para desenvolvedores profissionais. Client/Server : inclui mais recursos que a Professional, especificamente voltados para grandes desenvolvedores que utilizam bancos de dados no padro cliente/servidor. Note que o Delphi 4 s funciona para ambientes de 32 bits, ou seja, Windows 95/98/etc. e Windows NT. Se voc quiser desenvolver programas compatveis com Windows 3.x, voc deve utilizar a verso 1.0.

Delphi 4 Total

24

1997, 1998, 1999 GRIAULE

Captulo 3 Exemplos Adicionais


Exemplo: Calculadora

Delphi 4 Total

25

1997, 1998, 1999 GRIAULE

Exemplo: Calculadora
O nosso objetivo criar uma calculadora simples, que apenas soma dois nmeros fornecidos e mostra o resultado, semelhante figura:

Criando os Componentes
Para comear, inicie o Delphi ou, se o Delphi estiver aberto, crie um novo projeto com File |New Application e altere a propriedade Caption da janela principal (Form1) para "Calculadora". Agora grave o projeto usando File | Save All no menu do Delphi. D os nomes de CALC ao formulrio e CALCP ao projeto. Isso vai salvar trs arquivos em disco, como j vimos: CALC.PAS A unidade unidade associada ao formulrio CALC.DFM Contm a definio do formulrio e seus controles. CALCP.DPR O arquivo de projeto, que lista os nomes dos outros. D dois cliques no cone Edit para criar um quadro de edio no formulrio. Mova-o at o topo do formulrio e altere a sua propriedade Name, para "editOperando1". A propriedade Name determina o nome que ser usado no programa para manipular esse componente, que ser usado para receber o primeiro operando digitado. Repita as mesmas aes para criar outro quadro de texto para o segundo operando. Ele dever ficar logo abaixo do primeiro. D o nome "editOperando2". Delphi 4 Total 26

1997, 1998, 1999 GRIAULE

Agora crie um boto de comando, com um clique duplo na ferramenta seu tamanho para ficar igual ao dos quadros de texto.

. Altere o

Nota: Quando voc cria um componente, ele recebe um nome default como Edit1, Button1, etc. recomendvel dar um nome mais descritivo para que seja mais fcil entender o programa mais tarde. Nota: No curso adotaremos um padro para nomes de componentes: um prefixo de trs ou quatro letras que diz o tipo de componente (edit para Edit, btn para Button, etc.) seguido de um nome descritivo (no caso, Operando1). Veremos que esse padro facilita a compreenso dos programas.

Altere sua propriedade Caption para "=" (sinal de igual). Altere Name para "btnCalcula". Finalmente crie um quadro de texto, posicionando-o abaixo do boto de comando, que vai conter o resultado. D o nome de "editResultado". Agora, para mostrar o sinal de "+" vamos usar um componente Label (rtulo), que e apenas mostra um texto para o usurio, no permitindo alterao. Selecione o cone desenhe um rtulo esquerda do editOperando2, como na figura. Altere sua propriedade Caption para conter um sinal de +. Para fazer com que esse sinal fique maior, selecione a propriedade Font, que corresponde s caractersticas do texto, e clique duas vezes do seu lado direito. Selecione "MS Sans Serif" na lista de fontes e um tamanho maior na lista "Tamanho". Depois clique Ok.

Tratando os Eventos
A interface da calculadora est pronta, mas ela ainda no executa a funo desejada. Precisamos acrescentar cdigo que leia os dois operandos, some os seus valores e coloque o resultado no ltimo quadro de texto. Clique duas vezes no boto 'btnCalcula', no formulrio. Isso vai criar um tratador de eventos para o evento padro do boto, que o evento OnClick. O Delphi vai gerar o seguinte cdigo:

procedure TForm1.btnCalculaClick(Sender: TObject); begin end;


Para fazer o clculo precisaremos de variveis. Uma varivel uma rea de memria que tem um nome e armazena um determinado valor. No Delphi, toda varivel tambm tem um tipo, que determina quais os valores que ela pode conter. Depois veremos todos os tipos de Delphi 4 Total 27

1997, 1998, 1999 GRIAULE dados em detalhes, mas por enquanto, usaremos o tipo de dados 'double', que permite armazenar valores numricos com parte fracionria, com a preciso de 15 a 16 dgitos significativos. Nota: Voc pode tambm selecionar o evento no Object Inspector e criar o tratador a partir do nome dele, mas para o evento padro, mais rpido um clique duplo no prprio componente. Variveis so declaradas com a palavra var, informando-se o nome e o tipo das variveis. Antes da palavra reservada begin, acrescente o seguinte:

var op1, op2: double; res: double;


Isso declara trs variveis: 'op1', 'op2' e 'res', todas do tipo double. Repare que duas variveis do mesmo tipo podem ser declaradas separando-as por vrgula antes do tipo ou em uma declarao separada.No necessrio repetir o var para vrias declaraes, pois elas terminam quando se encontra o begin. Agora vamos utilizar essas variveis para obter os valores digitados pelo usurio. Para ler o valor digitado em um controle Edit, devemos ler a propriedade Text, s que essa propriedade tem um valor alfanumrico (pode conter letras e nmeros), logo precisamos convert-la para numrico. Isso feito com a funo StrToFloat:

op1 := StrToFloat(editOperando1.Text); op2 := StrToFloat(editOperando2.Text);


Depois basta somar as variveis e mostrar o resultado, utilizando novamente uma funo de converso:

res := op1 + op2; editResultado.Text := FloatToStr(res);


O resultado final, com todo o cdigo acrescentado, ser o seguinte:

procedure TForm1.btnCalculaClick(Sender: TObject); begin op1 := StrToFloat(editOperando1.Text); op2 := StrToFloat(editOperando2.Text); res := op1 + op2; editResultado.Text := FloatToStr(res); end;
Repare que foi utilizada a identao (deslocamento direita) dos comandos, mas isso no obrigatrio no Delphi. Foi utilizado apenas para facilitar a legibilidade. Delphi 4 Total 28

1997, 1998, 1999 GRIAULE Nota: Nomes de variveis em Object Pascal podem ter at 63 caracteres e podem conter letras (A-Z, a-z), nmeros e o caractere '_'. O primeiro caractere no pode ser nmero. O Object Pascal no diferencia maisculas de minsculas (no case-sensitive).

Executando o Programa
Execute o programa com o boto ou a tecla [F9]. Digite um nmero no editOperando1 e outro no editOperando2 e depois clique no btnCalcula. Repare que voc pode usar a tecla [Tab] para passar de um controle para outro utilizando o teclado (e no [Enter], como no DOS). O controle que responde s teclas em determinado momento tem o foco de teclado. Cada controle indica o foco de forma diferente. Por exemplo, um controle Edit mostra o cursor de texto quando ele tem o foco, j um controle Button mostra um retngulo tracejado em volta do texto. Como veremos, esta ordem de foco pode ser alterada.

Melhoras de Interface
Alguns detalhes podem ser melhorados: primeiro, o quadro de edio 'editResultado' no deveria receber o foco quando o usurio pressiona [Tab] e no deveria permitir edio do texto, pois no faz muito sentido. Para isso, selecione o controle e altere sua propriedade TabStop para False. Voc pode fazer isso selecionando o valor a partir da lista (com o boto de seta) ou com um clique duplo no valor da propriedade, que alterna de True para False. Essa propriedade, quando False, faz com que o controle seja "pulado" pela tecla [Tab]. Tambm altere a propriedade ReadOnly para True, o que faz com que o controle no permita edio de seu valor. Outra mudana: como o usurio no usar a tecla [Enter], podemos fazer com que ela acione o boto "=". Basta alterar a propriedade Default do boto 'btnCalcula' para True (verdadeiro). Isso faz com que ele seja o boto default, que sempre acionado quando o usurio tecla [Enter]. Execute o programa e teste as modificaes. Ao executar o projeto podemos observar que os quadros de edio 'editOperando1', 'editOperando2' e 'editResultado' aparecem com seus respectivos nomes , o ideal seria aparecer inicialmente sem nenhuma informao, para fazer esta modificao vamos retornar ao projeto e alterar a propriedade Text de cada componente edit . a propriedade Text que indica o contedo do componente naquele momento, ao criar o componente edit e modificar a propriedade Name o delphi automaticamente coloca o mesmo contedo desta propriedade na propriedade Text, caso esta no tenha sido modificada antes.

Delphi 4 Total

29

1997, 1998, 1999 GRIAULE

Salvando o Projeto
Para salvar o projeto e todos os arquivos, basta usar File|Save All ou clicar no boto da SpeedBar. Com isso o Delphi vai salvar todas as alteraes feitas no projeto, como foi informado o nome do projeto e da unit ele no ir pedir novamente.

Delphi 4 Total

30

1997, 1998, 1999 GRIAULE

Captulo 4 Variveis e Tipos de Dados


Tipos de Dados Funes de Converso OPeraes Aritmticas Tipos Ordinais Escopo de Variveis Constantes

Delphi 4 Total

31

1997, 1998, 1999 GRIAULE

Tipos de Dados
Toda varivel tem um tipo, que determina quais os valores que voc pode colocar nessa varivel e quais as operaes que podem ser executadas sobre ela. Uma varivel de um tipo numrico, por exemplo, s pode receber valores numricos. Esses valores podem ser constantes, valores de outras variveis, ou expresses com operaes sobre valores. Para colocar um valor em uma varivel, usa-se o operador de atribuio: ':=' (dois-pontosigual), que lido como "recebe". Por exemplo:

procedure TForm1.Button1Click(Sender: TObject); var a: integer; { 'a' uma varivel do tipo Integer } b: integer; { 'b' idem } begin a := 2; b := a; b := b + 3; end;
Geralmente, com algumas excees, uma varivel de um determinado tipo s pode receber valores deste tipo. No permitido, por exemplo, o seguinte:

a := 'Nome';
...pois apenas valores numricos podem ser colocados na varivel 'a'. Existem vrios tipos de dados numricos, e cada um tem uma determinada faixa de valores e ocupa um certo espao de memria. No permitido colocar em uma varivel um valor que esteja fora da faixa do seu tipo.

Tipos Numricos
A linguagem Object Pascal tem vrios tipos de dados para variveis numricas, que so os seguintes: Tipo Tipos Inteiros Shortint Byte Smallint 1 1 2 -128 a 127 0 a 255 -32768 a32767 N/A N/A N/A BytesFaixa de Valores Preciso(dgitos)

Delphi 4 Total

32

1997, 1998, 1999 GRIAULE Word Integer Longint Cardinal Longword Int64 2 4 4 4 4 8 0 a 65535 -2 bilhes a 2 bilhes (-2.147.483.648 a 2.147.483.647) -2.147.483.648 a 2.147.483.648 0 a 4.294.967.295 0 a 4.294.967.295 -2
63

N/A N/A N/A N/A N/A N/A

a2

63

Tipos Reais Single Real48 Real Double Comp Currency Extended 4 6 8 8 8 8 10 1.5x10-45 a 3.4x1038 2.9x10-39 a 1.7x1038 5x10-324 a 1.7x10308 5x10-324 a 1.7x10308 -263 a 263
-922337203685477.5808 a 922337203685477.5807

7-8 11-12 15-16 15-16 19-20 19-20 19-20

3.6x10-4951 a 1.1x104932

*Nota: No Delphi 4, o tipo Real idntico ao tipo Double. No Delphi 3, o tipo Real tem uma faixa de valore menor que o Double e equivale ao tipo Real48 do Delphi 4. No recomendvel utilizar Real48, porque ele muito mais lento para clculos. A coluna "bytes" diz quantos bytes de memria so ocupados por uma varivel do tipo. Quanto maior a faixa de valores, em geral, maior o espao de memria. Os tipos numricos se dividem em tipos inteiros (ou integrais), que s permitem valores inteiros e tipos reais (ou de ponto flutuante [floating point]), que permitem valores com parte fracionria. Uma forma de entender a diferena que tipos inteiros so usados para contagem de elementos, enquanto tipos reais so usados para medir alguma coisa. E essa medida nem sempre exata. Ao fazer clculos com variveis reais, nem sempre o resultado igual ao esperado. Por exemplo:

var fracao, a, b: real; {'real' um tipo real}


Delphi 4 Total 33

1997, 1998, 1999 GRIAULE

begin a := 1.0; { o mesmo que 1 } fracao := a / 3; b := fracao * 3; if a = b then ... { faz alguma coisa } end;
Teoricamente no programa, 'a' igual a 'b', mas como tipos reais no representam valores exatos, a igualdade no exata. A varivel 'b' pode ter um valor de 0.99999999..., que ao ser comparado, no igual a 1.0. Cada tipo real tem uma certa preciso, indicada na tabela, que diz quantos dgitos significativos (dgitos excetuando zeros esquerda e direita) a varivel pode guardar, sem perda de preciso nos clculos. Assim, importante lembrar que os valores guardados em um desses tipos nem sempre exato. Geralmente os tipos inteiros so mais eficientes para clculos, e tambm mantm valores exatos para qualquer operao, desde que o resultado no saia da sua faixa de valores. Os tipos mais utilizados so smallint, para valores inteiros pequenos, integer ou Longint para valores inteiros maiores, e Double para valores reais com uma preciso razovel. Os tipos Shortint e Byte so utilizados quando preciso guardar um contador bem pequeno e necessrio economizar memria.Quando os tipos integer ou longint no so suficientes podemos usar os tipos longWord e int64 que existe somente nesta verso. O tipo Comp considerado como real, mas ele permite apenas valores inteiros. Ele til para valores monetrios.

O tipo Char
O tipo Char permite criar variveis que guardam caracteres individuais, como letras, dgitos, sinais de pontuao e caracteres de controle. Cada varivel do tipo Char s pode conter um caractere. Caracteres comuns (imprimveis) so representados entre aspas simples (apstrofos):

var minhaVariavel: Char; ... ... minhaVariavel := 'A';


Um caractere tambm pode ser representado atravs do cdigo ASCII/ANSI correspondente. Isso til principalmente com caracteres de controle, que no podem ser impressos nem digitados normalmente no programa, como caracteres de backspace, fim de linha, retorno de carro etc. Por exemplo, para guardar o caractere 13 (retorno de carro), usa-se a sintaxe: Delphi 4 Total 34

1997, 1998, 1999 GRIAULE

minhaVariavel := #13;
Se o cdigo estivesse numa varivel em vez de uma constante, no pode ser usada essa sintaxe. Nesse caso, pode-se usar a funo Chr:

codigoASCII := 13; minhaVariavel := Chr(codigoASCII);


Nota: para ver os caracteres da tabela ANSI (exceto os de controle), use o aplicativo Mapa de Caracteres do Windows (em Iniciar | Programas | Acessrios).

O tipo String
Para guardar mais de um caractere, preciso usar o tipo String. Um valor constante do tipo String representado entre apstrofos, como por exemplo:

var nome: string; begin nome := 'Joo da Silva';


Uma varivel string normalmente no tem limite de tamanho definido. O espao de memria que ela ocupa muda dinamicamente de acordo com o contedo atribudo a ela, por exemplo:

nome := '123'; {3 caracteres} nome := 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'; {26 caracs.} nome := ''; {zero caracteres}
No ltimo caso, tem-se uma string vazia, que representada por '' (apstrofos sem caracteres dentro), que ocupa zero caracteres. Ela usada para "limpar" o contedo de uma varivel. Nota: O Windows usa uma tabela de caracteres chamada tabela ANSI, que associa um cdigo numrico a cada caractere. Nota: o Windows permite caracteres acentuados e especiais, como , , , , , , etc. Mas uma varivel string pode ser declarada com um tamanho fixo, da seguinte forma:

var nome: string[50]; telefone: string[10];


Nesse caso, a varivel ocupa um espao fixo de memria, de acordo com o tamanho declarado. No exemplo, nome ocupa 50 caracteres e telefone ocupa 10. Se voc tentar atribuir mais caracteres do que cabe na varivel, os caracteres restantes so ignorados. Se Delphi 4 Total 35

1997, 1998, 1999 GRIAULE voc atribuir menos, o tamanho lgico da string passa a ser menor que o tamanho fsico. O Object Pascal usa um byte a mais para armazenar o tamanho lgico. Voc pode concatenar (juntar) duas ou mais strings com o operador +. Por exemplo:

var prefixo, linguagem, titulo: string; begin prefixo := 'Curso'; linguagem := 'Delphi'; titulo := prefixo + ' de ' + linguagem; { O resultado uma string 'Curso de Delphi' }
Para obter caracteres individuais de uma string, voc pode usar o nome da varivel e mais um valor entre colchetes. Por exemplo, se voc quiser guardar o 7 caractere do nome numa varivel char, basta fazer:

c := nome[7];
Existem vrias propriedades que tambm so do tipo String, como Caption e Text, por exemplo. Assim, possvel atribuir uma constante ou varivel do tipo String para elas, por exemplo:

btnIniciar.Caption := '&Iniciar'; memoTempoTotal.Text := s;


Nota: existem vrias funes de manipulao de strings, por exemplo, para obter uma parte de uma string. Consulte o help do Delphi e procure por 'String manipulation functions'.

O tipo Boolean
Vrias propriedades (e variveis tambm) podem conter os valores True (verdadeiro) e False (falso), indicando uma condio lgica ou um "flag" (ligado/desligado, habilitado/desabilitado, sim/no). Para isso utiliza-se o tipo Boolean, que s tem dois valores possveis: True e False. Por exemplo:

tmrMarca.Enabled := False;
O Delphi tambm utiliza o tipo Boolean internamente, ao fazer qualquer comparao lgica, em um comando if, por exemplo. E uma varivel do tipo Boolean sozinha j uma condio lgica, portanto pode ser usada em um comando if diretamente, por exemplo:

var ValorCorreto: Boolean; begin ...


Delphi 4 Total 36

1997, 1998, 1999 GRIAULE

if ValorCorreto then ... ... { Enabled uma propriedade do tipo Boolean } if tmrMarca.Enabled then ... ... end;

O tipo TDateTime
Para trabalhar com datas em Delphi, voc pode usar o tipo TDateTime. Veremos as operaes de data mais em detalhe em Manipulao de datas.

Delphi 4 Total

37

1997, 1998, 1999 GRIAULE

Funes de Converso
Qualquer varivel numrica pode receber um valor do mesmo tipo ou de um outro tipo numrico, exceto que uma varivel inteira (Integer, Longint, Word etc.) no pode receber um valor real, pois este pode conter uma parte fracionria. Por exemplo:

var a: integer; b: longint; x: double; y: extended; begin b := 10; a := b; {ok: inteiro recebe inteiro} x := a; {ok: real recebe inteiro} y := x; {ok: real recebe real} x := 3.7; b := x; {errado: inteiro recebe real} end;
Nesse caso preciso usar uma funo de converso, que ou descarta a parte fracionria (funo trunc) ou arredonda o valor (funo round):

x := 3.7; a := trunc(x); {a vai valer 3} b := round(x); {b vai valer 4}


Existem vrias funes que convertem valores de tipos numricos para o tipo String e viceversa. Ns j vimos algumas em programas-exemplo:

var varReal: double; varInteira: integer; varString: string; begin { de String para numrico: } varReal := StrToFloat(varString); varInteira := StrToInt(varString); varInteira64 := StrToInt64(varInteira64); { de numrico para String: } varString := FloatToStr(varReal); {VarInteira pode ser de varString := IntToStr(varInteira); qualquer tipo inteiro,inclusive int64 }
Delphi 4 Total 38

1997, 1998, 1999 GRIAULE

end;
Alm dessas, existe a funo Str, do Pascal padro, que converte um nmero qualquer para String, permitindo especificar uma largura de campo (o nmero alinhado direita com espaos) e a quantidade de casas depois da vrgula. Por exemplo:

segundos := 34.749; Str(segundos:7:2, s);


A varivel 's' vai ser preenchida com uma string 'oo34.75' (cada o representa um espao em branco). Ou seja, vai conter no mnimo 10 caracteres, com os dgitos alinhados direita e duas casas depois da vrgula (casas a mais so arredondadas).

Delphi 4 Total

39

1997, 1998, 1999 GRIAULE

Operaes Aritmticas
Os tipos de dados inteiros suportam as operaes aritmticas usuais: soma: subtrao: multiplicao: diviso: a := x + y; a := x - y; a := x * y; a := x / y;

Se os dois operandos so do mesmo tipo, o resultado desse tipo. Se um deles tem uma faixa de valores maior (por exemplo, um Double e um Integer), o resultado ser do tipo deste operando (no exemplo, Double). Para os nmeros inteiros o resultado ser do tipo int64 somente se tiver uma varivel deste tipo, caso contrrio o resultado ser do tipo integer. Se os dois operandos so inteiros, o resultado ser inteiro e pode ser atribudo para uma varivel inteira. Uma exceo que no caso da diviso, o resultado sempre real, mesmo quando os dois operandos so inteiros. Portanto, no permitido fazer:

a := b / c;
quando 'a' uma varivel inteira. Mas pode-se utilizar uma funo de converso, como trunc:

a := trunc( b /c );
ou usa-se o operador de diviso inteira div (os dois operandos dever ser inteiros), por exemplo:

b := 13; c := 4; a := b div c; {retorna a parte inteira da diviso = 3}


Existe tambm o operador mod, que calcula o resto da diviso:

x := b mod c; {retorna o resto de 13 div 4, que = 1}


Expresses podem ser combinadas com vrios operadores e operandos. Multiplicao e diviso so executadas primeiro, depois soma e subtrao, a menos que sejam usados parnteses, por exemplo:

x := a + b * c; {multiplica 'b' e 'c' e soma com 'a'} y := (a + b)*c; {soma 'a' e 'b' e multiplica por 'c'}
Delphi 4 Total 40

1997, 1998, 1999 GRIAULE

Delphi 4 Total

41

1997, 1998, 1999 GRIAULE

Tipos Ordinais
Um tipo de dados considerado um tipo ordinal quando existe uma seqncia definida entre seus elementos, ou seja, a partir de um elemento sempre possvel passar para o prximo elemento do tipo. Os tipos ordinais predefinidos pela linguagem (veremos que voc pode criar outros) so: Todos os tipos inteiros (Integer, Word, Cardinal, Longint,Enumerados...); O tipo Char (os caracteres so ordenados pela tabela ASCII/ANSI); O tipo Boolean (s tem dois elementos: False,True nessa ordem). Notas: Os tipos reais no so considerados tipos ordinais. Algumas operaes podem ser feitas com qualquer tipo ordinal. A funo succ retorna o prximo elemento do tipo, enquanto pred retorna o anterior:

var c1, c2: char; x, y: integer; a, b: boolean; begin c1 := 'G'; c2 := succ(c1); {vai ser c2 := pred(c1); {vai ser x := 299; y := succ(x); {succ(x) = a := False; b := succ(a); {vai ser = end;

= 'H'} = 'F'} x + 1 e pred(x) = x - 1} True}

Se voc chamar succ para o ltimo elemento da seqncia ou pred para o primeiro elemento, isso vai causar um erro de execuo (por exemplo, 'succ(True)' no permitido). A funo ord retorna a posio numrica do elemento dentro do tipo. No caso de um nmero inteiro, retorna o prprio nmero, portanto no tem utilidade prtica. No caso de um caractere, retorna o cdigo ASCII (ANSI) do caractere, que sua posio na tabela ASCII (ANSI):

x := ord('G'); {x vai ser 71}


No caso do tipo Boolean, ord(False) = 0 e ord(True) = 1. Isso pode ser usado para converter uma condio lgica em valor numrico. Mais tarde veremos outras operaes que podem ser executadas em tipos ordinais. Delphi 4 Total 42

1997, 1998, 1999 GRIAULE Notas : As funes succ e pred podem ser utilizadas para variveis do tipo int64, mas o mesmo no vlido para a funo ord.

Delphi 4 Total

43

1997, 1998, 1999 GRIAULE

Escopo de Variveis
O lugar onde declarada uma varivel determina o escopo de uma varivel, ou seja, qual a regio do programa onde a varivel pode ser acessada e o tempo de vida da varivel, ou seja, qual o intervalo de tempo durante o qual ela mantm seu valor. Qualquer varivel s pode ser utilizada no programa depois do ponto onde foi declarada.

Variveis Locais
Uma varivel declarada dentro de um procedimento uma varivel local. Ela s pode ser utilizada dentro do procedimento (o escopo da varivel o corpo do procedimento). O tempo de vida de uma varivel local o tempo durante a execuo do procedimento. Quando a execuo do procedimento iniciada, a varivel est indefinida, ou seja, seu valor pode ser qualquer dado que existia anteriormente na memria. Se esse valor for utilizado, os resultados so imprevisveis. Depois que o procedimento termina, a memria ocupada pela varivel liberada, e seu valor anterior perdido. Como j vimos, variveis locais so declaradas com a palavra var, logo aps o cabealho do procedimento, mas antes do begin que inicia os comandos:

procedure btnCalculaClick(Sender: TObject); var op1, op2, res: double; begin ... end;

Variveis Globais da Unidade


Se uma varivel precisa ser usada em vrios procedimentos, mantendo o seu valor, preciso declarar a varivel como global, ou seja, fora de qualquer procedimento. O escopo dessa varivel passa a ser desde o ponto onde foi declarada at o fim da unidade. Por exemplo:

implementation {$R *.DFM} var VariavelGlobal: integer;


Variveis globais so inicializadas com valores padro: zero para numricas, False para booleans, '' (texto vazio) para strings, etc. Elas mantm seus valores durante toda a execuo do programa. Ao declarar uma varivel global, voc pode fornecer um valor inicial diferente do padro. Para isto, a varivel deve ser declarada em separado de outras (no em uma lista) e depois Delphi 4 Total 44

1997, 1998, 1999 GRIAULE do tipo de dados, voc deve colocar um "=" e o valor inicial, que deve ser constante. Por exemplo:

var VariavelGlobal: integer = 1; Titulo: string = 'Ttulo inicial'; AtivaTimer: boolean = true;

Variveis Globais do Projeto


Uma varivel global, se declarada na parte implementation, s pode ser acessada dentro daquela unidade. Se for declarada na parte interface, pode ser usada por outra unidade, desde que essa outra tenha uma clusula uses para a unidade que contm a varivel. Veremos mais sobre isso em Estrutura das Unidades.

Delphi 4 Total

45

1997, 1998, 1999 GRIAULE

Constantes
Constantes so valores que podem ser colocados em variveis, usados em expresses etc. Uma constante literal um valor sem nome, escrito explicitamente, como os seguintes:

20 3.5 (constantes numricas - integer e double) 'Testando' (constante do tipo string) False True (constantes do tipo boolean) 'x' #8 (constantes do tipo char)
O tipo de dados de uma constante determinado pela forma desta. Nmeros sem parte fracionria so considerados constantes inteiras (isso se o nmero couber na faixa de valores de um tipo inteiro). Uma constante inteira tambm pode ser especificada como um valor hexadecimal, prefixado por '$', por exemplo:

x := $2F3;
Nmeros hexadecimais contm tambm os dgitos A at F, alm de 0 a 9. Uma constante real tambm pode ser escrita em notao cientfica, especificando-se um valor e uma potncia de 10:

y := 3.5e4; { = 3.5 x 104 = 35000 } z := 2.78e-6; { = 2.78 x 10-6 = 0.00000278 }


Voc pode criar constante especificando o tipo que esta constante ir retornar , por exemplo:

const Inteiro64 = int64(17)


Desta forma o tipo que a constante ir retornar int64. Voc tambm pode criar constantes nomeadas, que so simplesmente substitudas pelos valores correspondentes durante a compilao do programa. Elas facilitam a manuteno do programa, quando um valor utilizado em vrios lugares. Para isso, usa-se a declarao const:

const TAMANHO = 30; METADE = TAMANHO/2; PI = 3.1415926536; MENS_ERRO = 'Valor incorreto. Digite novamente.'; >
Constantes nomeadas so utilizadas como qualquer outra constante:

x := TAMANHO * 8;
Delphi 4 Total 46

1997, 1998, 1999 GRIAULE

angulo := PI*graus/180;
Mas no so variveis, portanto no podem receber outro valor:

TAMANHO := 15; { erro de compilao }


Da mesma forma que variveis, uma constante pode ser local (se declarada em um procedimento) ou global (se declarada fora).

Delphi 4 Total

47

1997, 1998, 1999 GRIAULE

Captulo 5 Estruturas de Controle


Inserindo Comandos com o CodeInsight Estruturas de Deciso Estruturas de Laos Outros Comandos

Delphi 4 Total

48

1997, 1998, 1999 GRIAULE

Inserindo comandos com o CodeInsight


Para facilitar a digitao dos comandos da linguagem e reduzir os erros, o CodeInsight do Delphi possui um recurso chamado modelos de cdigo [code templates], que permite inserir rapidamente um comando da linguagem contendo apenas a estrutura bsica, que depois voc pode preencher. Por exemplo, digite casee no editor de cdigo e tecle [Ctrl+J]. O CodeInsight ir inserir um comando case com uma clusula else e espaos em branco para voc completar:

case : : else end;

of ; ; ;

O cursor ficar posicionado entre case e of. Voc pode completar com um nome de varivel, valores constante e os comandos a serem executados. Para ver uma lista completa dos modelos de cdigo, tecle [Ctrl+J]. Veja por exemplo, os modelos ife, ifb, ifeb, ifs, forb, fore, whileb, whiles, caseb, cases. Note que os outros usam comandos do Object Pascal que ainda no foram vistos. ] Nota: voc pode alterar os modelos de cdigo ou criar novos. Para isso clique em Tools|Environment Options e na pgina CodeInsight. Nesta mesma pgina, voc pode tambm desmarcar a opo "Code Completion" se quiser. Essa opo mostra a lista de propriedades e mtodos de um componente quando voc digita o nome do componente e um ponto.

Delphi 4 Total

49

1997, 1998, 1999 GRIAULE

Estruturas de Deciso
O Comando if...then...else...
Ns j vimos o comando if em vrias situaes. A sua sintaxe bsica :

if condio then comando1 else comando2; { OU sem o else: } if condio then comando1;
A identao de comandos, ou a separao do comando em vrias linhas no so obrigatrias em nenhuma situao no Object Pascal. Mas geralmente um comando if escrito em vrias linhas, para maior legibilidade:

if condio then comando1 else comando2;


Dica: No editor de cdigo, para identar um bloco de comandos (deslocar direita), use [Ctrl+Shift+I]. Para deslocar esquerda, use [Ctrl+Shift+U]. Nessa sintaxe, condio qualquer expresso que gere um resultado do tipo Boolean (True para verdadeiro, False para falso), podendo ser uma nica varivel booleana, embora na maioria das vezes seja construda usando operadores de comparao, como '=', '>' etc. Note que no permitido o ';' (ponto-e-vrgula) logo depois do then ou logo antes ou depois do else. S pode haver ';' depois do fim do comando if. Se no houver o else, o ';' colocado depois do comando1. Por exemplo:

if memoEditor.SelLength <> 0 then menuEdiRecortar.Enabled := True else menuEdiRecortar.Enabled := False;


Quando, em lugar de comando1 ou comando2 preciso executar vrios comandos, usa-se os delimitadores begin e end para criar um comando composto. Um comando composto tratado pelo Object Pascal como um nico comando, por exemplo:

if condio then begin comando1; comando2; end else


Delphi 4 Total 50

1997, 1998, 1999 GRIAULE

begin comando3; comando4; end;


Dentro do comando composto, os comandos so separados por ';', mas fora dele se aplicam as regras do if. Um comando if pode ser usado dentro de outro, mas isso pode dificultar o entendimento se um deles inclui uma clusula else. Nesse caso o else fica ligado ao if mais prximo. Mais de uma condio pode ser usada no if, combinando-as com and (e), or (ou) e not (no). Mas nesse caso, so obrigatrios parnteses em volta das condies:

if (Key < '0') or (Key > '9') then Key := #0;


O operador and tem precedncia sobre o or, e o not tem precedncia sobre os dois, portanto preciso levar isso em conta em condies mais complexas, e utilizar parnteses para especificar o que se deseja avaliar primeiro:

if ((Key < '0') or (Key > '9')) and (Key <> #8) then Key := #0;
E o operador not pode ser usado para inverter o resultado de uma condio:

if ((Key < '0') or (Key > '9')) and not (Key = #8) then Key := #0;
Dica: para encontrar um fecha-parnteses perdido, coloque o cursor antes do abreparnteses e tecle [Ctrl+Q+[ ] (ctrl+Q+abre-colchetes).

O Comando case...of...
Muitas vezes preciso comparar uma varivel com vrios valores. Isso pode ser feito com vrios comandos if aninhados:

if dia = 1 then desconto = 30 else if dia = 2 then desconto = 20 else if dia = 3 then desconto = 10;
Mas o mesmo pode ser feito com o comando case, especificando a varivel, e seus valores possveis: Delphi 4 Total 51

1997, 1998, 1999 GRIAULE

case dia of 1: desconto = 30; 2: desconto = 20; 3: desconto = 10; end;


A sintaxe geral desse comando :

case expresso of rtulo1: comando1; rtulo2: comando2; ... else comandoElse; end;
Onde expresso pode ser qualquer varivel ou expresso que retorne um valor de um tipo ordinal. Cada rtulo pode ser uma constante sozinha, vrias constantes separadas por vrgulas, ou uma faixa de valores. Por exemplo:

case dia of 1: nome := 'primeiro'; { constante } 2: nome := 'segundo'; 3..10: nome := 'terceiro'; { valores entre 3 e 10 } 11,13,15: nome := 'quarto'; { valores 11, 13 e 15 } end;
Cada comando na sintaxe pode ser um comando simples ou um comando composto formado pelos delimitadores begin e end. A parte do else opcional e indica um comando a ser executado se nenhum dos valores corresponde ao valor da expresso.

Delphi 4 Total

52

1997, 1998, 1999 GRIAULE

Estruturas de Laos
Estruturas de lao permitem repetir um conjunto de comandos. Cada um dos comandos de lao especifica uma forma diferente de iniciar e testar o lao.

O comando for
O comando for permite repetir um lao um nmero especificado de vezes, incrementando ou decrementando uma varivel a cada passagem do lao. Voc deve especificar o valor inicial e final da varivel. A forma de uso a seguinte:

for varivel := valor_inicial to valor_final do comando;


O comando, como antes, pode ser um comando simples, ou um comando composto. A varivel, o valor inicial e o valor final devem ser todos de um tipo ordinal. Se no incio da execuo o valor inicial maior do que o final, o comando nem chega a ser executado. O seguinte lao mostra os valores numricos de 1 at 20 dentro de um componente ListBox:

var valor: integer; s: string; begin for valor := 1 to 20 do begin s := IntToStr(valor); ListBox1.Items.Add(s); end; end;
A varivel tambm pode ser do tipo Char, pois este um tipo ordinal:

for letra := 'A' to 'Z' do ...


Para decrementar a varivel durante o lao, ao invs de incrementar, usa-se downto no lugar da palavra to:

for letra := 'Z' downto 'A' do ... for valor := 20 downto 1 do ...
Note que o incremento ou decremento sempre 1. Delphi 4 Total 53

1997, 1998, 1999 GRIAULE

O comando while...do...
O lao while repete um comando enquanto determinada condio verdadeira. Sua sintaxe de forma geral :

while condio do comando;


Por exemplo:

i := valorAnt; while i < 1000 do begin Processar(i); i := i + incremento; end;


Antes da primeira iterao do lao, a condio verificada. Se ela for falsa, o comando no chega a ser executado. Se for verdadeira, o comando executado, e a condio verificada novamente e assim por diante.

O comando repeat..until
O repeat..until semelhante ao while, mas testa a condio no final, depois de executar o comando, e termina a execuo se a condio for verdadeira (o contrrio do while). Sua sintaxe geral :

repeat comando1; comando2; ... until condio;


Por exemplo:

i := valorAnt; repeat Processar(i); i := i + incremento; until i >= 1000;


O comando repeat sempre executa uma iterao do lao pelo menos. Note que ele no precisa de begin e end para delimitar a lista de comandos, pois as prprias palavras repeat e until j formam delimitadores.

Delphi 4 Total

54

1997, 1998, 1999 GRIAULE

Outros Comandos
Comandos para sair de laos
Durante a execuo de um lao, comum precisar terminar sua execuo antes do tempo. Para isso, pode ser usado o comando break. Este comando sai imediatamente do lao mais interno (seja for, while, ou repeat) e vai para o prximo comando depois do lao. Por exemplo:

for i := 1 to 1000 do begin encontrou := ProcuraValor(i); if Encontrou(i) then break; end; { o break salta para esta linha }
Alm desse, existe o comando continue. Ele fora a execuo da prxima iterao (repetio) do lao, ignorando os comandos restantes dentro do bloco do lao. Por exemplo, o prximo lao mostra em uma list box os nmeros de 1 a 300, exceto os mltiplos de 7:

for x := 1 to 300 do begin if x mod 7 = 0 then { um mltiplo de 7? } continue; { vai para o prximo } s := IntToStr(x); ListBox1.Items.Add(s); end;

O comando exit
Para sair imediatamente de um procedimento, usa-se o comando exit. Use-o quando ocorre alguma condio de erro, por exemplo:

if valorErrado then begin mostrarMensagem; exit; end;

Delphi 4 Total

55

1997, 1998, 1999 GRIAULE

Captulo 6 Propriedades e Eventos Comuns


Tipos de Propriedades Propriedades Mais Usadas Eventos Comuns Detalhes do Tratemnto de Eventos

Delphi 4 Total

56

1997, 1998, 1999 GRIAULE

Tipos de Propriedades
Existem vrias formas de editar o valor de uma propriedade, dependendo da propriedade especfica. Ns j vimos a maioria delas, que so basicamente as seguintes: Propriedades que aceitam qualquer valor: voc precisa digitar o valor diretamente. Exemplo: Caption, Text. A propriedade Name s aceita um identificador vlido (mesmas regras que nomes de variveis). Propriedades numricas: O Delphi permite digitar qualquer coisa, mas quando voc teclar [Enter] ou sair, ele vai verificar se um valor numrico. Exemplo: Left, Top, MaxLength (do componente Edit). Propriedades de lista: Um boto aparece ao lado do valor. Ao clicar nele, abre-se uma lista de valores, e possvel selecionar um deles:

Exemplo: BorderStyle, Color, WindowState, Align. Geralmente o valor s pode ser um dos disponveis na lista, mas algumas propriedades permitem digitar outros valores, como Color. Propriedades booleanas: uma propriedade do tipo Boolean, que s tem dois valores possveis: False e True. Exemplo: Enabled, Visible, Ctl3D. Voc pode selecionar um deles na lista, mas mais fcil usar , com um clique duplo no valor, o contedo ser alternado entre True e False ou clicar no boto . Propriedades expansveis: um sinal de "+" aparece ao lado da propriedade e, clicando duas vezes no nome, ela se expande em sub-propriedades. Exemplo: Font.

Para fechar a lista de sub-propriedades, clique duas vezes no nome da propriedade. Para usar essa propriedade em tempo de projeto, utiliza-se um ponto a mais e o nome da subpropriedade, por exemplo:

memoEditor.Font.Color := clBlack;
Delphi 4 Total 57

1997, 1998, 1999 GRIAULE Propriedades de conjunto: So parecidas com propriedades expansveis. As "subpropriedades" que aparecem so todas booleanas (True/False). Exemplo: BorderIcons, Font.Style. O valor que aparece um conjunto de valores, que como veremos mais tarde, exige uma sintaxe diferente para ser usado no programa.

Para alterar a propriedade dentro do programa, use por exemplo:

BorderIcons := [biSystemMenu, biMaximize];


Propriedades com editor: Algumas propriedades mostram um valor como (TFont) ou (TStringList), que no pode ser editado, e um boto , que quando clicado mostra um editor de propriedade especializado. Exemplo: Lines (do componente Memo), Font (que tambm pode ser editada abrindo as sub-propriedades). O editor tambm pode ser chamado com um clique duplo na coluna de valor.

Delphi 4 Total

58

1997, 1998, 1999 GRIAULE

Propriedades Mais Usadas


Propriedades para Todos os Componentes
Duas propriedades existem para qualquer componente (inclusive para o formulrio, que considerado um componente): so Name (o nome do componente) e Tag. Esta ltima uma propriedade numrica (tipo integer) que o Delphi no utiliza. Ela pode ser usada para guardar uma informao qualquer associada ao componente, apenas para uso interno.

Propriedades de Tamanho e Posio


Voc pode alterar o tamanho e a posio do formulrio, ou de um controle, movendo-o na tela ou arrastando suas bordas. Mas voc tambm pode digitar suas coordenadas de posio e tamanho manualmente. Essas coordenadas so medidas em pixels, que so os pontos fsicos da tela, e so especificadas pelas propriedades Left, Top, Width e Height:

Para um formulrio, Left a distncia deste extremidade esquerda da tela, Top a distncia em relao ao topo da tela. Para um controle, essas medidas so feitas em relao rea interna do formulrio (excluindo as bordas). O tamanho do formulrio ou controle especificado por Width (na horizontal) e Height (na vertical). Todas essas propriedades podem ser alteradas tambm atravs de comandos de programa, para alterar dinamicamente a posio e tamanho de um controle.

Propriedades do Formulrio
Outras propriedades alteram o posicionamento e tamanho do formulrio. A maioria dessas propriedades s mostra efeito ao executar o programa. A propriedade WindowState controla como o formulrio vai aparecer: wsNormal Delphi 4 Total estado normal 59

1997, 1998, 1999 GRIAULE wsMinimized wsMaximized janela minimizada (aparece na forma de um cone) janela maximizada (ocupando a tela inteira)

A propriedade Position determina se o Windows pode alterar a posio ou o tamanho que voc definiu para o formulrio. O valor padro 'poDesigned': poDesigned poScreenCenter poDefault poDefaultPosOnly poDefaultSizeOnly posio e tamanho de acordo com o projetado centraliza o formulrio na tela o Windows pode mudar a posio e tamanho o Windows s pode mudar a posio o Windows s pode alterar o tamanho

A propriedade BorderStyle controla o estilo da borda do formulrio: bsSizeable bsSingle bsDialog bsNone bsToolWindow bsSizeToolWin permite o usurio alterar o tamanho da janela no permite alterar tamanho (estilo de borda fina) no permite alterar tamanho (estilo de borda dupla) nenhuma borda, nem barra de ttulo (no permite mover) como bsSingle, mas com ttulo menor como bsSizeable, mas com ttulo menor

O valor padro 'bsSizeable'. A diferena entre 'bsSingle' e 'bsDialog' uma questo de padres de interface, como veremos depois. A propriedade BorderIcons, que se expande em "sub-propriedades", determina quais cones de controle aparecem na barra de ttulo do formulrio. Cada valor correspondente aos elementos da barra, e alterando-o para True ou False pode-se ativar ou desativar um deles (o efeito s aparece ao executar o programa):

O outro valor, biHelp, coloca um boto de ajuda com uma interrogao na borda. Esse boto pode ser usado para chamar uma tela de help. S funciona se biMinimize e biMaximize estiverem desativados. A propriedade AutoScroll, como padro, verdadeira (contm o valor True). Isso faz com que o formulrio mostre barras de rolagem automaticamente quando os controles no cabem na rea visvel da tela. Para testar, crie um controle qualquer, como um Edit e Delphi 4 Total 60

1997, 1998, 1999 GRIAULE mova-o at deixar metade dele fora do formulrio em alguma das extremidades. Vai aparecer uma barra de rolagem (horizontal ou vertical), que voc pode usar para ver a rea que atualmente no visvel. Se voc quiser, pode desativar AutoScroll, colocando um valor False. Com isso, controles que estiverem fora da rea do formulrio no podem ser acessados pelo usurio.

Propriedades de Controles
Controles (ou componentes visuais), alm das quatro propriedades de posio (Left, Top, Width e Height) tm propriedades que alteram sua aparncia, a maioria existe tambm no formulrio. A propriedade Font determina as caractersticas do texto mostrado pelo controle. No caso do formulrio, ela afeta os controles contidos nele, no o prprio. Para testar, coloque trs controles Label no formulrio. Altere a propriedade Font do formulrio, mudando o nome da fonte para "Times New Roman". Isso vai afetar os dois controles. Agora altere a propriedade Font de um dos controles, "Label1", mudando Font.Name para "Arial". S esse controle ser afetado. Se voc novamente alterar a fonte do formulrio, apenas "Label2" e "Label3" sero alterados. O que determina se um controle usa uma fonte prpria ou a do formulrio a propriedade ParentFont. Note que ParentFont False para o "Label1" (que foi alterado) e True para os outros dois. Quando voc altera a fonte individualmente de um controle, ParentFont automaticamente mudado para False. Se voc mudar ParentFont para True, a fonte do controle vai ser alterada para ficar igual do formulrio. A propriedade Color determina a cor do formulrio ou controle. Existem vrias formas de escolher uma cor. Voc pode selecionar da lista o nome de uma cor especfica (clBlack = preto, clBlue = azul, etc.) e nesse caso, a cor ser sempre a que voc especificou. Outra opo usar nomes de cores relativas configurao do Windows, como clWindow = cor de janela, clBtnFace = cor de boto, clWindowText = cor de texto de janela etc. Nesse caso, a cor real que ser utilizada depende da configurao de cores do Windows no computador do usurio. Para cada controle que tem a propriedade Color, existe tambm uma propriedade ParentColor, que determina se o controle usa a cor definida pelo formulrio ou sua prpria cor individual (de forma anloga a Font e ParentFont). Como j vimos, um controle ou um item de menu pode ser habilitado ou desabilitado com a propriedade Enabled (True ou False). Voc tambm pode esconder um controle ou item de menu do usurio alterando a propriedade Visible para False. Ele continua aparecendo em tempo de projeto, e voc ainda pode utiliz-lo no programa, mas o usurio no vai v-lo durante a execuo. O texto mostrado por um controle definido pela propriedade Caption, se ele no permite edio, ou Text, se ele permite edio pelo usurio. Delphi 4 Total 61

1997, 1998, 1999 GRIAULE Uma facilidade que o Delphi fornece a capacidade de colocar "dicas" [hints] que so mostradas quando o usurio passa o mouse por cima de um controle. A propriedade Hint de um controle define qual o texto da dica. Para que a dica seja exibida, a propriedade ShowHint deve ter o valor True. Essa propriedade pode ser definida para cada controle individualmente, ou para o formulrio (nesse caso, ParentShowHint, em cada controle, define qual das duas usada). A propriedade Cursor define qual o tipo de ponteiro (ou cursor) do mouse que ser mostrado. O valor padro (crDefault) diz para utilizar o cursor padro atual (geralmente uma seta). Outros valores determinam ponteiros diferentes, por exemplo crArrow (seta), crHourglass (ampulheta).

Delphi 4 Total

62

1997, 1998, 1999 GRIAULE

Eventos Comuns
Crie um novo projeto. Nesse projeto, veremos os eventos mais utilizados pela maioria dos componentes, e tambm algumas propriedades vistas anteriormente.

Eventos de Mouse
O evento OnClick, como j vimos, ocorre quando o boto do mouse pressionado e solto sobre o controle (mas alguns controles, como botes, tambm acionam este evento quando so ativados pelo teclado). Esse evento no fornece nenhuma informao sobre as coordenadas do mouse. Alm desse, existe o evento OnDblClick, que informa um clique duplo (dois cliques em seqncia rpida). Os eventos OnMouseDown e OnMouseUp so acionados quando um boto do mouse pressionado ou liberado, respectivamente, quando o cursor do mouse est posicionado sobre o controle. Esses eventos informam a posio do mouse, qual boto foi pressionado e quais das teclas de modificao ([Shift], [Ctrl] e [Alt]) estavam pressionadas no momento. O evento OnMouseMove ocorre quando o cursor do mouse movimentado sobre o controle. Ele informa a posio atual do cursor do mouse. Vamos tratar o evento OnClick para o formulrio. Digite o seguinte no procedimento de evento:

procedure FormClick(Sender: TObject); begin if Cursor = crDefault then {cursor o padro?} Cursor := crHourglass {muda para ampulheta} else Cursor := crDefault; {seno muda pra default} end;
importante notar que Cursor uma propriedade do formulrio. Nesse caso, no preciso escrever o nome do formulrio na frente (o que seria Form1.Cursor), basta o prprio nome. Execute para testar. Agora quando voc clicar no formulrio, o ponteiro vai mudar para uma ampulheta. Clicando novamente ele retorna ao valor padro.

Eventos de Teclado
Existem trs eventos de teclado, que so acionados em momentos diferentes. Cada um deles fornece informao sobre a tecla pressionada, mas de formas diferentes. Para cada tecla que pressionada, o evento OnKeyDown acionado, e quando a tecla solta, OnKeyUp acionado. Ambos informam para o procedimento de evento o cdigo da tecla pressionada. Esse cdigo identifica a tecla, mas no o caractere digitado. Por exemplo, no possvel distinguir entre maisculas e minsculas, ou entre dois caracteres na mesma tecla. Alm disso, um caractere pode ser gerado pelo pressionamento de mais de uma tecla. Delphi 4 Total 63

1997, 1998, 1999 GRIAULE Quando necessrio distinguir os caracteres digitados, e no as teclas, pode ser utilizado o evento OnKeyPress. Ele informa o caractere digitado como uma varivel do tipo Char. Note que nem toda tecla aciona um evento OnKeyPress. Teclas que no geram digitao, como [F1], [Insert], [Home], [Ctrl], acionam apenas os eventos OnKeyDown e OnKeyUp. Vamos tratar esses eventos para o formulrio. Crie o seguinte procedimento de evento, associado ao OnKeyPress:

procedure TForm1.FormKeyPress(Sender: TObject; var Key: Char); begin if Key = '*' then Close; end;
Nota: A varivel 'Key' um parmetro do procedimento de evento, que preenchido pelo Delphi. Alguns eventos tm parmetros, que contm informaes adicionais fornecidas pelo Delphi. Com isso, quando for pressionada a tecla ('*'), o formulrio ser fechado, usando o mtodo Close. Agora vamos tratar as teclas de seta, fazendo a movimentao do formulrio na direo da seta utilizada. Inicialmente, crie um procedimento de evento para OnKeyDown:

procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); begin end;
Repare que o procedimento tem vrios parmetros: 'Key', que desta vez numrica (tipo Word) informa o cdigo da tecla pressionada e 'Shift' informa o estado das teclas de modificao. Para tratar as setas, precisamos comparar o valor de Key com cada um dos cdigos de teclas de seta. Na verdade no preciso saber o valor numrico de todos os cdigos. O Delphi tem constantes predefinidas correspondentes aos valores. Entre o begin e o end digite o seguinte:

case Key of vk_Left: Left := Left - 10; vk_Right: Left := Left + 10; vk_Up: Top := Top - 10; vk_Down: Top := Top + 10; end;
Delphi 4 Total 64

1997, 1998, 1999 GRIAULE O comando case..of.., como veremos, compara uma varivel com vrios valores numricos e executa um comando dependendo do valor. No caso os valores so dados pelas constantes 'vk_Left', 'vk_Right',... As propriedades Left e Top determinam a posio do formulrio na tela. Para mover o formulrio, basta alterar seus valores. Execute e teste as teclas de seta para movimentar e a tecla '*' para fechar o formulrio. Salve esse projeto como EVENTOS.PAS e EVENTOSP.DPR.

Eventos do Formulrio
Outros eventos do formulrio correspondem a situaes importantes de serem tratadas, por exemplo: OnCreate: Quando o formulrio criado, ou seja, na inicializao do programa. executado antes de qualquer outro evento do formulrio. Voc pode usar para inicializar componentes. OnDestroy: Quando o formulrio est sendo destrudo, ou seja, a sua rea de memria ser liberada. Ocorre geralmente quando o programa est terminando. OnShow: Logo antes do formulrio ser mostrado na tela (pode ocorrer vrias vezes durante a execuo). OnCloseQuery: O usurio est tentando fechar o formulrio. Voc pode cancelar o fechamento (fazendo CanClose := False) ou, por exemplo, confirmar se ele deseja salvar os dados. OnClose: O formulrio est sendo fechado. Voc pode cancelar o fechamento ou determinar uma ao diferente, como minimizar, ou destruir o formulrio. OnActivate: O formulrio passou a ser a janela ativa (recebeu o foco). OnDeactivate: O formulrio passou a ser uma janela inativa. OnResize: Quando o usurio altera o tamanho do formulrio. OnPaint: til para desenho de grficos.

Outros Eventos
Os controles que podem receber o foco de teclado tm eventos que so acionados quando o foco de teclado muda. O evento OnEnter acionado quando o controle recebe o foco de teclado, depois de um clique do mouse, por exemplo, ou depois que o usurio tecla [Tab] a partir do controle anterior. J o evento OnExit acionado quando o controle perde o foco de teclado, depois que o usurio passa para outro controle por exemplo.

Delphi 4 Total

65

1997, 1998, 1999 GRIAULE Controles de edio e similares possuem um evento OnChange. Esse evento acionado quando ocorre uma modificao no contedo do texto, por exemplo, acrescentar ou apagar um caractere.

Delphi 4 Total

66

1997, 1998, 1999 GRIAULE

Detalhes do Tratamento de Eventos


Vamos retornar ao projeto CALCP. Acione o menu File|Open... ou o cone SpeedBar e abra o CALCP.DPR. da

Tratando um Evento para Vrios Controles: OnKeyPress


Como vimos, existem trs eventos relacionados ao teclado, que permitem interceptar cada tecla digitada pelo usurio. Podemos usar o evento OnKeyPress para validar a digitao e s permitir digitao de nmeros. Nota: existem formas bem mais fceis de fazer validao de teclas no Delphi, como usar o componente MaskEdit da pgina Additional, mas faremos dessa forma apenas para fins de aprendizagem. Mas o tratamento deve ser o mesmo para os dois componentes Edit. Isso quer dizer que os dois acionaro um mesmo procedimento de evento. Selecione no formulrio os controles 'editOperando1' e 'editOperando2'. No Object Inspector, abra a pgina de eventos, clique em OnKeyPress e clique duas vezes no valor do evento. Lembre-se: para selecionar dois controles, clique no primeiro, segure [Shift] e clique no outro. O Delphi vai criar um procedimento da forma:

procedure editOperando1KeyPress(Sender:TObject; var Key: Char); begin end;


O nome do procedimento ("editOperando1KeyPress") baseado no primeiro controle, mas isso no importa. Quando voc cria um procedimento de evento dessa forma, ele fica associado a todos os componentes selecionados e vai ser executado quando o evento acontece com qualquer um deles no caso, quando o usurio digita uma tecla em um deles. O parmetro "Key" que passado contm a tecla digitada. Vamos verificar se ela numrica, e se no for, rejeitar a tecla:

procedure TForm1.editOperando1KeyPress( Sender: TObject; var Key: Char); begin


Delphi 4 Total 67

1997, 1998, 1999 GRIAULE

if (Key < '0') or (Key > '9') then Key := #0; { rejeita a tecla } end;
O caractere #0 no a mesma coisa que '0'. O primeiro o chamado caractere nulo (cdigo ASCII 0) que no corresponde a nenhum caractere imprimvel. O outro o dgito zero (cdigo ASCII 48). Quando o procedimento altera 'Key' para o valor #0, isso faz com que seja cancelada a digitao. Execute o programa e verifique que apenas caracteres numricos aparecem. Outros so simplesmente ignorados. Mas existe um problema: a tecla [Backspace] no funciona mais. Isso acontece porque [Backspace] gera um evento OnKeyPress, com o cdigo ASCII 8 (caractere #8). Para corrigir isso, altere o if para o seguinte:

if ((Key < '0') or (Key > '9')) and (Key <> #8) then Key := #0; { rejeita a tecla }

Renomeando um Procedimento de Evento


O nome de um procedimento de evento aparece no cdigo depois de "procedure TForm1.". Esse nome criado pelo Delphi juntando o nome do componente que foi selecionado para tratar eventos, com o nome do evento (sem o "On"). Mas quando um mesmo procedimento acionado por vrios eventos (ou componentes) melhor mudar esse nome. Quando voc percorre o arquivo da unidade, o nome ajuda a reconhecer a funo daquele procedimento. Para mudar o nome, selecione qualquer um dos dois componentes, clique no Object Inspector, no evento OnKeyPress. Substitua o nome atual "editOperando1KeyPress" por "TratarTecla" e tecle [Enter]. Depois clique duas vezes nesse nome e verifique que na unidade, o Delphi renomeou o procedimento:

procedure TForm1.TratarTecla(Sender: TObject; var Key: Char); begin if ((Key < '0') or (Key > '9')) and (key <> #8) then Key := #0; { rejeita a tecla } end;
Voc no deve mudar o nome diretamente no texto da unidade. Se fizer isso, o Delphi no conseguir localizar mais o procedimento e mostrar vrias mensagens de erro.

Associando um Procedimento Existente


Se depois de criar um procedimento, voc criar um novo componente, ou se voc esqueceu algum componente de fora ao criar o procedimento, voc pode lig-lo a um procedimento j existente. Delphi 4 Total 68

1997, 1998, 1999 GRIAULE Selecione no formulrio apenas o componente 'editResultado' (clique nele sem usar o [Shift]). Clique no evento OnKeyPress e no boto de seta . Aparece na lista o nome do procedimento de evento "TratarTecla". Selecione esse nome. Basta isso para associar o cdigo dos procedimentos com os eventos correspondentes do controle. Nesse caso, no til associar esse procedimento, porque o "editResultado" no aceita digitao ( somente leitura). Clique no evento OnKeyPress novamente e apague o nome do procedimento. Isso desfaz a associao.

Eliminando um Procedimento de Evento


Se voc quiser eliminar um procedimento de evento, no apague o corpo dele no cdigo. Apague apenas os comandos entre o begin e o end , necessrio tambm excluir as declaraes de variveis, se houver. Quando voc compila o programa, o Delphi nota que o procedimento est vazio, e o remove automaticamente do programa. S para teste, clique duas vezes no componente 'editOperando1'. Isso vai criar um procedimento para o evento OnChange, que executado quando o contedo do controle alterado. comum criar um procedimento por acidente, dessa forma. Agora salve o projeto. Repare que o procedimento vai desaparecer automaticamente. Nota: os procedimentos que aparecem na lista so apenas aqueles compatveis com o evento. Um procedimento compatvel quando a lista de parmetros (entre parnteses, no cabealho) est de acordo com o que o evento espera.

Delphi 4 Total

69

1997, 1998, 1999 GRIAULE

Captulo 7 Usando Vrios Formulrios


Caixas de Dilogo Funes de Mensagem Exemplo: CalcData Gerenciando os Arquivos do Projeto Definindo o Formulrio Principal

Delphi 4 Total

70

1997, 1998, 1999 GRIAULE

Caixas de Dilogo
Um programa em Delphi geralmente tem um formulrio principal, que aparece inicialmente, e com o qual o usurio interage. A partir desse formulrio, o usurio pode abrir outros formulrios do programa. Os formulrios auxiliares, chamados a partir do principal, geralmente so caixas de dilogo. Uma caixa de dilogo uma janela com a qual o usurio interage e depois retorna ao principal. Algumas funes do Delphi mostram caixas de dilogo predefinidas e voc no precisa criar um formulrio para us-las. Mas geralmente, quando voc precisa de alguma coisa a mais, voc deve criar um formulrio e utiliz-lo como uma caixa de dilogo.

Delphi 4 Total

71

1997, 1998, 1999 GRIAULE

Funes de Mensagem
Mensagens Informativas
O procedimento ShowMessage permite mostrar uma mensagem simples para o usurio, contendo apenas um boto de Ok. O ttulo da aplicao aparece no ttulo da mensagem. Por exemplo, a chamada:

ShowMessage('Erro de digitao no campo Nome. ' + 'Digite novamente.');


mostra uma mensagem como a seguinte (supondo que o ttulo da aplicao 'Meu Programa'):

Nota: para definir o ttulo da aplicao, abra o menu Project|Options, clique no marcador "Application", e digite o novo ttulo em Title. Esse ttulo ser usado em todas as mensagens de agora em diante. Esse procedimento geralmente usado para mensagens curtas, que no precisam de nenhum retorno do usurio. Note que se o texto da mensagem muito longo, voc pode dividir a string em partes, usando o operador "+". Se voc precisar de quebras de linha na mensagem, voc pode inserir os caracteres de fim de linha, #13 e #10. Por exemplo:

ShowMessage('Erro de digitao no campo Nome. '#13#10 + 'Digite novamente.');

Mensagens de Confirmao
A funo MessageBox, que um mtodo do objeto Application, mostra uma mensagem com botes que o usurio pode clicar para responder. De forma geral, a sintaxe para usar essa funo :

varivel := Application.MessageBox(mensagem, ttulo, flags);


onde: mensagem: o texto da mensagem Delphi 4 Total 72

1997, 1998, 1999 GRIAULE ttulo: o ttulo que aparece na janela de mensagem. flags: uma combinao de valores que determina quais botes ou cones so usados na janela de mensagem. (Ver abaixo) varivel:recebe um valor inteiro que indica qual boto foi pressionado. Esse valor pode ser um dos seguintes: IDOK IDCANCEL IDABORT IDRETRY IDIGNORE IDYES IDNO boto Ok boto Cancelar boto Anular boto Repetir boto Ignorar boto Sim boto No

O valor de flags pode ser uma combinao de um ou mais dos seguintes valores: MB_OK MB_OKCANCEL MB_ABORTRETRYIGNORE MB_YESNOCANCEL MB_YESNO MB_RETRYCANCEL MB_ICONERROR 0 1 2 3 4 5 16 s boto Ok (default) botes Ok e Cancelar botes Anular, Repetir e Ignorar botes Sim, No e Cancela botes Sim e No botes Repetir e Cancelar

sinal de erro crtico

MB_ICONQUESTION

32

sinal de pergunta

MB_ICONEXCLAMATION

48

sinal de advertncia

Delphi 4 Total

73

1997, 1998, 1999 GRIAULE MB_ICONINFORMATION MB_DEFBUTTON1 MB_DEFBUTTON2 MB_DEFBUTTON3 64 0 256 512

sinal de informao primeiro boto tem o foco (default) segundo boto tem o foco terceiro boto tem o foco

Veremos exemplos dessas funes no prximo projeto.

Delphi 4 Total

74

1997, 1998, 1999 GRIAULE

Exemplo: CalcData
Vamos criar um pequeno programa que permite mostrar um calendrio e executa a calculadora do Windows . Crie um novo projeto. No ttulo do formulrio coloque "Menu Principal" e na propriedade Name, troque "Form1", que o nome default, por "FormPrincipal".Para o formulrio ficar centralizado altere a propriedade Position para "poScreenCenter". Em outros projetos, no colocamos nome no formulrio porque ele no era utilizado dentro do cdigo do programa.

Coloque no formulrio trs componentes "Button" ( e um componente "Label" ( "Button1" Name Caption "Button2" Name Caption "Button3" Name Caption "Edit" Name Text "Label" Caption Data editData btnFechar Fechar btnCalculadora Calculadora btnCalendario Calendrio

) , um componente "Edit"(

) . Altere as seguintes propriedades:

O formulrio ir ficar da seguinte forma:

Delphi 4 Total

75

1997, 1998, 1999 GRIAULE

Pedindo Confirmao ao Usurio


Agora vamos tratar o evento OnClick do item do "Button" Fechar . No procedimento de evento digite o seguinte:

if Application.MessageBox( 'Tem certeza que quer sair?', 'Confirmao', MB_IconQuestion + MB_YesNo) = idYes then Close;
Isso chama a funo MessageBox, informando o texto da mensagem. O ltimo argumento, no caso 'MB_IconQuestion + MB_YesNo', diz para mostrar um cone de pergunta e especifica quais os botes da mensagem (no caso, "Yes" e "No"). A funo retorna um valor indicando qual o boto pressionado. Esse valor pode ser 'idYes' ou 'idNo' no caso. Se for idYes, executamos o mtodo Close para fechar o formulrio. Execute o programa e clique no boto "Fechar". Notas:Para alternar do formulrio para o editor de cdigo pressione a tecla F12. Ento ao clicar no boto "Fechar" ir aparecer a mensagem perguntando se deseja sair do formulrio. Mas esta no a nica forma de fechar o formulrio, o usurio pode usar as teclas [ALT+F4] ou clicar no cone . Mas ao fechar o formulrio, so gerados os eventos, OncloseQuery e o OnClose. No primeiro podemos cancelar a tentativa do usurio de fechar o formulrio, mas no segundo o formulrio foi fechado. Para mostrar a mensagem independente do modo que o usurio ir fechar , coloque o seguinte procedimento no evento OnCloseQuery do formulrio "frmPrincipal" :

if Application.MessageBox('Tem certeza que quer sair?', 'Confirmao',MB_IconQuestion + MB_YesNo) = idNo then CanClose := false
Delphi 4 Total 76

1997, 1998, 1999 GRIAULE

A varivel CanClose passada como parmetro pelo evento OnCloseQuery, ao sair do procedimento se esta varivel for False, quer dizer que voc esta interrompendo a tentativa do usurio de fechar o formulrio.O default dessa varivel True. Vamos retirar a mensagem que aperece quando clicar o boto "Fechar", pois se deixarmos como est, se o usurio clicar neste boto ir aparecer duas mensagens perguntando se deseja fechar o formulrio, neste procedimento iremos deixar somente o mtodo close.

Criando um Novo Formulrio


Para criar um novo formulrio no projeto, use o item File|New Form no menu do Delphi ou use o boto New Form: na SpeedBar. O novo formulrio vai aparecer como "Form1" e ainda no tem nenhum componente. Altere o seu nome (Name) para "formCalendario" e o ttulo (Caption) para "Calendrio". Altere tambm a propriedade Position do formulrio para "poScreenCenter". Coloque o componente "MonthCalendar"( ) que fica na pasta "Win32", altere sua propriedade Name para "MtCData". Para mostrar mais de um ms necessrio alterar o tamanho deste componente, podemos tambm alterar o valor da propriedade Width para 377. Este componente mostra um calendrio. Seu formulrio ir ficar como a figura abaixo:

Agora vamos acrescentar dois botes neste formulrio, vamos usar o componente "BitBtn" da pgina "Additional" - o primeiro cone da pgina, permite mostrar figuras junto com o texto. . Esse tipo de componente

Para o primeiro boto, defina a propriedade Kind [espcie] com o valor 'bkOk'. Isso altera automaticamente as propriedades Caption (para "Ok"), Default (para True), ModalResult (para 'mrOk') e Glyph (para conter uma imagem correspondente ao Ok). Delphi 4 Total 77

1997, 1998, 1999 GRIAULE Para o outro boto, defina Kind com o valor 'bkCancel'. Isso vai alterar Caption para "Cancel", Cancel para True, ModalResult para mrCancel, e Glyph para conter o desenho de um "x". Altere Caption para o valor "Cancelar". A propriedade ModalResult de um boto (de um Button "normal" ou de um BitBtn) importante com caixas de dilogo. Quando ModalResult contm um valor diferente de 'mrNone' (o default), o boto fecha o formulrio e retorna esse valor para quem "chamou" o formulrio. Esse valor numrico, mas existem constantes predefinidas para facilitar, como 'mrOk' e 'mrCancel'. A propriedade Default, como j vimos, faz com que o boto seja acionado por [Enter] e a propriedade Cancel faz com que o boto seja acionado pela tecla [Esc]. Notas: A propriedade no componente "BitBtn" que permite colocar imagem a propriedade Glyph.

Salvando o Projeto
Salve o projeto nesse ponto para dar nome aos arquivos. O Delphi vai pedir os nomes na ordem segundo formulrio,: formulrio principal e projeto. Chame-os respectivamente de: EXECCALEN.PAS (era "Unit2.PAS", segundo formulrio) EXECPRIN.PAS (era "Unit1.PAS", primeiro formulrio) CALCDATA.DPR (era "Project1.DPR", arquivo de projeto) Em projetos com mais de um formulrio, no usaremos o mesmo padro de nomes dos outros, que era acrescentar um "P" ao nome do projeto. melhor salvar o projeto agora porque vamos precisar dos nomes de unidades do projeto bem definidos para o prximo passo.

Executando um Arquivo
O boto "Calculadora" vai executar o calculadora do Windows , cujo arquivo "Calc.exe". No procedimento de evento OnClick , faa o seguinte:

begin WinExec('calc.exe', SW_SHOWNORMAL); end;


A funo WinExec uma funo do Windows que executa um programa. Ela recebe como parmetros o nome do programa e um valor que indica como a janela do programa deve aparecer. Para isso existe um comando que converte a string em PChar. Execute o programa e verifique o resultado. Vamos retornar ao formulrio principal, para fazer isto clique no cone menu View/forms, ir aparecer a seguinte tela: Delphi 4 Total ou [Shift+F12] ou 78

1997, 1998, 1999 GRIAULE

Escolha a opo "formPrincipal" e clique em "OK". Ele ir mostrar o formulrio principal, no evento OnClick do boto "Calendrio" iremos chamar o formulrio "formCalendrio". Para mostrar um outro formulrio basta usar o mtodo Show ou o mtodo ShowModal, da seguinte forma:

nome_do_formulrio.Show; { ou } nome_do_formulrio.ShowModal;
A diferena entre os dois que ShowModal mostra o formulrio de forma modal. Quando uma janela modal est na tela, o usurio no pode utilizar outras janelas do programa. Ele deve terminar de executar a tarefa atual e fechar a janela modal para poder retornar principal. Se uma janela no modal, o usurio pode alternar livremente entre ela e outras janelas no modais. Uma janela modal a interface recomendada para caixas de dilogo, por isso utilizaremos ShowModal. No cdigo do procedimento criado coloque:

if FormCalendario.ShowModal = mrOk then editData.Text := DatetoStr(FormCalendario.MtCData.Date);


Primeiro o mtodo ShowModal chamado e o valor retornado verificado. Se esse valor for 'mrOk', o boto "Ok" foi pressionado. Se ele for 'mrCancel', o boto "Cancelar" foi pressionado. Quando o valor 'mrOk', o componente 'editData' vai receber a data que foi escolhida , essa valor iremos obter pela propridade Date do componente MtCData no formulrio formCalendario. Repare que isso feito com a sintaxe: FormCalendario . MtCData . Date Mas para esse cdigo funcionar falta uma coisa. Se um formulrio precisa acessar outro que est em outra unidade, preciso adicionar uma referncia unidade, atravs de uma clusula uses. No arquivo da unidade EXECPRIN.PAS, procure a palavra implementation, e acrescente o seguinte logo depois do {$R *.DFM}:

Delphi 4 Total

79

1997, 1998, 1999 GRIAULE

uses ExecCalen;
"ExecCalen" o nome da outra unidade, que contm o formulrio "FormCalendario". Se no houvesse essa clusula, o cdigo no conseguiria acessar o outro formulrio. Como a propriedade Text do componente "Edit" do tipo String e a propriedade Date do componente MonthCalendar e do tipo TDate, temos que converte o contedo da propriedade Date para String, por isso foi necessrio usar a funo StrtoDate. Execute o programa e clique no boto "Calendrio". O segundo formulrio aparece como uma janela modal(se voc clicar no formulrio principal, no vai conseguir us-lo). Para retornar ao principal clique no boto "Ok". Salve novamente o projeto. Mantenha ele aberto no Delphi, pois vamos analisar algumas opes do Delphi utilizando esse mesmo projeto.

Delphi 4 Total

80

1997, 1998, 1999 GRIAULE

Gerenciando os Arquivos do Projeto


Um projeto grande, com vrios formulrios, pode ficar difcil de compreender e manter. Para facilitar o tratamento de projetos, o Delphi tem vrios recursos. Note que para utilizar esses recursos com eficincia, voc deve dar nomes descritivos a todos os formulrios e unidades.

Usando a Speedbar ou Menus


Para alternar entre os formulrios do projeto, clique no boto (Select form from list) da Speedbar. Ele vai mostrar uma janela com os nomes de todos os formulrios (no caso "FormPrincipal" e "FormCalendario"). Escolha um deles e clique Ok, ou clique duas vezes no nome dele. No teclado, voc pode usar [Shift+F12]. Para ver a lista de unidades disponveis, em vez de formulrios, use o boto (Select unit from list). Quando voc selecionar uma unidade, ela vai aparecer no editor de cdigo. Repare que aparece um nome a mais, que o nome do projeto ("CalcData"). Essa opo traz o arquivo de projeto (DPR), que analisaremos mais tarde. No teclado, voc pode usar [Ctrl+F12]. Nota: Se voc tentar executar o programa sem fazer essa alterao, o Delphi automaticamente se oferece para adicionar uma referncia unidade do outro formulrio, pedindo uma confirmao. Depois que as unidades foram abertas, voc pode alternar livremente entre elas clicando nas abas do editor de cdigo (ou usando [Ctrl+Tab]):

E voc tambm pode alternar para uma unidade e, a partir dela, abrir o formulrio associado. Para isso use a tecla [F12] ou o boto (Toggle Form/Unit) da SpeedBar. claro que se voc puder ver os dois (ou mais formulrios) ao mesmo tempo na tela, voc pode alternar entre eles com um clique de mouse.

Delphi 4 Total

81

1997, 1998, 1999 GRIAULE Voc tambm pode adicionar um arquivo ao projeto (como um formulrio que voc criou em outro projeto) usando o boto da SpeedBar ou o item de menu Project|Add to

project.... Para remover um arquivo do projeto, use o boto ou o item Project|Remove from project... e selecione qual voc quer remover. Nota: Quando voc adiciona um arquivo ao projeto, o Delphi no faz uma cpia do arquivo. Se outros projetos estiverem utilizando o arquivo, ele ser compartilhado entre eles. Quando voc remove um arquivo do projeto, o arquivo no excludo do disco. Ele continua no diretrio do projeto e pode ser utilizado novamente no mesmo projeto ou em outros projetos.

Usando o Project Manager


O Delphi tambm inclui um pequeno utilitrio que permite ter uma viso geral do projeto. Para us-lo, clique no item View|Project Manager no menu do Delphi. O Project Manager [gerente de projeto] tem uma aparncia como a seguinte:

O Project Manager mostra uma tabela com os nomes de cada unidade do projeto e ao expandir essas unidades ele mostra o formulrio correspondente , a no ser no caso de uma unidade independente. Na coluna "Path", aparece o diretrio do arquivo, isto se no estiver no mesmo diretrio do projeto. Podemos trabalhar com mais de um projeto ao mesmo tempo . Isso muito til , se voc quer desenvolver um desenvolver um programa EXE e uma DLL que trabalham em conjunto. Os arquivos podem ser salvos nos "grupo de projetos", que serve para manter agrupados todos os itens adicionados. Podemos adicionar um novo projeto e tambm um projeto j existente, para isso clique com o boto direito do mouse na palavra ProjectGroup1(caso no tenha mudado o nome do grupo). Com isso iro aparecer as seguintes opes:

Delphi 4 Total

82

1997, 1998, 1999 GRIAULE

Estas opes so utilizadas para: Add New Project : Adicionar um novo projeto ao grupo. Add Existing Project : Caso o projeto j exista , podemos adicion-lo ao grupo atravs desta opo. Save Project Group : Salva todas as alteraes feitas neste grupo. Save Project Group As: Salva as configuraes deste grupo com outro nome. View Project Group source : Para cada grupo criado gerado um arquivo com a extenso bgp, e neste arquivo contm todos os projetos associados ao grupo.Esta opo mostra o contedo do arquivo cuja extenso bgp. ToolBar: Se est opo estiver marcada , mostrado uma barra de ferramento onde apareem as opes:

Status Bar: Mostra o nome e o caminho do arquivo de projeto. Dockable: Permite encaixar a janela atual em outra janela, como por exemplo, o editor de cdigo, o object inspector, etc..

Delphi 4 Total

83

1997, 1998, 1999 GRIAULE

Delphi 4 Total

84

1997, 1998, 1999 GRIAULE

Definindo o Formulrio Principal


Esse exemplo que criamos possui um formulrio principal e um formulrio Calendrio. O formulrio principal de um projeto o que aparece inicialmente para o usurio, e a partir do qual os outros so chamados. Inicialmente o formulrio principal o primeiro Formulrio criado no projeto, mas voc pode mudar isso a qualquer momento. Para mudar, acione o menu Project|Options.... Na pgina Forms , lista "Main Form", selecione o nome do formulrio que voc quer que seja o principal, por exemplo, "FormCalendario" e clique "Ok". Quando voc executar o programa, esse formulrio vai aparecer em vez do "FormPrincipal". Depois retorne para a opo anterior.

Delphi 4 Total

85

1997, 1998, 1999 GRIAULE

Captulo 8 Estrutura das Unidades


Estrutura Geral das Unidades O Cdigo Gerado pelo Delphi Unidades Associadas e Independentes Compilao de Unidades Usando uma Unidade Resolvendo Conflitos de Nomes Arquivo de Projeto
Quando voc cria um formulrio no Delphi, automaticamente criada uma unidade associada, que contm algum cdigo gerado automaticamente pelo Delphi, alm do cdigo que voc acrescenta nos procedimentos de evento. Voc tambm pode criar uma unidade independente, para usar como uma biblioteca de funes e procedimentos, por exemplo. Neste captulo veremos como a estrutura do cdigo gerado pelo Delphi, e qual a forma geral da estrutura de uma unidade.

Delphi 4 Total

86

1997, 1998, 1999 GRIAULE

Estrutura Geral das Unidades


Todo arquivo de unidade dividido basicamente em uma seo de interface e uma seo de implementao. Em geral, o que declarado na seo de interface (variveis, constantes, procedimentos etc.) visvel externamente, em outras unidades. O que for declarado apenas na seo de implementao visvel apenas para uso dentro da prpria unidade:

unit Execprin; interface { itens visveis externamente } ... implementation { itens para uso interno } ... end.

Delphi 4 Total

87

1997, 1998, 1999 GRIAULE

O Cdigo Gerado pelo Delphi


Voc pode criar suas prprias unidades, mas para comear, vamos ver a estrutura do cdigo que o Delphi gera automaticamente num arquivo de unidade. No projeto anterior (CALCDATA.DPR) abra a unidade EXECPRIN.PAS, que est associada ao formulrio principal (FormPrincipal). Verifique que o cabealho da unidade contm uma linha:

unit Execprin;
A primeira linha contm a palavra unit seguida do nome da unidade (que corresponde ao nome do arquivo). Depois vem a palavra interface, que inicia a seo de interface da unidade.

Seo de Interface
interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,StdCtrls;
A seo de interface comea com uma clusula uses, que contm uma lista de nomes de outras unidades que so utilizadas por esta. Nesse caso esses nomes so de unidades do Delphi (Windows, SysUtils, ...) que compem a biblioteca do Delphi. Essa lista mantida automaticamente, mas voc pode acrescentar outros nomes lista. Aps a clusula uses, voc pode acrescentar declaraes de tipos de dados, variveis, procedimentos e funes. A primeira declarao, colocada automaticamente, a da classe de formulrio. A classe uma definio dos componentes que o formulrio contm, e dos procedimentos de evento definidos nele. Ns veremos a classe de formulrio mais em detalhes posteriormente.

type TformPrincipal = class(TForm) btnCalendario: TButton; btnCalculadora: TButton; btnFechar: TButton; editData: TEdit; Label1: TLabel; procedure btnFecharClick(Sender: TObject); ... private { Private declarations } public { Public declarations } end;
Delphi 4 Total 88

1997, 1998, 1999 GRIAULE

Com a palavra end, termina a definio da classe. Depois o Delphi acrescenta uma declarao de varivel para o formulrio.

var FormPrincipal: TFormPrincipal;


Depois dessas declaraes, vem a seo de implementao da unidade, que contm o seguinte:

implementation {$R *.DFM} uses execcalen; procedure TformPrincipal.btnFecharClick(Sender: TObject); begin .... end; procedure TformPrincipal.FormCloseQuery(Sender: TObject;var CanClose: Boolean); begin .... end; ... end.
A declarao {$R *.DFM} no um comentrio, apesar de parecer com um. Esse tipo de declarao chamada de diretiva do compilador e uma instruo para o compilador interno do Delphi. No caso, o que ela faz associar o arquivo de formulrio (EXECPRIN.DFM) com o arquivo de unidade. Essa diretiva necessria para o funcionamento do programa, portanto no a remova. Depois vem o corpo de cada um dos procedimentos de evento, Note que em cada um deles, o nome da classe de formulrio ("TFormPrincipal") includo como prefixo no cabealho do procedimento. Aps todos os procedimentos existe uma linha contendo apenas "end." (end seguido de ponto final). Essa linha sinaliza o final do arquivo da unidade. O compilador ignora tudo que for digitado depois dessa linha, mesmo sem especificar comentrios. Delphi 4 Total 89

1997, 1998, 1999 GRIAULE

Unidades Associadas e Independentes


No Delphi, uma unidade associada a um formulrio sempre tratada e utilizada em conjunto com o formulrio, e o cdigo da unidade geralmente est ligado (atravs de eventos) com os componentes do formulrio. Mas voc pode tambm criar unidades independentes, que contm apenas rotinas de cdigo e nenhum componente. Vamos ver alguns exemplos mais tarde, mas o processo de criar uma unidade independente simples: selecione o item de menu File|New... no Delphi, Unit e clique Ok. Com isso, criada uma unidade contendo apenas o clique no cone esqueleto das sees, como a seguinte:

unit Unit2; interface implementation end.


Quando voc salva o arquivo da unidade, fornecendo um outro nome, o Delphi vai alterar a declarao no cabealho para refletir esse nome.

Delphi 4 Total

90

1997, 1998, 1999 GRIAULE

Compilao de Unidades
O Delphi compila o seu projeto quando voc executa o programa, ou quando voc aciona Project|Compile (nome do projeto ativo). Caso queira compilar todos os projetos existente no grupo escolher Project|Compile All Projects. Para compilar o programa, o Delphi rene todas as unidades do projeto e cria um arquivo executvel, com o mesmo nome do projeto e extenso EXE. Essa compilao feita em vrias fases. Da primeira vez que o projeto compilado, para cada arquivo de unidade (.PAS), gerado um arquivo de unidade compilada (.DCU), e esses arquivos DCU so mantidos no disco. Depois todos os arquivos DCU, mais os arquivos (RES) e o arquivo DPR so combinados em um nico arquivo EXE independente. Da prxima vez que o projeto for compilado, apenas as unidades alteradas desde a ltima compilao so recompiladas (.PAS -> .DCU). O Delphi verifica isso comparando a data/hora do arquivo PAS com a data/hora do arquivo DCU correspondente. Se o arquivo fonte for mais recente, ele recompila. Voc pode tambm forar o Delphi a recompilar todas as unidades sem verificar a data. Para isso, use o comando Project|Build (nome do projeto ativo) , caso queira recompilar todos os projetos pertencentes ao grupo escolher Project|Build All Projects. O processo de compilao pode ser resumido com o diagrama:

Delphi 4 Total

91

1997, 1998, 1999 GRIAULE

Usando uma Unidade


Uma unidade sempre utilizada por outra unidade (ou pelo programa principal, como veremos). Na clusula uses, so especificadas quais as unidades utilizadas. Por exemplo: unidade FRMTESTE.PAS:

unit FrmTeste; interface uses Forms, Controls, ... Rotinas; {nome da outra unidade} ... implementation procedure... begin Contador := 30; AumentaCont; end; ... end.

unidade ROTINAS.PAS:

unit Rotinas; interface var Contador: integer; procedure AumentaCont; implementation ... end.
Quando uma unidade (FrmTeste), utiliza outra (Rotinas), ela passa a ter acesso a todos os identificadores, como variveis e procedimentos, que esto declarados na seo de interface Delphi 4 Total 92

1997, 1998, 1999 GRIAULE da outra (ela no tem acesso a identificadores declarados apenas na seo de implementao da outra). Existem dois lugares onde pode ser colocada a clusula uses: no incio da seo de interface, ou no incio da seo de implementao. Os identificadores da outra unidade s se tornam visveis a partir do ponto onde a outra unidade foi referenciada. Se voc colocar a referncia outra unidade na clusula uses da interface, ento os identificadores da outra podem ser usados j na parte de interface. Se voc referenciar a outra unidade na clusula uses da parte de implementao, os identificadores s podem ser usados a partir da parte de implementao. Se duas unidades dependem uma da outra atravs da seo de interface, ento o Delphi recompila a unidade dependente (gera o arquivo .DCU) sempre que a outra alterada. Nesse exemplo, toda vez que a unidade ROTINAS alterada, a unidade FRMTESTE, que depende dela, recompilada primeiro. Duas unidades podem se "utilizar" mutuamente, isto , pode haver tambm uma clusula uses em ROTINAS, que referencia FRMTESTE. Mas se ambas as referncias estiverem na parte interface das unidades, o Delphi no consegue determinar a ordem de compilao das duas, e gera uma mensagem de erro ("Circular unit not allowed"). Por isso, sempre melhor acrescentar a referncia para a outra unidade na seo implementation. S realmente necessrio colocar a referncia na interface quando voc precisa usar algo da outra unidade ainda dentro da parte interface (s acontece no caso de constantes e tipos de dados que sejam usados por outros tipos de dados ou constantes).

Delphi 4 Total

93

1997, 1998, 1999 GRIAULE

Resolvendo Conflitos de Nomes


Pode acontecer de voc ter um identificador que tem o mesmo nome na unidade atual e em outra que est sendo utilizada. Isso gera uma ambiguidade quando voc usa o nome. Por exemplo, suponhamos que FRMTESTE.PAS contenha uma varivel chamada 'Contador', e utiliza a unidade ROTINAS.PAS, que tambm contm uma varivel chamada 'Contador'. Se voc colocar na unidade FRMTESTE um comando:

Contador := 34;
o Delphi vai dar prioridade varivel da unidade atual ('Contador' em FRMTESTE). Mas para acessar a varivel da outra unidade (ROTINAS), voc pode usar um identificador qualificado, isto , prefixado com o nome da outra unidade, por exemplo:

Rotinas.Contador := 34;
Qualquer identificador pode ser usado dessa forma para resolver o conflito de nomes.

Delphi 4 Total

94

1997, 1998, 1999 GRIAULE

Arquivo de Projeto
Uma parte importante do seu programa, apesar de raramente voc precisar trabalhar diretamente com ela, o arquivo de projeto (.DPR). Quando voc abre o projeto, o Delphi usa o arquivo DPR para localizar todos os outros arquivos utilizados (formulrios, unidades associadas e unidades independentes). O arquivo DPR na verdade contm cdigo executvel gerado pelo Delphi, mas que pode ser personalizado. Para abrir o arquivo DPR, por exemplo no projeto CALCDATA, use o item Project|View Source, no menu do Delphi. Voc vai ver no editor de cdigo algo como o seguinte:

program calcdata; uses Forms, execprin in 'execprin.pas' {formPrincipal}, execcalen in 'execcalen.pas' {formCalendario}; {$R *.RES} begin Application.Initialize; Application.CreateForm(TformPrincipal, formPrincipal); Application.CreateForm(TformCalendario, formCalendario); Application.Run; end.
Este o programa principal do projeto, a partir do qual os formulrios e outras unidades so chamadas. A primeira linha, program CalcData; indica que ser gerado um programa executvel e contm o nome do projeto. Depois vem uma clusula uses, listando os nomes de todos os arquivos de unidades que compem o projeto. A clusula in especifica o nome do arquivo de unidade, que pode estar em um outro diretrio. Se um diretrio no especificado, o arquivo procurado no mesmo diretrio do arquivo DPR. A diretiva de compilao {$R *.RES} diz ao compilador para reunir ao executvel todos os arquivos com extenso RES. Esses arquivos so gerados a partir dos arquivos de formulrio (.DFM). Entre o begin e o end est o cdigo executado no incio da execuo do programa. Para cada formulrio do projeto, o Delphi acrescenta uma chamada a 'Application.CreateForm', que cria um objeto de formulrio baseado na classe de formulrio. O primeiro da lista ser o formulrio principal do programa. A ltima linha, 'Application.Run', executa o lao de processamento de eventos do Delphi.

Delphi 4 Total

95

1997, 1998, 1999 GRIAULE Quando voc usa comandos de manuteno de projeto, o Delphi automaticamente atualiza o arquivo DPR. Raramente voc precisa alterar o arquivo DPR manualmente, mas voc pode, por exemplo, acrescentar comandos dentro do begin e end para fazer alguma inicializao do programa mesmo antes que o formulrio principal seja mostrado.

Delphi 4 Total

96

1997, 1998, 1999 GRIAULE

Captulo 9 Outros Tipos de Dados e Depurao


Tipos Enumerados Tipos Faixa Vetores Exemplo: Clculo de Mdia Conjuntos Depurao

Delphi 4 Total

97

1997, 1998, 1999 GRIAULE

Tipos Enumerados
Um tipo enumerado composto por uma lista seqencial de valores simblicos. Uma varivel desse tipo pode assumir qualquer um desses valores. Para criar um tipo enumerado, usa-se uma declarao type:

type EstadoCivil = (Solteiro, Casado, Desquitado, Viuvo);


Aps criar um tipo de dados, podem ser criadas variveis desse tipo, com uma declarao de variveis normal:

var estCiv: EstadoCivil;


A varivel 'estCiv' s vai poder assumir um dos valores do tipo: Solteiro, Casado, etc. Esses valores no so numricos e no so strings de texto. So apenas constantes simblicas que representam uma informao. Por exemplo:

estCiv := Casado; ... if estCiv = Viuvo then begin ... end;


Tipos enumerados melhoram a legibilidade do programa, evitando que voc precise codificar uma varivel com valores numricos (p.ex.: 0 para Solteiro, 1 para Casado, etc.). Mas eles so manipulados de forma eficiente pelo Object Pascal, pois internamente so tratados como constantes numricas.

Operaes com Ordinais


Um tipo enumerado tambm um tipo ordinal, como os tipos inteiros, o tipo Char e o tipo Boolean. Por isso, tambm se aplicam a ele todas as operaes que podem ser feitas com tipos ordinais, vistas no Captulo sobre Variveis e Tipos de Dados e outros: Para obter o prximo elemento da seqncia: usa-se a funo succ. Por exemplo:

estInicial := Casado; estCiv := succ(estInicial); {o valor ser Desquitado}


Para obter o elemento anterior: usa-se a funo pred. Por exemplo: pred(Casado) retorna o valor Solteiro.

Delphi 4 Total

98

1997, 1998, 1999 GRIAULE Para saber a posio do elemento na seqncia: usa-se a funo ord. Ela retorna um valor indicando a posio do elemento na lista, e pode ser usada para converter um valor enumerado em numrico. O primeiro elemento tem a posio zero. Por exemplo: ord(Solteiro) = 0, ord(Casado) = 1, ord(Desquitado) = 2 e ord(Viuvo) = 3 e ord(estCiv) retorna um valor dependendo do valor atual da varivel. Para percorrer uma faixa de elementos: pode ser usado o comando for (visto em Estutura de Controle) para fazer um lao:

for estCiv := Solteiro to Viuvo do ...


Alm disso, tipos ordinais podem ser usados para ndices de vetor (como veremos adiante) ou para criar conjuntos (como veremos adiante) e podem ser usados com o comando case que foi visto anteriormente.

Tipos Enumerados no Delphi


A prpria VCL do Delphi utiliza tipos enumerados em vrios lugares. A propriedade BorderStyle do formulrio, por exemplo, de um tipo enumerado (TFormBorderStyle) que contm quatro valores possveis. A declarao desse tipo, no cdigo fonte da VCL, :

type TFormBorderStyle = (bsNone, bsSingle, bsSizeable, bsDialog);


Cada valor possvel representa um estilo de borda do formulrio, como vimos antes. Se BorderStyle fosse uma propriedade numrica em vez de enumerada, os valores possveis teriam que ser codificados como nmeros (0,1,2,3) e isso tornaria difcil a escrita e manuteno do programa. Se eles fossem codificados como strings de texto ('bsNone' etc.), seria muito ineficiente o armazenamento e manipulao dos valores.

Delphi 4 Total

99

1997, 1998, 1999 GRIAULE

Tipos Faixa
Se voc sabe que determinada varivel s pode pertencer a uma faixa de valores definida, pode utilizar um tipo faixa para que o prprio Delphi se encarregue de verificar isso automaticamente. Um tipo faixa uma restrio sobre os valores de um tipo ordinal qualquer. Por exemplo:

type EstadoCivil = (Solteiro, Casado, Desquitado, Viuvo); DiaMes = 1..31; LetraMaiuscula = 'A'..'Z'; EstadoNaoViuvo = Solteiro..Desquitado;
O tipo faixa declarado com o valor inicial e final da faixa, separados por '..' (um ponto seguido de outro). Os valores inicial e final devem pertencer a um tipo ordinal: inteiro, Char, ou enumerado. Depois de declarar o tipo, voc pode criar variveis baseadas no tipo:

var dm: DiaMes; letra1, letra2: LetraMaiuscula; est1: EstadoNaoViuvo; x:integer;


Qualquer atribuio a uma varivel do tipo faixa verificada, para saber se o valor est dentro dos limites. Por exemplo, os seguintes comandos geram erro de execuo, com uma mensagem "Range Check Error":

x := 32; dm := x; {erro: 32 est fora da faixa} letra1 := Chr(32); {erro: ' '(espao) est fora de faixa} estCivil := Viuvo; est1 := estCivil; {erro: Viuvo est fora da faixa}

Opo "Range Checking"


Na verdade, nem sempre o Delphi verifica se um valor est dentro da faixa. Ele s faz isso quando a opo "Range Checking" [verificao de faixa] est ativa nas opes do projeto. Para alterar essa opo, voc deve acionar o menu Project|Options... e, na pgina "Compiler", marcar ou desmarcar o item "Range Checking". Quando essa opo est marcada, ao compilar o programa o Delphi gera cdigo para cada atribuio de varivel do tipo faixa, garantindo que ela no vai receber um valor fora da faixa. Mas esse cdigo gerado aumenta o tamanho do programa e pode tambm reduzir a velocidade de execuo. Geralmente voc deve compilar com "Range Checking" ativo apenas durante o desenvolvimento do programa. Depois que o programa j tenha sido Delphi 4 Total 100

1997, 1998, 1999 GRIAULE testado, quando for gerar a verso final, desative essa opo para aumentar a eficincia da execuo.

Delphi 4 Total

101

1997, 1998, 1999 GRIAULE

Vetores
Um vetor (tambm chamado matriz) uma varivel que contm vrios elementos do mesmo tipo de dados. Cada elemento possui um ndice que identifica esse elemento no vetor. Podemos criar os vetores de duas formas : Esttica e Dinmica. Um vetor esttico tem um tamanho definido, enquanto que um vetor dinmico no tem tamanho declarado e seu tamanho pode ser mudado durante a execuo do programa.

Vetores Estticos
Para criar um tipo de dados que representa um vetor, usa-se uma declarao array, informando o tipo do ndice e o tipo dos elementos do vetor (ou tipo base). Por exemplo:

type TVetor = array [1..30] of double;


Essa declarao cria um tipo de vetor, com ndices na faixa de 1 a 30 (um tipo faixa) e elementos do tipo Double. Esse tipo pode ser usado para declarar uma ou mais variveis:

var vetA: TVetor; vetB, vetC: TVetor; ind, x: integer;


Cada varivel declarada um vetor com 30 elementos do tipo Double, e seus elementos individuais podem ser acessados informando o ndice do elemento entre colchetes:

begin vetA[3] := 1000; x := vetA[5]; ind := 10; vetB[ind] := x; end;


Na verdade no necessrio definir um tipo, quando voc s precisa de uma varivel daquele tipo. Voc pode inserir a definio do tipo na prpria declarao de varivel:

var vetA: array [1..30] of double;

Verificao de Faixa para Vetores


O ndice do elemento pode ser constante ou varivel. De qualquer forma, esse ndice deve estar na faixa definida pelo tipo do ndice. Se o ndice for uma varivel, o Delphi vai verificar Delphi 4 Total 102

1997, 1998, 1999 GRIAULE em tempo de execuo se a varivel est na faixa, mas apenas se a opo "Range Checking" estiver ativa, a mesma opo que controla verificaes de tipos faixa. Se "Range Checking" estiver desativado, qualquer valor admitido como ndice, e com isso, possvel acessar posies de memria fora do limite do vetor, com resultados imprevisveis. Essa posio de memria pode estar num espao ocupado por outra varivel, e nesse caso essa varivel ser modificada para conter um valor invlido, causando erros em outras partes do programa. Ou a posio pode estar numa rea de memria controlada pelo Windows. Como o Windows restringe o acesso memria apenas s reas reservadas ao programa, ele vai interceptar essa tentativa de acesso e terminar o programa. Geralmente, antes de terminar, o Windows mostra uma mensagem ("Este aplicativo provocou um erro e ser finalizado"). s vezes o Windows permite ao usurio ignorar o erro e continuar, mas na maioria das vezes, a nica opo finalizar a execuo.

Usando Outros Tipos de ndice


O tipo do ndice do vetor um tipo faixa, e por isso usa a mesma sintaxe. O ndice no precisa comear em um ou zero, por exemplo:

type TVetorInt = array [-3..3] of integer; TVetorBool = array [0..10] of boolean;


O nome do tipo no precisa comear com "T", mas isso uma conveno bastante utilizada para tipos de dados. Voc pode tambm definir um tipo faixa antes e depois utiliz-lo em um vetor:

type DiaMes = 1..31; TPresenca = (Presenca, Falta, Feriado); TVetPresenca = array [DiaMes] of TPresenca;
Como o ndice pode ser qualquer tipo ordinal ou tipo faixa, ele pode ser do tipo Char, Boolean ou enumerado, por exemplo:

type TFreqLetras = array ['A'..'Z'] of longint; var freq: TFreqLetras; letra: Char; maior: Longint; begin for letra := 'A' to 'Z' do
Delphi 4 Total 103

1997, 1998, 1999 GRIAULE

freq[letra] := 0; maior := freq['A']; ... end;


Outros exemplos so:

type TVetIndBool = array [False..True] of integer; TVetIndEnum = array [Solteiro..Viuvo] of string;

Vetores Dinmicos
Para criar um vetor dinmico tambm temos que utilizar a declarao array, informando o tipo dos elementos do vetor (ou tipo base). A diferena do vetor esttico que no informamos os tipo do ndice e o seu tamanho. Essa informao fornecida em tempo de execuo atravs do procedimento SetLength. O ndice inicial do vetor sempre zero.

var Vetor : array of double; N:integer; begin N := 10; SetLength(Vetor, N); // muda o tamanho do vetor Vetor[5] := 5; // ele tem elemento de 0 a 9 end;
Para redefinir o tamanho do vetor , usa-se a propriedade Setlength novamente com o novo tamanho que deseja . Por exemplo: continuando o exemplo anterior acrescente as seguinte linhas:

SetLength(Vetor, 20); // Redefine o tamanho para 20 Vetor[20] := 5;


O contedo do vetor na posio 20 5.

Vetores Multidimensionais
Um vetor tambm pode ter mais de uma dimenso, permitindo representar um vetor de vetores. Nesse caso, cada elemento possui dois ou mais ndices. Um vetor multidimensional pode ser criado definindo vrios tipos de ndices:

type TMatriz = array [1..10, 1..30] of double;


Delphi 4 Total 104

1997, 1998, 1999 GRIAULE

TMarcador = (marcaX, marcaO, marcaNada); TJogoDaVelha = array [0..2, 0..2] of TMarcador; TCubo = array [1..10, 1..10, 1..10] of integer; var m, n: TMatriz; i,j,k:integer; jogo: TJogoDaVelha; lin,col:integer; cubo: TCubo; begin { para acessar um elemento, usa-se dois ndices } m[i,j] := 100.0; for lin := 0 to 2 do for col := 0 to 2 do jogo[lin, col] := marcaNada; cubo[i,j,k] := 0; {trs ndices} end;
Podemos tambm criar vetores multidimensionais dinmicos. A idia a mesma do anterior, mas no informamos o tamanho do vetor durante a definio, seu tamanho definido durante o tempo de execuo utilizando tambm o mtodo SetLength e alm disso permito criar para cada linha um nmero diferente de elementos, por Exemplo:

var Matriz : array of array of double; begin setLength (Matriz, 2); // muda o tamanho do vetor multidimensional setLength (Matriz[0], 2); setLength (Matriz[1], 5); Matriz[0,1] := 3; Matriz[1, 4] := 5 end;

Delphi 4 Total

105

1997, 1998, 1999 GRIAULE

Exemplo: Clculo de Mdia


Para ver na prtica como utilizamos vetores, vamos criar um novo projeto. O programa vai permitir que o usurio informe uma lista de valores, e depois calcule a mdia dos valores fornecidos. No formulrio altere a propriedade Caption para "Calcula Mdia" e crie componentes no formulrio conforme o seguinte:

Crie um rtulo (componente Label) com Caption "Nmero:" e ao lado dele um componente Edit com nome "editNumero" , coloque a propriedade Text vazia . Crie os botes como mostrado, e mude seus nomes, respectivamente para 'btnAdicionar', 'btnLimpar' e 'btnCalcular'. Ao lado do rtulo "Mdia:", coloque um componente Edit que vai apenas mostrar o resultado. Defina seu nome como 'editMedia'. Coloque sua propriedade Text vazia.Altere sua propriedade ReadOnly para True, o que vai proibir a edio do valor. Altere tambm a propriedade Color escolhendo o valor 'clBtnFace'. Com isso, ele vai ficar da mesma cor do formulrio e dos botes, o que fornece ao usurio uma indicao visual de que ele no pode ser editado. Para o 'btnAdicionar', faa a propriedade Default = True, para que ele possa ser "pressionado" usando a tecla [Enter].

Declarando o Vetor
Antes de fazer qualquer tratamento de eventos, vamos adicionar na unidade uma declarao para o tipo do vetor e uma declarao de varivel desse tipo. Pressione [F12] para abrir o arquivo da unidade. No incio da seo de implementao, aps a palavra implementation, digite o seguinte:

type TVetorInt = array [1..3] of double; var Valores: TVetorInt; ContValores: integer;
A varivel 'Valores' um vetor do tipo 'TVetorInt', ou seja, um vetor com elementos do tipo 'double' e ndices de 1 a 3. A varivel 'ContValores' ser um contador usado para especificar quantos elementos do vetor esto sendo usados no momento. A cada vez que for clicado o boto "Adicionar", essa varivel ser incrementada. Delphi 4 Total 106

1997, 1998, 1999 GRIAULE

Adicionando um Elemento
No cdigo do boto 'btnAdicionar', vamos adicionar o nmero que foi digitado (em 'editNumero') ao vetor. A cada clique, vamos tambm incrementar o contador. Digite o seguinte:

procedure TForm1.btnAdicionarClick(Sender: TObject); var numero: double; begin numero := StrToFloat(editNumero.Text);{conv. p/ inteiro} ContValores := ContValores + 1; {increm. contador} Valores[ContValores] := numero; {guarda o elemento} { Facilita a digitao do prximo nmero } editNumero.Clear; editNumero.SetFocus; end;
Repare que depois de adicionar o elemento, o programa limpa o controle 'editNumero', usando o mtodo Clear. Isso facilita que o usurio digite seqencialmente os nmeros. Tambm para facilitar, o programa devolve o foco de teclado para o controle, no caso de ele ter usado o mouse para clicar no boto. Isso feito com o mtodo SetFocus.

Limpando a Lista
O boto 'btnLimpa' vai "limpar" a lista de valores. Na verdade no precisamos percorrer todos os elementos do vetor, apenas zerar o contador, para indicar que no h nenhum elemento guardado. Faa o seguinte:

procedure TForm1.btnLimparClick(Sender: TObject); begin ContValores := 0; end;

Calculando a Mdia dos Elementos


O boto 'btnCalcula' vai fazer a tarefa de calcular a mdia dos elementos do vetor. Para isso, temos que primeiro achar a soma dos elementos e depois dividir a soma pelo contador de elementos. Digite o seguinte, por enquanto:

procedure TForm1.btnCalcularClick(Sender: TObject); var soma: double; i: integer;


Delphi 4 Total 107

1997, 1998, 1999 GRIAULE

begin soma := 0.0; for i := 1 to ContValores do soma := soma + Valores[i];


Note que o lao for til para percorrer elementos de um vetor. No caso, o valor inicial sempre 1 e o valor final varivel, determinado por 'ContValores'. Aps fazer a soma, devemos fazer uma diviso dessa soma pelo contador. Mas antes, para evitar um erro de execuo, vamos verificar se o contador zero:

if ContValores = 0 then editMedia.Text := 'Erro' else editMedia.Text := FloatToStr(soma/ContValores); end;


Note que se 'ContValores' inicialmente for zero, o lao for no far nada (o valor final menor do que o inicial).

Testando o Programa
Execute o programa. Digite um nmero e clique no "Adicionar", ou tecle [Enter]. Repita o processo para adicionar alguns nmeros lista. (Repare que, como o programa no faz ainda verificao de erro, se voc digitar um valor no numrico e clicar em Adicionar, vai ver uma mensagem de erro do Delphi). Depois clique em "Calcular" para calcular o resultado. Se voc digitar, por exemplo, 13, 28 e 34, o resultado final ser: 25. No menu Project|Options na pasta Compiler se a opo RangeCheck estiver marcada , desmarque esta opo e pede para recompilar todo o projeto novamente (Project|Compile Mediap). Com isso se pedir para informar mais de 3 nmeros para ser adicionados a mdia , o Delphi no ir fazer a verificao se ultrapassou o tamanho do vetor, seu exemplo pode at continuar funcionando, vai depender da rea de memria que foi utilizada para acrescentar esses valores que foram colocados a mais, para que ocorre esta verificao a opo RangeCheck tem que estar marcada.

Salvando o Projeto
Vamos retornar a esse projeto mais tarde, portanto salve-o como MEDIA.PAS (unidade) e MEDIAP.DPR (projeto).

Delphi 4 Total

108

1997, 1998, 1999 GRIAULE

Conjuntos
O tipo de dados conjunto representa a noo matemtica de conjuntos, permitindo fazer todas as operaes padro de conjuntos. Um conjunto pode conter elementos de qualquer tipo ordinal (ou faixa). Para criar um tipo conjunto, usa-se a declarao set:

type TConjCarac = set of char; TConjLetra = set of 'A'..'Z'; TConjDia = set of 1..31; TConjEstado = set of EstadoCivil;
Para atribuir um valor (constante) a uma varivel conjunto, especifica-se os elementos do conjunto entre colchetes:

var vogais: TConjLetra; diasUteis: TConjDia; begin vogais := ['A','E','I','O','U']; diasUteis := [1..10, 13, 15, 20..23];
Note que uma faixa de valores pode ser colocada, para evitar enumerar todos os valores.

Verificando Elementos
Voc pode verificar se um elemento pertence a um conjunto, com o operador in, que equivale em matemtica operao x c. Por exemplo:

if caractere in vogais then texto := 'Vogal' else texto := 'Consoante'; if dia in diasUteis then ... if estCivil in [Desquitado, Viuvo] then ...
Esse tipo de teste mais eficiente do que uma srie de ifs, alm de mais legvel. Vamos abrir o projeto CALCP para fazer uma alterao semelhante em um dos testes. No cdigo associado ao evento OnKeyPress, do 'editOperando1', existe um if que testa os valores possveis da varivel 'Key':

Delphi 4 Total

109

1997, 1998, 1999 GRIAULE

if ((Key < '0') or (Key > '9')) and (Key<> #8) then Key := #0; { rejeita a tecla }
Vamos alterar esse if para utilizar um conjunto. Substitua pelo seguinte:

if not (Key in ['0'..'9', #8]) then Key := #0;


ou seja, se a tecla no estiver no conjunto formado por '0'..'9', mais o backspace (#8), ela ser rejeitada. Esse teste bem mais simples e mais eficiente do que o teste anterior.

Operaes com Conjuntos


Suponhamos duas variveis do tipo set of integer (conjunto de inteiros), recebendo os seguintes valores:

A := [1, 2, 3, 5, 7, 11]; B := [1, 3, 5, 7, 9];


Voc pode fazer vrios tipos de operaes com variveis conjunto, que so as seguintes: Unio: C = A B. O resultado da unio um conjunto que contm todos os elementos de ambos os conjuntos. A unio feita com o operador +. Por exemplo:

C := A + B; { o resultado ser [1, 2, 3, 5, 7, 9, 11] }


Interseo: C = A B. O resultado da interseo um conjunto que contm um elemento em comum entre os dois conjuntos. A interseo feita com o operador "*", por exemplo:

C := A * B; { O resultado ser [1, 3, 5, 7] }


Diferena: C = A - B. O resultado de A menos B o conjunto com os elementos de A que no existem em B. A diferena feita com o operador "-":

C := A - B; { O resultado ser [2, 11] } C := B - A; { O resultado ser [9] }


Contido: A B (A est contido em B) ou B A (B contm A). Verifica se todos os elementos de um conjunto pertencem tambm ao outro conjunto. No Object Pascal, o operador (est contido) representado por <= e (contm) por >= Por exemplo:

{verifica se os elementos 1 e 3 pertencem ao conjunto A} if [1,3] <= A then ... {verifica se B contm A} if B >= A then ...
Delphi 4 Total 110

1997, 1998, 1999 GRIAULE

Propriedades de Conjunto
Algumas propriedades de componentes do Delphi utilizam tipos de conjunto. Por exemplo, a propriedade BorderIcons de um formulrio contm um conjunto de valores, onde cada um determina se o formulrio ter ou no um determinado item da borda. Essas propriedades aparecem no Object Inspector com um sinal de "+" e o seu valor aparece com a sintaxe de conjunto. Quando voc clica duas vezes no nome da propriedade, aparecem subitens, que permitem adicionar ou remover elementos do conjunto. Para atribuir um valor para este tipo de propriedade no programa, voc deve usar a sintaxe de conjunto, por exemplo:

BorderIcons := [biSystemMenu, biMinimize, biMaximize];


Para alterar o valor, por exemplo, adicionando um elemento, voc deve usar os operadores de conjuntos:

BorderIcons := BorderIcons + [biMinimize];


Para verificar se um elemento est presente, voc deve usar o operador in:

if biMaximize in BorderIcons then ...

Delphi 4 Total

111

1997, 1998, 1999 GRIAULE

Depurao
Para encontrar as causas de uma exceo, ou para detectar erros de lgica no programa (erros que s voc pode saber que esto acontecendo), voc pode usar os mecanismos de depurao do Delphi. O processo de depurao [debugging] consiste em analisar o funcionamento do programa durante e execuo, vendo os valores de variveis, o fluxo da execuo, e assim por diante.

Colocando um Ponto de Parada


Para comear a depurao do programa, voc deve escolher um ponto inicial onde voc vai entrar em modo de depurao. Para isso coloque um ponto de parada [breakpoint] na linha onde voc quer comear. No nosso caso, coloque o cursor na primeira linha aps o begin, a que contm soma := 0. Para colocar ou retirar um ponto de parada voc pode usar a tecla [F5], ou clique na margem esquerda do editor, esquerda da linha. Em qualquer caso, o editor de cdigo mostra a linha destacada em vermelho e um marcador vermelho esquerda indicando um ponto de parada. Execute o programa, adicione uns dois ou trs nmeros e depois clique em "Calcular". Quando o Delphi encontra o ponto de parada, ele pra a execuo e destaca a linha atual. A janela principal do Delphi agora deve mostrar no ttulo "Delphi - Mediap [Stopped]". A palavra stopped [parado] significa que voc est em modo de depurao, com a execuo parada na linha atual. Para fazer os prximos testes, voc pode precisar executar vrias vezes o mesmo procedimento de evento. Depois da primeira vez, basta clicar no boto Calcular novamente.

Nota: voc tambm pode colocar um ponto de parada com o menu Run|Add Breakpoint|Source Breakpoint. Nesse caso, voc pode especificar uma condio de parada (Condition) e quantas vezes a linha deve ser executada antes de fazer uma parada (Pass count). Nota: as linhas que podem ter breakpoints esto marcadas com pontos azuis. As outras no esto relacionadas a cdigo executvel.

Executando Passo a Passo


Quando voc est em modo de depurao, voc tem vrias opes. Se quiser continuar a execuo normal, tecle [F9]. A janela do Delphi vai mudar para "Delphi - Mediap [Running]" indicando modo de execuo normal. Voc pode, ao invs disso, acompanhar passo a passo a execuo do programa. Execute novamente at chegar ao ponto de parada. Depois tecle [F7] ou [F8] (nesse caso tanto faz) para executar essa linha e passar para a prxima. A cada vez que voc teclar Delphi 4 Total 112

1997, 1998, 1999 GRIAULE [F7] ou [F8], voc vai executar uma linha e o tringulo que aparece esquerda se move indicando a prxima linha que ser executada. Com isso voc pode acompanhar o lao for, por exemplo. O comando dentro do for vai ser executado quantas vezes forem os nmeros que voc adicionou com o boto Adicionar. Essas teclas tambm equivalem a itens de menu do Delphi ou botes da SpeedBar: Tecla [F7] [F8] Boto Item de Menu Run|Trace Into Run|Step Over

A diferena entre "Trace Into/F7" e "Step Over/F8" s importante quando voc passa por uma chamada de procedimento. "Trace Into" entra no procedimento e executa cada linha dele passo a passo tambm. Isso pode ser o que voc quer, mas em alguns casos um procedimento j foi totalmente testado e voc no precisa acompanhar sua execuo de novo. Nesse caso, use "Step Over", que executa o procedimento inteiro em modo de execuo normal e depois volta ao modo depurao, depois da chamada do procedimento.

Executando At o Cursor
s vezes, durante a depurao voc quer "pular" para uma determinada linha diretamente, executando todo um trecho em velocidade normal de execuo. Por exemplo, durante a execuo, voc pode querer ir diretamente ao fim do lao for, em vez de acompanhar cada passagem. Para isso coloque o cursor na linha onde quer parar (por exemplo, no if depois do for) e use o item de menu Run|Run To Cursor ou sua tecla de atalho, [F4]. Nota: se a execuo nunca chegar linha do cursor, o programa entrar em modo de execuo normal ("Running") e no voltar automaticamente ao modo de depurao.

Vendo Valores de Variveis


Em modo de depurao, voc pode ver qual o valor atual de uma varivel ou, at mesmo, alterar o valor da varivel, afetando o funcionamento do programa da forma que voc quiser. Para isso, basta passear o cursor por cima do texto do programa. Quando o cursor estiver em cima do nome de uma varivel, o valor desta ser mostrado. Esse recurso chamado de avaliao instantnea. Nota: a avaliao instantnea, como outros recursos de depurao, funciona apenas em modo depurao [Stopped] e no em modo de execuo normal [Running].

Delphi 4 Total

113

1997, 1998, 1999 GRIAULE Para ver outras variveis ou alterar seus valores, use o comando Run |Evaluate/Modify... ou sua tecla de atalho, [Ctrl+F7]. Se voc clicar no nome de uma varivel e teclar [Ctrl+F7], a janela "Evaluate/Modify" aparece, mostrando o valor atual da varivel e permitindo voc digitar um novo valor em "New value:":

Voc tambm pode digitar o nome de outra varivel ou uma expresso qualquer em "Expression", por exemplo, "soma * 10 / 7", usando a janela como uma calculadora. Ou voc pode digitar o nome de uma constante (para saber o valor de uma constante predefinida do Delphi por exemplo), ou uma propriedade de um componente. Ao clicar em "Evaluate", voc ver o valor da expresso, varivel ou constante. Se for uma varivel, voc ter a opo de modificar o valor.

Monitorando o Valor de uma Varivel Dinamicamente


Se voc quer acompanhar o valor de uma varivel a cada momento da execuo, voc pode adicionar um "watch" [sentinela], que um mostrador permanentemente atualizado com o contedo da varivel. Para adicionar um "watch" para a varivel 'soma', por exemplo, clique no nome da varivel e use Run |Add Watch... ou a tecla [Ctrl+F5]. Existem vrias opes nesta janela, mas mantenha as opes padro e clique Ok. O Delphi vai mostrar a janela "Watch List", que contm todos os "watches" adicionados. Voc pode mov-la para uma posio qualquer da tela onde no cubra outras janelas. Agora medida que voc usar Trace Into/F7 ou Step Over/F8, o "watch" vai mostrar o valor da varivel sendo alterado.

Delphi 4 Total

114

1997, 1998, 1999 GRIAULE Para editar um "watch", clique duas vezes em cima dele na janela "Watch List" e altere suas opes. Para remov-lo, clique na lista e pressione [Delete]. Para adicionar um novo, com a janela "Watch List" aberta, clique duas vezes na linha vazia depois do fim da lista.

Forando a Finalizao do Programa


Quando, durante a depurao, voc quiser terminar a execuo do programa, o melhor a fazer continuar sua execuo normal e depois fechar a janela do programa. No entanto, s vezes necessrio forar a terminao do programa. Para fazer isso, use o item de menu Run |Program Reset ou tecle [Ctrl+F2] (essa tecla de atalho s funciona se voc estiver com o foco em uma janela do Delphi).

Outras Ferramentas de Depurao


Enquanto voc est em modo de depurao, voc pode chegar a executar um procedimento que foi chamado por outro, que por sua vez foi chamado por outro e assim por diante. Para esse tipo de programa mais complexo, voc pode visualizar a pilha de chamadas [call stack], que mostra toda a seqncia de chamadas de procedimento feitas at o ponto atual, desde o primeiro procedimento de evento executado. Para isso, use o menu View|Debug Windows|Call Stack[Ctrl+Alt+S]. As outras opes que aparecem em View|Debug Windows|Call so:

Threads

opo para verificar multiplas linhas de execuo (threads).

Modules

visualizar DLLS , que o programa utiliza.

CPU

mostra o cdigo assembler de dlls e programas, indenpendente se possui o cdigo fonte.

Se voc se perder durante a depurao e quiser encontrar a linha que est sendo executada agora, use o menu Run|Show Execution Point.

Delphi 4 Total

115

1997, 1998, 1999 GRIAULE

Captulo 10 Procedimentos e Funes


Procedimentos Gerais Unidades Independentes Funes Passagem de Parmetros

Delphi 4 Total

116

1997, 1998, 1999 GRIAULE

Procedimentos Gerais
Um procedimento um trecho de programa que tem um nome e pode ser utilizado (chamado) por outras partes do programa. Um procedimento de evento um procedimento que est diretamente ligado a um evento e chamado diretamente por um componente quando acontece aquele evento. Como j vimos, procedimentos de evento geralmente so criados pelo Delphi de forma automtica. Mas voc pode criar tambm procedimentos gerais, que no so associados a nenhum componente, e s so chamados quando voc determinar. Procedimentos gerais tornam o programa mais legvel e evitam repetio desnecessria de cdigo, facilitando a manuteno do programa. Em muitos casos, eles tambm contribuem para a reduo do tamanho do programa. Eles tambm podem ser reutilizados em vrios projetos, evitando "reinventar a roda" a cada novo programa que voc desenvolve.

Criando um Procedimento Geral


Abra novamente o projeto da calculadora, CALC.DPR. Nesse projeto temos uma validao de tecla, feita pelo procedimento de evento 'tratartecla'. Mas vamos transform-la em um procedimento geral, para poder reutilizar essa validao em outros programas. Quando voc cria um procedimento de evento, o Delphi gera automaticamente o esqueleto do procedimento, ou seja, um cabealho, mais o begin e end, inicialmente vazios. Mas um procedimento geral deve ser criado manualmente, ou seja, voc deve digitar todo o esqueleto. Na unidade CALC.PAS, coloque o cursor depois da palavra implementation e do comentrio {$R *.DFM}. Digite todas as linhas a seguir:

procedure ValidarTecla(var tecla: char); begin end;


O cabealho do procedimento contm a palavra procedure, o nome do procedimento (vamos cham-lo de 'ValidarTecla') e, entre parnteses, os parmetros do procedimento. Parmetros so variveis que recebem informaes externas, passadas por quem chamar o procedimento. Agora, dentro do procedimento 'TForm1.TratarTecla', selecione todo o texto entre o begin e o end e tecle [Ctrl+X] para retir-lo e guardar na rea de transferncia do Windows. Substitua o texto anterior por:

ValidarTecla(Key);

Delphi 4 Total

117

1997, 1998, 1999 GRIAULE Isso vai chamar o procedimento, substituindo o parmetro 'tecla' pelo argumento 'Key'. Argumentos so informaes passadas para o procedimento para substituir os parmetros. Volte ao procedimento 'ValidarTecla' e, dentro dele, use [Ctrl+V] para inserir o cdigo que foi copiado antes. Faa a seguinte alterao no cdigo: substitua as referncias a 'Key' por 'tecla'. O procedimento dever ficar como o seguinte:

procedure ValidarTecla(var tecla: char); begin if not (tecla in ['0'..'9', #8]) then tecla := #0; end;
O argumento (Key) e o parmetro (tecla) na verdade poderiam ter o mesmo nome. Ns colocamos nomes diferentes apenas para que o procedimento tenha uma forma mais geral. Execute o programa e ele deve continuar funcionando como antes.

Delphi 4 Total

118

1997, 1998, 1999 GRIAULE

Unidades Independentes
Da forma que o procedimento est, ele s pode ser usado na unidade CALC.PAS, associada ao formulrio da calculadora. Se quisermos que o procedimento seja usado por outras unidades do projeto, devemos colocar uma declarao do procedimento na interface da unidade. Mas essa ainda no a soluo ideal, pois para utilizar uma unidade associada em outro projeto, necessrio tambm utilizar o seu formulrio, mesmo que ele no seja necessrio. O melhor colocar o procedimento em uma unidade independente, ou seja, uma unidade no associada a nenhum formulrio. Unidades independentes facilitam a reutilizao, especialmente entre vrios projetos.

Criando uma Unidade Independente


Para criar uma unidade independente, use o item de menu File|New... do Delphi, ) e clique Ok. O Delphi vai abrir a nova unidade no editor de escolha o cone "Unit" ( cdigo, contendo apenas um esqueleto do mnimo que uma unidade deve ter (como vimos no captulo 9):

unit Unit2; interface implementation end.


Salve o projeto para dar um nome nova unidade. Chame-a de GERAL.PAS (porque ela vai conter procedimentos gerais). O cabealho da unidade automaticamente vai mudar para 'unit Geral;'.

Transferindo o Procedimento
Voltando unidade Calc (use as abas do editor de cdigo para mudar entre as duas), selecione todo o procedimento 'ValidarTecla', inclusive o cabealho. Tecle [Ctrl+X] para recort-lo da unidade. Agora alterne para a unidade Geral, coloque o cursor depois da palavra implementation e "cole" o texto, usando [Ctrl+V]. O corpo do procedimento deve ficar na seo de implementao, mas se ele precisar ser usado externamente, o cabealho do procedimento deve ser copiado para a seo de interface. Coloque o cursor na seo de interface e tecle [Ctrl+V]. Apague do begin ao end, porque s necessrio (e s permitido) o cabealho. A unidade ficar assim: Delphi 4 Total 119

1997, 1998, 1999 GRIAULE

unit Geral; interface procedure ValidarTecla(var tecla: char); implementation procedure ValidarTecla(var tecla: char); begin if not (tecla in ['0'..'9', #8]) then tecla := #0; end; end.

Usando a Unidade no Mesmo Projeto


Para utilizar os procedimentos da unidade 'Geral' em outra unidade, voc deve acrescentar 'Geral' clusula uses da unidade. Voltando unidade Calc, ela ainda no tem uma clusula uses na seo de implementao, ento acrescente uma, logo aps o {$R *.DFM}, contendo o seguinte:

uses Geral;
Execute o programa e ele dever funcionar como antes. Salve o projeto novamente.

Usando a Unidade em Outros Projetos


Abra o projeto MEDIAP.DPR. A unidade Geral, que criamos no outro projeto, um nico arquivo fonte (GERAL.PAS), que pode ser reutilizado quando necessrio em qualquer outro projeto. Primeiro acrescente a unidade ao projeto atual, usando File|Add to project... ou o boto da SpeedBar e escolhendo GERAL.PAS. Esse passo no estritamente necessrio(caso a unit GERAL esteja no mesmo diretrio que o projeto MEDIAP), mas importante para facilitar o gerenciamento do projeto, como veremos. Depois, voc deve acrescentar o nome da unidade clusula uses da unidade MEDIA.PAS, associada ao formulrio. A forma mais fcil de fazer isso a seguinte: selecione a unidade "Media" no editor de cdigo, e use o item de menu File|Use unit.... Na lista, clique em "Geral" e depois em Ok. O Delphi ir adicionar o seguinte seo de implementao da unidade:

uses Geral;
Delphi 4 Total 120

1997, 1998, 1999 GRIAULE Agora crie um procedimento de evento para o controle 'editNumero', evento OnKeyPress. Dentro do procedimento, coloque uma chamada a 'ValidarTecla'. Inicialmente digite apenas o seguinte e deixe o cursor posicionado aps o parntese:

ValidarTecla(
Repare que o Delphi mostra uma descrio dos parmetros do procedimento (no caso apenas var tecla: char). Essa uma caracterstica do Code Insight que permite saber facilmente quais so os parmetros que um determinado procedimento exige e o CodeExplorer mostra o procedimento na lista. Complete a linha como abaixo:

ValidarTecla(Key);
Ou seja, vamos passar como argumento a varivel 'Key'. Execute o programa. Note que agora o controle 'editNumero' agora tem a mesma validao de tecla, no permitindo valores no numricos.

Gerenciando um Projeto com Unidades Independentes


Ns vimos anteriormente que o Project Manager usado para facilitar o gerenciamento de projetos com vrios arquivos. Abra o Project Manager novamente e repare que a unidade independente 'Geral' aparece na lista de arquivos do projeto. Ele no permite expandir o arquivo GERAL.PAS, obviamente, pois essa unidade no est associada a um formulrio. Alm do Project Manager, voc pode usar o boto projeto, incluindo unidades independentes. (View Unit) para ver as unidades do

Se voc no adicionar uma unidade ao projeto, mas apenas adicionar uma clusula uses para ela, voc ainda pode acess-la,desde que esteja no mesmo diretrio do projeto ou no diretrio LIB do Delphi), mas ela no estar disponvel nas facilidades de gerenciamento de projeto.

Criando uma Biblioteca de Rotinas


Uma unidade independente pode funcionar como uma biblioteca de rotinas mais utilizadas, compartilhada por vrios projetos. Mas nesse caso preciso tomar certos cuidados. Por exemplo, se voc modificar um procedimento, isso pode afetar o funcionamento de outros projetos que o utilizam. Tambm, para que um procedimento seja reutilizvel, preciso que ele no dependa de nada especfico de um determinado projeto, como um formulrio ou uma varivel global, ou outra unidade. Uma unidade pode conter tambm, alm de procedimentos, constantes, tipos de dados definidos e variveis. Se estes forem declarados na parte interface, podem ser usados tambm por outras unidades. No caso de uma constante ou tipo de dados, pode ser Delphi 4 Total 121

1997, 1998, 1999 GRIAULE necessrio us-la(o) ainda na seo de interface. Nesse caso (e apenas nesse caso) necessrio acrescentar o nome a unidade clusula uses da seo de interface. Em todos os demais casos, melhor acrescent-la na seo de implementao.

Delphi 4 Total

122

1997, 1998, 1999 GRIAULE

Funes
Funes so semelhantes a procedimentos, mas so chamadas geralmente dentro de uma expresso. Uma funo retorna um valor para quem chamou, e esse valor inserido na expresso onde a funo foi chamada, por exemplo:

x := 3 * Soma(a,b);
Durante a execuo, a funo 'Soma' chamada, com os seus parmetros preenchidos de acordo com os argumentos fornecidos (a e b). A funo ento devolve um resultado, que inserido na expresso. Depois continua o clculo do restante da expresso.

Criando uma Funo


Vamos abrir novamente o projeto CALCP. Agora dentro da unidade Geral, vamos criar uma funo. Essa funo no vai fazer nada realmente til, pois apenas soma dois nmeros e devolve o resultado, mas ela ilustra os detalhes mais importantes que envolvem a criao e uso funes. Na seo de interface, digite o cabealho da funo:

function Soma(x,y: double): double;


No cabealho da funo, alm do nome e parmetros, preciso declarar o tipo de retorno da funo, ou seja, o tipo de dados do valor que a funo devolve. No caso, o tipo double, declarado depois do fecha parnteses. Agora na seo de implementao, repita o cabealho da funo e acrescente o corpo da funo, contendo o seguinte:

function Soma(x,y: double): double; begin Result := x + y; end;

Retornando um Valor
O nome 'Result' uma varivel automaticamente criada (no precisa ser declarada) dentro de uma funo. O valor colocado nessa varivel ser o valor retornado pela funo, que ser inserido no ponto de chamada. No caso, o valor calculado como a soma dos valores dos dois parmetros (x e y). O tipo dessa varivel o tipo de retorno da funo, no caso double. Para determinar o valor de retorno, tambm pode ser usada a sintaxe de antigas verses do Pascal, com o nome da funo do lado esquerdo: Delphi 4 Total 123

1997, 1998, 1999 GRIAULE

Soma := x + y;
A desvantagem dessa sintaxe que no possvel usar o nome 'Soma' do lado direito de uma atribuio, como possvel fazer com 'Result'. Ex:

Soma := Soma + y;

Chamando a Funo
No formulrio principal, clique duas vezes no boto com o sinal de "=" (btnCalcula) para abrir o procedimento de evento associado. Neste procedimento substitua a linha:

res := op1 + op2;


por uma chamada funo. Inicialmente digite apenas o seguinte e deixe o cursor aps o abre parnteses:

res := Soma(
Note que o recurso de Code Insight do Delphi automaticamente mostra a descrio dos parmetros (x: double; y: double). Caso voc no se lembre mais dos parmetros exigidos, esse recurso facilita bastante. Complete o restante da linha, com os argumentos:

res := Soma(op1, op2);


Note que os argumentos so separados por "," (vrgula) na chamada. Execute o programa e verifique que ele continua funcionando como antes. Notas: Se deseja ver o contedo de um procedimento ou funo ,clique com Ctrl+Clique . Notas: Se colocou o cabealho de um procedimento ou funo na seo interface, e deseja cri-los pressione Ctrl+Shift+C. Notas: Para alternar da seo implementation , para seo interface pressione Ctrl + Shift + ( ) , o contrrio utilize Ctrl+Shift + ( ).

Delphi 4 Total

124

1997, 1998, 1999 GRIAULE

Passagem de Parmetros
Quando um procedimento ou funo possui parmetros, ele deve ser chamado com argumentos correspondentes, na mesma ordem. Nenhum argumento deve ser omitido. (A documentao do Delphi chama os parmetros de formal parameters e argumentos de actual parameters). Por exemplo:

begin ValidarTecla(Key); end; ... procedure ValidarTecla(var tecla: char);

Declarao de Parmetros e Argumentos


Quando h mais de um parmetro, esses so separados por ";" (ponto-e-vrgula) na declarao do procedimento, se tm tipos diferentes:

function Soma(x: double; y: integer): double;


ou podem ser separados com ",", se tm o mesmo tipo:

function Soma(x, y: double): double;


e as duas formas podem ser combinadas, exatamente como em declaraes de variveis:

procedure TextOut(x,y:integer; text:string);


Na chamada ao procedimento ou funo, os argumentos so sempre separados por "," (vrgulas):

x := Soma(12, TAMANHO); TextOut(x, 13, 'Testando');


O nome do procedimento pode ser repetido no projeto ou na unit, o que diferencia um procedimento do outro o nmero e tipo de parmetros passados. Por Exemplo: A funo soma pode realizar a soma entre dois , trs e quatro nmeros , sendo que quando a soma for realizada entre quatro nmeros os dois ltimos so do tipo string. Como na Unit GERAL j existe uma funo que realiza a soma de dois nmeros , vamos criar as outras com o mesmo nome:

Delphi 4 Total

125

1997, 1998, 1999 GRIAULE

function Soma( op1, op2, op3 : double): double; begin result := op1 + op2 + op3; end; function Soma( op1, op2 : double, op3, op4 : string): double; begin result := op1 + op2 + strtofloat(op3) + strtofloat(op4); end;
Mas alm de criar as funes ou procedimentos com o mesmo nome necessrio que durante a declarao do procedimento especficique que eles sero sobrecarreagados, para isso temos que informar no final da declarao a diretiva overload.

function Soma(x,y: double): double;overload; function Soma( op1, op2, op3 : double): double;overload; function Soma( op1, op2 : double; op3, op4 : string): double;overload;

Tipos de Passagem
Existem vrias opes disponveis para passagem de parmetros de procedimentos ou funes. (Os nomes entre colchetes esto como aparecem na documentao do Delphi): Passagem por Valor [value parameter]: o valor do argumento (que pode ser uma varivel, constante ou uma expresso) simplesmente copiado para o parmetro. Isso significa tambm que qualquer alterao no parmetro no afeta o argumento original, mas apenas uma cpia local. Esse o mtodo padro de passagem, ou seja, um parmetro passado por valor se no for especificado em contrrio. A funo 'Soma' usa esse mtodo para os dois parmetros. Se o parmetro Tecla da funo Validar tecla for do tipo passagem por valor , o programa que chamar este procedimento no vai funcionar, porque o programa ir escrever os caracteres invlidos, portanto , necessrio alterar o argumento original. Passagem por Referncia [variable parameter]: o argumento deve ser uma varivel do mesmo tipo de dados do argumento. Qualquer alterao no parmetro afeta imediatamente o argumento original. Para indicar passagem por referncia, usa-se a palavra var antes do nome do parmetro. O procedimento 'ValidarTecla', por exemplo, usa passagem por referncia, porque precisa alterar o argumento original. Passagem Constante [constant parameter]: um parmetro constante (declarado com const antes do nome) no pode ser modificado dentro do procedimento. Essa caracterstica pode ser usada para impedir alteraes acidentais que violariam a lgica do programa. O argumento pode ser uma expresso qualquer. No caso de parmetros grandes, como Delphi 4 Total 126

1997, 1998, 1999 GRIAULE vetores e registros, a passagem constante evita que seja feita uma cpia do argumento, como na passagem por valor, portanto bem mais eficiente. No mesmo procedimento ou funo, um parmetro pode ser passado por valor e outros por referncia ou constantes, independentemente um do outro. Funes especificamente no precisam ter parmetros por referncia, pois elas j retornam um valor atravs da prpria chamada de funo, mas em alguns casos a passagem por referncia pode ser til.

Delphi 4 Total

127

1997, 1998, 1999 GRIAULE

Captulo 11 Objetos
O que Contm um Objeto Classes e Objetos Herana Formulrios como Objetos Variveis de Objetos Listas de strings Objetos Predefinidos Code Explorer Programao Orientada a Objeto

Delphi 4 Total

128

1997, 1998, 1999 GRIAULE

O Que Contm um Objeto


Um objeto, numa definio prtica, uma rea de memria separada do computador, contendo dados e o cdigo que manipula esses dados, e que manipulada como uma nica unidade. Por exemplo, qualquer componente, um formulrio, uma lista de strings, ou o objeto Clipboard. Nos programas, os dados de um objeto aparecem como campos do objeto, ou geralmente, como propriedades. Um objeto pode ter campos de dados que no so visveis externamente, com isso mantendo todo o controle sobre sua implementao interna. O cdigo de programa que manipula os dados feito atravs de mtodos. Um mtodo tem acesso a todos os campos de dados do objeto, mesmo aqueles que no so visveis externamente. Um mtodo pode ser um procedimento, que executa alguma ao quando chamado, ou uma funo, que alm de executar uma ao, retorna um valor para quem chamou, que pode ser usado em uma expresso.Os procedimentos de eventos criados so mtodos do objeto do formulrio criado. Por exemplo, com alguns mtodos que j vimos:

editNumero.SetFocus; {mtodo procedimento: SetFocus} Lines.SaveToFile(nome); {mtodo procedimento: SaveToFile} if Clipboard.HasFormat(cf_text) then {mtodo funo: HasFormat}
Um componente, que um tipo de objeto, pode ter tambm eventos, que so propriedades cujo valor um procedimento de evento. O procedimento que est associado a um evento chamado quando ele acionado.

Delphi 4 Total

129

1997, 1998, 1999 GRIAULE

Classes e Objetos
Todo objeto pertence a uma classe. Uma classe um esquema que deve como sero os objetos, quais suas caractersticas, e quais os mtodos que podem ser usados para manipular o objeto. Cada objeto especfico uma instncia da classe, criada de acordo com o modelo definido pela definio da classe. Por exemplo, cada cone da paleta de componentes corresponde a uma classe. O nome dessa classe tem a letra 'T' antes do nome que aparece. Por exemplo, o cone (Edit) corresponde classe TEdit. Quando voc seleciona esse cone e clica no formulrio, voc est criando um objeto da classe TEdit, que chamado (inicialmente) de "Edit1". Voc pode criar quantos objetos quiser da mesma classe, limitado apenas pela memria do computador. Se voc criar outros, eles sero chamados de "Edit2", "Edit3". O Object Inspector sempre mostra o nome do componente e o nome de sua classe, por exemplo:

Todos os objetos de uma mesma classe tm as mesmas caractersticas (propriedades), mas cada um tem seus prprios valores para essas caractersticas. Quando voc cria um objeto, ele comea como uma cpia idntica do modelo definido pela classe, e suas propriedades (exceto Name, que deve ser nico) comeam com os mesmos valores padro que a classe define. Depois voc pode alterar essas propriedades, diferenciando um objeto do outro. Voc pode tambm criar um objeto dinamicamente, durante a execuo do programa, conforme veremos.

Delphi 4 Total

130

1997, 1998, 1999 GRIAULE

Herana
Classes geralmente no so criadas a partir do zero. Quando voc cria uma nova classe, ela pode ser baseada em uma classe que j existe. Com isso, a classe herda todos os dados e mtodos da outra classe, mas pode acrescentar ou redefinir alguns de acordo com o que necessrio. O mecanismo de herana [inheritance] permite que voc programe apenas o que diferente entre a sua classe e a outra (programao por exceo). A classe da qual so herdadas as caractersticas chamada de classe base ou ancestral [ancestor] e a classe criada chamada de classe derivada ou descendente [descendent]. Herana no apenas uma cpia esttica de caractersticas. Qualquer alterao feita em uma classe ancestral automaticamente repercute nas classes descendentes. Quando a herana usada sucessivamente, com uma classe derivada tambm tendo classes derivadas, criada uma hierarquia [hierarchy] de classes, que pode ser representada com uma estrutura em rvore.

Hierarquia de Classes do Delphi


Ns j vimos que "todo controle um componente". Da mesma forma, "todo componente um objeto". Essas frases dizem respeito exatamente a relaes entre classes ancestrais e classes derivadas no Delphi. A classe 'TComponent' a ancestral, direta ou indireta de todas as outras classes de componentes. Ela contm as propriedades Name e Tag (alm de outras pouco usadas), que so herdadas por todas as outras classes descendentes. A classe 'TControl' uma das descendentes de TComponent. Ela contm propriedades, como Enabled, Visible, Left, Top, Width e Height e mtodos, como Refresh, que so herdados por todas as classes de controles, por exemplo, TEdit, TButton, TLabel. Todo formulrio tambm um controle. A classe 'TForm', que define as caractersticas de qualquer formulrio, descendente indireta de TControl. Quando voc cria um novo formulrio, o Delphi cria automaticamente uma classe de formulrio descendente de TForm, ou seja, seu formulrio tem todas as caractersticas de um formulrio padro, alm das que voc acrescentar (novos campos de dados, novos mtodos etc.). O nome da sua classe de formulrio criado com 'T' seguido do nome do formulrio, por exemplo, 'TMeuForm'. Uma viso simplificada de uma hierarquia de classes (omitindo algumas intermedirias) a seguinte: TComponent (ancestral de todos componentes) TOpenDialog (um componente que no controle) TControl (ancestral de todos controles) TForm (ancestral de todos formulrios) TFormPrincipal (suas classes... TFormCalen ...de formulrio) TButton (classes de... Delphi 4 Total 131

1997, 1998, 1999 GRIAULE TEdit ...controles) TTimer (um componente que no controle) Todas as classes no Delphi, inclusive TComponent, so descendentes diretas ou indiretas da classe TObject, que contm apenas mtodos bsicos de manipulao de objetos. Voc pode tambm criar uma nova classe de componente, derivando uma classe de TComponent ou de alguma descendente desta. Mas este um processo mais complexo, que envolve vrios detalhes de programao, e por isso no cobriremos no curso.

O Object Browser
Para visualizar a hierarquia de classes do Delphi e da sua aplicao, existe uma ferramenta que pode ser usada para isso. o Object Browser, que pode ser aberto no Delphi com o menu View|Browser (s est disponvel depois que voc compilou o projeto ao menos uma vez). Alm de classes, o Object Browser permite ver quais as constantes, tipos de dados e variveis das unidades utilizadas no projeto.

Simplificando o Acesso aos Campos


Campos, propriedades e mtodos de um objeto so acessados, geralmente, usando-se a sintaxe que j vimos, com o nome do objeto, seguido de um ponto e o nome do campo, propriedade ou mtodo:

editTamanho.Clear; editTamanho.Enabled := True; editTamanho.SetFocus;


Mas quando se acessa vrios campos do mesmo objeto, preciso repetir o nome do objeto em cada comando. Para evitar isso, existe o comando with. Dentro do bloco do comando with, o nome do objeto fica implcito:

with editTamanho do begin Clear; Enabled := True; SetFocus; end;

Delphi 4 Total

132

1997, 1998, 1999 GRIAULE

Formulrios como Objetos


Formulrios tambm so objetos. Quando voc cria um novo formulrio, o Delphi cria uma classe de formulrio e um objeto de formulrio dessa classe. O nome da classe de formulrio sempre inicia com um T, seguido do nome do objeto de formulrio (que voc define na propriedade Name do formulrio). A vantagem de ter uma classe de formulrio que isso torna possvel criar dinamicamente outros objetos de formulrio, alm do inicial, e alterar suas propriedades.

A Classe de Formulrio
Abra o projeto CalcData.DPR(Captulo 8). Voc ver inicialmente o formulrio principal. Tecle [F12] para ver a unidade do formulrio. Na seo de interface da unidade, logo aps a clusula uses, voc ver a declarao da classe de formulrio:

type TFormPrincipal = class(TForm) btnCalendario: TButton; btnCalculadora: TButton; btnFechar: TButton; editData: TEdit; Label1: TLabel; procedure btnFecharClick(Sender: TObject); procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean); procedure btnCalculadoraClick(Sender: TObject); procedure btnCalendarioClick(Sender: TObject); private { Private declarations } public { Public declarations } end; var formPrincipal: TFormPrincipal;
A primeira linha: TFormPrincipal = class(TForm) quer dizer que a classe do formulrio baseada na classe 'TForm', que define um formulrio genrico. Veremos mais sobre isso mais tarde. Dentro da definio da classe (que vai at a palavra end), existe uma declarao para cada componente do formulrio (no caso Button ,Edit e Label). Se voc adicionar, remover, ou renomear qualquer componente, o Delphi altera automaticamente essa seo. Para testar, alterne para o formulrio com [F12] e acrescente um componente Button. Quando voc Delphi 4 Total 133

1997, 1998, 1999 GRIAULE volta unidade, pode verificar que o Delphi acrescentou uma declarao para esse componente:

Button1: TButton;
onde 'Button1' o nome do componente e 'TButton' o nome da classe do componente, como veremos adiante. Volte ao formulrio, remova o boto e o Delphi vai tambm remover essa declarao. Depois das declaraes de componentes, comeam as declaraes para os procedimentos de evento. Para cada procedimento de evento, o Delphi adiciona uma declarao dentro da classe, como:

procedure btnFecharClick(Sender: TObject);


O corpo do procedimento, que fica na seo de implementao, contm os comandos que implementam realmente o procedimento. O cdigo at a palavra private mantido automaticamente pelo Delphi e voc no deve alter-lo. Geralmente no existe motivo para fazer alteraes manuais. As sees private e public dentro da definio da classe so onde voc pode adicionar mais elementos. O Delphi no troca o que voc colocar em uma dessas sees. O que fica na seo private acessvel apenas na unidade atual, mas o que for declarado na seo public visvel externamente em outras unidades. Com a palavra end, termina a definio da classe. Depois o Delphi acrescenta uma declarao de varivel para o formulrio. Essa declarao cria um formulrio baseado na classe definida antes:

Procedimentos na classe de formulrio


Vamos criar um mtodo para a classe desse formulrio, como um mtodo um procedimento criado dentro de um classe, podemos criar um procedimento na unit e declara-lo em uma das sees private ou public, por exemplo:

procedure AbrirFormulario;
E o corpo do procedimento, com os seus comandos, seria colocado na parte implementation, por exemplo:

procedure TFormPrincipal.AbrirFormulario; begin Show; end;


Quando definimos que um procedimento faz parte de uma determinada classe na criao do procedimento temos que especficar o nome da classe , como foi feito no exemplo anterior. Delphi 4 Total 134

1997, 1998, 1999 GRIAULE No exemplo citado o procedimento no faz muita coisa til. Mas a vantagem principal de criar um procedimento como parte da classe de formulrio que ele pode acessar diretamente qualquer componente que faz parte do formulrio, sem indicar o nome do formulrio. Isso torna mais fcil manipular os componentes. Vamos abrir o projeto EVENTOS.DPR (Captulo 6), podemos verificar que no procedimento abaixo que utiliza a propriedade Cursor do formulrio, no foi necessrio especificar o nome do objeto que referencia a classe do formulrio criado, isso no foi necessrio porque o procedimento faz parte da classe do formulrio especifico.

procedure TForm1.FormClick(Sender: TObject); begin if Cursor = crDefault then Cursor := crHourglass else Cursor := crDefault; end;

Delphi 4 Total

135

1997, 1998, 1999 GRIAULE

Variveis de Objeto
Uma varivel de objeto declarada utilizando o nome da classe como um tipo de dados, como j vimos:

var btnCalendario: TButton; Edit1:TEdit; formPrincipal: TFormPrincipal;


O contedo de uma varivel de objeto uma referncia a um objeto, internamente armazenada como o endereo de memria onde o objeto fica armazenado. Inicialmente o contedo da varivel lixo ou, no caso de uma varivel global, ela inicializada com o valor nil. Esse um valor especial que significa no caso "nenhum objeto". Se voc tentar usar uma varivel que contm nil, isso vai causar um erro de execuo. Voc pode inicializar a varivel, criando um objeto. Para isso, use o mtodo Create (o construtor da classe), com o nome da classe, por exemplo:

lista := TStringList.Create;
O construtor aloca um espao de memria para conter os dados do objeto e retorna o endereo dessa memria. Dependendo da classe, o construtor pode ter parmetros usados para inicializar o objeto. Algumas classes tm construtores com outros nomes ao invs de Create. Para liberar a memria usada pelo objeto, use o mtodo Free (definido na classe TObject e herdado por todas as classes). Se voc no liberar, o espao de memria do objeto continua alocado, mesmo que no existam mais variveis para acess-lo. Por exemplo, depois de terminar de usar uma string list, voc deve liberar a memria ocupada por ela:

lista.Free;
Quando voc atribui uma varivel de objeto a outra, no feita uma cpia fsica do objeto. A nica coisa copiada a referncia ao objeto. Depois da atribuio, ambas as variveis referenciam o mesmo objeto, por exemplo:

var btn: TButton; begin btn := btnDuplicar; btn.Caption := 'Duplicar de novo'; {afeta btnDuplicar indiretamente} ... end;
Delphi 4 Total 136

1997, 1998, 1999 GRIAULE Vamos criar um exemplo, que quando for clicado o mouse no formulrio, vamos criar componente TButton na posio do cursor. No formulrio, altere o nome para formCriaComp e o ttulo para "Criao de Componentes". Coloque dois componente Button , faa as seguintes alteraes: Button1 Name Caption Button2 Name Caption btnDestruir Destruir btnCriar Criar

Vamos criar uma propriedade na classe de formulrio 'TformCriaComp', para isto basta criar uma varivel nesta classe, como iremos armazenar nesta varivel a quantidade de botes criados,esta varivel ser publica. Na classe de formulrio 'TformCriaComp' na parte public , acrescente:

TForm1 = class(TForm) ....... private { Private declarations } public { Public declarations } QuantBotao:integer; end;
No evento OnClick do boto "btnCriar", faa o seguinte:

var botao : TButton; begin quantBotao := quantBotao + 1; botao := TButton.create(self); with botao do begin parent := self; caption := 'Boto' + inttostr(quantBotao); left : = 0; top := 0;
Delphi 4 Total 137

1997, 1998, 1999 GRIAULE

visible := true; end; end;


Antes de criar o Boto iremos adicionar o valor 1 a propriedade quantBotao. Quando voc cria um componente,usa o construtor Create da classe TComponent. Esse construtor exige como parmetro o formulrio onde o componente ser criado. No caso, passamos 'Self'(o formulrio atual), que o mesmo que 'FormCriaComp' nesse caso. O formulrio 'Self' ser o dono[owner] do componente.Mas no caso de um controle(componente visual) preciso dizer tambm quem ser o pai[parent] desse controle. Se for o prprio formulrio, o controle fica sobre o formulrio. Mas se houver outro controle que capaz de conter controles, o pai pode ser esse outro controle. Por Exemplo: O controle Panel, se colocar esse controle sendo o pai do Boto, este ser criado em cima do Panel. Quem determina o pai do componente a propriedade Parent. Depois a propriedade caption alterada para 'Boto' mais o contedo da propriedade quantBotao, e a posio do componente(propriedades Top e Left) definida com o valor Zero.A propriedade Visible faz com que o componente aparea no formulrio. No evento OnClick do boto "btnDestruir", vamos destruir o boto criado, o mtodo utilizado para liberar a memria o Free. Ento acrescente:

var botao :TButton; begin botao.free end;


Execute o programa. Para testar clique no boto 'Criar'. A cada clique no boto ser criado um componente da classe TButton, mas quando for destruir o componente no ir funcionar , pois, a referencia que existia para os botes que foram criados anteriormente foram perdidas. Um dos problemas ocorre porque a varivel que contm a referncia do objeto da classe TButton local, existindo somente no procedimento que foi criada. Para solucionar este problema vamos criar a varivel botao sendo global, ento vamos retirar a declarao desta varivel nos procedimentos de eventos TCriaComp.btnCriarClick e TCriaComp.btnDestruirClick. E na seo implementation acrescente a declarao desta varivel.

Implementation {$R *.DFM} var botao:TButton;

Delphi 4 Total

138

1997, 1998, 1999 GRIAULE Mesmo colocando esta varivel sendo global o problema ainda no foi resolvido , pois, o boto 'Criar' continua permitindo a criao de mais de um boto, com isso a varivel botao sempre ir conter a referncia para o ltimo boto criado. Vamos considerar que queremos criar somente um boto de cada vez, inicialmente o boto 'Destruir' vai aparecer desabilitado, porque no temos nenhum boto criado, ao criar iremos habilitar o boto 'Destruir' e desabilitar o boto 'Criar' e quando destruir o boto vamos desabitilitar o boto 'Destruir' e habilitar o boto 'Criar'. Na propriedade Enabled do boto 'Destruir' altere seu valor para false. No envento OnClick do boto 'Criar' acrescente o cdigo a seguir:

btnDestruir.enabled := true; btnCriar.enabled = false;


E no evento OnClick do boto 'Destruir' acrescente:

btnDestruir.enabled := true; btnCriar.enabled = false;


Vamos salvar o projeto como CRIACOMP.PAS e CRIACOMPP. Execute e teste o projeto.

Delphi 4 Total

139

1997, 1998, 1999 GRIAULE

Listas de Strings
O Delphi possui um tipo de objeto que til quando se trabalha com vetores de strings. So as chamadas listas de strings [string lists]. importante saber trabalhar com esse tipo de objeto, pois vrias propriedades de componentes so do tipo lista de strings, como a propriedade Items dos controles ListBox e ComboBox, a propriedade Lines de um controle Memo, entre outras. Vamos abrir o primeiro projeto criado, AULA1P. Nesse projeto, existe um componente ListBox chamado 'ListBox1' (o nome default). No cdigo do boto Adicionar, o programa faz o seguinte:

ListBox1.Items.Add(Edit1.Text);
Nesse cdigo, 'ListBox1.Items' uma string list, e nesse caso, est sendo utilizado o mtodo Add da string list, que adiciona um elemento. Como essa string list est associada a 'ListBox1', o item adicionado tambm aparece na lista.

Propriedades da String List


Voc pode usar a propriedade Strings, que um vetor, para acessar os elementos da lista (o ndice do vetor comea de zero), por exemplo:

nome := ListBox1.Items.Strings[i];
ou simplesmente, omitindo o nome da propriedade, pode-se acessar a lista como um vetor:

nome := ListBox1.Items[i];
A propriedade Count informa quantos elementos existem na lista, por exemplo:

for i := 0 to ListBox1.Items.Count - 1 do Writeln(arquivo, ListBox1.Items[i]);


A propriedade Sorted, quando True (verdadeiro), faz com que os elementos da lista sejam classificados automaticamente.

Mtodos da String List


O mtodo Add adiciona um elemento no final da lista ou na posio em ordem alfabtica, dependendo do valor de Sorted. Voc pode adicionar um elemento no meio da lista, usando Insert. Para remover um elemento, usa-se o mtodo Delete, informando a posio numrica. Para remover todos os elementos, basta usar o mtodo Clear. Alm disso, Move move um elemento para outra posio e Exchange troca dois elementos de lugar. Resumindo, os mtodos so usados da forma: Delphi 4 Total 140

1997, 1998, 1999 GRIAULE

Add(novoElemento); Insert(posio, novoElemento); Delete(posio); Clear; Move(posio-ant, posio-nova); Exchange(pos1, pos2);

{adiciona} {insere} {exclui um elemento} {exclui todos} {move} {troca os elementos}

Para procurar um elemento na lista, usa-se IndexOf. Se o elemento no for encontrado, retorna -1. Por exemplo:

pos := ListBox1.Items.IndexOf(Edit1.Text); if pos <> -1 then {achou...}


No programa EDITORP, ns utilizamos dois mtodos que permitem salvar ou ler uma string list para um arquivo, que so LoadFromFile e SaveToFile. Por exemplo:

memoEditor.Lines.LoadFromFile(dlgArquivo.FileName);
Isso pode ser feito porque 'memoEditor.Lines' uma string list. De forma geral, esse mtodos so usados como:

LoadFromFile(nomeArquivo); {carrega do arquivo} SaveToFile(nomeArquivo); {salva para o arquivo}

Criando String Lists Independentes


Voc tambm pode criar string lists independentemente de qualquer componente, declarando uma varivel do tipo TStringList, e usando o mtodo Create. Aps terminar de usar a string list, voc deve liberar a memria ocupada por ela com o mtodo Free:

var lista: TStringList; begin lista := TStringList.Create; lista.Sorted := True; lista.Add('Curso'); lista.Add('Delphi'); lista.Delete(0);
Delphi 4 Total 141

1997, 1998, 1999 GRIAULE

lista.Free; {libera memria} end;

Delphi 4 Total

142

1997, 1998, 1999 GRIAULE

Objetos Predefinidos
A biblioteca do Delphi contm vrios objetos predefinidos, que voc pode usar no programa sem precisar de declarar variveis para eles. Com esses objetos, voc pode utilizar funcionalidade adicional no seu programa.

O Objeto Application
O objeto Application representa a sua aplicao como um todo. Ele tem vrias propriedades e mtodos usadas internamente pelo Delphi, mas algumas delas so teis no seu prprio cdigo. A propriedade Title determina qual o ttulo que aparece no cone quando o programa minimizado. A propriedade ExeName (somente de leitura) permite voc consultar qual o nome do arquivo executvel do seu programa. Voc pode terminar a execuo do programa, em qualquer ponto, usando o mtodo Terminate. Quando voc passa muito tempo em um lao de processamento, o Delphi no tem uma oportunidade para verificar os eventos do usurio. Isso pode fazer o seu programa aparecer como se estivesse "travado" para o usurio. Para evitar isso, voc pode chamar o mtodo ProcessMessages do objeto Application, de tempos em tempos dentro do lao, o que d a oportunidade ao seu programa de processar os eventos:

while not fim do begin ... Application.ProcessMessages; ... end;

O Objeto Clipboard
O objeto Clipboard representa a rea de transferncia [clipboard] do Windows, uma rea de memria usada para passar informaes entre programas. O clipboard pode ser usado para guardar texto ou imagens. Para ler ou colocar um texto no Clipboard, use a propriedade AsText, por exemplo:

Clipboard.AsText := edit1.text; ... s := Clipboard.AsText; {se houver texto no clipboard, pega o valor desse texto}
Delphi 4 Total 143

1997, 1998, 1999 GRIAULE O mtodo Assign pode ser usado para copiar uma imagem para o Clipboard, a partir de um componente Image, por exemplo:

Clipboard.Assign(image1.Picture);
Para fazer o contrrio, voc pode trazer a imagem que est no Clipboard dentro de um componente Image, por exemplo:

image1.Picture.Assign(Clipboard);
Para saber se um determinado formato est disponvel, use o mtodo HasFormat, que retorna um valor do tipo boolean:

if Clipboard.HasFormat(CF_TEXT) then ...


O parmetro de HasFormat pode ser: CF_TEXT para verificar se existe um texto, ou CF_BITMAP, CF_DIB, CF_IMAGE para verificar se existe uma imagem. Para usar o objeto Clipboard no programa, voc precisa acrescentar a unidade Clipbrd sua clusula uses.

O Objeto Screen
O objeto Screen representa a tela do computador e tem propriedades que permitem consultar a resoluo da tela, e saber qual o controle ou formulrio que tem o foco atualmente. As propriedades Width e Height contm, respectivamente, a largura e altura da tela em pixels. A propriedade PixelsPerInch um fator de converso, que diz quantos pixels existem em uma polegada. Com isso voc pode converter pixels em unidades fsicas e viceversa. A propriedade Fonts um objeto TStringList que contm todos os nomes de fontes disponveis no Windows. Voc pode acessar o formulrio ativo (o que tem o foco de teclado) atravs da propriedade ActiveForm e o controle que tem o foco com a propriedade ActiveControl (do tipo TControl). A propriedade Cursor, se alterada, vai mudar o cursor do mouse de forma global para todos os formulrios. Voc pode tambm alterar o cursor para um formulrio individual, com a propriedade Cursor do formulrio.

Delphi 4 Total

144

1997, 1998, 1999 GRIAULE

Code Explorer
O code explorer aparece quando estamos editando uma Unit. Vamos abrir o projeto CRIACOMPP.DPR, e vamos no editor de codigo da Unit 'CriaComp', ir aparecer a seguinte janela:

O code Explorer o que parece do lado esquerdo desta janela, nele conseguimos visualizar quais so as constantes, variveis , uses e as classes utilizados na unidade que aparece no editor de cdigo. Vamos expandir cada item que aparece no code explorer e teremos o seguinte resultado:

Delphi 4 Total

145

1997, 1998, 1999 GRIAULE

Como a nica classe que foi definida dentro desta Unit 'TFormCriaComp', apareceu somento o nome dela. Nesta classe mostrado o que foi definido nas partes Public e Private. Na opo 'Variables/Constant' conseguimos obter todas as variveis globais que foram declaradas e em 'Uses' identificamos as units utilizadas.

Delphi 4 Total

146

1997, 1998, 1999 GRIAULE

Programao Orientada a Objetos


A programao orientada a objeto (POO) uma forma de programao que tenta construir os programas como colees de classes e objetos, relacionados entre si. Uma classe uma estrutura de dados, definida em tempo de projeto, que contm tambm os procedimentos que manipulam esses dados. Um objeto uma instncia de uma classe, criada em tempo de execuo, de acordo com a estrutura da classe e que pode ser manipulada com os mtodos da classe. A idia da POO criar o mnimo possvel de dependncias de uma parte do programa em relao outra. (As "partes" do programa so as classes e seus objetos). Com isso, uma parte pode ser alterada sem afetar as outras. Num programa orientado a objeto bem construdo, o efeito de uma alterao no cdigo menor e mais previsvel. Em outros tipos de programao, uma alterao no cdigo pode causar problemas, bugs, inconsistncias etc. em vrias partes do programa. Alm disso, a programao orientada a objeto facilita bastante a reutilizao de cdigo. Sem POO, possvel reutilizar cdigo, por exemplo, procedimentos e funes isolados, mas isso tem suas limitaes. Na POO, vrios conceitos so importantes: encapsulamento, herana e polimorfismo. Encapsulamento permite esconder membros de uma classe para evitar que outras classes alterem a estrutura interna do objeto. Por exemplo, um "cliente" da classe TConta no precisa saber como ela guarda as movimentaes da conta e no tem acesso para modificar essas informaes (e falsificar um extrato, por exemplo). Com o encapsulamento, voc garante que o objeto pode alterar sua representao interna sem afetar nenhuma outra classe. Ele s no pode alterar a sua interface, isto , o conjunto de mtodos e dados pblicos (por exemplo, Depositar(valor:double) e Retirar(valor:double)). O encapsulamento ento fora uma separao entre interface e implementao, onde a interface geralmente fixa ou muda pouco enquanto a implementao de uma classe tem total liberdade para mudar. Herana permite criar uma classe derivada a partir de uma classe base. A classe derivada herda a implementao da base, reutilizando o cdigo que j existe, que j foi testado e aprovado. A classe derivada pode modificar ou estender o funcionamento de mtodos j existentes. Uma classe derivada herda tambm a mesma interface da classe base. Isso quer dizer que em qualquer lugar que possa ser usado um objeto da classe TBase, ele pode ser substitudo por um objeto da classe TDerivada (porque ele suporta os mesmos mtodos). Essa possibilidade, de substituir um objeto por um de outra classe derivada, chamado polimorfismo. Com o polimorfismo, um "cliente" de uma classe (procedimento que usa objetos da classe) pode ser escrito sem se preocupar com a subclasse especfica que ele vai manipular. Futuramente, se novas subclasses so criadas, com capacidades adicionais, o cliente no precisa nem mesmo saber que elas existem, mas pode us-las como objetos da classe TBase.Claro que ainda possvel criar programas mal-estruturados, confusos, e Delphi 4 Total 147

1997, 1998, 1999 GRIAULE instveis com POO. Mas se voc entender corretamente os conceitos e aplicar da forma correta os recursos da linguagem, corre um risco menor de acontecer isso.

Delphi 4 Total

148

1997, 1998, 1999 GRIAULE

Captulo 12 Aplicaes de Banco de Dados


Termos Usados Desktop x Cliente / Servidor Formatos de Bancos de Dados Criando Tabelas Exemplo: Criando um Formulrio "Manualmente" Exemplo: Usando o Database Form Wizard Resumo dos Componentes de Dados Apelidos de Bancos de Dados

Delphi 4 Total

149

1997, 1998, 1999 GRIAULE

Termos Usados
Os sistemas de programao necessrios ao funcionamento de uma empresa precisam manter dados de forma permanente, e fornecer recursos para atualizar e pesquisar nesses dados. Os recursos de linguagem que permitem isso so chamados de acesso a bancos de dados. Um registro [record] um grupo de variveis com tipos de dados diferentes, que armazenam dados relacionados. Por exemplo, um registro pode conter os dados relativos a um produto vendido pela empresa, como descrio, cdigo de identificao, quantidade em estoque. Um campo [field] um dos itens de informao dentro do registro, como a descrio do produto. Uma tabela [table] no Delphi um conjunto de registros com a mesma estrutura, armazenados de forma permanente em disco. Uma tabela pode ser um arquivo fsico, mas no necessariamente, como veremos. Algumas documentaes se referem aos registros de uma tabela como linhas [rows] e aos campos como colunas [columns]. Um banco de dados [database] um conjunto de tabelas que contm dados relacionados. Por exemplo, um sistema de contas a pagar poderia ter um banco de dados de contas a pagar, com uma tabela para duplicatas, uma tabela para bancos etc. Geralmente sistemas pequenos ou mdios usam apenas um banco de dados contendo todos os dados. Um apelido [alias] no Delphi um nome que representa um banco de dados, independente de sua localizao. Isso permite mover os dados para outro local, sem alterar o programa. Existem vrios formatos de bancos de dados que podem ser acessados pelo Delphi. Dependendo do formato, um banco de dados pode ser fisicamente um subdiretrio do disco, ou um nico arquivo. Um ndice [index, plural 'indexes' ou 'indices'] um mecanismo que permite pesquisar rapidamente um registro em uma tabela, dado o valor de um determinado campo (ou alguns campos) da tabela. Durante a execuo, cada tabela possui um registro atual ou corrente [current record], cujos dados esto disponveis para o programa. Voc pode alterar a posio de registro atual, movimentando-se seqencialmente pelos registros, ou ento usando um ndice para procurar um registro. Um recurso extremamente poderoso do acesso a bancos de dados do Delphi a consulta [query], que permite obter todo um subconjunto da tabela ou de vrias tabelas, especificando as condies de seleo. Nota: Voc pode criar um registro no Object Pascal com uma estrutura do tipo record, e manipular um arquivo de registros. Mas esse tipo de acesso no tem muitos recursos, como a possiblidade de alterar a estrutura de um arquivo, ou excluir um registro, ou pesquisar um valor. Delphi 4 Total 150

1997, 1998, 1999 GRIAULE

Desktop x Cliente/Servidor
Uma aplicao que utiliza bancos de dados composta de trs partes: Interface com o usurio: responsvel por validar as entradas do usurio, e iniciar pesquisas de acordo com um pedido do usurio. Mecanismo de acesso a banco de dados: [database engine]: responsvel pela manuteno das estruturas de dados necessrias em arquivos, pelos detalhes internos do acesso aos dados, e pela manuteno da integridade dos dados. Armazenamento de dados: arquivos que contm os dados em si. Num computador isolado, todos os trs componentes ficam no mesmo computador. J numa rede, que envolve no mnimo uma estao e um servidor, a configurao pode ser diferente. Um banco de dados "desktop" (ou baseado em arquivos) aquele no qual a interface com o usurio e o mecanismo de acesso ficam no mesmo computador (a estao) e apenas os arquivos dados ficam num servidor de rede. Operaes de consulta ou pesquisa devem passar atravs da rede. Por exemplo, quando um usurio quer ver uma relao de contas a pagar, mas apenas em determinado perodo, o sistema deve selecionar alguns registros baseado na data informada. No ambiente desktop, a estao traz todos os registros atravs da rede, mesmo os que no so utilizados. O trfego gerado na rede grande, principalmente quando vrias estaes acessam simultaneamente o servidor. J num banco de dados cliente/servidor, a interface com o usurio fica na estao e se comunica remotamente com o mecanismo de acesso, que um sistema gerenciador de banco de dados (SGBD) rodando no servidor. Quando o SGBD recebe um pedido para selecionar alguns dados, ele acessa localmente os dados no servidor e retorna apenas o resultado pedido. No caso de uma atualizao, no necessrio nem mesmo retornar um resultado, apenas informar que a atualizao foi feita. O diagrama abaixo resume as diferenas entre os ambientes: Desktop Cliente/Servidor

Delphi 4 Total

151

1997, 1998, 1999 GRIAULE

Bancos de dados desktop funcionam relativamente bem quando so poucos os dados a serem acessados, ou poucas consultas feitas simultaneamente, de forma que o trfego na rede seja pequeno. Em redes maiores, recomendvel utilizar o mecanismo cliente/servidor. No Delphi voc pode comear a desenvolver sua aplicao usando um banco de dados desktop e depois migrar para cliente/servidor, com poucas modificaes no programa, pois a forma de acesso atravs do programa praticamente a mesma. Nota: De acordo com a Borland, com menos que 12 usurios simultneos, um ambiente desktop pode fornecer um timo desempenho. Mas para mais usurios, recomenda-se um sistema cliente/servidor, como o InterBase ou SQL Server por exemplo. Ambientes c/s tambm so mais confiveis.

Delphi 4 Total

152

1997, 1998, 1999 GRIAULE

Formatos de Bancos de Dados


Todo o acesso a dados feito atravs do Borland Database Engine (BDE), (anteriormente chamado IDAPI), que embutido no prprio Delphi. O BDE permite acesso a alguns formatos de dados "nativos", mas atravs de interfaces adicionais, permite acessar praticamente qualquer banco de dados padro de mercado. Em resumo, os formatos disponveis so os seguintes: Formatos Desktop: o BDE acessa "nativamente" vrios formatos de dados no padro desktop, como Paradox, dBase, Microsoft Access e FoxPro: Paradox: correspondem ao formato utilizado pelo Paradox, um banco de dados da Borland. Cada tabela tem um arquivo separado, com a extenso DB. dBASE/FoxPro: formatos semelhantes, com pequenas diferenas. Cada tabela um arquivo separado, com a extenso DBF. Access: usado pelo Access, da Microsoft. Cada banco de dados um nico arquivo .MDB, que contm vrias tabelas. InterBase: o InterBase um banco de dados da Borland que pode ser usado para desenvolver e testar aplicaes cliente/servidor. As edies Professional e Client/Server vm com uma verso reduzida do InterBase, chamado "InterBase Local", e com drivers que podem ser usados para acessar essa verso. A edio Client/Server vem com o InterBase para Windows NT, para ambientes cliente/servidor com at 4 usurios. O InterBase armazena o banco de dados inteiro, com todas suas tabelas, num nico arquivo de extenso GDB. SQL Links: na edio Client/Server, o Delphi inclui os drivers "SQL Link", para acesso nativo a vrios formatos de bancos de dados cliente/servidor, como: Oracle, Sybase SQL Server, Microsoft SQL Server, Informix, IBM DB/2 e InterBase. ODBC: permite utilizar drivers ODBC, que um padro definido pela Microsoft, mas utilizado por vrios fabricantes de bancos de dados. Atravs do ODBC voc pode utilizar outros bancos de dados que no so suportados das outras formas. ODBC pode ser usado a partir da edio Professional. O formato que voc vai utilizar depende de se voc est acessando um banco de dados j existente, que exige um determinado formato, ou se voc est criando o banco de dados a partir do incio. Neste ltimo caso, voc pode optar por um formato desktop ou cliente/servidor, dependendo do custo necessrio e do tamanho e quantidade de acessos previsto para os seus dados.

Delphi 4 Total

153

1997, 1998, 1999 GRIAULE

Criando Tabelas
Aps definir qual a estrutura que devem ter suas tabelas, voc deve criar fisicamente o seu banco de dados. Dependendo do formato de dados, voc pode utilizar um programa especfico do banco de dados ou usar um utilitrio fornecido juntamente com o Delphi o Database Desktop (DBD). Chame esse utilitrio a partir do Delphi, atravs de seu cone em: |Programas|Borland Delphi 4|Database Desktop.

Definindo um Diretrio de Trabalho


Antes de comear a criar tabelas, melhor definir um diretrio de trabalho, que o diretrio padro usado pelo DBD para criar os arquivos de dados. Voc pode salvar tabelas em qualquer diretrio, mas esta opo facilita o trabalho. Abra o menu File|Working Directory... e digite o diretrio onde sero colocados os arquivos do curso ("C:\CURSODF\TABELAS"). Clique Ok.

Definindo a Estrutura dos Campos


Para criar uma tabela, use File|New|Table.... Voc deve escolher qual o formato de dados a ser utilizado para a tabela (o padro "Paradox 7"). Clique Ok para aceitar o default. Agora dever aparecer a lista de campos a ser preenchida. No nosso caso, a tabela ter a seguinte estrutura: Campo CodCliente Nome Telefone DataNasc Tipo S A A D Tamanho (automtico) 40 10 (automtico) Chave *

Digite o nome do campo "CodCliente" na coluna "Field Name" e tecle [Tab] ou a seta [ ] para mudar para a coluna "Type". Em tabelas Paradox, nomes de campos podem ter at 25 caracteres, e podem incluir letras, dgitos e espaos. (outros formatos de dados tm regras diferentes). Os tipos de dados em tabelas Paradox so representados por letras. Clique com o boto direito na coluna "Type" para escolher um tipo de dados ou digite diretamente a letra correspondente. Para esse campo, escolha o tipo "S" (short), que corresponde a um nmero Delphi 4 Total 154

1997, 1998, 1999 GRIAULE inteiro binrio, com a mesma faixa de valores do tipo smallint do Object Pascal. O tamanho do campo determinado automaticamente, ento pule a coluna "Type". Em qualquer tipo de tabela, ndices pode ser usados para pesquisa ou ordenao de valores. Mas em tabelas Paradox, existem dois tipos de ndices. O ndice primrio [primary index] ou chave primria [primary key] determina um valor que deve ser nico para todos os registros da tabela, e tambm determina a ordem default em que os registros sero percorridos. Um ndice secundrio [secondary index] usado apenas para pesquisa e ordenao. A coluna "Key", se estiver marcada, diz que o campo parte da chave primria da tabela. (S os primeiros campos da tabela podem fazer parte da chave primria). No nosso caso, marque a coluna "Key" apenas para o campo "CodCliente". Faa isso com um duplo clique do mouse ou pressionando qualquer tecla. Tecle [ ] (seta para baixo) para definir os outros campos. Digite as caractersticas dos campos nas colunas apropriadas. Os campos "Nome" e "Telefone" so alfanumricos, isto , do tipo "Alpha". Note que eles exigem a definio do tamanho do campo, enquanto outros tipos como "Short" e "Date" no permitem uma determinao de tamanho, porque utilizam um tamanho automtico. O campo "DataNasc" do tipo "Date", que armazena datas. Note que o ano sempre armazenado com quatro dgitos, embora normalmente ele esteja configurado para mostrar apenas dois dgitos.

Salvando a Tabela
Para salvar a tabela, clique no boto "Save As...". Note que o DBD vai mostrar o diretrio de trabalho (definido anteriormente), mas tambm permite salvar em qualquer outro diretrio. Digite o nome "CLIENTE" e clique Ok. Como uma tabela Paradox, a extenso de arquivo ".DB" ser adicionada automaticamente, criando um arquivo CLIENTE.DB.

Entrando com Dados


Aps criar a tabela, voc pode entrar com alguns dados para teste no prprio Database Desktop. Para isso abra a tabela que voc criou com File|Open|Table..., selecionando CLIENTE.DB no diretrio. Voc vai ver a estrutura da tabela, mas ainda sem nenhum registro. Quando voc abre uma tabela, ela est em modo de visualizao, e no permite edio. Para editar os dados, tecle [F9] ou clique no boto , que vai colocar a tabela em modo de edio. O mesmo processo volta ao modo de visualizao.

Delphi 4 Total

155

1997, 1998, 1999 GRIAULE Digite alguns dados de teste para preencher a tabela. Use as setas, ou [Tab] e [Shift+Tab] para mudar de campos e a seta [ ] para incluir um novo registro. Como o campo "CodCliente" a chave primria, voc no pode incluir dois registros que tenham o mesmo valor desse campo. Os registros sempre sero mantidos na ordem desse campo. Para acrescentar um registro no meio, use a tecla [Ins]. Para excluir um registro, use [Ctrl+Del]. Tecle [F2] ou clique no boto quando quiser editar um campo seno, quando voc comear a digitar, o contedo anterior perdido. Note como o campo DataNasc automaticamente validado, e no permite datas invlidas como "32/04/97", "29/02/97" (1997 no bissexto). Ele lido e mostrado no formato "dia/ms/ano", se a configurao do Windows estiver com esse formato. Nota: o Windows armazena uma configurao padro para formato de datas, horas, nmeros etc., que usada por todos os programas. Ela pode ser alterada atravs do Painel de Controle, cone "Configuraes Regionais".

Delphi 4 Total

156

1997, 1998, 1999 GRIAULE

Exemplo: Criando um Formulrio "Manualmente"


Vamos criar um projeto para acessar a tabela de clientes. Crie um novo projeto para comearmos com um formulrio em branco. Para criar um formulrio que acessa dados, voc deve selecionar alguns componentes da pgina Data Access.

A Pgina Data Access


Selecione a pgina Data Access na paleta de componentes. Essa pgina contm componentes no-visuais que so responsveis pelo acesso bsico aos dados.

Selecione o cone do componente Table, . Coloque um componente Table no formulrio, em qualquer posio. Altere sua propriedade Name para "tblCliente". Na propriedade DatabaseName desse componente contm o nome do banco de dados. Como estamos usando um ambiente desktop, o nome do banco de dados o caminho do diretrio que contm os arquivos de dados ,altere seu contedo para "C:\CURSODF\TABELAS" (ou o diretrio onde estiverem os dados no seu computador). Na propriedade TableName, clique no boto de seta, voc ver a lista das tabelas existentes naquele diretrio selecione o nome da tabela "CLIENTE.DB". O componente Table representa uma tabela do banco de dados, mas ele no tem capacidade de mostrar os dados visualmente. Voc deve acrescentar tambm um componente DataSource.

Clique no cone do componente DataSource, , e coloque-o no formulrio. Altere seu nome para "dsCliente". Na propriedade DataSet, selecione da lista o nome do componente Table, "tblCliente", que determina de onde vem os dados. Isso faz a ligao entre os dois. Este componente serve como uma ponte entre um componente Table e os controles de dados. Esses dois componentes fazem o acesso aos dados, mas como eles no so visuais, preciso usar controles de dados, que mostram os valores de campos para o usurio, e lem os valores digitados para gravar no banco de dados.

Criando os Controles de Dados


Para mostrar e editar os dados, so necessrios controles de dados, que interagem com o usurio, permitindo editar um campo. Voc pode criar controles de dados selecionando um dos cones da pgina Data Controls. Por exemplo, o componente DBEdit funciona como o Edit, mas acessa um campo do banco de dados. Delphi 4 Total 157

1997, 1998, 1999 GRIAULE Mas a forma mais fcil de criar os controles de dados com um recurso do Delphi bastante utilizado, o editor de campos [fields editor]. Para abrir o editor de campos, clique duas vezes no componente 'tblCliente' no formulrio.

O editor de campos inicialmente aparece com a lista vazia. Isso significa que o componente Table cria automaticamente objetos de campo, baseado na estrutura da tabela. Para podermos inserir os controles de dados no formulrio, temos que fazer o seguinte: clique com o boto direito no fundo do editor de campos e clique em "Add fields...". Vai aparecer uma tela com todos os nomes de campos selecionados. Clique em Ok para adicionar todos os campos. Agora o editor de campos vai estar preenchido com a lista de campos. Selecione todos os campos , arraste e solte em cima do formulrio. Vo aparecer vrios controles de dados, do tipo DBEdit e, acima deles, controles do tipo Label com o nome dos campos. O primeiro controle de dados fica logo abaixo do label "CodCliente". Este um controle do tipo "DBEdit" e seu nome "Edit1". O que faz a associao so as propriedades DataSource e DataField. Movimente os labels para outra posio, esquerda do componente correspondente. Altere a propriedade Caption dos componentes Label "CodCliente" para "Cdigo" e o Label "DataNasc" para "Data Nasc.". A propriedade DataSource de cada um dos controles de dados(neste caso temos somente o DBEdit), contm "dsCliente", que o nome do componente DataSource . A propriedade DataField contm o nome do campo, por exemplo "CodCliente" no primeiro controle. (Note que a lista de valores de "DataField" contm todos os nomes de campos da tabela, em ordem alfabtica.) Todos os outros controles de dados tm o mesmo valor de DataSource, mas cada um tem um valor para DataField, que o nome do campo correspondente. Ou seja, todos os controles de dados so ligados ao 'dsCliente', que por sua vez est ligado a 'tblCliente'. Para alinhar os componentes selecione todos os componentes edit , em seguida clique em algum componente selecionado com o boto direito e escolha a opo "Align". Ser Delphi 4 Total 158

1997, 1998, 1999 GRIAULE mostrado uma janela para fazer as modificaes, marque as opes de acordo com a figura abaixo:

Se estas opes estiverem marcadas os componentes selecionados iram ficar alinhados esquerda e na vertical teram o mesmo espao. Repita o processo para os componentes Labels. O resultado final ser como a figura abaixo:

Notas: Cuidado ao escolher as opes de alinhamento, voc pode piorar a esttica do formulrio , principalmente se selecionar todos os componentes e na opo "Vertical" marcar "Centers", os componentes iram ficar na mesma posio, para consertar teria que retirar os componentes um a um , se voc no tem muita prtica de utilizar estas opes , salve o formulrio antes de fazer as alteraes.

Adicionando o DBNavigator
Ainda na pgina Data Controls, selecione o cone do DBNavigator, e coloque o controle no formulrio, acima dos controles de dados. Altere a propriedade DataSource desse controle para "dsCliente". Este controle permite ao usurio navegar na tabela, Delphi 4 Total 159

1997, 1998, 1999 GRIAULE adicionar , editar e excluir registros. A tabela que ser movimentada a tabela cliente. O DBNavigator contm os seguintes botes:

Ativando a Tabela
Voc pode, mesmo sem executar o programa, ativar o componente Table, de forma que ele j inicie o acesso aos dados. Se voc no fizer isso, ter de acrescentar ao programa um comando para abrir a tabela. Para ativar o componente table , clique nele e altere sua propriedade Active para True. Os valores do primeiro registro j aparecem nos controles DBEdit, mesmo sem executar o programa. Nota: Outra forma de ativar a tabela chamando o mtodo Open dentro do programa.

Testando o Programa
Execute o programa e veja qual o resultado. Voc ver inicialmente os dados do primeiro registro includo. Para percorrer os registros existentes, use os botes [next] e botes prximo

anterior [prior]. Voc pode posicionar no incio ou no fim da tabela com os primeiro [first] e ltimo [last], respectivamente.

Para editar valores do registro, basta digitar no controle de dados correspondente. Quando confirmar [post] e cancelar [cancel] ficam habilitados. O voc edita, os botes primeiro permite voc confirmar as edies, salvando o registro. O outro cancela todas as edies e retorna os registros para os valores anteriores. Se voc mover de registro, a edio automaticamente confirmada. Para incluir um novo registro, use o boto branco. Preencha os valores e clique no boto cancelar para cancelar a incluso. Os registros vai aparecer na ordem determinada pelo valor do campo chave, "CodCliente". Para excluir um registro, clique no boto excluir [delete]. O Delphi vai mostrar uma mensagem predefinida de confirmao e voc deve clicar Ok para confirmar a excluso. incluir [insert], que vai abrir um registro em confirmar para salvar o registro, ou

Delphi 4 Total

160

1997, 1998, 1999 GRIAULE Finalmente, o boto atualizar [refresh] s tem utilidade quando h vrios usurios alterando a mesma tabela, como numa rede. O que ele faz trazer para a tela os dados de editar [edit] pode um registro que tenha sido modificado por outro usurio. E o boto ser usado para iniciar a edio de um registro mas geralmente no necessrio. Antes de salvar vamos mudar a propridade Name do formulrio para 'formCadCliente' e a propriedade Caption para 'Cadastro de Cliente' . Salve o projeto como CADCLIENTE e CADCLIENTEP.

Delphi 4 Total

161

1997, 1998, 1999 GRIAULE

Exemplo: Usando o Database Form Wizard


A forma mais rpida de criar um programa que acessa bancos de dados em Delphi utilizando o Database Form Wizard [assistente de formulrio de banco de dados]. Com essa ferramenta, no preciso programao nem mesmo criao de componentes, basta especificar qual a tabela a ser acessada e ele cria um formulrio contendo tudo que preciso. O que feito pelo Database Form Wizard (DFW) o que fizemos manualmente no "Cadastro de Cliente", e voc pode personalizar o formulrio criado da forma que voc quiser. Mas na maioria das vezes, ele facilita o trabalho inicial.

Criando um campo autoincremento


Quando definimos um campo sendo autoincremento, a coluna que foi definida com este tipo tem um nico valor que gerado automaticamente pelo sistema. O contedo desta coluna ,conseguimos obter somente quando o registro for gravado. Outro detalhe que no podemos informar seu contedo durante uma alterao ou incluso de dados. Como exemplo vamos criar a tabela de produto. Para criar uma nova tabela no Database Desktop , no menu File|New|Table... e digite os campos como abaixo: Campo CodProduto Nome QtdEstoque PrecoVenda CodForncedor Tipo Tamanho + A S N S 40 Chave *

No Paradox o que identifica um campo sendo autoincremento o tipo sendo + (AutoIncrement) . Podemos ter somente um coluna com esse tipo na tabela. Note que o campo PrecoVenda vai usar o tipo N (Number). Esse tipo equivale ao tipo double do Object Pascal, isto , permite armazenar nmeros inteiros bem como nmeros com parte fracionria.

Criando um Formulrio para Acessar a Tabela com Form Wizard


Crie um novo projeto no Delphi e depois acione o item de menu Database| Form Wizard.... O DFW dividido em vrias telas de informaes. A primeira tela oferece dois grupos de opes: Delphi 4 Total 162

1997, 1998, 1999 GRIAULE

Mantenha as opes padro: "Create a simple form" em "Form Options" indica que vamos criar um formulrio "simples", que acessa uma nica tabela e "Create a form using TTable objects" em "DataSet Options" indica o tipo de componente de acesso a dados utilizado. Veremos as outras alternativas mais tarde. Clique em "Next". Agora voc deve selecionar a tabela a ser utilizada. Selecione PRODUTO.DB, que foi criada anteriormente e clique em Next. Na prxima tela, voc pode escolher apenas alguns campos ou todos os campos da tabela para utilizar no formulrio. Para selecionar todos os campos, clique no boto [>>] e depois em Next. Voc pode escolher um lay-out para o formulrio. Escolha o padro "Horizontally" (Horizontal) e clique em Next. A ltima tela tem uma opo "Generate a main form" [gerar um formulrio principal]. Se ela estiver marcada, o novo formulrio ser o principal do projeto. Deixe essa opo marcada, e clique no boto "Finish".

Testando o Programa
Note que o formulrio gerado tem vrios componentes j posicionados, incluindo controles de dados para cada campo da tabela. Cada controle de dados responsvel por ler e gravar os dados de um campo. Voc pode alterar a posio e o tamanho do formulrio como quiser. Altere o Caption do formulrio para "Cadastro de Produto" e a propriedade Name para formCadProduto. Note que para alterar uma propriedade do formulrio voc deve selecionar o formulrio. Se um componente estiver selecionado, tecle [Esc] at no aparecer nenhuma indicao de seleo. O que o DFW faz quando cria um novo formulrio o mesmo processo que fizemos para criar o formulrio manualmente.

Delphi 4 Total

163

1997, 1998, 1999 GRIAULE Vamos alterar a propriedade Name do componente table para 'tblProduto', os componentes que tiverem alguma propriedade associada com o componente Table o Delphi automaticamente muda o nome tambm , o nome s no mudado em linhas de cdigo . No componente DataSource colocar o nome sendo 'dsProduto', como o nome do componente Table foi mudado precisamos tambm alterar um trecho de cdigo no formulrio que abre a tabela (no exemplo anterior usamos a propriedade Active). Selecione o formulrio (tecle [Esc] algumas vezes se houver algum componente selecionado) e, no Object Inspector, clique na pgina de eventos. Clique duas vezes no valor do evento OnCreate, e ir aparecer um procedimento de evento contendo:

Table1.Open;
Altere esse comando para:

tblProduto.Open;

Salvando o Projeto
Antes de salvar o projeto, devemos remover o formulrio inicial, que no tem funo nenhuma. Isso preciso porque o Database Form Wizard cria um novo formulrio, mas no altera os anteriores. Clique em Project|Remove from project..., selecione Form1 e clique OK. Agora salve o projeto, dando os nomes de CADPRODUTO e CADPRODUTOP. Execute o projeto e cadastre alguns produtos.

Delphi 4 Total

164

1997, 1998, 1999 GRIAULE

Resumo dos Componentes de Dados


Neste captulo fizemos alguns projetos que utilizam os componentes de acesso a dados e os controles de dados do Delphi. De forma geral, o fluxo dos dados nesse tipo de programa :

Os componentes de acesso a dados, como o componente Table, lem e gravam no banco de dados. O componente DataSource faz a ligao entre estes componentes e os controles de dados, como o DBEdit.

Delphi 4 Total

165

1997, 1998, 1999 GRIAULE

Apelidos de Bancos de Dados


Quando voc desenvolve uma aplicao de banco de dados, voc deve especificar o diretrio onde estaro os seus dados (se for um banco de dados local) atravs da propriedade DatabaseName de um componente Table. Mas com isso o programa fica dependente do local onde esto armazenados os dados. Se voc mover as tabelas para outro diretrio, o programa no vai mais funcionar como antes. Para resolver esse problema, existem os alias do BDE. Um alias, ou apelido, um nome que pode ser usado nos programas em lugar de especificar o diretrio. Num banco de dados cliente/servidor, um alias tambm a forma mais usada para acesso aos dados, porque ele guarda tambm outros parmetros de configurao. Os apelidos so armazenados em um arquivo de configurao do BDE e so globais a todas as aplicaes em Delphi. Voc pode criar ou alterar apelidos usando o utilitrio Database Desktop (DBD), atravs do comando Tools|Alias Manager, mas mais fcil usar um utilitrio que faz parte do prprio Delphi, o Database Explorer. Para isso clique em Database|Explore no menu do Delphi. Voc ver uma tela como a seguinte:

O Database Explorer mostra do lado esquerdo, na pgina "Databases", uma rvore contendo os apelidos que j foram definidos. Ele permite tambm visualizar e alterar os dados de qualquer tabela, atravs de um apelido. Para criar um novo alias, clique em Object|New... Voc deve escolher o tipo de banco de dados que ser usado. Os tipos disponveis dependem de quais drivers esto instalados no computador. No nosso caso, deixe selecionado o tipo STANDARD (acesso a Paradox e dBase), que o padro. Clique Ok e o novo alias aparece na lista, com o nome provisrio de Delphi 4 Total 166

1997, 1998, 1999 GRIAULE "STANDARD1". Digite "CursoDelphi" para o alias. Note que um tringulo aparece esquerda do nome, que indica que esse nome ainda no foi salvo na configurao:

Do lado direito, esto os parmetros de configurao do alias. O nico parmetro que importa no caso o PATH. Clique neste e digite "C:\CURSODF\TABELAS" (o diretrio onde esto os arquivos do curso). Agora clique no boto (Apply) para salvar as alteraes.

Se voc quiser ver as tabelas que esto neste alias, clique no sinal de [+] ao lado do nome para abrir o alias, depois abra o cone "Tables" e voc ver as tabelas definidas. Ao clicar em uma delas, por exemplo, CLIENTE.DB, voc pode visualizar informaes gerais sobre a tabela, ou visualizar e alterar os dados, clicando na pgina "Data":

Delphi 4 Total

167

1997, 1998, 1999 GRIAULE

Note que aparecem botes de controle na parte superior, semelhantes ao DBNavigator. Para fechar a conexo com o alias, clique em CursoDelphi e no boto feche o Database Explorer (ou SQL Explorer) e retorne ao Delphi. (Open Close). Agora

Abra um dos projetos anteriores, como o projeto CADCLIENTeP. No componente Table, primeiro altere a propriedade Active para False. Depois selecione a propriedade DatabaseName, abra a lista de valores e selecione "CursoDelphi" e altere novamente a propriedade Active para True. Faa a mesma alterao para o projeto CADPRODUTOP. A lista de valores na propriedade DatabaseName, sempre mostra quais so os aliases cadastrados. O programa vai mostrar os mesmos dados que antes, mas agora ele no mais dependente do diretrio "C:\CURSODF\TABELAS". Se voc quiser mover os dados para outro lugar, basta alterar o alias novamente, usando o Database Explorer ou o Database Desktop.

Delphi 4 Total

168

1997, 1998, 1999 GRIAULE

Captulo 13 Recursos Adicionais


Definindo Tabelas Criando o Menu Principal Alterando o Formulrio Principal Usando o Controle DBGrid

Delphi 4 Total

169

1997, 1998, 1999 GRIAULE

Definindo Tabelas
Durante o curso, iremos desenvolver um mini-sistema de controle de vendas, no qual teremos um cadastro de clientes, um controle das vendas efetuadas para cada cliente e de itens vendidos para cada venda. Isso vai envolver vrias tabelas adicionais no nosso banco de dados. O modelo abaixo mostra como esto relacionadas as tabelas que sero utilizadas no nosso exemplo:

Volte ao Database Desktop para definir tabelas adicionais e alterar a estrutura da tabela de cliente, criada anteriormente.

Delphi 4 Total

170

1997, 1998, 1999 GRIAULE

Reestruturando a Tabela "Cliente"


Aps criar uma tabela, voc sempre pode alterar a estrutura desta, acrescentando novos campos, removendo campos existentes ou alterando o tipo de um campo. Os dados anteriores so preservados, sempre que possvel, mas obviamente, se voc reduzir o tamanho de um campo, ou mudar seu tipo para uma faixa de valores menor, voc pode perder parte dos dados. Para reestruturar a tabela, use Table|Restructure Table.... A mesma janela com a estrutura dos campos aparece. Vamos adicionar um campo no meio da estrutura, entre Nome e Telefone. Para isso, clique no campo Telefone e pressione [Insert]. Digite "CPF" no nome do campo, "A" para o tipo e 11 para o tamanho. Agora adicione dois campos no final: clique no campo DataNasc, pressione a seta para baixo e digite os novos campos: "Cidade", "A", 25 e "Estado", "A", 2. A estrutura da tabela agora a seguinte: Nome do Campo CodCliente Nome CPF Telefone DataNasc Cidade Estado Tipo S A A A D A A Tamanho (automtico) 40 11 10 (automtico) 20 2 Chave *

Criando um ndice Secundrio


Antes de salvar a tabela modificada, para facilitar as pesquisas e ordenaes por nome, vamos criar um ndice secundrio para o campo Nome. Clique na lista direita, abaixo de "Table Properties", e escolha a opo "Secondary Indexes". Agora o boto "Define..." estar ativo. Clique nesse boto para ver a janela de definio de ndices. Na lista da esquerda esto todos os campos da tabela. Para definir que o campo "Nome" far parte do ndice, selecione-o e clique na seta para a direita. No quadro "Index Options", abaixo da lista de campos, existem opes que voc pode alterar. A opo "Maintained" faz com que o ndice seja mantido automaticamente a cada alterao, que o mais usado. Se estiver desabilitada, o ndice s atualizado quando voc tentar fazer uma pesquisa, o que toma certo tempo. Delphi 4 Total 171

1997, 1998, 1999 GRIAULE A opo "Case sensitive" s tem efeito em campos alfanumricos. Se habilitada, as pesquisas no ndice fazem diferena entre maisculas e minsculas. Agora clique em OK para salvar o ndice. O Database Desktop vai pedir um nome para o ndice. O nome segue as mesmas regras de nomes de campos. Nesse caso, coloque o nome de "IndNome". Mais tarde veremos como utilizar um ndice secundrio no programa. Para salvar a tabela modificada, clique no boto "Save". Se quiser, entre com dados para o campo CPF nos registros. Nota: voc tambm pode criar um ndice que utiliza vrios campos da tabela. Basta adicionar todos os campos utilizados lista da direita.

Criando a Tabela "Venda"


Vamos criar agora a tabela de vendas. Para criar uma nova tabela no DBD, faa como antes, usando File|New|Table... e digite os campos como abaixo: Campo CodVenda CodCliente DataVenda O campo "CodVenda" a chave primria da tabela, que identifica um registro de venda. O campo "CodCliente" est relacionado com um registro da tabela "Cliente", indicando que esta venda se refere quele cliente. Clique em "Save As..." para salvar a tabela e digite o nome "VENDA". Tipo S S Tamanho Chave *

Criando Integridade Referencial


Vamos alterar a estrutura da tabela "Venda". Como o campo "CodCliente" nesta tabela est relacionado com um registro da tabela "Cliente" , no podemos deixar que neste campo seja colocado cdigo do cliente que no exista na tabela "Cliente" e at mesmo ao excluir um cliente no pode ser permitido excluir um cliente que tenha venda , a no ser que exclua as vendas ,para depois excluir o cliente desejado (chamamos este processo de excluso por cascata). Ento na tabela "Venda" vamos alterar sua estrutura criando "Integridade Referencial" na coluna 'CodCliente' com a tabela "Cliente" , para isto clique na lista "Table Properties", escolha a opo "Referential Integrity" e clique no boto "Define...". Selecione o campo "CodCliente" na lista da esquerda, e clique na seta para mov-lo para a direita. Clique em Delphi 4 Total 172

1997, 1998, 1999 GRIAULE OK para salvar o ndice e d o nome de "IntCliente". Iremos criar integridade referencial somente nesta tabela, a ttulo de demonstrao. Notas: Utilizar integridade referencial no Paradox, no muito seguro, pois, ao colocar o programa para funcionar principalmente em rede ocorre problemas do tipo "Arquivo Corrompido" ou "ndice Fora de Data". Com banco de dados Client/Server utilizar a integridade referencial bem mais seguro. No caso do Paradox uma sada seria tratar a integridade pelo Delphi. Clique em "Save ..." para salvar a tabela "VENDA".

Criando a Tabela de Itens


No DBD, use File|New|Table... como antes e defina a seguinte estrutura para a tabela: Campo CodVenda CodProduto Quantidade Tipo S S S Chave * *

Defina tambm um ndice secundrio no campo CodVenda. Isso necessrio para que o Delphi possa tratar o relacionamento mais tarde. Para definir um ndice secundrio, faa como antes: selecione "Secondary Indexes", clique no boto "Define...", selecione o campo CodVenda e clique Ok. D o nome de "IndVenda" para o ndice e clique Ok. Salve a tabela com o boto "Save as...", dando o nome de ITEM.db (lembre-se que a extenso no precisa ser digitada). Depois feche o DBD e retorne ao Delphi. Nota: nomes de tabelas podem ter at 253 caracteres (fora extenso), mas melhor usar um nome com oito ou menos caracteres para manter compatiblidade com programas mais antigos.

Criando a tabela Fornecedores


No DBD, use File|New|Table... como antes e defina a seguinte estrutura para a tabela:

Campo

Tipo

Tamanho

Chave

Delphi 4 Total

173

1997, 1998, 1999 GRIAULE CodFornecedor Nome S A 60 *

Defina tambm um ndice secundrio no campo 'Nome' . Para definir um ndice secundrio, faa como antes: selecione "Secondary Indexes", clique no boto "Define...", selecione o campo 'Nome' e clique Ok. D o nome de "IndNome" para o ndice e clique Ok. Salve a tabela com o boto "Save as...", dando o nome de "FORNECEDOR.DB".

Delphi 4 Total

174

1997, 1998, 1999 GRIAULE

Criando o Menu Principal


Vamos criar um programa onde utilizaremos os formulrios criados anteriormente, alm de alguns novos. Crie um novo projeto no Delphi. O formulrio criado durante a criao do projeto ser o formulrio principal , este formulrio ser a janela a partir da qual o usurio acessa as outras janelas do programa.

O MenuDesigner: criando menus


Para utilizar um menu em um programa, precisamos inserir um componente MainMenu . Aps coloc-lo no formulrio, no formulrio. Ele o primeiro da pgina Standard: clique duas vezes nele para abrir o Menu Designer, que tem uma aparncia como a seguinte:

O Menu Designer mostra uma simulao do menu e permite voc criar os itens de menu que voc vai utilizar. medida que voc criar itens de menu, o Object Inspector vai mostrar as propriedades do item selecionado. Para criar o primeiro item, simplesmente digite "Cadastro" (sem as aspas) e tecle [Enter]. O Menu Designer vai mudar para a seguinte aparncia:

Delphi 4 Total

175

1997, 1998, 1999 GRIAULE

direita e abaixo do item, sempre ficam disponveis retngulos vazios que voc pode preencher para criar novos itens. Se voc no os preencher, eles no vo aparecer no menu final. Agora digite o texto do prximo item: "Cliente" e tecle [Enter]. O marcador vai passar para a prxima linha. Crie mais um item "Produto". Agora crie o item "Fornecedor". Em seguida crie uma barra separadora no prximo item. Para criar uma barra separadora, digite "-" (um sinal de menos). Depois da barra, crie um item "Venda", crie novamente uma barra separadora e finalmente crie mais um item "Sair". A aparncia final vai ficar como na figura:

Quando voc digita o texto do menu, voc est alterando a propriedade Caption de cada item de menu. O Object Inspector automaticamente altera a propriedade Name de cada Delphi 4 Total 176

1997, 1998, 1999 GRIAULE item para ser igual ao valor do Caption, com um nmero acrescentado ao final (por exemplo, Cadastro1). Ns vamos mudar esses nomes para definir um padro mais descritivo. Clique no item "Cadastro" e na propriedade Name, troque "Cadastro1" (o nome que o Delphi colocou automaticamente), por "menuCadastro". Faa de forma semelhante para os outros itens, de acordo com a tabela: Cliente Produto Fornecedor Venda Sair menuCadClientes menuCadProdutos menuCadFornecedores N!(separador) menuCadVendas N2(separador) menuCadSair

Agora clique no item vazio direita do item Arquivo e digite "Editar". Abaixo desse item, crie subitens de acordo com a figura:

A propriedade name altere de acordo com a tabela abaixo: Consultas Delphi 4 Total menuConsulta 177

1997, 1998, 1999 GRIAULE s Cliente por Estado menuconCliEst ado menuConVend asTotais

Vendas por Cliente

Nota: O Menu Designer tem outras facilidades tambm. Para inserir um item de menu no meio, pressione a tecla [Ins]. Para excluir um item de menu, use o [Ctrl+Del]. Para definir um nvel adicional de submenu, use [Ctrl+seta para direita].

Tratando Eventos de Menus


Feche a janela do Menu Designer e retorne ao formulrio "real". O menu vai estar inserido no formulrio, exatamente com a aparncia que foi definida que ele ir aparecer para o usurio, mas no permite modificao. Voc pode clicar nos menus "Arquivo" ou "Editar" para ver os seus subitens. Se voc executar o programa, tambm pode clicar os subitens no vo fazer nada, pois ainda no fizemos nenhum tratamento de eventos. Para tratar eventos em um sub-item de um menu, basta abrir o menu e clicar no sub-item (no formulrio, mas no no Menu Designer). Clique no menu "Cadastro" e depois no item "Sair". O Delphi vai abrir um procedimento de evento para esse item:

procedure TForm1.menuCadSairClick(Sender:TObject); begin end;


Esse item deve terminar o programa quando clicado. Para isso, basta fechar o formulrio, utilizando um comando (na verdade, um mtodo) chamado Close:

Close;
O mtodo Close fecha o formulrio e, como o nico formulrio do programa, ele finaliza a execuo. Execute o programa e clique em Arquivo|Sair. O programa dever finalizar e retornar ao modo de projeto. Acrescente no Menu Designer o item de menu abaixo Crie a seguinte estrutura de menus: Delphi 4 Total 178

1997, 1998, 1999 GRIAULE Relatrio Clientes Vendas por Produto menuRelatorios menuRelClientes menuRelVendasProduto

Teclas de Acesso e Teclas de Atalho


Apesar do Windows geralmente ser mais fcil de usar com o mouse, bom ter em mente que um programa Windows tambm deve ser fcil de usar apenas com o teclado, sem utilizar o mouse. Isso entre outras coisas, envolve uma forma de selecionar menus atravs do teclado. O Windows j fornece automaticamente uma interface padronizada de teclado para os menus. Para verificar isso durante a execuo do programa, pressione a tecla [F10]. Agora voc pode usar as teclas [ ] e [ ] para mudar entre os itens na barra de menu e [Enter] para abrir um menu. Quando o menu est aberto, as teclas [ ] e [ ] so usadas para movimentao entre os itens do menu, [Enter] para acionar o item selecionado, ou [Esc] para fechar o menu aberto. Alm dessa facilidade, voc pode definir uma tecla de acesso para cada menu e cada item dentro de um menu. Uma tecla de acesso aparece como uma letra sublinhada no texto do menu. Para um menu da barra principal, o usurio pode abrir o menu pressionando [Alt+letra], onde letra a tecla de acesso. Quando o menu est aberto, um item do menu pode ser acionado pressionando-se sua tecla de acesso (sem usar [Alt]).

Clique duas vezes no componente (MainMenu) no formulrio para chamar o Menu Designer. Clique no menu "Cadastro" e na propriedade Caption. Para inserir uma tecla de acesso no 'C', digite &Cadastro. Faa de forma semelhante para todos os outros itens (no altere as barras separadoras):

Item &Clientes &Vendas &Produtos &Fornecedores &Sair Delphi 4 Total

Tecla de Acesso &C &V &P &F &S 179

1997, 1998, 1999 GRIAULE C&onsultas Clientes por &Estado &Vendas por Cliente &Relatrio &Clientes &Vendas por Produto &O &E &V &R &C &V

Agora, o item Cadastro|Cliente, por exemplo, pode ser acionado com as teclas [Alt+C,C]. Outra forma de acionar itens de menu atravs de teclas de atalho [shortcut keys]. A diferena que teclas de atalho podem ser usadas mesmo quando o menu no est aberto, esteja onde estiver o foco de teclado, e no precisam ser letras. Se voc abrir um menu do Delphi, ver que teclas de atalho aparecem direita do item, como [Ctrl+S], [F5], [Ctrl+F7] etc. S itens de menu podem ter teclas de atalho (no os menus da barra principal). Ainda no Menu Designer, clique no item "Clientes" e na propriedade Shortcut [atalho]. Selecione da lista a opo "Ctrl+K". Para "Vendas...", coloque "Ctrl+E".Para "Produtos" , coloque "Ctrl+P". Note tambm que o item Sair no tem uma tecla de atalho. Isso porque j existe um atalho definido pelo Windows para sair de um programa qualquer: [Alt+F4]. De forma geral, bom tentar economizar teclas de atalho, e s colocar essas teclas nos itens mais utilizados do programa. Se voc tem muitas teclas de atalho, o usurio no conseguir memoriz-las, e isso desvia do propsito original desse tipo de acesso. Nota:Voc no deve repetir a mesma tecla em um grupo de itens do mesmo nvel. O Delphi permite fazer isso, mas a tecla no vai funcionar da forma esperada. J itens em menus diferentes podem usar a mesma tecla sem problemas. Nota: Teclas de atalho devem ser nicas entre todos os itens de menu. Execute o programa e teste as teclas. Voc no precisa abrir um menu para acionar a tecla correspondente a um item. Note que nos itens separadores, o Delphi coloca momes padro(N1 e N2), que voc no precisa alterar. A propriedade ShortCut fornece um acesso rpido pelo teclado em alguns itens.

Delphi 4 Total

180

1997, 1998, 1999 GRIAULE

Alterando o Menu Principal


Alterando Propriedades
Reduza o tamanho do formulrio na vertical, ou a propriedade Height, de forma que ele no ocupe espao na tela, deixando apenas a barra de menu visvel. Crie um procedimento para o evento OnCreate , e coloque os cdigos abaixo:

left := 0; top := 0;
A barra de menu ir ficar posicionada no topo do DeskTop. Altere o Name do formulrio para 'FormPrincipal'. Num projeto grande, importante dar nomes distintos aos vrios formulrios. Altere sua propriedade Caption para "Controle de Estoque". Salve o projeto e chame a unidade do formulrio principal de VENDPRIN.PAS e o projeto de VENDAS.DPR.

Acrescentando os formulrios anteriores


Neste projeto iremos acrescentar os formulrios criados anteriormente. Para cada um dos fomulrios, voc deve clicar no cone (Add File to Project).

Adicione as unidades CADCLIENTE.PAS e CADPRODUTO.PAS.

Associando os formulrios aos itens de menu


O formulrio principal, que contm os itens de menu, ir chamar cada um dos formulrios criados. Para que ele possa fazer isso, a unidade principal deve ter uma clusula uses, com os nomes de todas as unidades. Fique posicionado na unit "VendPrin" . nessa unidade logo aps a palavra implementation, acrescente:

uses CadCliente, CadProduto;


Agora tecle [F12] para voltar ao formulrio. Clique no item de menu Cadastro|Clientes e, no procedimento de evento, coloque o seguinte comando:

formCadCliente.Show;
Iremos fazer a mesma coisa para o Produto. Clique no item de menu Cadastro|Produto e , no procedimento de evento, coloque : Delphi 4 Total 181

1997, 1998, 1999 GRIAULE

formCadProduto.Show;
Salve o projeto e depois execute o programa.Note que no incio da execuo, aparece apenas o formulrio principal. Ao clicar em um item de menu, por exemplo Cadastro|Clientes, aparece o formulrio correspondente. Voc pode clicar novamente no formulrio principal e abrir outro formulrio. Como os formulrios no so modais, vrios formulrios podem estar na tela ativos simultaneamente.

Delphi 4 Total

182

1997, 1998, 1999 GRIAULE

Usando o Controle DBGrid


Alm de usar os controles de dados, para mostrar um formulrio da forma "tradicional", usando um controle para cada campo, voc pode usar um controle DBGrid, que permite visualizar vrios registros ao mesmo tempo.

Criando os Componentes de Dados


Vamos criar um novo formulrio e utilizar a mesma tabela de clientes, mas com um componente DBGrid. Para criar um formulrio ir no menu File|New Form . Selecione a pgina Data Access e coloque no formulrio um componente Table e um componente DataSource. Defina suas propriedades como antes:

Table Name: tblCliente DatabaseName: CursoDelphi TableName: CLIENTE.DB

DataSource Name: dsCliente DataSet: tblCliente Note que em DatabaseName estamos usando o alias definido anteriormente, "CursoDelphi", que pode ser escolhido na lista de valores. De agora em diante, usaremos esse nome para fazer referncia ao diretrio.

Agora abra a pgina Data Controls e selecione o cone (DBGrid). Coloque o componente no formulrio e altere sua propriedade DataSource para "dsCliente". Agora volte ao componente Table e altere sua propriedade Active para True. A grade de dados j vai mostrar os dados da tabela e voc pode usar as barras de rolagem para ver mais registros. Altere a propriedade Align do DBGrid para "alClient", desta forma o DBGrid ir preencher todo o formulrio. Altere tambm a propriedade Name do formulrio para "formConsClienteEstado".

Manipulando dados no DBGrid


Para verificar o funcionamente do DBGrid , temos que no menu principal chamar o formulrio. Posicione no formulrio da Unit VendPrin , no clique no menu Consultas|Clientes por Estado e coloque o comando a seguir:

procedure TformPrincipal.menuConCliEstadoClick(Sender: TObject);


Delphi 4 Total 183

1997, 1998, 1999 GRIAULE

begin formConsClienteEstado.show; end;


Salvar esta unit como CONSCLIENTEESTADO. Acrescente na unit VendPrin na seo implementation, uma uses para a unit ConsClienteEstado. Ficando desta forma:

uses CadCliente, CadProduto, ConsClienteEstado;


Execute o programa, clique no menu Consultas|Clientes por Estado e verifique o funcionamento do DBGrid, que bem semelhante a uma grade de dados do Database Desktop. Voc pode usar as setas para mover entre campos (linhas) e registros (colunas). Quando voc tenta sair de um campo, se voc digitou um dado invlido, imediatamente ver uma mensagem de erro (por exemplo, no campo DataNasc). Quando voc sai de uma linha, os dados do registro so imediatamente gravados. Para alterar um campo, editando o valor existente, pressione [F2]. Para inserir um registro, voc pode descer abaixo do ltimo registro, ou teclar [Insert]. Para excluir um registro, tecle [Ctrl+Del]. Nota: voc tambm pode alterar caractersticas das colunas se voc clicar duas vezes no prprio DBGrid. Essas alteraes tm prioridade sobre as propriedades dos campos da tabela e voc tem outras opes como, por exemplo, mudar a cor do campo. Mas geralmente no necessrio alterar opes no prprio DBGrid.

Usando o Editor de Campos


Vamos posicionar na unit "CadCliente.pas", caso esteja na unit pressione a tecla [F12] para mostrar o fomulrio.At agora utilizamos os objetos de campos para criar os controles de dados, mas ele tem outras finalidades tambm colocar mscara para a edio de determinados campos. Quando voc utiliza o componente Table, ele cria internamente, para cada campo da tabela, um objeto TField correspondente, que tem propriedades para definir a formatao do campo, tamanho com o qual ele aparece na tela etc. Se voc quiser alterar as propriedades dos campos em tempo de projeto, voc precisa criar uma lista persistente de objetos, e isto feito no editor de campos. A estrutura da tabela "Cliente" foi alterada , foi acrescentado alguns campos que ainda no foram adicionados ao editor de campos. Clique duas vezes no componente 'tblCliente' no formulrio para abrir o editor de campos. Quando a lista de campos est vazia, significa que todos os campos tero as propriedades default. Para adicionar os objetos de campo que esto faltando, clique com o boto direito no fundo e clique em "Add fields...", ser mostrado somente os campos que foram acrescentados a tabela , como todos os campos esto selecionados clique em Ok para adicion-los. Agora quando voc clicar em um dos campos na lista, as propriedades do campo (do objeto TField) aparecem no Object Inspector.

Delphi 4 Total

184

1997, 1998, 1999 GRIAULE No editoe de campos clique em "DataNasc" vamos mudar o formato de data que usado para mostrar as datas. Altere a propriedade DisplayFormat, colocando o valor "dd/mm/yyyy".

Alterando a Mscara de Edio


Cada campo pode ter tambm uma mscara de edio, que define alguns caracteres que aparecem no campo, mas que o usurio no precisa digitar. No nosso caso, vamos colocar uma mscara no campo CPF. No editor de campos, clique no campo CPF. No Object Inspector, clique na propriedade EditMask. Para alterar a mscara de edio, voc pode digitar um valor diretamente para essa propriedade, mas mais fcil usar o editor especializado. Clique duas vezes no valor ou uma vez no boto de reticncias. Na mscara de edio, digite: 999.999.999-99. Cada nove na mscara corresponde a uma posio digitada pelo usurio, que s permite nmeros, mas os outros caracteres sempre aparecero na mscara, e o usurio no precisa digitar. importante tambm desmarcar o quadro "Save literal characters". Se esse quadro estiver marcado, os pontos e traos da mscara sero includos no campo, quando ele for gravado. Se ele ficar desmarcado, s os caracteres digitados sero includos no campo. Note que quando voc altera essa opo, um 0 ou 1 adicionado ao final da mscara. A opo "Character for blanks" define qual o caractere que ser usado nos espaos vazios durante a digitao. Geralmente melhor manter o padro, '_' (sublinhado). Quando voc altera essa opo, o caractere adicionado ao final da mscara. Para testar a mscara, na mesma janela voc pode digitar alguma coisa em Test Input. Se voc digitar e no conseguir sair do campo (o Delphi vai mostrar uma mensagem), tecle [Esc] e tente novamente. Vamos definir uma mscara para edio no campo "DataNasc". Ento no editor de campos, clique no campo "DataNasc". No Object Inspector, clique na propriedade EditMask , em "Sample Masks" clique na opo "date" , esta opo contm uma mscara para data. O contedo de "Input Mask" ser '!99/99/00;1;_', substitua o '0' por '9', a diferena de utilizar 0 ou 9 que quando colocamos '0' fazendo parte da mscara, quer dizer que naquele local o usurio obrigado a informar algum nmero, se utilizar '9' aceita somente nmeros, mas no obirgatrio. importante que a opo "Save literal characters" esteja marcada , pois, as barras so gravadas no campo.

Delphi 4 Total

185

1997, 1998, 1999 GRIAULE

Captulo 14 Validao e Pesquisas


Exemplo: Cliente por Estado Exemplo: Clientes - Alterando Validao de Campos e Registros Tratamento de Excees Pesquisas na Tabela Blocos Protegidos Usando Outros Controles de Dados

Delphi 4 Total

186

1997, 1998, 1999 GRIAULE

Exemplo: Cliente por Estado


Iremos realizar algumas alteraes no formulrio "formConsClienteEstado", portanto , abra este formulrio.Atualmente este formulrio mostra todos os clientes cadastrados, vamos realizar uma procura onde iremos mostrar os Clientes por um determinado Estado escolhido pelo usurio. Altere a propriedade Caption para 'Cliente por Estado' e modifique tambm a propriedade Align do DBGrid para 'alBottom' e aumente o tamanho do fomulrio para acrescentar um Componente GroupBox( "Parmetros", como na figura abaixo: ) . Altere sua propriedade Caption para

Altere o nome do controle de edio para 'editEstado'e sua propriedade CharCase para 'ecUpperCase', deixe a propriedade Text vazia. Isso faz com que todas as letras digitadas sejam convertidas em maisculas. Chame o boto de 'btnProcurar' e mude sua propriedade Default para True. No evento OnClick do boto 'btnProcurar', vamos alterar a propriedade Filter do componente Table dinamicamente,com esta propriedade iremos definir um filtro que ir procurar os clientes que pertencem ao estado indicado.Digite o seguinte:

tblCliente.Filter := 'Estado = ''' + editEstado.text + tblCliente.Filtered := true; tblCliente.Open;

'''';

Note que para modificar a propriedade Filter, usamos vrios apstrofos na sintaxe. Cada dois apstrofos na string representam um apstrofo na string resultante. Por exemplo, se editEstado = 'GO' a string do Filter vai conter : Delphi 4 Total 187

1997, 1998, 1999 GRIAULE

Estado = 'GO'
Mas a propriedade Filter funciona somente se a propriedade Filtered for True.Aps a alterao da propriedade necessrio abrir o componente Table novamente para ver o resultado. Salve o formulrio e execute. Para testar informe alguns estados e clique no boto 'Procurar'. Notas: O paradox "case sensitive", portanto ele faz diferenciao entre letras maisculas e minsculas. Exceo somente quando cria um ndice secundrio para o campo e a opo "case sensitive" deve estar desmarcada.

Delphi 4 Total

188

1997, 1998, 1999 GRIAULE

Exemplo: Clientes - Alterando


Neste captulo, faremos vrias alteraes no formulrio "formCadCliente". Portanto, abra esse projeto. Note que ainda faltam no formulrio controles de dados para os novos campos que foram acrescentados por ltimo: CPF, Cidade e Estado. Os objetos foram criados , falta criar os controles de dados.

Clique duas vezes em 'tblCliente' (o nico componente Table do formulrio) para abrir o editor de campos. Agora arraste, um de cada vez, os campos CPF, Cidade e Estado para o formulrio. Deixe o formulrio com a aparncia semelhante a figura abaixo:

Mantenha o editor de campos aberto.

Delphi 4 Total

189

1997, 1998, 1999 GRIAULE

Validao de Campos e Registros


Uma mscara de edio proporciona uma forma automtica de validao de campos, mas voc pode tambm adicionar seu prprio cdigo de validao, executado pelo Delphi quando for necessrio. Existem duas formas de validao: Validao de Campo: feita logo quando o usurio alterna para outro campo, no mesmo registro ou em outro. Se a validao falha, o usurio no consegue mudar de campo. Validao de Registro: feita apenas quando o usurio muda de registro, e se a validao falha, o usurio no pode mudar de registro. Pode ser usada para fazer uma verificao que envolva mais de um campo.

Validando Campos
Para fazer a validao de campo, voc deve tratar o evento OnValidate. Esse um evento do componente TField associado ao campo. Vamos adicionar uma validao ao campo CPF. Para este projeto foi criado uma unit independente chamada GeralVenda que contm uma funo para fazer a verificao do CPF, a idia no explicar como funciona a verificao de CPF , mas de como fazer esse tipo de verificao no Delphi, segue tambm nesta unit uma rotina para verificao de CGC.Ento iremos utiliz-la para verificar se um determinado CPF foi informado corretamente.O nome da funo ValidaCPF ela retorna true se o CPF estiver correto, temos que passar como parmetro um valor do tipo 'String'. Notas:Para verificar se um cpf vlido ou no, primeiro certifique que ele tenha 11 dgitos. Os dois ltimos dgitos so utilizados para verificao. Declare algumas variveis:

var soma, somaDig, pos, resto : smallint;


A constante ordZero contm a posio do nmero 0 na tabela Ascii. A verificao do penltimo dgito feita atravs da soma dos dgitos at a posio , cada dgito necessrio multiplicar por 11 e subtrair pela sua posio, necessrio tambm ter a soma de todos os dgitos at a posio 9..

for pos := 1 to 9 do begin soma := soma + (ord(textoCPF[pos]) - ordZero) * (11 - pos); somaDig := SomaDig + (ord(textoCPF[pos]) - ordZero); end;

Delphi 4 Total

190

1997, 1998, 1999 GRIAULE Verificao do Penltimo Dgito: Divida o contedo da varivel soma por 11,faa a subtrao do resto pelo nmero 11 e atribua a uma varivel, se o contedo desta varivel for maior que 9, altere o contedo da variavel para 0, em seguida verifique se o contedo desta varivel diferente do penltimo digito do CPF, se for CPF invlido, caso contrrio necessrio verificar o ltimo dgito.

resto := 11 - soma mod 11; if resto > 9 then resto := 0; if resto <> ord(textoCPF[10] - ordZero then exit; {DV errado}
Para verificar o ltimo dgito nessrio somar os resultados encontrados nos calculos anteriores. Ento Soma + SomaDig + 2 * resto , dividir este resultado por 11, o resto subtrair por 11 , se o resultado obtido for maior que 9 , atribuir 0 a esse resultado, em seguida verificar se o resultado encontrado igual ao ltimo dgito verificador , se for igual CPF Vlido.

soma := soma + somaDig + 2 * resto; resto := 11 - soma mod 11; if resto > 9 then resto := 0; if resto <> ord(textoCPF[11]) - ordZero then exit; { segundo DV errado } Result := True; { tudo certo }
No formulrio "formCadCliente" abra o editor de campos para tblCliente e clique no campo CPF na lista. No Object Inspector, abra a pgina de eventos e crie um procedimento de evento para OnValidate. Neste procedimento de eventos, adicione o seguinte:

begin if not ValidaCPF(tblClienteCpf.value) then begin ShowMessage('CPF Invlido!'); Abort; end; end;
A funo ValidaCPF verifica se o CPF esta correto.Caso esteja errado, o procedimento mostra uma mensagem, com ShowMessage e gera uma exceo com o procedimento Abort. Qualquer exceo gerada faz com que o Delphi cancele a movimentao de campo ou de registro, mas melhor usar Abort porque ele gera uma exceo silenciosa, da classe Delphi 4 Total 191

1997, 1998, 1999 GRIAULE EAbort, que no mostra nenhuma mensagem de erro alm das mensagens do seu programa. Antes de executar o programa na seo Implementation da Unit CADCLIENTE acrescente uma clausula uses para a unit independente:

uses GeralVenda;
Para adicionar a Unit ao projeto , no menu Project|Add to Project ( unit "GERALVENDAS.PAS" em seguida clique no boto "Abrir". ), escolha a

Execute o programa e veja o que acontece. Altere um registro existente, digitando um valor para o CPF, Invlido e tecle [Tab] para tentar mudar de campo. Voc deve digitar um valor vlido ou teclar [Esc] para retornar ao valor anterior do campo. importante notar que a validao de campo s acontece quando o usurio edita o campo. Um registro j existente, que tenha um valor invlido, no passar pela validao a no ser que o usurio altere o valor do campo CPF. Nota: Quando vrios controles esto associados ao mesmo campo, as alteraes de propriedade afetam todos eles.

Validando Registros
Para fazer uma validao de registro, voc pode utilizar o evento BeforePost do componente Table. Esse evento executado logo antes do registro ser gravado, seja um novo registro ou um registro j existente. Essa gravao pode ocorrer quando o usurio clica no boto alterado. do DBNavigator ou quando ele muda de registro, se o registro foi

Selecione o componente 'tblCliente', e na pgina de eventos, clique duas vezes no valor de BeforePost. Neste evento vamos fazer o seguinte:

begin if tblClienteNome.IsNull then begin ShowMessage('O nome obrigatrio'); tblClienteNome.FocusControl; Abort; end; if tblClienteCidade.IsNull then begin ShowMessage('A cidade obrigatrio'); tblClienteCidade.FocusControl; Abort;
Delphi 4 Total 192

1997, 1998, 1999 GRIAULE

end; end;
A propriedade IsNull de um componente TField retorna True se ele tem um valor nulo, isto , vazio, no informado. Se o campo estiver vazio, o procedimento mostra uma mensagem e chama o mtodo FocusControl do componente. Esse mtodo coloca o foco no controle de dados associado (com isso no preciso saber o nome do controle DBEdit ligado ao campo). Depois de fazer isso, o procedimento chama Abort para cancelar a gravao do registro. Com a validao de registro, o usurio s tem duas opes: ou digitar valores vlidos, do DBNavigator. Execute o programa e ou cancelar a edio do campo, com o boto note que agora essa validao tambm feita se voc incluir um registro e tentar grav-lo. Salve e execute o programa. Para testar crie um novo cliente , no informe seu nome , mas coloque o nome da cidade onde ele mora, ao salvar o cliente , o cliente no ser salvo enquanto no informar o seu nome. Notas: A verificao se um campo ou no obrigatrio pode ser no banco de dados e no Delphi podemos fazer a verificao atravs de erros.Veremos nos prximos captulos.

Delphi 4 Total

193

1997, 1998, 1999 GRIAULE

Tratamento de Excees
Desmarque a opo " Stop on Delphi Exceptions" no menu Tools | Debugger Options | Language Exceptions. Mas tarde iremos entender o motivo. Observe que ao digitar uma data invlida , ocorre a seguinte mensagem:

Esta mensagem que aparece um erro de execuo, ou seja, uma mensagem do Delphi avisando de uma condio de erro.O termo usado no Delphi para essas situaes exceo.Uma exceo[exception] uma condio anormal que ocorre durante a execuo do programa, que interrompe o seu funcionamento. Quando ocorre uma exceo, o Delphi mostra uma mensagem padro e termina a execuo do procedimento de evento atual, mas continua a responder a eventos e executar o programa.Para qualquer exceo, voc pode fazer seu prprio tratamento, interceptando o tratamento do Delphi. Para tratar essa exceo voc tem que utilizar um evento que ocorra antes da mensagem de erro. Como o componente est associado a um objeto de campo , podemos fazer este tratamento nos eventos do objeto de campo. Clique duas vezes no componente tblCliente ( ) para abrir o editor de campos. Clique no campo "DataNasc" e crie um procedimento para o evento OnSetText . Esse evento executado todas as vezes que alterado o contedo do objeto de campo. Neste procedimento o parmetro "Text" contm o valor da data informada. Coloque o cdigo a abaixo:

var Data : TDateTime; begin try data := strtodate(text); tblClienteDataNasc.asDatetime := data; except on EConvertError do begin showmessage('Data Invlida!'); abort;
Delphi 4 Total 194

1997, 1998, 1999 GRIAULE

end; end; end;


O comando try (tentar) um comando de tratamento de excees. Os comandos entre o try e o except so executados, mas se ocorre alguma exceo nesse bloco, o Delphi sai do bloco e entra na parte except[exceto]. Ento o Delphi procura uma clusula on correspondente classe da exceo gerada. Se ele encontra um on correspondente, ele executa o comando de tratamento associado. Depois de executar o tratador, o Delphi no termina a execuo do procedimento de evento, mas continua a execuo com o prximo comando depois do end do try. A funo strtodate converte uma varivel do tipo string para data, caso ocorra algum erro gera uma exceo da classe 'EConvertError', se ocorrer a exceo mostramos a mensagem 'Data Invlida' , em seguida o comando abort executado ,es este comando cancela o procedimento, se ele no for colocado a mensagem do Delphi ir continuar aparecendo. Quando colocamos algum procedimento para este evento , ao sair do procedimento a data informada no ser colocada no objeto de campo, por isso que atribuimos o valor da data ao objeto 'tblClienteDataNasc'.

Visualizando Informaes sobre Excees


Se a opo " Stop on Delphi Exceptions" estiver marcada , o Delphi mostra uma mensagem mais detalhada sobre cada exceo e mostra exatamente qual a linha que causou a exceo. Para verificar esta opo no menu Tools | Debugger Options | Language Exceptions e marque a opo " Stop on Delphi Exceptions". Agora execute o programa e provoque uma exceo, cadastrando um data invlida para a data de nascimento'. Nesse caso a mensagem ser:

ou seja , o projeto causou uma exceo da classe 'EConvertError'. O nome da classe de exceo uma informao importante quando voc fizer o tratamento da exceo no programa. Para continuar a execuo, tecle[F9] ou clique no boto (Run). Depois ir aparecer a mensagem que colocamos ( caso no tenha tratado a exceo aparece a mensagem do Delphi).

Delphi 4 Total

195

1997, 1998, 1999 GRIAULE

Classes de Excees
Quando voc faz o tratamento de excees, pode trat-las a nvel especfico de cada exceo ou voc pode tratar uma classe de exceo mais geral. As classes fazem parte de uma hierarquia de excees, como a seguinte: Exception (qualquer exceo) EIntError (erros de nmeros inteiros) EDivByZero (diviso por zero de inteiro) EIntOverflow (transbordo inteiro) ERangeError (valor ou ind. vetor fora de faixa) EMathError (erros de matemtica real) EOverflow (transbordo de real) EUnderflow (valor muito peq. de real) EZeroDivide (diviso por zero de real) Se voc criar uma clusula de tratamento para uma exceo mais geral, como 'EMathError', ela ser acionada para qualquer uma das classes abaixo na hierarquia, seja diviso por zero (EZeroDivide), transbordo de valor (EOverflow) ou qualquer outra. A classe Exception o nvel mais geral de tratamento e intercepta qualquer exceo. Se num conjunto de tratadores, voc colocar um tratador primeiro para uma exceo mais geral e depois para uma exceo especfica, o tratador mais especfico nem vai chegar a ser executado. Notas: O tratamento de exceo pode ser feito em qualquer procedimento que julgar necessrio.

Delphi 4 Total

196

1997, 1998, 1999 GRIAULE

Pesquisas na Tabela
Uma caracterstica fundamental de um programa permitir que o usurio faa uma pesquisa em uma tabela, fornecendo o valor a ser pesquisado. Na tabela de clientes, vamos facilitar a pesquisa pelo nome do cliente.

Adicionando um DBGrid
Para isso vamos adicionar ao formulrio um controle DBGrid, que vai mostrar toda a lista de clientes, permitindo selecionar qualquer um deles. Abra um espao adicional direita do formulrio e acrescente um componente Label, com o texto "Procura:" e um componente Edit (no use um DBEdit), com o nome de "editProcura". Abaixo deles acrescente um componente DBGrid (cone ficar como o seguinte: da pgina Data Controls). O formulrio deve

Agora associe a grade (DBGrid) com a tabela, alterando sua propriedade DataSource para 'dsCliente'. Com isso, se a tabela estiver ativa, ele vai automaticamente mostrar todos os campos e todos os registros da tabela. No vamos permitir que o usurio altere os dados usando o grid. Para isso basta mudar a sua propriedade ReadOnly para True. Vamos restringir os campos mostrados apenas ao campo "Nome". Para isso, clique duas vezes em 'tblCliente' para abrir o editor de campos, selecione todos os campos menos Nome e altere a propriedade Visible para False. Se preciso, reduza o DisplayWidth para que o valor do campo aparea todo no Grid.

Delphi 4 Total

197

1997, 1998, 1999 GRIAULE Algumas caractersticas de visualizao do DBGrid no so necessrias aqui, como as linhas divisrias de registros e campos, ou os ttulos da parte de cima. Vamos desativar essas caractersticas, alterando a propriedade Options. Expanda essa propriedade no Object Inspector e altere as seguintes opes: Opo dgEditing dgTitles dgIndicator dgColLines dgRowLines dgTabs dgAlwaysShowSelection Valor False False False False False False True Finalidade no permite incluir ou excluir desativa os ttulos desativa o indicador de registro desativa as linhas verticais desativa as linhas horizontais no usa [Tab] para mudar de campo sempre mostra a linha selecionada

Se a opo 'dgAlwaysShowSelection' estiver desativada, o grid s mostra qual a linha selecionada (a do registro atual) quando ele tem o foco de teclado. Ns devemos ativ-la para que o usurio saiba qual o nome selecionado na lista a qualquer momento. Execute o programa e verifique. Voc pode clicar na grade a qualquer momento para selecionar um dos registros, ou usar o DBNavigator para percorrer os registros. Nota: existem duas opes parecidas: dgAlwaysShowEditor e dgAlwaysShowSelection. Para visualizar melhor as opes, aumente a largura do Object Inspector.

Utilizando um ndice Secundrio


Mas h um problema: a grade mostra os dados ordenados pelo ndice principal da tabela, que no caso o ndice no campo CodCliente. Para facilitar a pesquisa, eles deveriam estar ordenados por nome. Para mudar a ordem dos registros, podemos usar um ndice diferente. Para ordenar por nome, que o necessrio, precisamos usar o ndice criado para o campo Nome. Para isso, basta alterar a propriedade IndexName do componente Table. Se ela estiver vazia, a ordem dos registros ser determinada pelo ndice primrio da tabela. Se voc colocar o nome de um ndice secundrio, a ordem ser de acordo com esse ndice. Essa propriedade afeta tanto a ordem virtual dos registros, quanto as pesquisas que voc fizer, como veremos.

Delphi 4 Total

198

1997, 1998, 1999 GRIAULE Clique na propriedade IndexName e selecione o nome "IndNome" da lista. Esse o nome do ndice secundrio criado. Note como a ordem dos registros alterada no controle DBGrid. Se voc apagar o valor de IndexName, a ordem volta a ser a do campo CodCliente. Alm da propriedade IndexName, existe outra chamada IndexFieldNames, que tem a mesma funo. O valor desta propriedade a lista dos campos que compem o ndice. Por exemplo, voc poderia colocar "Nome" em IndexFieldNames e teria o mesmo efeito. Isto til se voc no souber o nome do ndice, mas se souber quais os campos que fazem parte dele. As duas propriedades so mutuamente exclusivas: se voc altera uma, a outra ter seu valor eliminado.

Pesquisando pelo Nome


Os controles acima do DBGrid sero usados para permitir pesquisa na tabela pelo nome do cliente. A cada digitao do usurio, vamos posicionar a tabela no nome mais prximo. Para isso, vamos usar o mtodo FindNearest do componente Table. Esse mtodo procura um valor na tabela utilizando o ndice atual. Se o valor no for encontrado exatamente, ele posiciona no registro mais prximo. Selecione o controle 'editProcura' e crie um procedimento para o evento OnChange. Esse evento executado toda vez que o usurio altera o valor do controle, digitando ou apagando caracteres. No procedimento basta colocar o seguinte:

begin tblCliente.FindNearest([editProcura.Text]); end;


Execute e verifique o resultado. Quando voc digita um nome em 'editProcura', o valor mais prximo selecionado. Isso chamado de busca incremental. Nota: se o ndice tiver mais de um campo, coloque em IndexFieldNames os nomes de campos separados por ponto-e-vrgula ";", sem espaos. Nota: quando voc clica num cone da paleta de componentes e depois em cima de um componente, aquele que voc criou fica contido no primeiro, isto , restrito rea do componente e os dois so movimentados em conjunto.

Pesquisando pelo Cdigo


Agora vamos dar ao usurio a opo de procurar um registro pelo valor do campo cdigo, que tambm tem um ndice definido (o ndice primrio da tabela). Para isso, abra um espao na parte inferior do formulrio. Vamos colocar nesse espao um componente GroupBox, que usado para agrupar visualmente outros componentes. Delphi 4 Total 199

1997, 1998, 1999 GRIAULE

do GroupBox na pgina standard e coloque-o no formulrio. Coloque Selecione o cone na sua propriedade Caption o texto "Procura por cdigo". Dentro do componente GroupBox, crie um label, um quadro de edio e um boto, como na figura abaixo:

Mude o Caption do label para "Cdigo:". Mude o Name do componente Edit para 'editProcCodigo' , a propriedade Text deixe vazia e o nome do boto para 'btnProcCodigo' e altere a propriedade caption para "Procurar". Agora clique duas vezes no boto Procurar. Neste procedimento, vamos usar o valor digitado para pesquisar na tabela, usando o mtodo FindKey. Como vamos pesquisar por um campo diferente, devemos alterar a propriedade IndexName do componente dinamicamente, e depois retorn-la ao original. Isso gera um pequeno problema ao alterar essa propriedade, os controles do formulrio vo mudar para refletir o novo ndice. Isso pode ser evitado com o mtodo DisableControls do componente Table. Quando ele chamado, os controles de dados no atualizam mais seus valores at que o mtodo EnableControls seja chamado. Com isso, coloque o seguinte no cdigo do procedimento:

var codigo: integer; begin codigo := StrToInt(editProcCodigo.Text); with tblCliente do try DisableControls; IndexName := ''; {usando ndice primrio} if not FindKey([codigo]) then ShowMessage('Codigo no encontrado'); finally IndexName := 'IndNome'; {usando ndice por Nome} EnableControls; end; end;
O mtodo FindKey uma funo que retorna True se encontrou o registro. Caso ele encontre, ele posiciona no registro, seno mantm posicionado no registro atual.

Delphi 4 Total

200

1997, 1998, 1999 GRIAULE

Blocos Protegidos
Os tratamentos de erros no Delphi podem ser feitos para uma exceo especfica. As vezes , no necessrio tratar um exceo especfica , mas preciso realizar uma ao de finalizao, O finally utilizado quando uma determinada exceo ocorre , e necessitamos executar de qualquer forma um determinado comando ou vrios comandos antes de interromper o procedimento. Esses comandos devem ser colocados no trecho finally..end. Em geral , blocos protegidos podem ser usados em qualquer situao que envolva uma alocao e liberao de recursos(como um arquivo , por exemplo). No procedimento de evento do OnClick observe que a alterao de IndexName e a chamada de EnableControls so feitas no bloco finally. Isso significa que mesmo que acontea uma exceo, esses comandos so executados. Isso importante, pois se esse tipo de tratamento no for feito, os controles de dados podem ficar num estado desabilitado, e o usurio no conseguiria mais utilizar o programa. Execute e verifique o resultado. Se voc digitar um cdigo e clicar no boto Procurar, o programa vai tentar procurar o registro.

Delphi 4 Total

201

1997, 1998, 1999 GRIAULE

Usando Outros Controles de Dados


Alm dos controles DBEdit e DBGrid, que j utilizamos, a pgina Data Controls contm vrios outros que so teis nos programas.

Usando o DBComboBox
Os controles DBListBox ( ) e DBComboBox ( ) so equivalentes, respectivamente,

aos controles padro ListBox ( ) e ComboBox ( ), da pgina Standard. Ambos mostram uma lista de nomes (definida pela propriedade Items) e permitem que o usurio escolha um dos itens da lista. Os controles ComboBox e DBComboBox mostram a lista fechada, com um boto de seta que permite o usurio selecionar um valor, enquanto que ListBox e DBListBox mostram a lista sempre aberta. Os controles da pgina Data Controls, alm da mesma funo que seus equivalentes na pgina Standard, ainda tm a capacidade de ler e gravar um valor no banco de dados. O campo Estado da tabela pode utilizar uma lista de valores, com os nomes de estados possveis. Para isso, vamos utilizar um controle DBComboBox. Apague o controle DBEdit relacionado ao Estado e substitua por um DBComboBox ( anterior. ), na mesma posio do

A propriedade Style de uma combo box determina se ela permite digitao de um valor que no est na lista. O valor padro 'csDropDown', que permite digitar, alm de escolher da lista. O valor 'csDropDownList' probe digitao o usurio s pode escolher um valor da lista. Altere para 'csDropDownList. Associe o controle com o campo da tabela: em DataSource, selecione 'dsCliente' e em DataField selecione "Estado". Agora vamos preencher a lista dos valores possveis da combo box. Para isso, clique na propriedade Items e abra o seu editor. Agora, em cada linha, digite uma sigla de estado (para simplificar, digite apenas as que estiverem presentes nos seus dados de teste). No preciso se preocupar com a ordem alfabtica: AM, PA, RR, RO, AC, GO, TO, MT, MS, SE, SP, RJ, MG, ES, BA, AL, MA, CE, PI, RS, SC,DF. Para colocar todos os itens da lista em ordem alfabtica, altere a propriedade Sorted para True. Execute o programa e veja a diferena. Agora o usurio, ao invs de digitar a sigla do estado, pode selecionar a partir da lista. Para usar a combo box pelo teclado, sem usar o mouse, use as setas [ ] e [ ] para se movimentar pelos itens, ou digite [Alt+ ] ou [Alt+ ] Delphi 4 Total 202

1997, 1998, 1999 GRIAULE para abrir ou fechar a lista. Quando a lista est aberta, use as setas para escolher um item e tecle [Enter] para selecionar, ou [Esc] para fechar a lista. Se voc teclar uma letra, a combo box seleciona o primeiro item que comea com essa letra e, se voc continuar repetindo a tecla, seleciona os prximos. Em alguns casos, a lista de valores no fixa no programa, mas deve ser criada dinamicamente. Nesse caso, preencha a propriedade Items em tempo de execuo, usando o mtodo Add:

cboEstado.Items.Add(sigla);
Nota: quando os dados vm de outra tabela, existe uma forma mais fcil, que utilizar o controle DBLookupComboBox ( ), como veremos mais tarde.

Delphi 4 Total

203

1997, 1998, 1999 GRIAULE

Captulo 15 Acesso s/ Controle de Dados


Estados de uma Tabela Mtodos para Percorrer Dados Mtodos para Modificar Dados Eventos dos Componentes de Dados Manipulao de Datas Exemplo: Criando Formulrio sem Utilizar o dbNavigator Tratamento do Erro "Key Violation" Usando um Controle DBLookupComboBox

Delphi 4 Total

204

1997, 1998, 1999 GRIAULE

Estados de uma Tabela


Dependendo da situao, um componente Table pode estar em vrios estados diferentes. preciso entender estes diferentes estados para poder utiliz-lo. A propriedade State (acessvel somente em tempo de execuo) tem valores diferentes dependendo do estado. Os principais so: Inativo (dsInactive): a tabela est fechada. A propriedade Active True. Visualizao (dsBrowse): a tabela est aberta, e o usurio est visualizando ou percorrendo registros. Inserindo (dsInsert): foi iniciada a incluso de um novo registro, mas esse registro ainda no foi salvo no banco de dados. O componente entra nesse estado quando o usurio clica no boto do DBNavigator.

Editando (dsEdit): foi iniciada a edio de um registro existente, mas o registro ainda no foi salvo. O componente entra nesse estado quando o usurio comea a alterar um campo. Quando a propriedade AutoEdit do componente DataSource False (o padro True), o usurio deve iniciar a edio explicitamente, clicando no boto do DBNavigator.

Quando a tabela est no estado inativo, voc no pode acessar os dados. Quando ela est no estado de visualizao (dsBrowse), voc pode percorrer os registros da tabela e ler os valores de campos, utilizando os componentes TField, mas voc no pode alterar os valores de campos. Para alterar os valores dos campos de um registro, voc deve colocar a tabela em estado de edio (dsEdit) e depois alterar o valor dos componentes TField. Depois voc deve salvar os dados, retornando ao estado de visualizao. Quando voc inicia a incluso de um registro, todos os componentes TField ficam com o valor em branco (nulo), e voc pode atribuir valores para eles. Depois que voc salva o registro, a tabela retorna ao estado de visualizao.

Delphi 4 Total

205

1997, 1998, 1999 GRIAULE

Mtodos para Percorrer Dados


O componente Table tem vrios mtodos que permitem voc acessar a tabela utilizada, independemente dos controles de dados. Se o componente Table estiver ligado a um componente DataSource, que utiliza controles de dados, o resultado dos mtodos vai aparecer na tela.

Mtodos de Abertura e Fechamento


Para abrir a tabela e poder acessar os seus dados, primeiro defina as propriedades DatabaseName e TableName do componente Table, seja em tempo de projeto ou no cdigo do programa. Depois utilize o mtodo Open, por exemplo:

tblCliente.Open;
Aps terminar de utilizar a tabela, voc pode usar o mtodo Close para liberar a tabela e o componente Table para outros usos.

tblCliente.Close;
O mtodo Open equivale a alterar a propriedade Active para True. O mtodo Close equivale a alterar a propriedade Active para False.

Mtodos para Percorrer Registros


Os seguintes mtodos podem ser usados para percorrer registros: Boto Mtodo First Prior Next Last Descrio Posiciona no primeiro registro. Volta para o registro anterior. Avana para o prximo registro. Posiciona no ltimo registro. Avana 'n' registros. Se 'n' for positivo, move para frente. Se 'n' for negativo, move para trs.

N/A

MoveBy ( n )

Repare que cada um deles, exceto MoveBy, equivalente a um boto correspondente do controle DBNavigator. Na verdade, o DBNavigator apenas chama os mtodos correspondentes do componente Table, em resposta ao clique do usurio. Delphi 4 Total 206

1997, 1998, 1999 GRIAULE Lembre-se que a ordem em que os registros aparecem quando voc percorre seqencialmente a ordem determinada pelo ndice que estiver sendo utilizado no momento. Quando a tabela aberta, o ndice utilizado o ndice primrio, mas isso pode ser alterado. Para ler os campos do registro atual, existem duas formas. Se voc usou o editor de campos para criar uma lista de componentes TField, cada um deles tem um nome, que formado pelo nome do componente Table, mais o nome do campo. Com isso, basta acessar a propriedade Value do componente TField:

preco := tblItemPrecoVenda.Value; quant := tblItemQuantidade.Value;


Mas se voc no criou uma lista de campos, os componentes TField so criados internamente e no tm nome, mas ainda podem ser acessados com o mtodo FieldByName:

preco := tblItem.FieldByName('PrecoVenda').AsFloat; quant := tblItem.FieldByName('Quantidade').AsInteger;


As propriedades AsFloat e AsInteger so necessrias nesse caso, para especificar qual o tipo de dados que voc est acessando. No caso de um componente criado explicitamente, o Delphi j sabe o tipo de campo pela declarao, ento voc pode usar Value, que tem o mesmo tipo de dados do campo. Da mesma forma, existem outras propriedades "As*", como AsString, AsDate, que retornam o valor do campo convertido para um determinado tipo de dados. Voc no pode atribuir valores para a propriedade Value ou As* do componente se voc estiver em modo de percorrer registros. Quando voc est percorrendo a tabela, existem duas propriedades teis, ambas do tipo boolean. A propriedade EOF verdadeira quando voc estiver posicionado no fim da tabela, depois do ltimo registro. J BOF verdadeira quando voc estiver posicionado no incio da tabela. Por exemplo, para percorrer a tabela do incio ao fim.

with tblItem do begin First; { vai para o primeiro registro } while not EOF do begin preco := tblItemPrecoVenda.Value; quant := tblItemQuantidade.Value; ... Next; { vai para o prximo registro } end; end;
Delphi 4 Total 207

1997, 1998, 1999 GRIAULE Se ambas forem verdadeiras, a tabela est vazia, no tem nenhum registro:

if tblItem.BOF and tblItem.EOF then ShowMessage('A tabela est vazia');

Exemplo: Percorrendo a Tabela de Itens


Crie um novo projeto no Delphi, no qual vamos percorrer a tabela de itens (ITEM.DB) atravs de comandos de programa, usando os mtodos do componente Table. Esse programa vai percorrer toda a tabela e totalizar a quantidade de itens vendiddos. Altere a propriedade Caption do formulrio para 'Totalizar Itens'.

Coloque no formulrio um componente Table ( ) e defina as seguintes propriedades: Name ser 'tblItem', DatabaseName ser 'CursoDelphi', o alias que diz onde esto os dados e TableName ser 'ITEM.DB'. Crie controles no formulrio como na figura:

Coloque um label, com o texto "Total:" e um controle de edio, com o nome 'editTotal', que ir mostrar o resultado final. Finalmente coloque um boto, com o texto 'Totalizar' e nome 'btnTotalizar'. Clique duas vezes no 'tblItem' para abrir o editor de campos. Acrescente todos os campos lista. Repare que se voc clicar em um nome de campo, por exemplo 'Quantidade', voc ver que a propriedade Name do objeto de campo tblItemQuantidade. Esse o nome que voc deve utilizar no programa para acessar o valor do campo. Clique duas vezes no boto Totalizar e digite o seguinte:

var total: double; begin total := 0; with tblItem do begin Open; First; while not EOF do begin total := total + tblItemQuantidade.Value ; Next; end; Close;
Delphi 4 Total 208

1997, 1998, 1999 GRIAULE

end; editTotal.Text := FloatToStr(total); end;


Dentro do with, a primeira linha chama o mtodo Open para abrir a tabela. Isso no seria necessrio se a propriedade Active j tivesse o valor True no incio da execuo. Depois First posiciona no primeiro registro. Essa chamada no realmente necessria, porque logo depois de abrir a tabela, o registro atual j o primeiro. O lao while verifica o valor da propriedade EOF. Enquanto ela for falsa (not EOF), o lao percorre os registros. Para cada registro, o campo Quantidade somado com varivel 'total'. Note a forma de acesso aos campos: com os nomes dos objetos TField, usando sua propriedade Value. Depois de somar o valor, o mtodo Next muda para o prximo registro. Depois do lao, o mtodo Close fecha a tabela (faz Active = False), e finalmente o resultado final, acumulado em 'total', mostrado no controle 'editTotal'. Execute o programa e clique no boto Totalizar para ver o resultado. Salve o projeto como TOTALITEM.PAS E TOTALITEMP.DPR.

Delphi 4 Total

209

1997, 1998, 1999 GRIAULE

Mtodos para Modificar Dados


Editando Registros
Para alterar os campos do registro atual, voc deve colocar a tabela em modo de edio. Para isso voc deve chamar o mtodo Edit do componente Table. Aps chamar o mtodo Edit, altere os valores dos campos, usando os objetos TField. As alteraes no sero gravadas at que voc chame o mtodo Post. Por exemplo:

tblItem.Edit; tblItem.FieldByName('Quantidade').AsString := quantidade; ... {outras alteraes} tblItem.Post;


Ou, de forma mais abreviada, usando o with:

with tblItem do begin Edit; FieldByName('Quantidade').AsString := quantidade; ... {outras alteraes} Post; end;
Voc pode usar tambm os componentes TField, se voc tiver usado o editor de campos para cri-los explicitamente. Nesse caso, melhor atribuir um valor para a propriedade Value, que j tem o tipo de dados correto. Quando mltiplos usurios acessam a mesma tabela, Edit tem uma funo mais importante: ele trava [lock] o registro, de forma que nenhum usurio consegue edit-lo (mais ainda pode fazer a leitura). Quando voc tentar travar o registro, e outro usurio j est editando, seja no mesmo computador ou em outro computador na rede, Edit vai gerar uma exceo EDBEngineError. Essa exceo pode ser tratada usando um comando try..except, coma j vimos. Depois que voc chama o mtodo Post, o registro gravado e liberado. Se depois de chamar Edit, voc resolver cancelar as alteraes no registro (devido a uma exceo, por exemplo), voc pode chamar o mtodo Cancel em vez de Post. Esse mtodo libera o registro e cancela todas as alteraes feitas nos componentes TField. Se voc mudar de registro aps o Edit, usando o mtodo Next por exemplo, o componente vai verificar se voc alterou algum campo. Se voc tiver alterado, ele automaticamente salva o registro antes da movimentao. Se no foi feita alterao, ele cancela a edio para no gravar um registro desnecessariamente.

Delphi 4 Total

210

1997, 1998, 1999 GRIAULE Quando voc usa o controle DBNavigator, alguns botes dele chamam automaticamente esses mtodos: =Edit, = Post, = Cancel.

O boto Edit geralmente no necessrio, porque geralmente o usurio pode iniciar a edio simplesmente alterando um controle de dados, o que automaticamente chama o mtodo Edit. Mas isso depende da propriedade AutoEdit do componente DataSource, que normalmente True. Quando AutoEdit False, o usurio no pode editar os controles de dados e para poder modificar o registro, ele deve primeiro clicar no boto DBNavigator. do

Acrescentando Registros
Para incluir um novo registro na tabela, voc deve chamar o mtodo Insert ou Append. Se a tabela no tem ndice primrio, Insert insere um novo registro no meio da tabela e Append acrescenta o novo registro ao final. Para uma tabela que tem chave primria, os dois mtodos fazem exatamente a mesma coisa: o registro ser inserido na posio determinada pela chave. Assim, o que discutiremos sobre Insert se aplica igualmente a Append. Quando voc chama Insert, ele no grava dados na tabela. Ele apenas cria um novo registro vazio em memria. Depois voc deve preencher os campos desse registro com os seus valores, usando os objetos TField. Para gravar os dados, chame o mtodo Post. O novo registro ser o registro atual da tabela, e vai se tornar o registro atual. A posio do registro na tabela ser determinada pelo valor da sua chave primria. Por exemplo:

codigo := 20; with tblItem do begin Insert; tblItemCodItem.Value := codigo; tblItemQuantidade.Value := quant; tblItemPrecoVenda.Value := preco; Post; end;
Se voc quiser cancelar a insero do novo registro, use o mtodo Cancel. Quando voc cancela, a posio de registro volta ao registro onde voc estava posicionado antes de chamar Insert. Se voc mudar de registro aps chamar Insert, o componente vai verificar se voc alterou algum campo, e vai gravar o novo registro, caso tenha havido alterao, ou cancelar a incluso, caso voc tenha deixado o registro inteiro em branco. Quando voc usa o controle DBNavigator, o usurio pode clicar no boto , que chama automaticamente o mtodo Insert da tabela. Depois ele preenche os campos e clica no Delphi 4 Total 211

1997, 1998, 1999 GRIAULE boto , que chama o mtodo Post, ou no boto , que chama o mtodo Cancel. Quando voc usa o controle DBGrid, o usurio pode pressionar a tecla [Insert] para chamar o mtodo Insert, preencher os campos, e mudar de registro.

Excluindo Registros
Para excluir o registro atual, use o mtodo Delete:

tblItem.Delete;
A operao de excluso executada imediatamente e no pode ser desfeita. Registros excludos no podem ser recuperados. Usando o controle DBNavigator, o usurio pode clicar no boto , que chama esse mtodo automaticamente. Usando o controle DBGrid, o usurio pode pressionar [Ctrl+Delete] para excluir o registro atual. Esses dois controles tm uma propriedade ConfirmDelete. Se ela estiver verdadeira (valor True), o controle mostra uma mensagem de confirmao predefinida, seno exclui o registro imediatamente.

Outros Mtodos
Quando voc trabalha com os mtodos do componente Table, o efeito dos mtodos (edio, incluso, ou movimentao) aparece imediatamente nos controles de dados (se houver). Essa atualizao dos controles geralmente desnecessrio, e toma um certo tempo, tornando muito demorada uma operao com vrios registros, por exemplo. Voc pode desabilitar temporariamente a atualizao dos controles, com o mtodo DisableControls e depois habilitar novamente a atualizao com o mtodo EnableControls. Quando voc chama EnableControls, todos os controles de dados ficam "congelados" com seus valores atuais. Por exemplo:

with tblItem do begin DisableControls; while not EOF do ... EnableControls; end;
Se voc no lembrar de habilitar os controles de dados, eles ficam inutilizveis pelo usurio. Note tambm que se acontecer uma exceo depois de desabilitar os controles, o Delphi vai sair do procedimento e eles no sero habilitados novamente. Para evitar essa ltima situao, use um comando try..finally:

try DisableControls;
Delphi 4 Total 212

1997, 1998, 1999 GRIAULE

while not EOF do ... finally EnableControls; end;


Um comando try..finally garante que a parte do finally sempre executada, seja numa execuo normal, ou quando ocorre uma exceo no bloco do try. Nesse caso, isso garante que os controles de dados so habilitados novamente. Numa rede, os registros que esto sendo visualizados podem ficar desatualizados medida que outros usurios adicionam novos registros. Para obter os registros mais atualizados da tabela, voc pode usar o mtodo Refresh:

tblCliente.Refresh;
Esse mtodo chamado automaticamente pelo boto do DBNavigator.

Delphi 4 Total

213

1997, 1998, 1999 GRIAULE

Eventos dos Componentes de Dados


Os componentes de dados tm vrios eventos que so acionados em momentos especficos.

Eventos do Componente Table


Para cada mtodo do componente Table (Edit, Insert, Post, etc.), existem eventos "Before" e "After", que acontecem respectivamente antes e depois da execuo do mtodo. No evento "Before", voc pode cancelar a execuo do mtodo atual, gerando uma exceo. Esses eventos so acionados nas seguintes situaes: BeforeScroll, AfterScroll: antes e depois, respectivamente, de qualquer movimentao de registro na tabela, provocada por um dos mtodos de movimentao First, Next, Prior, Last, MoveBy, FindKey, FindNearest, etc. BeforeCancel, AfterCancel: antes e depois do cancelamento de uma edio ou incluso (mtodo Cancel). BeforeClose, AfterClose: antes e depois da tabela ser fechada (mtodo Close). BeforeDelete, AfterDelete: antes e depois de um registro ser excludo. No evento BeforeDelete, voc pode mostrar sua prpria mensagem de confirmao de excluso, evitando uma mensagem do Delphi. BeforeEdit, AfterEdit: antes e depois do incio da edio de um registro. BeforeInsert, AfterInsert: antes e depois do incio da incluso de um registro. BeforeOpen, AfterOpen : antes e depois da tabela ser aberta (ativada). BeforePost, AfterPost: antes e depois do registro ser gravado. O evento BeforePost, como j vimos, o melhor lugar para se fazer uma validao de registro, evitando a gravao se necessrio. OnNewRecord: acontece depois da incluso de um novo registro, antes do evento AfterInsert. Nesse evento voc pode, por exemplo, preencher o campo chave da tabela com um valor gerado pelo programa. Se voc fizer alguma alterao de campos em AfterInsert, ou qualquer outro evento, o registro ser considerado modificado, por isso melhor usar OnNewRecord. Cada um desses eventos tem um cabealho como o seguinte:

procedure TForm1.Table1BeforePost(DataSet: TDataset);


Ou seja, um parmetro do tipo 'TDataset'. TDataset uma classe que ancestral da classe TTable e de outros objetos de acesso a dados. Usando o parmetro 'DataSet', voc pode manipular a tabela de forma genrica, sem especificar o nome exato do componente. Delphi 4 Total 214

1997, 1998, 1999 GRIAULE Alm desses, o evento OnCalcFields, como j vimos, acontece quando voc tem campos calculados, no momento em que necessrio obter o valor desses campos.

Delphi 4 Total

215

1997, 1998, 1999 GRIAULE

Manipulao de Datas
O Delphi permite armazenar datas e horas no banco de dados, em campos do tipo Date (apenas datas), ou do tipo Time (apenas horas), ou campos Date/Time ou Timestamp (guarda data e hora), em alguns bancos de dados. importante tambm saber nesse caso as funes disponveis para manipulao de datas. O Delphi codifica datas e horas internamente como nmeros, que representam uma contagem de dias desde 1/1/0001. Ele usa o tipo de dados TDateTime para esse formato codificado. Voc pode usar a funo EncodeDate para gerar esse valor codificado, e o procedimento DecodeDate para obter os componentes da data separados (dia, ms e ano). Por exemplo:

var data: TDateTime; ... begin ... data := EncodeDate( ano, mes, dia ); .... DecodeDate( data, ano, mes, dia ); ... end;
Para tratamento de horas, voc tem semelhantemente as rotinas EncodeTime e DecodeTime, que de forma genrica, so usadas assim:

varHora := EncodeTime( horas, minutos, segundos, milisegs ); DecodeTime( varHora, horas, minutos, segundos, milisegs );
Voc pode fazer operaes com as datas codificadas, como por exemplo, somar um nmero a uma data, ou subtrair duas datas para saber a quantidade de dias entre elas. Voc tambm pode converter uma data/hora para sua representao textual, para trat-la como uma string, usando DateToStr, TimeToStr, ou DateTimeToStr:

editData.Text := DateToStr(tblClienteDataNasc.Value); labelRelogio.Caption := TimeToStr(Now);


Essas funes convertem a data usando o formato padro, que depende da configurao do Windows. Mas voc pode tambm usar outros formatos, usando FormatDateTime, por exemplo:

texto := FormatDateTime(data, 'dd/mm/yyyy');


Delphi 4 Total 216

1997, 1998, 1999 GRIAULE No segundo argumento de FormatDateTime, voc pode usar os marcadores de posio (entre outros): Marcado Insere r d, dd ddd dddd m, mm mmm mmmm yy yyyy h, hh m, mm s, ss / : O dia do ms. Se o dia de 1 a 9, "dd" acrescenta um zero esquerda. O dia da semana abreviado. O nome do dia da semana, completo. O ms como um nmero. Se o ms de 1 a 9, "mm" acrescenta um zero esquerda. O nome do ms abreviado. O nome do ms completo. O ano com dois dgitos. O ano com quatro dgitos. As horas. Se de 0 a 9, "hh" acrescenta um zero esquerda. Os minutos. Se de 0 a 9, "mm" acrescenta um zero esquerda. Os segundos. Se de 0 a 9, "mm" acrescenta um zero esquerda. O separador de datas (pode no ser uma barra). O separador de horas (pode no ser o dois-pontos).

Esses mesmos marcadores podem ser usados com a propriedade DisplayFormat de um campo do tipo data ou hora. Voc pode converter uma string em data/hora, usando as funes de converso StrToDate, StrToTime e StrToDateTime. Para saber o dia da semana, voc pode usar a funo DayOfWeek:

diaSemana := DayOfWeek(data); {1=domingo,...7=sbado}


Finalmente, voc tem funes para consultar a data/hora atuais do computador: Now retorna a data e hora atuais codificadas, Date retorna apenas a data e Time retorna apenas a hora. Por exemplo, para mostrar a data de hoje em um controle de edio, faa:

editData.Text := DateToStr(Date);
Delphi 4 Total 217

1997, 1998, 1999 GRIAULE

Exemplo: Criando formulrio sem utilizar o dbNavigator


Neste exemplo iremos criar o cadastro de fornecedores, sem utilizar o componente dbNavigator , iremos utilizar Botes e tratar o evento de cada um , fazendo uma simulao do dbNavigator. Crie um novo formulrio, altere seu nome para 'formCadFornecedor', na propriedade Caption coloque 'Cadastro de Fornecedores'. Acrescente 9 componentes SpeedButton ( ), e altere as propriedades a seguir, as figuras so encontradas no direito do Delphi 'BORLAND SHARED\IMAGES\BUTTONS' : SpeedButton1 Name Glyph Hint SpeedButton2 Name Glyph Hint SpeedButton3 Name Glyph Hint SpeedButton4 Name Glyph Hint SpeedButton5 spbCancelar IGNORE.BMP Cancelar spbSalvar FLOPPY.BMP Salvar spbAlterar FILEOPEN.BMP Alterar spbIncluir FILENEW.BMP Inclui

Delphi 4 Total

218

1997, 1998, 1999 GRIAULE Name Glyph Hint SpeedButton6 Name Glyph Hint SpeedButton7 Name Glyph Hint SpeedButton8 Name Glyph Hint SpeedButton9 Name Glyph Hint spbExcluir TRASH.BMP Excluir spbUltimo VCRFSFOR.BMP ltimo spbProximo ARROW3R.BMP Prximo spbAnterior ARROW3L.BMP Anterior spbPrimeiro VCRREWND.BMP Primeiro

Coloque seu formulrio como a figura abaixo:

Delphi 4 Total

219

1997, 1998, 1999 GRIAULE

Coloque um componente Table e um DataSource no formulrio, defina suas propriedades como:

Table Name: tblFornecedor DatabaseName: CursoDelphi TableName: Fornecedor

DataSource Name: dsFornecedor DataSet: tblFornecedor Clique duas vezes no componente tblFornecedor, para abrir o editor de campos, em seguida adicione os objetos de campos e arraste-os para o formulrio. Organize seu formulrio de acordo com a figura abaixo:

Delphi 4 Total

220

1997, 1998, 1999 GRIAULE Salve a unit como 'CADFORNCEDOR.PAS'. No evento OnShow do formulario, vamos abrir o componente tblFornecedor , crie um procedimento para este evento e coloque:

tblFornecedor.Open
Para que o formulrio funcione necessrio acrescentar em cada Boto , um procedimento para o evento OnClick. No procedimento do evento OnClick do boto spbIncluir colocar:

procedure TformCadFornecedor.spbIncluirClick(Sender: TObject); begin tblFornecedor.insert end;


O mtodo Insert do componente Table, inclui um registro em branco. No procedimento do evento OnClick do boto spbAlterar colocar:

procedure TformCadFornecedor.spbAlterarClick(Sender: TObject); begin tblFornecedor.edit end;


O mtodo Edit que permite fazer alteraes, mas essas alteraes podem ser confirmadas ou no. No procedimento do evento OnClick do boto spbSalvar colocar:

procedure TformCadFornecedor.spbSalvarClick(Sender: TObject); begin tblFornecedor.post end;


O mtodo Post, confirma as alteraes feitas nos campos da tabela. No procedimento do evento OnClick do boto spbCancelar colocar:

procedure TformCadFornecedor.spbCancelarClick(Sender: TObject); begin tblFornecedor.cancel end;


O mtodo Cancel, cancela as alteraes feitas nos campos da Delphi 4 Total tabela. 221

1997, 1998, 1999 GRIAULE No procedimento do evento OnClick do boto spbPrimeiro colocar:

procedure TformCadFornecedor.spbprimeiroClick(Sender: TObject); begin tblFornecedor.first end;


O mtodo First movimenta para o primeiro registro. No procedimento do evento OnClick do boto spbAnterior colocar:

procedure TformCadFornecedor.spbAnteriorClick(Sender: TObject); begin tblFornecedor.prior end;


O mtodo Previous movimenta para o registro anterior. No procedimento do evento OnClick do boto spbIncluir colocar:

procedure TformCadFornecedor.spbProximoClick(Sender: TObject); begin tblFornecedor.next end;


O mtodo Next movimenta para o prximo registro. No procedimento do evento OnClick do boto spbUltimo colocar:

procedure TformCadFornecedor.spbUltimoClick(Sender: TObject); begin tblFornecedor.last end;


O mtodo Last movimenta para o ltimo registro. No procedimento do evento OnClick do boto spbExcluir colocar:

procedure TformCadFornecedor.spbExcluirClick(Sender: TObject); begin if application.messagebox('Deseja excluir o fornecedor?', 'Confirmao', MB_ICONQUESTION + MB_YESNO) = idyes then tblFornecedor.delete end;
Delphi 4 Total 222

1997, 1998, 1999 GRIAULE

O mtodo Delete exclui o registro atual. Antes de excluir o registro ser mostrado uma mensagem perguntando se deseja excluir o fornecedor. Notas: Se foi feita alguma alterao no registro atual , em seguida foi aplicado algum modo de movimentao na tabela ,as alteraes sero confirmadas, antes da movimentao. Neste exemplo mostramos somente o que cada mtodo faz, no foi realizado nenhum controle de desativar o boto Salvar , se o componente Table no estiver no modo de Alterao ou Incluso , esses controles podem ser feitos com a propriedade Enabled de cada componente SpeedButton.

Delphi 4 Total

223

1997, 1998, 1999 GRIAULE

Tratamento do Erro 'Key violation.'


Este erro ocorre quando estamos inclundo um registro , e o valor informado para a chave primria j existe. Para mostrar uma mensagem de erro mais clara para o usurio , podemos mostrar a nossa prpria mensagem de erro. Este erro ocorre quando o usurio confirma as informaes que foram colocadas, ou seja, quando o nosso programa executa o mtodo Post. Quando ocorre algum erro durante a execuo desse mtodo, gera o evento OnPostError, ento podemos criar um procedimento para este evento que ir mostrar a mensagem que desejamos.Neste procedimento coloque os comandos abaixo:

if e.message = 'Key violation.' then begin showmessage('Fornecedor Cadastrado!'); abort; end;


O parmetro 'E' contm o erro que ocorreu durante a gravao dos dados. Este parmetro da classe EDataBaseError,a propriedade message desta classe , contm a mensagem do erro. necessrio abortar o procedimento, para que a mensagem em ingls no aparece, por isso utilizamos o mtodo Abort;. Notas: Ao verificar uma mensagem com a propriedade message, para que a condio utilizada seja verdadeira, a mensagem que esta verificando case sensitive, portanto, tem que ser escrita idntica ao contedo da propriedade Vamos associar este formulrio ao formulrio principal, na Unit 'VENDPRIN.PAS', logo aps a seo implementation acrescente:

Uses

CadCliente, ....., CadFornecedor;

Agora tecle [F12] para voltar ao formulrio. Clique no item de menu Cadastro|Fornecedor e, no procedimento de evento, coloque o seguinte comando:

formCadFornecedor.show
Salve o projeto e execute . Para testar cadastre alguns fornecedores , faa alteraes, tente cadastrar fornecedores que tenham o mesmo cdigo.

Delphi 4 Total

224

1997, 1998, 1999 GRIAULE

Usando um Controle DBLookupComboBox


Quando o usurio cadastra um produto, ele precisa digitar o cdigo do fornecedor, que deve corresponder a um valor vlido na outra tabela. Esse um processo sujeito a erros e torna difcil validar o valor que o usurio digita (para validar, seria necessrio pesquisar na tabela de fornecedores). Voc pode facilitar a entrada desse campo para o usurio permitindo a ele selecionar o fornecedor a partir de um lista de nomes. Para isso, no formulrio de produtos, apague o controle DBEdit que est sendo usado para o campo "CodFarnecedor". Vamos utilizar outro controle que o DBLookupComboBox ) da pgina Data Controls. Esse controle tem a capacidade de gravar valores em uma ( tabela e mostrar uma lista de valores de outra. Coloque um controle DBLookupComboBox no formulrio ao lado do rtulo "CodFornecedor". Altere o Caption do rtulo para "Fornecedor". No controle DBLookupComboBox, mude o nome para 'cboFornecedor'. Vamos alterar tambm as seguintes propriedades: DataSource para 'dsProduto', e DataField para 'CodFornecedor', ou seja, os mesmos valores do DBEdit anterior. Essas propriedades, como para qualquer controle de dados, dizem quais os dados que o controle vai acessar. Alm dessas propriedades, outras propriedades determinam de onde o controle busca a lista de valores a ser mostrada. Mas antes de alterar essas propriedades, precisamos criar novos componentes de dados no formulrio. No formulrio de fabricantes (FormCadFornecedor), selecione o componente 'tblFornecedor' e o componente 'dsFornecedor' e tecle [Ctrl+C] para copi-los. Agora volte para o formulrio de produtos (FormCadProduto) e tecle [Ctrl+V]. Isso vai colocar no formulrio duas cpias dos componentes, que acessam a tabela FORNECEDOR. Isso necessrio para fornecer os valores mostrados por 'cboFornecedor'. Retornando ao componente 'cboFornecedor', altere as seguintes propriedades: Propriedade ListSource KeyField ListField Valor dsFornecedor CodFornecedor Nome

A propriedade ListSource determina qual a tabela que ser usada para buscar os valores a serem mostrados. Como 'dsFornecedor' est ligado tabela FORNECEDOR.DB, os dados sero lidos desta tabela. O valor de KeyField (CodFornecedor, nesse caso) o nome do campo, na tabela FORNECEDOR, que corresponde ao campo DataField na tabela Delphi 4 Total 225

1997, 1998, 1999 GRIAULE PRODUTO. Finalmente ListField determina qual o campo que ser mostrado na lista, nesse caso, Nome. Falta um detalhe: voc deve ativar a tabela de fornecedores, 'tblFornecedor' nesse formulrio. Acrescente o seguinte no procedimento do evento OnCreate do formulrio:

begin tblProduto.Open; tblFornecedor.Open; end;


Agora execute o programa. Repare que voc pode selecionar o fornecedor pelo nome agora. Se voc quiser mostrar o cdigo tambm, alm do nome, voc pode alterar a propriedade ListField para incluir mais de um campo. Para isso, coloque os nomes dos campos, separados por ";" (sem espao entre os nomes e o ponto-e-vrgula). No nosso caso, coloque "Nome;CodFornecedor" em ListField e execute o programa. Quando a lista est fechada, aparece apenas o nome do fornecedor, mas quando voc abre a lista, vo aparecer os dois campos: nome e cdigo.

Delphi 4 Total

226

1997, 1998, 1999 GRIAULE

Captulo 16 Utilizando Mestre/Detalhe


Criando um Formulrio Mestre/Detalhe Usando Trs Tabelas no Formulrio

Delphi 4 Total

227

1997, 1998, 1999 GRIAULE

Criando um Formulrio Mestre/Detalhe


Uma situao muito comum na utilizao de bancos de dados o relacionamento entre duas tabelas, onde uma tabela tem um registro que se relaciona com vrios registros de outra. No Delphi, isto chamado de relacionamento mestre/detalhe [master/detail]. A tabela mestre aquela que tem um nico registro fazendo parte do relacionamento. A tabela detalhe aquela que tem vrios registros relacionados. No nosso caso, um cliente possui vrios registros de venda relacionados (1-N). A tabela Cliente ser a tabela mestre e a tabela Venda ser a tabela detalhe.

Usando o DFW para criar o formulrio


O Database Form Wizard pode criar automaticamente um formulrio mestre/detalhe, basta voc informar as tabelas e quais os campos relacionados. No nosso caso, usaremos a tabela Cliente como mestre e a tabela Venda, criada anteriormente, como detalhe. Esse formulrio ser criado no projeto VENDA.DPR , portanto ele tem que estar aberto. No menu Database|Form Wizard.... Na primeira tela, no primeiro grupo de opes, selecione a segunda opo, "Create a master/detail form" e clique em Next. Na prxima tela, voc deve escolher a tabela mestre. Primeiro clique na lista "Drive or Alias name" e selecione "CursoDelphi", o nome de alias que for criado anteriormente. Agora, na lista de tabelas, escolha CLIENTE.DB e clique em Next. Depois selecione apenas os campos CodCliente e Nome (clique no campo e no boto ">"). Na prxima tela, escolha um layout horizontal para o formulrio. Agora voc deve selecionar a tabela detalhe. Selecione a tabela VENDA.DB, e na outra tela adicione todos os campos (clique no campo e no boto ">>"). Na prxima tela, escolha o layout "Grid". Isso vai colocar um controle DBGrid na parte "detalhe" do formulrio, em vez de controles de dados separados, este componente permite visualizar vrios registros ao mesmo tempo.. Por ltimo, o Database Form Wizard vai perguntar quais os campos que compem o relacionamento entre as tabelas. A tabela detalhe deve ter um ndice definido para o campo que faz o relacionamento. A lista dos ndices disponveis aparece abaixo de "Index Name". Selecione o ndice "CodCliente", que foi criado quando colocamos a restrio de integridade . Agora, na lista da esquerda, aparece o campo "CodCliente" (se o ndice tivesse mais de um campo, todos estariam na lista). Selecione o campo. Na lista da direita, aparecem os campos da tabela mestre. Selecione o campo que tem o mesmo nome, "CodCliente". A tela do DFW ficar como a seguinte:

Delphi 4 Total

228

1997, 1998, 1999 GRIAULE

Isso define o seguinte relacionamento entre as tabelas:

Agora clique em Next e depois no boto "Finish". O formulrio ser adicionado com as opes definidas.

Testando o Formulrio Gerado


Execute o programa, e veja como funciona o relacionamento mestre/detalhe. Na parte "detalhe" do formulrio (o controle DBGrid da parte inferior), voc pode adicionar registros que estaro automaticamente relacionados com o registro de cliente que aparece na parte superior. Se voc usar o DBNavigator do topo do formulrio para mudar de registro na tabela mestre, os registros de detalhe que aparecem embaixo sero diferentes. Como a tabela Venda no continha dados, inicialmente nenhum cliente tem registros associados. Note que o campo "CodCliente", que define o relacionamento com o cliente, aparece no Grid. Quando voc comea a incluir um registro, ele preenchido automaticamente de acordo com o valor do cdigo do cliente atual. Se voc alterar esse campo manualmente, o registro vai desaparecer da lista, pois vai estar relacionado com outro cliente. Delphi 4 Total 229

1997, 1998, 1999 GRIAULE Aps entrar com alguns dados, finalize a execuo.

Analisando o Formulrio
Vejamos exatamente como definido o relacionamento mestre/detalhe pelo DFW. Como antes, so utilizados os componentes Table e DataSource, s que desta vez existem dois componentes Table e dois DataSource, todos no topo do formulrio, ao lado do DBNavigator, como na figura:

O primeiro 'Table1', est associado com a tabela CLIENTE.DB, atravs da propriedade TableName. O 'DataSource1' est ligado com 'Table1', atravs da propriedade DataSet. De forma anloga, os outros dois acessam a tabela de vendas: Table2.TableName tem o valor "VENDA.DB" e DataSource2.DataSet Table2. Os dois controles DBEdit da parte superior do formulrio esto ligados ao DataSource1 e o controle DBGrid da parte inferior est ligado ao DataSource2. Vamos alterar os nomes desses componentes de dados, para facilitar o entendimento. Mude os nomes para os seguintes:

Alm das ligaes que j vimos, num formulrio mestre/detalhe, preciso relacionar as duas tabelas. Isso feito com propriedades que ligam 'tblVenda' (antes Table2) a 'dsCliente' (antes DataSource1). Selecione o componente 'tblVenda' e veja que a propriedade MasterSource est ligada com 'dsCliente'. Isso define qual tabela ser a mestre para essa tabela. A propriedade MasterFields diz qual o campo (ou campos, se mais de um) na tabela mestre, que faz o relacionamento, e nesse caso "CodCliente". A propriedade IndexFieldNames, nesse caso, define qual o campo (ou campos) na tabela detalhe, que faz o relacionamento com o outro, e nesse caso tem o mesmo nome, "CodCliente" (mas no obrigatrio que tenha o mesmo nome).

Delphi 4 Total

230

1997, 1998, 1999 GRIAULE Nota: O valor que aparece na propriedade DataSet o nome do outro componente, mas para propriedades de ligao, o Delphi guarda internamente um ponteiro de objeto, independente do nome. Tente executar o programa o Delphi vai mostrar um erro de compilao dentro do procedimento de evento 'FormCreate' , que foi criado pelo Database Form Wizard. Os dois comandos, "Table1.Open" e "Table2.Open", so para abrir as duas tabelas em tempo de execuo. Eles no funcionaro mais, porque voc alterou os nomes dos componentes Table. Substitua pelo seguinte:

begin tblCliente.Open; tblVenda.Open; end;


Notas: Os comandos existente no procedimento de evento OnCreate sero executados no momente que o formulrio for criado.

Alterando Propriedades do Formulrio


Vamos alterar algumas caractersticas desse formulrio. Ao executar observe que ele permite alterar registros da tabela mestre, no caso a tabela de clientes. Mas voc pode proibir esse tipo de alterao. A forma mais simples de fazer isso alterar a propriedade ReadOnly de 'tblCliente' para o valor True. Isso probe qualquer forma de alterao na tabela, seja edio, incluso ou excluso de registros. Com isso, alguns botes do DBNavigator, como , , , e , que fazem alteraes na tabela, estaro sempre desabilitados e no tm mais funo. Por isso vamos remov-los do DBNavigator. Selecione o controle e a propriedade VisibleButtons. Essa uma propriedade de conjunto que determina quais botes so visveis. Clique duas vezes no nome da propriedade para expandir os elementos do conjunto. Cada um deles corresponde a um boto do DBNavigator. Altere para False os elementos nbInsert (afeta o boto nbDelete ( ), nbEdit ( ), nbPost ( ) e nbCancel ( ). ),

No DBGrid da parte inferior, o campo 'CodCliente' est disponvel para visualizao e edio, mas ele sempre ter o mesmo valor que o campo CodCliente da parte superior, portanto vamos torn-lo invisvel. Para tornar o campo invisvel, clique duas vezes no componente 'tblVenda' para abrir o editor de campos. Selecione o campo CodCliente. No remova da lista, seno o Delphi no vai conseguir manter o relacionamento. Apenas altere sua propriedade Visible para False. Altere o Caption do formulrio para "Clientes e Vendas" e a propriedade Name para formCadCliVend . Altere tambm o label "CodCliente", para "Cdigo". Se quiser, reduza o Delphi 4 Total 231

1997, 1998, 1999 GRIAULE tamanho do painel que contm os controles de edio para a tabela de clientes. Voc deve clicar na borda mais espessa e no no fundo do painel. Execute o programa e verifique que agora no possvel editar os campos da tabela de clientes, apenas adicionar e remover registros de vendas relacionados.

Salvando o Projeto
Salve esse projeto como CADCLIVEND.

Delphi 4 Total

232

1997, 1998, 1999 GRIAULE

Usando Trs Tabelas no Formulrio


Com o Database Form Wizard s possvel criar um formulrio mestre/detalhe para no mximo duas tabelas. Algumas situaes exigem tratar um relacionamento mestre detalhe detalhe, com trs tabelas, ou dois relacionamentos mestre/detalhe no mesmo formulrio. Para isso preciso criar manualmente os relacionamentos, alterando as propriedades MasterSource e MasterFields do componente Table. Agora vamos relacionar a tabela de vendas com a tabela de itens vendidos (ITEM), que contm informaes sobre cada item individual vendido.

Ligando os Componentes de Dados


Abra o projeto anterior, VENDA.DPR, se ele j no estiver aberto no Delphi. Ns precisamos alterar o formulrio de clientes e vendas. Primeiro adicione ao formulrio mais um componente Table e mais um DataSource. Para o componente Table, altere as seguintes propriedades: Name para 'tblItem', DatabaseName com o nome do alias, "CursoDelphi" e, TableName com o nome da tabela "ITEM.DB" (note que a lista de valores de TableName mostra as trs tabelas). Para cada registro de venda, haver vrios registros de item de venda, relacionados atravs do campo "CodVenda". Para fazer esse relacionamento, altere a propriedade MasterSource, selecionando da lista o 'dsVenda'. Isso define qual a tabela mestre para esta. Agora clique na propriedade MasterFields e no boto de reticncias. Deve aparecer uma caixa de dilogo, onde voc pode facilmente definir o relacionamento, bem semelhante ao que aparece no Database Form Wizard. Em "Available indexes", selecione o ndice "IndVenda". Nas listas abaixo, selecione o campo "CodVenda" em cada uma e clique no boto Add. Depois clique em Ok. Isso vai alterar automaticamente a propriedade IndexFieldNames para conter "CodVenda", e MasterFields contm "CodVenda" tambm. Ambas definem os nomes dos campos que participam do relacionamento. Agora selecione o componente DataSource que voc colocou por ltimo. Mude o seu nome para 'dsItem' e na propriedade DataSet, selecione 'tblItem' para lig-lo com o ltimo componente Table. No evento Oncreate do formulrio coloque tblitem.open;

Criando Controles de Dados


Vamos ampliar o formulrio para incluir um grid para a tabela de itens. Mas antes de fazer isso, precisamos alterar propriedades do painel que contm o grid da parte inferior. Delphi 4 Total 233

1997, 1998, 1999 GRIAULE Clique no grid de vendas e tecle [Esc] para selecionar seu painel. Altere sua propriedade Align para 'alTop'. O valor anterior era 'alClient', que alinhava o painel de acordo com o espao disponvel no formulrio. Clique no quadrado de seleo inferior e arraste-o para reduzir o tamanho vertical do painel. Isso vai deixar um espao vazio na parte inferior do formulrio. Se preciso, aumente o formulrio na vertical para aumentar essa rea. Para manter a aparncia do formulrio, selecione a pgina Standard e o componente Panel, , que o ltimo cone. Coloque um componente na parte inferior. Esse um controle cuja finalidade geralmente s a de conter outros controles. Altere suas propriedades da seguinte forma: Propriedade Caption BevelInner BorderWidth Align Valor (vazio) bvLowered efeito 4 alClient Efeito tira o texto "Panel2"

3-d interno "afundado" aumenta a borda preenche o espao disponvel

Agora, selecione a pgina Data Controls na paleta de componentes e selecione o ). Coloque-o em cima do painel. Altere sua propriedade Align para 'alclient', DBGrid ( para que ele ocupe o espao do painel e BorderStyle para 'bsNone', para remover a borda preta em volta do controle. Altere tambm DataSource para 'dsItem'. Com isso, a grade vai mostrar os dados da tabela de itens e permitir alterao. Para que o campo 'CodVenda' no aparea na grade, selecione o componente 'tblItem' e clique duas vezes para abrir o editor de campos. Adicione todos os campos, selecione 'CodVenda' na lista e altere a propriedade Visible para False.

Criando Campos Calculados


Usando um componente Table, voc pode mostrar, alm dos campos da tabela, campos calculados, que aparecem da mesma forma que campos do registro, mas sem permitir alterao. O valor de um campo calculado definido pelo cdigo do seu programa. Quando o Delphi precisa mostrar um campo calculado, ele aciona o evento OnCalcFields do componente Table. No nosso caso, a tabela de itens ter um campo calculado. O preo de venda do item um preo unitrio, que deve ser multiplicado pela quantidade de itens vendidos. Para isso, vamos criar um novo campo PrecoTotal contendo esse resultado.

Delphi 4 Total

234

1997, 1998, 1999 GRIAULE No formulrio, clique duas vezes no componente 'tblItem', para abrir o editor de campos. Para definir um novo campo calculado, clique com o boto direito e em "New Field...". Voc deve definir um nome para o campo. Digite "PrecoTotal". O nome do componente TField criado automaticamente como "tblItemPrecoTotal", mas voc pode mudar se precisar. Voc deve tambm escolher um tipo de dados para o campo. Escolha "FloatField" na lista (tipo real) e clique Ok. Todos os componentes TField tm nomes baseados no nome do componente Table ao qual eles pertencem, como "tblItemCodVenda" etc. Esses nomes podem ser alterados, se necessrio, selecionando o componente na lista e alterando sua propriedade Name. Para definir o valor de um campo calculado no programa, precisamos saber o nome dos componentes utilizados. Para realizar o calculo do Preo Total necessrio ter o preo de venda do produto, portanto vamos acrescentar um componente Table e um DataSource, que estaro associados com a tabela "Produto.db". Para o componente Table, altere as seguintes propriedades: Name para 'tblProduto', DatabaseName com o nome do alias, "CursoDelphi" e, TableName com o nome da tabela "PRODUTO.DB". Clique duas vezes no componente 'tblProduto', para abrir o editor de campos.Para adicionar os objetos de campos clique em "Add..." em seguida clique no boto 'Ok'. Agora selecione o componente 'tblItem' e crie um procedimento para o seu evento OnCalcFields. Esse procedimento executado a cada vez que um registro da tabela mostrado. Durante a sua execuo, voc pode atribuir valores para campos calculados, como 'tblItemPrecoTotal'. Digite o seguinte:

begin if tblproduto.FindKey([tblitemCodProduto.value]) then tblItemPrecoTotal.Value := tblItemQuantidade.Value * tblProdutoPrecoVenda.Value; end;


Para ler ou alterar o valor de um componente TField, leia ou altere sua propriedade Value. O tipo dessa propriedade depende do tipo de dados do campo. Como o Preco de Venda do produto est na tabela produto necessrio obter o valor desta tabela, portanto, utilizamos o mtodo FindKey para posicionarmos no produto que estamos querendo o preo. E o objeto de campo "PrecoTotal" ser o valor da quantidade vendida multiplicada pelo preo de venda do produto. Ao invs de ficar mostrando o cdigo do produto , iremos tambm mostrar o nome do produto, para isto temos que criar um outro campo LooKup, mas este ser mostrado o campo nome da tabela produto.

Delphi 4 Total

235

1997, 1998, 1999 GRIAULE

Usando um campo Lookup


Para mostrar o nome do produto , vamos criar um campo Lookup.Um campo Lookup traz dados de uma outra tabela relacionada. Neste caso, o campo ir buscar um registro na tabela de produto, atravs do campo CodProduto, e mostrar o nome do produto. Para inserir um campo Lookup, clique duas vezes em 'tblItem' para abrir o editor de campos. Clique com o boto direito e selecione "New Field...". Em "Name", especifique "NomeProduto", em "Type" selecione "string", em "Size" informe 50. Marque a opo "Lookup". Agora em "Key Fields", selecione "CodProduto" .Esse o campo que ser usado para buscar o produto na outra tabela. Em "DataSet", selecione "tblProduto", que a tabela de onde ser buscado os dados. Finalmente , em "LooKup Keys", selecione "codproduto" este o campo que ser utilizado para fazer o relacionamente da tabela produto com a tabela item e em "Result Field" coloque nome (o campo de resultado que ser mostrado). As propriedades estaro como abaixo:

Arraste o campo LookUp 'NomeProduto' , para a primeira posio e o campo 'PrecoTotal' coloque-o na ltima posio, como na figura abaixo:

Delphi 4 Total

236

1997, 1998, 1999 GRIAULE

Testando e Salvando o Projeto


Para que o usurio possa acessar o formulrio de vendas , preciso mostrar esse formulrio a partir do menu principal. Para isso , retorne ao formPrincipal. Voc pode usar o boto Agora, acrescente o seguinte cdigo ao evento Onclick do item de menu Cadastro|Vendas: .

procedure TformPrincipal.menuCadVendasClick(Sender: TObject); begin formCadCliVend.show end;


Para funcionar, voc precisa adicionar uma clusula uses, no incio da seo de implementao (implementation) do formulrio. Adicione o seguinte:

uses CadCliVend
Agora execute o programa para ver o efeito das modificaes. Note que no grid da tabela Item, o campo calculado PrecoTotal , os campos LooKup PrecoVenda e Nome vo aparecer para cada registro. Se voc alterar os campos Quantidade , PrecoVenda ou o Produto, o evento OnCalcFields ser executado, e o valor do campo ser alterado. Na verdade, esse evento executado para qualquer alterao de campo, mesmo os que no afetam seu valor. Finalize a execuo e salve o projeto novamente.

Delphi 4 Total

237

1997, 1998, 1999 GRIAULE

Atualizando Quantidade em Estoque


Ao realizar uma venda de um determinado produto, necessrio atualizar a quantidade disponvel em estoque. Ento antes de salvar os dados na tabela de item, iremos atualizar a tabela de produto. O evento que ocorre antes de gravar um determinado registro o evento OnBeforePost, crie um procedimento para este evento na tabela 'tblItem', e acrescente o cdigo a seguir:

procedure TformCadCliVend.tblItemBeforePost(DataSet: TDataSet); begin if not tblproduto.findkey([tblItemCodProduto.value]) then begin showmessage('Produto no encontrado!'); abort; end; tblproduto.edit; if tblItem.State in [dsEdit] then tblProdutoqtdEstoque.value := tblprodutoqtdEstoque.value + QuantidadeAnterior; if tblitemquantidade.value > tblprodutoqtdEstoque.value then begin showMessage('Quantidade Insuficiente no Estoque!'); tblProduto.cancel; if tblitem.State in [dsEdit] then tblItem.Cancel. tblItemQuantidade.FocusControl; abort; end else tblProdutoqtdEstoque.value := tblprodutoqtdEstoque.value - tblItemQuantidade.value; tblproduto.post; end;
O mtodo FindKey foi utilizado para verificar se o produto includo existe, caso no exista ir aparecer uma mensagem e o procedimento ser abortado. Quando o procedimento OnBeforePost abortado o evento OnAfterPost no ocorre, portanto, a venda no ser efetuada. O mtodo Edit foi utilizado para colocar a tabela 'Produto' em modo de Alterao , com isso pode ser feito alteraes em qualquer campo desta tabela . Antes de atualizar o campo 'QtdEstoque' , necessrio verificar se a tabela 'Item' esta sendo alterada, caso esteja , o campo alterado 'Quantidade' ( pois o nico campo que iremos permitir alterao) , Delphi 4 Total 238

1997, 1998, 1999 GRIAULE portanto, temos que adicionar o valor antigo ao estoque , para depois retirar a quantidade desejada, o valor antigo foi armazendo na varivel QuantidadeAnterior. Em seguida feito uma verificao se o valor que esta sendo vendido maior que o estoque existente, se isso ocorrer no podemos permitir a venda do item, ento cancelamos a alterao feito na tabela produto(est alterao ocorre somente se o campo 'quantidade' da tabela item esta sendo alterado) , cancelamos tambm as alteraes da tabela item , caso ela esteja em modo de edio e em seguida abortamos o procedimento. Caso no tenha ocorrido nenhum dos problemas citados anteriormente, finalmente podemos subtrair a quantidade vendida pela quantidade existente no estoque. Para atualizar o estoque estamos considerando que o nico campo que possa ser alterado da tabela 'Item' o campo 'Quantidade', para fazer a alterao do produto necessrio excluir o item de venda e incluir novamente. No iremos aceitar modificao no campo 'codproduto' da tabela 'item', vamos criar um procedimento no evento OnChange do objeto 'tblItemQuantidade', para criar este procedimento clique duas vezes na tabela 'Item', com isso ir abrir o editor de cdigo, escolha o campo 'Quantidade', no 'Object Inspector ', clique na pgina 'Events', em OnChange, acrescente o cdigo a seguir:

procedure TformCadCliVend.tblItemCodProdutoChange(Sender: TField); begin if tblItem.state in [dsEdit] then begin showmessage('No permitido a alterao do produto!'); tblitem.cancel; abort; end end;
Falta criar a varivel 'QuantidadeAnterior' e atribuir um valor, abaixo da seo implementation acrescente:

Var

QuantidadeAnterior : integer;

Essa varivel ir conter o valor do campo 'Quantidade' antes de ser modificado, crie um procedimento para o evento OnBeforeEdit, este evento ocorre antes de fazer modificaes nas tabelas, neste procedimento coloque:

procedure TformCadCliVend.tblItemBeforeEdit(DataSet: TDataSet); begin Quantidadeanterior := tblItemQuantidade.value; end;


Quando o item for excludo , temos que acrescentar a quantidade que foi retirada ao estoque, portanto, no evento OnBeforeDelete (antes de excluir) , coloque o procedimento abaixo: Delphi 4 Total 239

1997, 1998, 1999 GRIAULE

procedure TformCadCliVend.tblItemBeforeDelete(DataSet: TDataSet); begin if tblproduto.findkey([tblItemCodProduto.value]) then begin tblproduto.edit; tblProdutoqtdEstoque.value := tblprodutoqtdEstoque.value + tblItemQuantidade.value; tblproduto.post; end; end;
Neste procedimento realizado uma procura do produto pertencente ao item , caso o produto seja encontrado , ser adicionado ao campo 'qtdEstoque' a quantidade do item excludo.

Delphi 4 Total

240

1997, 1998, 1999 GRIAULE

Captulo 17 Consultas e SQL


Exemplo: Usando Consultas Exemplo: Consultando Vrias Tabelas Outros Comandos SQL Consultas num Ambiente Cliente/Servidor Mtodos e Eventos do Componente Query

Delphi 4 Total

241

1997, 1998, 1999 GRIAULE

Exemplo: Usando Consultas


O componente - Query usado para obter dados baseados em um comando SQL. Ele pode ser usado em situaes onde uma tabela no seria suficiente, por exemplo: Acessar um subconjunto da tabela, em vez de todos os registros (isso fundamental para ter bom desempenho num ambiente cliente/servidor) Reunir dados de mltiplas tabelas (junes) Totalizaes de dados de vrios registros A forma mais fcil de usar um componente Query usar o Database Form Expert para criar um formulrio.

Criando o Formulrio
Abra o projeto VENDAS.DRP e acione o menu Database |Form Wizard.... Na primeira tela do DFW, mantenha a opo "Create a simple form" na parte superior, mas na parte de baixo selecione "Create a form using TQuery objects". Clique em Next. Na prxima tela, na lista "Drive or alias", selecione CursoDelphi. Na lista de tabelas, selecione a tabela VENDA.DB, depois selecione todos os campos e escolha o layout "In a grid". Na ltima tela, desmarque a opo "Generate a main form" e clique em Finish. O formulrio gerado semelhante aos que j criamos com o DFW, mas ele utiliza um componente Query em vez de um Table. Os componentes de dados esto no topo do formulrio:

Query1

DataSource1

Selecione o componente 'Query1' e veja suas propriedades. Note que o 'DataSource1' tem na propriedade Dataset o valor 'Query1'. Isso faz a ligao entre os dois. Vamos alterar os nomes dos componentes para 'qryVenda' e 'dsVenda', respectivamente. Depois altere tambm o cdigo do evento OnCreate do formulrio, para abrir 'qryVenda' em vez de 'Query1'. A propriedade mais importante do componente Query a propriedade SQL. Essa propriedade uma lista de strings (TStrings), que contm um comando da linguagem SQL. Clique em SQL e no boto com reticncias. Repare que o contedo da propriedade o seguinte: Delphi 4 Total 242

1997, 1998, 1999 GRIAULE

Select venda."CodVenda", venda."CodCliente", venda."DataVenda" From "c:\cursodelphi\venda.DB" As venda


O comando select um comando SQL que consulta registros. Primeiro so especificados os campos da tabela que sero retornados pelo select. Depois do from, vem o nome da tabela. Nesse caso, um nome completo, incluindo subdiretrio. A expresso "as Venda" cria um apelido para a tabela dentro do comando, que utilizado anteriormente, na lista do select (Venda."CodCliente", por exemplo). Clique OK para fechar o editor de strings. Altere a propriedade Name do formulrio para 'formConsVendasporCliente' e a propriedade Caption para 'Vendas por Cliente". Para o usurio poder visualizar esse fomulrio temos que cham-lo no evento Onclick do menu Consultas|Vendas por Cliente da Unit VendPrin. Neste evento coloque o cdigo abaixo:

formConsVendasporCliente.show;
Para isso funcionar, voc precisa adicionar uma clusula uses , no incio da seo implementation do formulrio VendPrin. adicione o seguinte:

uses

ConsVendasCliente;

Salve o formulrio criado como "CONSVENDASCLIENTE.PAS". Execute o programa e veja o resultado: voc pode percorrer os registros da tabela, mas no pode alter-los.

Obtendo um Resultado Modificvel


Uma consulta geralmente retorna um resultado que no modificvel, ou seja, registros apenas para leitura. Mas voc pode pedir ao Delphi para retornar um conjunto de registros modificvel ["live" result set], que permite acessar a tabela como atravs de um componente Table. Para isso, altere a propriedade RequestLive do componente Query para True. Quando esta propriedade verdadeira, o componente vai tentar retornar um conjunto de registros modificvel, mas nem sempre isso possvel. Em tempo de execuo, voc pode verificar se a consulta modificvel, consultando sua propriedade CanModify (do tipo boolean). Execute o programa e agora voc deve ser capaz de fazer alteraes nos registros.

Delphi 4 Total

243

1997, 1998, 1999 GRIAULE

Simplificando o Select
O comando select, que retorna os dados, pode ser simplificado, e podemos evitar que o diretrio da tabela seja codificado de forma fixa. Abra novamente a propriedade SQL e substitua todas as linhas do comando pelo seguinte:

select * from Venda


Voc pode colocar os comandos na mesma linha, ou em linhas separadas. O "*" (asterisco) no select em vez de uma lista de campos seleciona todos os campos da tabela, independentemente da estrutura dessa tabela. Note que no preciso colocar a extenso de arquivo (.DB) e melhor no colocar porque isso torna mais fcil alterar o programa para trabalhar com outros formatos de dados (onde tabelas no so arquivos). Execute o programa e repare que ele continua funcionando como antes.

Alterando a Consulta
Uma consulta que retorna todos os registros no realmente muito utilizada. A principal funo de consultas restringir os registros retornados a um subconjunto dos dados. Para fazer isso, vamos alterar a propriedade SQL novamente, acrescentando uma clusula where ao final:

select * from Venda where DataVenda

= '08/02/98'

Isso vai retornar todos os registros onde o campo DataVenda tenha o valor '02/08/98', e apenas esses registros. Observe que a data deve ser informada como 'mm/dd/yy' . Execute o programa e veja o resultado. Note que se voc alterar o valor do campo DataVenda, e salvar o registro, o registro vai desaparecer do resultado. Quando o tipo do campo for data ou Caracter a condio deve ser passada entre apstrofos, caso seja um valor numrico especifique somente o nmero. Nota: na sintaxe do SQL, para inserir um texto, voc pode usar " (aspas) ou ' (apstrofos).

Alterando a Consulta Dinamicamente


A consulta como est uma consulta esttica, ou seja, a condio de seleo de registros nunca muda, porque est usando um valor constante, '08/02/98'. Voc pode fazer tambm uma consulta dinmica, e alterar a condio em tempo de execuo.

Delphi 4 Total

244

1997, 1998, 1999 GRIAULE Para fazer isso, vamos alterar a propriedade SQL para incluir um parmetro no lugar da constante '08/02/98'. Um parmetro uma varivel dentro do comando SQL, que voc pode alterar dinamicamente. Altere o SQL para o seguinte:

select * from Venda where DataVenda = :ValorData


Isso cria um parmetro chamado 'valorData'. O que define o parmetro so os dois-pontos antes do nome. Depois de fazer essa alterao, clique Ok. Nota: No deve haver nenhum espao entre o dois-pontos e o nome do parmetro. Agora selecione a propriedade Params e abra o seu editor. O editor de parmetros, que vai aparecer, onde voc define qual o tipo de dados a ser usado pelo parmetro, primeiro deve-se escolher o parmetro e ir no object inspector:

Expande a propriedade Value em type escolha "Date", que ser o tipo de dados do campo , ao confirmar o Object Inspector ira ficar como a figura abaixo:

Notas: Nos parmetros colocamos as datas sendo 'dd/mm/yy', pois, nos parmetros as datas so do tipo date e ao passar para a linguagem SQL o Delphi coloca no formato que o SQL utiliza. Delphi 4 Total 245

1997, 1998, 1999 GRIAULE Em "Value" voc pode, opcionalmente, fornecer um valor inicial para o parmetro, ou marcar a opo "Null Value", que significa que ele comea com o valor nulo, ou vazio. Nesse caso digite "02/08/98" e depois clique Ok. Precisamos de uma interface para alterar o parmetro dinamicamente. Na pgina ) e coloque um controle no formulrio, em Standard, selecione o cone do GroupBox ( qualquer espao vazio. Altere sua propriedade Caption para "Parmetros". Agora crie controles dentro do GroupBox "Parmetros", dentro dele acrescente o componente MaskEdit ( ) , seu funcionamento idntico ao Edit a diferena que ele permite utilizar mscaras. Altere a propriedade Name para mskDataVenda, clique na reticncias da propriedade EditMask e escolha a opo "Date", substitua os '0' por '9', em seguida clique em "Ok", com uso definimos uma mscara para o componente de edio. Acrescente um componente Button e um Label , conforme a figura abaixo:

Chame o boto de 'btnAlterar' e mude a sua propriedade Default para True. No cdigo associado ao 'btnAlterar', alterar os parmetros, e abrir a consulta novamente com os parmetros modificados. Com isso o usurio pode realizar a consulta para qualquer data. Digite o seguinte:

begin try with qryvenda do


Delphi 4 Total 246

1997, 1998, 1999 GRIAULE

begin Close; Params[0].AsDate := strtodate(mskDataVenda.Text); Open; end; except on EConvertError do begin showmessage('Data Invlida!'); mskDataVenda.setfocus; end; end; end;
Como feito uma converso de String para Date, foi feito o tratamento de exceo , pois, se a pessoa informar uma data invlida iremos mostrar a mensagem de erro 'Data Invlida'. A propriedade Params do componente Query um vetor de objetos do tipo TParam, com ndices comeando de zero. Cada um desses objetos tem propriedades como AsString, AsInteger, ... que permitem alterar o valor do parmetro. Execute o programa e veja o que acontece quando voc altera os parmetros. Nota: Outra forma de alterar o parmetro usando a funo-mtodo ParamByName, fornecendo o nome do parmetro em vez de sua posio na lista. Por exemplo, o cdigo abaixo tambm acessa o parmetro valorData: ParamByName('valorDAta').AsDate := strtodate(mskDataVenda.Text);

Alterando Outras Partes da Consulta


Os parmetros permitem que voc substitua constantes dentro da consulta por variveis do programa, mas se voc precisar alterar a estrutura da consulta, precisa alterar a propriedade SQL em tempo de execuo. Essa propriedade uma string list, que pode ser utilizada com os mtodos de string lists j vistos. O exemplo abaixo mostra como mudar a propriedade SQL dinamicamente :

with qryCliente.SQL do begin Clear; Add('select * from Cliente'); Add('where Estado = "' + estado1 + '"'); Add('or Estado = "' + estado2 + '"'); end;

Delphi 4 Total

247

1997, 1998, 1999 GRIAULE Ao abrir o componente QryCliente , a consulta ir mostrar os clientes que pertencem ao intervalo de estados pedidos. No faremos isso neste projeto, e na maioria das vezes isso no necessrio.

Delphi 4 Total

248

1997, 1998, 1999 GRIAULE

Exemplo: Consultando Vrias Tabelas


Tendo os nossos dados sobre clientes, vendas e itens, imagine que precisamos fazer o seguinte: consultar todos os itens vendidos para cada cliente para uma data especfica. Para isso, podemos usar um comando select do SQL envolvendo vrias tabelas, chamado de juno de tabelas.

Consulta com Duas Tabelas


Como no exemplo anterior realizamos uma consulta que mostra as vendas e os cdigos dos clientes, vamos mostrar o nome do cliente, para isto temos que alterar a propridade SQL do componente QryVenda . Como queremos mostrar o nome do cliente temos que utilizar a tabela 'cliente' na clausula from da consulta.Altere a propriedade SQL de acordo o comando abaixo:

select cli.Nome, vend.CodVenda from CLIENTE cli, VENDA vend where cli.CodCliente = vend.CodCliente order by cli.Nome
Notas: Quando o comando Select utiliza mais de uma tabela, o componente Query no permite alteraes dos dados. Note que na clusula from, os nomes das tabelas esto seguidos de nomes mais curtos, que so os apelidos [alias] utilizados para as tabelas dentro do SQL. Esses apelidos afetam apenas o comando atual. A lista de campos do select seleciona o campo Nome da tabela 'cli' (apelido de "CLIENTE.DB") e o campo CodVenda da tabela 'vend' (apelido de "VENDA.DB"). A condio cli.CodCliente = vend.CodCliente na clusula where importante numa juno de tabelas. Ela diz qual a ligao entre elas. Se no for especificada, a consulta vai funcionar, mas vai retornar o produto cartesiano das duas tabelas, ou seja, todas as combinaes possveis com o registro de uma e o registro da outra tabela. A clusula order by determina que o resultado ser ordenado pelo campo Nome da tabela CLIENTE.DB. Coloque a propriedade Active do componente qryVenda para true. Com isso ir aparecer a seguinte mensagem:

Delphi 4 Total

249

1997, 1998, 1999 GRIAULE

Isso ocorre porque antes de fazer a modificao na propriedade SQL , foi criado um objeto de campo para o cdigo do cliente , com a alterao foi retirado o campo, mas como o objeto ainda existe. Ele continua procurando o campo 'codcliente', para resolver o problema clique duas vezes no componente 'qryVenda' para abrir o objeto de campo, remove todos os objetos de campos existentes. Altere a propridade Active para true e observe que cada registro do resultado tem o valor do campo Nome e do campo CodVenda. Existem vrios registros de resultado para cada cliente, ou seja, com o nome do cliente repetido, mas com cdigos de venda diferentes.

Consultando Trs Tabelas


Para adicionar mais uma tabela na consulta, a tabela de itens de venda, vamos alterar o select, acrescentando o nome da tabela e a condio de ligao. Desta vez vamos obter no resultado apenas o campo Nome da tabela de clientes e o campo Quantidade, da tabela de itens. Na propriedade SQL, digite o seguinte:

select cli.Nome, item.Quantidade from CLIENTE cli, VENDA vend, ITEM where cli.CodCliente = vend.CodCliente and vend.CodVenda = item.CodVenda order by cli.Nome
Repare que como so trs tabelas, temos duas condies de juno, uma ligando CLIENTE a VENDA e outra ligando VENDA a ITEM Quando voc altera a propriedade SQL, o componente automaticamente muda a propriedade Active para False, altere para True.

Usando Campos Calculados no SQL


Podemos ainda gerar um campo calculado para cada registro, que ser mostrado no resultado. Uma forma de fazer isso definindo campos calculados e usando o evento Delphi 4 Total 250

1997, 1998, 1999 GRIAULE OnCalcFields. Mas quando se usa componentes Query, outra forma mais fcil usar expresses no SQL. Por exemplo, vamos calcular para cada item, o preo de venda multiplicado pela quantidade, gerando um campo calculado 'PrecoTotal', mas o preo de venda existe na tabela produto, portanto iremos acrescentar tambm a tabela produto. Altere a lista de campos do select para o seguinte:

select cli.Nome, item.Quantidade , prod.precoVenda * item.Quantidade as PrecoTotal from CLIENTE cli, VENDA vend, ITEM, produto prod where cli.CodCliente = vend.CodCliente and vend.CodVenda = item.CodVenda and prod.codproduto = item.codproduto and datavenda =:ValorData order by cli.Nome
Depois da expresso colocado um "as PrecoTotal", que define um nome de campo para a expresso (seno no cabealho do campo vai aparecer a prpria expresso). Altere Active para True novamente e veja o resultado.

Usando Funes de Resumo


Em vez de retornar registros com o nome do cliente repetido, como est sendo feito, voc pode, usando SQL, agrupar vrios registros, retornando um registro de resumo, contendo, por exemplo, o total de algum campo. Para isso, voc deve usar a clusula group by do SQL, alm de funes de resumo do SQL. Por exemplo, para totalizar o produto de 'Quantidade' e 'PrecoVenda' para todos os itens relacionados a cada cliente, basta usar o seguinte comando:

select cli.Nome, sum(item.Quantidade * prod.PrecoVenda) as TotalVenda from CLIENTE cli, VENDA vend, ITEM item, PRODUTO prod where cli.CodCliente = vend.CodCliente and vend.CodVenda = item.CodVenda and prod.codproduto = item.codproduto and datavenda =:ValorData group by cli.Nome
Delphi 4 Total 251

1997, 1998, 1999 GRIAULE

A funo sum uma funo de resumo (ou funo agregada) do SQL, que faz o somatrio de um campo ou expresso. A clusula group by define como so formados os grupos de registros para fazer a totalizao. Outras funes de resumo que podem ser usadas em vez de sum so: avg(campo) max(campo) min(campo) count(campo) count(distinct campo) count(*) calcula a mdia de um campo calcula o valor mximo do campo calcula o valor mnimo do campo conta os valores do campo, mas s considera registros onde o campo est preenchido conta quantos valores distintos do campo existem (em [4 2 2 4 2 3], a contagem seria 3). conta os registros

Delphi 4 Total

252

1997, 1998, 1999 GRIAULE

Outros Comandos SQL


O comando select um comando SQL de consulta, mas existem comandos SQL para atualizao de tabelas, que permitem atualizar diversos registros. Esses comandos so utilizados tambm atravs de um componente Query, mas de uma forma ligeiramente diferente, como veremos.

Testando Comandos SQL


Para executar um comando SQL de atualizao, como os que sero usados, voc pode usar o Database Explorer. Clique em Database|Explore, no menu do Delphi. Na rvore "Databases", abra o alias "CursoDelphi". Ao fazer isso, do lado direito aparece um marcador de pgina "Enter SQL":

Clique em

(Execute Query) para executar o comando.

Alterando Registros
Para alterar valores de registros, use o comando update. Com ele, basta fornecer a tabela, a condio de atualizao e as alteraes de campos a serem feitas. Por exemplo, o comando a seguir atualiza a tabela Cliente, preenchendo o campo Estado, com o valor 'GO', mas apenas nos registros onde Estado era vazio (is null verifica se o campo est vazio):

update Cliente set Estado = 'GO'


Delphi 4 Total 253

1997, 1998, 1999 GRIAULE

where Estado is null

Excluindo Registros
Para excluir um conjunto de registros baseado numa condio, use o comando delete. Por exemplo, o seguinte comando exclui todos os registros da tabela Venda, que estejam entre 01/01/94 e 01/01/95:

delete from Venda where DataVenda >= '01/01/94' and DataVenda <= '01/01/95'
ou, de forma equivalente:

delete from Venda where DataVenda between '01/01/94' and '01/01/95'

Inserindo e Copiando Registros


Para inserir um registro em uma tabela, voc pode usar o comando insert:

insert into Produto (CodProduto, Nome, CodFabricante) values (1234, 'Novo Produto', 34)
Mas geralmente essa forma no tem muita utilidade. Outra forma, que de mais ajuda na programao, permite copiar dados de uma tabela para outra. Para isso, use um comando select dentro do insert. Por exemplo, para copiar todos os registros da tabela Cliente que tem Estado = 'GO' ou 'TO', para uma outra tabela 'ClienteCentroOeste', pode-se fazer:

insert into ClienteCentroOeste select * from Cliente where Estado in ('GO', 'TO') Esse comando assume que ambas as tabelas tm a mesma estrutura. Se no tiverem, voc pode alterar a lista de campos do select para incluir apenas os que esto presentes na tabela de destino, por exemplo: insert into ClienteCentroOeste select Codigo, Nome from Cliente where Estado in ('GO', 'TO')

Delphi 4 Total

254

1997, 1998, 1999 GRIAULE

Executando um Comando de Atualizao


Para usar um comando SQL de atualizao, coloque o comando na propriedade SQL de um componente Query. Mas existe uma diferena em relao ao select: um comando de atualizao no retorna resultado nenhum. Por isso, voc no deve abrir a consulta (alterando Active), e nem ligar o componente com um DataSource, por exemplo. Para executar o comando, voc deve chamar o mtodo ExecSQL do componente. Esse mtodo no retorna resultado e s pode ser acionado em tempo de execuo. Voc pode tambm preencher parmetros do componente antes de executar o comando. Por exemplo, suponha que voc quer apagar todos os registros de VENDA.DB entre uma data inicial e uma data final. Voc pode definir a propriedade SQL com o seguinte:

delete from Venda where DataVenda between :dataIni and :dataFin


e, no programa, executar o cdigo a seguir quando for excluir os itens:

with qryApagaItem do begin ParamByName('dataIni').AsString := editDataIni.Text; ParamByName('dataFin').AsString := editDataFin.Text; ExecSQL; end;

Delphi 4 Total

255

1997, 1998, 1999 GRIAULE

Consultas num Ambiente Cliente/Servidor


Num ambiente cliente/servidor, consultas so a forma mais eficiente de acesso aos dados. Nesse tipo de ambiente, uma consulta envia o comando SQL ao servidor, para ser processado localmente. O servidor ento retorna apenas os registros pedidos. Se voc utilizar um componente Table, voc sempre estar acessando todos os registros, e isso traz as desvantagens que j vimos, de gerar trfego de rede. Voc pode tambm usar expresses em comandos SQL, como vimos nos exemplos. A vantagem que o clculo da expresso feito no servidor, aliviando o processamento na estao, que recebe apenas os resultados. Funes de resumo tambm repassam parte do processamento para o servidor, que vai fazer toda a operao de totalizao e retornar os resultados. Quando voc usa comandos de atualizao, como update, o comando enviado ao servidor, que o processa localmente. Nesse caso, como ele no retorna resultados, o trfego entre a estao e o servidor o mnimo possvel.

Delphi 4 Total

256

1997, 1998, 1999 GRIAULE

Mtodos e Eventos do Componente Query


As classes de componentes TTable ( ) e TQuery ( ) so ambas derivadas de uma classe ancestral comum, chamada TDataSet. Quase todos os mtodos e eventos que vimos para o componente Table se aplicam tambm a um componente Query: Mtodos de abertura e fechamento: Open, Close. Mtodos e propriedades de movimentao: First, Next, Prior, Last, MoveBy, propriedades BOF e EOF. Mtodos de modificao: Edit, Insert, Post, Cancel, Delete. Note que se a consulta no retorna um resultado modificvel, no possvel utilizar esses mtodos, e a propriedade CanModify ter o valor False. Mtodos e propriedades de acesso a campos: FieldByName, propriedade Fields. Mtodos para os controles de dados: EnableControls, DisableControls. Eventos: Before..., After..., OnCalcFields, OnNewRecord.

Delphi 4 Total

257

1997, 1998, 1999 GRIAULE

Captulo 18 Instalador e Alias Local


Usando um Alias Local Criando um Programa Instalador

Delphi 4 Total

258

1997, 1998, 1999 GRIAULE

Usando um Alias Local


Se voc quisesse alterar o diretrio dos dados em tempo de execuo, teria que alterar a propriedade DatabaseName de todos os componentes de dados. Mas, como j vimos, um alias resolve esse problema: ele armazena a localizao do diretrio, evitando que sejam necessrias alteraes no programa. Mas um alias no pode ser criado dinamicamente pelo programa, e no resolve algumas situaes, como por exemplo, um programa que usa um diretrio diferente a cada vez que rodado. Para esse tipo de situao, voc pode usar um alias local. Um alias local funciona apenas dentro do seu programa, enquanto ele est rodando, e pode ser modificado durante a execuo.

Usando o Componente Database


O componente Database da pgina Data Access ( ) permite criar um alias local. No 'FormPrincipal', coloque um componente Database. Mude o seu nome para 'dbVendas'. Esse componente tem vrias propriedades, mas a forma mais fcil de alter-las usando o Database Editor. Clique duas vezes no componente para chamar esse editor. A janela do Database Editor semelhante seguinte:

Em "Name", voc digita o nome do alias local que voc est criando. Depois, se voc escolher um valor da lista "Alias name", seu alias local ser sinnimo para um alias j existente. Seno, voc deve escolher um driver de banco de dados em "Driver name" e alterar seus parmetros de configurao em "Parameter overrides". Repare que "Alias name" e "Driver name" so mutuamente exclusivas. Delphi 4 Total 259

1997, 1998, 1999 GRIAULE No nosso caso, em "Name", digite "VENDAS". Esse ser o nome do nosso alias local. Na lista "Driver name", selecione "STANDARD" e clique no boto "Defaults". Esse boto preenche a lista de parmetros, de acordo com os parmetros de configurao do driver. No caso do driver "STANDARD", usado para bancos de dados locais, s importa o parmetro PATH. A lista vai mostrar uma linha com o parmetro PATH, sem valor definido:

PATH=
Na lista de parmetros, coloque o diretrio atual dos dados depois do parmetro:

PATH=C:\CURSODF\TABELAS
Isso basta para definir o alias local. As outras opes s tem utilidade em bancos de dados cliente/servidor, onde necessrio fornecer uma senha para conectar com o gerenciador de bancos de dados: "Login prompt", se ativo, mostra uma janela que requisita o nome de usurio e senha para conexo. E "Keep inactive connection", se ativado, diz para manter a conexo com o banco de dados mesmo quando ele no estiver sendo usado. Clique Ok e repare que o Database Editor altera vrias propriedades do componente Database, de acordo com as opes escolhidas: DatabaseName fica com o valor "VENDAS", DriverName com o valor "STANDARD", LoginPrompt e KeepConnection com o valor True e Params (do tipo TStrings) com os parmetros. Note que o nome do alias (DatabaseName = "VENDAS") no necessariamente igual ao nome do componente (Name = "dbVendas").

Alterando os Componentes de Dados


Agora, vamos alterar a propriedade DatabaseName de cada um dos componentes Table dos formulrios do projeto. Para comear, no formulrio de fabricantes, selecione o componente 'tblFabricante' e clique na propriedade DatabaseName. O nome do alias local que foi criado, VENDAS, vai aparecer na lista de valores, juntamente com os aliases globais, como CursoDelphi. Selecione VENDAS na lista. Agora no formulrio de produtos, selecione ambos os componentes 'tblProduto' e 'tblFabricante' e altere DatabaseName para VENDAS. Faa o mesmo para todos os formulrios e seus componentes Table ou Query. Execute o programa e verifique que ele ainda continua funcionando. De agora em diante, se voc quiser alterar o diretrio onde esto os dados, basta alterar a propriedade Params do componente 'dbVendas' no formulrio principal, em tempo de projeto. Mas a verdadeira utilidade deste componente permitir alterar a localizao dos dados em tempo de execuo. Delphi 4 Total 260

1997, 1998, 1999 GRIAULE

Alterando o Caminho em Tempo de Execuo


A propriedade Params do componente 'dbVendas', no formulrio principal, contm uma lista de valores de parmetros de configurao. Essa uma propriedade do tipo string list, que pode ser manipulada com os mtodos j vistos para string lists. Vamos alterar o caminho do diretrio dinamicamente, de acordo com o diretrio onde est o programa executvel. Com isso, o programa vai sempre encontrar os dados, desde que os arquivos de dados estejam no mesmo diretrio. No formulrio principal, acrescente no procedimento do evento OnCreate, os cdigos abaixo:

var diretorio: string; begin diretorio := ExtractFilePath(Application.EXEName); dbVendas.Connected := False; dbVendas.Params[0] := 'PATH=' + diretorio + 'tabelas\'; end;
O objeto Application tem a propriedade EXEName, que contm o caminho completo do arquivo executvel. Usamos essa propriedade com a funo ExtractFilePath, para extrair apenas a parte do diretrio. Depois alteramos a primeira linha da propriedade Params, de 'dbVenda', para utilizar esse diretrio. A propriedade Connected do componente Database "ativa" o banco de dados, assim como Active faz para uma tabela. No normalmente necessrio alterar essa propriedade manualmente, porque o componente Table j faz isso automaticamente. Mas num ambiente cliente/servidor, geralmente melhor alter-la no incio da execuo. Para alterar os parmetros, ela deve estar com o valor False, por isso alterada logo no incio. importante notar que o cdigo acima executado antes do cdigo do OnCreate para os outros formulrios. Quando o programa tenta abrir uma tabela que depende de um componente Database, preciso que ele esteja configurado com parmetros vlidos. Execute o programa e veja que ele continua funcionando, desde que os arquivos de dados estejam no mesmo diretrio do executvel. Salve o projeto novamente. Lembre-se: A propriedade Params uma lista de strings (v. cap. 12), por isso pode ser acessada como um vetor onde o primeiro elemento tem o ndice zero.

Delphi 4 Total

261

1997, 1998, 1999 GRIAULE

Criando um programa instalador


Como j foi dito, ao executar um projeto no Delphi, ele cria um programa executvel, um arquivo que pode ser executado independentemente do Delphi. Por exemplo, no nosso projeto anterior (VENDAS.DPR), o programa se chama VENDAS.EXE. Voc pode execut-lo diretamente no Windows. Finalize o Delphi. No Windows, clique em [ ]|Executar... , digite "C:\CURSODF\VENDAS.EXE" e clique Ok. Isso ir executar o programa fora do Delphi. No entanto, preciso uma forma mais amigvel de executar o programa, para que o usurio no precise digitar o nome do executvel. Geralmente, os programas no Windows so executados atravs de atalhos, que muitas vezes ficam no menu . Se voc for copiar esse programa para outro usurio, no precisa do Delphi para execut-lo, mas precisa instalar alguns arquivos do BDE (quando se utiliza bancos de dados). O Delphi (edies Professional e Client/Server) vem com um programa chamado InstallShield Express, para criar programas instaladores. Um programa instalador copia para o computador do usurio o seu arquivo executvel e mais os arquivos que ele precisa utilizar.

Iniciando o InstallShield
O InstallShield trabalha com projetos de instalao [setup projects]. Um projeto de instalao um arquivo contendo um conjunto de opes que definiro o contedo e funcionamento do seu instalador. Para o projeto Vendas, iremos criar um projeto de instalao, que criar disquetes de instalao para o programa. Esses disquetes contm um programa de instalao (SETUP.EXE) e todos os arquivos necessrios ao funcionamento do programa VENDAS.EXE, compactados para ocupar menos espao. Quando voc fornece os disquetes de instalao a um usurio, ele pode executar o programa de instalao, que copia VENDAS.EXE e os outros arquivos necessrios para o computador do usurio e cria um atalho no menu do Windows, para poder executar VENDAS.EXE. ]|Programas, no cone "IS Express Delphi Execute o InstallShield atravs do menu [ 4.0 ". Ao execut-lo, aparece uma tela com trs opes: "Open an existing Setup Project" usado para abrir um projeto de instalao feito anteriormente. "Open your last Setup Project" abre o ltimo projeto de instalao usado (se houver). No nosso caso, use "Create a new Setup Project" para criar um novo projeto de instalao. Agora voc ver a janela New Project, que permite escolher o nome do projeto de instalao e o local onde ele ser salvo. Em "Project Name", digite "VENDAS". Na lista de diretrios, selecione CURSODF, sob o drive C:. Em "New Subdirectory", digite "INSTVEND". Isso ir criar um novo subdiretrio sob CURSODF, para conter os arquivos do projeto de instalao. Finalmente clique no boto Create. O InstallShield criar um novo arquivo, chamado VENDAS.iwz, no diretrio C:\CURSODF\INSTVEND. Delphi 4 Total 262

1997, 1998, 1999 GRIAULE

Gerando os disquetes de instalao


Para instalar o programa em outro computador, voc pode gerar disquetes de instalao a partir do InstallShield. Clique em "Copy to floppy". Para copiar todos os discos, clique em "Copy all disk images". Ou selecione apenas um disco e clique em "Copy selected disk image". Para terminar, clique em File|Save para salvar o projeto de instalao e feche o InstallShield.

Delphi 4 Total

267

1997, 1998, 1999 GRIAULE

A Configurao do BDE
O BDE (Borland Database Engine), o software de acesso a banco de dados do Delphi, tem vrias opes de configurao que podem ser alteradas. Essas opes esto disponveis atravs do utilitrio BDE Administrator. Chame esse utilitrio a partir do menu [ ]|Programas|Borland Delphi 4, no cone "BDE Administrator". A tela dele dividida em duas partes. Do lado direito, a pgina "Databases" mostra os apelidos de bancos de dados, e permite criar, alterar e excluir esses apelidos. A pgina Configuration mostra uma rvore com opes de configurao: Drivers: contm opes dos drivers de bancos de dados, que so os softwares utilizados para acesso aos dados. Os drivers nativos [native] so os que se comunicam diretamente com o BDE. Os drivers ODBC usam o padro ODBC para se conectar a vrios bancos de dados. Ao selecionar um driver, voc pode alterar as opes de configurao dele do lado direito. System: opes de configurao gerais. Se divide em INIT, que tem opes globais usadas ao iniciar uma aplicao e Formats, com os ramos Date, Time, Number, com opes de formatao para datas, horas e nmeros. A maioria dessas opes no precisa ser alterada. Para ver uma descrio rpida de uma opo (na barra de status), clique sobre ela. Para ver ajuda mais detalhada, tecle [F1].

Delphi 4 Total

268

1997, 1998, 1999 GRIAULE

Captulo 19 Relatrios
Conceitos do QuickReport Usando o QuickReport Wizard Criando um Relatrio com Vrias Tabelas

Delphi 4 Total

269

1997, 1998, 1999 GRIAULE

Conceitos do QuickReport
O QuickReport um gerador de relatrios composto de vrios tipos de componentes que trabalham em conjunto. Com ele, voc pode criar visualmente o relatrio, sem se preocupar com detalhes como quebras de pgina, agrupamentos, subtotais etc. Os componentes do QuickReport esto na pgina QReport.

A pgina QReport

QuickRep O componente bsico sobre o qual voc monta os relatrios. Tem a aparncia de uma folha de papel. Como veremos, ele se conecta a um dataset, de onde traz os dados, e permite colocar componentes imprimveis sobre ele, que mostram os dados.

QRSubDetail Faz a ligao do relatrio com outras tabelas, ligadas da forma mestre/detalhe.

QRBand Uma banda uma faixa do relatrio que impressa em determinados momentos. Esse componente permite criar vrios tipos de bandas.

QRChildBand Cria uma banda filha, que sempre impressa aps uma determinada banda mestra. til se uma banda muito grande e se expande, ocupando vrias pginas.

QRGroup Cria um agrupamento de itens dentro do relatrio. Quando um determinado campo muda de valor, uma banda de cabealho de grupo impressa.

QRLabel Funciona como um componente Label, mas para impresso. Imprime o contedo da propriedade Caption.

QRDBText Imprime o contedo de um campo do banco de dados, escolhido atravs das propriedades DataSet e DataField. Pode se expandir verticalmente ou se dividir em vrias pginas se necessrio.

QRExpr Imprime campos calculados e outros itens.

Delphi 4 Total

270

1997, 1998, 1999 GRIAULE

QRSysData Imprime informaes diversas como nmero de pgina, data/hora etc. A propriedade Data define o que ser impresso.

QRMemo Imprime um texto de vrias linhas, que no vem do banco de dados. Pode se expandir verticalmente ou se dividir em vrias pginas se necessrio.

QRRichText Imprime texto formatado, com diferentes fontes, tamanhos e estilos. O texto deve ser definido via programao.

QRDBRichText: Imprime texto formatado, com diferentes fontes, tamanhos e estilos. O texto vem de um campo do banco de dados, determinado pelas propriedades DataSet e DataField.

QRShape Usado para colocar desenhos no relatrio, como linhas, retngulos, crculos etc.

QRImage Imprime uma imagem no relatrio (ex.: o logotipo da empresa).

QRDBImage Imprime uma imagem no relatrio, a partir de um campo do banco de dados, determinado pelas propriedades DataSet e DataField.

QRCompositeReport: Permite agrupar vrios relatrios para imprimir como se fossem um s

QRPreview Usado para ver uma prvia de impresso do relatrio em outra janela.

Construindo o Relatrio
Um relatrio do QuickReport tira seus dados de um dataset principal (tabela ou consulta SQL) e de alguns datasets secundrios, que estejam de alguma forma ligados a ele. A propriedade DataSet do componente QuickRep determina o dataset principal. Funciona como a propriedade DataSet de um componente DataSource do Delphi. O relatrio construdo visualmente a partir de bandas, que so as diversas faixas horizontais e componentes imprimveis, que so colocados nessas bandas. Os relatrios mais simples tm uma banda de cabealho da pgina [page header], uma banda de detalhes [details] e uma banda de rodap [page footer]. Outros mais complexos podem usar outros tipos. Os tipos de bandas so: Delphi 4 Total 271

1997, 1998, 1999 GRIAULE Ttulo [title]: impressa uma nica vez, na primeira pgina do relatrio, aps o cabealho de pgina. Resumo [summary]: impressa uma nica vez, no final da ltima pgina do relatrio. Usada geralmente para os totais gerais. Cabealho de pgina [page header]: impressa no topo de cada pgina. Rodap de pgina [page footer]: impressa na parte inferior de cada pgina. Cabealho de coluna [column header]: impressa no topo de cada coluna. S tem utilidade com relatrios de mltiplas colunas. (Vide propriedade Page.Columns no componente QuickRep). Detalhe [detail]: impressa uma vez para cada registro do dataset Cabealho de grupo [group header]: quando existe um agrupamento de itens, impressa uma vez para cada grupo. Ex.: se um relatrio imprime vendas agrupadas por cliente, um cabealho de grupo impresso para cada cliente, contendo o nome do cliente. Rodap de grupo [group footer]: impressa no final de um grupo de itens. Sub-detalhe [subdetail]: usada em relatrios mestre/detalhe, como veremos mais tarde. Filha [child]: banda que serve como continuao de outra. Usado apenas pelo componente QRChildBand.

Voc pode construir um relatrio posicionando componentes ou

QRBand,

QRChildBand

QRGroup manualmente ou usar a propriedade HasBand do componente QuickRep para criar alguns tipos de bandas automaticamente.

Os componentes imprimveis so colocados sobre as bandas em tempo de projeto e so impressos quando o relatrio impresso. Eles podem conter texto ou imagens fixos (como QRLabel, QRMemo, QRRichText, QRImage, QRShape), ou contedo ligado aos QRDBText, QRDBRichText, QRDBImage) ou QRExpr e

campos do banco de dados (como

ainda contedo varivel, calculado ou determinado pelo relatrio (como QRSysData).

O componente QuickRep visual e aparece num formulrio em tempo de projeto. No entanto, esse formulrio no mostrado ao usurio, mas apenas usado internamente pelo programa. Para imprimir o relatrio, usa-se o mtodo Print do componente. Para ver uma prvia de impresso numa janela, usa-se o mtodo Preview. Delphi 4 Total 272

1997, 1998, 1999 GRIAULE

Usando o QuickReport Wizard


Existem duas formas de criar um relatrio no QuickReport. A forma mais rpida usar o QuickReport Wizard, que cria um relatrio bem simples, com todos os campos de uma tabela. A outra forma desenhar o relatrio, colocando os componentes imprimveis e definindo suas propriedades, o que mais trabalhoso, mas necessrio com relatrios mais complicados. Para o primeiro exemplo, vamos criar um relatrio usando o QuickReport Wizard, com a relao de clientes cadastrados. Agora clique em File|New... O Delphi ir mostrar o repositrio de itens para voc escolher o que quer criar. Clique na pgina "Business", selecione o cone "QuickReport Wizard" e clique Ok. O assistente ir perguntar inicialmente se voc deseja criar um relatrio com os campos de uma tabela, cliqque no boto "Start Wizard" , em seguida qual o diretrio ou alias da tabela e qual o nome da tabela e os campos que deseja mostrar. Selecione "CursoDelphi" na lista superior e depois "CLIENTE.DB" na lista inferior, e selecione os campos "Nome" e "Telefone". Em seguida clique no boto "Finish".

Note que existe um componente Table no formulrio. Altere o seu nome para 'tblCliente' e a sua propriedade Active para True. Mude o Name do formulrio para "FormRelCliente".

Delphi 4 Total

273

1997, 1998, 1999 GRIAULE

Imprimindo o Relatrio
Salve o formulrio com RELCLIENTE.PAS. Retorne ao formulrio principal (formPrincipal), clique duas vezes no menu Relatrio|Clientes e coloque o seguinte comando;

FormRelCliente.QuickRep1.Preview;
Note que 'FormRelCliente' o nome do formulrio que contm o componente QuickReport e 'QuickRep1' o nome desse componente (no foi alterado). Preview um mtodo do componente que mostra uma janela de prvia de impresso. Caso queira imprimeir utilize o mtodo Print.

Para que os comandos acima funcionem, acrescente uma clusula uses no incio da seo de implementao da unidade:

uses RelCliente;
Lembre-se de que 'RelCliente' o nome da outra unidade, que contm o formulrio do QuickReport. Agora execute o programa e teste o funcionamento do relatrio que ser mostrado no vdeo. Note que a janela de visualizao modal _ voc deve fech-la para voltar ao formulrio. Nota: a qualquer momento, se voc quiser ver uma prvia de impresso, basta clicar com o boto direito no componente QuickRep (a folha em branco) e no item "Preview".

Analisando o Relatrio Gerado


Termine a execuo do programa e abra o formulrio 'FormRelCliente'. Vamos ver como funciona esse formulrio bsico. Note que ele possui um componente Table no canto. Esse componente est ligado tabela CLIENTE.DB, do banco de dados CursoDelphi, como foi informado no QuickReport Wizard, na propriedade DataBaseName altere seu contedo para 'Vendas', pois, em todos os formulrios estamos usando o Alias Local . Em vez de uma tabela, poderia ser um componente Query que faz uma consulta SQL. A "folha branca" com linhas horizontais e verticais um componente QuickRep, que o local de desenho do relatrio. Nesse componente, a propriedade DataSet faz referncia a "tblCliente", a tabela usada para os dados do relatrio. Sobre esse componente, so colocadas vrias bandas. A banda "Column Header", logo abaixo, tem um componente QRLabel para cada nome de campo, definindo os cabealhos Delphi 4 Total 274

1997, 1998, 1999 GRIAULE das colunas. Se voc quiser alterar o texto de um deles, clique no componente e altere a propriedade Caption. A banda "Detail", mais abaixo, impressa repetidas vezes, uma para cada registro. Os componentes que esto nesta banda so da classe QRExpr e cada um est associado com um campo da tabela. Em tempo de projeto, o componente mostra o nome do campo entre colchetes. Esta escolha da campo que ser mostrado feito na propriedade Expression , no prximo exemplo iremos ver essa propriedade com mais detalhes. Finalmente, na parte inferior, existe uma banda "Page Footer", impressa no rodap da pgina. Clique na barra de rolagem horizontal, para ver o contedo do formulrio direita. Note que mais direita na banda, existe um componente que mostra "Page". Esse um componente QRSysData, cuja propriedade Data contm o valor 'qrsPageNumber', que o faz mostrar o nmero de pgina automaticamente. Salve o projeto novamente.

Delphi 4 Total

275

1997, 1998, 1999 GRIAULE

Criando um Relatrio com Vrias Tabelas


Agora que j usamos o QuickReport Wizard, veremos como criar um relatrio posicionando os componentes manualmente.Iremos criar um relatrio de vendas de produtos, por cliente, que envolve dados de vrias tabelas: CLIENTE, VENDA, ITEMVEND, PRODUTO. Inicialmente iremos colocar somente a tabela de CLIENTE,depois que estiver mostrando os Clientes, iremos acrescentar as vendas e os itens vendidos. Abra o projeto VENDAS.DPR. Nesse projeto, vamos utilizar o QuickReport para criar um . Altere relatrio de clientes. Crie um novo formulrio, com File|New Form ou o boto o nome do formulrio para 'FormRelVenda'. Agora coloque um componente Table no formulrio e altere suas propriedades para acessar a tabela de clientes: Name: tblCliente DatabaseName: CursoDelphi TableName: Cliente

Agora clique na pgina 'QReport' e selecione o componente QuickRep para colocar no formulrio. Mova-o para o canto superior esquerdo e mude as seguintes propriedades: Name: qrpRelatorio DataSet: tblCliente Agora devemos escolher quais as bandas que sero includas no relatrio. Clique duas vezes no sinal de + da propriedade Bands para ver seus sub-itens. Altere HasPageHeader, HasPageFooter e HasDetail para True. medida que voc altera os valores, novas bandas iro aparecer no relatrio. O formulrio dever ter a seguinte aparncia:

Delphi 4 Total

276

1997, 1998, 1999 GRIAULE

Nota: ou, se preferir, copie o componente Table do formulrio de clientes [Ctrl+C] e cole [Ctrl+V] neste formulrio. Nota: basta clicar duas vezes em DataSet para aparecer o valor. Aumente a largura do formulrio para que ele ocupe a tela inteira, para melhor visualizao. Note que voc pode selecionar uma banda clicando nela com o o mouse. Voc pode aumentar a altura da banda, mas a largura determinada automaticamente baseado no tamanho de pgina. As medidas que aparecem no relatrio so dadas em centmetros, como padro.

Vamos colocar um ttulo do relatrio, coloque um componente QRLabel na banda "Page Header". Altere o Caption para "Vendas por Cliente" e tambm as seguintes propriedades: Font.Size: 20, para aumentar o texto Alignment: taCenter, para centralizar o texto AlignToBand: True, para centralizar o componente em relao banda. Quando voc altera AlignToBand, a posio do componente se altera. Se voc mudar apenas Alignment, apenas a posio do texto em relao ao componente se altera. Agora na banda "Details", iremos mostrar somente o nome do cliente(essa seo ser impressa uma vez para cada cliente). Coloque um componente QRLabel e altere o

Caption para "Nome" e, logo frente dele, um componenteQRDBText( ), com as propriedades DataSet ,selecione "tblCliente" e DataField, selecione o nome do campo, "Nome". Delphi 4 Total 277

1997, 1998, 1999 GRIAULE Nota: para chamar o Object Inspector, se ele no estiver visvel, use a tecla [F11] ou [Enter].

Inserindo um Nmero de Pgina


Voc pode inserir, em qualquer posio do relatrio, um nmero de pgina que ser incrementado automaticamente. Vamos colocar um na banda "Page Footer". Primeiro coloque um componente QRLabel e altere o seu Caption com "Pgina:". QRSysData e coloque direita do rtulo. Altere a Depois selecione o componente propriedade Data, selecionando 'qrsPageNumber'. Vamos colocar tambm outro componente QRSysData para exibir a data e hora de impresso do relatrio. Coloque-o na banda "Page Footer" e altere as seguintes propriedades: Data: qrsDateTime, para mostrar data e hora AutoSize: True, para que o componente aumente de acordo com o contedo dele. Alignment: taRightJustify, para alinhar o texto direita do componente AlignToBand: True, para alinhar o componente direita da banda

Visualizando o Relatrio
Para visualizar o relatrio como ele vai estar quando impresso, altere a propriedade Active do 'tblCliente' para True, clique no componente QuickRep (fora das bandas) com o boto direito e clique na opo Preview do menu. Isso vai mostrar, como antes, a janela de prvia de impresso. Essa janela contm vrios botes de controle. Os trs primeiros permitem escolher a quantidade de zoom: 100 % ou largura da pgina. Quando o relatrio primeira,

tem vrias pginas, podem ser usados botes para navegar entre as pginas: anterior, prxima e

ltima. Voc pode imprimir o relatrio clicando no boto . O boto permite salvar o

ou configurar as opes de impresso com o boto

relatrio num arquivo e permite abrir esse arquivo novamente para visualizar. E o boto Close fecha a janela de visualizao. Desative a tabela (altere Active para False) porque ela ser ativada apenas durante a execuo do programa. Salve o projeto. Quando o Delphi pedir o nome da unidade do novo formulrio, informe "RVenda".

Delphi 4 Total

278

1997, 1998, 1999 GRIAULE

Acrescentando Vrias Tabelas ao Relatrio


Coloque trs componentes Table no formulrio. Para todos eles, altere DatabaseName, selecionando "Vendas". Defina as suas propriedades da seguinte forma: Name TableName VENDA.DB

tblVenda

tblItem

ITEM.DB

tblProduto

PRODUTO.DB

Agora coloque trs componentes DataSource no formulrio e conecte-os aos componentes Table correspondentes: Name DataSet tblCliente

dsCliente

dsVenda

tblVenda

dsItem

tblItem

Conectando as Tabelas
Faremos ligaes mestre-detalhe para relacionar as tabelas. Primeiro vamos conectar 'Venda' a 'Cliente' (um cliente tem N vendas). Clique em 'tblVenda' e altere as propriedades: MasterSource: dsCliente, MasterFields: CodCliente, IndexName: CodCliente. Agora vamos conectar 'ITEM' e 'VENDA'. Clique em 'tblItem' e altere: MasterSource: dsVenda, MasterFields: CodVenda, IndexName: IndVenda. Finalmente, para buscar o nome do produto a partir da tabela ITEM, devemos conectar as duas. Clique em 'tblProduto' e altere: MasterSource: dsItem, MasterFields: CodProduto, IndexFieldNames: CodProduto. A aparncia do relatrio , nesse momento, ser semelhante figura:

Delphi 4 Total

279

1997, 1998, 1999 GRIAULE

Criando Sub-detalhes para Vendas


Quando se tem um relatrio com tabelas mestre-detalhe, a banda "detalhe" se relaciona apenas com a tabela mestra. Para colocar dados das outras tabelas, devemos colocar bandas "sub-detalhes", utilizando o componente QRSubDetail.

Coloque no formulrio um componente QRSubDetail. Ele aparece como uma nova banda, abaixo de "Detail", mas acima de "Page Footer". Vamos mostrar nesse caso os dados da tabela de vendas. Na propriedade DataSet, selecione 'tblVenda'. Mude o nome desse componente para 'qrsubVenda'. Isso vai ajudar a identific-lo mais tarde, como veremos. Nesse componente, a propriedade Master define quem o 'relatrio mestre' para ele, que determina quando ele ser impresso. Note que a propriedade Master nesse caso foi definida como 'qrpRelatorio', que o nome do componente QuickRep. Deixe-a como est. Coloque na banda sub-detail um componente QRLabel, com o texto "Cdigo Venda:". Na frente coloque um componente QRDBText, com DataSet: tblVenda e DataField: CodVenda. Aps os dois, coloque mais um QRLabel, com o texto "Data Venda:" e um QRDBText, com DataSet: tblVenda e DataField: DataVenda. Destaque os rtulos em negrito. O resultado ficar como o seguinte:

Delphi 4 Total

280

1997, 1998, 1999 GRIAULE Se quiser, use o Preview para visualizar o relatrio (tblVenda deve estar ativo). Note que primeiro impressa a seo 'Detail', com os dados do cliente, depois impressa vrias vezes a seo Sub-detail, contendo as vendas efetuadas. Por exemplo: Cliente: Primeiro Cdigo Venda:101 Cdigo Venda:102 Cdigo Venda:105 Cliente: Segundo Cdigo Venda:107 Cdigo Venda:108 Cdigo Venda:110 Cliente: Terceiro Cdigo Venda:107 Cdigo Venda:108 ........ Data Venda: 20/07/97 Data Venda: 30/07/97 Data Venda: 20/07/97 Data Venda: 30/07/97 Data Venda: 30/08/97 Data Venda: 04/07/97 Data Venda: 05/07/97 Data Venda: 13/07/97

Criando Sub-detalhes para Itens de Venda


Agora, para cada venda, devemos imprimir os itens de venda correspondentes a eles. QRSubDetail no relatrio, que vai aparecer Para isso, coloque mais um componente abaixo da banda de vendas. Altere as seguintes propriedades: Name: qrsubItem DataSet: tblItem Master: qrsubVenda A propriedade Master deve ser alterada, para dizer que essa banda sub-detalhe estar subordinada banda 'qrsubVenda', criada anteriormente ,ou seja, para cada registro de venda impresso, sero impressos vrios registros de itens de venda. Agora, para essa banda, vamos criar um cabealho de grupo e um rodap de grupo. Um cabealho de grupo uma banda impressa antes de todos os registros do grupo (no caso, todos os itens de uma determinada venda) e um rodap de grupo impresso aps todos os registros do grupo. O cabealho ser usado para mostrar os nomes de campos e o rodap ser usado para mostrar um total geral. Delphi 4 Total 281

1997, 1998, 1999 GRIAULE Clique na propriedade Bands desse componente e expanda seus sub-itens. Altere os dois, HasHeader e HasFooter, para True. Isso vai criar as bandas de cabealho e rodap de grupo, acima e abaixo do 'sub-detail'. Clique na banda "Group Header". Na propriedade Font, clique no boto de reticncias, selecione "Negrito" e clique Ok. Com isso, todos os componentes colocados nessa banda ficaro em negrito. Coloque quatro rtulos de texto (QRLabel), alterando o Caption em cada um com os textos "Produto", "Quantidade", "Preo Unitrio" e "Preo Total". Deixe um espao maior entre "Produto" e "Quantidade". Agora clique na banda "sub-detail", abaixo do "Group Header" novamente. Vamos mostrar aqui o nome do produto (campo Nome de tblProduto), a quantidade vendida (campo Quantidade de tblItem) e o preo de venda (campo PrecoVenda de tblItem). O preo total um campo calculado, que ser colocado mais tarde. Coloque trs componentes QRDBText, debaixo dos rtulos correspondentes e defina suas propriedades da seguinte forma: DataSet tblProduto tblItem tblItem DataField Nome Quantidade PrecoVenda

O resultado, visualmente, ser o seguinte:

Se desejar, clique com o boto direito no relatrio e depois em Preview(Para funcionar todas as tabelas tem que estar com a propriedade Active = True). Alguns detalhes ainda precisam ser acertados, como a formatao dos campos.

Formatando os Campos
Para melhorar a aparncia do relatrio, vamos mostrar os campos "Quantidade" e "PrecoVenda" alinhados direita e "PrecoVenda" formatado como um valor monetrio. Clique no componente QRDBText que mostra "[Quantidade]". Altere a propriedade AutoSize para False. Quando AutoSize True, ele muda de tamanho de acordo com o contedo. Posicione-o alinhado direita de acordo com o rtulo e mude a propriedade Alignment para 'taRightJustify'. Delphi 4 Total 282

1997, 1998, 1999 GRIAULE Selecione o componente "[PrecoVenda]" e faa o mesmo: AutoSize=False e Alignment=taRightJustify. Alm disso, altere a propriedade Mask, colocando o texto "#,0.00". Essa propriedade tem o mesmo efeito de DisplayFormat para campos da tabela, como j foi visto. Agora visualize novamente a prvia de impresso. Note que os campos aparecem formatados corretamente.

Criando um Campo Calculado


Voc pode criar campos calculados no QuickReport, usando o componente QRExpr. Com ele, voc pode digitar uma expresso qualquer, envolvendo campos da tabela. Voc no precisa escrever cdigo de programa para fazer o clculo. Vamos usar esse componente para calcular o "Preo Total" do item, que PrecoVenda * Quantidade. Coloque no formulrio um componente QRExpr logo abaixo do rtulo "Preo Total". Clique na propriedade Expression, que define a frmula de clculo do campo e clique duas vezes no boto de reticncias. Voc ver uma janela onde poder montar uma expresso de clculo.

Clique no boto "Database Field", na lista "Select dataset", a tabela 'tblItem', que contm os valores a serem calculados. Os campos da tabela aparecem na lista abaixo do nome. Clique em 'Quantidade', em seguida pressione o boto 'OK'. No quadro de texto na parte superior da janela, aparece 'tblItem.Quantidade'. Agora, clique no boto com o sinal de multiplicao, [*]. Um sinal * ser inserido no texto da frmula. Para terminar, clique novamente em "Database Field", escolha a tabela 'tblProduto' e o campo 'PrecoVenda'. Delphi 4 Total 283

1997, 1998, 1999 GRIAULE A frmula final aparecer como na figura:

A frmula de clculo do campo, portanto, 'tblItem.Quantidade * tblProduto.PrecoVenda'. Agora clique Ok para retornar ao formulrio. Para visualizar esse componente melhor, altere a propriedade AutoSize para False e reduza a largura do componente de acordo com o rtulo na parte superior. Altere tambm as propriedades: Alignment: taRightJustify e Mask: "#,0.00", como foi feito antes para o preo de venda. Se voc usar o comando Preview novamente, ver que o campo calculado mostrado corretamente para cada registro.

Criando um Sub-total
Agora vamos totalizar o campo calculado criado, para mostrar o total de vendas para cada cliente. Selecione o componente QRExpr, que foi criado para calcular o preo total. Tecle [Ctrl+C] para fazer uma cpia dele. Clique na banda "Group Footer" e tecle [Ctrl+V] para trazer essa cpia. Na propriedade Expression, faa uma alterao manual (no clique no boto de reticncias, pois seria mais complicado). Onde est o valor atual:

tblItem.PrecoVenda * tblItem.Quantidade
substitua por:

SUM(tblItem.PrecoVenda * tblItem.Quantidade)
Delphi 4 Total 284

1997, 1998, 1999 GRIAULE

A funo SUM calcula o somatrio de uma expresso. Mas preciso tambm informar qual o conjunto de registros sobre os quais essa soma ser efetuada. No nosso caso, ser para os itens de cada venda. Para definir o escopo da soma, usada a propriedade Master do componente. Essa propriedade faz referncia a uma banda que define quando o somatrio ser atualizado. Quando essa banda for impressa, o componente atualiza internamente o total, antes de imprimir. No nosso caso, em Master, selecione 'qrsubItem', que a banda que contm os itens de venda. Com isso, a cada item de venda impresso, o componente acumular internamente o seu total. Altere tambm a propriedade ResetAfterPrint para True. Se ela for False, o componente continua acumulando o total at o fim da impresso. Quando ela True, o componente zera o seu acumulador depois de impresso. Para dar mais destaque ao sub-total, coloque-o em negrito. Agora coloque esquerda desse componente um QRLabel, com o texto "Total da venda" e em negrito. Use o comando Preview para visualizar o relatrio. Note agora que o sub-total ser impresso aps os itens de venda.

Chamando o Relatrio a Partir do Menu


Agora que o relatrio est pronto, faremos com que ele seja chamado a partir do menu principal, no item de menu Relatrios|Vendas. Mas antes vamos criar um procedimento no formulrio do relatrio para facilitar a sua chamada. Na unidade "RVendas", encontre a classe de formulrio (TFormRelVendas). Dentro da seo public, acrescente a seguinte declarao de procedimento:

procedure VisualizarRelatorio;
Agora, no comeo da seo implementation, acrescente o corpo do procedimento:

procedure TFormRelVenda.VisualizarRelatorio; begin {abrir todas as tabelas usadas} tblCliente.Open; tblVenda.Open; tblItem.Open; tblProduto.Open; {visualizar o relatrio} qrpRelatorio.Preview; {fechar todas as tabelas usadas}
Delphi 4 Total 285

1997, 1998, 1999 GRIAULE

tblCliente.Close; tblVenda.Close; tblItem.Close; tblProduto.Close; end;


Abra a unidade do formulrio principal, VENDPRIN.PAS. Para poder chamar o outro formulrio, clique em File|Use unit... e selecione "RVenda" para acrescentar a unidade na clusula uses. No formulrio, clique no item de menu Relatrios|Vendas. Coloque os seguinte comando:

FormRelVenda.VisualizarRelatorio;
Execute o programa e clique em Relatrios|Vendas. O programa mostrar a janela de prvia de impresso, como j foi visto. Salve o projeto novamente.

Delphi 4 Total

286