Escolar Documentos
Profissional Documentos
Cultura Documentos
Delphi 4 Total
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
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
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
Estruturas de Laos_______________________________________________________________ 53
O comando for __________________________________________________________________________53 O comando while...do... ___________________________________________________________________54 O comando repeat..until ___________________________________________________________________54
Unidades Associadas e Independentes________________________________________________ 90 Compilao de Unidades___________________________________________________________ 91 Usando uma Unidade _____________________________________________________________ 92 Resolvendo Conflitos de Nomes _____________________________________________________ 94 Arquivo de Projeto _______________________________________________________________ 95
1997, 1998, 1999 GRIAULE Testando o Programa ____________________________________________________________________108 Salvando o Projeto ______________________________________________________________________108
Funes________________________________________________________________________ 123
Criando uma Funo_____________________________________________________________________123 Retornando um Valor ____________________________________________________________________123 Chamando a Funo _____________________________________________________________________124
1997, 1998, 1999 GRIAULE Propriedades da String List________________________________________________________________140 Mtodos da String List ___________________________________________________________________140 Criando String Lists Independentes _________________________________________________________141
Resumo dos Componentes de Dados ________________________________________________ 165 Apelidos de Bancos de Dados ______________________________________________________ 166
Exemplo: Criando formulrio sem utilizar o dbNavigator ______________________________ 218 Tratamento do Erro 'Key violation.' ________________________________________________ 224 Usando um Controle DBLookupComboBox__________________________________________ 225
Consultas num Ambiente Cliente/Servidor___________________________________________ 256 Mtodos e Eventos do Componente Query ___________________________________________ 257
Delphi 4 Total
Delphi 4 Total
Delphi 4 Total
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:
Delphi 4 Total
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
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
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:
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
ListBox1.Sorted := True;
Finalmente retorne ao formulrio, selecione o boto Limpar e siga o mesmo processo. Digite o seguinte cdigo:
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
Delphi 4 Total
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.
Delphi 4 Total
10
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
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.
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
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:
Delphi 4 Total
14
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
Delphi 4 Total
16
Delphi 4 Total
17
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
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
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.
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.
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 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.
Delphi 4 Total
22
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"
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
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
Delphi 4 Total
25
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
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:
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:
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
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
Delphi 4 Total
31
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
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
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:
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):
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:
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:
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:
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:
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:
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
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):
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
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:
Delphi 4 Total
39
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:
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
Delphi 4 Total
41
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;
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):
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
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;
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;
Delphi 4 Total
45
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:
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
angulo := PI*graus/180;
Mas no so variveis, portanto no podem receber outro valor:
Delphi 4 Total
47
Delphi 4 Total
48
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
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 ((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
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
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:
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 := 'Z' downto 'A' do ... for valor := 20 downto 1 do ...
Note que o incremento ou decremento sempre 1. Delphi 4 Total 53
O comando while...do...
O lao while repete um comando enquanto determinada condio verdadeira. Sua sintaxe de forma geral :
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 :
Delphi 4 Total
54
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:
Delphi 4 Total
55
Delphi 4 Total
56
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.
Delphi 4 Total
58
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
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
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 }
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.
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.
Delphi 4 Total
69
Delphi 4 Total
70
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
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:
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:
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 :
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
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
Delphi 4 Total
74
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"(
Delphi 4 Total
75
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
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.
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:
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:
Delphi 4 Total
79
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
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.
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
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
Delphi 4 Total
84
Delphi 4 Total
85
Delphi 4 Total
86
unit Execprin; interface { itens visveis externamente } ... implementation { itens para uso interno } ... end.
Delphi 4 Total
87
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
Com a palavra end, termina a definio da classe. Depois o Delphi acrescenta uma declarao de varivel para o formulrio.
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
Delphi 4 Total
90
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
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
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
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
Delphi 4 Total
97
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:
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:
Delphi 4 Total
99
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:
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}
1997, 1998, 1999 GRIAULE testado, quando for gerar a verso final, desative essa opo para aumentar a eficincia da execuo.
Delphi 4 Total
101
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:
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.
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
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:
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:
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
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
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:
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
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
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:
{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
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:
Delphi 4 Total
111
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.
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.
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.
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.
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.
Threads
Modules
CPU
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
Delphi 4 Total
116
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.
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
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.
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
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.
uses Geral;
Execute o programa e ele dever funcionar como antes. Salve o projeto novamente.
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.
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.
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
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.
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
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 := 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:
Delphi 4 Total
124
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:
Delphi 4 Total
125
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
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
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
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
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.
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.
Delphi 4 Total
132
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 AbrirFormulario;
E o corpo do procedimento, com os seus comandos, seria colocado na parte implementation, por exemplo:
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
Variveis de Objeto
Uma varivel de objeto declarada utilizando o nome da classe como um tipo de dados, como j vimos:
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
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:
Delphi 4 Total
139
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.
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:
Para procurar um elemento na lista, usa-se IndexOf. Se o elemento no for encontrado, retorna -1. 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:
var lista: TStringList; begin lista := TStringList.Create; lista.Sorted := True; lista.Add('Curso'); lista.Add('Delphi'); lista.Delete(0);
Delphi 4 Total 141
Delphi 4 Total
142
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:
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:
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
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
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 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
Delphi 4 Total
149
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
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
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
Delphi 4 Total
153
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.
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.
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
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.
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
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.
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
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
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
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
Delphi 4 Total
169
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 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.
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".
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.
Campo
Tipo
Tamanho
Chave
Delphi 4 Total
173
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
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
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
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].
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
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):
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
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.
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
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
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".
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".
Delphi 4 Total
185
Delphi 4 Total
186
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:
'''';
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
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
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:
Delphi 4 Total
189
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:
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
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
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
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
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
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.
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.
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
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
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
Delphi 4 Total
204
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
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.
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:
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:
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
Delphi 4 Total
209
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
tblCliente.Refresh;
Esse mtodo chamado automaticamente pelo boto do DBNavigator.
Delphi 4 Total
213
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
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:
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:
editData.Text := DateToStr(Date);
Delphi 4 Total 217
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
Delphi 4 Total
219
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:
1997, 1998, 1999 GRIAULE No procedimento do evento OnClick do boto spbPrimeiro 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
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
Uses
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
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:
Delphi 4 Total
226
Delphi 4 Total
227
Delphi 4 Total
228
Agora clique em Next e depois no boto "Finish". O formulrio ser adicionado com as opes definidas.
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:
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 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"
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.
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:
Delphi 4 Total
235
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
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
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.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
Delphi 4 Total
241
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
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.
Delphi 4 Total
243
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:
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:
= '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).
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:
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 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);
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
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
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.
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.
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.
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
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
Clique em
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):
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:
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
Delphi 4 Total
255
Delphi 4 Total
256
Delphi 4 Total
257
Delphi 4 Total
258
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").
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
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
Delphi 4 Total
267
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
Captulo 19 Relatrios
Conceitos do QuickReport Usando o QuickReport Wizard Criando um Relatrio com Vrias Tabelas
Delphi 4 Total
269
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.
Delphi 4 Total
270
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.
QRDBImage Imprime uma imagem no relatrio, a partir de um campo do banco de dados, determinado pelas propriedades DataSet e DataField.
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.
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
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
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
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".
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
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
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].
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
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
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
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
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
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.
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
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
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.
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
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