Apostila

Delphi 4.0

Capítulo 1
CAPÍTULO 1 ..............................................................................................................................................2 CAPÍTULO 01 - INICIANDO O DELPHI...............................................................................................8 ......................................................................................................................................................................8 PRINCÍPIOS DA PROGRAMAÇÃO WINDOWS ................................................................................................9 INICIANDO O DELPHI ...............................................................................................................................10 CRIANDO UM PRIMEIRO PROGRAMA........................................................................................................12 Propriedades do Formulário ..............................................................................................................12 Colocando Componentes ....................................................................................................................12 Alterando as Propriedades dos Componentes ....................................................................................13 Respondendo a Eventos ......................................................................................................................13 Testando o Programa .........................................................................................................................14 Salvando o Programa .........................................................................................................................14 AMBIENTE DE PROGRAMAÇÃO ................................................................................................................14 Programação Orientada a Objeto (POO) ..........................................................................................14 EVENTOS E PROCEDIMENTOS...................................................................................................................14 COMPONENTES ........................................................................................................................................15 Visão Geral dos Componentes............................................................................................................15 PROPRIEDADES ........................................................................................................................................16 MÉTODOS ................................................................................................................................................16 OBJECT PASCAL E BIBLIOTECAS ..............................................................................................................17 VCL - VISUAL COMPONENT LIBRARY .....................................................................................................17 OBJETOS ..................................................................................................................................................17 RESUMO ..................................................................................................................................................17 PROJETOS ................................................................................................................................................17 Salvando o Projeto em Disco..............................................................................................................18 Comandos para trabalhar com Projetos ............................................................................................18 GRUPOS DE PROJETOS .............................................................................................................................19 Comandos para tabalhar com grupos de projetos..............................................................................19 EDIÇÕES DO DELPHI ................................................................................................................................19 CAPÍTULO 3 EXEMPLOS ADICIONAIS............................................................................................21 EXEMPLO: CALCULADORA ......................................................................................................................22 Criando os Componentes....................................................................................................................22 Tratando os Eventos ...........................................................................................................................23 Executando o Programa .....................................................................................................................24 Melhoras de Interface .........................................................................................................................24 Salvando o Projeto..............................................................................................................................24 CAPÍTULO 4 VARIÁVEIS E TIPOS DE DADOS ...............................................................................25 TIPOS DE DADOS......................................................................................................................................26 Tipos Numéricos .................................................................................................................................26 O tipo Char .........................................................................................................................................27 O tipo String .......................................................................................................................................27 O tipo Boolean ....................................................................................................................................28 O tipo TDateTime ...............................................................................................................................28 FUNÇÕES DE CONVERSÃO........................................................................................................................29 OPERAÇÕES ARITMÉTICAS ......................................................................................................................29 TIPOS ORDINAIS ......................................................................................................................................30 ESCOPO DE VARIÁVEIS ............................................................................................................................31 Variáveis Locais .................................................................................................................................31 Variáveis Globais da Unidade............................................................................................................31 Variáveis Globais do Projeto..............................................................................................................31

2

CONSTANTES ...........................................................................................................................................31 CAPÍTULO 5 ESTRUTURAS DE CONTROLE ..................................................................................33 INSERINDO COMANDOS COM O CODEINSIGHT ..........................................................................................34 ESTRUTURAS DE DECISÃO .......................................................................................................................34 O Comando if...then...else...................................................................................................................34 O Comando case...of...........................................................................................................................35 ESTRUTURAS DE LAÇOS...........................................................................................................................37 O comando for ....................................................................................................................................37 O comando while...do... ......................................................................................................................37 O comando repeat..until .....................................................................................................................37 OUTROS COMANDOS ...............................................................................................................................38 Comandos para sair de laços .............................................................................................................38 O comando exit ...................................................................................................................................38 CAPÍTULO 6 PROPRIEDADES E EVENTOS COMUNS..................................................................39 TIPOS DE PROPRIEDADES .........................................................................................................................40 PROPRIEDADES MAIS USADAS .................................................................................................................41 Propriedades para Todos os Componentes ........................................................................................41 Propriedades de Tamanho e Posição .................................................................................................41 Propriedades do Formulário ..............................................................................................................41 Propriedades de Controles .................................................................................................................42 EVENTOS COMUNS ..................................................................................................................................43 Eventos de Mouse ...............................................................................................................................43 Eventos de Teclado .............................................................................................................................43 Eventos do Formulário .......................................................................................................................44 Outros Eventos....................................................................................................................................44 DETALHES DO TRATAMENTO DE EVENTOS ..............................................................................................45 Tratando um Evento para Vários Controles: OnKeyPress.................................................................45 Renomeando um Procedimento de Evento..........................................................................................45 Associando um Procedimento Existente .............................................................................................46 Eliminando um Procedimento de Evento............................................................................................46 CAPÍTULO 7 USANDO VÁRIOS FORMULÁRIOS...........................................................................47 CAIXAS DE DIÁLOGO ...............................................................................................................................48 FUNÇÕES DE MENSAGEM.........................................................................................................................48 Mensagens Informativas .....................................................................................................................48 Mensagens de Confirmação................................................................................................................48 EXEMPLO: CALCDATA ............................................................................................................................49 Pedindo Confirmação ao Usuário ......................................................................................................50 Criando um Novo Formulário ............................................................................................................50 Salvando o Projeto..............................................................................................................................51 Executando um Arquivo......................................................................................................................51 GERENCIANDO OS ARQUIVOS DO PROJETO ..............................................................................................52 Usando a Speedbar ou Menus ............................................................................................................53 Usando o Project Manager.................................................................................................................53 DEFININDO O FORMULÁRIO PRINCIPAL ...................................................................................................56 CAPÍTULO 8 ESTRUTURA DAS UNIDADES ....................................................................................57 ESTRUTURA GERAL DAS UNIDADES ........................................................................................................58 O CÓDIGO GERADO PELO DELPHI ............................................................................................................58 Seção de Interface...............................................................................................................................58 UNIDADES ASSOCIADAS E INDEPENDENTES.............................................................................................59 COMPILAÇÃO DE UNIDADES ....................................................................................................................60 USANDO UMA UNIDADE ..........................................................................................................................60 RESOLVENDO CONFLITOS DE NOMES ......................................................................................................62 CAPÍTULO 9 OUTROS TIPOS DE DADOS E DEPURAÇÃO ..........................................................63 TIPOS ENUMERADOS................................................................................................................................64

3

............................................................................................................65 Verificação de Faixa para Vetores .......................................................................................................................................................................................................................................................................................................................................................................................................................................................................................80 Tipos de Passagem.......................................................................................................83 CLASSES E OBJETOS ........................................................................................68 Declarando o Vetor ............................................79 PASSAGEM DE PARÂMETROS ............................................................84 Hierarquia de Classes do Delphi..............................................................................................................................................................................................................................................................................................................70 CONJUNTOS ......................................................................................................................................................................................................................................................................................................................................................................................73 Monitorando o Valor de uma Variável Dinamicamente ....77 Gerenciando um Projeto com Unidades Independentes .................................................................................................65 VETORES ......................................................................................................................................................76 UNIDADES INDEPENDENTES.............................................................................................................................78 FUNÇÕES ............................................................................................................................................................74 Outras Ferramentas de Depuração ......................................................................................................................................................................................................................................................................65 Vetores Estáticos...................................................................................................................................................................................79 Retornando um Valor....................................................................................................................................................................................................................................................................................................................................................................................................................................................................76 Criando um Procedimento Geral.....................................................79 Chamando a Função.........................................................................................................................................................................69 Salvando o Projeto..................................................74 10 ................80 CAPÍTULO 11 OBJETOS .................................................87 4 ..72 Executando Passo a Passo..............................................................................................................................................................................................................................................................................................70 Verificando Elementos ..............83 HERANÇA .......................................................................................66 Usando Outros Tipos de Índice .............................................64 TIPOS FAIXA ............................................................................................................................87 VARIÁVEIS DE OBJETO ..............................................................................................................................................................86 A Classe de Formulário ......................69 Testando o Programa ..80 Declaração de Parâmetros e Argumentos ..........................................................................................75 PROCEDIMENTOS GERAIS ...............................................................84 Simplificando o Acesso aos Campos.........84 FORMULÁRIOS COMO OBJETOS ...........68 Limpando a Lista ......................................................................................................................................................................................77 Usando a Unidade no Mesmo Projeto ............................................................................77 Transferindo o Procedimento ..............................................................................................................................................................................72 Executando Até o Cursor ..........................................................................................................................................66 Vetores Dinâmicos....67 EXEMPLO: CÁLCULO DE MÉDIA ..................................................................................................................................................65 Opção "Range Checking" .............................................................................................................................76 Criando uma Unidade Independente ........................................................................................................................................................................................................................................................................................................................PROCEDIMENTOS E FUNÇÕES.........................................................................71 DEPURAÇÃO ......................79 Criando uma Função .................................67 Vetores Multidimensionais....................................................77 Usando a Unidade em Outros Projetos ..................................84 O Object Browser ...........................................................Operações com Ordinais .........................72 Vendo Valores de Variáveis...................................................................................................................................86 Procedimentos na classe de formulário..........................................................78 Criando uma Biblioteca de Rotinas ..........................................................70 Propriedades de Conjunto .........................................................................................................................73 Forçando a Finalização do Programa .............................69 Calculando a Média dos Elementos.......................................................................68 Adicionando um Elemento ....................................................70 Operações com Conjuntos ........................................................................................................82 O QUE CONTÉM UM OBJETO.....................64 Tipos Enumerados no Delphi.............................................................................72 Colocando um Ponto de Parada..................................................................................................

.....................................................111 ALTERANDO O MENU PRINCIPAL...........................................................................................................................................................ALTERANDO .......................................................................................................................................................................................................................................................................102 RESUMO DOS COMPONENTES DE DADOS .....................................................................................................................................................................................116 EXEMPLO: CLIENTE POR ESTADO ...............................91 O Objeto Screen....................................................................107 Criando a Tabela "Venda"......................................................................122 5 ........107 Criando Integridade Referencial .......................................................................................101 Criando um Formulário para Acessar a Tabela com Form Wizard..........................................................................................................................................................................101 Criando um campo autoincremento.............................................................................................................................................................................................................................................................................................................103 CAPÍTULO 13 RECURSOS ADICIONAIS ..........................................................................................................................................................................................112 Acrescentando os formulários anteriores ............................................................................................................................................................................................................99 EXEMPLO: USANDO O DATABASE FORM WIZARD ....................................................................................................................................................112 Alterando Propriedades..............................................................................91 O Objeto Application ..................................................112 USANDO O CONTROLE DBGRID ..............................................................108 CRIANDO O MENU PRINCIPAL..........................................................99 Entrando com Dados ...............................................................................................................................................97 FORMATOS DE BANCOS DE DADOS ...............................................................................................................................................................................................................................................................101 Testando o Programa ....112 Associando os formulários aos itens de menu .............................98 Definindo um Diretório de Trabalho ......................................90 OBJETOS PREDEFINIDOS ..............................113 Manipulando dados no DBGrid............................................90 Propriedades da String List ........................................................................................................................................113 Criando os Componentes de Dados..........................................................................................................................................................................................................98 Definindo a Estrutura dos Campos..............92 CODE EXPLORER .............................................................90 Métodos da String List ........................................................................107 Criando a tabela Fornecedores ...........................................................................107 Criando a Tabela de Itens.........................................................................92 PROGRAMAÇÃO ORIENTADA A OBJETOS ....................................................................................109 Tratando Eventos de Menus......................................................................................................................................................................................................................................................................................................90 Criando String Lists Independentes.......................................................................................................................................................................................................113 Usando o Editor de Campos ...................................................................................................................................................................................................................................................................................................................................................................................LISTAS DE STRINGS ..............114 Alterando a Máscara de Edição ..............................................................................118 Validando Registros.............114 CAPÍTULO 14 VALIDAÇÃO E PESQUISAS ....................................97 CRIANDO TABELAS................................................................117 VALIDAÇÃO DE CAMPOS E REGISTROS ..........................................................................................................................91 O Objeto Clipboard ....................109 O MenuDesigner: criando menus ..........................................................................................117 EXEMPLO: CLIENTES ..................................120 TRATAMENTO DE EXCEÇÕES ............................................................................................................................................................................................98 Salvando a Tabela ...................................................................................................................................................................................................................................................................................................................................................................................................................95 TERMOS USADOS .............................................................118 Validando Campos...............................................................................................................................................................................................................111 Teclas de Acesso e Teclas de Atalho.......................................................................106 Criando um Índice Secundário ......................................121 Visualizando Informações sobre Exceções ......................106 Reestruturando a Tabela "Cliente".........93 CAPÍTULO 12 APLICAÇÕES DE BANCO DE DADOS ...................................105 DEFININDO TABELAS ..........................................................122 Classes de Exceções......102 Salvando o Projeto......................102 APELIDOS DE BANCOS DE DADOS ................................................................................................96 DESKTOP X CLIENTE/SERVIDOR ...............

..............................................................................................................................................132 Outros Métodos...................124 BLOCOS PROTEGIDOS ...........................157 Usando Campos Calculados no SQL...........................................................................................................128 Métodos de Abertura e Fechamento .........................................................................146 Criando Controles de Dados .....134 Eventos do Componente Table.144 Analisando o Formulário....................................................................................145 Salvando o Projeto..................................................................................................................................................................................................................................................................................................................158 Testando Comandos SQL...............................................................................................................................................................................................................................146 Criando Campos Calculados....................................................................................................................................................143 Testando o Formulário Gerado ....................131 Acrescentando Registros................................................................................................................................................................................................................................................................................................................................................................................................................................................................129 MÉTODOS PARA MODIFICAR DADOS ...........................137 TRATAMENTO DO ERRO 'KEY VIOLATION.............' ............................................................................................................................................122 Adicionando um DBGrid ...................................................................................................................................................144 Alterando Propriedades do Formulário .....................131 Excluindo Registros .................................158 Excluindo Registros ......................................................................................................................................................................................................155 EXEMPLO: CONSULTANDO VÁRIAS TABELAS ..................................157 Usando Funções de Resumo ..............................................................................................................................................................157 OUTROS COMANDOS SQL ............145 USANDO TRÊS TABELAS NO FORMULÁRIO ...........................................................131 Editando Registros.......................................................................................................................................140 USANDO UM CONTROLE DBLOOKUPCOMBOBOX ............................................................132 EVENTOS DOS COMPONENTES DE DADOS .........................152 Criando o Formulário ..................................................................................134 MANIPULAÇÃO DE DATAS .......................126 ESTADOS DE UMA TABELA ............................................................................................................................................152 Obtendo um Resultado Modificável ....153 Simplificando o Select......................159 Executando um Comando de Atualização...............124 Pesquisando pelo Código ...................................................156 Consulta com Duas Tabelas ........................125 CAPÍTULO 15 ACESSO S/ CONTROLE DE DADOS ..........................................................................................................................149 CAPÍTULO 17 CONSULTAS E SQL ..........................................................................................................................................................................156 Consultando Três Tabelas ...........................158 Alterando Registros ..........................................................................................................................................................................................................................................................................................159 Inserindo e Copiando Registros...................................................153 Alterando a Consulta Dinamicamente ...............................................................................................................146 Ligando os Componentes de Dados..............................................159 6 ..................................140 CAPÍTULO 16 UTILIZANDO MESTRE/DETALHE ..........................................................................123 Pesquisando pelo Nome.......................................................................................................128 Métodos para Percorrer Registros ...............................................................................................................................................................................................................................153 Alterando Outras Partes da Consulta........................................................................................................................................................135 EXEMPLO: CRIANDO FORMULÁRIO SEM UTILIZAR O DBNAVIGATOR.............................................................................................................................................................143 Usando o DFW para criar o formulário..................................................127 MÉTODOS PARA PERCORRER DADOS ...................................147 Testando e Salvando o Projeto ....................................................148 Atualizando Quantidade em Estoque ......................................................................................................................................................................................................................PESQUISAS NA TABELA ................151 EXEMPLO: USANDO CONSULTAS .............................................................................................................128 Exemplo: Percorrendo a Tabela de Itens ..............................................................153 Alterando a Consulta ...................................................................................................................147 Usando um campo Lookup.....................................................................................................................................................................................................................142 CRIANDO UM FORMULÁRIO MESTRE/DETALHE ..........................................................................................................122 Utilizando um Índice Secundário.......................................................................................................................................................................................................................................................................................

........................168 Construindo o Relatório .........................164 Iniciando o InstallShield .........................................................................................................174 Formatando os Campos......................................................................................................................171 CRIANDO UM RELATÓRIO COM VÁRIAS TABELAS ...............................................................160 CAPÍTULO 18 INSTALADOR E ALIAS LOCAL ........165 Escolhendo as caixas de diálogo ...................................................................................................................................................................................179 7 ................................................................168 A página QReport ..........................................................................................................165 Definindo os Arquivos Utilizados ..........................................................................173 Conectando as Tabelas ....170 Analisando o Relatório Gerado .............................CONSULTAS NUM AMBIENTE CLIENTE/SERVIDOR ...............................................................................................................................171 Inserindo um Número de Página .............................................................................................................................................................................................................................................................................................................................................................................................................................166 Gerando os disquetes de instalação....................................................................................173 Criando Sub-detalhes para Vendas ............................162 Alterando os Componentes de Dados ................................................177 Chamando o Relatório a Partir do Menu .....................................................174 Criando Sub-detalhes para Itens de Venda .............................................................................................................................................................................................................................................................................163 Alterando o Caminho em Tempo de Execução .................................................................................................................................................................................................................................................................................................177 BIBLIOGRAFIA SUGERIDA .......................................................................................................................................................................................................................................................................................................164 Definindo as Opções de Instalação ...............................167 CAPÍTULO 19 RELATÓRIOS...............................................................162 Usando o Componente Database..........................................165 Definindo os Ícones do Programa ...................................169 USANDO O QUICKREPORT WIZARD ......................................173 Acrescentando Várias Tabelas ao Relatório......161 USANDO UM ALIAS LOCAL .....175 Criando um Sub-total.172 Visualizando o Relatório................................................................................................................................................159 MÉTODOS E EVENTOS DO COMPONENTE QUERY ....................................................................................................................................164 Criando um Instalador.....175 Criando um Campo Calculado ......................................................................170 Imprimindo o Relatório .167 CONCEITOS DO QUICKREPORT .............................................................................................................................................................................................................................................163 CRIANDO UM PROGRAMA INSTALADOR ........................................................................................................................................................................................................................................................................

Iniciando o Delphi Princípios da Programação Windows Iniciando o Delphi Criando um Primeiro Programa 8 .Capítulo 01 .

e outros programas não rodam enquanto isso. ou uma aviso do sistema). mas a melhor forma de aprendê-los é praticar com os aplicativos Windows mais usados do mercado. como veremos. Multitarefa: No DOS. o que evita que o programador tenha que se preocupar com detalhes específicos do hardware. que são ativados pelo Windows quando alguma coisa acontece externamente (ou seja. a execução segue uma ordem prestabelecida pelo programador. uma ação do usuário. livrando o programador de se preocupar com esses detalhes específicos. Além disso. Configuração Padrão: O Windows armazena centralmente as configurações de formato de números. 9 . Já no Windows. moeda. Já no Windows vários programas são executados de maneira simultânea e não há como evitar isso. Cooperação com o Sistema: Num programa DOS.Princípios da Programação Windows Antes de começar a trabalhar com o Delphi. Falaremos de alguns deles no curso. A sequência de execução do programa depende da sequencia de eventos. e o programa só chama o sistema operacional quando precisa de alguma coisa dele. Controle da Tela: No DOS geralmente um programa ocupa todo o espaço de telas. afeta radicalmente o estilo de programação e a forma de pensar no programa. Isso. um programa geralmente toma o controle da máquina só para si. é uma área separada da tela que pode ser sobreposta por outras janelas (de outros programas por exemplo). e o usuário vê e interage apenas com aquele programa. datas e horas. é importante ter algumas noções do que está envolvido na programação Windows e no Delphi em particular. o programa deve responder a eventos. Já no Windows [janelas]. o acesso aos dispositivos de hardware é feito com intermédio de drivers fornecidos pelo fabricante de hardware. Algumas coisas tornam a tarefa de programação no Windows bem diferente de outros ambientes: Independência do Hardware:No Windows. todos os elementos de interface aparecem para o usuário e interagem da mesma forma. Padrões de Interface: No Windows. existem padrões definidos pela Microsoft que são recomendados para conseguir a consistência entre aplicativos. além da configuração de cores. toda informações mostradas e todas entradas recebidas do usuário são feitas por meio de uma janela.

consulte a documentação do Windows. A tela básica do Delphi tem os seguintes elementos: Ao pressionar F12 irá aparecer a seguinte tela:+ Nota: para criar um atalho para o Delphi.Iniciando o Delphi Inicie o Delphi através do seu ícone no Windows. Senão. o formulário aparece de forma praticamente 10 . • Formulário (Form1): Um formulário é a janela do seu programa. se você já tiver um atalho para o do Windows e depois em programa na sua área de trabalho. o local onde você projeta a sua interface com o usuário. Localize o arquivo executável DELPHI32.EXE sob o diretório de instalação. Durante o projeto. clique no menu Programas|Borland Delphi 4|Delphi 4.

onde uma contém as propriedades do componente selecionado. mas permite que você faça alterações no posicionamento dos componentes (elementos de tela) e em suas propriedades (características). você pode facilmente mudar entre os vários arquivos utilizados no projeto ou mesmo abrir um arquivo de texto qualquer. • Paleta de Componentes: Também na janela principal. Contém o código-fonte do projeto. etc. definição de opções. por exemplo. • Menu Principal: Contém os comandos do ambiente de programação do Delphi. • Speedbar: Uma barra de botões na janela principal do Delphi. 11 . Com ele.idêntica ao que o usuário final verá. e a outra uma lista de eventos associados a este componente. que contém botões para executar os comandos mais usados do Delphi. inicialmente). • Object Inspector: [inspetor de objeto]: Dividido em duas páginas. • Code Editor: (Aparece atrás do formulário. onde cada uma contém vários tipos de componentes que você pode escolher para colocar no formulário. para tratamento de arquivos. é dividida em várias páginas. que define as ações externas as quais você pode tratar.

y) indicando a posição do componente no formulário . o formulário reflete essa alteração na sua barra de título. o título que aparece no formulário (inicialmente Form1) é uma propriedade que você pode alterar no Object Inspector. Agora precisamos de um quadro de lista. que são inicializadas com valores padrão quando o projeto é criado. Clique na coluna da direita (que contém o valor da propriedade) e digite o texto Primeiro Programa Delphi. limpar a lista e ordenar a lista em ordem alfabética. Ela também é dividida em páginas. usando o teclado. O programa terá uma interface como a seguir. com uma lista de itens. e arraste-o para outra posição. se preferir. À medida que você digita. Agora clique no formulário. que são os objetos de interface com o usuário e alterando as características desses componentes como por exemplo. Vai aparecer um quadro de edição chamado "Edit1". 12 . ao arrastar o componente será mostrado as coordenadas (x. ela mostra o nome daquele componente. posicione o cursor em cima dele. seu comportamento. segure o botão do mouse e arraste-o para a direita. Por último. pressione e segure o botão do mouse. através das propriedades. onde cada um representa um tipo de componente que você pode colocar no formulário. Quando você passa o cursor do mouse por cima de um ícone. um pouco abaixo do quadro de texto (não se preocupe com alinhamento). Selecione a propriedade Caption no Object Inspector. na mesma página Standard. um quadro de texto que permite digitar o próximo item da lista. A Paleta de Componentes contém vários ícones. clique na alça mais à direita. e algumas vezes. portanto vamos colocar componentes nesse formulário. precisamos alterar propriedades do formulário e colocar componentes em cima dele. e botões para manipular a lista: Para criá-lo. Propriedades do Formulário Propriedades do formulário são as características que definem sua aparência.Criando um Primeiro Programa No Delphi você inicia o projeto da sua aplicação escolhendo componentes. depois clique no formulário. Clique no ícone (ListBox) da paleta de componentes. Ou. segure a tecla [Ctrl] e use as teclas de seta para movimentá-lo. Ou. Para mudá-lo de posição no formulário. que podem ser acessadas clicando no marcador de página correspondente. Por exemplo. fonte de caracteres. segure [Shift] e pressione a seta para a direita. Colocando Componentes Um formulário vazio não é muito útil. Nosso primeiro programa irá mostrar uma lista de nomes e permitirá ao usuário adicionar itens na lista. você decide quais eventos você quer tratar e escreve o código de programa que é executado por esses eventos. tamanho. usando o teclado. Para aumentar seu tamanho lateral. cor. O Object Inspector lista todas as propriedades do formulário. Depois iremos alterar esse nome padrão. Clique na página Standard e depois clique no ícone (Edit).

Add(Edit1. Clique no segundo botão (Button2) e altere Caption para "Ordenar" e no terceiro botão. Assim esse componente não vai mais começar mostrando "Edit1" no seu conteúdo. Mas para definir o que o programa vai fazer.Vamos colocar três botões no formulário. e o Delphi vai abrir o editor de código. Isso define o texto do botão. Apague o valor atual (que é Edit1). como ele reage aos eventos externos. Quando você (ou o usuário) clica em um botão por exemplo. alteraremos suas propriedades. podemos fazer o seguinte: segure [Shift] e clique no ícone (Button) da paleta de componentes.Items. e clicar nos botões. clique no marcador de página "Events". Durante a execução. Agora clique três vezes no formulário. altere Caption para "Limpar". Quando você clica em um componente com o mouse. isso provoca um evento. direta ou indiretamente. acontece quanto o botão recebe um clique do mouse. Alterando as Propriedades dos Componentes Para mudar a aparência dos componentes. Respondendo a Eventos Todo o código no Delphi é executado. Clique duas vezes na coluna da direita. colocando um botão abaixo do outro. você pode alterar as propriedades do formulário. Não se preocupe com o alinhamento por enquanto Depois clique no ícone do ponteiro ( formulário deve ficar parecido com o seguinte: ). que será executado ao clicar no botão Adicionar. Agora clique no primeiro botão (Button1) e altere sua propriedade Caption para Adicionar.Text). OnClick. begin end. gerando um arquivo executável e vai iniciar sua execução. 13 . O primeiro deles. isto é. No Object Inspector.Button1Click(Sender: TObject). Escreva o seguinte (diferenças entre maiúsculas e minúsculas não importam): ListBox1. Você não precisa escrever código para mostrar uma janela na tela nem seus componentes. Selecione o quadro de texto e depois clique na propriedade Text no Object Inspector.O Clique no botão (Run) da SpeedBar. Como são vários controles do mesmo tipo. Depois tecle [Alt+F4] para terminar o programa (ou feche a janela com o mouse). Essa página lista quais eventos são reconhecidos pelo componente. ele é selecionado e você pode alterar suas propriedades. esse trecho será executado. indicando onde você deve escrever o código. ou seja. Se existir um trecho de programa associado a esse evento (um procedimento de evento). você pode digitar texto no quadro de texto. Senão. O Delphi irá compilar o programa. O cursor está posicionado entre os delimitadores begin e end. contendo o seguinte texto: procedure TForm1. Quando você clica numa região vazia do formulário (ou pressiona [Esc]). em resposta a eventos. o evento não vai fazer nada. Repare que o Delphi cuida de toda a parte de interface com o usuário. você precisa escrever código. Clique no botão Adicionar para selecioná-lo. É importante notar que o Object Inspector disponibiliza as propriedades do componente que estiver selecionado. com as alças de marcação.

Isso vai gerar um tratador de evento para o botão Ordenar. Escreva o seguinte entre o begin e o end: ListBox1. Você pode digitar um valor no quadro de texto. Cada resultado de uma ação do usuário é chamada de evento.Edit1. Nota: Você também pode clicar no formulário ou no editor de código com o mouse. clique em Limpar. gera um programa executável com código de máquina a partir do programa fonte que você criou. isto é. o Delphi compila o programa. Programação Orientada a Objeto (POO) Para compreendermos melhor ambiente de desenvolvimento do Delphi é necessário que você entenda os conceitos de Programação Orientada a Objetos(POO). O programa deve reagir de forma apropriada nos momentos determinados pelo usuário. etc. Esses programas executáveis se tornam independentes do Delphi e podem rodar separadamente. clique em File|Save All (menu File. Sempre que você executa o programa.Sorted := False. mas geralmente o método mais rápido de alternar entre os dois é usar a tecla [F12]. Depois de acrescentar alguns itens. Salvando o Programa Para que você possa usar esse programa mais tarde. item Save All) ou no botão da SpeedBar. em que um comando segue o outro de forma definida pelo programador. Digite AULA1P e clique Ok (não use o mesmo nome que o formulário). por exemplo: clique do mouse. Digite o seguinte código: ListBox1. de forma que facilite a manutenção e a reutilizacão de partes do programa. Programas em uma interface multitarefa. O usuário deve agir de acordo com os "modos" de operação do programa e saber o momento certo para entrar com comandos. selecione o botão Limpar e siga o mesmo processo.Clear.Estas partes são chamadas de Classes (Iremos discutir em Objetos). O Delphi vai pedir um nome para o arquivo do formulário. O Windows intercepta as ações realizadas pelo usuário e informa ao programa onde. Clique no botão Ordenar e depois clique duas vezes no valor do evento OnClick. Ambiente de Programação O Delphi possui um ambiente integrado de desenvolvimento (IDE . Digite AULA1 e clique Ok. e clicar no botão Adicionar (ou teclar [Enter]).Clear. Para esvaziar a lista. clique em Ordenar. Eventos e Procedimentos Programas DOS convencionais seguem um fluxo seqüencial.Integrated Development Environment) onde você utiliza a maioria das funções de desenvolvimento. como o Windows. A POO é um forma de gerenciar a complexidade do programa. ListBox1. Testando o Programa Agora execute o programa clicando no botão . O programa é dividido em partes relativamente isoladas que podem ser alteradas de forma independente e podem ser reutilizadas mais facilmente em outros programas.Sorted := True. Finalmente retorne ao formulário. Pressione a tecla [F12] para voltar ao formulário. como e quando elas acontecem. A lista será colocada em ordem alfabética. apresentam todas as opções ao usuário. para que ele possa selecioná-los na ordem em que desejar. Depois o Delphi vai perguntar o nome do arquivo de projeto. Nesse ambiente você projeta o programa e depois executa o programa para testar o seu funcionamento. digitação de uma tecla. O item digitado será acrescentado à lista. 14 .

e serem manipulados pelo código do programa. exibição de imagens. Contém componentes para dividir um formulário em páginas. edição de texto. consulte o help do Delphi. É importante lembrar que todo controle é um componente. cada uma responsável pela tarefa a realizar em resposta a um determinado evento. e geralmente contém vários outros componentes. componentes para exibição e edição de tabelas. Nós veremos alguns deles no curso. usando rotinas auxiliares. São os componentes não-visuais (veremos alguns deles no decorrer do curso). Note que há mais páginas do que cabe na tela em dado momento. Win 3. Visão Geral dos Componentes A paleta de componentes se divide em várias páginas para facilitar a organização. clique nos botões ficam na extremidade direita da janela do Delphi. você pode dividir o seu programa. iniciar ações de programa. métodos e eventos. gráficos etc. Nota: todos os componentes são descritos em detalhe no Help do Delphi. Nota: para melhor utilização do ambiente de programação e da linguagem. Midas. Contém botões com capacidades adicionais. Standard: componentes padrão da interface do Windows. Como veremos mais tarde. Não é obrigatório definir todos os eventos para um componente. Cada evento é associado a um componente e cada componente tem uma lista de eventos que são acionados por ele em situações específicas (o Object Inspector mostra esta lista na página Events). Win32: componentes comuns de interface que são fornecidos pelo Windows 95/NT para os programas. edição de texto 15 . Componentes A paleta de componentes lista tipos de componentes que podem ser utilizados no programa. Com isso. Clique em um ícone de componente e pressione F1 para ver o texto de help sobre ele. Alguns componentes não aparecem para o usuário durante a execução do programa. Se não existe um procedimento para um evento específico. Para ver as páginas que restantes. Para criar um componente. barras de rolagem. Geralmente são os mais usados. além dos procedimentos de evento. mas nem todo componente é um controle. usados para barras de menu. você seleciona o ícone correspondente e depois clica no formulário para colocá-lo. grades de dados e editores de texto.1. exibição de texto. Mas a maioria aparece como um objeto de interface durante a execução. pressionando o botão do mouse sobre o formulário e arrastando para definir o tamanho. o programa não é mais um bloco único. simplesmente não acontece nada para aquele evento. Os procedimentos de evento são armazenados na unidade. O próprio formulário também é considerado um componente. embora seja tratado de forma diferente. seleção de opções. Você pode editar todas as unidades no editor de código do Delphi. como Dialogs. como botões de pressionar. exibir listas de itens etc. com todas suas propriedades. Samples e ActiveX. Additional: componentes especializados que complementam os da página Standard. apesar de aparecer no formulário. mas é importante ter uma noção geral do conteúdo dessas páginas. que é um arquivo de texto associado ao formulário. Essas seções são os procedimentos de evento do Delphi. o projeto de um programa é feito iniciando pelo projeto de sua interface (seus componentes) e depois escrevendo-se os procedimentos de evento.Como conseqüência. São os controles (ou componentes visuais). mas é dividida em pequenas seções. Você também pode criá-lo já com o tamanho desejado.

basta inserir no código de programa um comando como o seguinte: Edit1. impressão. Midas (apenas Delphi Client/Server e Enterprise) : componentes utilizados para criar aplicações multi-tiered. o procedimento de evento do botão Adicionar faz: Edit1. Esta página tem componentes que permitem utilizar essas caixas de diálogo comuns. planilha. etc. o código pode alterar uma propriedade dinamicamente (em resposta a um evento). Data Access: componentes para acesso a banco de dados. Samples: contém exemplos de componentes para que você possa estudá-los e aprender a criar seus próprios componentes. como temporização. São semelhantes aos componentes padrão (Standard). O código fonte desses exemplos está no subdiretório SOURCE\SAMPLES do diretório de instalação do Delphi. Text) no Object Inspector e digita seu valor. Propriedades Componentes têm propriedades [properties]. que facilitam mostrar uma interface padrão dentro do seu programa para as tarefas comuns. 16 . o Delphi mostrará o texto de help relacionado àquela propriedade. Para isso. você seleciona o componente desejado (por exemplo Edit1). barras de progresso. No programa anterior. Decision Cube (apenas Delphi Client/Server): componentes para análise multidimensional de dados. Durante a execução do programa. criação de tabelas e gráficos etc. geralmente relacionados com ações do usuário. NNTP. Por exemplo o formulário tem como propriedades o título da janela (Caption).formatado. OLE e DDE. e quando ele pressiona uma tecla. como abrir e salvar arquivos. acesso aos protocolos FTP. que quando executado. que definem suas características específicas e eventos. Por exemplo. Os componentes desta página permitem desenhar o seu relatório dentro do Delphi. multimídia. Esta página contém alguns exemplos de componentes ActiveX prontos para utilizar. configuração de cores e fontes etc.1: Esta página contém controles considerados obsoletos. Data Controls: componentes visuais para mostrar dados em aplicações de bancos de dados. Métodos Métodos são nomes para ações executadas por um componente. Quando o usuário clica com o mouse em um controle. ActiveX: um componente ActiveX é um tipo de componente que pode ser criado em outra linguagem e utilizado no Delphi. que são acontecimentos externos. barras de status e de ferramentas etc. como veremos. sua posição na tela (Left e Top). Um quadro de texto tem uma propriedade que define o texto que este contém (Text). que estão disponíveis apenas para compatibilidade com programas antigos. no programa anterior. como criação de páginas Web dinâmicas. por exemplo. Win3. Não crie programas novos que utilizam esses controles. QReport: QuickReport é um gerador de relatórios que acompanha o Delphi. TCP. Internet: componentes para acesso aos recursos e protocolos da Internet. System: componentes que utilizam funções avançadas do sistema operacional. exibição de dados em árvore ou em forma de ícones. exibição de animações.Clear. Nota: se você clicar em uma propriedade e teclar [F1]. UDP. com capacidades de tabulação cruzada [crosstab]. Dialogs: O Windows tem caixas de diálogo comuns. isso causa um evento OnClick. Para alterar propriedades durante o projeto da interface. sua cor (Color). limpa o conteúdo de um controle. depois seleciona a propriedade desejada (por exemplo. SMTP. entre outras. causa um evento OnKeyDown (entre outros).Text := 'Bem-vindo ao Delphi'. que têm funções de gráficos. usamos o método Clear. POP.

Objetos Componentes são apenas um tipo de objetos. No caso de um componente. que é uma lista dos arquivos necessários para construir um programa. mesmo que ele não possa ser colocado num formulário e editado. O código fonte da VCL é fornecido com o Delphi e permite você modificar os componentes ou estudar como eles foram feitos. é uma área de memória separada. o controle é esvaziado. que é um termo bastante utilizado no Delphi. nas diversas versões do Turbo Pascal. A maioria das rotinas úteis do Delphi não fazem parte da linguagem em si. clique na palavra desejada. os objetos das bibliotecas do Delphi e a linguagem Object Pascal. o Delphi nos fornece o Project Manager. suas propriedades. Para saber quais são os formulários.Quando esse comando é executado. Basicamente todo objeto contém propriedades e métodos. contendo dados (variáveis) e o código que manipula esses dados. também chamada VCL. por isso não aparecem no Object Inspector (mas veremos mais tarde que é possível consultar a lista de métodos disponíveis). mas são implementados pela biblioteca de tempo de execução [run-time library] do Delphi. A definição da linguagem contém as regras de sintaxe e os tipos de dados básicos que você pode usar.. etc. Ao continuar digitando.Visual Component Library Os componentes. da mesma forma que uma propriedade. utilizando-se a linguagem Object Pascal e versões sucessivas do ambiente. Você também pode criar novos componentes. depois o nome do método. no editor de código e pressione a tecla [F1]. numa definição prática. Projetos O Delphi trata cada aplicativo que você cria como um projeto. é preciso conhecer os componentes da VCL. Um objeto. Nota: para obter ajuda sobre qualquer elemento do Object Pascal ou da VCL. é feita uma busca incremental nessa lista. os dados aparecem como propriedades e o código que os manipula é composto de métodos. Métodos só tem utilidade no código do programa. e tem sido aperfeiçoada pela Borland por vários anos. as unidades correspondentes. que é a linguagem de programação usada por ele. que pode ser acessado através 17 . Object Pascal e Bibliotecas Todo código de programa no Delphi é escrito em Object Pascal. O próprio nome Object Pascal indica que se trata de uma linguagem orientada a objetos. Repare que todo método é chamado usando-se primeiro o nome do componente. Nota: se você digitar apenas o nome do componente e um ponto. eventos e métodos são implementados pela biblioteca visual de componentes [Visual Component Library]. O próprio Delphi foi criado em Delphi. VCL . o CodeInsight do Delphi mostrará a lista das propriedades e métodos disponíveis. Essa linguagem é derivada da linguagem Pascal original. escrevendo-os em Object Pascal. Mais tarde veremos vários exemplos de objetos que não são componentes Resumo Para dominar a programação em Delphi. que é o fundamento no qual tudo se baseia.

Salvando o Projeto em Disco Ao gravar o projeto em disco. A janela de título do Delphi sempre tem. Reopen Salva o arquivo atual (unidade). O arquivo de projeto é um arquivo . Só pede nomes de Save All arquivos para os que não foram salvos ainda. Open.~DP Para salvar o projeto. 18 .~PA.~DF.PAS") e o nome do arquivo de projeto (o padrão é "Project1.PAS (unidade associada) Unidades independentes: . Salva uma cópia do arquivo atual com outro nome ou em outro diretório.DFM e . a maioria deles quando você compila o programa (por exemplo. Sempre pede o nome.. o Delphi pede o nome do arquivo de formulário (o padrão é "Unit1. Mostra os arquivos utilizados recentemente e permite reabrir qualquer um deles.EXE Arquivos de backup: *.DPR e .DCU Arquivo de recursos: nome-do-projeto. bem como todo o código gerado pelo Delphi. Se esta é a primeira vez que está sendo salvo.Nome do projeto. A partir desse arquivo.DPR. com o mesmo nome de arquivo. que corresponde ao código principal do programa executável. opção Project Manager. Save pergunta pelo nome. o Delphi localiza os outros arquivos necessários. Cada formulário tem uma unidade associada. e outro arquivo contendo as propriedades do formulário e de todos os componentes. Unidades independentes geralmente contém variáveis e rotinas usadas por toda aplicação. Comandos para trabalhar com Projetos Vários comandos do menu File do Delphi são usados para trabalhar com os projetos e os arquivos que fazem parte deles: Cria um novo projeto vazio New Application Cria um novo formulário e sua unidade New Form Abre um projeto ou unidade existente... Quando você salva um arquivo de formulário. pois o Delphi cuida de acrescentá-las. use o item de menu File|Save All do Delphi. Normalmente toda aplicação contém um ou mais formulários. Os arquivos têm as seguintes extensões: Projeto: .OPT (opções) Formulários: . o Delphi cria vários arquivos: dois para o projeto em si.DFM. no título. Lembre-se que um projeto é apenas uma lista dos arquivos usados para construir o programa. mas com a extensão . que é um arquivo contendo todo o código associado a eventos. com uma extensão . e outros para cada formulário e cada unidade independente usada. Da primeira vez que você salva o projeto. · Unidades independentes: uma unidade independente contém código do Delphi que não está necessariamente associado a nenhum formulário ou controle em particular. *.do Menu View..PAS. o nome Delphi .dpr"). *.PAS Além disso. Save As. Save Project As. que é um arquivo contendo todo o código de programa associado aos eventos. Um projeto em Delphi se compõe de: · Formulários: um formulário é uma janela que projetamos no Delphi. Não é necessário digitar as extensões.. Nota: o nome do arquivo de projeto deve ser diferente de qualquer unidade do projeto. juntamente com seus arquivos. o Delphi salva dois arquivos: a unidade associada ao arquivo [unit]. Salva todos os arquivos do projeto e o próprio arquivo de projeto.RES Programa compilado: nome-do-projeto. automaticamente ao executar): Unidade compilada: nome-da-unit. mas não os contém propriamente.. Salva o arquivo de projeto. o Delphi gera outros arquivos no diretório do projeto.

mais sofisticada e com recursos úteis para grandes empresas: Standard: muito limitada em recursos. Close All Além desses comandos.O arquivo de um grupo tem a extensão ". passando pela Professional. Atual) Compila somente as units que foram modificadas.0.BPG" Comandos para tabalhar com grupos de projetos Vários comandos do menu Project são usados para trabalhar com grupos de projetos . 19 . desde a Standard (a mais simples). independente se Build All Projects foram ou não modificadas. mas mostra apenas os arquivos de projeto. dos projetos pertencentes Compile All ao grupo.. (Remove file from project) Grupos de Projetos O delphi 4. até a edição Client/Server Suite. esses projetos podem ser definidos em um grupo. Compile (Projeto Atual) Compila todas as units do projeto ativo. que tem mais recursos. Edições do Delphi O Delphi está atualmente na versão 4. É importante saber também que existem várias edições diferentes do Delphi.0 permite trabalhar com mais de um projeto aberto.Fecha o arquivo atual. Projects Compila todas as units dos projetos pertencentes ao grupo. (Add file to project) Remove um arquivo do projeto atual. Add New Project Adiciona um projeto existente ao grupo Add Existing Project Compila somente as units que foram modificadas. independente se foram ou não Build ( Projeto modificadas. Close Fecha todos os arquivos e o projeto atual. No menu View|Project Manager é informado os projetos que pertencem a um determinado grupo. os principais são: Adiciona um novo projeto ao grupo. especificamente voltados para grandes desenvolvedores que utilizam bancos de dados no padrão cliente/servidor. (Open Project) O mesmo que File|Save (Save ) Adiciona um arquivo ao projeto atual. do projeto ativo. Recomendada para desenvolvedores profissionais. existem ícones na SpeedBar que podem ser usados para essas tarefas: Equivale a File|Open. Client/Server : inclui mais recursos que a Professional. especialmente os feitos para a versão 1. embora alguns necessitem de modificação para funcionar. (Open project) O mesmo que File|Save all (Save all) O mesmo que File|Open Project. Indicada apenas para quem tem interesse em desenvolvimento de pequenos programas ou para fins de aprendizado. Essa versão é geralmente compatível com programas desenvolvidos nas versões anteriores.. Professional: inclui mais recursos que a edição Standard.

você deve utilizar a versão 1. Se você quiser desenvolver programas compatíveis com Windows 3.x. e Windows NT.Note que o Delphi 4 só funciona para ambientes de 32 bits. 20 . Windows 95/98/etc.0. ou seja.

Capítulo 3 Exemplos Adicionais Exemplo: Calculadora 21 .

Isso vai salvar três arquivos em disco.PAS A unidade unidade associada ao formulário CALC. com um clique duplo na ferramenta . etc. crie um novo projeto com File |New Application e altere a propriedade Caption da janela principal (Form1) para "Calculadora". Nota: No curso adotaremos um padrão para nomes de componentes: um prefixo de três ou quatro letras que diz o tipo de componente (edit para Edit. para "editOperando1". Finalmente crie um quadro de texto. se o Delphi estiver aberto. inicie o Delphi ou. A propriedade Name determina o nome que será usado no programa para manipular esse componente. Nota: Quando você cria um componente. Button1. Repita as mesmas ações para criar outro quadro de texto para o segundo operando. semelhante à figura: Criando os Componentes Para começar. que vai conter o resultado. Altere Name para "btnCalcula". É recomendável dar um nome mais descritivo para que seja mais fácil entender o programa mais tarde. Altere sua propriedade Caption para "=" (sinal de igual). Ele deverá ficar logo abaixo do primeiro. etc. Agora crie um botão de comando. Dê os nomes de CALC ao formulário e CALCP ao projeto. posicionando-o abaixo do botão de comando.Exemplo: Calculadora O nosso objetivo é criar uma calculadora simples. que lista os nomes dos outros. que apenas soma dois números fornecidos e mostra o resultado. Dê dois cliques no ícone Edit para criar um quadro de edição no formulário. btn para Button. Dê o nome de "editResultado".) seguido de um nome descritivo (no caso. 22 . Dê o nome "editOperando2". Operando1).DPR O arquivo de projeto. Agora grave o projeto usando File | Save All no menu do Delphi. que será usado para receber o primeiro operando digitado. ele recebe um nome default como Edit1. Veremos que esse padrão facilita a compreensão dos programas. Mova-o até o topo do formulário e altere a sua propriedade Name. como já vimos: CALC. CALCP.DFM Contém a definição do formulário e seus controles. Altere o seu tamanho para ficar igual ao dos quadros de texto.

a-z). mas para o evento padrão. Altere sua propriedade Caption para conter um sinal de +.Text). toda variável também tem um tipo.Text). mas por enquanto. Selecione "MS Sans Serif" na lista de fontes e um tamanho maior na lista "Tamanho". mas ela ainda não executa a função desejada. informando-se o nome e o tipo das variáveis. Depois veremos todos os tipos de dados em detalhes. todas do tipo double. O resultado final.btnCalculaClick(Sender: TObject). para mostrar o sinal de "+" vamos usar um componente Label (rótulo). some os seus valores e coloque o resultado no último quadro de texto. acrescente o seguinte: var op1. Nota: Nomes de variáveis em Object Pascal podem ter até 63 caracteres e podem conter letras (A-Z. Para ler o valor digitado em um controle Edit. devemos ler a propriedade Text.Text). O primeiro caractere não pode ser número. Isso declara três variáveis: 'op1'. op2 := StrToFloat(editOperando2. é mais rápido um clique duplo no próprio componente. Isso vai criar um tratador de eventos para o evento padrão do botão. que corresponde às características do texto. Repare que foi utilizada a identação (deslocamento à direita) dos comandos. só que essa propriedade tem um valor alfanumérico (pode conter letras e números).Text := FloatToStr(res). Variáveis são declaradas com a palavra var. Tratando os Eventos A interface da calculadora está pronta.Não é necessário repetir o var para várias declarações. pois elas terminam quando se encontra o begin. Clique duas vezes no botão 'btnCalcula'.Agora.Text := FloatToStr(res). res: double. números e o caractere '_'. que apenas mostra um texto para o usuário. que é o evento OnClick. editResultado. Antes da palavra reservada begin. será o seguinte: procedure TForm1. Depois basta somar as variáveis e mostrar o resultado. O Delphi vai gerar o seguinte código: procedure TForm1. No Delphi. no formulário. O Object Pascal não diferencia maiúsculas de minúsculas (não é case-sensitive). que determina quais os valores que ela pode conter. Uma variável é uma área de memória que tem um nome e armazena um determinado valor. e clique duas vezes do seu lado direito. selecione a propriedade Font. Para fazer com que esse sinal fique maior. editResultado. Selecione o ícone e desenhe um rótulo à esquerda do editOperando2. begin end. com a precisão de 15 a 16 dígitos significativos.Text). Para fazer o cálculo precisaremos de variáveis.btnCalculaClick(Sender: TObject). logo precisamos convertê-la para numérico. op2: double. res := op1 + op2. begin op1 := StrToFloat(editOperando1. Agora vamos utilizar essas variáveis para obter os valores digitados pelo usuário. Repare que duas variáveis do mesmo tipo podem ser declaradas separando-as por vírgula antes do tipo ou em uma declaração separada. não permitindo alteração. end. 23 . que permite armazenar valores numéricos com parte fracionária. Depois clique Ok. usaremos o tipo de dados 'double'. mas isso não é obrigatório no Delphi. com todo o código acrescentado. Foi utilizado apenas para facilitar a legibilidade. Precisamos acrescentar código que leia os dois operandos. Isso é feito com a função StrToFloat: op1 := StrToFloat(editOperando1. Nota: Você pode também selecionar o evento no Object Inspector e criar o tratador a partir do nome dele. como na figura. op2 := StrToFloat(editOperando2. utilizando novamente uma função de conversão: res := op1 + op2. 'op2' e 'res'.

o ideal seria aparecer inicialmente sem nenhuma informação. como no DOS). Repare que você pode usar a tecla [Tab] para passar de um controle para outro utilizando o teclado (e não [Enter]. ao criar o componente edit e modificar a propriedade Name o delphi automaticamente coloca o mesmo conteúdo desta propriedade na propriedade Text. que é sempre acionado quando o usuário tecla [Enter]. caso esta não tenha sido modificada antes. para fazer esta modificação vamos retornar ao projeto e alterar a propriedade Text de cada componente edit . Cada controle indica o foco de forma diferente. Essa propriedade. Isso faz com que ele seja o botão default. quando é False. O controle que responde às teclas em determinado momento tem o foco de teclado. Também altere a propriedade ReadOnly para True. podemos fazer com que ela acione o botão "=". É a propriedade Text que indica o conteúdo do componente naquele momento. Para isso. 24 . 'editOperando2' e 'editResultado' aparecem com seus respectivos nomes . Basta alterar a propriedade Default do botão 'btnCalcula' para True (verdadeiro). basta usar File|Save All ou clicar no botão da SpeedBar. o que faz com que o controle não permita edição de seu valor. que alterna de True para False. Execute o programa e teste as modificações. esta ordem de foco pode ser alterada. Por exemplo. Melhoras de Interface Alguns detalhes podem ser melhorados: primeiro. pois não faz muito sentido. Salvando o Projeto Para salvar o projeto e todos os arquivos. já um controle Button mostra um retângulo tracejado em volta do texto. o quadro de edição 'editResultado' não deveria receber o foco quando o usuário pressiona [Tab] e não deveria permitir edição do texto. como foi informado o nome do projeto e da unit ele não irá pedir novamente. Ao executar o projeto podemos observar que os quadros de edição 'editOperando1'. Outra mudança: como o usuário não usará a tecla [Enter]. Você pode fazer isso selecionando o valor a partir da lista (com o botão de seta) ou com um clique duplo no valor da propriedade. faz com que o controle seja "pulado" pela tecla [Tab]. selecione o controle e altere sua propriedade TabStop para False. Digite um número no editOperando1 e outro no editOperando2 e depois clique no btnCalcula. um controle Edit mostra o cursor de texto quando ele tem o foco.Executando o Programa Execute o programa com o botão ou a tecla [F9]. Como veremos. Com isso o Delphi vai salvar todas as alterações feitas no projeto.

Capítulo 4 Variáveis e Tipos de Dados Tipos de Dados Funções de Conversão OPerações Aritméticas Tipos Ordinais Escopo de Variáveis Constantes 25 .

4x1038 2. por exemplo. por exemplo. e cada um tem uma determinada faixa de valores e ocupa um certo espaço de memória. Existem vários tipos de dados numéricos. usa-se o operador de atribuição: ':=' (dois-pontos-igual). No Delphi 3.648 a 2.Button1Click(Sender: TObject).483. b := a. Uma variável de um tipo numérico. que são os seguintes: Tipo Bytes Faixa de Valores Precisão(dígitos) Tipos Inteiros Shortint 1 -128 a 127 N/A Byte 1 0 a 255 N/A Smallint 2 -32768 a32767 N/A Word 2 0 a 65535 N/A Integer 4 -2 bilhões a 2 bilhões N/A (-2. end. Não é recomendável utilizar Real48.7x1038 5x10-324 a 1. o seguinte: a := 'Nome'. ou expressões com operações sobre valores.967.648 a 2. só pode receber valores numéricos. valores de outras variáveis. { 'b' idem } begin a := 2.483.294.. Geralmente. Os tipos numéricos se dividem em tipos inteiros (ou integrais).. A coluna "bytes" diz quantos bytes de memória são ocupados por uma variável do tipo. que é lido como "recebe".5808 a 922337203685477. que só permitem valores inteiros e tipos reais (ou de ponto flutuante [floating point]). var a: integer. Uma forma de entender a diferença é que tipos inteiros são usados para contagem de 26 .295 N/A Int64 8 . o tipo Real tem uma faixa de valore menor que o Double e equivale ao tipo Real48 do Delphi 4. Para colocar um valor em uma variável.647) Longint 4 -2.483. Não é permitido. Quanto maior a faixa de valores. o tipo Real é idêntico ao tipo Double.2 63 a 2 63 N/A Tipos Reais Single Real48 Real Double Comp Currency Extended 1. Esses valores podem ser constantes.9x10-39 a 1. Por exemplo: procedure TForm1. que permitem valores com parte fracionária. com algumas exceções. Tipos Numéricos A linguagem Object Pascal tem vários tipos de dados para variáveis numéricas.pois apenas valores numéricos podem ser colocados na variável 'a'.295 N/A Longword 4 0 a 4.294.147.967.7x10308 -263 a 263 -922337203685477.5807 4 6 8 8 8 8 10 3. uma variável de um determinado tipo só pode receber valores deste tipo.6x10-4951 a 1.Tipos de Dados Toda variável tem um tipo.648 N/A Cardinal 4 0 a 4.147. maior o espaço de memória. em geral. .5x10-45 a 3.7x10308 5x10-324 a 1. que determina quais os valores que você pode colocar nessa variável e quais as operações que podem ser executadas sobre ela. b := b + 3. porque ele é muito mais lento para cálculos.147.483.147.1x104932 7-8 11-12 15-16 15-16 19-20 19-20 19-20 *Nota: No Delphi 4. Não é permitido colocar em uma variável um valor que esteja fora da faixa do seu tipo. { 'a' é uma variável do tipo Integer } b: integer.

elementos, enquanto tipos reais são usados para medir alguma coisa. E essa medida nem sempre é exata. Ao fazer cálculos com variáveis reais, nem sempre o resultado é igual ao esperado. Por exemplo: var fracao, a, b: real; {'real' é um tipo real} 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 não representam valores exatos, a igualdade não é exata. A variável 'b' pode ter um valor de 0.99999999..., que ao ser comparado, não é igual a 1.0. Cada tipo real tem uma certa precisão, indicada na tabela, que diz quantos dígitos significativos (dígitos excetuando zeros à esquerda e à direita) a variável pode guardar, sem perda de precisão nos cálculos. Assim, é importante lembrar que os valores guardados em um desses tipos nem sempre é exato. Geralmente os tipos inteiros são mais eficientes para cálculos, e também mantém valores exatos para qualquer operação, desde que o resultado não saia da sua faixa de valores. Os tipos mais utilizados são smallint, para valores inteiros pequenos, integer ou Longint para valores inteiros maiores, e Double para valores reais com uma precisão razoável. Os tipos Shortint e Byte são utilizados quando é preciso guardar um contador bem pequeno e é necessário economizar memória.Quando os tipos integer ou longint não são suficientes podemos usar os tipos longWord e int64 que existe somente nesta versão. O tipo Comp é considerado como real, mas ele permite apenas valores inteiros. Ele é útil para valores monetários.

O tipo Char
O tipo Char permite criar variáveis que guardam caracteres individuais, como letras, dígitos, sinais de pontuação e caracteres de controle. Cada variável do tipo Char só pode conter um caractere. Caracteres comuns (imprimíveis) são representados entre aspas simples (apóstrofos): var minhaVariavel: Char; ... ... minhaVariavel := 'A'; Um caractere também pode ser representado através do código ASCII/ANSI correspondente. Isso é útil principalmente com caracteres de controle, que não podem ser impressos nem digitados normalmente no programa, como caracteres de backspace, fim de linha, retorno de carro etc. Por exemplo, para guardar o caractere 13 (retorno de carro), usa-se a sintaxe: minhaVariavel := #13; Se o código estivesse numa variável em vez de uma constante, não pode ser usada essa sintaxe. Nesse caso, pode-se usar a função Chr: codigoASCII := 13; minhaVariavel := Chr(codigoASCII); Nota: para ver os caracteres da tabela ANSI (exceto os de controle), use o aplicativo Mapa de Caracteres do Windows (em Iniciar | Programas | Acessórios).

O tipo String
Para guardar mais de um caractere, é preciso usar o tipo String. Um valor constante do tipo String é representado entre apóstrofos, como por exemplo: var nome: string; begin nome := 'João da Silva'; Uma variável string normalmente não tem limite de tamanho definido. O espaço de memória que ela ocupa muda dinamicamente de acordo com o conteúdo atribuído a ela, por exemplo: nome := '123'; {3 caracteres}

27

nome := 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'; {26 caracs.} nome := ''; {zero caracteres} No último caso, tem-se uma string vazia, que é representada por '' (apóstrofos sem caracteres dentro), que ocupa zero caracteres. Ela é usada para "limpar" o conteúdo de uma variável. Nota: O Windows usa uma tabela de caracteres chamada tabela ANSI, que associa um código numérico a cada caractere. Nota: o Windows permite caracteres acentuados e especiais, como Â, Ç, ©, ½, «, ¶, etc. Mas uma variável string pode ser declarada com um tamanho fixo, da seguinte forma: var nome: string[50]; telefone: string[10]; Nesse caso, a variável ocupa um espaço fixo de memória, de acordo com o tamanho declarado. No exemplo, nome ocupa 50 caracteres e telefone ocupa 10. Se você tentar atribuir mais caracteres do que cabe na variável, os caracteres restantes são ignorados. Se você atribuir menos, o tamanho lógico da string passa a ser menor que o tamanho físico. O Object Pascal usa um byte a mais para armazenar o tamanho lógico. 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 variável e mais um valor entre colchetes. Por exemplo, se você quiser guardar o 7º caractere do nome numa variável char, basta fazer: c := nome[7]; Existem várias propriedades que também são do tipo String, como Caption e Text, por exemplo. Assim, é possível atribuir uma constante ou variável do tipo String para elas, por exemplo: btnIniciar.Caption := '&Iniciar'; memoTempoTotal.Text := s; Nota: existem várias funções de manipulação de strings, por exemplo, para obter uma parte de uma string. Consulte o help do Delphi e procure por 'String manipulation functions'.

O tipo Boolean
Várias propriedades (e variáveis também) podem conter os valores True (verdadeiro) e False (falso), indicando uma condição lógica ou um "flag" (ligado/desligado, habilitado/desabilitado, sim/não). Para isso utiliza-se o tipo Boolean, que só tem dois valores possíveis: True e False. Por exemplo: tmrMarca.Enabled := False; O Delphi também utiliza o tipo Boolean internamente, ao fazer qualquer comparação lógica, em um comando if, por exemplo. E uma variável do tipo Boolean sozinha já é uma condição lógica, portanto pode ser usada em um comando if diretamente, por exemplo: var ValorCorreto: Boolean; begin ... 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 operações de data mais em detalhe em Manipulação de datas.

28

Funções de Conversão
Qualquer variável numérica pode receber um valor do mesmo tipo ou de um outro tipo numérico, exceto que uma variável inteira (Integer, Longint, Word etc.) não pode receber um valor real, pois este pode conter uma parte fracionária. 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 função de conversão, que ou descarta a parte fracionária (função trunc) ou arredonda o valor (função round): x := 3.7; a := trunc(x); {a vai valer 3} b := round(x); {b vai valer 4} Existem várias funções que convertem valores de tipos numéricos para o tipo String e viceversa. Nós já vimos algumas em programas-exemplo: var varReal: double; varInteira: integer; varString: string; begin { de String para numérico: } varReal := StrToFloat(varString); varInteira := StrToInt(varString); varInteira64 := StrToInt64(varInteira64); { de numérico para String: } varString := FloatToStr(varReal); varString := IntToStr(varInteira); {VarInteira pode ser de qualquer tipo inteiro,inclusive int64 } end; Além dessas, existe a função Str, do Pascal padrão, que converte um número qualquer para String, permitindo especificar uma largura de campo (o número é alinhado à direita com espaços) e a quantidade de casas depois da vírgula. Por exemplo: segundos := 34.749; Str(segundos:7:2, s); A variável 's' vai ser preenchida com uma string 'oo34.75' (cada o representa um espaço em branco). Ou seja, vai conter no mínimo 10 caracteres, com os dígitos alinhados à direita e duas casas depois da vírgula (casas a mais são arredondadas).

Operações Aritméticas
Os tipos de dados inteiros suportam as operações aritméticas usuais: soma: a := x + y; subtração: a := x - y; multiplicação: a := x * y; divisão: a := x / y;

29

b: boolean. a := b div c. Mas pode-se utilizar uma função de conversão. Algumas operações podem ser feitas com qualquer tipo ordinal. que é = 1} Expressões podem ser combinadas com vários operadores e operandos. c2 := succ(c1). Isso pode ser usado para converter uma condição lógica em valor numérico. {multiplica 'b' e 'c' e soma com 'a'} y := (a + b)*c. um Double e um Integer). · O tipo Char (os caracteres são ordenados pela tabela ASCII/ANSI). No caso de um caractere. enquanto pred retorna o anterior: var c1. ou seja. Se você chamar succ para o último elemento da seqüência ou pred para o primeiro elemento. mesmo quando os dois operandos são inteiros. c2: char. y: integer. como trunc: a := trunc( b /c ). isso vai causar um erro de execução (por exemplo. a partir de um elemento é sempre possível passar para o próximo elemento do tipo.. retorna o próprio número. {vai ser = 'F'} x := 299. a. · O tipo Boolean (só tem dois elementos: False.True nessa ordem). Para os números inteiros o resultado será do tipo int64 somente se tiver uma variável deste tipo. y := succ(x). {x vai ser 71} No caso do tipo Boolean. depois soma e subtração. {retorna o resto de 13 div 4. {vai ser = 'H'} c2 := pred(c1). begin c1 := 'G'. quando 'a' é uma variável inteira. caso contrário o resultado será do tipo integer.Se os dois operandos são do mesmo tipo. Cardinal. Os tipos ordinais predefinidos pela linguagem (veremos que você pode criar outros) são: · Todos os tipos inteiros (Integer. ord(False) = 0 e ord(True) = 1. Uma exceção é que no caso da divisão.. 'succ(True)' não é permitido).1} a := False. ou usa-se o operador de divisão inteira div (os dois operandos dever ser inteiros). o resultado sempre é real. Portanto. portanto não tem utilidade prática. A função ord retorna a posição numérica do elemento dentro do tipo. 30 . mas o mesmo não é válido para a função ord. por exemplo: x := a + b * c.Enumerados. b := succ(a). Longint. No caso de um número inteiro. {vai ser = True} end. x. a menos que sejam usados parênteses. que calcula o resto da divisão: x := b mod c. Multiplicação e divisão são executadas primeiro. Se os dois operandos são inteiros. o resultado é desse tipo. c := 4. Word. {succ(x) = x + 1 e pred(x) = x . o resultado será do tipo deste operando (no exemplo. A função succ retorna o próximo elemento do tipo. {retorna a parte inteira da divisão = 3} Existe também o operador mod. Mais tarde veremos outras operações que podem ser executadas em tipos ordinais. retorna o código ASCII (ANSI) do caractere. Se um deles tem uma faixa de valores maior (por exemplo. Notas: Os tipos reais não são considerados tipos ordinais. o resultado será inteiro e pode ser atribuído para uma variável inteira. por exemplo: b := 13. não é permitido fazer: a := b / c. {soma 'a' e 'b' e multiplica por 'c'} Tipos Ordinais Um tipo de dados é considerado um tipo ordinal quando existe uma seqüência definida entre seus elementos.). Double). Notas : As funções succ e pred podem ser utilizadas para variáveis do tipo int64. que é sua posição na tabela ASCII (ANSI): x := ord('G').

Como já vimos. seu valor pode ser qualquer dado que existia anteriormente na memória. como os seguintes: 20 3. desde que essa outra tenha uma cláusula uses para a unidade que contém a variável. end. False para booleans. Qualquer variável só pode ser utilizada no programa depois do ponto onde foi declarada. ou seja.5 (constantes numéricas . você pode fornecer um valor inicial diferente do padrão. Variáveis globais são inicializadas com valores padrão: zero para numéricas. variáveis locais são declaradas com a palavra var.integer e double) 'Testando' (constante do tipo string) False True (constantes do tipo boolean) 'x' #8 (constantes do tipo char) 31 . Se esse valor for utilizado. res: double.DFM} var VariavelGlobal: integer. qual a região do programa onde a variável pode ser acessada e o tempo de vida da variável. Depois que o procedimento termina. Uma constante literal é um valor sem nome. Quando a execução do procedimento é iniciada. fora de qualquer procedimento. Variáveis Locais Uma variável declarada dentro de um procedimento é uma variável local. mantendo o seu valor. usados em expressões etc. ou seja. é preciso declarar a variável como global.. a variável deve ser declarada em separado de outras (não em uma lista) e depois do tipo de dados. O escopo dessa variável passa a ser desde o ponto onde foi declarada até o fim da unidade. '' (texto vazio) para strings. ou seja. qual o intervalo de tempo durante o qual ela mantém seu valor. Veremos mais sobre isso em Estrutura das Unidades. Por exemplo: var VariavelGlobal: integer = 1. op2. Por exemplo: implementation {$R *. begin . Se for declarada na parte interface. pode ser usada por outra unidade. etc. e seu valor anterior é perdido. AtivaTimer: boolean = true. escrito explicitamente..Escopo de Variáveis O lugar onde é declarada uma variável determina o escopo de uma variável. a memória ocupada pela variável é liberada. Constantes Constantes são valores que podem ser colocados em variáveis. Elas mantêm seus valores durante toda a execução do programa. se declarada na parte implementation. os resultados são imprevisíveis. logo após o cabeçalho do procedimento. Ao declarar uma variável global. Titulo: string = 'Título inicial'. Variáveis Globais do Projeto Uma variável global. só pode ser acessada dentro daquela unidade. Ela só pode ser utilizada dentro do procedimento (o escopo da variável é o corpo do procedimento). Para isto. Variáveis Globais da Unidade Se uma variável precisa ser usada em vários procedimentos. O tempo de vida de uma variável local é o tempo durante a execução do procedimento. ou seja. var op1. que deve ser constante. a variável está indefinida. mas antes do begin que inicia os comandos: procedure btnCalculaClick(Sender: TObject). você deve colocar um "=" e o valor inicial.

além de 0 a 9. uma constante pode ser local (se declarada em um procedimento) ou global (se declarada fora). Você também pode criar constantes nomeadas. portanto não podem receber outro valor: TAMANHO := 15. que são simplesmente substituídas pelos valores correspondentes durante a compilação do programa.5 x 104 = 35000 } z := 2. usa-se a declaração const: const TAMANHO = 30. Elas facilitam a manutenção do programa. prefixado por '$'.78e-6.'. Digite novamente. MENS_ERRO = 'Valor incorreto. { = 3.78 x 10-6 = 0. Para isso. Números sem parte fracionária são considerados constantes inteiras (isso se o número couber na faixa de valores de um tipo inteiro). 32 . por exemplo: const Inteiro64 = int64(17) Desta forma o tipo que a constante irá retornar é int64. especificando-se um valor e uma potência de 10: y := 3. Uma constante inteira também pode ser especificada como um valor hexadecimal. Uma constante real também pode ser escrita em notação científica.5e4. { = 2.1415926536. angulo := PI*graus/180.O tipo de dados de uma constante é determinado pela forma desta. { erro de compilação } Da mesma forma que variáveis. PI = 3.00000278 } Você pode criar constante especificando o tipo que esta constante irá retornar . METADE = TAMANHO/2. quando um valor é utilizado em vários lugares. por exemplo: x := $2F3. Mas não são variáveis. Números hexadecimais contém também os dígitos A até F. > Constantes nomeadas são utilizadas como qualquer outra constante: x := TAMANHO * 8.

Capítulo 5 Estruturas de Controle Inserindo Comandos com o CodeInsight Estruturas de Decisão Estruturas de Laços Outros Comandos 33 .

Nós já vimos o comando if em várias situações. Para ver uma lista completa dos modelos de código. o CodeInsight do Delphi possui um recurso chamado modelos de código [code templates]. ou a separação do comando em várias linhas não são obrigatórias em nenhuma situação no Object Pascal. você pode também desmarcar a opção "Code Completion" se quiser. que permite inserir rapidamente um comando da linguagem contendo apenas a estrutura básica. : . Nessa sintaxe. ] Nota: você pode alterar os modelos de código ou criar novos. para identar um bloco de comandos (deslocar à direita). digite casee no editor de código e tecle [Ctrl+J]. usa-se os delimitadores begin e end para criar um comando composto. Dica: No editor de código. O CodeInsight irá inserir um comando case com uma cláusula else e espaços em branco para você completar: case of : . por exemplo: if condição then begin comando1.Enabled := True else menuEdiRecortar. tecle [Ctrl+J]. O cursor ficará posicionado entre case e of. A identação de comandos. Mas geralmente um comando if é escrito em várias linhas.Enabled := False. ifb. forb. Você pode completar com um nome de variável. whiles.' é colocado depois do comando1. '>' etc. A sua sintaxe básica é: if condição then comando1 else comando2. o '. Note que os outros usam comandos do Object Pascal que ainda não foram vistos. caseb.. Por exemplo. Note que não é permitido o '. False para falso).Inserindo comandos com o CodeInsight Para facilitar a digitação dos comandos da linguagem e reduzir os erros. end. whileb. fore.. para maior legibilidade: if condição then comando1 else comando2. Por exemplo: if memoEditor.then. condição é qualquer expressão que gere um resultado do tipo Boolean (True para verdadeiro. use [Ctrl+Shift+U]. Para deslocar à esquerda.else. Se não houver o else. cases. Um comando composto é tratado pelo Object Pascal como um único comando.' (ponto-e-vírgula) logo depois do then ou logo antes ou depois do else. ifs. else . em lugar de comando1 ou comando2 é preciso executar vários comandos. Estruturas de Decisão O Comando if.. valores constante e os comandos a serem executados. 34 .. comando2.' depois do fim do comando if. embora na maioria das vezes seja construída usando operadores de comparação. { OU sem o else: } if condição then comando1. Veja por exemplo. que depois você pode preencher.SelLength <> 0 then menuEdiRecortar. Quando.. Essa opção mostra a lista de propriedades e métodos de um componente quando você digita o nome do componente e um ponto. ifeb. Para isso clique em Tools|Environment Options e na página CodeInsight. podendo ser uma única variável booleana. como '='. os modelos ife. Nesta mesma página.. Só pode haver '. use [Ctrl+Shift+I].

Cada comando na sintaxe pode ser um comando simples ou um comando composto formado pelos delimitadores begin e end... { valores 11. são obrigatórios parênteses em volta das condições: if (Key < '0') or (Key > '9') then Key := #0. Mas nesse caso.. várias constantes separadas por vírgulas. 2: desconto = 20. Dentro do comando composto. Cada rótulo pode ser uma constante sozinha. O operador and tem precedência sobre o or. 3. Mas o mesmo pode ser feito com o comando case.. end. Isso pode ser feito com vários comandos if aninhados: if dia = 1 then desconto = 30 else if dia = 2 then desconto = 20 else if dia = 3 then desconto = 10. comando4. 13 e 15 } end. A sintaxe geral desse comando é: case expressão of rótulo1: comando1. mas fora dele se aplicam as regras do if. { constante } 2: nome := 'segundo'. end. Muitas vezes é preciso comparar uma variável com vários valores. os comandos são separados por '... especificando a variável. Dica: para encontrar um fecha-parênteses perdido. coloque o cursor antes do abre-parênteses e tecle [Ctrl+Q+[ ] (ctrl+Q+abre-colchetes). 35 . e utilizar parênteses para especificar o que se deseja avaliar primeiro: if ((Key < '0') or (Key > '9')) and (Key <> #8) then Key := #0. Por exemplo: case dia of 1: nome := 'primeiro'. e o not tem precedência sobre os dois. O Comando case. Um comando if pode ser usado dentro de outro. end. or (ou) e not (não).15: nome := 'quarto'. else comandoElse.of. combinando-as com and (e). rótulo2: comando2. 3: desconto = 10. E o operador not pode ser usado para inverter o resultado de uma condição: if ((Key < '0') or (Key > '9')) and not (Key = #8) then Key := #0. Onde expressão pode ser qualquer variável ou expressão que retorne um valor de um tipo ordinal. . e seus valores possíveis: case dia of 1: desconto = 30. portanto é preciso levar isso em conta em condições mais complexas. mas isso pode dificultar o entendimento se um deles inclui uma cláusula else.10: nome := 'terceiro'.'. { valores entre 3 e 10 } 11. ou uma faixa de valores.end else begin comando3. Nesse caso o else fica ligado ao if mais próximo. Mais de uma condição pode ser usada no if.13..

A parte do else é opcional e indica um comando a ser executado se nenhum dos valores corresponde ao valor da expressão. 36 .

until O repeat. o comando é executado. Sua sintaxe geral é: repeat comando1. s: string. end. 37 .Estruturas de Laços Estruturas de laço permitem repetir um conjunto de comandos. end.. O comando. mas testa a condição no final. comando2. e termina a execução se a condição for verdadeira (o contrário do while). Se no início da execução o valor inicial é maior do que o final. o comando nem chega a ser executado.. O laço while repete um comando enquanto determinada condição é verdadeira. o valor inicial e o valor final devem ser todos de um tipo ordinal.. while i < 1000 do begin Processar(i). Se ela for falsa..do. depois de executar o comando.Add(s). Por exemplo: i := valorAnt. end. ListBox1.. A variável. o comando não chega a ser executado. Sua sintaxe de forma geral é: while condição do comando. Se for verdadeira. Você deve especificar o valor inicial e final da variável.. O comando for O comando for permite repetir um laço um número especificado de vezes. O comando while. pois este é um tipo ordinal: for letra := 'A' to 'Z' do .... O seguinte laço mostra os valores numéricos de 1 até 20 dentro de um componente ListBox: var valor: integer. a condição é verificada. for valor := 20 downto 1 do . como antes. usa-se downto no lugar da palavra to: for letra := 'Z' downto 'A' do .. O comando repeat.Items. i := i + incremento. . A variável também pode ser do tipo Char. e a condição é verificada novamente e assim por diante. Antes da primeira iteração do laço.. begin for valor := 1 to 20 do begin s := IntToStr(valor). ou um comando composto. Para decrementar a variável durante o laço.until é semelhante ao while. ao invés de incrementar. Cada um dos comandos de laço especifica uma forma diferente de iniciar e testar o laço.. incrementando ou decrementando uma variável a cada passagem do laço. A forma de uso é a seguinte: for variável := valor_inicial to valor_final do comando.. Note que o incremento ou decremento é sempre 1. pode ser um comando simples..

end.Items. Ele força a execução da próxima iteração (repetição) do laço. 38 . { vai para o próximo } s := IntToStr(x). end. O comando exit Para sair imediatamente de um procedimento. O comando repeat sempre executa uma iteração do laço pelo menos. ou repeat) e vai para o próximo comando depois do laço.until condição. repeat Processar(i). Por exemplo. i := i + incremento. Por exemplo: for i := 1 to 1000 do begin encontrou := ProcuraValor(i). if Encontrou(i) then break. usa-se o comando exit. Por exemplo: i := valorAnt. exit. é comum precisar terminar sua execução antes do tempo. Outros Comandos Comandos para sair de laços Durante a execução de um laço. { o break salta para esta linha } Além desse. Use-o quando ocorre alguma condição de erro. until i >= 1000.Add(s). Para isso. ignorando os comandos restantes dentro do bloco do laço. Este comando sai imediatamente do laço mais interno (seja for. o próximo laço mostra em uma list box os números de 1 a 300. exceto os múltiplos de 7: for x := 1 to 300 do begin if x mod 7 = 0 then { é um múltiplo de 7? } continue. por exemplo: if valorErrado then begin mostrarMensagem. Note que ele não precisa de begin e end para delimitar a lista de comandos. pois as próprias palavras repeat e until já formam delimitadores. pode ser usado o comando break. while. existe o comando continue. ListBox1. end.

Capítulo 6 Propriedades e Eventos Comuns Tipos de Propriedades Propriedades Mais Usadas Eventos Comuns Detalhes do Tratemnto de Eventos 39 .

Tipos de Propriedades
Existem várias formas de editar o valor de uma propriedade, dependendo da propriedade específica. Nós já vimos a maioria delas, que são basicamente as seguintes: Propriedades que aceitam qualquer valor: você precisa digitar o valor diretamente. Exemplo: Caption, Text. A propriedade Name só aceita um identificador válido (mesmas regras que nomes de variáveis). Propriedades numéricas: O Delphi permite digitar qualquer coisa, mas quando você teclar [Enter] ou sair, ele vai verificar se é um valor numérico. Exemplo: Left, Top, MaxLength (do componente Edit). Propriedades de lista: Um botão aparece ao lado do valor. Ao clicar nele, abre-se uma lista de valores, e é possível selecionar um deles:

Exemplo: BorderStyle, Color, WindowState, Align. Geralmente o valor só pode ser um dos disponíveis na lista, mas algumas propriedades permitem digitar outros valores, como Color. Propriedades booleanas: uma propriedade do tipo Boolean, que só tem dois valores possíveis: False e True. Exemplo: Enabled, Visible, Ctl3D. Você pode selecionar um deles na lista, mas é mais fácil usar , com um clique duplo no valor, o conteúdo será alternado entre True e False ou clicar no botão . Propriedades expansíveis: 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; Propriedades de conjunto: São parecidas com propriedades expansíveis. As "subpropriedades" que aparecem são todas booleanas (True/False). Exemplo: BorderIcons, Font.Style. O valor que aparece é um conjunto de valores, que como veremos mais tarde, exige uma sintaxe diferente para ser usado no programa.

Para alterar a propriedade dentro do programa, use por exemplo: BorderIcons := [biSystemMenu, biMaximize]; Propriedades com editor: Algumas propriedades mostram um valor como (TFont) ou (TStringList), que não pode ser editado, e um botão , que quando clicado mostra um editor de propriedade especializado. Exemplo: Lines (do componente Memo), Font (que também

40

pode ser editada abrindo as sub-propriedades). O editor também pode ser chamado com um clique duplo na coluna de valor.

Propriedades Mais Usadas
Propriedades para Todos os Componentes
Duas propriedades existem para qualquer componente (inclusive para o formulário, que é considerado um componente): são Name (o nome do componente) e Tag. Esta última é uma propriedade numérica (tipo integer) que o Delphi não utiliza. Ela pode ser usada para guardar uma informação qualquer associada ao componente, apenas para uso interno.

Propriedades de Tamanho e Posição
Você pode alterar o tamanho e a posição do formulário, ou de um controle, movendo-o na tela ou arrastando suas bordas. Mas você também pode digitar suas coordenadas de posição e tamanho manualmente. Essas coordenadas são medidas em pixels, que são os pontos físicos da tela, e são especificadas pelas propriedades Left, Top, Width e Height:

Para um formulário, Left é a distância deste à extremidade esquerda da tela, Top é a distância em relação ao topo da tela. Para um controle, essas medidas são feitas em relação à área interna do formulário (excluindo as bordas). O tamanho do formulário ou controle é especificado por Width (na horizontal) e Height (na vertical). Todas essas propriedades podem ser alteradas também através de comandos de programa, para alterar dinamicamente a posição e tamanho de um controle.

Propriedades do Formulário
Outras propriedades alteram o posicionamento e tamanho do formulário. A maioria dessas propriedades só mostra efeito ao executar o programa. A propriedade WindowState controla como o formulário vai aparecer: wsNormal estado normal wsMinimized janela minimizada (aparece na forma de um ícone) wsMaximized janela maximizada (ocupando a tela inteira) A propriedade Position determina se o Windows pode alterar a posição ou o tamanho que você definiu para o formulário. O valor padrão é 'poDesigned': poDesigned posição e tamanho de acordo com o projetado poScreenCenter centraliza o formulário na tela poDefault o Windows pode mudar a posição e tamanho poDefaultPosOnly o Windows só pode mudar a posição poDefaultSizeOnly o Windows só pode alterar o tamanho A propriedade BorderStyle controla o estilo da borda do formulário: bsSizeable permite o usuário alterar o tamanho da janela bsSingle não permite alterar tamanho (estilo de borda fina) bsDialog não permite alterar tamanho (estilo de borda dupla) bsNone nenhuma borda, nem barra de título (não permite mover) bsToolWindow como bsSingle, mas com título menor bsSizeToolWin como bsSizeable, mas com título menor

41

O valor padrão é 'bsSizeable'. A diferença entre 'bsSingle' e 'bsDialog' é uma questão de padrões de interface, como veremos depois. A propriedade BorderIcons, que se expande em "sub-propriedades", determina quais ícones de controle aparecem na barra de título do formulário. 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 botão de ajuda com uma interrogação na borda. Esse botão pode ser usado para chamar uma tela de help. Só funciona se biMinimize e biMaximize estiverem desativados. A propriedade AutoScroll, como padrão, é verdadeira (contém o valor True). Isso faz com que o formulário mostre barras de rolagem automaticamente quando os controles não cabem na área visível da tela. Para testar, crie um controle qualquer, como um Edit e mova-o até deixar metade dele fora do formulário em alguma das extremidades. Vai aparecer uma barra de rolagem (horizontal ou vertical), que você pode usar para ver a área que atualmente não é visível. Se você quiser, pode desativar AutoScroll, colocando um valor False. Com isso, controles que estiverem fora da área do formulário não podem ser acessados pelo usuário.

Propriedades de Controles
Controles (ou componentes visuais), além das quatro propriedades de posição (Left, Top, Width e Height) têm propriedades que alteram sua aparência, a maioria existe também no formulário. A propriedade Font determina as características do texto mostrado pelo controle. No caso do formulário, ela afeta os controles contidos nele, não o próprio. Para testar, coloque três controles Label no formulário. Altere a propriedade Font do formulário, 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 formulário, apenas "Label2" e "Label3" serão alterados. O que determina se um controle usa uma fonte própria ou a do formulário é 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 formulário. A propriedade Color determina a cor do formulário ou controle. Existem várias formas de escolher uma cor. Você pode selecionar da lista o nome de uma cor específica (clBlack = preto, clBlue = azul, etc.) e nesse caso, a cor será sempre a que você especificou. Outra opção é usar nomes de cores relativas à configuração do Windows, como clWindow = cor de janela, clBtnFace = cor de botão, clWindowText = cor de texto de janela etc. Nesse caso, a cor real que será utilizada depende da configuração de cores do Windows no computador do usuário. Para cada controle que tem a propriedade Color, existe também uma propriedade ParentColor, que determina se o controle usa a cor definida pelo formulário ou sua própria cor individual (de forma análoga 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ê também pode esconder um controle ou item de menu do usuário alterando a propriedade Visible para False. Ele continua aparecendo em tempo de projeto, e você ainda pode utilizá-lo no programa, mas o usuário não vai vê-lo durante a execução. O texto mostrado por um controle é definido pela propriedade Caption, se ele não permite edição, ou Text, se ele permite edição pelo usuário. Uma facilidade que o Delphi fornece é a capacidade de colocar "dicas" [hints] que são mostradas quando o usuário 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 formulário (nesse caso, ParentShowHint, em cada controle, define qual das duas é usada).

42

OnKeyUp é acionado. Ele informa o caractere digitado como uma variável do tipo Char. Esse código identifica a tecla. qual botão foi pressionado e quais das teclas de modificação ([Shift]. Nota: A variável 'Key' é um parâmetro do procedimento de evento. o ponteiro vai mudar para uma ampulheta. Eventos de Mouse O evento OnClick. Crie o seguinte procedimento de evento. respectivamente. pode ser utilizado o evento OnKeyPress. veremos os eventos mais utilizados pela maioria dos componentes. e quando a tecla é solta. Eventos de Teclado Existem três eventos de teclado. existe o evento OnDblClick. crHourglass (ampulheta). como botões. [Insert]. Teclas que não geram digitação. Além disso. ou entre dois caracteres na mesma tecla. mas de formas diferentes. [Ctrl] e [Alt]) estavam pressionadas no momento. 43 . o evento OnKeyDown é acionado. basta o próprio nome. Cada um deles fornece informação sobre a tecla pressionada. Nesse projeto. Outros valores determinam ponteiros diferentes. não é preciso escrever o nome do formulário na frente (o que seria Form1. Agora quando você clicar no formulário. Vamos tratar esses eventos para o formulário. e também algumas propriedades vistas anteriormente. acionam apenas os eventos OnKeyDown e OnKeyUp. Quando é necessário distinguir os caracteres digitados. Esse evento não fornece nenhuma informação sobre as coordenadas do mouse. Os eventos OnMouseDown e OnMouseUp são acionados quando um botão do mouse é pressionado ou liberado. e não as teclas. begin if Key = '*' then Close. por exemplo crArrow (seta). [Home]. O evento OnMouseMove ocorre quando o cursor do mouse é movimentado sobre o controle. begin if Cursor = crDefault then {cursor é o padrão?} Cursor := crHourglass {muda para ampulheta} else Cursor := crDefault. O valor padrão (crDefault) diz para utilizar o cursor padrão atual (geralmente uma seta). Ambos informam para o procedimento de evento o código da tecla pressionada. como já vimos. também acionam este evento quando são ativados pelo teclado). como [F1]. Esses eventos informam a posição do mouse. um caractere pode ser gerado pelo pressionamento de mais de uma tecla. var Key: Char). [Ctrl]. Alguns eventos têm parâmetros. É importante notar que Cursor é uma propriedade do formulário.FormKeyPress(Sender: TObject.Cursor). Para cada tecla que é pressionada. Execute para testar. quando o cursor do mouse está posicionado sobre o controle. {senão muda pra default} end. Digite o seguinte no procedimento de evento: procedure FormClick(Sender: TObject). que são acionados em momentos diferentes. Clicando novamente ele retorna ao valor padrão. associado ao OnKeyPress: procedure TForm1. Eventos Comuns Crie um novo projeto. que é preenchido pelo Delphi. Além desse. Note que nem toda tecla aciona um evento OnKeyPress. que contém informações adicionais fornecidas pelo Delphi. não é possível distinguir entre maiúsculas e minúsculas. mas não o caractere digitado.A propriedade Cursor define qual o tipo de ponteiro (ou cursor) do mouse que será mostrado. ocorre quando o botão do mouse é pressionado e solto sobre o controle (mas alguns controles. Vamos tratar o evento OnClick para o formulário. end. Ele informa a posição atual do cursor do mouse. que informa um clique duplo (dois cliques em seqüência rápida). Por exemplo. Nesse caso.

Entre o begin e o end digite o seguinte: case Key of vk_Left: Left := Left .. As propriedades Left e Top determinam a posição do formulário na tela. compara uma variável com vários valores numéricos e executa um comando dependendo do valor. No caso os valores são dados pelas constantes 'vk_Left'. O evento OnEnter é acionado quando o controle recebe o foco de teclado. Controles de edição e similares possuem um evento OnChange.10.Com isso. Você pode cancelar o fechamento ou determinar uma ação diferente. a sua área de memória será liberada. Outros Eventos Os controles que podem receber o foco de teclado têm eventos que são acionados quando o foco de teclado muda. Repare que o procedimento tem vários parâmetros: 'Key'. como minimizar. confirmar se ele deseja salvar os dados. Execute e teste as teclas de seta para movimentar e a tecla '*' para fechar o formulário. end. É executado antes de qualquer outro evento do formulário. ou seja. ou depois que o usuário tecla [Tab] a partir do controle anterior.of.. Para tratar as setas. var Key: Word. Ocorre geralmente quando o programa está terminando. por exemplo. OnPaint: Útil para desenho de gráficos.10. 'vk_Right'. Eventos do Formulário Outros eventos do formulário correspondem a situações importantes de serem tratadas. O comando case. usando o método Close. Já o evento OnExit é acionado quando o controle perde o foco de teclado. OnClose: O formulário está sendo fechado. Esse evento é acionado quando ocorre uma modificação no conteúdo do texto.. depois de um clique do mouse..PAS e EVENTOSP. Para mover o formulário. 44 . por exemplo. crie um procedimento de evento para OnKeyDown: procedure TForm1. vk_Down: Top := Top + 10. por exemplo: OnCreate: Quando o formulário é criado. OnResize: Quando o usuário altera o tamanho do formulário. ou seja. que desta vez é numérica (tipo Word) informa o código da tecla pressionada e 'Shift' informa o estado das teclas de modificação..DPR. OnCloseQuery: O usuário está tentando fechar o formulário. OnShow: Logo antes do formulário ser mostrado na tela (pode ocorrer várias vezes durante a execução). O Delphi tem constantes predefinidas correspondentes aos valores. vk_Right: Left := Left + 10. Shift: TShiftState). precisamos comparar o valor de Key com cada um dos códigos de teclas de seta. Você pode cancelar o fechamento (fazendo CanClose := False) ou. OnDestroy: Quando o formulário está sendo destruído. Na verdade não é preciso saber o valor numérico de todos os códigos. Salve esse projeto como EVENTOS.FormKeyDown(Sender: TObject. depois que o usuário passa para outro controle por exemplo. na inicialização do programa. fazendo a movimentação do formulário na direção da seta utilizada. acrescentar ou apagar um caractere. basta alterar seus valores. como veremos. Agora vamos tratar as teclas de seta. ou destruir o formulário. o formulário será fechado. begin end. quando for pressionada a tecla ('*'). vk_Up: Top := Top . OnActivate: O formulário passou a ser a janela ativa (recebeu o foco). por exemplo.. OnDeactivate: O formulário passou a ser uma janela inativa. Inicialmente. Você pode usar para inicializar componentes.

{ rejeita a tecla } Renomeando um Procedimento de Evento O nome de um procedimento de evento aparece no código depois de "procedure TForm1. O nome do procedimento ("editOperando1KeyPress") é baseado no primeiro controle. begin if (Key < '0') or (Key > '9') then Key := #0. clique no primeiro. Acione o menu File|Open. Lembre-se: para selecionar dois controles.. begin end. ou o ícone SpeedBar e abra o CALCP. abra a página de eventos. da Tratando um Evento para Vários Controles: OnKeyPress Como vimos. Mas quando um mesmo procedimento é acionado por vários eventos (ou componentes) é melhor mudar esse nome.. Outros são simplesmente ignorados. com o código ASCII 8 (caractere #8). Podemos usar o evento OnKeyPress para validar a digitação e só permitir digitação de números. Substitua o nome atual "editOperando1KeyPress" por "TratarTecla" e tecle [Enter]. Vamos verificar se ela é numérica. com o nome do evento (sem o "On"). segure [Shift] e clique no outro. Isso acontece porque [Backspace] gera um evento OnKeyPress. que permitem interceptar cada tecla digitada pelo usuário. Isso quer dizer que os dois acionarão um mesmo procedimento de evento.DPR. clique no Object Inspector. Mas existe um problema: a tecla [Backspace] não funciona mais. no evento OnKeyPress. mas faremos dessa forma apenas para fins de aprendizagem. Quando você cria um procedimento de evento dessa forma. o nome ajuda a reconhecer a função daquele procedimento. Execute o programa e verifique que apenas caracteres numéricos aparecem. Para corrigir isso. Depois clique duas vezes nesse nome e verifique que na unidade. isso faz com que seja cancelada a digitação. var Key: Char). Quando o procedimento altera 'Key' para o valor #0. e se não for.". existem três eventos relacionados ao teclado. Selecione no formulário os controles 'editOperando1' e 'editOperando2'.Detalhes do Tratamento de Eventos Vamos retornar ao projeto CALCP. o Delphi renomeou o procedimento: 45 . var Key: Char). mas isso não importa. O primeiro é o chamado caractere nulo (código ASCII 0) que não corresponde a nenhum caractere imprimível. Mas o tratamento deve ser o mesmo para os dois componentes Edit.editOperando1KeyPress( Sender: TObject. Esse nome é criado pelo Delphi juntando o nome do componente que foi selecionado para tratar eventos. No Object Inspector. O outro é o dígito zero (código ASCII 48). quando o usuário digita uma tecla em um deles. { rejeita a tecla } end. O parâmetro "Key" que é passado contém a tecla digitada. O Delphi vai criar um procedimento da forma: procedure editOperando1KeyPress(Sender:TObject. rejeitar a tecla: procedure TForm1. Quando você percorre o arquivo da unidade. altere o if para o seguinte: if ((Key < '0') or (Key > '9')) and (Key <> #8) then Key := #0. Para mudar o nome. O caractere #0 não é a mesma coisa que '0'. como usar o componente MaskEdit da página Additional. Nota: existem formas bem mais fáceis de fazer validação de teclas no Delphi. ele fica associado a todos os componentes selecionados e vai ser executado quando o evento acontece com qualquer um deles — no caso. selecione qualquer um dos dois componentes. clique em OnKeyPress e clique duas vezes no valor do evento.

Eliminando um Procedimento de Evento Se você quiser eliminar um procedimento de evento. você criar um novo componente. não apague o corpo dele no código. porque o "editResultado" não aceita digitação (é somente leitura). no cabeçalho) está de acordo com o que o evento espera. begin if ((Key < '0') or (Key > '9')) and (key <> #8) then Key := #0. Nota: os procedimentos que aparecem na lista são apenas aqueles compatíveis com o evento. Selecione esse nome. Clique no evento OnKeyPress novamente e apague o nome do procedimento. se houver. Associando um Procedimento Existente Se depois de criar um procedimento. dessa forma. Um procedimento é compatível quando a lista de parâmetros (entre parênteses. { rejeita a tecla } end. não é útil associar esse procedimento. Só para teste. ou se você esqueceu algum componente de fora ao criar o procedimento. o Delphi não conseguirá localizar mais o procedimento e mostrará várias mensagens de erro. que é executado quando o conteúdo do controle é alterado. Repare que o procedimento vai desaparecer automaticamente. e o remove automaticamente do programa. var Key: Char). o Delphi nota que o procedimento está vazio.TratarTecla(Sender: TObject. 46 . Apague apenas os comandos entre o begin e o end . Aparece na lista o nome do procedimento de evento "TratarTecla". Clique no evento OnKeyPress e no botão de seta . Você não deve mudar o nome diretamente no texto da unidade. Quando você compila o programa. você pode ligá-lo a um procedimento já existente. Nesse caso. clique duas vezes no componente 'editOperando1'.procedure TForm1. Basta isso para associar o código dos procedimentos com os eventos correspondentes do controle. Se fizer isso. é necessário também excluir as declarações de variáveis. Agora salve o projeto. Selecione no formulário apenas o componente 'editResultado' (clique nele sem usar o [Shift]). É comum criar um procedimento por acidente. Isso desfaz a associação. Isso vai criar um procedimento para o evento OnChange.

Capítulo 7 Usando Vários Formulários Caixas de Diálogo Funções de Mensagem Exemplo: CalcData Gerenciando os Arquivos do Projeto Definindo o Formulário Principal 47 .

Funções de Mensagem Mensagens Informativas O procedimento ShowMessage permite mostrar uma mensagem simples para o usuário. onde: mensagem: é o texto da mensagem título: é o título que aparece na janela de mensagem. Esse valor pode ser um dos seguintes: IDOK botão Ok IDCANCEL botão Cancelar IDABORT botão Anular IDRETRY botão Repetir IDIGNORE botão Ignorar IDYES botão Sim IDNO botão Não 48 . De forma geral.MessageBox(mensagem. Os formulários auxiliares. (Ver abaixo) variável:recebe um valor inteiro que indica qual botão foi pressionado. Mas geralmente. Esse procedimento geralmente é usado para mensagens curtas. você pode dividir a string em partes. mostra uma mensagem como a seguinte (supondo que o título da aplicação é 'Meu Programa'): Nota: para definir o título da aplicação. que aparece inicialmente. chamados a partir do principal. o usuário pode abrir outros formulários do programa. Note que se o texto da mensagem é muito longo. clique no marcador "Application". mostra uma mensagem com botões que o usuário pode clicar para responder. A partir desse formulário. usando o operador "+". #13 e #10. Esse título será usado em todas as mensagens de agora em diante. Algumas funções do Delphi mostram caixas de diálogo predefinidas e você não precisa criar um formulário para usá-las. contendo apenas um botão de Ok. ' + 'Digite novamente. Uma caixa de diálogo é uma janela com a qual o usuário interage e depois retorna ao principal. Se você precisar de quebras de linha na mensagem. Por exemplo. você pode inserir os caracteres de fim de linha. você deve criar um formulário e utilizá-lo como uma caixa de diálogo. flags). geralmente são caixas de diálogo.').'). título. flags: é uma combinação de valores que determina quais botões ou ícones são usados na janela de mensagem. abra o menu Project|Options. quando você precisa de alguma coisa a mais. '#13#10 + 'Digite novamente. Por exemplo: ShowMessage('Erro de digitação no campo Nome. a sintaxe para usar essa função é: variável := Application. que é um método do objeto Application. e digite o novo título em Title.Caixas de Diálogo Um programa em Delphi geralmente tem um formulário principal. a chamada: ShowMessage('Erro de digitação no campo Nome. e com o qual o usuário interage. O título da aplicação aparece no título da mensagem. que não precisam de nenhum retorno do usuário. Mensagens de Confirmação A função MessageBox.

por "FormPrincipal".Para o formulário ficar centralizado altere a propriedade Position para "poScreenCenter". No título do formulário coloque "Menu Principal" e na propriedade Name. que é o nome default. troque "Form1". Exemplo: CalcData Vamos criar um pequeno programa que permite mostrar um calendário e executa a calculadora do Windows . Não e Cancela MB_YESNO 4 botões Sim e Não MB_RETRYCANCEL 5 botões Repetir e Cancelar MB_ICONERROR 16 sinal de erro crítico MB_ICONQUESTION MB_ICONEXCLAMATION MB_ICONINFORMATION 32 sinal de pergunta 48 sinal de advertência 64 sinal de informação MB_DEFBUTTON1 0 primeiro botão tem o foco (default) MB_DEFBUTTON2 256 segundo botão tem o foco MB_DEFBUTTON3 512 terceiro botão tem o foco Veremos exemplos dessas funções no próximo projeto. um componente "Edit"( )e ) . Coloque no formulário três componentes "Button" ( ) . Crie um novo projeto. Em outros projetos. Repetir e Ignorar MB_YESNOCANCEL 3 botões Sim.O valor de flags pode ser uma combinação de um ou mais dos seguintes valores: MB_OK 0 só botão Ok (default) MB_OKCANCEL 1 botões Ok e Cancelar MB_ABORTRETRYIGNORE 2 botões Anular. Altere as seguintes propriedades: um componente "Label" ( "Button1" btnCalendario Name Caption Calendário "Button2" Name btnCalculadora Calculadora Caption "Button3" btnFechar Name Fechar Caption "Edit" Name editData Text "Label" Data Caption O formulário irá ficar da seguinte forma: 49 . não colocamos nome no formulário porque ele não era utilizado dentro do código do programa.

A função retorna um valor indicando qual o botão pressionado. Isso chama a função MessageBox. no caso 'MB_IconQuestion + MB_YesNo'. diz para mostrar um ícone de pergunta e especifica quais os botões da mensagem (no caso. quer dizer que você esta interrompendo a tentativa do usuário de fechar o formulário. se o usuário clicar neste botão irá aparecer duas mensagens perguntando se deseja fechar o formulário. Criando um Novo Formulário Para criar um novo formulário no projeto.Pedindo Confirmação ao Usuário Agora vamos tratar o evento OnClick do item do "Button" Fechar . use o item File|New Form no menu do Delphi ou use o botão New Form: na SpeedBar. O último argumento. executamos o método Close para fechar o formulário. 50 . Execute o programa e clique no botão "Fechar". neste procedimento iremos deixar somente o método close. 'Confirmação'. o usuário pode usar as teclas [ALT+F4] ou clicar no ícone . são gerados os eventos. ) que fica na pasta "Win32". pois se deixarmos como está. No procedimento de evento digite o seguinte: if Application. informando o texto da mensagem. O novo formulário vai aparecer como "Form1" e ainda não tem nenhum componente. No primeiro podemos cancelar a tentativa do usuário de fechar o formulário.MB_IconQuestion + MB_YesNo) = idNo then CanClose := false A variável CanClose é passada como parâmetro pelo evento OnCloseQuery. Vamos retirar a mensagem que aperece quando clicar o botão "Fechar". "Yes" e "No"). ao sair do procedimento se esta variável for False.MessageBox( 'Tem certeza que quer sair?'. Então ao clicar no botão "Fechar" irá aparecer a mensagem perguntando se deseja sair do formulário. Se for idYes. podemos também alterar o valor da propriedade Width para 377. Notas:Para alternar do formulário para o editor de código pressione a tecla F12. OncloseQuery e o OnClose. Altere o seu nome (Name) para "formCalendario" e o título (Caption) para "Calendário". MB_IconQuestion + MB_YesNo) = idYes then Close. 'Confirmação'. Mas esta não é a única forma de fechar o formulário. altere sua Coloque o componente "MonthCalendar"( propriedade Name para "MtCData". Para mostrar a mensagem independente do modo que o usuário irá fechar . coloque o seguinte procedimento no evento OnCloseQuery do formulário "frmPrincipal" : if Application. Esse valor pode ser 'idYes' ou 'idNo' no caso. mas no segundo o formulário foi fechado.MessageBox('Tem certeza que quer sair?'. Mas ao fechar o formulário.O default dessa variável é True. Altere também a propriedade Position do formulário para "poScreenCenter". Para mostrar mais de um mês é necessário alterar o tamanho deste componente.

Isso vai alterar Caption para "Cancel".PAS (era "Unit1. Esse tipo de componente permite página "Additional" . Isso altera automaticamente as propriedades Caption (para "Ok"). Default (para True).é o primeiro ícone da página. Para o outro botão. arquivo de projeto) Em projetos com mais de um formulário. Vamos retornar ao formulário principal. Executando um Arquivo O botão "Calculadora" vai executar o calculadora do Windows .: formulário principal e projeto.PAS". faz com que o botão seja acionado por [Enter] e a propriedade Cancel faz com que o botão seja acionado pela tecla [Esc]. defina Kind com o valor 'bkCancel'. mas existem constantes predefinidas para facilitar.exe'. que era acrescentar um "P" ao nome do projeto.PAS (era "Unit2. primeiro formulário) CALCDATA. como já vimos. mostrar figuras junto com o texto. não usaremos o mesmo padrão de nomes dos outros. É melhor salvar o projeto agora porque vamos precisar dos nomes de unidades do projeto bem definidos para o próximo passo. No procedimento de evento OnClick . Para o primeiro botão. Execute o programa e verifique o resultado. Seu formulário irá ficar como a figura abaixo: Agora vamos acrescentar dois botões neste formulário. Altere Caption para o valor "Cancelar". Notas: A propriedade no componente "BitBtn" que permite colocar imagem é a propriedade Glyph. vamos usar o componente "BitBtn" da . A propriedade ModalResult de um botão (de um Button "normal" ou de um BitBtn) é importante com caixas de diálogo. Esse valor é numérico. Cancel para True. o botão fecha o formulário e retorna esse valor para quem "chamou" o formulário. O Delphi vai pedir os nomes na ordem segundo formulário. cujo arquivo é "Calc. Ela recebe como parâmetros o nome do programa e um valor que indica como a janela do programa deve aparecer. ModalResult para mrCancel. Salvando o Projeto Salve o projeto nesse ponto para dar nome aos arquivos.Este componente mostra um calendário. faça o seguinte: begin WinExec('calc. Quando ModalResult contém um valor diferente de 'mrNone' (o default). A função WinExec é uma função do Windows que executa um programa.DPR". para fazer isto clique no ícone menu View/forms. e Glyph para conter o desenho de um "x". Chame-os respectivamente de: EXECCALEN.PAS". ModalResult (para 'mrOk') e Glyph (para conter uma imagem correspondente ao Ok). A propriedade Default.exe". irá aparecer a seguinte tela: ou [Shift+F12] ou 51 . end. SW_SHOWNORMAL). segundo formulário) EXECPRIN. como 'mrOk' e 'mrCancel'. defina a propriedade Kind [espécie] com o valor 'bkOk'. Para isso existe um comando que converte a string em PChar.DPR (era "Project1.

Quando uma janela modal está na tela.ShowModal = mrOk then editData. o botão "Cancelar" foi pressionado. o componente 'editData' vai receber a data que foi escolhida . Ele deve terminar de executar a tarefa atual e fechar a janela modal para poder retornar à principal.Date).Text := DatetoStr(FormCalendario. Se esse valor for 'mrOk'. o Delphi tem vários recursos. você deve dar nomes descritivos a todos os formulários e unidades. No arquivo da unidade EXECPRIN. o código não conseguiria acessar o outro formulário. Se uma janela não é modal.DFM}: uses ExecCalen. temos que converte o conteúdo da propriedade Date para String. { ou } nome_do_formulário. pode ficar difícil de compreender e manter. Repare que isso é feito com a sintaxe: FormCalendario . não vai conseguir usá-lo). Date Mas para esse código funcionar falta uma coisa. O segundo formulário aparece como uma janela modal(se você clicar no formulário principal. "ExecCalen" é o nome da outra unidade. o botão "Ok" foi pressionado. por isso utilizaremos ShowModal. Gerenciando os Arquivos do Projeto Um projeto grande. Uma janela modal é a interface recomendada para caixas de diálogo. o usuário pode alternar livremente entre ela e outras janelas não modais. 52 . Execute o programa e clique no botão "Calendário". da seguinte forma: nome_do_formulário. procure a palavra implementation.ShowModal. com vários formulários. e acrescente o seguinte logo depois do {$R *. MtCData . Quando o valor é 'mrOk'. Salve novamente o projeto. Primeiro o método ShowModal é chamado e o valor retornado é verificado. Para facilitar o tratamento de projetos.PAS. que contém o formulário "FormCalendario". através de uma cláusula uses. no evento OnClick do botão "Calendário" iremos chamar o formulário "formCalendário". No código do procedimento criado coloque: if FormCalendario. Como a propriedade Text do componente "Edit" é do tipo String e a propriedade Date do componente MonthCalendar e do tipo TDate. Se ele for 'mrCancel'. Ele irá mostrar o formulário principal. Mantenha ele aberto no Delphi. Se não houvesse essa cláusula.Escolha a opção "formPrincipal" e clique em "OK". Note que para utilizar esses recursos com eficiência.MtCData.Show. por isso foi necessário usar a função StrtoDate. Para mostrar um outro formulário basta usar o método Show ou o método ShowModal. essa valor iremos obter pela propridade Date do componente MtCData no formulário formCalendario. Para retornar ao principal clique no botão "Ok". o usuário não pode utilizar outras janelas do programa. A diferença entre os dois é que ShowModal mostra o formulário de forma modal. Se um formulário precisa acessar outro que está em outra unidade. pois vamos analisar algumas opções do Delphi utilizando esse mesmo projeto. é preciso adicionar uma referência à unidade.

Para isso use a tecla [F12] ou o botão (Toggle Form/Unit) da SpeedBar. Nota: Quando você adiciona um arquivo ao projeto. Repare que aparece um nome a mais. Usando o Project Manager O Delphi também inclui um pequeno utilitário que permite ter uma visão geral do projeto. abrir o formulário associado.. a partir dela. O Project Manager [gerente de projeto] tem uma aparência como a seguinte: 53 . Ele continua no diretório do projeto e pode ser utilizado novamente no mesmo projeto ou em outros projetos.. você pode alternar entre eles com um clique de mouse. pedindo uma confirmação. você pode alternar livremente entre elas clicando nas abas do editor de código (ou usando [Ctrl+Tab]): E você também pode alternar para uma unidade e.. No teclado. Depois que as unidades foram abertas. É claro que se você puder ver os dois (ou mais formulários) ao mesmo tempo na tela. Ele vai mostrar uma janela com os nomes de todos os formulários (no caso "FormPrincipal" e "FormCalendario"). você pode usar [Shift+F12]. o Delphi automaticamente se oferece para adicionar uma referência à unidade do outro formulário. você pode usar [Ctrl+F12]. Se outros projetos estiverem utilizando o arquivo. use o botão (Select unit from list). Você também pode adicionar um arquivo ao projeto (como um formulário que você criou em outro projeto) usando o botão da SpeedBar ou o item de menu Project|Add to project. ou clique duas vezes no nome dele. que analisaremos mais tarde. clique no item View|Project Manager no menu do Delphi. use o botão project.. e selecione qual você quer remover. o Delphi não faz uma cópia do arquivo. Quando você remove um arquivo do projeto. Escolha um deles e clique Ok. em vez de formulários. clique no botão (Select form from list) da Speedbar. ela vai aparecer no editor de código. ou o item Project|Remove from Para remover um arquivo do projeto. No teclado. Nota: Se você tentar executar o programa sem fazer essa alteração. ele será compartilhado entre eles. Essa opção traz o arquivo de projeto (DPR). Quando você selecionar uma unidade. o arquivo não é excluído do disco.. Para ver a lista de unidades disponíveis. que é o nome do projeto ("CalcData").Usando a Speedbar ou Menus Para alternar entre os formulários do projeto. Para usá-lo.

o editor de código.. Podemos adicionar um novo projeto e também um projeto já existente. isto se não estiver no mesmo diretório do projeto. ToolBar: Se está opção estiver marcada . etc. é mostrado uma barra de ferramento onde apareçem as opções: Status Bar: Mostra o nome e o caminho do arquivo de projeto. e neste arquivo contém todos os projetos associados ao grupo. Podemos trabalhar com mais de um projeto ao mesmo tempo . que serve para manter agrupados todos os itens adicionados. View Project Group source : Para cada grupo criado é gerado um arquivo com a extensão bgp. Com isso irão aparecer as seguintes opções: Estas opções são utilizadas para: Add New Project : Adicionar um novo projeto ao grupo. Isso é muito útil . aparece o diretório do arquivo. Os arquivos podem ser salvos nos "grupo de projetos". o object inspector. 54 . se você quer desenvolver um desenvolver um programa EXE e uma DLL que trabalham em conjunto. podemos adicioná-lo ao grupo através desta opção.O Project Manager mostra uma tabela com os nomes de cada unidade do projeto e ao expandir essas unidades ele mostra o formulário correspondente . Na coluna "Path". Add Existing Project : Caso o projeto já exista . Save Project Group : Salva todas as alterações feitas neste grupo. como por exemplo. Dockable: Permite encaixar a janela atual em outra janela. Save Project Group As: Salva as configurações deste grupo com outro nome. para isso clique com o botão direito do mouse na palavra ProjectGroup1(caso não tenha mudado o nome do grupo). a não ser no caso de uma unidade independente.Esta opção mostra o conteúdo do arquivo cuja extensão é bgp.

55 .

selecione o nome do formulário que você quer que seja o principal. "FormCalendario" e clique "Ok". Quando você executar o programa.. O formulário principal de um projeto é o que aparece inicialmente para o usuário. Na página Forms . acione o menu Project|Options. mas você pode mudar isso a qualquer momento.. 56 . Para mudar. lista "Main Form". por exemplo.Definindo o Formulário Principal Esse exemplo que criamos possui um formulário principal e um formulário Calendário. Depois retorne para a opção anterior. esse formulário vai aparecer em vez do "FormPrincipal". Inicialmente o formulário principal é o primeiro Formulário criado no projeto.. e a partir do qual os outros são chamados.

Capítulo 8 Estrutura das Unidades Estrutura Geral das Unidades O Código Gerado pelo Delphi Unidades Associadas e Independentes Compilação de Unidades Usando uma Unidade Resolvendo Conflitos de Nomes Arquivo de Projeto 57 .

. No projeto anterior (CALCDATA. constantes. editData: TEdit. Forms.. mas para começar.PAS.. O Código Gerado pelo Delphi Você pode criar suas próprias unidades.Quando você cria um formulário no Delphi. end.. type TformPrincipal = class(TForm) btnCalendario: TButton. btnCalculadora: TButton.. que inicia a seção de interface da unidade. é a da classe de formulário. A primeira declaração. e qual a forma geral da estrutura de uma unidade.DPR) abra a unidade EXECPRIN. A classe é uma definição dos componentes que o formulário contém. que contém algum código gerado automaticamente pelo Delphi. colocada automaticamente. procedure btnFecharClick(Sender: TObject). implementation { itens para uso interno } . Seção de Interface interface uses Windows. . Classes. Após a cláusula uses. em outras unidades. que contém uma lista de nomes de outras unidades que são utilizadas por esta. Essa lista é mantida automaticamente. Graphics.StdCtrls. Controls.) que compõem a biblioteca do Delphi. você pode acrescentar declarações de tipos de dados. O que for declarado apenas na seção de implementação é visível apenas para uso dentro da própria unidade: unit Execprin. private 58 . mas você pode acrescentar outros nomes à lista. Dialogs. Neste capítulo veremos como é a estrutura do código gerado pelo Delphi.. Estrutura Geral das Unidades Todo arquivo de unidade é dividido basicamente em uma seção de interface e uma seção de implementação. procedimentos etc. automaticamente é criada uma unidade associada. o que é declarado na seção de interface (variáveis. Em geral.. Nós veremos a classe de formulário mais em detalhes posteriormente. interface { itens visíveis externamente } . btnFechar: TButton. variáveis.. procedimentos e funções. Messages. Depois vem a palavra interface. vamos ver a estrutura do código que o Delphi gera automaticamente num arquivo de unidade. Você também pode criar uma unidade independente. e dos procedimentos de evento definidos nele. Nesse caso esses nomes são de unidades do Delphi (Windows. A seção de interface começa com uma cláusula uses. que está associada ao formulário principal (FormPrincipal). Label1: TLabel. SysUtils. Verifique que o cabeçalho da unidade contém uma linha: unit Execprin. por exemplo. . além do código que você acrescenta nos procedimentos de evento.) é visível externamente. SysUtils. para usar como uma biblioteca de funções e procedimentos. A primeira linha contém a palavra unit seguida do nome da unidade (que corresponde ao nome do arquivo).

var FormPrincipal: TFormPrincipal. Depois vem o corpo de cada um dos procedimentos de evento. .. Mas você pode também criar unidades independentes. no Delphi.. Após todos os procedimentos existe uma linha contendo apenas "end. vem a seção de implementação da unidade. que contém o seguinte: implementation {$R *. Com a palavra end.. mesmo sem especificar comentários. end..DFM} não é um comentário. apesar de parecer com um.{ Private declarations } public { Public declarations } end. A declaração {$R *. Essa linha sinaliza o final do arquivo da unidade. e o código da unidade geralmente está ligado (através de eventos) com os componentes do formulário..FormCloseQuery(Sender: TObject.. mas o processo de criar uma unidade independente é simples: selecione o item de menu File|New.DFM) com o arquivo de unidade." (end seguido de ponto final).var CanClose: Boolean). clique no ícone Unit e clique Ok. procedure TformPrincipal. o nome da classe de formulário ("TFormPrincipal") é incluído como prefixo no cabeçalho do procedimento. Unidades Associadas e Independentes No Delphi. interface 59 . No caso. é criada uma unidade contendo apenas o esqueleto das seções. end.. procedure TformPrincipal.. Depois dessas declarações. Esse tipo de declaração é chamada de diretiva do compilador e é uma instrução para o compilador interno do Delphi. o que ela faz é associar o arquivo de formulário (EXECPRIN...DFM} uses execcalen. portanto não a remova. Note que em cada um deles. end. Com isso. Vamos ver alguns exemplos mais tarde. O compilador ignora tudo que for digitado depois dessa linha. termina a definição da classe. uma unidade associada a um formulário sempre é tratada e utilizada em conjunto com o formulário.btnFecharClick(Sender: TObject). como a seguinte: unit Unit2. que contém apenas rotinas de código e nenhum componente. Depois o Delphi acrescenta uma declaração de variável para o formulário. begin . Essa diretiva é necessária para o funcionamento do programa. begin .

Rotinas. fornecendo um outro nome. Essa compilação é feita em várias fases. é gerado um arquivo de unidade compilada (. Na cláusula uses. interface uses Forms.DCU).. com o mesmo nome do projeto e extensão EXE. Caso queira compilar todos os projetos existente no grupo escolher Project|Compile All Projects.PAS).. . apenas as unidades alteradas desde a última compilação são recompiladas (. O processo de compilação pode ser resumido com o diagrama: Usando uma Unidade Uma unidade sempre é utilizada por outra unidade (ou pelo programa principal. {nome da outra unidade} . ele recompila. O Delphi verifica isso comparando a data/hora do arquivo PAS com a data/hora do arquivo DCU correspondente. Para compilar o programa. Para isso. Da primeira vez que o projeto é compilado. Por exemplo: unidade FRMTESTE. e esses arquivos DCU são mantidos no disco. mais os arquivos (RES) e o arquivo DPR são combinados em um único arquivo EXE independente. Depois todos os arquivos DCU..PAS: unit FrmTeste.. Da próxima vez que o projeto for compilado. ou quando você aciona Project|Compile (nome do projeto ativo). Você pode também forçar o Delphi a recompilar todas as unidades sem verificar a data. como veremos)..PAS -> . use o comando Project|Build (nome do projeto ativo) . 60 . Compilação de Unidades O Delphi compila o seu projeto quando você executa o programa. caso queira recompilar todos os projetos pertencentes ao grupo escolher Project|Build All Projects. são especificadas quais as unidades utilizadas.implementation end. o Delphi reúne todas as unidades do projeto e cria um arquivo executável..DCU). para cada arquivo de unidade (. Quando você salva o arquivo da unidade. Se o arquivo fonte for mais recente. o Delphi vai alterar a declaração no cabeçalho para refletir esse nome. implementation procedure. Controls.

a unidade FRMTESTE. então o Delphi recompila a unidade dependente (gera o arquivo . utiliza outra (Rotinas).begin Contador := 30. end.PAS: unit Rotinas. e gera uma mensagem de erro ("Circular unit not allowed"). que referencia FRMTESTE. que estão declarados na seção de interface da outra (ela não tem acesso a identificadores declarados apenas na seção de implementação da outra). Quando uma unidade (FrmTeste). implementation . que depende dela. Existem dois lugares onde pode ser colocada a cláusula uses: no início da seção de interface. procedure AumentaCont. é sempre melhor acrescentar a referência para a outra unidade na seção implementation. isto é. toda vez que a unidade ROTINAS é alterada. é recompilada primeiro. então os identificadores da outra podem ser usados já na parte de interface. interface var Contador: integer.. os identificadores só podem ser usados a partir da parte de implementação. ela passa a ter acesso a todos os identificadores. o Delphi não consegue determinar a ordem de compilação das duas. Se você referenciar a outra unidade na cláusula uses da parte de implementação. como variáveis e procedimentos... Duas unidades podem se "utilizar" mutuamente. . Nesse exemplo.DCU) sempre que a outra é alterada. end. 61 .. Por isso. pode haver também uma cláusula uses em ROTINAS. AumentaCont. Se duas unidades dependem uma da outra através da seção de interface. Mas se ambas as referências estiverem na parte interface das unidades. Só é realmente necessário colocar a referência 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). ou no início da seção de implementação. unidade ROTINAS. end. Os identificadores da outra unidade só se tornam visíveis a partir do ponto onde a outra unidade foi referenciada. Se você colocar a referência à outra unidade na cláusula uses da interface.

Contador := 34. por exemplo: Rotinas. e utiliza a unidade ROTINAS. que também contém uma variável chamada 'Contador'.PAS. prefixado com o nome da outra unidade. Qualquer identificador pode ser usado dessa forma para resolver o conflito de nomes. suponhamos que FRMTESTE. Isso gera uma ambiguidade quando você usa o nome.PAS contenha uma variável chamada 'Contador'. você pode usar um identificador qualificado. Por exemplo. o Delphi vai dar prioridade à variável da unidade atual ('Contador' em FRMTESTE). Se você colocar na unidade FRMTESTE um comando: Contador := 34. 62 . Mas para acessar a variável da outra unidade (ROTINAS).Resolvendo Conflitos de Nomes Pode acontecer de você ter um identificador que tem o mesmo nome na unidade atual e em outra que está sendo utilizada. isto é.

Capítulo 9 Outros Tipos de Dados e Depuração Tipos Enumerados Tipos Faixa Vetores Exemplo: Cálculo de Média Conjuntos Depuração 63 .

A declaração desse tipo. no código fonte da VCL. é de um tipo enumerado (TFormBorderStyle) que contém quatro valores possíveis. Tipos enumerados melhoram a legibilidade do programa.. Desquitado. Operações com Ordinais Um tipo enumerado também é um tipo ordinal.ex.: 0 para Solteiro.. Uma variável desse tipo pode assumir qualquer um desses valores. também se aplicam a ele todas as operações que podem ser feitas com tipos ordinais. A propriedade BorderStyle do formulário. Casado. tipos ordinais podem ser usados para índices de vetor (como veremos adiante) ou para criar conjuntos (como veremos adiante) e podem ser usados com o comando case que foi visto anteriormente.3) e isso tornaria difícil a escrita e manutenção 64 . com uma declaração de variáveis normal: var estCiv: EstadoCivil. vistas no Capítulo sobre Variáveis e Tipos de Dados e outros: · Para obter o próximo elemento da seqüência: usa-se a função succ. Por exemplo: estCiv := Casado. Casado. bsSingle. bsDialog). · Para percorrer uma faixa de elementos: pode ser usado o comando for (visto em Estutura de Controle) para fazer um laço: for estCiv := Solteiro to Viuvo do . podem ser criadas variáveis desse tipo.. etc..Tipos Enumerados Um tipo enumerado é composto por uma lista seqüencial de valores simbólicos. como vimos antes. como os tipos inteiros. é: type TFormBorderStyle = (bsNone. Mas eles são manipulados de forma eficiente pelo Object Pascal. os valores possíveis teriam que ser codificados como números (0.2.1. Após criar um tipo de dados. if estCiv = Viuvo then begin . evitando que você precise codificar uma variável com valores numéricos (p. Além disso. Esses valores não são numéricos e não são strings de texto. A variável 'estCiv' só vai poder assumir um dos valores do tipo: Solteiro. etc. O primeiro elemento tem a posição zero. por exemplo. Cada valor possível representa um estilo de borda do formulário. Por isso. pois internamente são tratados como constantes numéricas. · Para saber a posição do elemento na seqüência: usa-se a função ord. Se BorderStyle fosse uma propriedade numérica em vez de enumerada. end.. {o valor será Desquitado} · Para obter o elemento anterior: usa-se a função pred. . Viuvo). usa-se uma declaração type: type EstadoCivil = (Solteiro. ord(Desquitado) = 2 e ord(Viuvo) = 3 e ord(estCiv) retorna um valor dependendo do valor atual da variável. e pode ser usada para converter um valor enumerado em numérico. Ela retorna um valor indicando a posição do elemento na lista. Tipos Enumerados no Delphi A própria VCL do Delphi utiliza tipos enumerados em vários lugares. 1 para Casado. Por exemplo: pred(Casado) retorna o valor Solteiro. São apenas constantes simbólicas que representam uma informação. bsSizeable. ord(Casado) = 1. Por exemplo: ord(Solteiro) = 0.. o tipo Char e o tipo Boolean. Para criar um tipo enumerado.). estCiv := succ(estInicial). Por exemplo: estInicial := Casado.

Depois que o programa já tenha sido testado. na página "Compiler". quando for gerar a versão final.. Char... x:integer.. 65 . est1: EstadoNaoViuvo. você deve acionar o menu Project|Options. Vetores Um vetor (também chamado matriz) é uma variável que contém vários elementos do mesmo tipo de dados. Se eles fossem codificados como strings de texto ('bsNone' etc. os seguintes comandos geram erro de execução. nem sempre o Delphi verifica se um valor está dentro da faixa. pode utilizar um tipo faixa para que o próprio Delphi se encarregue de verificar isso automaticamente. informando o tipo do índice e o tipo dos elementos do vetor (ou tipo base). dm := x. Um tipo faixa é uma restrição sobre os valores de um tipo ordinal qualquer. Por exemplo: type EstadoCivil = (Solteiro.Desquitado. LetraMaiuscula = 'A'. Podemos criar os vetores de duas formas : Estática e Dinâmica.31. O tipo faixa é declarado com o valor inicial e final da faixa. Os valores inicial e final devem pertencer a um tipo ordinal: inteiro. você pode criar variáveis baseadas no tipo: var dm: DiaMes..30] of double. garantindo que ela não vai receber um valor fora da faixa.. enquanto que um vetor dinâmico não tem tamanho declarado e seu tamanho pode ser mudado durante a execução do programa. separados por '. marcar ou desmarcar o item "Range Checking".' (um ponto seguido de outro). Geralmente você deve compilar com "Range Checking" ativo apenas durante o desenvolvimento do programa. Por exemplo. Quando essa opção está marcada. Viuvo). Desquitado. Casado. ao compilar o programa o Delphi gera código para cada atribuição de variável do tipo faixa. seria muito ineficiente o armazenamento e manipulação dos valores. Vetores Estáticos Para criar um tipo de dados que representa um vetor. letra2: LetraMaiuscula. desative essa opção para aumentar a eficiência da execução. Cada elemento possui um índice que identifica esse elemento no vetor. com uma mensagem "Range Check Error": x := 32.. {erro: ' '(espaço) está fora de faixa} estCivil := Viuvo. Qualquer atribuição a uma variável do tipo faixa é verificada.do programa. est1 := estCivil. Um vetor estático tem um tamanho definido. Mas esse código gerado aumenta o tamanho do programa e pode também reduzir a velocidade de execução. Ele só faz isso quando a opção "Range Checking" [verificação de faixa] está ativa nas opções do projeto. ou enumerado. Depois de declarar o tipo. EstadoNaoViuvo = Solteiro. letra1.). usa-se uma declaração array. DiaMes = 1. {erro: 32 está fora da faixa} letra1 := Chr(32).'Z'. Tipos Faixa Se você sabe que determinada variável só pode pertencer a uma faixa de valores definida. {erro: Viuvo está fora da faixa} Opção "Range Checking" Na verdade. Por exemplo: type TVetor = array [1. para saber se o valor está dentro dos limites. Para alterar essa opção. e.

TVetPresenca = array [DiaMes] of TPresenca.. x: integer. ind := 10. Às vezes o Windows permite ao usuário ignorar o erro e continuar. o Delphi vai verificar em tempo de execução se a variável está na faixa. vetC: TVetor. causando erros em outras partes do programa. Como o índice pode ser qualquer tipo ordinal ou tipo faixa.. o Windows mostra uma mensagem ("Este aplicativo provocou um erro e será finalizado"). mas apenas se a opção "Range Checking" estiver ativa. com resultados imprevisíveis. Se o índice for uma variável. Feriado). Como o Windows restringe o acesso à memória apenas às áreas reservadas ao programa. ele pode ser do tipo Char.'Z'] of longint. TVetorBool = array [0. Falta.. TPresenca = (Presenca.30] of double. ele vai interceptar essa tentativa de acesso e terminar o programa. x := vetA[5]. mas na maioria das vezes.. begin for letra := 'A' to 'Z' do freq[letra] := 0. Verificação de Faixa para Vetores O índice do elemento pode ser constante ou variável.. var freq: TFreqLetras. a única opção é finalizar a execução. vetB[ind] := x.Essa declaração cria um tipo de vetor. vetB. Você pode inserir a definição do tipo na própria declaração de variável: var vetA: array [1. De qualquer forma. Boolean ou enumerado. é possível acessar posições de memória fora do limite do vetor. Você pode também definir um tipo faixa antes e depois utilizá-lo em um vetor: type DiaMes = 1. Esse tipo pode ser usado para declarar uma ou mais variáveis: var vetA: TVetor. esse índice deve estar na faixa definida pelo tipo do índice. O índice não precisa começar em um ou zero.31. quando você só precisa de uma variável daquele tipo. Usando Outros Tipos de Índice O tipo do índice do vetor é um tipo faixa. com índices na faixa de 1 a 30 (um tipo faixa) e elementos do tipo Double. Se "Range Checking" estiver desativado. e com isso. mas isso é uma convenção bastante utilizada para tipos de dados. e seus elementos individuais podem ser acessados informando o índice do elemento entre colchetes: begin vetA[3] := 1000.10] of boolean. Geralmente.3] of integer. antes de terminar. qualquer valor é admitido como índice. Na verdade não é necessário definir um tipo. O nome do tipo não precisa começar com "T". e nesse caso essa variável será modificada para conter um valor inválido. a mesma opção que controla verificações de tipos faixa. e por isso usa a mesma sintaxe. ind. Ou a posição pode estar numa área de memória controlada pelo Windows. end. por exemplo: type TVetorInt = array [-3. Cada variável declarada é um vetor com 30 elementos do tipo Double. 66 . letra: Char. maior: Longint. Essa posição de memória pode estar num espaço ocupado por outra variável. por exemplo: type TFreqLetras = array ['A'.

// muda o tamanho do vetor multidimensional setLength (Matriz[0]. SetLength(Vetor. . lin. Nesse caso. TMarcador = (marcaX.0.Viuvo] of string..col:integer. // muda o tamanho do vetor Vetor[5] := 5. cubo[i. {três índices} end. permitindo representar um vetor de vetores. usa-se a propriedade Setlength novamente com o novo tamanho que deseja .30] of double.10.k] := 0. informando o tipo dos elementos do vetor (ou tipo base).. O índice inicial do vetor é sempre zero.. i. n: TMatriz. begin setLength (Matriz. var m.10. Outros exemplos são: type TVetIndBool = array [False. 67 .k:integer.10. usa-se dois índices } m[i.True] of integer. TJogoDaVelha = array [0..10] of integer. // Redefine o tamanho para 20 Vetor[20] := 5. 0. Um vetor multidimensional pode ser criado definindo vários tipos de índices: type TMatriz = array [1.maior := freq['A']. TVetIndEnum = array [Solteiro. O conteúdo do vetor na posição 20 é 5.j.j. marcaNada). marcaO. A idéia é a mesma do anterior. cada elemento possui dois ou mais índices.. begin { para acessar um elemento...2. TCubo = array [1. por Exemplo: var Matriz : array of array of double. // ele tem elemento de 0 a 9 end.j] := 100. 20). begin N := 10.. Vetores Multidimensionais Um vetor também pode ter mais de uma dimensão. Essa informação é fornecida em tempo de execução através do procedimento SetLength. Por exemplo: continuando o exemplo anterior acrescente as seguinte linhas: SetLength(Vetor. A diferença do vetor estático é que não informamos os tipo do índice e o seu tamanho.. 1. N:integer.2] of TMarcador. mas não informamos o tamanho do vetor durante a definição. Para redefinir o tamanho do vetor . Podemos também criar vetores multidimensionais dinâmicos. 1. 2).. cubo: TCubo. for lin := 0 to 2 do for col := 0 to 2 do jogo[lin. Vetores Dinâmicos Para criar um vetor dinâmico também temos que utilizar a declaração array. N). end.. 1. var Vetor : array of double. 2). col] := marcaNada. jogo: TJogoDaVelha. seu tamanho é definido durante o tempo de execução utilizando também o método SetLength e além disso é permito criar para cada linha um número diferente de elementos.

para que ele possa ser "pressionado" usando a tecla [Enter]. A variável 'Valores' é um vetor do tipo 'TVetorInt'.. Para o 'btnAdicionar'. e depois calcule a média dos valores fornecidos. contador} 68 . vamos criar um novo projeto. ou seja. No início da seção de implementação. vamos também incrementar o contador. 5). Pressione [F12] para abrir o arquivo da unidade. Altere também a propriedade Color escolhendo o valor 'clBtnFace'. essa variável será incrementada. coloque a propriedade Text vazia . coloque um componente Edit que vai apenas mostrar o resultado. p/ inteiro} ContValores := ContValores + 1.1] := 3. o que vai proibir a edição do valor. Exemplo: Cálculo de Média Para ver na prática como utilizamos vetores. Adicionando um Elemento No código do botão 'btnAdicionar'. vamos adicionar na unidade uma declaração para o tipo do vetor e uma declaração de variável desse tipo. Com isso.setLength (Matriz[1]. Digite o seguinte: procedure TForm1. No formulário altere a propriedade Caption para "Calcula Média" e crie componentes no formulário conforme o seguinte: Crie um rótulo (componente Label) com Caption "Número:" e ao lado dele um componente Edit com nome "editNumero" . ContValores: integer. o que fornece ao usuário uma indicação visual de que ele não pode ser editado. A cada vez que for clicado o botão "Adicionar". faça a propriedade Default = True. A variável 'ContValores' será um contador usado para especificar quantos elementos do vetor estão sendo usados no momento.{conv. Crie os botões como mostrado. digite o seguinte: type TVetorInt = array [1. e mude seus nomes. var Valores: TVetorInt. Defina seu nome como 'editMedia'.Text). var numero: double. 'btnLimpar' e 'btnCalcular'.3] of double. A cada clique. Matriz[1. Declarando o Vetor Antes de fazer qualquer tratamento de eventos.btnAdicionarClick(Sender: TObject). O programa vai permitir que o usuário informe uma lista de valores. {increm. 4] := 5 end.Altere sua propriedade ReadOnly para True. Ao lado do rótulo "Média:". ele vai ficar da mesma cor do formulário e dos botões. respectivamente para 'btnAdicionar'. um vetor com elementos do tipo 'double' e índices de 1 a 3. vamos adicionar o número que foi digitado (em 'editNumero') ao vetor. begin numero := StrToFloat(editNumero. Matriz[0. após a palavra implementation. Coloque sua propriedade Text vazia.

Digite um número e clique no "Adicionar". para evitar um erro de execução. seu exemplo pode até continuar funcionando. Faça o seguinte: procedure TForm1. Com isso se pedir para informar mais de 3 números para ser adicionados a média .btnLimparClick(Sender: TObject). {guarda o elemento} { Facilita a digitação do próximo número } editNumero. o programa devolve o foco de teclado para o controle. determinado por 'ContValores'.0. ou tecle [Enter]. por exemplo. var soma: double.Text := 'Erro' else editMedia. editNumero. Limpando a Lista O botão 'btnLimpa' vai "limpar" a lista de valores. o laço for não fará nada (o valor final é menor do que o inicial). devemos fazer uma divisão dessa soma pelo contador. vai depender da área de memória que foi utilizada para acrescentar esses valores que foram colocados a mais. begin ContValores := 0. vamos verificar se o contador é zero: if ContValores = 0 then editMedia. usando o método Clear. No menu Project|Options na pasta Compiler se a opção RangeCheck estiver marcada . Mas antes. Isso é feito com o método SetFocus. Na verdade não precisamos percorrer todos os elementos do vetor. Note que se 'ContValores' inicialmente for zero. Digite o seguinte. se você digitar um valor não numérico e clicar em Adicionar. apenas zerar o contador. Se você digitar. 69 . (Repare que.Text := FloatToStr(soma/ContValores).SetFocus. por enquanto: procedure TForm1. para que ocorre esta verificação a opção RangeCheck tem que estar marcada.btnCalcularClick(Sender: TObject). temos que primeiro achar a soma dos elementos e depois dividir a soma pelo contador de elementos. for i := 1 to ContValores do soma := soma + Valores[i]. como o programa não faz ainda verificação de erro. Isso facilita que o usuário digite seqüencialmente os números. i: integer. Para isso. o valor inicial é sempre 1 e o valor final é variável. Também para facilitar. end. Repita o processo para adicionar alguns números à lista. begin soma := 0. o programa limpa o controle 'editNumero'. o Delphi não irá fazer a verificação se ultrapassou o tamanho do vetor. Depois clique em "Calcular" para calcular o resultado. Note que o laço for é útil para percorrer elementos de um vetor. desmarque esta opção e pede para recompilar todo o projeto novamente (Project|Compile Mediap).Clear. Repare que depois de adicionar o elemento. Calculando a Média dos Elementos O botão 'btnCalcula' vai fazer a tarefa de calcular a média dos elementos do vetor. end. Testando o Programa Execute o programa.Valores[ContValores] := numero. para indicar que não há nenhum elemento guardado. No caso. 28 e 34. vai ver uma mensagem de erro do Delphi). 13. Após fazer a soma. o resultado final será: 25. end. no caso de ele ter usado o mouse para clicar no botão.

DPR (projeto). 3. 2. 11] } 70 . 3.. se a tecla não estiver no conjunto formado por '0'. Você pode fazer vários tipos de operações com variáveis conjunto. Viuvo] then . para evitar enumerar todos os valores.Salvando o Projeto Vamos retornar a esse projeto mais tarde. 5. { o resultado será [1. permitindo fazer todas as operações padrão de conjuntos. TConjDia = set of 1. especifica-se os elementos do conjunto entre colchetes: var vogais: TConjLetra. begin vogais := ['A'. 7. Operações com Conjuntos Suponhamos duas variáveis do tipo set of integer (conjunto de inteiros). do 'editOperando1'. if estCivil in [Desquitado. 5. 7. A união é feita com o operador +. Por exemplo: C := A + B.'I'. Um conjunto pode conter elementos de qualquer tipo ordinal (ou faixa)... TConjLetra = set of 'A'.10. que são as seguintes: B. que equivale em matemática à operação x c.. Esse teste é bem mais simples e mais eficiente do que o teste anterior. Para atribuir um valor (constante) a uma variável conjunto. B := [1.. diasUteis: TConjDia. TConjEstado = set of EstadoCivil. diasUteis := [1. Para criar um tipo conjunto.23]. Conjuntos O tipo de dados conjunto representa a noção matemática de conjuntos. { rejeita a tecla } Vamos alterar esse if para utilizar um conjunto. mais o backspace (#8). além de mais legível. Substitua pelo seguinte: if not (Key in ['0'.'Z'. portanto salve-o como MEDIA. No código associado ao evento OnKeyPress. Esse tipo de teste é mais eficiente do que uma série de ifs.PAS (unidade) e MEDIAP. 13. #8]) then Key := #0. ou seja. O resultado da união é um conjunto que contém todos os elementos de · União: C = A ambos os conjuntos. 9].'U']. usa-se a declaração set: type TConjCarac = set of char. 15. 3.'O'. 2. Por exemplo: if caractere in vogais then texto := 'Vogal' else texto := 'Consoante'... Verificando Elementos Você pode verificar se um elemento pertence a um conjunto.'9'. 11].31. 5. existe um if que testa os valores possíveis da variável 'Key': if ((Key < '0') or (Key > '9')) and (Key<> #8) then Key := #0. Note que uma faixa de valores pode ser colocada.. Vamos abrir o projeto CALCP para fazer uma alteração semelhante em um dos testes. if dia in diasUteis then . 20. recebendo os seguintes valores: A := [1.'9'. 7.. 9. com o operador in. ela será rejeitada.'E'..

Para atribuir um valor para este tipo de propriedade no programa. Quando você clica duas vezes no nome da propriedade. 71 . { O resultado será [9] } · Contido: A B (A está contido em B) ou B A (B contém A). {verifica se B contém A} if B >= A then .. Por exemplo. Para alterar o valor.. 5. biMinimize. { O resultado será [2. Essas propriedades aparecem no Object Inspector com um sinal de "+" e o seu valor aparece com a sintaxe de conjunto.. O resultado de A menos B é o conjunto com os elementos de A que não existem em B. No Object Pascal. Para verificar se um elemento está presente. 3. A diferença é feita com o operador "-": C := A .A. você deve usar o operador in: if biMaximize in BorderIcons then . 7] } · Diferença: C = A . onde cada um determina se o formulário terá ou não um determinado item da borda.· Interseção: C = A B. a propriedade BorderIcons de um formulário contém um conjunto de valores. biMaximize]. o operador (está (contém) por >= Por exemplo: contido) é representado por <= e {verifica se os elementos 1 e 3 pertencem ao conjunto A} if [1. { O resultado será [1. O resultado da interseção é um conjunto que contém um elemento em comum entre os dois conjuntos. A interseção é feita com o operador "*". Verifica se todos os elementos de um conjunto pertencem também ao outro conjunto..B. 11] } C := B . aparecem subitens.B. Propriedades de Conjunto Algumas propriedades de componentes do Delphi utilizam tipos de conjunto. você deve usar a sintaxe de conjunto. que permitem adicionar ou remover elementos do conjunto. você deve usar os operadores de conjuntos: BorderIcons := BorderIcons + [biMinimize]. por exemplo: BorderIcons := [biSystemMenu. por exemplo.. por exemplo: C := A * B. adicionando um elemento..3] <= A then .

Com isso você pode acompanhar o laço for. você pode especificar uma condição de parada (Condition) e quantas vezes a linha deve ser executada antes de fazer uma parada (Pass count). basta clicar no botão Calcular novamente. ao invés disso. Executando Passo a Passo Quando você está em modo de depuração. As outras não estão relacionadas a código executável. por exemplo. Depois tecle [F7] ou [F8] (nesse caso tanto faz) para executar essa linha e passar para a próxima. ele pára a execução e destaca a linha atual. Você pode. Nesse caso. Execute o programa. Isso pode ser o que você quer. que executa o procedimento inteiro em modo de execução normal e depois volta ao modo depuração. executando todo um trecho em velocidade normal de execução. ou para detectar erros de lógica no programa (erros que só você pode saber que estão acontecendo). você pode precisar executar várias vezes o mesmo procedimento de evento.Mediap [Stopped]". Por exemplo. Executando Até o Cursor Às vezes. "Trace Into" entra no procedimento e executa cada linha dele passo a passo também. depois da chamada do procedimento. coloque o cursor na primeira linha após o begin. a que contém soma := 0. A cada vez que você teclar [F7] ou [F8].Mediap [Running]" indicando modo de execução normal. você pode usar os mecanismos de depuração do Delphi. durante a depuração você quer "pular" para uma determinada linha diretamente. Nota: você também pode colocar um ponto de parada com o menu Run|Add Breakpoint|Source Breakpoint. Para isso coloque um ponto de parada [breakpoint] na linha onde você quer começar. com a execução parada na linha atual. Nota: as linhas que podem ter breakpoints estão marcadas com pontos azuis. Nesse caso. O processo de depuração [debugging] consiste em analisar o funcionamento do programa durante e execução. você deve escolher um ponto inicial onde você vai entrar em modo de depuração. à esquerda da linha. Essas teclas também equivalem a itens de menu do Delphi ou botões da SpeedBar: Tecla Botão Item de Menu [F7] Run|Trace Into [F8] Run|Step Over A diferença entre "Trace Into/F7" e "Step Over/F8" só é importante quando você passa por uma chamada de procedimento. o fluxo da execução. adicione uns dois ou três números e depois clique em "Calcular". No nosso caso. você vai executar uma linha e o triângulo que aparece à esquerda se move indicando a próxima linha que será executada. Colocando um Ponto de Parada Para começar a depuração do programa. Execute novamente até chegar ao ponto de parada. tecle [F9]. mas em alguns casos um procedimento já foi totalmente testado e você não precisa acompanhar sua execução de novo. ou clique na margem esquerda do editor. durante a 72 . Em qualquer caso.Depuração Para encontrar as causas de uma exceção. você tem várias opções. vendo os valores de variáveis. Para colocar ou retirar um ponto de parada você pode usar a tecla [F5]. Para fazer os próximos testes. o editor de código mostra a linha destacada em vermelho e um marcador vermelho à esquerda indicando um ponto de parada. Quando o Delphi encontra o ponto de parada. acompanhar passo a passo a execução do programa. A palavra stopped [parado] significa que você está em modo de depuração. Depois da primeira vez. e assim por diante. use "Step Over". Se quiser continuar a execução normal. A janela principal do Delphi agora deve mostrar no título "Delphi . A janela do Delphi vai mudar para "Delphi . O comando dentro do for vai ser executado quantas vezes forem os números que você adicionou com o botão Adicionar.

Quando o cursor estiver em cima do nome de uma variável. funciona apenas em modo depuração [Stopped] e não em modo de execução normal [Running]. variável ou constante. O Delphi vai mostrar a janela "Watch List". que é um mostrador permanentemente atualizado com o conteúdo da variável. Esse recurso é chamado de avaliação instantãnea. usando a janela como uma calculadora. Para ver outras variáveis ou alterar seus valores. Você pode movê-la para uma posição qualquer da tela onde não cubra outras janelas. você terá a opção de modificar o valor. você verá o valor da expressão. Ao clicar em "Evaluate". que contém todos os "watches" adicionados. Monitorando o Valor de uma Variável Dinamicamente Se você quer acompanhar o valor de uma variável a cada momento da execução.. até mesmo.. Para isso. "soma * 10 / 7". Vendo Valores de Variáveis Em modo de depuração. Para isso coloque o cursor na linha onde quer parar (por exemplo. Agora à medida que você usar Trace Into/F7 ou Step Over/F8. por exemplo.. mostrando o valor atual da variável e permitindo você digitar um novo valor em "New value:": Você também pode digitar o nome de outra variável ou uma expressão qualquer em "Expression". [Ctrl+F7]. Ou você pode digitar o nome de uma constante (para saber o valor de uma constante predefinida do Delphi por exemplo). ou sua tecla de atalho. alterar o valor da variável. [F4]. 73 . por exemplo. Se você clicar no nome de uma variável e teclar [Ctrl+F7]. no if depois do for) e use o item de menu Run|Run To Cursor ou sua tecla de atalho. o valor desta será mostrado. como outros recursos de depuração. use o comando Run |Evaluate/Modify. Nota: se a execução nunca chegar à linha do cursor. ou a tecla [Ctrl+F5].execução. basta passear o cursor por cima do texto do programa. afetando o funcionamento do programa da forma que você quiser. o programa entrará em modo de execução normal ("Running") e não voltará automaticamente ao modo de depuração. o "watch" vai mostrar o valor da variável sendo alterado. a janela "Evaluate/Modify" aparece. você pode ver qual o valor atual de uma variável ou. Se for uma variável. em vez de acompanhar cada passagem. você pode querer ir diretamente ao fim do laço for. ou uma propriedade de um componente. clique no nome da variável e use Run |Add Watch. mas mantenha as opções padrão e clique Ok.. Nota: a avaliação instantânea. você pode adicionar um "watch" [sentinela]. Para adicionar um "watch" para a variável 'soma'. Existem várias opções nesta janela.

o melhor a fazer é continuar sua execução normal e depois fechar a janela do programa. As outras opções que aparecem em View|Debug Windows|Call são: Threads opção para verificar multiplas linhas de execução (threads).Para editar um "watch". durante a depuração. Forçando a Finalização do Programa Quando. que mostra toda a seqüência de chamadas de procedimento feitas até o ponto atual. você pode visualizar a pilha de chamadas [call stack]. Modules visualizar DLLS . que o programa utiliza. 74 . às vezes é necessário forçar a terminação do programa. você pode chegar a executar um procedimento que foi chamado por outro. indenpendente se possui o código fonte. Se você se perder durante a depuração e quiser encontrar a linha que está sendo executada agora. desde o primeiro procedimento de evento executado. Para removê-lo. clique duas vezes na linha vazia depois do fim da lista. clique duas vezes em cima dele na janela "Watch List" e altere suas opções. No entanto. use o item de menu Run |Program Reset ou tecle [Ctrl+F2] (essa tecla de atalho só funciona se você estiver com o foco em uma janela do Delphi). você quiser terminar a execução do programa. com a janela "Watch List" aberta. use o menu View|Debug Windows|Call Stack[Ctrl+Alt+S]. Para isso. CPU mostra o código assembler de dlls e programas. clique na lista e pressione [Delete]. que por sua vez foi chamado por outro e assim por diante. use o menu Run|Show Execution Point. Outras Ferramentas de Depuração Enquanto você está em modo de depuração. Para esse tipo de programa mais complexo. Para adicionar um novo. Para fazer isso.

10 .Procedimentos e Funções Procedimentos Gerais Unidades Independentes Funções Passagem de Parâmetros 75 .

mais o begin e end. que não são associados a nenhum componente. mesmo que ele não seja necessário. ele só pode ser usado na unidade CALC.PAS. dentro do procedimento 'TForm1.. para poder reutilizar essa validação em outros programas. dentro dele. coloque o cursor depois da palavra implementation e do comentário {$R *. entre parênteses. é necessário também utilizar o seu formulário. devemos colocar uma declaração do procedimento na interface da unidade. Volte ao procedimento 'ValidarTecla' e. Digite todas as linhas a seguir: procedure ValidarTecla(var tecla: char). ou seja.DFM}. Agora. pois para utilizar uma unidade associada em outro projeto. Substitua o texto anterior por: ValidarTecla(Key).'9'. substituindo o parâmetro 'tecla' pelo argumento 'Key'. O argumento (Key) e o parâmetro (tecla) na verdade poderiam ter o mesmo nome. Isso vai chamar o procedimento. Unidades Independentes Da forma que o procedimento está. passadas por quem chamar o procedimento. feita pelo procedimento de evento 'tratartecla'. Procedimentos gerais tornam o programa mais legível e evitam repetição desnecessária de código. uma unidade não 76 . Criando um Procedimento Geral Abra novamente o projeto da calculadora. Mas você pode criar também procedimentos gerais. #8]) then tecla := #0. O procedimento deverá ficar como o seguinte: procedure ValidarTecla(var tecla: char). Execute o programa e ele deve continuar funcionando como antes. Eles também podem ser reutilizados em vários projetos. CALC. Em muitos casos. o nome do procedimento (vamos chamá-lo de 'ValidarTecla') e. Faça a seguinte alteração no código: substitua as referências a 'Key' por 'tecla'. Parâmetros são variáveis que recebem informações externas. evitando "reinventar a roda" a cada novo programa que você desenvolve. Argumentos são informações passadas para o procedimento para substituir os parâmetros. os parâmetros do procedimento. O melhor é colocar o procedimento em uma unidade independente. Nós colocamos nomes diferentes apenas para que o procedimento tenha uma forma mais geral. begin end. Um procedimento de evento é um procedimento que está diretamente ligado a um evento e é chamado diretamente por um componente quando acontece aquele evento. e só são chamados quando você determinar. associada ao formulário da calculadora.TratarTecla'. Quando você cria um procedimento de evento.DPR. facilitando a manutenção do programa. eles também contribuem para a redução do tamanho do programa. o Delphi gera automaticamente o esqueleto do procedimento. use [Ctrl+V] para inserir o código que foi copiado antes.PAS. você deve digitar todo o esqueleto. Como já vimos. procedimentos de evento geralmente são criados pelo Delphi de forma automática. begin if not (tecla in ['0'. selecione todo o texto entre o begin e o end e tecle [Ctrl+X] para retirá-lo e guardar na área de transferência do Windows. ou seja. um cabeçalho. Se quisermos que o procedimento seja usado por outras unidades do projeto.Procedimentos Gerais Um procedimento é um trecho de programa que tem um nome e pode ser utilizado (chamado) por outras partes do programa. O cabeçalho do procedimento contém a palavra procedure. ou seja. Nesse projeto temos uma validação de tecla. Mas essa ainda não é a solução ideal. inicialmente vazios. Na unidade CALC. Mas vamos transformá-la em um procedimento geral. Mas um procedimento geral deve ser criado manualmente. end.

implementation procedure ValidarTecla(var tecla: char). ela ainda não tem uma cláusula uses na seção de implementação. porque só é necessário (e só é permitido) o cabeçalho.DFM}.'9'. Execute o programa e ele deverá funcionar como antes. Chame-a de GERAL.. O Delphi vai abrir a nova unidade no editor de código. end. Salve o projeto novamente.PAS). mas se ele precisar ser usado externamente. Unidades independentes facilitam a reutilização. interface implementation end. interface procedure ValidarTecla(var tecla: char). #8]) then tecla := #0. Voltando à unidade Calc. é um único arquivo fonte (GERAL. Usando a Unidade no Mesmo Projeto Para utilizar os procedimentos da unidade 'Geral' em outra unidade. inclusive o cabeçalho. usando [Ctrl+V].DPR. o cabeçalho do procedimento deve ser copiado para a seção de interface. o ícone "Unit" ( contendo apenas um esqueleto do mínimo que uma unidade deve ter (como vimos no capítulo 9): unit Unit2.associada a nenhum formulário. Apague do begin ao end. escolha ) e clique Ok. end. logo após o {$R *. Usando a Unidade em Outros Projetos Abra o projeto MEDIAP. A unidade Geral. Salve o projeto para dar um nome à nova unidade.PAS (porque ela vai conter procedimentos gerais). Criando uma Unidade Independente Para criar uma unidade independente. selecione todo o procedimento 'ValidarTecla'. então acrescente uma.. especialmente entre vários projetos. que pode ser reutilizado quando necessário em qualquer outro 77 . contendo o seguinte: uses Geral. Transferindo o Procedimento Voltando à unidade Calc (use as abas do editor de código para mudar entre as duas). use o item de menu File|New. Tecle [Ctrl+X] para recortá-lo da unidade. O cabeçalho da unidade automaticamente vai mudar para 'unit Geral. Coloque o cursor na seção de interface e tecle [Ctrl+V]. Agora alterne para a unidade Geral.. begin if not (tecla in ['0'.'. O corpo do procedimento deve ficar na seção de implementação. você deve acrescentar 'Geral' à cláusula uses da unidade. A unidade ficará assim: unit Geral. do Delphi. coloque o cursor depois da palavra implementation e "cole" o texto. que criamos no outro projeto.

. se você modificar um procedimento. incluindo unidades independentes. pode ser necessário usá-la(o) ainda na seção de interface. Execute o programa. Gerenciando um Projeto com Unidades Independentes Nós vimos anteriormente que o Project Manager é usado para facilitar o gerenciamento de projetos com vários arquivos. Se você não adicionar uma unidade ao projeto. mas ela não estará disponível nas facilidades de gerenciamento de projeto. você pode usar o botão (View Unit) para ver as unidades do projeto.. constantes. mas apenas adicionar uma cláusula uses para ela. Essa é uma característica do Code Insight que permite saber facilmente quais são os parâmetros que um determinado procedimento exige e o CodeExplorer mostra o procedimento na lista. podem ser usados também por outras unidades. Além do Project Manager. Agora crie um procedimento de evento para o controle 'editNumero'. ou outra unidade. como um formulário ou uma variável global. Abra o Project Manager novamente e repare que a unidade independente 'Geral' aparece na lista de arquivos do projeto... mas é importante para facilitar o gerenciamento do projeto. para que um procedimento seja reutilizável. 78 . Complete a linha como abaixo: ValidarTecla(Key). O Delphi irá adicionar o seguinte à seção de implementação da unidade: uses Geral. Se estes forem declarados na parte interface.. No caso de uma constante ou tipo de dados. como veremos. Ele nào permite expandir o arquivo GERAL.projeto. compartilhada por vários projetos. é melhor acrescentá-la na seção de implementação. Dentro do procedimento. coloque uma chamada a 'ValidarTecla'. Ou seja.PAS. tipos de dados definidos e variáveis. Em todos os demais casos. associada ao formulário. usando File|Add to project. você ainda pode acessá-la. ou o da SpeedBar e escolhendo GERAL. Na lista. clique em "Geral" e depois em Ok. Inicialmente digite apenas o seguinte e deixe o cursor posicionado após o parêntese: ValidarTecla( Repare que o Delphi mostra uma descrição dos parâmetros do procedimento (no caso apenas var tecla: char). Criando uma Biblioteca de Rotinas Uma unidade independente pode funcionar como uma biblioteca de rotinas mais utilizadas. vamos passar como argumento a variável 'Key'. e use o item de menu File|Use unit. Primeiro acrescente a unidade ao projeto atual. Nesse caso (e apenas nesse caso) é necessário acrescentar o nome a unidade à cláusula uses da seção de interface. não permitindo valores não numéricos.desde que esteja no mesmo diretório do projeto ou no diretório LIB do Delphi). isso pode afetar o funcionamento de outros projetos que o utilizam.PAS. Uma unidade pode conter também. Depois. A forma mais fácil de fazer isso é a seguinte: selecione a unidade "Media" no editor de código. Por exemplo. evento OnKeyPress. Também. é preciso que ele não dependa de nada específico de um determinado projeto. você deve acrescentar o nome da unidade à cláusula uses da unidade MEDIA. além de procedimentos. Mas nesse caso é preciso tomar certos cuidados. Note que agora o controle 'editNumero' agora tem a mesma validação de tecla.PAS. Esse passo não é estritamente botão necessário(caso a unit GERAL esteja no mesmo diretório que o projeto MEDIAP). pois essa unidade não está associada a um formulário. obviamente.

como é possível fazer com 'Result'. também pode ser usada a sintaxe de antigas versões do Pascal.Funções Funções são semelhantes a procedimentos. O tipo dessa variável é o tipo de retorno da função. Agora dentro da unidade Geral. A desvantagem dessa sintaxe é que não é possível usar o nome 'Soma' do lado direito de uma atribuição. Complete o restante da linha. e deseja criá-los pressione Ctrl+Shift+C. Agora na seção de implementação. e esse valor é inserido na expressão onde a função foi chamada. com o nome da função do lado esquerdo: Soma := x + y. por exemplo: x := 3 * Soma(a. A função então devolve um resultado. mas ela ilustra os detalhes mais importantes que envolvem a criação e uso funções.y: double): double. esse recurso facilita bastante.y: double): double. begin Result := x + y. Criando uma Função Vamos abrir novamente o projeto CALCP. Uma função retorna um valor para quem chamou. O valor colocado nessa variável será o valor retornado pela função. Depois continua o cálculo do restante da expressão. a função 'Soma' é chamada. Retornando um Valor O nome 'Result' é uma variável automaticamente criada (não precisa ser declarada) dentro de uma função. clique duas vezes no botão com o sinal de "=" (btnCalcula) para abrir o procedimento de evento associado. Inicialmente digite apenas o seguinte e deixe o cursor após o abre parênteses: res := Soma( Note que o recurso de Code Insight do Delphi automaticamente mostra a descrição dos parâmetros (x: double. Neste procedimento substitua a linha: res := op1 + op2. Notas: Se colocou o cabeçalho de um procedimento ou função na seção interface. y: double). No cabeçalho da função. o valor é calculado como a soma dos valores dos dois parâmetros (x e y). é preciso declarar o tipo de retorno da função. no caso double. o tipo de dados do valor que a função devolve. Na seção de interface. op2). ou seja. declarado depois do fecha parênteses. Notas: Se deseja ver o conteúdo de um procedimento ou função .b)." (vírgula) na chamada. end. No caso. Execute o programa e verifique que ele continua funcionando como antes. digite o cabeçalho da função: function Soma(x. Essa função não vai fazer nada realmente útil. Durante a execução.clique com Ctrl+Clique . pois apenas soma dois números e devolve o resultado. que será inserido no ponto de chamada. repita o cabeçalho da função e acrescente o corpo da função. por uma chamada à função. mas são chamadas geralmente dentro de uma expressão. além do nome e parâmetros. Para determinar o valor de retorno. No caso. Note que os argumentos são separados por ". que é inserido na expressão. vamos criar uma função. Caso você não se lembre mais dos parâmetros exigidos. com os seus parâmetros preenchidos de acordo com os argumentos fornecidos (a e b). o tipo é double. 79 . Ex: Soma := Soma + y. contendo o seguinte: function Soma(x. com os argumentos: res := Soma(op1. Chamando a Função No formulário principal.

. function Soma( op1. ele deve ser chamado com argumentos correspondentes. function Soma( op1. Passagem de Parâmetros Quando um procedimento ou função possui parâmetros. y: double): double. . op3 : double): double. end. Declaração de Parâmetros e Argumentos Quando há mais de um parâmetro. sendo que quando a soma for realizada entre quatro números os dois últimos são do tipo string.overload. o que diferencia um procedimento do outro é o número e tipo de parâmetros passados.. op2 : double. TAMANHO). Como na Unit GERAL já existe uma função que realiza a soma de dois números . op2 : double. procedure ValidarTecla(var tecla: char). Na chamada ao procedimento ou função. O nome do procedimento pode ser repetido no projeto ou na unit. Isso significa também que qualquer alteração no parâmetro não afeta o argumento original. para seção interface pressione Ctrl + Shift + ( ) .y:integer. Nenhum argumento deve ser omitido.y: double): double. Tipos de Passagem Existem várias opções disponíveis para passagem de parâmetros de procedimentos ou funções. (Os nomes entre colchetes estão como aparecem na documentação do Delphi): • Passagem por Valor [value parameter]: o valor do argumento (que pode ser uma variável." (vírgulas): x := Soma(12." (ponto-e-vírgula) na declaração do procedimento. op4 : string): double. begin result := op1 + op2 + op3. op2. end. TextOut(x. text:string). ou podem ser separados com ". 13.Notas: Para alternar da seção implementation . begin result := op1 + op2 + strtofloat(op3) + strtofloat(op4). mas apenas uma cópia 80 . para isso temos que informar no final da declaração a diretiva overload. vamos criar as outras com o mesmo nome: function Soma( op1. Por Exemplo: A função soma pode realizar a soma entre dois . op4 : string): double. op2. na mesma ordem. op3 : double): double. três e quatro números . se têm o mesmo tipo: function Soma(x. op3.". esses são separados por ". o contrário utilize Ctrl+Shift + ( ). e as duas formas podem ser combinadas. function Soma( op1. end. Por exemplo: begin ValidarTecla(Key).overload.overload. (A documentação do Delphi chama os parâmetros de formal parameters e argumentos de actual parameters). y: integer): double. op3. Mas além de criar as funções ou procedimentos com o mesmo nome é necessário que durante a declaração do procedimento especficique que eles serão sobrecarreagados. os argumentos são sempre separados por ". 'Testando'). constante ou uma expressão) é simplesmente copiado para o parâmetro. exatamente como em declarações de variáveis: procedure TextOut(x. se têm tipos diferentes: function Soma(x: double. function Soma(x.

como vetores e registros. portanto . A função 'Soma' usa esse método para os dois parâmetros. um parâmetro pode ser passado por valor e outros por referência ou constantes. usa passagem por referência. usa-se a palavra var antes do nome do parâmetro. é necessário alterar o argumento original. o programa que chamar este procedimento não vai funcionar. Qualquer alteração no parâmetro afeta imediatamente o argumento original. como na passagem por valor. Esse é o método padrão de passagem. um parâmetro é passado por valor se não for especificado em contrário. No mesmo procedimento ou função. No caso de parâmetros grandes. mas em alguns casos a passagem por referência pode ser útil. Para indicar passagem por referência. porque o programa irá escrever os caracteres inválidos. pois elas já retornam um valor através da própria chamada de função. Se o parâmetro Tecla da função Validar tecla for do tipo passagem por valor . • Passagem Constante [constant parameter]: um parâmetro constante (declarado com const antes do nome) não pode ser modificado dentro do procedimento. portanto é bem mais eficiente. a passagem constante evita que seja feita uma cópia do argumento. independentemente um do outro. por exemplo. porque precisa alterar o argumento original.local. O procedimento 'ValidarTecla'. ou seja. Essa característica pode ser usada para impedir alterações acidentais que violariam a lógica do programa. 81 . Funções especificamente não precisam ter parâmetros por referência. • Passagem por Referência [variable parameter]: o argumento deve ser uma variável do mesmo tipo de dados do argumento. O argumento pode ser uma expressão qualquer.

Capítulo 11 Objetos O que Contém um Objeto Classes e Objetos Herança Formulários como Objetos Variáveis de Objetos Listas de strings Objetos Predefinidos Code Explorer Programação Orientada a Objeto 82 .

Por exemplo.SetFocus. que é chamado (inicialmente) de "Edit1". mesmo aqueles que não são visíveis externamente. e que é manipulada como uma única unidade. contendo dados e o código que manipula esses dados. Um objeto pode ter campos de dados que não são visíveis externamente. "Edit3". Cada objeto específico é uma instância da classe. numa definição prática. pode ter também eventos. com alguns métodos que já vimos: editNumero. Você pode também criar um objeto dinamicamente. um formulário. O nome dessa (Edit) corresponde classe tem a letra 'T' antes do nome que aparece. Por exemplo. ou geralmente. eles serão chamados de "Edit2".Os procedimentos de eventos criados são métodos do objeto do formulário criado. Uma classe é um esquema que deve como serão os objetos. O Object Inspector sempre mostra o nome do componente e o nome de sua classe. durante a execução do programa. limitado apenas pela memória do computador. e quais os métodos que podem ser usados para manipular o objeto. Quando você cria um objeto. que são propriedades cujo valor é um procedimento de evento. ele começa como uma cópia idêntica do modelo definido pela classe. criada de acordo com o modelo definido pela definição da classe. por exemplo: Todos os objetos de uma mesma classe têm as mesmas características (propriedades). como propriedades. Um método tem acesso a todos os campos de dados do objeto. você está criando um objeto da classe TEdit. {método procedimento: SaveToFile} if Clipboard. Um método pode ser um procedimento.HasFormat(cf_text) then {método função: HasFormat} Um componente.O Que Contém um Objeto Um objeto. que deve ser único) começam com os mesmos valores padrão que a classe define. conforme veremos. ou uma função. o ícone à classe TEdit. que além de executar uma ação. mas cada um tem seus próprios valores para essas características.SaveToFile(nome). e suas propriedades (exceto Name. O procedimento que está associado a um evento é chamado quando ele é acionado. {método procedimento: SetFocus} Lines. qualquer componente. uma lista de strings. com isso mantendo todo o controle sobre sua implementação interna. O código de programa que manipula os dados é feito através de métodos. Por exemplo. é uma área de memória separada do computador. que pode ser usado em uma expressão. Quando você seleciona esse ícone e clica no formulário. Você pode criar quantos objetos quiser da mesma classe. Classes e Objetos Todo objeto pertence a uma classe. cada ícone da paleta de componentes corresponde a uma classe. que executa alguma ação quando é chamado. Nos programas. Depois você pode alterar essas propriedades. os dados de um objeto aparecem como campos do objeto. diferenciando um objeto do outro. 83 . que é um tipo de objeto. Se você criar outros. Por exemplo. ou o objeto Clipboard. quais suas características. retorna um valor para quem chamou.

É o Object Browser.. que define as características de qualquer formulário. O mecanismo de herança [inheritance] permite que você programe apenas o que é diferente entre a sua classe e a outra (programação por exceção). derivando uma classe de TComponent ou de alguma descendente desta. Ela contém propriedades. Mas este é um processo mais complexo.. que pode ser aberto no Delphi com o menu View|Browser (só está disponível depois que você compilou o projeto ao menos uma vez). que são herdados por todas as classes de controles. TButton. a classe herda todos os dados e métodos da outra classe. seu formulário tem todas as características de um formulário padrão. TEdit. ela pode ser baseada em uma classe que já existe. direta ou indireta de todas as outras classes de componentes. Quando você cria um novo formulário. Uma visão simplificada de uma hierarquia de classes (omitindo algumas intermediárias) é a seguinte: TComponent (ancestral de todos componentes) TOpenDialog (um componente que não é controle) TControl (ancestral de todos controles) TForm (ancestral de todos formulários) TFormPrincipal (suas classes. com uma classe derivada também tendo classes derivadas. Com isso. Você pode também criar uma nova classe de componente.Herança Classes geralmente não são criadas a partir do zero. Visible. que pode ser representada com uma estrutura em árvore. Quando a herança é usada sucessivamente. Essas frases dizem respeito exatamente a relações entre classes ancestrais e classes derivadas no Delphi. O Object Browser Para visualizar a hierarquia de classes do Delphi e da sua aplicação. Top. novos métodos etc. Left. TEdit . como Enabled. 'TMeuForm'. A classe da qual são herdadas as características é chamada de classe base ou ancestral [ancestor] e a classe criada é chamada de classe derivada ou descendente [descendent]. que são herdadas por todas as outras classes descendentes.. mas pode acrescentar ou redefinir alguns de acordo com o que é necessário. é descendente indireta de TControl.). como Refresh. que contém apenas métodos básicos de manipulação de objetos.controles) TTimer (um componente que não é controle) Todas as classes no Delphi.. Width e Height e métodos.. Além de classes. é criada uma hierarquia [hierarchy] de classes. e por isso não cobriremos no curso. Hierarquia de Classes do Delphi Nós já vimos que "todo controle é um componente". Todo formulário é também um controle. por exemplo. TLabel. Herança não é apenas uma cópia estática de características. A classe 'TForm'. tipos de dados e variáveis das unidades utilizadas no projeto. Simplificando o Acesso aos Campos 84 . ou seja.. A classe 'TControl' é uma das descendentes de TComponent. Quando você cria uma nova classe. além das que você acrescentar (novos campos de dados. o Delphi cria automaticamente uma classe de formulário descendente de TForm. O nome da sua classe de formulário é criado com 'T' seguido do nome do formulário. Qualquer alteração feita em uma classe ancestral automaticamente repercute nas classes descendentes. são descendentes diretas ou indiretas da classe TObject. que envolve vários detalhes de programação. o Object Browser permite ver quais as constantes.. TFormCalen . inclusive TComponent. "todo componente é um objeto". A classe 'TComponent' é a ancestral. Da mesma forma. por exemplo. existe uma ferramenta que pode ser usada para isso. Ela contém as propriedades Name e Tag (além de outras pouco usadas)..de formulário) TButton (classes de.

editTamanho. Mas quando se acessa vários campos do mesmo objeto. geralmente. Para evitar isso. é preciso repetir o nome do objeto em cada comando. seguido de um ponto e o nome do campo. Enabled := True. usando-se a sintaxe que já vimos. end.SetFocus. editTamanho.Enabled := True. o nome do objeto fica implícito: with editTamanho do begin Clear. Dentro do bloco do comando with. propriedades e métodos de um objeto são acessados. SetFocus.Campos.Clear. propriedade ou método: editTamanho. existe o comando with. com o nome do objeto. 85 .

Se você adicionar.Edit e Label). O código até a palavra private é mantido automaticamente pelo Delphi e você não deve alterálo. existe uma declaração para cada componente do formulário (no caso Button . contém os comandos que implementam realmente o procedimento. Geralmente não existe motivo para fazer alterações manuais. O que fica na seção private é acessível apenas na unidade atual. Quando você volta à unidade. O nome da classe de formulário sempre inicia com um T. Label1: TLabel. onde 'Button1' é o nome do componente e 'TButton' é o nome da classe do componente. Tecle [F12] para ver a unidade do formulário. procedure btnFecharClick(Sender: TObject). As seções private e public dentro da definição da classe são onde você pode adicionar mais elementos. editData: TEdit. var formPrincipal: TFormPrincipal. começam as declarações para os procedimentos de evento. mas o que for declarado na seção public é visível externamente em outras unidades. como veremos adiante. O corpo do procedimento. Dentro da definição da classe (que vai até a palavra end). além do inicial. btnCalculadora: TButton.Formulários como Objetos Formulários também são objetos. pode verificar que o Delphi acrescentou uma declaração para esse componente: Button1: TButton. A Classe de Formulário Abra o projeto CalcData. procedure FormCloseQuery(Sender: TObject. o Delphi adiciona uma declaração dentro da classe. var CanClose: Boolean). procedure btnCalendarioClick(Sender: TObject). que fica na seção de implementação. 86 . Para cada procedimento de evento. Veremos mais sobre isso mais tarde. logo após a cláusula uses. Na seção de interface da unidade. procedure btnCalculadoraClick(Sender: TObject). Volte ao formulário. A primeira linha: TFormPrincipal = class(TForm) quer dizer que a classe do formulário é baseada na classe 'TForm'. que define um formulário genérico. e alterar suas propriedades. você verá a declaração da classe de formulário: type TFormPrincipal = class(TForm) btnCalendario: TButton. O Delphi não troca o que você colocar em uma dessas seções. Para testar. o Delphi altera automaticamente essa seção.DPR(Capítulo 8). btnFechar: TButton. A vantagem de ter uma classe de formulário é que isso torna possível criar dinamicamente outros objetos de formulário. remover. remova o botão e o Delphi vai também remover essa declaração. Você verá inicialmente o formulário principal. alterne para o formulário com [F12] e acrescente um componente Button. Quando você cria um novo formulário. seguido do nome do objeto de formulário (que você define na propriedade Name do formulário). como: procedure btnFecharClick(Sender: TObject). Depois das declarações de componentes. private { Private declarations } public { Public declarations } end. ou renomear qualquer componente. o Delphi cria uma classe de formulário e um objeto de formulário dessa classe.

seria colocado na parte implementation. podemos criar um procedimento na unit e declara-lo em uma das seções private ou public. criando um objeto. Inicialmente o conteúdo da variável é lixo ou. com o nome da classe. Edit1:TEdit. Esse é um valor especial que significa no caso "nenhum objeto".Free. não foi necessário especificar o nome do objeto que referencia a classe do formulário criado. 87 . Dependendo da classe. por exemplo: lista := TStringList. Se você não liberar. Quando definimos que um procedimento faz parte de uma determinada classe na criação do procedimento temos que especficar o nome da classe . O conteúdo de uma variável de objeto é uma referência a um objeto. no caso de uma variável global. Para liberar a memória usada pelo objeto. você deve liberar a memória ocupada por ela: lista. Algumas classes têm construtores com outros nomes ao invés de Create.Com a palavra end. Você pode inicializar a variável. end. isso não foi necessário porque o procedimento faz parte da classe do formulário especifico. begin Show. sem indicar o nome do formulário. Depois o Delphi acrescenta uma declaração de variável para o formulário. internamente armazenada como o endereço de memória onde o objeto fica armazenado. mesmo que não existam mais variáveis para acessá-lo. use o método Free (definido na classe TObject e herdado por todas as classes). isso vai causar um erro de execução. Variáveis de Objeto Uma variável de objeto é declarada utilizando o nome da classe como um tipo de dados. termina a definição da classe. Mas a vantagem principal de criar um procedimento como parte da classe de formulário é que ele pode acessar diretamente qualquer componente que faz parte do formulário. Para isso.AbrirFormulario.FormClick(Sender: TObject). ela é inicializada com o valor nil. como já vimos: var btnCalendario: TButton. Essa declaração cria um formulário baseado na classe definida antes: Procedimentos na classe de formulário Vamos criar um método para a classe desse formulário. begin if Cursor = crDefault then Cursor := crHourglass else Cursor := crDefault. depois de terminar de usar uma string list. por exemplo: procedure TFormPrincipal. podemos verificar que no procedimento abaixo que utiliza a propriedade Cursor do formulário. como um método é um procedimento criado dentro de um classe. formPrincipal: TFormPrincipal.DPR (Capítulo 6). Por exemplo. o espaço de memória do objeto continua alocado. o construtor pode ter parâmetros usados para inicializar o objeto. com os seus comandos.Create. use o método Create (o construtor da classe). Isso torna mais fácil manipular os componentes. end. como foi feito no exemplo anterior. Vamos abrir o projeto EVENTOS. E o corpo do procedimento. No exemplo citado o procedimento não faz muita coisa útil. Se você tentar usar uma variável que contém nil. procedure TForm1. O construtor aloca um espaço de memória para conter os dados do objeto e retorna o endereço dessa memória. por exemplo: procedure AbrirFormulario.

passamos 'Self'(o formulário atual).Mas no caso de um controle(componente visual) é preciso dizer também quem será o pai[parent] desse controle. se colocar esse controle sendo o pai do Botão. por exemplo: var btn: TButton. vamos criar componente TButton na posição do cursor. No formulário. with botao do begin parent := self.. não é feita uma cópia física do objeto. altere o nome para formCriaComp e o título para "Criação de Componentes". que quando for clicado o mouse no formulário. Depois a propriedade caption é alterada para 'Botão' mais o conteúdo da propriedade quantBotao. Mas se houver outro controle que é capaz de conter controles. end.. btn. Na classe de formulário 'TformCriaComp' na parte public . Esse construtor exige como parâmetro o formulário onde o componente será criado.. end. No evento OnClick do botão "btnCriar".. end. que é o mesmo que 'FormCriaComp' nesse caso.esta variável será publica. end. este será criado em cima do Panel. ambas as variáveis referenciam o mesmo objeto. Se for o próprio formulário. top := 0.. Por Exemplo: O controle Panel.create(self). o controle fica sobre o formulário... Coloque dois componente Button . left : = 0. Quando você cria um componente. A única coisa copiada é a referência ao objeto. begin quantBotao := quantBotao + 1. O formulário 'Self' será o dono[owner] do componente. para isto basta criar uma variável nesta classe. No caso. faça o seguinte: var botao : TButton. Quem determina o pai do componente é a propriedade Parent. Vamos criar um exemplo. faça as seguintes alterações: Button1 btnCriar Name Caption Criar Button2 btnDestruir Name Caption Destruir Vamos criar uma propriedade na classe de formulário 'TformCriaComp'. como iremos armazenar nesta variável a quantidade de botões criados. Antes de criar o Botão iremos adicionar o valor 1 a propriedade quantBotao..usa o construtor Create da classe TComponent. caption := 'Botão' + inttostr(quantBotao). private { Private declarations } public { Public declarations } QuantBotao:integer. o pai pode ser esse outro controle. Depois da atribuição. botao := TButton. acrescente: TForm1 = class(TForm) . {afeta btnDuplicar indiretamente} .Quando você atribui uma variável de objeto a outra. e a posição do 88 . begin btn := btnDuplicar.Caption := 'Duplicar de novo'. visible := true.

o método utilizado para liberar a memória é o Free.btnCriarClick e TCriaComp. Implementation {$R *. Vamos salvar o projeto como CRIACOMP. então vamos retirar a declaração desta variável nos procedimentos de eventos TCriaComp. Mesmo colocando esta variável sendo global o problema ainda não foi resolvido . Para solucionar este problema vamos criar a variável botao sendo global. mas quando for destruir o componente não irá funcionar . Então acrescente: var botao :TButton. No evento OnClick do botão "btnDestruir". Um dos problemas ocorre porque a variável que contém a referência do objeto da classe TButton é local. pois. btnCriar. ao criar iremos habilitar o botão 'Destruir' e desabilitar o botão 'Criar' e quando destruir o botão vamos desabitilitar o botão 'Destruir' e habilitar o botão 'Criar'.free end. vamos destruir o botão criado. existindo somente no procedimento que foi criada. E na seção implementation acrescente a declaração desta variável.enabled := true. Para testar clique no botão 'Criar'. o botão 'Criar' continua permitindo a criação de mais de um botão. btnCriar. Execute e teste o projeto.enabled = false.enabled = false.A propriedade Visible faz com que o componente apareça no formulário. a referencia que existia para os botões que foram criados anteriormente foram perdidas. 89 .enabled := true. Execute o programa.PAS e CRIACOMPP. Na propriedade Enabled do botão 'Destruir' altere seu valor para false. porque não temos nenhum botão criado.DFM} var botao:TButton.btnDestruirClick. A cada clique no botão será criado um componente da classe TButton. Vamos considerar que queremos criar somente um botão de cada vez. begin botao. inicialmente o botão 'Destruir' vai aparecer desabilitado. E no evento OnClick do botão 'Destruir' acrescente: btnDestruir. No envento OnClick do botão 'Criar' acrescente o código a seguir: btnDestruir. com isso a variável botao sempre irá conter a referência para o último botão criado. pois.componente(propriedades Top e Left) é definida com o valor Zero.

A propriedade Count informa quantos elementos existem na lista. por exemplo: nome := ListBox1. pode-se acessar a lista como um vetor: nome := ListBox1. o programa faz o seguinte: ListBox1. quando é True (verdadeiro). posição{move} nova). os métodos são usados da forma: Add(novoElemento). De forma geral. omitindo o nome da propriedade. if pos <> -1 then {achou.FileName). para acessar os elementos da lista (o índice do vetor começa de zero).Items. Para remover um elemento. {carrega do arquivo} SaveToFile(nomeArquivo). o item adicionado também aparece na lista.} No programa EDITORP. Por exemplo: memoEditor.1 do Writeln(arquivo. Move move um elemento para outra posição e Exchange troca dois elementos de lugar.Count .Items. que é um vetor. por exemplo: for i := 0 to ListBox1. usa-se o método Delete. Você pode adicionar um elemento no meio da lista.Add(Edit1.Items. Nesse projeto. Se o elemento não for encontrado. {exclui um elemento} {exclui todos} Clear.Items[i]. a propriedade Lines de um controle Memo. Além disso.. retorna -1. AULA1P. pois várias propriedades de componentes são do tipo lista de strings. Para remover todos os elementos. que são LoadFromFile e SaveToFile. A propriedade Sorted. {troca os elementos} Para procurar um elemento na lista. Propriedades da String List Você pode usar a propriedade Strings. ou simplesmente.Strings[i]. como a propriedade Items dos controles ListBox e ComboBox. Exchange(pos1. esse métodos são usados como: LoadFromFile(nomeArquivo). Resumindo. No código do botão Adicionar. basta usar o método Clear.Lines.Items' é uma string list. Isso pode ser feito porque 'memoEditor.Listas de Strings O Delphi possui um tipo de objeto que é útil quando se trabalha com vetores de strings. 'ListBox1. novoElemento). Métodos da String List O método Add adiciona um elemento no final da lista ou na posição em ordem alfabética. Vamos abrir o primeiro projeto criado.Lines' é uma string list. e nesse caso. ListBox1. que adiciona um elemento. Como essa string list está associada a 'ListBox1'. nós utilizamos dois métodos que permitem salvar ou ler uma string list para um arquivo. faz com que os elementos da lista sejam classificados automaticamente. Por exemplo: pos := ListBox1.IndexOf(Edit1.LoadFromFile(dlgArquivo. {salva para o arquivo} Criando String Lists Independentes 90 .Text).. usando Insert. Move(posição-ant.Items.Text). informando a posição numérica. usa-se IndexOf. {adiciona} Insert(posição. existe um componente ListBox chamado 'ListBox1' (o nome default). Nesse código. {insere} Delete(posição). entre outras. dependendo do valor de Sorted.Items[i]). está sendo utilizado o método Add da string list. São as chamadas listas de strings [string lists]. pos2). É importante saber trabalhar com esse tipo de objeto.

Quando você passa muito tempo em um laço de processamento. você pode utilizar funcionalidade adicional no seu programa... O Objeto Clipboard O objeto Clipboard representa a área de transferência [clipboard] do Windows.Picture). o Delphi não tem uma oportunidade para verificar os eventos do usuário. o que dá a oportunidade ao seu programa de processar os eventos: while not fim do begin . Para saber se um determinado formato está disponível. {libera memória} end. begin lista := TStringList. use a propriedade AsText. que você pode usar no programa sem precisar de declarar variáveis para eles. por exemplo: Clipboard. pega o valor desse texto} O método Assign pode ser usado para copiar uma imagem para o Clipboard.. declarando uma variável do tipo TStringList.Free. em qualquer ponto. você pode chamar o método ProcessMessages do objeto Application..Sorted := True. por exemplo: image1. Ele tem várias propriedades e métodos usadas internamente pelo Delphi. end. {se houver texto no clipboard. . que retorna um valor do tipo boolean: 91 . Para evitar isso. O Objeto Application O objeto Application representa a sua aplicação como um todo. e usando o método Create.text. Para fazer o contrário. Isso pode fazer o seu programa aparecer como se estivesse "travado" para o usuário.Add('Delphi'). Com esses objetos.Assign(image1. usando o método Terminate. A propriedade Title determina qual o título que aparece no ícone quando o programa é minimizado. Você pode terminar a execução do programa. por exemplo: Clipboard.Você também pode criar string lists independentemente de qualquer componente. use o método HasFormat. Para ler ou colocar um texto no Clipboard.AsText. . A propriedade ExeName (somente de leitura) permite você consultar qual o nome do arquivo executável do seu programa. uma área de memória usada para passar informações entre programas. lista. lista. lista.Picture.. você pode trazer a imagem que está no Clipboard dentro de um componente Image. lista. s := Clipboard. Application.AsText := edit1. mas algumas delas são úteis no seu próprio código. lista. O clipboard pode ser usado para guardar texto ou imagens.. você deve liberar a memória ocupada por ela com o método Free: var lista: TStringList.ProcessMessages.Create. a partir de um componente Image. de tempos em tempos dentro do laço.Delete(0). Objetos Predefinidos A biblioteca do Delphi contém vários objetos predefinidos.Add('Curso'). Após terminar de usar a string list.Assign(Clipboard).

ou CF_BITMAP.DPR. Você pode acessar o formulário ativo (o que tem o foco de teclado) através da propriedade ActiveForm e o controle que tem o foco com a propriedade ActiveControl (do tipo TControl).HasFormat(CF_TEXT) then . CF_DIB. Você pode também alterar o cursor para um formulário individual. você precisa acrescentar a unidade Clipbrd à sua cláusula uses. A propriedade PixelsPerInch é um fator de conversão. Vamos expandir cada item que aparece no code explorer e teremos o seguinte resultado: 92 . a largura e altura da tela em pixels. e vamos no editor de codigo da Unit 'CriaComp'. Code Explorer O code explorer aparece quando estamos editando uma Unit. variáveis . com a propriedade Cursor do formulário. vai mudar o cursor do mouse de forma global para todos os formulários. que diz quantos pixels existem em uma polegada. As propriedades Width e Height contêm. e saber qual é o controle ou formulário que tem o foco atualmente. irá aparecer a seguinte janela: O code Explorer é o que parece do lado esquerdo desta janela. nele conseguimos visualizar quais são as constantes.if Clipboard. O parâmetro de HasFormat pode ser: CF_TEXT para verificar se existe um texto. A propriedade Fonts é um objeto TStringList que contém todos os nomes de fontes disponíveis no Windows. A propriedade Cursor. O Objeto Screen O objeto Screen representa a tela do computador e tem propriedades que permitem consultar a resolução da tela. se alterada.. CF_IMAGE para verificar se existe uma imagem. respectivamente.. uses e as classes utilizados na unidade que aparece no editor de código. Vamos abrir o projeto CRIACOMPP. Para usar o objeto Clipboard no programa. Com isso você pode converter pixels em unidades físicas e vice-versa.

Uma classe é uma estrutura de dados. Com o encapsulamento. o efeito de uma alteração no código é menor e mais previsível. onde a interface geralmente é fixa ou muda pouco enquanto a implementação de uma classe tem total liberdade para mudar. definida em tempo de projeto. Por exemplo. Nesta classe é mostrado o que foi definido nas partes Public e Private.Como a única classe que foi definida dentro desta Unit é 'TFormCriaComp'. Ele só não pode alterar a sua interface. 93 . criada em tempo de execução. um "cliente" da classe TConta não precisa saber como ela guarda as movimentações da conta e não tem acesso para modificar essas informações (e falsificar um extrato. isto é. inconsistências etc. é possível reutilizar código. Encapsulamento permite esconder membros de uma classe para evitar que outras classes alterem a estrutura interna do objeto. Na POO. (As "partes" do programa são as classes e seus objetos). mas isso tem suas limitações. de acordo com a estrutura da classe e que pode ser manipulada com os métodos da classe. herança e polimorfismo. Com isso. uma parte pode ser alterada sem afetar as outras. bugs. por exemplo. Num programa orientado a objeto bem construído. relacionados entre si. Depositar(valor:double) e Retirar(valor:double)). Programação Orientada a Objetos A programação orientada a objeto (POO) é uma forma de programação que tenta construir os programas como coleções de classes e objetos. uma alteração no código pode causar problemas. O encapsulamento então força uma separação entre interface e implementação. a programação orientada a objeto facilita bastante a reutilização de código. Em outros tipos de programação. em várias partes do programa. Sem POO. A idéia da POO é criar o mínimo possível de dependências de uma parte do programa em relação à outra. apareceu somento o nome dela. Na opção 'Variables/Constant' conseguimos obter todas as variáveis globais que foram declaradas e em 'Uses' identificamos as units utilizadas. por exemplo). procedimentos e funções isolados. que contém também os procedimentos que manipulam esses dados. vários conceitos são importantes: encapsulamento. Além disso. o conjunto de métodos e dados públicos (por exemplo. você garante que o objeto pode alterar sua representação interna sem afetar nenhuma outra classe. Um objeto é uma instância de uma classe.

confusos. mas pode usá-las como objetos da classe TBase. Futuramente. o cliente não precisa nem mesmo saber que elas existem. Mas se você entender corretamente os conceitos e aplicar da forma correta os recursos da linguagem.Herança permite criar uma classe derivada a partir de uma classe base. que já foi testado e aprovado. um "cliente" de uma classe (procedimento que usa objetos da classe) pode ser escrito sem se preocupar com a subclasse específica que ele vai manipular. 94 . Isso quer dizer que em qualquer lugar que possa ser usado um objeto da classe TBase. A classe derivada pode modificar ou estender o funcionamento de métodos já existentes. se novas subclasses são criadas. de substituir um objeto por um de outra classe derivada. corre um risco menor de acontecer isso. Com o polimorfismo. com capacidades adicionais. A classe derivada herda a implementação da base. Essa possibilidade. ele pode ser substituído por um objeto da classe TDerivada (porque ele suporta os mesmos métodos).Claro que ainda é possível criar programas mal-estruturados. Uma classe derivada herda também a mesma interface da classe base. é chamado polimorfismo. reutilizando o código que já existe. e instáveis com POO.

Capítulo 12 Aplicações de Banco de Dados Termos Usados Desktop x Cliente / Servidor Formatos de Bancos de Dados Criando Tabelas Exemplo: Criando um Formulário "Manualmente" Exemplo: Usando o Database Form Wizard Resumo dos Componentes de Dados Apelidos de Bancos de Dados 95 .

um banco de dados pode ser fisicamente um subdiretório do disco. Mas esse tipo de acesso não tem muitos recursos. uma tabela para bancos etc. Uma tabela [table] no Delphi é um conjunto de registros com a mesma estrutura. Algumas documentações se referem aos registros de uma tabela como linhas [rows] e aos campos como colunas [columns]. quantidade em estoque. como descrição. ou pesquisar um valor. como a possiblidade de alterar a estrutura de um arquivo.Termos Usados Os sistemas de programação necessários ao funcionamento de uma empresa precisam manter dados de forma permanente. Um apelido [alias] no Delphi é um nome que representa um banco de dados. Existem vários formatos de bancos de dados que podem ser acessados pelo Delphi. Por exemplo. ou um único arquivo. 96 . Você pode alterar a posição de registro atual. e manipular um arquivo de registros. especificando as condições de seleção. com uma tabela para duplicatas. que permite obter todo um subconjunto da tabela ou de várias tabelas. Um campo [field] é um dos itens de informação dentro do registro. e fornecer recursos para atualizar e pesquisar nesses dados. Por exemplo. independente de sua localização. ou excluir um registro. 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. Um registro [record] é um grupo de variáveis com tipos de dados diferentes. código de identificação. um registro pode conter os dados relativos a um produto vendido pela empresa. Um banco de dados [database] é um conjunto de tabelas que contêm dados relacionados. sem alterar o programa. como veremos. Geralmente sistemas pequenos ou médios usam apenas um banco de dados contendo todos os dados. Um índice [index. Os recursos de linguagem que permitem isso são chamados de acesso a bancos de dados. cujos dados estão disponíveis para o programa. um sistema de contas a pagar poderia ter um banco de dados de contas a pagar. armazenados de forma permanente em disco. movimentando-se seqüencialmente pelos registros. ou então usando um índice para procurar um registro. cada tabela possui um registro atual ou corrente [current record]. Nota: Você pode criar um registro no Object Pascal com uma estrutura do tipo record. como a descrição do produto. Uma tabela pode ser um arquivo físico. mas não necessariamente. Um recurso extremamente poderoso do acesso a bancos de dados do Delphi é a consulta [query]. Dependendo do formato. Isso permite mover os dados para outro local. Durante a execução. que armazenam dados relacionados.

No Delphi você pode começar a desenvolver sua aplicação usando um banco de dados desktop e depois migrar para cliente/servidor. Mas para mais usuários. um ambiente desktop pode fornecer um ótimo desempenho. todos os três componentes ficam no mesmo computador. Nota: De acordo com a Borland. recomenda-se um sistema cliente/servidor. ele acessa localmente os dados no servidor e retorna apenas o resultado pedido. o sistema deve selecionar alguns registros baseado na data informada. de forma que o tráfego na rede seja pequeno. como o InterBase ou SQL Server por exemplo. • Mecanismo de acesso a banco de dados: [database engine]: responsável pela manutenção das estruturas de dados necessárias em arquivos. com menos que 12 usuários simultâneos. mas apenas em determinado período. não é necessário nem mesmo retornar um resultado. que é embutido no próprio Delphi. Quando o SGBD recebe um pedido para selecionar alguns dados. a estação traz todos os registros através da rede. No caso de uma atualização. é recomendável utilizar o mecanismo cliente/servidor. No ambiente desktop. O diagrama abaixo resume as diferenças entre os ambientes: Desktop Cliente/Servidor Bancos de dados desktop funcionam relativamente bem quando são poucos os dados a serem acessados. que envolve no mínimo uma estação e um servidor. quando um usuário quer ver uma relação de contas a pagar. Já num banco de dados cliente/servidor. • Armazenamento de dados: arquivos que contém os dados em si. com poucas modificações no programa. Um banco de dados "desktop" (ou baseado em arquivos) é aquele no qual a interface com o usuário e o mecanismo de acesso ficam no mesmo computador (a estação) e apenas os arquivos dados ficam num servidor de rede. Ambientes c/s também são mais confiáveis. O tráfego gerado na rede é grande. e pela manutenção da integridade dos dados. e iniciar pesquisas de acordo com um pedido do usuário. Formatos de Bancos de Dados Todo o acesso a dados é feito através do Borland Database Engine (BDE). a configuração pode ser diferente. Operações de consulta ou pesquisa devem passar através da rede. a interface com o usuário fica na estação e se comunica remotamente com o mecanismo de acesso. principalmente quando várias estações acessam simultaneamente o servidor. pelos detalhes internos do acesso aos dados. O BDE permite acesso a alguns formatos 97 . ou poucas consultas feitas simultaneamente. pois a forma de acesso através do programa é praticamente a mesma. Já numa rede. apenas informar que a atualização foi feita.Desktop x Cliente/Servidor Uma aplicação que utiliza bancos de dados é composta de três partes: • Interface com o usuário: responsável por validar as entradas do usuário. mesmo os que não são utilizados. Por exemplo. que é um sistema gerenciador de banco de dados (SGBD) rodando no servidor. Num computador isolado. (anteriormente chamado IDAPI). Em redes maiores.

O formato que você vai utilizar depende de se você está acessando um banco de dados já existente.. Abra o menu File|Working Directory. · SQL Links: na edição Client/Server.de dados "nativos". como: Oracle. Em resumo. como Paradox. você deve criar fisicamente o seu banco de dados. através de seu ícone em: |Programas|Borland Delphi 4|Database Desktop. e com drivers que podem ser usados para acessar essa versão. com a extensão DB. IBM DB/2 e InterBase. os formatos disponíveis são os seguintes: · Formatos Desktop: o BDE acessa "nativamente" vários formatos de dados no padrão desktop. que exige um determinado formato. Microsoft Access e FoxPro: · Paradox: correspondem ao formato utilizado pelo Paradox. Chame esse utilitário a partir do Delphi. que contém várias tabelas. No nosso caso. Definindo a Estrutura dos Campos Para criar uma tabela. a tabela terá a seguinte estrutura: Campo Tipo Tamanho Chave CodCliente S (automático) * Nome A 40 Telefone A 10 DataNasc D (automático) 98 . O InterBase armazena o banco de dados inteiro. Cada banco de dados é um único arquivo . para acesso nativo a vários formatos de bancos de dados cliente/servidor. que é o diretório padrão usado pelo DBD para criar os arquivos de dados. As edições Professional e Client/Server vêm com uma versão reduzida do InterBase. · Access: usado pelo Access. mas esta opção facilita o trabalho. Você deve escolher qual o formato de dados a ser utilizado para a tabela (o padrão é "Paradox 7"). Cada tabela tem um arquivo separado. mas através de interfaces adicionais. Criando Tabelas Após definir qual a estrutura que devem ter suas tabelas. o Delphi inclui os drivers "SQL Link". Definindo um Diretório de Trabalho Antes de começar a criar tabelas. com todas suas tabelas.. Dependendo do formato de dados. · dBASE/FoxPro: formatos semelhantes. dependendo do custo necessário e do tamanho e quantidade de acessos previsto para os seus dados. você pode utilizar um programa específico do banco de dados ou usar um utilitário fornecido juntamente com o Delphi — o Database Desktop (DBD). Agora deverá aparecer a lista de campos a ser preenchida.. Sybase SQL Server. para ambientes cliente/servidor com até 4 usuários. Informix. · InterBase: o InterBase é um banco de dados da Borland que pode ser usado para desenvolver e testar aplicações cliente/servidor. e digite o diretório onde serão colocados os arquivos do curso ("C:\CURSODF\TABELAS"). chamado "InterBase Local".. permite acessar praticamente qualquer banco de dados padrão de mercado. · ODBC: permite utilizar drivers ODBC. você pode optar por um formato desktop ou cliente/servidor. mas utilizado por vários fabricantes de bancos de dados. é melhor definir um diretório de trabalho. Clique Ok para aceitar o default.. Cada tabela é um arquivo separado. dBase. com pequenas diferenças. um banco de dados da Borland. ODBC pode ser usado a partir da edição Professional. A edição Client/Server vem com o InterBase para Windows NT. Você pode salvar tabelas em qualquer diretório. use File|New|Table. da Microsoft.MDB. num único arquivo de extensão GDB. com a extensão DBF. ou se você está criando o banco de dados a partir do início. Neste último caso. Através do ODBC você pode utilizar outros bancos de dados que não são suportados das outras formas. Microsoft SQL Server. Clique Ok. que é um padrão definido pela Microsoft.

Para esse campo. Como é uma tabela Paradox. Note como o campo DataNasc é automaticamente validado. Clique com o botão direito na coluna "Type" para escolher um tipo de dados ou digite diretamente a letra correspondente. O campo "DataNasc" é do tipo "Date". então pule a coluna "Type". existem dois tipos de índices. se a configuração do Windows estiver com esse formato.. No nosso caso. clique no botão "Save As. (Só os primeiros campos da tabela podem fazer parte da chave primária). Mas em tabelas Paradox. você pode entrar com alguns dados para teste no próprio Database Desktop. marque a coluna "Key" apenas para o campo "CodCliente". A coluna "Key".DB. Salvando a Tabela Para salvar a tabela. Para isso abra a tabela que você criou com File|Open|Table. mas também permite salvar em qualquer outro diretório. dígitos e espaços. Os tipos de dados em tabelas Paradox são representados por letras. Note que o DBD vai mostrar o diretório de trabalho (definido anteriormente). Entrando com Dados Após criar a tabela. use [Ctrl+Del]. Tecle [ ] (seta para baixo) para definir os outros campos.. que corresponde a um número inteiro binário. "29/02/97" (1997 não é bissexto). Para excluir um registro. e também determina a ordem default em que os registros serão percorridos. Como o campo "CodCliente" é a chave primária. Ele é lido e mostrado no formato "dia/mês/ano". 99 . Os campos "Nome" e "Telefone" são alfanuméricos. Faça isso com um duplo clique do mouse ou pressionando qualquer tecla. diz que o campo é parte da chave primária da tabela.". Nota: o Windows armazena uma configuração padrão para formato de datas. criando um arquivo CLIENTE. ou [Tab] e [Shift+Tab] para mudar de campos e a seta [ ] para incluir um novo registro. isto é.. o conteúdo anterior é perdido. e não permite edição. que vai colocar a tabela em modo de edição. do tipo "Alpha".. embora normalmente ele esteja configurado para mostrar apenas dois dígitos. Digite as características dos campos nas colunas apropriadas. Em tabelas Paradox. que armazena datas. índices pode ser usados para pesquisa ou ordenação de valores. Para acrescentar um registro no meio. O tamanho do campo é determinado automaticamente. e não permite datas inválidas como "32/04/97". . selecionando CLIENTE. use a tecla [Ins].. Digite alguns dados de teste para preencher a tabela. números etc. com a mesma faixa de valores do tipo smallint do Object Pascal. quando você começar a digitar. O mesmo tecle [F9] ou clique no botão processo volta ao modo de visualização.Digite o nome do campo "CodCliente" na coluna "Field Name" e tecle [Tab] ou a seta [ ] para mudar para a coluna "Type". enquanto outros tipos como "Short" e "Date" não permitem uma determinação de tamanho. Note que o ano sempre é armazenado com quatro dígitos. escolha o tipo "S" (short). ela está em modo de visualização. a extensão de arquivo ". ícone "Configurações Regionais". mas ainda sem nenhum registro. Você vai ver a estrutura da tabela. Em qualquer tipo de tabela. horas. Os registros sempre serão mantidos na ordem desse campo.DB no diretório.DB" será adicionada automaticamente. nomes de campos podem ter até 25 caracteres. (outros formatos de dados têm regras diferentes). Note que eles exigem a definição do tamanho do campo. porque utilizam um tamanho automático. Digite o nome "CLIENTE" e clique Ok. Use as setas. se estiver marcada. Um índice secundário [secondary index] é usado apenas para pesquisa e ordenação. O índice primário [primary index] ou chave primária [primary key] determina um valor que deve ser único para todos os registros da tabela. que é usada por todos os programas. Ela pode ser alterada através do Painel de Controle. Para editar os dados. Tecle [F2] ou clique no botão quando quiser editar um campo senão.. e podem incluir letras. você não pode incluir dois registros que tenham o mesmo valor desse campo. Quando você abre uma tabela.

100 .

basta especificar qual a tabela a ser acessada e ele cria um formulário contendo tudo que é preciso. O que é feito pelo Database Form Wizard (DFW) é o que fizemos manualmente no "Cadastro de Cliente". ele facilita o trabalho inicial. Agora você deve selecionar a tabela a ser utilizada. Criando um campo autoincremento Quando definimos um campo sendo autoincremento. A primeira tela oferece dois grupos de opções: Mantenha as opções padrão: "Create a simple form" em "Form Options" indica que vamos criar um formulário "simples". Para criar uma nova tabela no Database Desktop . e digite os campos como abaixo: Campo Tipo Tamanho Chave CodProduto + * Nome A 40 QtdEstoque S PrecoVenda N CodForncedor S No Paradox o que identifica um campo sendo autoincremento é o tipo sendo + (AutoIncrement) . Criando um Formulário para Acessar a Tabela com Form Wizard Crie um novo projeto no Delphi e depois acione o item de menu Database| Form Wizard. Selecione PRODUTO. 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. Note que o campo PrecoVenda vai usar o tipo N (Number).. O conteúdo desta coluna . Veremos as outras alternativas mais tarde. que foi criada anteriormente e clique em Next. não é preciso programação nem mesmo criação de componentes. Esse tipo equivale ao tipo double do Object Pascal. Outro detalhe é que não podemos informar seu conteúdo durante uma alteração ou inclusão de dados. Como exemplo vamos criar a tabela de produto.. no menu File|New|Table. e você pode personalizar o formulário criado da forma que você quiser.conseguimos obter somente quando o registro for gravado. permite armazenar números inteiros bem como números com parte fracionária. Clique em "Next". isto é. a coluna que foi definida com este tipo tem um único valor que é gerado automaticamente pelo sistema. Podemos ter somente um coluna com esse tipo na tabela. Na próxima tela. Mas na maioria das vezes.DB. Com essa ferramenta. você pode 101 ..Exemplo: Usando o Database Form Wizard A forma mais rápida de criar um programa que acessa bancos de dados em Delphi é utilizando o Database Form Wizard [assistente de formulário de banco de dados].. O DFW é dividido em várias telas de informações..

Isso é preciso porque o Database Form Wizard cria um novo formulário. lêem e gravam no banco de dados. Execute o projeto e cadastre alguns produtos. selecione Form1 e clique OK. Testando o Programa Note que o formulário gerado tem vários componentes já posicionados.. 102 . Clique duas vezes no valor do evento OnCreate. no Object Inspector. clique no botão [>>] e depois em Next. e clique no botão "Finish". Para selecionar todos os campos. clique na página de eventos. como o DBEdit. Deixe essa opção marcada. Selecione o formulário (tecle [Esc] algumas vezes se houver algum componente selecionado) e. incluindo controles de dados para cada campo da tabela. os componentes que tiverem alguma propriedade associada com o componente Table o Delphi automaticamente muda o nome também .. Vamos alterar a propriedade Name do componente table para 'tblProduto'. Se ela estiver marcada. como o nome do componente Table foi mudado precisamos também alterar um trecho de código no formulário que abre a tabela (no exemplo anterior usamos a propriedade Active). Altere o Caption do formulário para "Cadastro de Produto" e a propriedade Name para formCadProduto. No componente DataSource colocar o nome sendo 'dsProduto'. Resumo dos Componentes de Dados Neste capítulo fizemos alguns projetos que utilizam os componentes de acesso a dados e os controles de dados do Delphi. Salvando o Projeto Antes de salvar o projeto. o nome só não é mudado em linhas de código .Open. o novo formulário será o principal do projeto. Você pode alterar a posição e o tamanho do formulário como quiser.Open. Você pode escolher um lay-out para o formulário. O que o DFW faz quando cria um novo formulário é o mesmo processo que fizemos para criar o formulário manualmente. Note que para alterar uma propriedade do formulário você deve selecionar o formulário. Clique em Project|Remove from project. Escolha o padrão "Horizontally" (Horizontal) e clique em Next. e irá aparecer um procedimento de evento contendo: Table1. O componente DataSource faz a ligação entre estes componentes e os controles de dados. Cada controle de dados é responsável por ler e gravar os dados de um campo. A última tela tem uma opção "Generate a main form" [gerar um formulário principal]. Altere esse comando para: tblProduto. devemos remover o formulário inicial. mas não altera os anteriores. o fluxo dos dados nesse tipo de programa é: Os componentes de acesso a dados. dando os nomes de CADPRODUTO e CADPRODUTOP. como o componente Table.. tecle [Esc] até não aparecer nenhuma indicação de seleção. Agora salve o projeto.escolher apenas alguns campos ou todos os campos da tabela para utilizar no formulário. Se um componente estiver selecionado. De forma geral. que não tem função nenhuma.

ou apelido. clique em Object|New. que indica que esse nome ainda não foi salvo na configuração: 103 . mas é mais fácil usar um utilitário que faz parte do próprio Delphi. Você verá uma tela como a seguinte: O Database Explorer mostra do lado esquerdo. Para resolver esse problema. Ele permite também visualizar e alterar os dados de qualquer tabela. No nosso caso. um alias também é a forma mais usada para acesso aos dados. na página "Databases". que é o padrão. Note que um triângulo aparece à esquerda do nome. Os apelidos são armazenados em um arquivo de configuração do BDE e são globais a todas as aplicações em Delphi. uma árvore contendo os apelidos que já foram definidos. através do comando Tools|Alias Manager.. Mas com isso o programa fica dependente do local onde estão armazenados os dados.Apelidos de Bancos de Dados Quando você desenvolve uma aplicação de banco de dados. Você deve escolher o tipo de banco de dados que será usado. através de um apelido. Clique Ok e o novo alias aparece na lista. você deve especificar o diretório onde estarão os seus dados (se for um banco de dados local) através da propriedade DatabaseName de um componente Table. Um alias. Num banco de dados cliente/servidor. deixe selecionado o tipo STANDARD (acesso a Paradox e dBase).. Se você mover as tabelas para outro diretório. Para isso clique em Database|Explore no menu do Delphi. o programa não vai mais funcionar como antes. porque ele guarda também outros parâmetros de configuração. Os tipos disponíveis dependem de quais drivers estão instalados no computador. o Database Explorer. com o nome provisório de "STANDARD1". Para criar um novo alias. é um nome que pode ser usado nos programas em lugar de especificar o diretório. Digite "CursoDelphi" para o alias. Você pode criar ou alterar apelidos usando o utilitário Database Desktop (DBD). existem os alias do BDE.

como o projeto CADCLIENTeP. Faça a mesma alteração para o projeto CADPRODUTOP. CLIENTE. depois abra o ícone "Tables" e você verá as tabelas definidas. Abra um dos projetos anteriores. No componente Table. abra a lista de valores e selecione "CursoDelphi" e altere novamente a propriedade Active para True. 104 . clicando na página "Data": Note que aparecem botões de controle na parte superior. Agora clique no botão (Apply) para salvar as alterações.Do lado direito. Se você quiser ver as tabelas que estão neste alias. estão os parâmetros de configuração do alias. basta alterar o alias novamente. sempre mostra quais são os aliases cadastrados. usando o Database Explorer ou o Database Desktop. O único parâmetro que importa no caso é o PATH. O programa vai mostrar os mesmos dados que antes. Para fechar a conexão com o alias. primeiro altere a propriedade Active para False. clique no sinal de [+] ao lado do nome para abrir o alias. ou visualizar e alterar os dados. por exemplo. Agora feche o Database Explorer (ou SQL Explorer) e retorne ao Delphi. A lista de valores na propriedade DatabaseName. clique em CursoDelphi e no botão (Open Close). Clique neste e digite "C:\CURSODF\TABELAS" (o diretório onde estão os arquivos do curso). mas agora ele não é mais dependente do diretório "C:\CURSODF\TABELAS". Ao clicar em uma delas. Se você quiser mover os dados para outro lugar. semelhantes ao DBNavigator.DB. você pode visualizar informações gerais sobre a tabela. Depois selecione a propriedade DatabaseName.

Capítulo 13 Recursos Adicionais Definindo Tabelas Criando o Menu Principal Alterando o Formulário Principal Usando o Controle DBGrid 105 .

sempre que possível. "A" para o tipo e 11 para o tamanho. clique no campo Telefone e pressione [Insert]. ou mudar seu tipo para uma faixa de valores menor. Digite "CPF" no nome do campo. Agora adicione dois campos no final: clique no campo DataNasc. mas obviamente. removendo campos existentes ou alterando o tipo de um campo. no qual teremos um cadastro de clientes... entre Nome e Telefone. se você reduzir o tamanho de um campo. você sempre pode alterar a estrutura desta. Para reestruturar a tabela. um controle das vendas efetuadas para cada cliente e de itens vendidos para cada venda. iremos desenvolver um mini-sistema de controle de vendas.. Os dados anteriores são preservados. A estrutura da tabela agora é a seguinte: Nome do Campo Tipo Tamanho Chave CodCliente S (automático) * Nome A 40 CPF A 11 Telefone A 10 DataNasc D (automático) Cidade A 20 Estado A 2 106 . 25 e "Estado". criada anteriormente. "A". use Table|Restructure Table. Para isso. acrescentando novos campos. você pode perder parte dos dados. "A". A mesma janela com a estrutura dos campos aparece. O modelo abaixo mostra como estão relacionadas as tabelas que serão utilizadas no nosso exemplo: Volte ao Database Desktop para definir tabelas adicionais e alterar a estrutura da tabela de cliente. pressione a seta para baixo e digite os novos campos: "Cidade". Isso vai envolver várias tabelas adicionais no nosso banco de dados. Reestruturando a Tabela "Cliente" Após criar uma tabela. Vamos adicionar um campo no meio da estrutura.Definindo Tabelas Durante o curso. 2.

. pois. o índice só é atualizado quando você tentar fazer uma pesquisa. Nesse caso. Clique nesse botão para ver a janela de definição de índices. O campo "CodCliente" está relacionado com um registro da tabela "Cliente". Clique em "Save As.. que é o mais usado." para salvar a tabela "VENDA". Clique em OK para salvar o índice e dê o nome de "IntCliente". como antes e defina a seguinte estrutura para a tabela: 107 . Com banco de dados Client/Server utilizar a integridade referencial é bem mais seguro.. ao colocar o programa para funcionar principalmente em rede ocorre problemas do tipo "Arquivo Corrompido" ou "Índice Fora de Data". clique no botão "Save". existem opções que você pode alterar. indicando que esta venda se refere àquele cliente. O Database Desktop vai pedir um nome para o índice. Para definir que o campo "Nome" fará parte do índice. selecione-o e clique na seta para a direita. A opção "Maintained" faz com que o índice seja mantido automaticamente a cada alteração. Agora clique em OK para salvar o índice. as pesquisas no índice fazem diferença entre maiúsculas e minúsculas.. entre com dados para o campo CPF nos registros. o que toma certo tempo. Iremos criar integridade referencial somente nesta tabela.Criando um Índice Secundário Antes de salvar a tabela modificada. Para salvar a tabela modificada. Mais tarde veremos como utilizar um índice secundário no programa.. a não ser que exclua as vendas . Criando Integridade Referencial Vamos alterar a estrutura da tabela "Venda". não é muito seguro. para isto clique na lista "Table Properties". Se estiver desabilitada. Criando a Tabela de Itens No DBD. A opção "Case sensitive" só tem efeito em campos alfanuméricos. Na lista da esquerda estão todos os campos da tabela. Criando a Tabela "Venda" Vamos criar agora a tabela de vendas. Como o campo "CodCliente" nesta tabela está relacionado com um registro da tabela "Cliente" . Se habilitada. Se quiser. Clique na lista à direita. Nota: você também pode criar um índice que utiliza vários campos da tabela. faça como antes. que identifica um registro de venda. usando File|New|Table. Selecione o campo "CodCliente" na lista da esquerda. e clique na seta para movê-lo para a direita. Então na tabela "Venda" vamos alterar sua estrutura criando "Integridade Referencial" na coluna 'CodCliente' com a tabela "Cliente" . abaixo de "Table Properties". a título de demonstração. e digite os campos como abaixo: Campo Tipo Tamanho Chave CodVenda S * CodCliente S DataVenda O campo "CodVenda" é a chave primária da tabela. vamos criar um índice secundário para o campo Nome.. escolha a opção "Referential Integrity" e clique no botão "Define.. Agora o botão "Define." para salvar a tabela e digite o nome "VENDA".." estará ativo... Clique em "Save . e escolha a opção "Secondary Indexes". Basta adicionar todos os campos utilizados à lista da direita.. Para criar uma nova tabela no DBD. não podemos deixar que neste campo seja colocado código do cliente que não exista na tabela "Cliente" e até mesmo ao excluir um cliente não pode ser permitido excluir um cliente que tenha venda . Notas: Utilizar integridade referencial no Paradox.. use File|New|Table. No caso do Paradox uma saída seria tratar a integridade pelo Delphi.para depois excluir o cliente desejado (chamamos este processo de exclusão por cascata). O nome segue as mesmas regras de nomes de campos. abaixo da lista de campos. para facilitar as pesquisas e ordenações por nome. No quadro "Index Options".". coloque o nome de "IndNome".

dando o nome de "FORNECEDOR. 108 . Depois feche o DBD e retorne ao Delphi. use File|New|Table.. Salve a tabela com o botão "Save as.. dando o nome de ITEM. selecione o campo CodVenda e clique Ok. Dê o nome de "IndNome" para o índice e clique Ok. Para definir um índice secundário. mas é melhor usar um nome com oito ou menos caracteres para manter compatiblidade com programas mais antigos. Criando a tabela Fornecedores No DBD."... Para definir um índice secundário.... faça como antes: selecione "Secondary Indexes"..DB". faça como antes: selecione "Secondary Indexes". Salve a tabela com o botão "Save as. como antes e defina a seguinte estrutura para a tabela: Campo Tipo Tamanho Chave CodFornecedor S * Nome A 60 Defina também um índice secundário no campo 'Nome' ."...Campo CodVenda CodProduto Quantidade Tipo S S S Chave * * Defina também um índice secundário no campo CodVenda.". selecione o campo 'Nome' e clique Ok.". Isso é necessário para que o Delphi possa tratar o relacionamento mais tarde. Dê o nome de "IndVenda" para o índice e clique Ok. Nota: nomes de tabelas podem ter até 253 caracteres (fora extensão).db (lembre-se que a extensão não precisa ser digitada). clique no botão "Define. clique no botão "Define.

digite "-" (um sinal de menos). Se você não os preencher. Ele é o primeiro da página Standard: . que tem uma aparência como a seguinte: O Menu Designer mostra uma simulação do menu e permite você criar os itens de menu que você vai utilizar. além de alguns novos. Agora crie o item "Fornecedor". O Menu Designer vai mudar para a seguinte aparência: À direita e abaixo do item. precisamos inserir um componente MainMenu no formulário. Agora digite o texto do próximo item: "Cliente" e tecle [Enter]. O formulário criado durante a criação do projeto será o formulário principal . o Object Inspector vai mostrar as propriedades do item selecionado. crie um item "Venda". Crie um novo projeto no Delphi. eles não vão aparecer no menu final.Criando o Menu Principal Vamos criar um programa onde utilizaremos os formulários criados anteriormente. Depois da barra. Para criar uma barra separadora. Para criar o primeiro item. O MenuDesigner: criando menus Para utilizar um menu em um programa. A aparência final vai ficar como na figura: 109 . clique duas vezes nele para abrir o Menu Designer. crie novamente uma barra separadora e finalmente crie mais um item "Sair". Após colocá-lo no formulário. O marcador vai passar para a próxima linha. sempre ficam disponíveis retângulos vazios que você pode preencher para criar novos itens. Em seguida crie uma barra separadora no próximo item. simplesmente digite "Cadastro" (sem as aspas) e tecle [Enter]. À medida que você criar itens de menu. Crie mais um item "Produto". este formulário será a janela a partir da qual o usuário acessa as outras janelas do programa.

com um número acrescentado ao final (por exemplo.Quando você digita o texto do menu. por "menuCadastro". você está alterando a propriedade Caption de cada item de menu. Nós vamos mudar esses nomes para definir um padrão mais descritivo. Clique no item "Cadastro" e na propriedade Name. de acordo com a tabela: Cliente menuCadClientes Produto menuCadProdutos Fornecedor menuCadFornecedores N!(separador) Venda menuCadVendas N2(separador) Sair menuCadSair Agora clique no item vazio à direita do item Arquivo e digite "Editar". Cadastro1). crie subitens de acordo com a figura: A propriedade name altere de acordo com a tabela abaixo: Consultas menuConsultas Cliente por Estado menuconCliEstado Vendas por Cliente menuConVendasTotais 110 . O Object Inspector automaticamente altera a propriedade Name de cada item para ser igual ao valor do Caption. troque "Cadastro1" (o nome que o Delphi colocou automaticamente). Abaixo desse item. Faça de forma semelhante para os outros itens.

use o [Ctrl+Del]. Acrescente no Menu Designer o item de menu abaixo Crie a seguinte estrutura de menus: Relatório menuRelatorios Clientes menuRelClientes Vendas por Produto menuRelVendasProduto Teclas de Acesso e Teclas de Atalho Apesar do Windows geralmente ser mais fácil de usar com o mouse. pressione a tecla [Ins]. sem utilizar o mouse. begin end. também pode clicar os subitens não vão fazer nada. Para tratar eventos em um sub-item de um menu. Para excluir um item de menu.menuCadSairClick(Sender:TObject). envolve uma forma de selecionar menus através do teclado. pressione a tecla [F10]. use [Ctrl+seta para direita]. pois ainda não fizemos nenhum tratamento de eventos.Nota: O Menu Designer tem outras facilidades também. ele finaliza a execução. Clique duas vezes no componente (MainMenu) no formulário para chamar o Menu Designer. basta fechar o formulário. Além dessa facilidade. mas não no Menu Designer). como é o único formulário do programa. mas não permite modificação. Uma tecla de acesso aparece como uma letra sublinhada no texto do menu. Para definir um nível adicional de submenu. Faça de forma semelhante para todos os outros itens (não altere as barras separadoras): Item &Clientes &Vendas &Produtos Tecla de Acesso &C &V &P 111 . Para verificar isso durante a execução do programa. Clique no menu "Cadastro" e depois no item "Sair". digite &Cadastro. Clique no menu "Cadastro" e na propriedade Caption. as teclas [ ] e [ ] são usadas para movimentação entre os itens do menu. utilizando um comando (na verdade. Quando o menu está aberto. Para um menu da barra principal. Execute o programa e clique em Arquivo|Sair. O método Close fecha o formulário e. Para isso. onde letra é a tecla de acesso. O programa deverá finalizar e retornar ao modo de projeto. você pode definir uma tecla de acesso para cada menu e cada item dentro de um menu. Se você executar o programa. Quando o menu está aberto. Isso entre outras coisas. Para inserir uma tecla de acesso no 'C'. O Delphi vai abrir um procedimento de evento para esse item: procedure TForm1. o usuário pode abrir o menu pressionando [Alt+letra]. [Enter] para acionar o item selecionado. ou [Esc] para fechar o menu aberto. O Windows já fornece automaticamente uma interface padronizada de teclado para os menus. Você pode clicar nos menus "Arquivo" ou "Editar" para ver os seus subitens. O menu vai estar inserido no formulário. exatamente com a aparência que foi definida é que ele irá aparecer para o usuário. um método) chamado Close: Close. basta abrir o menu e clicar no sub-item (no formulário. Esse item deve terminar o programa quando clicado. Agora você pode usar as teclas [ ] e [ ] para mudar entre os itens na barra de menu e [Enter] para abrir um menu. Tratando Eventos de Menus Feche a janela do Menu Designer e retorne ao formulário "real". Para inserir um item de menu no meio. um item do menu pode ser acionado pressionando-se sua tecla de acesso (sem usar [Alt]). é bom ter em mente que um programa Windows também deve ser fácil de usar apenas com o teclado.

De forma geral. Já itens em menus diferentes podem usar a mesma tecla sem problemas. e isso desvia do propósito original desse tipo de acesso.Para "Produtos" .. top := 0. O Delphi permite fazer isso. Ainda no Menu Designer. clique no item "Clientes" e na propriedade Shortcut [atalho]. coloque "Ctrl+E". Nota: Teclas de atalho devem ser únicas entre todos os itens de menu. por exemplo. Associando os formulários aos itens de menu 112 .C]. Selecione da lista a opção "Ctrl+K". é bom tentar economizar teclas de atalho.PAS e CADPRODUTO.PAS e o projeto de VENDAS. A propriedade ShortCut fornece um acesso rápido pelo teclado em alguns itens. Isso porque já existe um atalho definido pelo Windows para sair de um programa qualquer: [Alt+F4]. o usuário não conseguirá memorizá-las. e coloque os códigos abaixo: left := 0. Salve o projeto e chame a unidade do formulário principal de VENDPRIN. Note também que o item Sair não tem uma tecla de atalho. Se você abrir um menu do Delphi. Altere sua propriedade Caption para "Controle de Estoque". de forma que ele não ocupe espaço na tela. Se você tem muitas teclas de atalho. Nota:Você não deve repetir a mesma tecla em um grupo de itens do mesmo nível. pode ser acionado com as teclas [Alt+C. o item Cadastro|Cliente. Acrescentando os formulários anteriores Neste projeto iremos acrescentar os formulários criados anteriormente.. que você não precisa alterar. Altere o Name do formulário para 'FormPrincipal'. esteja onde estiver o foco de teclado.&Fornecedores &Sair C&onsultas Clientes por &Estado &Vendas por Cliente &Relatório &Clientes &Vendas por Produto &F &S &O &E &V &R &C &V Agora. Para "Vendas. ou a propriedade Height. você deve clicar no ícone (Add File to Project). e não precisam ser letras. [Ctrl+F7] etc. mas a tecla não vai funcionar da forma esperada. Num projeto grande.DPR. Note que nos itens separadores. é importante dar nomes distintos aos vários formulários. Adicione as unidades CADCLIENTE. como [Ctrl+S].PAS. Você não precisa abrir um menu para acionar a tecla correspondente a um item. Alterando o Menu Principal Alterando Propriedades Reduza o tamanho do formulário na vertical. coloque "Ctrl+P". Só itens de menu podem ter teclas de atalho (não os menus da barra principal). Outra forma de acionar itens de menu é através de teclas de atalho [shortcut keys]. Crie um procedimento para o evento OnCreate . e só colocar essas teclas nos itens mais utilizados do programa. Execute o programa e teste as teclas. A diferença é que teclas de atalho podem ser usadas mesmo quando o menu não está aberto. [F5]. deixando apenas a barra de menu visível.". o Delphi coloca momes padrão(N1 e N2). Para cada um dos fomulários. A barra de menu irá ficar posicionada no topo do DeskTop. verá que teclas de atalho aparecem à direita do item.

acrescente: uses CadCliente. Clique no item de menu Cadastro|Produto e . Defina suas propriedades como antes: Table Name: tblCliente DatabaseName: CursoDelphi TableName: CLIENTE. que pode ser escolhido na lista de valores. A grade de dados já vai mostrar os dados da tabela e você pode usar as barras de rolagem para ver mais registros. Fique posicionado na unit "VendPrin" . com os nomes de todas as unidades. De agora em diante. vários formulários podem estar na tela ativos simultaneamente.O formulário principal. para mostrar um formulário da forma "tradicional". Para que ele possa fazer isso.menuConCliEstadoClick(Sender: TObject).DB DataSource Name: dsCliente DataSet: tblCliente Note que em DatabaseName estamos usando o alias definido anteriormente. Para criar um formulário ir no menu File|New Form . que permite visualizar vários registros ao mesmo tempo. usando um controle para cada campo. Criando os Componentes de Dados Vamos criar um novo formulário e utilizar a mesma tabela de clientes.Note que no início da execução. 113 . Ao clicar em um item de menu. coloque o seguinte comando: formCadCliente. coloque : formCadProduto. você pode usar um controle DBGrid. Manipulando dados no DBGrid Para verificar o funcionamente do DBGrid . Agora tecle [F12] para voltar ao formulário. por exemplo Cadastro|Clientes. temos que no menu principal chamar o formulário. Altere a propriedade Align do DBGrid para "alClient". Agora volte ao componente Table e altere sua propriedade Active para True. Clique no item de menu Cadastro|Clientes e. a unidade principal deve ter uma cláusula uses.Show.Show. no procedimento de evento. aparece apenas o formulário principal. no procedimento de evento. Selecione a página Data Access e coloque no formulário um componente Table e um componente DataSource. Como os formulários não são modais. Agora abra a página Data Controls e selecione o ícone (DBGrid). usaremos esse nome para fazer referência ao diretório. Coloque o componente no formulário e altere sua propriedade DataSource para "dsCliente". desta forma o DBGrid irá preencher todo o formulário. mas com um componente DBGrid. nessa unidade logo após a palavra implementation. Salve o projeto e depois execute o programa. que contém os itens de menu. no clique no menu Consultas|Clientes por Estado e coloque o comando a seguir: procedure TformPrincipal. aparece o formulário correspondente. irá chamar cada um dos formulários criados. Altere também a propriedade Name do formulário para "formConsClienteEstado". Posicione no formulário da Unit VendPrin . CadProduto. "CursoDelphi". Você pode clicar novamente no formulário principal e abrir outro formulário. Iremos fazer a mesma coisa para o Produto. Usando o Controle DBGrid Além de usar os controles de dados.

pas". e isto é feito no editor de campos. Cada nove na máscara corresponde a uma posição digitada pelo usuário. tecle [Ctrl+Del]. clique no menu Consultas|Clientes por Estado e verifique o funcionamento do DBGrid. Clique duas vezes no valor ou uma vez no botão de reticências. A estrutura da tabela "Cliente" foi alterada . digite: 999. que só permite números. editando o valor existente. que tem propriedades para definir a formatação do campo. mudar a cor do campo. Clique duas vezes no componente 'tblCliente' no formulário para abrir o editor de campos. Para alterar um campo. você precisa criar uma lista persistente de objetos.. Agora quando você clicar em um dos campos na lista. foi acrescentado alguns campos que ainda não foram adicionados ao editor de campos. Alterando a Máscara de Edição Cada campo pode ter também uma máscara de edição. para cada campo da tabela. você pode digitar um valor diretamente para essa propriedade. Se ele ficar desmarcado. Execute o programa.Até agora utilizamos os objetos de campos para criar os controles de dados. Você pode usar as setas para mover entre campos (linhas) e registros (colunas). um objeto TField correspondente. end. É importante também desmarcar o quadro "Save literal characters". pressione [F2]. clique com o botão direito no fundo e clique em "Add fields. os pontos e traços da máscara serão incluídos no campo.999. mas ele tem outras finalidades também colocar máscara para a edição de determinados campos. No Object Inspector. mas os outros caracteres sempre aparecerão na máscara. Para alterar a máscara de edição. No editor de campos. clique no campo CPF. ou teclar [Insert]. tamanho com o qual ele aparece na tela etc.999-99. um 0 ou 1 é adicionado ao final da máscara. os dados do registro são imediatamente gravados. por exemplo. colocando o valor "dd/mm/yyyy". CadProduto. como todos os campos estão selecionados clique em Ok para adicioná-los. mas é mais fácil usar o editor especializado. e o usuário não precisa digitar. Quando a lista de campos está vazia. Para adicionar os objetos de campo que estão faltando. quando ele for gravado. Note que quando você altera essa opção. Ficando desta forma: uses CadCliente. será mostrado somente os campos que foram acrescentados a tabela . uma uses para a unit ConsClienteEstado. vamos colocar uma máscara no campo CPF. ele cria internamente. No editoe de campos clique em "DataNasc" vamos mudar o formato de data que é usado para mostrar as datas. Acrescente na unit VendPrin na seção implementation. Quando você utiliza o componente Table. Nota: você também pode alterar características das colunas se você clicar duas vezes no próprio DBGrid. 114 . imediatamente verá uma mensagem de erro (por exemplo. caso esteja na unit pressione a tecla [F12] para mostrar o fomulário. mas que o usuário não precisa digitar.show. no campo DataNasc). só os caracteres digitados serão incluídos no campo. Para excluir um registro. Salvar esta unit como CONSCLIENTEESTADO.begin formConsClienteEstado. Usando o Editor de Campos Vamos posicionar na unit "CadCliente. ConsClienteEstado. Quando você sai de uma linha. que define alguns caracteres que aparecem no campo. as propriedades do campo (do objeto TField) aparecem no Object Inspector. significa que todos os campos terão as propriedades default. Se esse quadro estiver marcado. se você digitou um dado inválido. você pode descer abaixo do último registro. No nosso caso. Se você quiser alterar as propriedades dos campos em tempo de projeto. que é bem semelhante a uma grade de dados do Database Desktop. clique na propriedade EditMask.. Para inserir um registro. Altere a propriedade DisplayFormat. Mas geralmente não é necessário alterar opções no próprio DBGrid.". Na máscara de edição. Essas alterações têm prioridade sobre as propriedades dos campos da tabela e você tem outras opções como. Quando você tenta sair de um campo.

Quando você altera essa opção. clique no campo "DataNasc". pois. tecle [Esc] e tente novamente. se utilizar '9' aceita somente números.É importante que a opção "Save literal characters" esteja marcada . Vamos definir uma máscara para edição no campo "DataNasc". 115 . quer dizer que naquele local o usuário é obrigado a informar algum número.1. Para testar a máscara. a diferença de utilizar 0 ou 9 é que quando colocamos '0' fazendo parte da máscara.A opção "Character for blanks" define qual o caractere que será usado nos espaços vazios durante a digitação. mas não é obirgatório. '_' (sublinhado). O conteúdo de "Input Mask" será '!99/99/00. esta opção contém uma máscara para data. substitua o '0' por '9'. Então no editor de campos. na mesma janela você pode digitar alguma coisa em Test Input. as barras são gravadas no campo. o caractere é adicionado ao final da máscara. Se você digitar e não conseguir sair do campo (o Delphi vai mostrar uma mensagem). clique na propriedade EditMask . em "Sample Masks" clique na opção "date" . No Object Inspector. Geralmente é melhor manter o padrão._'.

Capítulo 14 Validação e Pesquisas Exemplo: Cliente por Estado Exemplo: Clientes .Alterando Validação de Campos e Registros Tratamento de Exceções Pesquisas na Tabela Blocos Protegidos Usando Outros Controles de Dados 116 .

se editEstado = 'GO' a string do Filter vai conter : Estado = 'GO' Mas a propriedade Filter funciona somente se a propriedade Filtered for True.Alterando Neste capítulo. vamos realizar uma procura onde iremos mostrar os Clientes por um determinado Estado escolhido pelo usuário. No evento OnClick do botão 'btnProcurar'. portanto ele faz diferenciação entre letras maiúsculas e minúsculas. Altere sua propriedade Caption para Altere o nome do controle de edição para 'editEstado'e sua propriedade CharCase para 'ecUpperCase'. vamos alterar a propriedade Filter do componente Table dinamicamente. faremos várias alterações no formulário "formCadCliente". como na figura abaixo: ) . abra esse projeto.text + ''''. 117 . Por exemplo. Notas: O paradox é "case sensitive". Exemplo: Clientes .Atualmente este formulário mostra todos os clientes cadastrados. Exceção somente quando cria um índice secundário para o campo e a opção "case sensitive" deve estar desmarcada. Salve o formulário e execute.Filtered := true. Altere a propriedade Caption para 'Cliente por Estado' e modifique também a propriedade Align do DBGrid para 'alBottom' e aumente o tamanho do fomulário para acrescentar um Componente GroupBox( "Parâmetros". portanto .Open. deixe a propriedade Text vazia. Portanto.Filter := 'Estado = ''' + editEstado.com esta propriedade iremos definir um filtro que irá procurar os clientes que pertencem ao estado indicado. tblCliente. Chame o botão de 'btnProcurar' e mude sua propriedade Default para True. usamos vários apóstrofos na sintaxe.Exemplo: Cliente por Estado Iremos realizar algumas alterações no formulário "formConsClienteEstado". tblCliente. Isso faz com que todas as letras digitadas sejam convertidas em maiúsculas. abra este formulário. Para testar informe alguns estados e clique no botão 'Procurar'. Note que para modificar a propriedade Filter.Digite o seguinte: tblCliente. Cada dois apóstrofos na string representam um apóstrofo na string resultante.Após a alteração da propriedade é necessário abrir o componente Table novamente para ver o resultado.

O nome da função é ValidaCPF ela retorna true se o CPF estiver correto. é necessário também ter a soma de todos os dígitos até a posição 9. mas de como fazer esse tipo de verificação no Delphi. somaDig. · Validação de Registro: é feita apenas quando o usuário muda de registro. 118 . resto : smallint. Validação de Campos e Registros Uma máscara de edição proporciona uma forma automática de validação de campos.Então iremos utilizá-la para verificar se um determinado CPF foi informado corretamente. Deixe o formulário com a aparência semelhante a figura abaixo: Mantenha o editor de campos aberto. a idéia não é explicar como funciona a verificação de CPF . os campos CPF. o usuário não consegue mudar de campo. segue também nesta unit uma rotina para verificação de CGC. Cidade e Estado. Pode ser usada para fazer uma verificação que envolva mais de um campo.Note que ainda faltam no formulário controles de dados para os novos campos que foram acrescentados por último: CPF. executado pelo Delphi quando for necessário. A constante ordZero contém a posição do número 0 na tabela Ascii. pos. cada dígito é necessário multiplicar por 11 e subtrair pela sua posição. Notas:Para verificar se um cpf é válido ou não. Cidade e Estado para o formulário. falta criar os controles de dados. Existem duas formas de validação: · Validação de Campo: é feita logo quando o usuário alterna para outro campo. Os dois últimos dígitos são utilizados para verificação. um de cada vez. Agora arraste. temos que passar como parâmetro um valor do tipo 'String'. e se a validação falha. Os objetos foram criados . Validando Campos Para fazer a validação de campo. no mesmo registro ou em outro. Declare algumas variáveis: var soma. Clique duas vezes em 'tblCliente' (o único componente Table do formulário) para abrir o editor de campos. Para este projeto foi criado uma unit independente chamada GeralVenda que contém uma função para fazer a verificação do CPF. Esse é um evento do componente TField associado ao campo. primeiro certifique que ele tenha 11 dígitos. A verificação do penúltimo dígito é feita através da soma dos dígitos até a posição . Vamos adicionar uma validação ao campo CPF. você deve tratar o evento OnValidate. o usuário não pode mudar de registro. mas você pode também adicionar seu próprio código de validação. Se a validação falha..

for pos := 1 to 9 do begin soma := soma + (ord(textoCPF[pos]) - ordZero) * (11 pos); somaDig := SomaDig + (ord(textoCPF[pos]) - ordZero); end; Verificação do Penúltimo Dígito: Divida o conteúdo da variável soma por 11,faça a subtração do resto pelo número 11 e atribua a uma variável, se o conteúdo desta variável for maior que 9, altere o conteúdo da variavel para 0, em seguida verifique se o conteúdo desta variável é diferente do penúltimo digito do CPF, se for CPF é inválido, caso contrário é necessário verificar o último dígito. 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 dígito é nessário somar os resultados encontrados nos calculos anteriores. Então 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 dígito verificador , se for igual CPF Válido. 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 formulário "formCadCliente" abra o editor de campos para tblCliente e clique no campo CPF na lista. No Object Inspector, abra a página 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 Inválido!'); Abort; end; end; A função ValidaCPF verifica se o CPF esta correto.Caso esteja errado, o procedimento mostra uma mensagem, com ShowMessage e gera uma exceção com o procedimento Abort. Qualquer exceção gerada faz com que o Delphi cancele a movimentação de campo ou de registro, mas é melhor usar Abort porque ele gera uma exceção silenciosa, da classe EAbort, que não mostra nenhuma mensagem de erro além das mensagens do seu programa. Antes de executar o programa na seção 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 ( ), escolha a unit "GERALVENDAS.PAS" em seguida clique no botão "Abrir". Execute o programa e veja o que acontece. Altere um registro existente, digitando um valor para o CPF, Inválido e tecle [Tab] para tentar mudar de campo. Você deve digitar um valor válido ou teclar [Esc] para retornar ao valor anterior do campo. É importante notar que a validação de campo só acontece quando o usuário edita o campo. Um registro já existente, que tenha um valor inválido, não passará pela validação a não ser que o usuário altere o valor do campo CPF. Nota: Quando vários controles estão associados ao mesmo campo, as alterações de propriedade afetam todos eles.

119

Validando Registros
Para fazer uma validação 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 do um registro já existente. Essa gravação pode ocorrer quando o usuário clica no botão DBNavigator ou quando ele muda de registro, se o registro foi alterado. Selecione o componente 'tblCliente', e na página de eventos, clique duas vezes no valor de BeforePost. Neste evento vamos fazer o seguinte: begin if tblClienteNome.IsNull then begin ShowMessage('O nome é obrigatório'); tblClienteNome.FocusControl; Abort; end; if tblClienteCidade.IsNull then begin ShowMessage('A cidade é obrigatório'); tblClienteCidade.FocusControl; Abort; end; end; A propriedade IsNull de um componente TField retorna True se ele tem um valor nulo, isto é, vazio, não informado. Se o campo estiver vazio, o procedimento mostra uma mensagem e chama o método FocusControl do componente. Esse método coloca o foco no controle de dados associado (com isso não é preciso saber o nome do controle DBEdit ligado ao campo). Depois de fazer isso, o procedimento chama Abort para cancelar a gravação do registro. Com a validação de registro, o usuário só tem duas opções: ou digitar valores válidos, ou do DBNavigator. Execute o programa e note que cancelar a edição do campo, com o botão agora essa validação também é feita se você incluir um registro e tentar gravá-lo. Salve e execute o programa. Para testar crie um novo cliente , não informe seu nome , mas coloque o nome da cidade onde ele mora, ao salvar o cliente , o cliente não será salvo enquanto não informar o seu nome. Notas: A verificação se um campo é ou não obrigatório pode ser no banco de dados e no Delphi podemos fazer a verificação através de erros.Veremos nos próximos capítulos.

120

Tratamento de Exceções
Desmarque a opção " Stop on Delphi Exceptions" no menu Tools | Debugger Options | Language Exceptions. Mas tarde iremos entender o motivo. Observe que ao digitar uma data inválida , ocorre a seguinte mensagem:

Esta mensagem que aparece é um erro de execução, ou seja, uma mensagem do Delphi avisando de uma condição de erro.O termo usado no Delphi para essas situações é exceção.Uma exceção[exception] é uma condição anormal que ocorre durante a execução do programa, que interrompe o seu funcionamento. Quando ocorre uma exceção, o Delphi mostra uma mensagem padrão e termina a execução do procedimento de evento atual, mas continua a responder a eventos e executar o programa.Para qualquer exceção, você pode fazer seu próprio tratamento, interceptando o tratamento do Delphi. Para tratar essa exceção 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 conteúdo do objeto de campo. Neste procedimento o parâmetro "Text" contém o valor da data informada. Coloque o código a abaixo: var Data : TDateTime; begin try data := strtodate(text); tblClienteDataNasc.asDatetime := data; except on EConvertError do begin showmessage('Data Inválida!'); abort; end; end; end; O comando try (tentar) é um comando de tratamento de exceções. Os comandos entre o try e o except são executados, mas se ocorre alguma exceção nesse bloco, o Delphi sai do bloco e entra na parte except[exceto]. Então o Delphi procura uma cláusula on correspondente à classe da exceção gerada. Se ele encontra um on correspondente, ele executa o comando de tratamento associado. Depois de executar o tratador, o Delphi não termina a execução do procedimento de evento, mas continua a execução com o próximo comando depois do end do try. A função strtodate converte uma variável do tipo string para data, caso ocorra algum erro gera uma exceção da classe 'EConvertError', se ocorrer a exceção mostramos a mensagem 'Data Inválida' , em seguida o comando abort é executado ,es este comando cancela o procedimento, se ele não for colocado a mensagem do Delphi irá continuar aparecendo. Quando colocamos algum procedimento para este evento , ao sair do procedimento a data

121

Para verificar esta opção no menu Tools | Debugger Options | Language Exceptions e marque a opção " Stop on Delphi Exceptions". Pesquisas na Tabela Uma característica fundamental de um programa é permitir que o usuário faça uma pesquisa em uma tabela. o tratador mais específico nem vai chegar a ser executado. Adicionando um DBGrid Para isso vamos adicionar ao formulário um controle DBGrid. fornecendo o valor a ser pesquisado. Classes de Exceções Quando você faz o tratamento de exceções. pode tratá-las a nível específico de cada exceção ou você pode tratar uma classe de exceção mais geral. permitindo selecionar qualquer um deles. ela será acionada para qualquer uma das classes abaixo na hierarquia.informada não será colocada no objeto de campo. vamos facilitar a pesquisa pelo nome do cliente. Notas: O tratamento de exceção pode ser feito em qualquer procedimento que julgar necessário. A classe Exception é o nível mais geral de tratamento e intercepta qualquer exceção. Agora execute o programa e provoque uma exceção. como a seguinte: Exception (qualquer exceção) EIntError (erros de números inteiros) EDivByZero (divisão por zero de inteiro) EIntOverflow (transbordo inteiro) ERangeError (valor ou ind. tecle[F9] ou clique no botão (Run). Visualizando Informações sobre Exceções Se a opção " Stop on Delphi Exceptions" estiver marcada . que vai mostrar toda a lista de clientes. Se num conjunto de tratadores. o projeto causou uma exceção da classe 'EConvertError'. você colocar um tratador primeiro para uma exceção mais geral e depois para uma exceção específica. seja divisão por zero (EZeroDivide). de real) EZeroDivide (divisão por zero de real) Se você criar uma cláusula de tratamento para uma exceção mais geral. Na tabela de clientes. Nesse caso a mensagem será: ou seja . Para continuar a execução. Depois irá aparecer a mensagem que colocamos ( caso não tenha tratado a exceção aparece a mensagem do Delphi). As classes fazem parte de uma hierarquia de exceções. Abra um espaço adicional à direita do 122 . vetor fora de faixa) EMathError (erros de matemática real) EOverflow (transbordo de real) EUnderflow (valor muito peq. O nome da classe de exceção é uma informação importante quando você fizer o tratamento da exceção no programa. transbordo de valor (EOverflow) ou qualquer outra. por isso que atribuimos o valor da data ao objeto 'tblClienteDataNasc'. o Delphi mostra uma mensagem mais detalhada sobre cada exceção e mostra exatamente qual a linha que causou a exceção. cadastrando um data inválida para a data de nascimento'. como 'EMathError'.

Com isso. eles deveriam estar ordenados por nome. Para isso basta mudar a sua propriedade ReadOnly para True. alterando a propriedade Options. selecione todos os campos menos Nome e altere a propriedade Visible para False. Se preciso. Não vamos permitir que o usuário altere os dados usando o grid. Para isso. se a tabela estiver ativa. Para facilitar a pesquisa. com o texto "Procura:" e um componente Edit (não use um DBEdit). Expanda essa propriedade no Object Inspector e altere as seguintes opções: Opção Valor Finalidade dgEditing False não permite incluir ou excluir dgTitles False desativa os títulos dgIndicator False desativa o indicador de registro dgColLines False desativa as linhas verticais dgRowLines False desativa as linhas horizontais dgTabs False não usa [Tab] para mudar de campo dgAlwaysShowSelection True sempre mostra a linha selecionada Se a opção 'dgAlwaysShowSelection' estiver desativada. Nota: existem duas opções parecidas: dgAlwaysShowEditor e dgAlwaysShowSelection. Execute o programa e verifique.formulário e acrescente um componente Label. O formulário deve ficar como o seguinte: Agora associe a grade (DBGrid) com a tabela. reduza o DisplayWidth para que o valor do campo apareça todo no Grid. Vamos restringir os campos mostrados apenas ao campo "Nome". aumente a largura do Object Inspector. o grid só mostra qual a linha selecionada (a do registro atual) quando ele tem o foco de teclado. Utilizando um Índice Secundário Mas há um problema: a grade mostra os dados ordenados pelo índice principal da tabela. que no caso é o índice no campo CodCliente. Algumas características de visualização do DBGrid não são necessárias aqui. Abaixo deles acrescente um componente DBGrid (ícone da página Data Controls). ou usar o DBNavigator para percorrer os registros. alterando sua propriedade DataSource para 'dsCliente'. Nós devemos ativá-la para que o usuário saiba qual o nome selecionado na lista a qualquer momento. como as linhas divisórias de registros e campos. com o nome de "editProcura". Vamos desativar essas características. Você pode clicar na grade a qualquer momento para selecionar um dos registros. ele vai automaticamente mostrar todos os campos e todos os registros da tabela. ou os títulos da parte de cima. clique duas vezes em 'tblCliente' para abrir o editor de campos. Para visualizar melhor as opções. 123 .

Esse método procura um valor na tabela utilizando o índice atual. abra um espaço na parte inferior do formulário. precisamos usar o índice criado para o campo Nome. Nota: quando você clica num ícone da paleta de componentes e depois em cima de um componente. Pesquisando pelo Nome Os controles acima do DBGrid serão usados para permitir pesquisa na tabela pelo nome do cliente. um quadro de edição e um botão. Clique na propriedade IndexName e selecione o nome "IndNome" da lista. aquele que você criou fica contido no primeiro. Se você apagar o valor de IndexName. você poderia colocar "Nome" em IndexFieldNames e teria o mesmo efeito. Quando você digita um nome em 'editProcura'. coloque em IndexFieldNames os nomes de campos separados por ponto-e-vírgula ". Esse é o nome do índice secundário criado. Como vamos pesquisar por um campo diferente.FindNearest([editProcura. a ordem dos registros será determinada pelo índice primário da tabela. Execute e verifique o resultado. crie um label. que é usado para agrupar visualmente outros componentes. Neste procedimento.Para mudar a ordem dos registros. Nota: se o índice tiver mais de um campo. Para ordenar por nome. devemos alterar a propriedade IndexName do componente dinamicamente. Isto é útil se você não souber o nome do índice. como veremos. Para isso. vamos posicionar a tabela no nome mais próximo. a propriedade Text deixe vazia e o nome do botão para 'btnProcCodigo' e altere a propriedade caption para "Procurar". Se o valor não for encontrado exatamente. Vamos colocar nesse espaço um componente GroupBox. que também tem um índice definido (o índice primário da tabela). basta alterar a propriedade IndexName do componente Table. que tem a mesma função. podemos usar um índice diferente. do GroupBox na página standard e coloque-o no formulário. Esse evento é executado toda vez que o usuário altera o valor do controle. Coloque na Selecione o ícone sua propriedade Caption o texto "Procura por código". a outra terá seu valor eliminado. end. Pesquisando pelo Código Agora vamos dar ao usuário a opção de procurar um registro pelo valor do campo código. como na figura abaixo: Mude o Caption do label para "Código:". Isso pode ser evitado com o 124 . No procedimento basta colocar o seguinte: begin tblCliente. existe outra chamada IndexFieldNames. e depois retorná-la ao original. Isso gera um pequeno problema — ao alterar essa propriedade. a ordem volta a ser a do campo CodCliente. que é o necessário. Por exemplo. Note como a ordem dos registros é alterada no controle DBGrid. isto é. vamos usar o valor digitado para pesquisar na tabela. usando o método FindKey. Para isso.". Mude o Name do componente Edit para 'editProcCodigo' . Selecione o controle 'editProcura' e crie um procedimento para o evento OnChange. Se você colocar o nome de um índice secundário. Dentro do componente GroupBox. mas se souber quais os campos que fazem parte dele. Agora clique duas vezes no botão Procurar. Essa propriedade afeta tanto a ordem virtual dos registros. A cada digitação do usuário. vamos usar o método FindNearest do componente Table. os controles do formulário vão mudar para refletir o novo índice. sem espaços. Para isso. O valor desta propriedade é a lista dos campos que compõem o índice. a ordem será de acordo com esse índice. As duas propriedades são mutuamente exclusivas: se você altera uma. Além da propriedade IndexName. Se ela estiver vazia. ele posiciona no registro mais próximo. Isso é chamado de busca incremental. digitando ou apagando caracteres. quanto as pesquisas que você fizer.Text]). restrito à área do componente e os dois são movimentados em conjunto. o valor mais próximo é selecionado.

125 . Blocos Protegidos Os tratamentos de erros no Delphi podem ser feitos para uma exceção específica. with tblCliente do try DisableControls. {usando índice por Nome} EnableControls. os controles de dados podem ficar num estado desabilitado.método DisableControls do componente Table. coloque o seguinte no código do procedimento: var codigo: integer. pois se esse tipo de tratamento não for feito. os controles de dados não atualizam mais seus valores até que o método EnableControls seja chamado. Quando ele é chamado. No procedimento de evento do OnClick observe que a alteração de IndexName e a chamada de EnableControls são feitas no bloco finally. o programa vai tentar procurar o registro. O finally é utilizado quando uma determinada exceção ocorre . Se você digitar um código e clicar no botão Procurar.. ele posiciona no registro. Esses comandos devem ser colocados no trecho finally. begin codigo := StrToInt(editProcCodigo. e necessitamos executar de qualquer forma um determinado comando ou vários comandos antes de interromper o procedimento. não é necessário tratar um exceção específica . Isso significa que mesmo que aconteça uma exceção. e o usuário não conseguiria mais utilizar o programa. Execute e verifique o resultado. end. senão mantém posicionado no registro atual. mas é preciso realizar uma ação de finalização. Em geral . O método FindKey é uma função que retorna True se encontrou o registro. end. Isso é importante. esses comandos são executados. Com isso. blocos protegidos podem ser usados em qualquer situação que envolva uma alocação e liberação de recursos(como um arquivo .end. Caso ele encontre. IndexName := ''. por exemplo). {usando índice primário} if not FindKey([codigo]) then ShowMessage('Codigo não encontrado'). As vezes .Text). finally IndexName := 'IndNome'.

Capítulo 15 Acesso s/ Controle de Dados Estados de uma Tabela Métodos para Percorrer Dados Métodos para Modificar Dados Eventos dos Componentes de Dados Manipulação de Datas Exemplo: Criando Formulário sem Utilizar o dbNavigator Tratamento do Erro "Key Violation" Usando um Controle DBLookupComboBox 126 .

Quando ela está no estado de visualização (dsBrowse). mas você não pode alterar os valores de campos. mas o registro ainda não foi salvo. você deve colocar a tabela em estado de edição (dsEdit) e depois alterar o valor dos componentes TField. · Visualização (dsBrowse): a tabela está aberta. clicando no botão Quando a tabela está no estado inativo. a tabela retorna ao estado de visualização. você não pode acessar os dados. É preciso entender estes diferentes estados para poder utilizá-lo. você pode percorrer os registros da tabela e ler os valores de campos. Depois que você salva o registro. O componente entra nesse estado quando o usuário clica no do DBNavigator. retornando ao estado de visualização. Os principais são: · Inativo (dsInactive): a tabela está fechada. botão · Editando (dsEdit): foi iniciada a edição de um registro existente.Estados de uma Tabela Dependendo da situação. 127 . e o usuário está visualizando ou percorrendo registros. A propriedade State (acessível somente em tempo de execução) tem valores diferentes dependendo do estado. Para alterar os valores dos campos de um registro. · Inserindo (dsInsert): foi iniciada a inclusão de um novo registro. um componente Table pode estar em vários estados diferentes. mas esse registro ainda não foi salvo no banco de dados. o do DBNavigator. e você pode atribuir valores para eles. A propriedade Active é True. utilizando os componentes TField. Depois você deve salvar os dados. todos os componentes TField ficam com o valor em branco (nulo). usuário deve iniciar a edição explicitamente. O componente entra nesse estado quando o usuário começa a alterar um campo. Quando a propriedade AutoEdit do componente DataSource é False (o padrão é True). Quando você inicia a inclusão de um registro.

Repare que cada um deles. o DBNavigator apenas chama os métodos correspondentes do componente Table. que tem o mesmo tipo de dados do campo. Com isso. ambas do tipo boolean. que retornam o valor do campo convertido para um determinado tipo de dados. para especificar qual o tipo de dados que você está acessando. O método Close equivale a alterar a propriedade Active para False. First Prior Next Last N/A MoveBy ( n ) Volta para o registro anterior. Lembre-se que a ordem em que os registros aparecem quando você percorre seqüencialmente é a ordem determinada pelo índice que estiver sendo utilizado no momento. o índice utilizado é o índice primário. Avança 'n' registros. quant := tblItem. por exemplo: tblCliente. mais o nome do campo. que é formado pelo nome do componente Table. Avança para o próximo registro. Para ler os campos do registro atual. move para trás. os componentes TField são criados internamente e não têm nome. existem duas propriedades úteis. mas isso pode ser alterado. Na verdade. cada um deles tem um nome. que utiliza controles de dados. Da mesma forma. independemente dos controles de dados. Se você usou o editor de campos para criar uma lista de componentes TField.AsInteger. Se 'n' for negativo. é equivalente a um botão correspondente do controle DBNavigator. exceto MoveBy. mas ainda podem ser acessados com o método FieldByName: preco := tblItem. Mas se você não criou uma lista de campos. Depois utilize o método Open. então você pode usar Value.Close. Métodos para Percorrer Registros Os seguintes métodos podem ser usados para percorrer registros: Botão Método Descrição Posiciona no primeiro registro. Após terminar de utilizar a tabela. As propriedades AsFloat e AsInteger são necessárias nesse caso. existem outras propriedades "As*". existem duas formas.Value. em resposta ao clique do usuário. quant := tblItemQuantidade.AsFloat. basta acessar a propriedade Value do componente TField: preco := tblItemPrecoVenda. Você não pode atribuir valores para a propriedade Value ou As* do componente se você estiver em modo de percorrer registros. como AsString. Quando você está percorrendo a tabela. move para frente.FieldByName('Quantidade'). o Delphi já sabe o tipo de campo pela declaração. Métodos de Abertura e Fechamento Para abrir a tabela e poder acessar os seus dados. A propriedade EOF é verdadeira quando você estiver posicionado no fim da tabela. tblCliente. você pode usar o método Close para liberar a tabela e o componente Table para outros usos. Se o componente Table estiver ligado a um componente DataSource. o resultado dos métodos vai aparecer na tela. Se 'n' for positivo. O método Open equivale a alterar a propriedade Active para True.Open.Métodos para Percorrer Dados O componente Table tem vários métodos que permitem você acessar a tabela utilizada. Quando a tabela é aberta. No caso de um componente criado explicitamente. seja em tempo de projeto ou no código do programa. 128 . Posiciona no último registro. primeiro defina as propriedades DatabaseName e TableName do componente Table.Value. AsDate.FieldByName('PrecoVenda').

com o texto 'Totalizar' e nome 'btnTotalizar'. while not EOF do begin total := total + tblItemQuantidade. Next. with tblItem do begin Open. Esse programa vai percorrer toda a tabela e totalizar a quantidade de itens vendiddos. Depois First posiciona no primeiro registro. Clique duas vezes no botão Totalizar e digite o seguinte: var total: double. por exemplo 'Quantidade'. { vai para o primeiro registro } while not EOF do begin preco := tblItemPrecoVenda. editTotal. Repare que se você clicar em um nome de campo. não tem nenhum registro: if tblItem. Por exemplo. Dentro do with. Já BOF é verdadeira quando você estiver posicionado no início da tabela. com o nome 'editTotal'. que irá mostrar o resultado final. .Value .BOF and tblItem. porque logo depois de abrir a tabela. o registro atual já é o primeiro.. Altere a propriedade Caption do formulário para 'Totalizar Itens'.Text := FloatToStr(total). end. Close. First.DB) através de comandos de programa. begin total := 0. Se ambas forem verdadeiras. no qual vamos percorrer a tabela de itens (ITEM.DB'. Next. 129 . para percorrer a tabela do início ao fim. Acrescente todos os campos à lista. DatabaseName será 'CursoDelphi'. Crie controles no formulário como na figura: Coloque um label. quant := tblItemQuantidade. Essa chamada não é realmente necessária. a tabela está vazia.EOF then ShowMessage('A tabela está vazia'). Coloque no formulário um componente Table ( ) e defina as seguintes propriedades: Name será 'tblItem'. Esse é o nome que você deve utilizar no programa para acessar o valor do campo.Value. usando os métodos do componente Table. Finalmente coloque um botão.Value. end. Isso não seria necessário se a propriedade Active já tivesse o valor True no início da execução. o alias que diz onde estão os dados e TableName será 'ITEM. { vai para o próximo registro } end. a primeira linha chama o método Open para abrir a tabela.depois do último registro. end. Exemplo: Percorrendo a Tabela de Itens Crie um novo projeto no Delphi. com o texto "Total:" e um controle de edição.. end. with tblItem do begin First. você verá que a propriedade Name do objeto de campo é tblItemQuantidade. Clique duas vezes no 'tblItem' para abrir o editor de campos.

Execute o programa e clique no botão Totalizar para ver o resultado. acumulado em 'total'. e finalmente o resultado final. Para cada registro.DPR. o campo Quantidade é somado com à variável 'total'. Salve o projeto como TOTALITEM. Depois do laço.PAS E TOTALITEMP.O laço while verifica o valor da propriedade EOF. o método Close fecha a tabela (faz Active = False). usando sua propriedade Value. o laço percorre os registros. é mostrado no controle 'editTotal'. Depois de somar o valor. Note a forma de acesso aos campos: com os nomes dos objetos TField. 130 . o método Next muda para o próximo registro. Enquanto ela for falsa (not EOF).

e vai se tornar o registro atual. Quando você tentar travar o registro.FieldByName('Quantidade'). ele cancela a edição para não gravar um registro desnecessariamente.Post. o que discutiremos sobre Insert se aplica igualmente a Append. ele deve primeiro clicar no botão do DBNavigator. Quando múltiplos usuários acessam a mesma tabela.Edit. chame o método Post. de forma mais abreviada. seja no mesmo computador ou em outro computador na rede. Quando você chama Insert. coma já vimos. ele automaticamente salva o registro antes da movimentação.. porque geralmente o usuário pode iniciar a edição simplesmente alterando um controle de dados. Depois você deve preencher os campos desse registro com os seus valores. As alterações não serão gravadas até que você chame o método Post. Assim. usando os objetos TField. que normalmente é True. que já tem o tipo de dados correto. você deve chamar o método Insert ou Append. o usuário não pode editar os controles de dados e para poder modificar o registro. Se você tiver alterado. Essa exceção pode ser tratada usando um comando try.. . end. de forma que nenhum usuário consegue editá-lo (mais ainda pode fazer a leitura). Acrescentando Registros Para incluir um novo registro na tabela. Quando AutoEdit é False.. Quando você usa o controle DBNavigator. tblItem. Se a tabela não tem índice primário. por exemplo). você pode chamar o método Cancel em vez de Post.. Nesse caso. {outras alterações} Post. Ou. Edit tem uma função mais importante: ele trava [lock] o registro. usando o with: with tblItem do begin Edit. Depois que você chama o método Post.except. o componente vai verificar se você alterou algum campo. O novo registro será o registro atual da tabela. Insert insere um novo registro no meio da tabela e Append acrescenta o novo registro ao final. Mas isso depende da propriedade AutoEdit do componente DataSource. = Cancel. o registro é gravado e liberado. Para uma tabela que tem chave primária. Após chamar o método Edit. . é melhor atribuir um valor para a propriedade Value. FieldByName('Quantidade').AsString := quantidade. Por exemplo: codigo := 20. o que automaticamente chama o método Edit. alguns botões dele chamam automaticamente esses =Edit. Se depois de chamar Edit. 131 . se você tiver usado o editor de campos para criá-los explicitamente. Para isso você deve chamar o método Edit do componente Table. Se você mudar de registro após o Edit. {outras alterações} tblItem. = Post. usando o método Next por exemplo. Se não foi feita alteração. Para gravar os dados. Ele apenas cria um novo registro vazio em memória. métodos: O botão Edit geralmente não é necessário.Métodos para Modificar Dados Editando Registros Para alterar os campos do registro atual. A posição do registro na tabela será determinada pelo valor da sua chave primária. Por exemplo: tblItem. Esse método libera o registro e cancela todas as alterações feitas nos componentes TField. altere os valores dos campos. e outro usuário já está editando.AsString := quantidade. ele não grava dados na tabela. você resolver cancelar as alterações no registro (devido a uma exceção. usando os objetos TField. os dois métodos fazem exatamente a mesma coisa: o registro será inserido na posição determinada pela chave. Edit vai gerar uma exceção EDBEngineError. você deve colocar a tabela em modo de edição. Você pode usar também os componentes TField..

Se você quiser cancelar a inserção do novo registro. finally EnableControls. e mudar de registro. que chama esse método automaticamente. end. end. por exemplo. Note também que se acontecer uma exceção depois de desabilitar os controles. tblItemPrecoVenda. tblItemQuantidade. Essa atualização dos controles geralmente é desnecessário. Depois ele preenche os campos e clica no botão . Excluindo Registros Para excluir o registro atual. Quando você usa o controle DBGrid. Quando você cancela. A operação de exclusão é executada imediatamente e não pode ser desfeita. while not EOF do . Se você não lembrar de habilitar os controles de dados.with tblItem do begin Insert. tblItemCodItem. o controle mostra uma mensagem de confirmação predefinida.Value := quant.finally: try DisableControls. eles ficam inutilizáveis pelo usuário. 132 . inclusão. Se você mudar de registro após chamar Insert. que chama Quando você usa o controle DBNavigator. caso você tenha deixado o registro inteiro em branco.Value := codigo.Value := preco. e vai gravar o novo registro. while not EOF do . Outros Métodos Quando você trabalha com os métodos do componente Table. e toma um certo tempo. senão exclui o registro imediatamente. use o método Cancel. end. que chama o método Cancel. EnableControls. Registros excluídos não podem ser recuperados. Se ela estiver verdadeira (valor True). o usuário pode clicar no botão .. use um comando try. todos os controles de dados ficam "congelados" com seus valores atuais.. com o método DisableControls e depois habilitar novamente a atualização com o método EnableControls. tornando muito demorada uma operação com vários registros. ou cancelar a inclusão. o componente vai verificar se você alterou algum campo... Por exemplo: with tblItem do begin DisableControls. o usuário pode pressionar a tecla [Insert] para chamar o método Insert.. Esses dois controles têm uma propriedade ConfirmDelete. . o efeito dos métodos (edição. preencher os campos. a posição de registro volta ao registro onde você estava posicionado antes de chamar Insert. ou no botão . ou movimentação) aparece imediatamente nos controles de dados (se houver). o usuário pode pressionar [Ctrl+Delete] para excluir o registro atual.Delete. Para evitar essa última situação. o usuário pode clicar no botão automaticamente o método Insert da tabela. o Delphi vai sair do procedimento e eles não serão habilitados novamente. Post. Você pode desabilitar temporariamente a atualização dos controles. caso tenha havido alteração. que chama o método Post. Usando o controle DBNavigator. Usando o controle DBGrid. Quando você chama EnableControls. use o método Delete: tblItem.

Para obter os registros mais atualizados da tabela.. seja numa execução normal. Esse método é chamado automaticamente pelo botão do DBNavigator.finally garante que a parte do finally é sempre executada. os registros que estão sendo visualizados podem ficar desatualizados à medida que outros usuários adicionam novos registros. você pode usar o método Refresh: tblCliente.Um comando try. Numa rede.Refresh. Nesse caso. isso garante que os controles de dados são habilitados novamente. ou quando ocorre uma exceção no bloco do try. 133 .

de qualquer movimentação de registro na tabela. você pode manipular a tabela de forma genérica. antes do evento AfterInsert. Nesse evento você pode. AfterClose: antes e depois da tabela ser fechada (método Close). Insert. AfterPost: antes e depois do registro ser gravado. Last. preencher o campo chave da tabela com um valor gerado pelo programa. evitando uma mensagem do Delphi. · BeforeOpen. que acontecem respectivamente antes e depois da execução do método. ou qualquer outro evento. · BeforeClose. FindKey. você pode mostrar sua própria mensagem de confirmação de exclusão. evitando a gravação se necessário. Ou seja. Eventos do Componente Table Para cada método do componente Table (Edit. · OnNewRecord: acontece depois da inclusão de um novo registro. Se você fizer alguma alteração de campos em AfterInsert. AfterEdit: antes e depois do início da edição de um registro. Next. por isso é melhor usar OnNewRecord. AfterScroll: antes e depois. No evento BeforeDelete. sem especificar o nome exato do componente. FindNearest. · BeforePost. AfterOpen : antes e depois da tabela ser aberta (ativada). Usando o parâmetro 'DataSet'. gerando uma exceção. é o melhor lugar para se fazer uma validação de registro.Eventos dos Componentes de Dados Os componentes de dados têm vários eventos que são acionados em momentos específicos. no momento em que é necessário obter o valor desses campos. Cada um desses eventos tem um cabeçalho como o seguinte: procedure TForm1.Table1BeforePost(DataSet: TDataset). existem eventos "Before" e "After". acontece quando você tem campos calculados.). Esses eventos são acionados nas seguintes situações: · BeforeScroll. · BeforeCancel. como já vimos. um parâmetro do tipo 'TDataset'. etc. · BeforeDelete. provocada por um dos métodos de movimentação First. No evento "Before". 134 . você pode cancelar a execução do método atual. respectivamente. · BeforeInsert. O evento BeforePost. AfterCancel: antes e depois do cancelamento de uma edição ou inclusão (método Cancel). Prior. etc. TDataset é uma classe que é ancestral da classe TTable e de outros objetos de acesso a dados. o registro será considerado modificado. AfterDelete: antes e depois de um registro ser excluído. Post. o evento OnCalcFields. por exemplo. AfterInsert: antes e depois do início da inclusão de um registro. como já vimos. MoveBy. · BeforeEdit. Além desses.

que depende da configuração do Windows. segundos. Se o dia é de 1 a 9. mm O mês como um número.Value).. yyyy O ano com quatro dígitos. em alguns bancos de dados. usando FormatDateTime. mmmm O nome do mês completo. mes.. No segundo argumento de FormatDateTime. Ele usa o tipo de dados TDateTime para esse formato codificado. h. ou do tipo Time (apenas horas). hh As horas. você tem semelhantemente as rotinas EncodeTime e DecodeTime. Se é de 0 a 9.7=sábado} 135 . usando DateToStr. "hh" acrescenta um zero à esquerda. ou DateTimeToStr: editData.. Você pode converter uma string em data/hora. data := EncodeDate( ano.. e o procedimento DecodeDate para obter os componentes da data separados (dia. que de forma genérica. TimeToStr. Por exemplo: var data: TDateTime. . ss Os segundos. É importante também saber nesse caso as funções disponíveis para manipulação de datas. s. mm Os minutos.. Se é de 0 a 9. Se é de 0 a 9. Você pode fazer operações com as datas codificadas. mes. ddd O dia da semana abreviado. . "mm" acrescenta um zero à esquerda. ano. "dd" acrescenta um zero à esquerda. StrToTime e StrToDateTime. mmm O nome do mês abreviado. segundos. minutos. Para saber o dia da semana. mês e ano). dd O dia do mês. ou subtrair duas datas para saber a quantidade de dias entre elas. m. completo. "mm" acrescenta um zero à esquerda. {1=domingo. usando as funções de conversão StrToDate. DecodeTime( varHora. ou campos Date/Time ou Timestamp (guarda data e hora). Você também pode converter uma data/hora para sua representação textual. que representam uma contagem de dias desde 1/1/0001. para tratá-la como uma string. dia ).. minutos. horas. yy O ano com dois dígitos. Para tratamento de horas. Mas você pode também usar outros formatos. você pode usar os marcadores de posição (entre outros): Marcador Insere d.Caption := TimeToStr(Now).. "mm" acrescenta um zero à esquerda. begin . Se o mês é de 1 a 9. end.. dddd O nome do dia da semana. por exemplo: texto := FormatDateTime(data. Essas funções convertem a data usando o formato padrão. somar um número a uma data. Esses mesmos marcadores podem ser usados com a propriedade DisplayFormat de um campo do tipo data ou hora. / O separador de datas (pode não ser uma barra). DecodeDate( data. milisegs ).. milisegs ).. são usadas assim: varHora := EncodeTime( horas. como por exemplo. m. você pode usar a função DayOfWeek: diaSemana := DayOfWeek(data). em campos do tipo Date (apenas datas). 'dd/mm/yyyy'). dia ).Manipulação de Datas O Delphi permite armazenar datas e horas no banco de dados.. labelRelogio.. Você pode usar a função EncodeDate para gerar esse valor codificado.Text := DateToStr(tblClienteDataNasc. O Delphi codifica datas e horas internamente como números. : O separador de horas (pode não ser o dois-pontos). .

Date retorna apenas a data e Time retorna apenas a hora. você tem funções para consultar a data/hora atuais do computador: Now retorna a data e hora atuais codificadas. 136 .Finalmente.Text := DateToStr(Date). Por exemplo. faça: editData. para mostrar a data de hoje em um controle de edição.

BMP Glyph Excluir Hint Coloque seu formulário como a figura abaixo: 137 .BMP Glyph Inclui Hint SpeedButton2 spbAlterar Name FILEOPEN.Exemplo: Criando formulário sem utilizar o dbNavigator Neste exemplo iremos criar o cadastro de fornecedores.BMP Glyph Primeiro Hint SpeedButton6 spbAnterior Name ARROW3L. Crie um novo formulário.BMP Glyph Salvar Hint SpeedButton4 spbCancelar Name IGNORE.BMP Glyph Anterior Hint SpeedButton7 spbProximo Name ARROW3R. Acrescente 9 componentes SpeedButton ( e altere as propriedades a seguir. altere seu nome para 'formCadFornecedor'. Caption coloque 'Cadastro de Fornecedores'. sem utilizar o componente dbNavigator . as figuras são encontradas no direito do Delphi 'BORLAND SHARED\IMAGES\BUTTONS' : SpeedButton1 spbIncluir Name FILENEW.BMP Glyph Cancelar Hint SpeedButton5 spbPrimeiro Name VCRREWND.BMP Glyph Alterar Hint SpeedButton3 spbSalvar Name FLOPPY.BMP Glyph Próximo Hint SpeedButton8 spbUltimo Name VCRFSFOR. fazendo uma simulação do dbNavigator.BMP Glyph Último Hint SpeedButton9 spbExcluir Name TRASH. na propriedade ). iremos utilizar Botões e tratar o evento de cada um .

edit 138 .PAS'. vamos abrir o componente tblFornecedor . crie um procedimento para este evento e coloque: tblFornecedor. begin tblFornecedor. para abrir o editor de campos. Organize seu formulário de acordo com a figura abaixo: Salve a unit como 'CADFORNCEDOR. O método Insert do componente Table. inclui um registro em branco. No procedimento do evento OnClick do botão spbAlterar colocar: procedure TformCadFornecedor. No procedimento do evento OnClick do botão spbIncluir colocar: procedure TformCadFornecedor.spbIncluirClick(Sender: TObject).insert end. defina suas propriedades como: Table Name: tblFornecedor DatabaseName: CursoDelphi TableName: Fornecedor DataSource Name: dsFornecedor DataSet: tblFornecedor Clique duas vezes no componente tblFornecedor.Coloque um componente Table e um DataSource no formulário. begin tblFornecedor. em seguida adicione os objetos de campos e arraste-os para o formulário. No evento OnShow do formulario.Open Para que o formulário funcione é necessário acrescentar em cada Botão .spbAlterarClick(Sender: TObject). um procedimento para o evento OnClick.

Antes de excluir o registro será mostrado uma mensagem perguntando se deseja excluir o fornecedor.spbExcluirClick(Sender: TObject).spbCancelarClick(Sender: TObject).spbProximoClick(Sender: TObject).cancel end. em seguida foi aplicado algum méodo de movimentação na tabela . O método Edit que permite fazer alterações. O método Post.delete end. antes da movimentação.as alterações serão confirmadas.first end.spbUltimoClick(Sender: TObject).prior end. se o componente Table não estiver no modo de Alteração ou 139 . O método First movimenta para o primeiro registro.spbAnteriorClick(Sender: TObject). No procedimento do evento OnClick do botão spbPrimeiro colocar: procedure TformCadFornecedor. begin if application.spbprimeiroClick(Sender: TObject). No procedimento do evento OnClick do botão spbExcluir colocar: procedure TformCadFornecedor. Neste exemplo mostramos somente o que cada método faz. Notas: Se foi feita alguma alteração no registro atual . MB_ICONQUESTION + MB_YESNO) = idyes then tblFornecedor. begin tblFornecedor. No procedimento do evento OnClick do botão spbUltimo colocar: procedure TformCadFornecedor. No procedimento do evento OnClick do botão spbSalvar colocar: procedure TformCadFornecedor. O método Delete exclui o registro atual. O método Previous movimenta para o registro anterior. 'Confirmação'.next end. cancela as alterações feitas nos campos da tabela. O método Last movimenta para o último registro. begin tblFornecedor.last end.end. begin tblFornecedor. begin tblFornecedor. No procedimento do evento OnClick do botão spbAnterior colocar: procedure TformCadFornecedor. O método Cancel.post end.messagebox('Deseja excluir o fornecedor?'. O método Next movimenta para o próximo registro. begin tblFornecedor. não foi realizado nenhum controle de desativar o botão Salvar .spbSalvarClick(Sender: TObject). begin tblFornecedor. No procedimento do evento OnClick do botão spbCancelar colocar: procedure TformCadFornecedor. mas essas alterações podem ser confirmadas ou não. confirma as alterações feitas nos campos da tabela. No procedimento do evento OnClick do botão spbIncluir colocar: procedure TformCadFornecedor.

no procedimento de evento. No controle DBLookupComboBox. tente cadastrar fornecedores que tenham o mesmo código. Agora tecle [F12] para voltar ao formulário. mude o nome para 'cboFornecedor'. no formulário de produtos.Inclusão . portanto. Além dessas propriedades. Vamos utilizar outro controle que é o DBLookupComboBox ( ) da página Data Controls.. É necessário abortar o procedimento. para que a mensagem em inglês não aparece. Para isso. gera o evento OnPostError. para que a condição utilizada seja verdadeira. na Unit 'VENDPRIN. Para testar cadastre alguns fornecedores . a mensagem que esta verificando é case sensitive.' then begin showmessage('Fornecedor Cadastrado!'). Esse controle tem a capacidade de gravar valores em uma tabela e mostrar uma lista de valores de outra. esses controles podem ser feitos com a propriedade Enabled de cada componente SpeedButton. 140 . outras propriedades determinam de onde o controle busca a lista de valores a ser mostrada.a propriedade message desta classe . Usando um Controle DBLookupComboBox Quando o usuário cadastra um produto.message = 'Key violation. que deve corresponder a um valor válido na outra tabela. Altere o Caption do rótulo para "Fornecedor". Quando ocorre algum erro durante a execução desse método. Você pode facilitar a entrada desse campo para o usuário permitindo a ele selecionar o fornecedor a partir de um lista de nomes. então podemos criar um procedimento para este evento que irá mostrar a mensagem que desejamos. Clique no item de menu Cadastro|Fornecedor e. Essas propriedades. Vamos alterar também as seguintes propriedades: DataSource para 'dsProduto'. quando o nosso programa executa o método Post. como para qualquer controle de dados. Tratamento do Erro 'Key violation. podemos mostrar a nossa própria mensagem de erro. Esse é um processo sujeito a erros e torna difícil validar o valor que o usuário digita (para validar. logo após a seção implementation acrescente: Uses CadCliente. O parâmetro 'E' contém o erro que ocorreu durante a gravação dos dados. ele precisa digitar o código do fornecedor. Para mostrar uma mensagem de erro mais clara para o usuário . precisamos criar novos componentes de dados no formulário. seria necessário pesquisar na tabela de fornecedores). contém a mensagem do erro. tem que ser escrita idêntica ao conteúdo da propriedade Vamos associar este formulário ao formulário principal. Notas: Ao verificar uma mensagem com a propriedade message.. Mas antes de alterar essas propriedades. dizem quais os dados que o controle vai acessar..' Este erro ocorre quando estamos incluíndo um registro . Este parâmetro é da classe EDataBaseError. e DataField para 'CodFornecedor'. coloque o seguinte comando: formCadFornecedor. CadFornecedor. ou seja. end.Neste procedimento coloque os comandos abaixo: if e. Coloque um controle DBLookupComboBox no formulário ao lado do rótulo "CodFornecedor". os mesmos valores do DBEdit anterior. e o valor informado para a chave primária já existe. ..show Salve o projeto e execute . faça alterações. Este erro ocorre quando o usuário confirma as informações que foram colocadas. ou seja.. apague o controle DBEdit que está sendo usado para o campo "CodFarnecedor".PAS'.. abort. por isso utilizamos o método Abort.

coloque os nomes dos campos. Se você quiser mostrar o código também. vão aparecer os dois campos: nome e código. Agora execute o programa. Finalmente ListField determina qual o campo que será mostrado na lista. você pode alterar a propriedade ListField para incluir mais de um campo. Quando a lista está fechada. que acessam a tabela FORNECEDOR. os dados serão lidos desta tabela." (sem espaço entre os nomes e o ponto-e-vírgula). coloque "Nome.Open. Para isso.Open. O valor de KeyField (CodFornecedor. nesse caso. Agora volte para o formulário de produtos (FormCadProduto) e tecle [Ctrl+V]. mas quando você abre a lista.CodFornecedor" em ListField e execute o programa. separados por ". Repare que você pode selecionar o fornecedor pelo nome agora. 141 . Nome. selecione o componente 'tblFornecedor' e o componente 'dsFornecedor' e tecle [Ctrl+C] para copiá-los. aparece apenas o nome do fornecedor. Isso vai colocar no formulário duas cópias dos componentes. tblFornecedor.DB. que corresponde ao campo DataField na tabela PRODUTO. Isso é necessário para fornecer os valores mostrados por 'cboFornecedor'. Acrescente o seguinte no procedimento do evento OnCreate do formulário: begin tblProduto. Como 'dsFornecedor' está ligado à tabela FORNECEDOR. além do nome. altere as seguintes propriedades: Propriedade Valor dsFornecedor ListSource CodFornecedor KeyField Nome ListField A propriedade ListSource determina qual a tabela que será usada para buscar os valores a serem mostrados. end. na tabela FORNECEDOR.No formulário de fabricantes (FormCadFornecedor). Retornando ao componente 'cboFornecedor'. nesse caso) é o nome do campo. No nosso caso. 'tblFornecedor' nesse formulário. Falta um detalhe: você deve ativar a tabela de fornecedores.

Capítulo 16 Utilizando Mestre/Detalhe Criando um Formulário Mestre/Detalhe Usando Três Tabelas no Formulário 142 .

Na lista da direita. todos estariam na lista). Selecione o campo. Selecione o índice "CodCliente".. basta você informar as tabelas e quais os campos relacionados. aparecem os campos da tabela mestre. Por último. A lista dos índices disponíveis aparece abaixo de "Index Name". Na próxima tela. A tela do DFW ficará como a seguinte: Isso define o seguinte relacionamento entre as tabelas: 143 . No Delphi. Agora você deve selecionar a tabela detalhe. onde uma tabela tem um registro que se relaciona com vários registros de outra. Usando o DFW para criar o formulário O Database Form Wizard pode criar automaticamente um formulário mestre/detalhe. este componente permite visualizar vários registros ao mesmo tempo.. Selecione a tabela VENDA. Esse formulário será criado no projeto VENDA. selecione a segunda opção. o Database Form Wizard vai perguntar quais os campos que compõem o relacionamento entre as tabelas.DPR . escolha um layout horizontal para o formulário. Na primeira tela. Na próxima tela. Agora. A tabela Cliente será a tabela mestre e a tabela Venda será a tabela detalhe. em vez de controles de dados separados.. Primeiro clique na lista "Drive or Alias name" e selecione "CursoDelphi". portanto ele tem que estar aberto. o nome de alias que for criado anteriormente.. na lista de tabelas. Agora. Na próxima tela. No nosso caso. isto é chamado de relacionamento mestre/detalhe [master/detail]. Depois selecione apenas os campos CodCliente e Nome (clique no campo e no botão ">"). criada anteriormente. aparece o campo "CodCliente" (se o índice tivesse mais de um campo. "CodCliente". A tabela detalhe deve ter um índice definido para o campo que faz o relacionamento. na lista da esquerda. "Create a master/detail form" e clique em Next.DB e clique em Next.Criando um Formulário Mestre/Detalhe Uma situação muito comum na utilização de bancos de dados é o relacionamento entre duas tabelas. um cliente possui vários registros de venda relacionados (1-N). como detalhe.DB. Isso vai colocar um controle DBGrid na parte "detalhe" do formulário. que foi criado quando colocamos a restrição de integridade . e na outra tela adicione todos os campos (clique no campo e no botão ">>"). usaremos a tabela Cliente como mestre e a tabela Venda. você deve escolher a tabela mestre. escolha CLIENTE. No nosso caso. no primeiro grupo de opções. No menu Database|Form Wizard. A tabela detalhe é aquela que tem vários registros relacionados. A tabela mestre é aquela que tem um único registro fazendo parte do relacionamento. Selecione o campo que tem o mesmo nome. escolha o layout "Grid".

como na figura: O primeiro 'Table1'. Vamos alterar os nomes desses componentes de dados. Os dois controles DBEdit da parte superior do formulário estão ligados ao DataSource1 e o controle DBGrid da parte inferior está ligado ao DataSource2.Agora clique em Next e depois no botão "Finish". nesse caso. Como antes.DB. A propriedade MasterFields diz qual o campo (ou campos. Mude os nomes para os seguintes: Além das ligações que já vimos. os outros dois acessam a tabela de vendas: Table2. Na parte "detalhe" do formulário (o controle DBGrid da parte inferior). através da propriedade DataSet. através da propriedade TableName. e nesse caso é "CodCliente". A propriedade IndexFieldNames. que define o relacionamento com o cliente. Analisando o Formulário Vejamos exatamente como é definido o relacionamento mestre/detalhe pelo DFW. Testando o Formulário Gerado Execute o programa. e nesse caso tem o mesmo nome. num formulário mestre/detalhe. Se você alterar esse campo manualmente. só que desta vez existem dois componentes Table e dois DataSource. Após entrar com alguns dados. ele é preenchido automaticamente de acordo com o valor do código do cliente atual. aparece no Grid. Quando você começa a incluir um registro. Note que o campo "CodCliente". 144 . o registro vai desaparecer da lista. é preciso relacionar as duas tabelas. pois vai estar relacionado com outro cliente. O formulário será adicionado com as opções definidas.DataSet é Table2. Isso define qual tabela será a mestre para essa tabela. De forma análoga. Selecione o componente 'tblVenda' e veja que a propriedade MasterSource está ligada com 'dsCliente'. se mais de um) na tabela mestre.DB" e DataSource2. O 'DataSource1' está ligado com 'Table1'. que faz o relacionamento. "CodCliente" (mas não é obrigatório que tenha o mesmo nome). são utilizados os componentes Table e DataSource. inicialmente nenhum cliente tem registros associados. todos no topo do formulário. para facilitar o entendimento. ao lado do DBNavigator. define qual o campo (ou campos) na tabela detalhe. que faz o relacionamento com o outro. e veja como funciona o relacionamento mestre/detalhe. está associado com a tabela CLIENTE. Se você usar o DBNavigator do topo do formulário para mudar de registro na tabela mestre. Isso é feito com propriedades que ligam 'tblVenda' (antes Table2) a 'dsCliente' (antes DataSource1). os registros de detalhe que aparecem embaixo serão diferentes. você pode adicionar registros que estarão automaticamente relacionados com o registro de cliente que aparece na parte superior.TableName tem o valor "VENDA. Como a tabela Venda não continha dados. finalize a execução.

alguns botões do DBNavigator. senão o Delphi não vai conseguir manter o relacionamento.Open" e "Table2. tblVenda. o Delphi guarda internamente um ponteiro de objeto. para "Código". Mas você pode proibir esse tipo de alteração. Alterando Propriedades do Formulário Vamos alterar algumas características desse formulário. Altere para False os elementos nbInsert (afeta o botão ). Execute o programa e verifique que agora não é possível editar os campos da tabela de clientes.Open. nbEdit ( ). nbPost ( ) e nbCancel ( ). Você deve clicar na borda mais espessa e não no fundo do painel. Não remova da lista. 145 . que foi criado pelo Database Form Wizard. porque você alterou os nomes dos componentes Table. Essa é uma propriedade de conjunto que determina quais botões são visíveis. Com isso. Se quiser. Selecione o controle e a propriedade VisibleButtons. inclusão ou exclusão de registros. Selecione o campo CodCliente. independente do nome. mas ele sempre terá o mesmo valor que o campo CodCliente da parte superior. Notas: Os comandos existente no procedimento de evento OnCreate serão executados no momente que o formulário for criado. reduza o tamanho do painel que contém os controles de edição para a tabela de clientes. No DBGrid da parte inferior. Altere também o label "CodCliente". são para abrir as duas tabelas em tempo de execução.Nota: O valor que aparece na propriedade DataSet é o nome do outro componente. Ao executar observe que ele permite alterar registros da tabela mestre. mas para propriedades de ligação.Open. como . "Table1. o campo 'CodCliente' está disponível para visualização e edição.Open". Altere o Caption do formulário para "Clientes e Vendas" e a propriedade Name para formCadCliVend . Por isso vamos removê-los do DBNavigator. Para tornar o campo invisível. estarão sempre desabilitados e não têm mais função. clique duas vezes no componente 'tblVenda' para abrir o editor de campos. Cada um deles corresponde a um botão do DBNavigator. A forma mais simples de fazer isso é alterar a propriedade ReadOnly de 'tblCliente' para o valor True. apenas adicionar e remover registros de vendas relacionados. Clique duas vezes no nome da propriedade para expandir os elementos do conjunto. Os dois comandos. end. Eles não funcionarão mais. que fazem alterações na tabela. Tente executar o programa — o Delphi vai mostrar um erro de compilação dentro do procedimento de evento 'FormCreate' . no caso a tabela de clientes. Salvando o Projeto Salve esse projeto como CADCLIVEND. seja edição. Apenas altere sua propriedade Visible para False. nbDelete ( ). e . portanto vamos torná-lo invisível. Isso proíbe qualquer forma de alteração na tabela. Substitua pelo seguinte: begin tblCliente. . .

Em "Available indexes". TableName com o nome da tabela "ITEM. aumente o formulário na vertical para aumentar essa área. para que ele ( ocupe o espaço do painel e BorderStyle para 'bsNone'. altere as seguintes propriedades: Name para 'tblItem'. Clique no grid de vendas e tecle [Esc] para selecionar seu painel. Deve aparecer uma caixa de diálogo. Isso vai deixar um espaço vazio na parte inferior do formulário. Ambas definem os nomes dos campos que participam do relacionamento. e MasterFields contém "CodVenda" também. que contém informações sobre cada item individual vendido. Coloque um componente na parte inferior. No evento Oncreate do formulário coloque tblitem.DPR. Mude o seu nome para 'dsItem' e na propriedade DataSet. Esse é um Panel. Nós precisamos alterar o formulário de clientes e vendas. "CursoDelphi" e. Altere suas propriedades da seguinte forma: Propriedade Valor Efeito (vazio) tira o texto "Panel2" Caption bvLowered efeito 3-d interno "afundado" BevelInner aumenta a borda BorderWidth 4 alClient preenche o espaço disponível Align Agora. Coloque-o em cima do painel. Para cada registro de venda. Se preciso. selecione o índice "IndVenda". Depois clique em Ok. Nas listas abaixo. que alinhava o painel de acordo com o espaço disponível no formulário. bem semelhante ao que aparece no Database Form Wizard.open. Altere sua propriedade Align para 'alclient'. Algumas situações exigem tratar um relacionamento mestre à detalhe à detalhe. selecione 'tblItem' para ligá-lo com o último componente Table. altere a propriedade MasterSource. O valor anterior era 'alClient'. Agora clique na propriedade MasterFields e no botão de reticências. Ligando os Componentes de Dados Abra o projeto anterior. Para isso é preciso criar manualmente os relacionamentos. DatabaseName com o nome do alias. Criando Controles de Dados Vamos ampliar o formulário para incluir um grid para a tabela de itens. VENDA. Isso define qual a tabela mestre para esta. Primeiro adicione ao formulário mais um componente Table e mais um DataSource. haverá vários registros de item de venda. Altere sua propriedade Align para 'alTop'. controle cuja finalidade geralmente é só a de conter outros controles. Agora vamos relacionar a tabela de vendas com a tabela de itens vendidos (ITEM). onde você pode facilmente definir o relacionamento. Agora selecione o componente DataSource que você colocou por último. selecione a página Data Controls na paleta de componentes e selecione o DBGrid ). Para o componente Table. selecionando da lista o 'dsVenda'. se ele já não estiver aberto no Delphi.DB" (note que a lista de valores de TableName mostra as três tabelas). Mas antes de fazer isso. com três tabelas. selecione o campo "CodVenda" em cada uma e clique no botão Add. Para fazer esse relacionamento. que é o último ícone. para remover a borda preta em volta 146 . precisamos alterar propriedades do painel que contém o grid da parte inferior. relacionados através do campo "CodVenda". Clique no quadrado de seleção inferior e arraste-o para reduzir o tamanho vertical do painel. ou dois relacionamentos mestre/detalhe no mesmo formulário.Usando Três Tabelas no Formulário Com o Database Form Wizard só é possível criar um formulário mestre/detalhe para no máximo duas tabelas. alterando as propriedades MasterSource e MasterFields do componente Table. Para manter a aparência do formulário. Isso vai alterar automaticamente a propriedade IndexFieldNames para conter "CodVenda". selecione a página Standard e o componente .

No nosso caso. portanto. Para o componente Table. utilizamos o método FindKey para posicionarmos no produto que estamos querendo o preço. leia ou altere sua propriedade Value.Para adicionar os objetos de campos clique em "Add.. O valor de um campo calculado é definido pelo código do seu programa. e mostrará o nome do produto. Digite "PrecoTotal". clique duas vezes no componente 'tblItem'.FindKey([tblitemCodProduto. se necessário. Ao invés de ficar mostrando o código do produto . end. você pode atribuir valores para campos calculados. selecione o componente 'tblItem' e clique duas vezes para abrir o editor de campos. Esses nomes podem ser alterados.. campos calculados. altere as seguintes propriedades: Name para 'tblProduto'. O tipo dessa propriedade depende do tipo de dados do campo." em seguida clique no botão 'Ok'.Um campo Lookup traz dados de uma outra tabela relacionada. clique com o botão direito e em "New Field. Para realizar o calculo do Preço Total é necessário ter o preço de venda do produto. Para definir um novo campo calculado. 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. E o objeto de campo "PrecoTotal" será o valor da quantidade vendida multiplicada pelo preço de venda do produto. que estarão associados com a tabela "Produto. TableName com o nome da tabela "PRODUTO. que aparecem da mesma forma que campos do registro.. O nome do componente TField é criado automaticamente como "tblItemPrecoTotal".. como 'tblItemPrecoTotal'. Digite o seguinte: begin if tblproduto.Value := tblItemQuantidade. como "tblItemCodVenda" etc. a grade vai mostrar os dados da tabela de itens e permitir alteração. Clique duas vezes no componente 'tblProduto'. Você deve também escolher um tipo de dados para o campo. Criando Campos Calculados Usando um componente Table. vamos criar um campo Lookup. mas este será mostrado o campo nome da tabela produto. selecionando o componente na lista e alterando sua propriedade Name. Adicione todos os campos. que deve ser multiplicado pela quantidade de itens vendidos. Para ler ou alterar o valor de um componente TField. Todos os componentes TField têm nomes baseados no nome do componente Table ao qual eles pertencem. para isto temos que criar um outro campo LooKup. Para definir o valor de um campo calculado no programa.". ele aciona o evento OnCalcFields do componente Table.value]) then tblItemPrecoTotal.Value. Usando um campo Lookup Para mostrar o nome do produto . 147 . Você deve definir um nome para o campo. selecione 'CodVenda' na lista e altere a propriedade Visible para False. DatabaseName com o nome do alias. para abrir o editor de campos. No formulário. "CursoDelphi" e. vamos criar um novo campo PrecoTotal contendo esse resultado. Para isso. através do campo CodProduto. Como o Preco de Venda do produto está na tabela produto é necessário obter o valor desta tabela.Value * tblProdutoPrecoVenda. a tabela de itens terá um campo calculado. precisamos saber o nome dos componentes utilizados. além dos campos da tabela. mas você pode mudar se precisar. Durante a sua execução. Para que o campo 'CodVenda' não apareça na grade. mas sem permitir alteração.DB". Neste caso. portanto vamos acrescentar um componente Table e um DataSource. para abrir o editor de campos. iremos também mostrar o nome do produto. Escolha "FloatField" na lista (tipo real) e clique Ok. O preço de venda do item é um preço unitário. Quando o Delphi precisa mostrar um campo calculado.db". o campo irá buscar um registro na tabela de produto.do controle. Com isso. você pode mostrar. Altere também DataSource para 'dsItem'.

.Para inserir um campo Lookup.show end. em "Type" selecione "string". em "LooKup Keys". que é a tabela de onde será buscado os dados.Esse é o campo que será usado para buscar o produto na outra tabela. em "Size" informe 50.". Para isso . begin formCadCliVend. selecione "codproduto" este é o campo que será utilizado para fazer o relacionamente da tabela produto com a tabela item e em "Result Field" coloque nome (o campo de resultado que será mostrado). Agora em "Key Fields". Finalmente . Em "Name". selecione "CodProduto" . clique duas vezes em 'tblItem' para abrir o editor de campos. Marque a opção "Lookup". acrescente o seguinte código ao evento Onclick do item de menu Cadastro|Vendas: procedure TformPrincipal. retorne ao formPrincipal. é preciso mostrar esse formulário a .menuCadVendasClick(Sender: TObject).. As propriedades estarão como abaixo: Arraste o campo LookUp 'NomeProduto' . para a primeira posição e o campo 'PrecoTotal' coloque-o na última posição. selecione "tblProduto". Clique com o botão direito e selecione "New Field. Em "DataSet". partir do menu principal. como na figura abaixo: Testando e Salvando o Projeto Para que o usuário possa acessar o formulário de vendas . especifique "NomeProduto". Você pode usar o botão Agora. 148 .

cancelamos também as alterações da tabela item .findkey([tblItemCodProduto. Antes de atualizar o campo 'QtdEstoque' .value := tblprodutoqtdEstoque. Quando o procedimento OnBeforePost é abortado o evento OnAfterPost não ocorre. e acrescente o código a seguir: procedure TformCadCliVend. abort.value .value]) then begin showmessage('Produto não encontrado!'). mesmo os que não afetam seu valor. O método FindKey foi utilizado para verificar se o produto incluído existe.Para funcionar. iremos atualizar a tabela de produto. abort.tblItemQuantidade.value. então cancelamos a alteração feito na tabela produto(está alteração ocorre somente se o campo 'quantidade' da tabela item esta sendo alterado) . if tblitemquantidade.edit. com isso pode ser feito alterações em qualquer campo desta tabela .FocusControl. Na verdade. Em seguida é feito uma verificação se o valor que esta sendo vendido é maior que o estoque existente. os campos LooKup PrecoVenda e Nome vão aparecer para cada registro. no início da seção de implementação (implementation) do formulário.value > tblprodutoqtdEstoque. o campo alterado é 'Quantidade' ( pois é o único campo que iremos permitir alteração) . esse evento é executado para qualquer alteração de campo.value := tblprodutoqtdEstoque. caso esteja . é necessário verificar se a tabela 'Item' esta sendo alterada.State in [dsEdit] then tblProdutoqtdEstoque. Note que no grid da tabela Item. se isso ocorrer não podemos permitir a venda do item. if tblitem. end. end. Então antes de salvar os dados na tabela de item. caso ela esteja em modo de edição e em seguida abortamos o procedimento. Adicione o seguinte: uses CadCliVend Agora execute o programa para ver o efeito das modificações. portanto. crie um procedimento para este evento na tabela 'tblItem'. portanto. tblproduto. if tblItem.State in [dsEdit] then tblItem. tblProduto. tblproduto. tblItemQuantidade. Finalize a execução e salve o projeto novamente. PrecoVenda ou o Produto.Cancel. o evento OnCalcFields será executado. end else tblProdutoqtdEstoque. Se você alterar os campos Quantidade .post. a venda não será efetuada. O evento que ocorre antes de gravar um determinado registro é o evento OnBeforePost. Caso não tenha ocorrido nenhum dos problemas citados 149 .tblItemBeforePost(DataSet: TDataSet).value + QuantidadeAnterior. Atualizando Quantidade em Estoque Ao realizar uma venda de um determinado produto. para depois retirar a quantidade desejada. é necessário atualizar a quantidade disponível em estoque. begin if not tblproduto. O método Edit foi utilizado para colocar a tabela 'Produto' em modo de Alteração . o campo calculado PrecoTotal .cancel. temos que adicionar o valor antigo ao estoque .value then begin showMessage('Quantidade Insuficiente no Estoque!'). caso não exista irá aparecer uma mensagem e o procedimento será abortado. o valor antigo foi armazendo na variável QuantidadeAnterior. e o valor do campo será alterado. você precisa adicionar uma cláusula uses.

Para atualizar o estoque estamos considerando que o único campo que possa ser alterado da tabela 'Item' é o campo 'Quantidade'. tblitem. abaixo da seção implementation acrescente: Var QuantidadeAnterior : integer. end end. Quando o item for excluído . no 'Object Inspector '. end. begin if tblItem. Não iremos aceitar modificação no campo 'codproduto' da tabela 'item'. com isso irá abrir o editor de código.value + tblItemQuantidade.value := tblprodutoqtdEstoque. vamos criar um procedimento no evento OnChange do objeto 'tblItemQuantidade'. no evento OnBeforeDelete (antes de excluir) .tblItemBeforeEdit(DataSet: TDataSet). temos que acrescentar a quantidade que foi retirada ao estoque. portanto. tblproduto. 150 .value]) then begin tblproduto. end. para criar este procedimento clique duas vezes na tabela 'Item'. Neste procedimento é realizado uma procura do produto pertencente ao item .findkey([tblItemCodProduto.value.tblItemCodProdutoChange(Sender: TField). será adicionado ao campo 'qtdEstoque' a quantidade do item excluído. crie um procedimento para o evento OnBeforeEdit.anteriormente. begin Quantidadeanterior := tblItemQuantidade.state in [dsEdit] then begin showmessage('Não é permitido a alteração do produto!'). acrescente o código a seguir: procedure TformCadCliVend. abort.value. para fazer a alteração do produto é necessário excluir o item de venda e incluir novamente. coloque o procedimento abaixo: procedure TformCadCliVend. tblProdutoqtdEstoque.edit. em OnChange.tblItemBeforeDelete(DataSet: TDataSet). escolha o campo 'Quantidade'. end. caso o produto seja encontrado .post. begin if tblproduto. Falta criar a variável 'QuantidadeAnterior' e atribuir um valor. neste procedimento coloque: procedure TformCadCliVend.cancel. clique na página 'Events'. Essa variável irá conter o valor do campo 'Quantidade' antes de ser modificado. este evento ocorre antes de fazer modificações nas tabelas. finalmente podemos subtrair a quantidade vendida pela quantidade existente no estoque.

Capítulo 17 Consultas e SQL Exemplo: Usando Consultas Exemplo: Consultando Várias Tabelas Outros Comandos SQL Consultas num Ambiente Cliente/Servidor Métodos e Eventos do Componente Query 151 .

respectivamente. selecione a tabela VENDA. Note que o 'DataSource1' tem na propriedade Dataset o valor 'Query1'. no início da seção implementation do formulário VendPrin. Essa propriedade é uma lista de strings (TStrings). na lista do select (Venda. venda. na lista "Drive or alias". por exemplo). venda..DB. Clique em SQL e no botão com reticências. 152 . Altere a propriedade Name do formulário para 'formConsVendasporCliente' e a propriedade Caption para 'Vendas por Cliente". Salve o formulário criado como "CONSVENDASCLIENTE. mas ele utiliza um componente Query em vez de um Table. Clique OK para fechar o editor de strings. mantenha a opção "Create a simple form" na parte superior. Ele pode ser usado em situações onde uma tabela não seria suficiente. Primeiro são especificados os campos da tabela que serão retornados pelo select."CodCliente". O formulário gerado é semelhante aos que já criamos com o DFW. em vez de todos os registros (isso é fundamental para ter bom desempenho num ambiente cliente/servidor) · Reunir dados de múltiplas tabelas (junções) · Totalizações de dados de vários registros A forma mais fácil de usar um componente Query é usar o Database Form Expert para criar um formulário. A propriedade mais importante do componente Query é a propriedade SQL.DRP e acione o menu Database |Form Wizard. Na primeira tela do DFW. Na lista de tabelas. que é utilizado anteriormente. Os componentes de dados estão no topo do formulário: Query1 DataSource1 Selecione o componente 'Query1' e veja suas propriedades. Para o usuário poder visualizar esse fomulário temos que chamá-lo no evento Onclick do menu Consultas|Vendas por Cliente da Unit VendPrin. incluindo subdiretório. Depois altere também o código do evento OnCreate do formulário. adicione o seguinte: uses ConsVendasCliente."CodCliente".show. Nesse caso. Neste evento coloque o código abaixo: formConsVendasporCliente."DataVenda" From "c:\cursodelphi\venda. Vamos alterar os nomes dos componentes para 'qryVenda' e 'dsVenda'. Execute o programa e veja o resultado: você pode percorrer os registros da tabela. Para isso funcionar. Na última tela."CodVenda". para abrir 'qryVenda' em vez de 'Query1'. por exemplo: · Acessar um subconjunto da tabela..DB" As venda O comando select é um comando SQL que consulta registros. Clique em Next. vem o nome da tabela. A expressão "as Venda" cria um apelido para a tabela dentro do comando. Depois do from.Query é usado para obter dados baseados em um comando SQL. você precisa adicionar uma cláusula uses . mas não pode alterá-los. Repare que o conteúdo da propriedade é o seguinte: Select venda. depois selecione todos os campos e escolha o layout "In a grid".PAS". Isso faz a ligação entre os dois. Na próxima tela. é um nome completo. Criando o Formulário Abra o projeto VENDAS. mas na parte de baixo selecione "Create a form using TQuery objects". selecione CursoDelphi. que contém um comando da linguagem SQL.Exemplo: Usando Consultas O componente .. desmarque a opção "Generate a main form" e clique em Finish.

Agora selecione a propriedade Params e abra o seu editor. Execute o programa e veja o resultado. caso seja um valor numérico especifique somente o número. '08/02/98'. que permite acessar a tabela como através de um componente Table. que retorna os dados. Altere o SQL para o seguinte: select * from Venda where DataVenda = :ValorData Isso cria um parâmetro chamado 'valorData'. Você pode fazer também uma consulta dinâmica. Simplificando o Select O comando select. clique Ok.Obtendo um Resultado Modificável Uma consulta geralmente retorna um resultado que não é modificável. Um parâmetro é uma variável dentro do comando SQL. e alterar a condição em tempo de execução. você pode verificar se a consulta é modificável. Para fazer isso. Note que se você alterar o valor do campo DataVenda. Para isso. vamos alterar a propriedade SQL novamente. que vai aparecer. Execute o programa e repare que ele continua funcionando como antes. Quando esta propriedade é verdadeira. e salvar o registro. vamos alterar a propriedade SQL para incluir um parâmetro no lugar da constante '08/02/98'. altere a propriedade RequestLive do componente Query para True. e podemos evitar que o diretório da tabela seja codificado de forma fixa. porque está usando um valor constante. Abra novamente a propriedade SQL e substitua todas as linhas do comando pelo seguinte: select * from Venda Você pode colocar os comandos na mesma linha. ou em linhas separadas. Alterando a Consulta Uma consulta que retorna todos os registros não é realmente muito utilizada. primeiro deve-se escolher o parâmetro e ir no object inspector: 153 . O "*" (asterisco) no select em vez de uma lista de campos seleciona todos os campos da tabela. Mas você pode pedir ao Delphi para retornar um conjunto de registros modificável ["live" result set]. Quando o tipo do campo for data ou Caracter a condição deve ser passada entre apóstrofos. A principal função de consultas é restringir os registros retornados a um subconjunto dos dados. Alterando a Consulta Dinamicamente A consulta como está é uma consulta estática. Nota: Não deve haver nenhum espaço entre o dois-pontos e o nome do parâmetro. que você pode alterar dinamicamente. o componente vai tentar retornar um conjunto de registros modificável. Observe que a data deve ser informada como 'mm/dd/yy' . Execute o programa e agora você deve ser capaz de fazer alterações nos registros. Em tempo de execução. Note que não é preciso colocar a extensão de arquivo (. Nota: na sintaxe do SQL.DB) e é melhor não colocar porque isso torna mais fácil alterar o programa para trabalhar com outros formatos de dados (onde tabelas não são arquivos). a condição de seleção de registros nunca muda. para inserir um texto. é onde você define qual o tipo de dados a ser usado pelo parâmetro. independentemente da estrutura dessa tabela. pode ser simplificado. Depois de fazer essa alteração. e apenas esses registros. ou seja. consultando sua propriedade CanModify (do tipo boolean). registros apenas para leitura. o registro vai desaparecer do resultado. acrescentando uma cláusula where ao final: select * from Venda where DataVenda = '08/02/98' Isso vai retornar todos os registros onde o campo DataVenda tenha o valor '02/08/98'. você pode usar " (aspas) ou ' (apóstrofos). ou seja. Para fazer isso. O que define o parâmetro são os dois-pontos antes do nome. O editor de parâmetros. mas nem sempre isso é possível.

que será o tipo de dados do campo . Altere sua propriedade Caption para "Parâmetros". Precisamos de uma interface para alterar o parâmetro dinamicamente. nos parâmetros as datas são do tipo date e ao passar para a linguagem SQL o Delphi coloca no formato que o SQL utiliza. em Standard. que significa que ele começa com o valor nulo. ao confirmar o Object Inspector ira ficar como a figura abaixo: Notas: Nos parâmetros colocamos as datas sendo 'dd/mm/yy'. selecione o ícone do GroupBox ( qualquer espaço vazio. seu funcionamento é idêntico ao Edit a diferença é que ele componente MaskEdit ( permite utilizar máscaras. substitua os '0' por '9'. ou vazio. clique na reticências da propriedade EditMask e escolha a opção "Date". Nesse caso digite "02/08/98" e depois clique Ok. Em "Value" você pode. pois. Acrescente um componente Button e um Label . ou marcar a opção "Null Value". Altere a propriedade Name para mskDataVenda. em seguida clique em "Ok". com uso definimos uma máscara para o componente de edição.Expande a propriedade Value em type escolha "Date". dentro dele acrescente o ) . Na página ) e coloque um controle no formulário. Agora crie controles dentro do GroupBox "Parâmetros". conforme a figura abaixo: 154 . fornecer um valor inicial para o parâmetro. opcionalmente.

Por exemplo. Alterando Outras Partes da Consulta Os parâmetros permitem que você substitua constantes dentro da consulta por variáveis do programa. except on EConvertError do begin showmessage('Data Inválida!'). se a pessoa informar uma data inválida iremos mostrar a mensagem de erro 'Data Inválida'. alterar os parâmetros.Chame o botão de 'btnAlterar' e mude a sua propriedade Default para True. AsInteger. end..Text). No código associado ao 'btnAlterar'. Nota: Outra forma de alterar o parâmetro é usando a função-método ParamByName. com índices começando de zero. end. Essa propriedade é uma string list. pois. end.AsDate := strtodate(mskDataVenda. mskDataVenda.Text). . A propriedade Params do componente Query é um vetor de objetos do tipo TParam. o código abaixo também acessa o parâmetro valorData: ParamByName('valorDAta'). e abrir a consulta novamente com os parâmetros modificados. que pode ser utilizada com os 155 . mas se você precisar alterar a estrutura da consulta. Cada um desses objetos tem propriedades como AsString. Como é feito uma conversão de String para Date. foi feito o tratamento de exceção .AsDate := strtodate(mskDataVenda. Open. end. precisa alterar a propriedade SQL em tempo de execução..setfocus. Params[0]. Execute o programa e veja o que acontece quando você altera os parâmetros. que permitem alterar o valor do parâmetro. Com isso o usuário pode realizar a consulta para qualquer data. Digite o seguinte: begin try with qryvenda do begin Close. fornecendo o nome do parâmetro em vez de sua posição na lista.

a consulta irá mostrar os clientes que pertencem ao intervalo de estados pedidos.CodCliente na cláusula where é importante numa junção de tabelas.CodVenda from CLIENTE cli. para isto temos que alterar a propridade SQL do componente QryVenda . a consulta vai funcionar. mas como o objeto ainda existe. Coloque a propriedade Active do componente qryVenda para true.DB").SQL do begin Clear. com a alteração foi retirado o campo. todas as combinações possíveis com o registro de uma e o registro da outra tabela. A lista de campos do select seleciona o campo Nome da tabela 'cli' (apelido de "CLIENTE.CodCliente order by cli.Nome Notas: Quando o comando Select utiliza mais de uma tabela. e na maioria das vezes isso não é necessário. vend. A condição cli. Consulta com Duas Tabelas Como no exemplo anterior realizamos uma consulta que mostra as vendas e os códigos dos clientes. Como queremos mostrar o nome do cliente temos que utilizar a tabela 'cliente' na clausula from da consulta. ou seja.DB") e o campo CodVenda da tabela 'vend' (apelido de "VENDA. Add('or Estado = "' + estado2 + '"'). foi criado um objeto de campo para o código do cliente . 156 . podemos usar um comando select do SQL envolvendo várias tabelas. para resolver o problema clique duas vezes no componente 'qryVenda' para abrir o objeto de campo.CodCliente = vend. os nomes das tabelas estão seguidos de nomes mais curtos. Com isso irá aparecer a seguinte mensagem: Isso ocorre porque antes de fazer a modificação na propriedade SQL . chamado de junção de tabelas. remove todos os objetos de campos existentes. Ela diz qual a ligação entre elas.Nome. mas vai retornar o produto cartesiano das duas tabelas. A cláusula order by determina que o resultado será ordenado pelo campo Nome da tabela CLIENTE. VENDA vend where cli. vamos mostrar o nome do cliente. Esses apelidos afetam apenas o comando atual. imagine que precisamos fazer o seguinte: consultar todos os itens vendidos para cada cliente para uma data específica. end. Add('select * from Cliente'). O exemplo abaixo mostra como mudar a propriedade SQL dinamicamente : with qryCliente.métodos de string lists já vistos. Não faremos isso neste projeto. Add('where Estado = "' + estado1 + '"'). Ao abrir o componente QryCliente . Exemplo: Consultando Várias Tabelas Tendo os nossos dados sobre clientes.CodCliente = vend.DB.Altere a propriedade SQL de acordo o comando abaixo: select cli. vendas e itens. Se não for especificada. Ele continua procurando o campo 'codcliente'. Para isso. Note que na cláusula from. o componente Query não permite alterações dos dados. que são os apelidos [alias] utilizados para as tabelas dentro do SQL.

Altere a propridade Active para true e observe que cada registro do resultado tem o valor do campo Nome e do campo CodVenda. Existem vários registros de resultado para cada cliente, ou seja, com o nome do cliente repetido, mas com códigos de venda diferentes.

Consultando Três Tabelas
Para adicionar mais uma tabela na consulta, a tabela de itens de venda, vamos alterar o select, acrescentando o nome da tabela e a condição de ligação. Desta vez vamos obter no resultado apenas o campo Nome da tabela de clientes e o campo Quantidade, da tabela de itens. Na propriedade SQL, digite o seguinte: select cli.Nome, item.Quantidade from CLIENTE cli, VENDA vend, ITEM where cli.CodCliente = vend.CodCliente and vend.CodVenda = item.CodVenda order by cli.Nome Repare que como são três tabelas, temos duas condições de junção, uma ligando CLIENTE a VENDA e outra ligando VENDA a ITEM Quando você altera a propriedade SQL, o componente automaticamente muda a propriedade Active para False, altere para True.

Usando Campos Calculados no SQL
Podemos ainda gerar um campo calculado para cada registro, que será mostrado no resultado. Uma forma de fazer isso é definindo campos calculados e usando o evento OnCalcFields. Mas quando se usa componentes Query, outra forma mais fácil é usar expressões no SQL. Por exemplo, vamos calcular para cada item, o preço de venda multiplicado pela quantidade, gerando um campo calculado 'PrecoTotal', mas o preço de venda existe na tabela produto, portanto iremos acrescentar também 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 expressão é colocado um "as PrecoTotal", que define um nome de campo para a expressão (senão no cabeçalho do campo vai aparecer a própria expressão). Altere Active para True novamente e veja o resultado.

Usando Funções de Resumo
Em vez de retornar registros com o nome do cliente repetido, como está sendo feito, você pode, usando SQL, agrupar vários registros, retornando um registro de resumo, contendo, por exemplo, o total de algum campo. Para isso, você deve usar a cláusula group by do SQL, além de funções de resumo do SQL. Por exemplo, para totalizar o produto de 'Quantidade' e 'PrecoVenda' para todos os itens relacionados a cada cliente, basta usar o seguinte comando: select cli.Nome, sum(item.Quantidade * prod.PrecoVenda) as TotalVenda from CLIENTE cli, VENDA vend, ITEM item, PRODUTO prod where cli.CodCliente = vend.CodCliente

157

and vend.CodVenda = item.CodVenda and prod.codproduto = item.codproduto and datavenda =:ValorData group by cli.Nome A função sum é uma função de resumo (ou função agregada) do SQL, que faz o somatório de um campo ou expressão. A cláusula group by define como são formados os grupos de registros para fazer a totalização. Outras funções de resumo que podem ser usadas em vez de sum são: avg(campo) calcula a média de um campo max(campo) calcula o valor máximo do campo min(campo) calcula o valor mínimo do campo count(campo) conta os valores do campo, mas só considera registros onde o campo está preenchido count(distinct conta quantos valores distintos do campo existem (em [4 2 2 4 2 3], a campo) contagem seria 3). count(*) conta os registros

Outros Comandos SQL
O comando select é um comando SQL de consulta, mas existem comandos SQL para atualização de tabelas, que permitem atualizar diversos registros. Esses comandos são utilizados também através de um componente Query, mas de uma forma ligeiramente diferente, como veremos.

Testando Comandos SQL
Para executar um comando SQL de atualização, como os que serão usados, você pode usar o Database Explorer. Clique em Database|Explore, no menu do Delphi. Na árvore "Databases", abra o alias "CursoDelphi". Ao fazer isso, do lado direito aparece um marcador de página "Enter SQL":

Clique em

(Execute Query) para executar o comando.

Alterando Registros
Para alterar valores de registros, use o comando update. Com ele, basta fornecer a tabela, a condição de atualização e as alterações de campos a serem feitas. Por exemplo, o comando a seguir atualiza a tabela Cliente, preenchendo o campo Estado, com o valor 'GO', mas apenas nos registros onde Estado era vazio (is null verifica se o campo está vazio): update Cliente

158

set Estado = 'GO' where Estado is null

Excluindo Registros
Para excluir um conjunto de registros baseado numa condição, use o comando delete. Por exemplo, o seguinte comando exclui todos os registros da tabela Venda, que estejam entre 01/01/94 e 01/01/95: delete from Venda where DataVenda >= '01/01/94' and DataVenda <= '01/01/95' ou, de forma equivalente: delete from Venda where DataVenda between '01/01/94' and '01/01/95'

Inserindo e Copiando Registros
Para inserir um registro em uma tabela, você pode usar o comando insert: insert into Produto (CodProduto, Nome, CodFabricante) values (1234, 'Novo Produto', 34) Mas geralmente essa forma não tem muita utilidade. Outra forma, que é de mais ajuda na programação, 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 têm a mesma estrutura. Se não tiverem, você pode alterar a lista de campos do select para incluir apenas os que estão presentes na tabela de destino, por exemplo: insert into ClienteCentroOeste select Codigo, Nome from Cliente where Estado in ('GO', 'TO')

Executando um Comando de Atualização
Para usar um comando SQL de atualização, coloque o comando na propriedade SQL de um componente Query. Mas existe uma diferença em relação ao select: um comando de atualização não retorna resultado nenhum. Por isso, você não deve abrir a consulta (alterando Active), e nem ligar o componente com um DataSource, por exemplo. Para executar o comando, você deve chamar o método ExecSQL do componente. Esse método não retorna resultado e só pode ser acionado em tempo de execução. Você pode também preencher parâmetros do componente antes de executar o comando. Por exemplo, suponha que você quer apagar todos os registros de VENDA.DB entre uma data inicial e uma data final. Você pode definir a propriedade SQL com o seguinte: delete from Venda where DataVenda between :dataIni and :dataFin e, no programa, executar o código a seguir quando for excluir os itens: with qryApagaItem do begin ParamByName('dataIni').AsString := editDataIni.Text; ParamByName('dataFin').AsString := editDataFin.Text; ExecSQL; end;

Consultas num Ambiente Cliente/Servidor
Num ambiente cliente/servidor, consultas são a forma mais eficiente de acesso aos dados. Nesse tipo de ambiente, uma consulta envia o comando SQL ao servidor, para ser processado localmente. O servidor então retorna apenas os registros pedidos. Se você utilizar um componente Table, você sempre estará acessando todos os registros, e isso traz as desvantagens que já vimos, de gerar tráfego de rede.

159

aliviando o processamento na estação.. OnCalcFields. DisableControls. Quando você usa comandos de atualização. · Métodos e propriedades de movimentação: First. OnNewRecord. como vimos nos exemplos. Note que se a consulta não retorna um resultado modificável. A vantagem é que o cálculo da expressão é feito no servidor. como ele não retorna resultados.Você pode também usar expressões em comandos SQL. Métodos e Eventos do Componente Query As classes de componentes TTable ( ) e TQuery ( ) são ambas derivadas de uma classe ancestral comum. Quase todos os métodos e eventos que vimos para o componente Table se aplicam também a um componente Query: · Métodos de abertura e fechamento: Open. que recebe apenas os resultados. 160 . chamada TDataSet. propriedade Fields.. Close. · Eventos: Before. que o processa localmente. Post. o tráfego entre a estação e o servidor é o mínimo possível. Insert. como update. Next. Prior.... · Métodos para os controles de dados: EnableControls. MoveBy. · Métodos e propriedades de acesso a campos: FieldByName. que vai fazer toda a operação de totalização e retornar os resultados. Nesse caso. Delete. e a propriedade CanModify terá o valor False.. Cancel. Last. After. Funções de resumo também repassam parte do processamento para o servidor. o comando é enviado ao servidor. não é possível utilizar esses métodos. · Métodos de modificação: Edit. propriedades BOF e EOF.

Capítulo 18 Instalador e Alias Local Usando um Alias Local Criando um Programa Instalador 161 .

e pode ser modificado durante a execução. como já vimos. Repare que "Alias name" e "Driver name" são mutuamente exclusivas. seu alias local será sinônimo para um alias já existente. 162 . enquanto ele está rodando. Um alias local funciona apenas dentro do seu programa. Depois. diz para manter a conexão com o banco de dados mesmo quando ele não estiver sendo usado. onde é necessário fornecer uma senha para conectar com o gerenciador de bancos de dados: "Login prompt". de acordo com os parâmetros de configuração do driver. Esse botão preenche a lista de parâmetros. No nosso caso. se ativo. como por exemplo. você pode usar um alias local. coloque um componente Database. digite "VENDAS". um programa que usa um diretório diferente a cada vez que é rodado. você deve escolher um driver de banco de dados em "Driver name" e alterar seus parâmetros de configuração em "Parameter overrides". A lista vai mostrar uma linha com o parâmetro PATH. em "Name".Usando um Alias Local Se você quisesse alterar o diretório dos dados em tempo de execução. coloque o diretório atual dos dados depois do parâmetro: PATH=C:\CURSODF\TABELAS Isso basta para definir o alias local. selecione "STANDARD" e clique no botão "Defaults". Esse componente tem várias propriedades. se ativado. só importa o parâmetro PATH. Mas um alias não pode ser criado dinamicamente pelo programa. sem valor definido: PATH= Na lista de parâmetros. Usando o Componente Database O componente Database da página Data Access ( ) permite criar um alias local. você digita o nome do alias local que você está criando. No caso do driver "STANDARD". Na lista "Driver name". mas a forma mais fácil de alterá-las é usando o Database Editor. Esse será o nome do nosso alias local. se você escolher um valor da lista "Alias name". Senão. e não resolve algumas situações. evitando que sejam necessárias alterações no programa. E "Keep inactive connection". Mude o seu nome para 'dbVendas'. Mas. um alias resolve esse problema: ele armazena a localização do diretório. Clique duas vezes no componente para chamar esse editor. A janela do Database Editor é semelhante à seguinte: Em "Name". No 'FormPrincipal'. Para esse tipo de situação. mostra uma janela que requisita o nome de usuário e senha para conexão. usado para bancos de dados locais. teria que alterar a propriedade DatabaseName de todos os componentes de dados. As outras opções só tem utilidade em bancos de dados cliente/servidor.

DriverName com o valor "STANDARD". VENDAS. Execute o programa e veja que ele continua funcionando. de acordo com o diretório onde está o programa executável. juntamente com os aliases globais. Selecione VENDAS na lista. desde que os arquivos de dados estejam no mesmo diretório do executável. para utilizar esse diretório. Salve o projeto novamente. end. o programa vai sempre encontrar os dados. que pode ser manipulada com os métodos já vistos para string lists. Agora no formulário de produtos. cap. Alterando o Caminho em Tempo de Execução A propriedade Params do componente 'dbVendas'. no formulário principal. vai aparecer na lista de valores.Connected := False. se você quiser alterar o diretório onde estão os dados. Com isso. LoginPrompt e KeepConnection com o valor True e Params (do tipo TStrings) com os parâmetros. assim como Active faz para uma tabela. porque o componente Table já faz isso automaticamente. begin diretorio := ExtractFilePath(Application.Params[0] := 'PATH=' + diretorio + 'tabelas\'. os códigos abaixo: var diretorio: string. No formulário principal. Mas a verdadeira utilidade deste componente é permitir alterar a localização dos dados em tempo de execução. por isso é alterada logo no início. ela deve estar com o valor False. para extrair apenas a parte do diretório. De agora em diante. basta alterar a propriedade Params do componente 'dbVendas' no formulário principal. Lembre-se: A propriedade Params é uma lista de strings (v. Alterando os Componentes de Dados Agora. Depois alteramos a primeira linha da propriedade Params. vamos alterar a propriedade DatabaseName de cada um dos componentes Table dos formulários do projeto. de 'dbVenda'. Note que o nome do alias (DatabaseName = "VENDAS") não é necessariamente igual ao nome do componente (Name = "dbVendas"). A propriedade Connected do componente Database "ativa" o banco de dados. O nome do alias local que foi criado. Faça o mesmo para todos os formulários e seus componentes Table ou Query. Quando o programa tenta abrir uma tabela que depende de um componente Database.EXEName). de acordo com as opções escolhidas: DatabaseName fica com o valor "VENDAS". como CursoDelphi. é preciso que ele esteja configurado com parâmetros válidos. no formulário de fabricantes. desde que os arquivos de dados estejam no mesmo diretório. selecione ambos os componentes 'tblProduto' e 'tblFabricante' e altere DatabaseName para VENDAS. É importante notar que o código acima é executado antes do código do OnCreate para os outros formulários. selecione o componente 'tblFabricante' e clique na propriedade DatabaseName. 163 .Clique Ok e repare que o Database Editor altera várias propriedades do componente Database. dbVendas. Vamos alterar o caminho do diretório dinamicamente. acrescente no procedimento do evento OnCreate. que contém o caminho completo do arquivo executável. geralmente é melhor alterá-la no início da execução. 12). em tempo de projeto. por isso pode ser acessada como um vetor onde o primeiro elemento tem o índice zero. Execute o programa e verifique que ele ainda continua funcionando. Essa é uma propriedade do tipo string list. dbVendas. contém uma lista de valores de parâmetros de configuração. Usamos essa propriedade com a função ExtractFilePath. Para começar. Não é normalmente necessário alterar essa propriedade manualmente. Mas num ambiente cliente/servidor. Para alterar os parâmetros. O objeto Application tem a propriedade EXEName.

Iniciando o InstallShield O InstallShield trabalha com projetos de instalação [setup projects]. Se você for copiar esse programa para outro usuário. Isso irá criar um novo subdiretório sob CURSODF. Esses disquetes contêm um programa de instalação (SETUP. como "típica".0 ". que são conjuntos de grupos [groups] a serem incluídos e cada grupo é um conjunto de arquivos que pode ser 164 .EXE. que muitas vezes ficam no menu . que permite escolher o nome do projeto de instalação e o local onde ele será salvo. no nosso projeto anterior (VENDAS. Finalize o Delphi. compactados para ocupar menos espaço. Você pode definir tipos de instalação [setup types]. os programas no Windows são executados através de atalhos. Em "Project Name". chamado VENDAS. Geralmente.EXE. nome do arquivo executável etc. O InstallShield criará um novo arquivo. usuário e cria um atalho no menu ]|Programas. para que o usuário não precise digitar o nome do executável. ele pode executar o programa de instalação. Na lista de diretórios. para criar programas instaladores. com as tarefas que você deve fazer para criar um programa instalador. clique em [ ]|Executar. digite "INSTVEND". • Especificar Componentes e Arquivos [specify components and files]: O InstallShield permite criar uma instalação com várias opções para o usuário. Em "New Subdirectory". No nosso caso. Por exemplo. no diretório C:\CURSODF\INSTVEND. digite "C:\CURSODF\VENDAS. sob o drive C:. "personalizada" que serão apresentados como escolha para o usuário.iwz. • Selecionar Objetos para o Delphi[Select InstallShield Objects for Delphi]: define se o programa usa ou não o BDE para acesso a banco de dados e. Agora você verá uma janela semelhante a um caderno de anotações. ao executar um projeto no Delphi.EXE" e clique Ok. não precisa do Delphi para executá-lo.EXE. "compacta". Finalmente clique no botão Create. Para o projeto Vendas. é preciso uma forma mais amigável de executar o programa. caso use. que copia VENDAS. e informações sobre as mensagens que serão mostradas durante a instalação. aparece uma tela com três opções: "Open an existing Setup Project" é usado para abrir um projeto de instalação feito anteriormente.. Criando um Instalador A criação de um instalador envolve diversas fases: • Definir o Projeto Visual [set the visual design]: nesta fase. Nota: o InstallShield não é instalado em conjunto com o Delphi. Isso irá executar o programa fora do Delphi. use "Create a new Setup Project" para criar um novo projeto de instalação. ele cria um programa executável. No Windows. para conter os arquivos do projeto de instalação. um arquivo que pode ser executado independentemente do Delphi. como nome descritivo. para poder executar VENDAS. você fornece informação básica ao InstallShield sobre sua aplicação. no ícone "IS Express Delphi Execute o InstallShield através do menu [ 4. Um programa instalador copia para o computador do usuário o seu arquivo executável e mais os arquivos que ele precisa utilizar.DPR). que criará disquetes de instalação para o programa. O Delphi (edições Professional e Client/Server) vem com um programa chamado InstallShield Express. digite "VENDAS". selecione CURSODF. "Open your last Setup Project" abre o último projeto de instalação usado (se houver). que contém a chamada checklist. mas precisa instalar alguns arquivos do BDE (quando se utiliza bancos de dados). iremos criar um projeto de instalação.Criando um programa instalador Como já foi dito. Um projeto de instalação é um arquivo contendo um conjunto de opções que definirão o conteúdo e funcionamento do seu instalador. No entanto. Você pode executá-lo diretamente no Windows. Você pode definir componentes [components]. o programa se chama VENDAS. Ele deve ser instalado separadamente a partir do diretório ISXPRESS do CD do Delphi. . quais são os drivers necessários que devem ser incluídos com o programa.. Ao executá-lo.EXE) e todos os arquivos necessários ao funcionamento do programa VENDAS. Agora você verá a janela New Project.EXE e os outros arquivos necessários para o computador do do Windows. Quando você fornece os disquetes de instalação a um usuário.

Opcionalmente. No "caderno" do InstallShield. aparece embaixo como: <ProgramFilesDir>\nome-empresa\Controle de Vendas O nome <ProgramFilesDir> é uma variável do InstallShield que será substituída no momento da instalação. • Especificar pastas e ícones [specify folders and icons]: define qual o nome da pasta no menu iniciar que será criada para o programa e quais os ícones que o programa criará no menu iniciar. O título muda para "BDE Alias Step 1 of 4". por exemplo). • Fazer Mudanças no Registro [make registry changes]: O Registro [registry] é o banco de dados central de configuração do Windows.DB. por isso você pode pular todos os passos. Procure o diretório C:\CURSODF e selecione VENDAS. com extensões . Note que o diretório de destino. abaixo de "InstallShield Objects for Delphi". mas não vamos alterar essa opção. Clique Ok.XG0. No nosso caso. VENDAS.incluido ou não na instalação. marque "Paradox driver". Agora clique em Ok para retornar à tela principal. Escolhendo as caixas de diálogo 165 . Não entraremos em detalhes sobre este tópico. Clique em Avançar três vezes. as tabelas usadas pelo programa. '. Depois clique [Avançar].DB. Como nosso programa utiliza apenas o formato de bancos de dados Paradox. não estamos usando apelidos externos ao programa. Você pode clicar na página "Main Window" para alterar o texto que aparece durante a instalação. Primeiro clique em "Application Information" para abrir a caixa de diálogo "App Info".EXE. '. o InstallShield já acrescentou o arquivo do programa.".0 e em "Company". Definindo as Opções de Instalação Vamos definir as opções para o instalador do Controle de Vendas. Você poderia escolher um logotipo também (uma imagem desenhada no MS Paint do Windows. informe "Controle de Vendas". clique no botão "Insert Files.Y??. à lista de arquivos a serem instalados. Quando tudo estiver pronto. Coloque também "Controle de Vendas". O mais importante é que nesta fase você pode acrescentar arquivos adicionais além do seu executável. digite o nome da sua empresa. Note que já contém o arquivo executável. com o nome do diretório de programas do usuário (geralmente "C:\Arquivos de Programas"). FABRIC. marque "SQL Engine".Y' (como CLIENTE. Agora vamos alterar as opções do BDE. .PX.DB. Selecione o diretório "CURSODF" para ver os arquivos que ele contém. Em "Version". Aparecerá uma outra janela para escolher o tipo de instalação. no nosso caso. em "Main Title". Isso vai abrir uma janela. você pode gerar os discos de distribuição. Em "Application Name".PX'. Aparece uma lista com a opção BDE (Borland Database Engine). Esse é o nome que aparece para o usuário. PRODUTO. clique Ok.. VENDA.EXE. ITEMVEND. FABRIC. deixe 1. Aparece uma árvore com os grupos de arquivos. clique em "Groups and Files". depois clique em Fim. Após colocar todos os arquivos na lista e conferir. mostrando os diretórios do drive C:. você pode gerar os discos com o Disk Builder. Nesta fase.EXE nesse diretório.DB e todos os arquivos que têm o mesmo nome. vamos selecionar instalação parcial ("Partial BDE Installation"). Definindo os Arquivos Utilizados Quando você definiu as informações iniciais. Você pode alterar esse diretório se quiser. Em "BDE Driver Types". • Escolher Componentes da Interface [select user interface components]: permite configurar as várias janelas de diálogo que o programa de instalação mostra. você pode definir para o InstallShield os apelidos de bancos de dados que serão criados no computador do usuário. executando o programa de instalação no seu próprio computador para ver o funcionamento.X?? e . um processo que irá compactar todos os arquivos necessários e dividir em disquetes. Clique no sinal [+] ao lado de "Program Files" para expandir esse grupo. Você pode também acrescentar outros arquivos como. Selecione s arquivos com extensão '.. Marque a opção.YG0 etc. Para acrescentar outros arquivos.DB'. Depois você pode testar a instalação. que se compõe dos seguintes arquivos: CLIENTE. é possível definir modificações que serão feitas no registro. onde o programa será instalado. Após definir as opções. '.X'.'.DB. VENDAS.VAL'. mas sim locais.). Em "Query Engine Types". Clique em "General Options". Clique no botão Browse para buscar o arquivo executável da aplicação.

você pode escolher outro na propriedade Icon. permite escolher o que será instalado ou não. Progress Indicator [indicador de progresso]: mostra a porcentagem de arquivos copiados. Desative a menos que você tenha criado seus próprios arquivos Setup Complete: mostra uma janela avisando que a instalação foi completada e se oferece para executar o programa. Algumas delas têm opções de configuração diversas que podem ser alteradas. Se houvessem outros arquivos executáveis incluídos. Readme Information [informação tipo leia-me]: você pode escolher um arquivo texto. Gerando os arquivos e testando a instalação Para gerar os discos de instalação. Clique no ícone. altere "Description" para "Controle de Vendas" e clique em "Modify Icon". Vejamos cada uma: Welcome Bitmap [bitmap de boas-vindas]: mostra uma imagem inicial ao usuário. com o nome "Vendas". O InstallShield irá compactar os arquivos e informar quantos disquetes foram gerados. por exemplo). o local default. clique em "Disk Builder". Você pode escolher qual o tamanho do disquete de destino em "Disk Size" ou "CD-ROM" para gerar arquivos sem limite de tamanho. Start Copying Files [iniciar cópia de arquivos]: o instalador mostra uma janela avisando que vai começar a copiar os arquivos. Para esse exemplo. em Settings. Para fazer isso. Para mudar esse ícone. abaixo de "Specify Folders and Icons". Select Program Folder [escolher pasta do programa]: permite ao usuário escolher qual a pasta onde o programa será instalado. Choose Destination Location [escolha local de destino]: janela que permite ao usuário selecionar um diretório qualquer para instalar o programa. ela não será usada. você pode clicar na página "Settings". Software License Agreement [contrato de licença do software]: você pode escolher um arquivo texto (na página Settings) que será mostrado ao usuário. basta digitar seus parâmetros e clicar em "Add Icon". Depois clique no botão Build. User Information [informação de usuário]: uma janela que pede nome de usuário. dentro do seu projeto. o usuário não pode alterar esse local). Em Settings. Depois clique em Close. Welcome Message [mensagem de boas-vindas]: mensagem genérica do InstallShield. permite ao usuário selecionar uma delas. que mostra informação de última hora sobre o software. Nota: o ícone que aparece para o programa é o que foi definido no formulário principal. em inglês. você poderia criar ícones para eles também. mas vamos apenas ver quais estão disponíveis. Clique em Dialog Boxes na janela do InstallShield. Recomendase usar o mesmo nome descritivo do programa. Você pode definir. Clique Ok para sair dessa janela. ela será usada no instalador. Quando existe apenas um ícone a ser instalado. 166 . opcionalmente. para configurar. Billboards [anúncios]: mostra vários bitmaps enquanto o programa está sendo instalado. você pode mudar a opção padrão. Em Settings. senha e. você pode escolher qualquer arquivo de imagem . Você verá que o InstallShield já definiu um ícone para o seu programa.O InstallShield tem várias caixas de diálogo predefinidas. Na página Settings. é recomendável não criar um sub-menu na pasta Programas. não alteraremos nenhuma opção. Custom Setup [instalação personalizada]: quando o usuário usa a instalação personalizada. Se estiver desmarcada. marque a opção "Programs Menu Folder" e clique no botão "Modify Info". Para isso. Setup Type [tipo de instalação]: se você usa tipos de instalação (típica. compacta). do lado direito. você pode escolher um diretório contendo seus arquivos de imagem. de 16 cores (desenhado com o Paint. clique na página Advanced. que são apresentadas durante a instalação do programa. Se ela tiver opções a ser configuradas. mas sim colocar o ícone diretamente na pasta Programas (veremos o funcionamento disso mais tarde).BMP. personalizada. um número de série. Definindo os Ícones do Programa Agora clique em "General Settings". Você pode clicar no botão "Preview" para ver como a janela aparece em tela cheia. Se uma caixa de diálogo estiver marcada. (Se você desativar essa janela.

Após confirmação. Para terminar. Gerando os disquetes de instalação Para instalar o programa em outro computador. Capítulo 19 Relatórios Conceitos do QuickReport Usando o QuickReport Wizard Criando um Relatório com Várias Tabelas 167 . você pode gerar disquetes de instalação a partir do InstallShield.Agora. Informe as opções indicadas até finalizar a instalação. você pode executar o programa através do menu [ ]|Programas. no seu próprio computador. o programa será removido do Windows. selecione "Controle de Vendas" na lista e clique no botão "Adicionar/remover". O programa de instalação será executado. Ou selecione apenas um disco e clique em "Copy selected disk image". abra o Painel de Controle do Windows. clique em "Copy all disk images". Clique em "Copy to floppy". clique no ícone "Adicionar ou remover programas". clique em File|Save para salvar o projeto de instalação e feche o InstallShield. ícone Controle de Vendas. clique em "Test Run". Para desinstalar o programa. Após a instalação. para testar a instalação. Para copiar todos os discos.

sem se preocupar com detalhes como quebras de página. uma banda de cabeçalho de grupo é impressa. Pode se expandir verticalmente ou se dividir em várias páginas se necessário. tamanhos e estilos. A página QReport QuickRep O componente básico sobre o qual você monta os relatórios. Esse componente permite criar vários tipos de bandas. ele se conecta a um dataset. a partir de um campo do banco de dados. agrupamentos. círculos etc. ligadas da forma mestre/detalhe. Tem a aparência de uma folha de papel. Pode se expandir verticalmente ou se dividir em várias páginas se necessário. escolhido através das propriedades DataSet e DataField.Conceitos do QuickReport O QuickReport é um gerador de relatórios composto de vários tipos de componentes que trabalham em conjunto. O texto vem de um campo do banco de dados. que não vem do banco de dados. QRLabel Funciona como um componente Label. subtotais etc. com diferentes fontes. QRShape Usado para colocar desenhos no relatório. Como veremos. como linhas. com diferentes fontes. que é sempre impressa após uma determinada banda mestra. Imprime o conteúdo da propriedade Caption. mas para impressão. QRChildBand Cria uma banda filha. QRBand Uma banda é uma faixa do relatório que é impressa em determinados momentos. Útil se uma banda é muito grande e se expande. Os componentes do QuickReport estão na página QReport. determinado pelas propriedades DataSet e DataField. e permite colocar componentes imprimíveis sobre ele. QRRichText Imprime texto formatado. Quando um determinado campo muda de valor. que mostram os dados. QRDBRichText: Imprime texto formatado. ocupando várias páginas. data/hora etc. determinado pelas propriedades DataSet e DataField.: o logotipo da empresa). retângulos. QRMemo Imprime um texto de várias linhas. tamanhos e estilos. QRExpr Imprime campos calculados e outros itens. QRDBText Imprime o conteúdo de um campo do banco de dados. O texto deve ser definido via programação. 168 . QRSubDetail Faz a ligação do relatório com outras tabelas. QRSysData Imprime informações diversas como número de página. Com ele. QRGroup Cria um agrupamento de itens dentro do relatório. QRDBImage Imprime uma imagem no relatório. A propriedade Data define o que será impresso. de onde traz os dados. você pode criar visualmente o relatório. QRImage Imprime uma imagem no relatório (ex.

uma banda de detalhes [details] e uma banda de rodapé [page footer]. QRChildBand QRGroup manualmente ou usar a propriedade HasBand do componente ou QuickRep para criar alguns tipos de bandas automaticamente. No entanto. que são colocados nessas bandas. QRRichText. Você pode construir um relatório posicionando componentes QRBand. A propriedade DataSet do componente QuickRep determina o dataset principal. contendo o nome do cliente. QRShape). • Resumo [summary]: impressa uma única vez. • Rodapé de página [page footer]: impressa na parte inferior de cada página. • Detalhe [detail]: impressa uma vez para cada registro do dataset • Cabeçalho de grupo [group header]: quando existe um agrupamento de itens. no final da última página do relatório. que são as diversas faixas horizontais e componentes imprimíveis. Ex. Usada geralmente para os totais gerais. • Cabeçalho de página [page header]: impressa no topo de cada página. Outros mais complexos podem usar outros tipos. QRDBImage) campos do banco de dados (como QRExpr e ou ainda conteúdo variável. Os componentes imprimíveis são colocados sobre as bandas em tempo de projeto e são impressos quando o relatório é impresso. que estejam de alguma forma ligados a ele. Para imprimir o relatório. Os relatórios mais simples têm uma banda de cabeçalho da página [page header]. • Filha [child]: banda que serve como continuação de outra. Construindo o Relatório Um relatório do QuickReport tira seus dados de um dataset principal (tabela ou consulta SQL) e de alguns datasets secundários. Só tem utilidade com relatórios de múltiplas colunas. Funciona como a propriedade DataSet de um componente DataSource do Delphi. mas apenas usado internamente pelo programa.QRCompositeReport: Permite agrupar vários relatórios para imprimir como se fossem um só QRPreview Usado para ver uma prévia de impressão do relatório em outra janela.Columns no componente QuickRep). Eles podem conter texto ou imagens fixos (como QRLabel. após o cabeçalho de página. na primeira página do relatório. usa-se o método Preview. esse formulário não é mostrado ao usuário. QRMemo. 169 . (Vide propriedade Page. • Rodapé de grupo [group footer]: impressa no final de um grupo de itens. usa-se o método Print do componente. • Sub-detalhe [subdetail]: usada em relatórios mestre/detalhe. Para ver uma prévia de impressão numa janela. O componente QuickRep é visual e aparece num formulário em tempo de projeto. Os tipos de bandas são: • Título [title]: impressa uma única vez. como veremos mais tarde. • Cabeçalho de coluna [column header]: impressa no topo de cada coluna. QRImage. um cabeçalho de grupo é impresso para cada cliente. Usado apenas pelo componente QRChildBand. calculado ou determinado pelo relatório (como QRSysData).: se um relatório imprime vendas agrupadas por cliente. ou conteúdo ligado aos QRDBText. é impressa uma vez para cada grupo. QRDBRichText. O relatório é construído visualmente a partir de bandas.

FormRelCliente. A forma mais rápida é usar o QuickReport Wizard. com todos os campos de uma tabela.. que contém o formulário do QuickReport.Usando o QuickReport Wizard Existem duas formas de criar um relatório no QuickReport. colocando os componentes imprimíveis e definindo suas propriedades. Caso queira imprimeir utilize o método Print. em seguida qual o diretório ou alias da tabela e qual o nome da tabela e os campos que deseja mostrar. Preview é um método do componente que mostra uma janela de prévia de impressão. 170 . A outra forma é desenhar o relatório. Mude o Name do formulário para "FormRelCliente".Preview. O Delphi irá mostrar o repositório de itens para você escolher o que quer criar.QuickRep1. Agora clique em File|New. com a relação de clientes cadastrados. que cria um relatório bem simples. Imprimindo o Relatório Salve o formulário com RELCLIENTE. Selecione "CursoDelphi" na lista superior e depois "CLIENTE. Note que a janela de visualização é modal _ você deve fechá-la para voltar ao formulário. e selecione os campos "Nome" e "Telefone". Agora execute o programa e teste o funcionamento do relatório que será mostrado no vídeo.. selecione o ícone "QuickReport Wizard" e clique Ok. Clique na página "Business". Para que os comandos acima funcionem. Retorne ao formulário principal (formPrincipal). Note que 'FormRelCliente' é o nome do formulário que contém o componente QuickReport e 'QuickRep1' é o nome desse componente (não foi alterado). clique duas vezes no menu Relatório|Clientes e coloque o seguinte comando. mas é necessário com relatórios mais complicados. Em seguida clique no botão "Finish".PAS. Altere o seu nome para 'tblCliente' e a sua propriedade Active para True.DB" na lista inferior. cliqque no botão "Start Wizard" . o que é mais trabalhoso. acrescente uma cláusula uses no início da seção de implementação da unidade: uses RelCliente. Para o primeiro exemplo. O assistente irá perguntar inicialmente se você deseja criar um relatório com os campos de uma tabela. Note que existe um componente Table no formulário. Lembre-se de que 'RelCliente' é o nome da outra unidade. vamos criar um relatório usando o QuickReport Wizard.

impressa no rodapé da página. Os componentes que estão nesta banda são da classe QRExpr e cada um está associado com um campo da tabela. na parte inferior. À medida que você altera os valores. tem um componente QRLabel para cada nome de campo. é impressa repetidas vezes. Agora coloque um componente Table no formulário e altere suas propriedades para acessar a tabela de clientes: Name: tblCliente DatabaseName: CursoDelphi TableName: Cliente Agora clique na página 'QReport' e selecione o componente QuickRep para colocar no formulário. basta clicar com o botão direito no componente QuickRep (a folha em branco) e no item "Preview". para ver o conteúdo do formulário à direita. Abra o projeto VENDAS. VENDA. existe uma banda "Page Footer". O formulário deverá ter a seguinte aparência: 171 . mais abaixo. Criando um Relatório com Várias Tabelas Agora que já usamos o QuickReport Wizard. o componente mostra o nome do campo entre colchetes. são colocadas várias bandas. vamos utilizar o QuickReport para criar um . novas bandas irão aparecer no relatório. Crie um novo formulário. a tabela usada para os dados do relatório. Finalmente. Clique na barra de rolagem horizontal. Nesse componente. iremos acrescentar as vendas e os itens vendidos. Em vez de uma tabela. em todos os formulários estamos usando o Alias Local .Iremos criar um relatório de vendas de produtos. Salve o projeto novamente. PRODUTO. no próximo exemplo iremos ver essa propriedade com mais detalhes. Altere HasPageHeader. do banco de dados CursoDelphi. com File|New Form ou o botão nome do formulário para 'FormRelVenda'. A banda "Detail". Em tempo de projeto. que é o local de desenho do relatório. uma para cada registro. existe um componente que mostra "Page". Esse componente está ligado à tabela CLIENTE. Mova-o para o canto superior esquerdo e mude as seguintes propriedades: Name: qrpRelatorio DataSet: tblCliente Agora devemos escolher quais as bandas que serão incluídas no relatório. definindo os cabeçalhos das colunas. Clique duas vezes no sinal de + da propriedade Bands para ver seus sub-itens. cuja propriedade Data contém o valor 'qrsPageNumber'. Esse é um componente QRSysData. se você quiser ver uma prévia de impressão. Sobre esse componente. Note que ele possui um componente Table no canto. a propriedade DataSet faz referência a "tblCliente". Nesse projeto. Vamos ver como funciona esse formulário básico. na propriedade DataBaseName altere seu conteúdo para 'Vendas'. Altere o relatório de clientes. A "folha branca" com linhas horizontais e verticais é um componente QuickRep. clique no componente e altere a propriedade Caption. pois. que envolve dados de várias tabelas: CLIENTE. que o faz mostrar o número de página automaticamente.Nota: a qualquer momento. veremos como criar um relatório posicionando os componentes manualmente.DB. por cliente.DPR. A banda "Column Header". Se você quiser alterar o texto de um deles. Inicialmente iremos colocar somente a tabela de CLIENTE. ITEMVEND. Esta escolha da campo que será mostrado é feito na propriedade Expression . HasPageFooter e HasDetail para True. Analisando o Relatório Gerado Termine a execução do programa e abra o formulário 'FormRelCliente'.depois que estiver mostrando os Clientes. como foi informado no QuickReport Wizard. poderia ser um componente Query que faz uma consulta SQL. logo abaixo. Note que mais à direita na banda.

selecione o nome do campo.selecione "tblCliente" e DataField.Size: 20. iremos mostrar somente o nome do cliente(essa seção será impressa uma vez para cada cliente). um número de página que será incrementado automaticamente. Note que você pode selecionar uma banda clicando nela com o o mouse. Você pode aumentar a altura da banda. para centralizar o componente em relação à banda. selecionando 'qrsPageNumber'. 172 . Primeiro coloque um componente QRLabel e altere o seu Caption com "Página:". para mostrar data e hora AutoSize: True. para aumentar o texto Alignment: taCenter. Altere o Caption para "Vendas por Cliente" e também as seguintes propriedades: Font. Depois QRSysData e coloque à direita do rótulo. copie o componente Table do formulário de clientes [Ctrl+C] e cole [Ctrl+V] neste formulário. Nota: para chamar o Object Inspector. se preferir. a posição do componente se altera. para que o componente aumente de acordo com o conteúdo dele. para melhor visualização. com as Caption para "Nome" e. Coloque-o na banda "Page Footer" e altere as seguintes propriedades: Data: qrsDateTime. Se você mudar apenas Alignment. se ele não estiver visível. Inserindo um Número de Página Você pode inserir. Agora na banda "Details". como padrão. use a tecla [F11] ou [Enter]. em qualquer posição do relatório. logo à frente dele. As medidas que aparecem no relatório são dadas em centímetros. "Nome". coloque um componente QRLabel na banda "Page Header". mas a largura é determinada automaticamente baseado no tamanho de página.Nota: ou. Nota: basta clicar duas vezes em DataSet para aparecer o valor. para centralizar o texto AlignToBand: True. Aumente a largura do formulário para que ele ocupe a tela inteira. Vamos colocar um título do relatório. Vamos colocar um na banda "Page Footer". Vamos colocar também outro componente QRSysData para exibir a data e hora de impressão do relatório. um componenteQRDBText( propriedades DataSet . Quando você altera AlignToBand. apenas a posição do texto em relação ao componente se altera. Altere a propriedade selecione o componente Data. Coloque um componente QRLabel e altere o ).

Clique em 'tblProduto' e altere: MasterSource: dsItem. IndexName: CodCliente. Para todos eles. a janela de prévia de impressão. IndexName: IndVenda. Essa janela contém vários botões de controle.DB tblVenda ITEM. selecionando "Vendas". Você pode imprimir o relatório clicando no botão .Alignment: taRightJustify.DB tblProduto Agora coloque três componentes DataSource no formulário e conecte-os aos componentes Table correspondentes: Name DataSet tblCliente dsCliente tblVenda dsVenda tblItem dsItem Conectando as Tabelas Faremos ligações mestre-detalhe para relacionar as tabelas.DB tblItem PRODUTO. para alinhar o texto à direita do componente AlignToBand: True. altere DatabaseName. Defina as suas propriedades da seguinte forma: Name TableName VENDA. MasterFields: CodVenda. Finalmente. A aparência do relatório . Quando o Delphi pedir o nome da unidade do novo formulário. devemos conectar as duas. podem ser usados botões para navegar entre as páginas: anterior. Clique em 'tblItem' e altere: MasterSource: dsVenda. informe "RVenda". Desative a tabela (altere Active para False) porque ela será ativada apenas durante a execução do programa. Acrescentando Várias Tabelas ao Relatório Coloque três componentes Table no formulário. Agora vamos conectar 'ITEM' e 'VENDA'. MasterFields: CodProduto. MasterFields: CodCliente. altere a propriedade Active do 'tblCliente' para True. Primeiro vamos conectar 'Venda' a 'Cliente' (um cliente tem N vendas). Os três primeiros permitem escolher a quantidade de zoom: 100 % ou largura da página. clique no componente QuickRep (fora das bandas) com o botão direito e clique na opção Preview do menu. para buscar o nome do produto a partir da tabela ITEM. Salve o projeto. Isso vai mostrar. O botão configurar as opções de impressão com o botão permite salvar o relatório permite abrir esse arquivo novamente para visualizar. será semelhante à figura: 173 . para alinhar o componente à direita da banda Visualizando o Relatório Para visualizar o relatório como ele vai estar quando impresso. nesse momento. Quando o relatório tem primeira. Clique em 'tblVenda' e altere as propriedades: MasterSource: dsCliente. como antes. ou várias páginas. IndexFieldNames: CodProduto. próxima e última. E o botão Close fecha num arquivo e a janela de visualização.

Criando Sub-detalhes para Vendas Quando se tem um relatório com tabelas mestre-detalhe. Na frente coloque um componente QRDBText.. com os dados do cliente. com o texto "Data Venda:" e um QRDBText. Criando Sub-detalhes para Itens de Venda 174 . Na propriedade DataSet. Note que primeiro é impressa a seção 'Detail'. Vamos mostrar nesse caso os dados da tabela de vendas. a propriedade Master define quem é o 'relatório mestre' para ele. "sub-detalhes".. coloque mais um QRLabel. use o Preview para visualizar o relatório (tblVenda deve estar ativo). Ele aparece como uma nova banda. Deixe-a como está. Nesse componente. Por exemplo: Cliente: Primeiro Código Venda:101 Data Venda: 04/07/97 Código Venda:102 Data Venda: 05/07/97 Código Venda:105 Data Venda: 13/07/97 Cliente: Segundo Código Venda:107 Data Venda: 20/07/97 Código Venda:108 Data Venda: 30/07/97 Código Venda:110 Data Venda: 30/08/97 Cliente: Terceiro Código Venda:107 Data Venda: 20/07/97 Código Venda:108 Data Venda: 30/07/97 . O resultado ficará como o seguinte: Se quiser. que determina quando ele será impresso.. com o texto "Código Venda:". Destaque os rótulos em negrito.. Note que a propriedade Master nesse caso foi definida como 'qrpRelatorio'. Para colocar dados das outras tabelas. com DataSet: tblVenda e DataField: DataVenda. selecione 'tblVenda'. depois é impressa várias vezes a seção Sub-detail. contendo as vendas efetuadas.. utilizando o componente Coloque no formulário um componente QRSubDetail. Após os dois. mas acima de "Page Footer".. abaixo de "Detail". devemos colocar bandas QRSubDetail. com DataSet: tblVenda e DataField: CodVenda. a banda "detalhe" se relaciona apenas com a tabela mestra. Coloque na banda sub-detail um componente QRLabel. Mude o nome desse componente para 'qrsubVenda'. que é o nome do componente QuickRep. como veremos.. Isso vai ajudar a identificá-lo mais tarde.

Um cabeçalho de grupo é uma banda impressa antes de todos os registros do grupo (no caso. Coloque quatro rótulos de texto (QRLabel). para dizer que essa banda sub-detalhe estará subordinada à banda 'qrsubVenda'. ele muda de tamanho de acordo com o conteúdo.00". Clique na propriedade Bands desse componente e expanda seus sub-itens. Agora visualize novamente a prévia de impressão. para True. como a formatação dos campos. serão impressos vários registros de itens de venda. Agora. Clique na banda "Group Header". Além disso. devemos imprimir os itens de venda correspondentes a eles. coloque mais um componente QRSubDetail no relatório. HasHeader e HasFooter. clique no botão de reticências. criada anteriormente . Vamos mostrar aqui o nome do produto (campo Nome de tblProduto). que será colocado mais tarde. Com isso. visualmente. colocando o texto "#. para cada venda. abaixo do "Group Header" novamente. como já foi visto. Coloque três componentes QRDBText. Deixe um espaço maior entre "Produto" e "Quantidade". todos os itens de uma determinada venda) e um rodapé de grupo é impresso após todos os registros do grupo. Na propriedade Font. vamos criar um cabeçalho de grupo e um rodapé de grupo. altere a propriedade Mask. O preço total é um campo calculado. debaixo dos rótulos correspondentes e defina suas propriedades da seguinte forma: DataSet DataField tblProduto Nome tblItem Quantidade tblItem PrecoVenda O resultado. Clique no componente QRDBText que mostra "[Quantidade]". vamos mostrar os campos "Quantidade" e "PrecoVenda" alinhados à direita e "PrecoVenda" formatado como um valor monetário. Alguns detalhes ainda precisam ser acertados. que vai aparecer abaixo da banda de vendas. para essa banda. Essa propriedade tem o mesmo efeito de DisplayFormat para campos da tabela.ou seja. Quando AutoSize é True. Posicione-o alinhado à direita de acordo com o rótulo e mude a propriedade Alignment para 'taRightJustify'. Altere os dois. para cada registro de venda impresso. todos os componentes colocados nessa banda ficarão em negrito. será o seguinte: Se desejar. Formatando os Campos Para melhorar a aparência do relatório. a quantidade vendida (campo Quantidade de tblItem) e o preço de venda (campo PrecoVenda de tblItem). "Preço Unitário" e "Preço Total". Isso vai criar as bandas de cabeçalho e rodapé de grupo.Agora. Note que os campos aparecem formatados corretamente. "Quantidade". acima e abaixo do 'sub-detail'.0. selecione "Negrito" e clique Ok. Agora clique na banda "sub-detail". Altere a propriedade AutoSize para False. Altere as seguintes propriedades: Name: qrsubItem DataSet: tblItem Master: qrsubVenda A propriedade Master deve ser alterada. O cabeçalho será usado para mostrar os nomes de campos e o rodapé será usado para mostrar um total geral. Para isso. alterando o Caption em cada um com os textos "Produto". Criando um Campo Calculado 175 . clique com o botão direito no relatório e depois em Preview(Para funcionar todas as tabelas tem que estar com a propriedade Active = True). Selecione o componente "[PrecoVenda]" e faça o mesmo: AutoSize=False e Alignment=taRightJustify.

é 'tblItem. Agora. que contém os valores a serem calculados. escolha a tabela 'tblProduto' e o campo 'PrecoVenda'. usando o componente QRExpr. em seguida pressione o botão 'OK'. Coloque no formulário um componente QRExpr logo abaixo do rótulo "Preço Total". na lista "Select dataset". portanto. Clique no botão "Database Field". Clique na propriedade Expression. clique novamente em "Database Field".PrecoVenda'. clique no botão com o sinal de multiplicação. Você verá uma janela onde poderá montar uma expressão de cálculo. [*]. envolvendo campos da tabela. No quadro de texto na parte superior da janela.Quantidade * tblProduto. Os campos da tabela aparecem na lista abaixo do nome. Vamos usar esse componente para calcular o "Preço Total" do item. A fórmula final aparecerá como na figura: A fórmula de cálculo do campo. aparece 'tblItem. que define a fórmula de cálculo do campo e clique duas vezes no botão de reticências. Você não precisa escrever código de programa para fazer o cálculo. Clique em 'Quantidade'. 176 . Agora clique Ok para retornar ao formulário. que é PrecoVenda * Quantidade. Para terminar. a tabela 'tblItem'. você pode digitar uma expressão qualquer.Você pode criar campos calculados no QuickReport. Com ele. Um sinal * será inserido no texto da fórmula.Quantidade'.

Dentro da seção public. pois seria mais complicado). No nosso caso.Open. tblVenda. é usada a propriedade Master do componente. selecione 'qrsubItem'. o componente acumulará internamente o seu total. {fechar todas as tabelas usadas} tblCliente. o componente atualiza internamente o total. será para os itens de cada venda. no começo da seção implementation. Use o comando Preview para visualizar o relatório. Tecle [Ctrl+C] para fazer uma cópia dele. 177 . Se você usar o comando Preview novamente. begin {abrir todas as tabelas usadas} tblCliente.PrecoVenda * tblItem. com o texto "Total da venda" e em negrito. faça uma alteração manual (não clique no botão de reticências.0. acrescente a seguinte declaração de procedimento: procedure VisualizarRelatorio.Para visualizar esse componente melhor. para mostrar o total de vendas para cada cliente. No nosso caso. Agora coloque à esquerda desse componente um QRLabel.Close. em Master. encontre a classe de formulário (TFormRelVendas). a cada item de venda impresso. Onde está o valor atual: tblItem. o componente continua acumulando o total até o fim da impressão. Mas é preciso também informar qual é o conjunto de registros sobre os quais essa soma será efetuada. que é a banda que contém os itens de venda. faremos com que ele seja chamado a partir do menu principal. Na unidade "RVendas". coloque-o em negrito. Com isso. Se ela for False.Open. tblProduto.Open. o componente zera o seu acumulador depois de impresso. no item de menu Relatórios|Vendas.Close. Mas antes vamos criar um procedimento no formulário do relatório para facilitar a sua chamada. Para dar mais destaque ao sub-total. como foi feito antes para o preço de venda. Na propriedade Expression. acrescente o corpo do procedimento: procedure TFormRelVenda. verá que o campo calculado é mostrado corretamente para cada registro. Agora. que foi criado para calcular o preço total. Para definir o escopo da soma.Quantidade substitua por: SUM(tblItem.Close. tblItem. tblVenda.VisualizarRelatorio. Altere também as propriedades: Alignment: taRightJustify e Mask: "#.PrecoVenda * tblItem. Essa propriedade faz referência a uma banda que define quando o somatório será atualizado.Quantidade) A função SUM calcula o somatório de uma expressão.Close. Altere também a propriedade ResetAfterPrint para True. Selecione o componente QRExpr. antes de imprimir. Note agora que o sub-total será impresso após os itens de venda. Clique na banda "Group Footer" e tecle [Ctrl+V] para trazer essa cópia. tblProduto. Quando essa banda for impressa.Preview. {visualizar o relatório} qrpRelatorio. altere a propriedade AutoSize para False e reduza a largura do componente de acordo com o rótulo na parte superior. Chamando o Relatório a Partir do Menu Agora que o relatório está pronto.00". Quando ela é True.Open. Criando um Sub-total Agora vamos totalizar o campo calculado criado. tblItem.

. O programa mostrará a janela de prévia de impressão. clique em File|Use unit. e selecione "RVenda" para acrescentar a unidade na cláusula uses. Coloque os seguinte comando: FormRelVenda.end. Salve o projeto novamente. como já foi visto. No formulário.. 178 . Execute o programa e clique em Relatórios|Vendas.PAS.VisualizarRelatorio. clique no item de menu Relatórios|Vendas. Abra a unidade do formulário principal. VENDPRIN. Para poder chamar o outro formulário.

O livro discute assuntos sobre desenvolvimento de aplicações e conceitos de estrutura para aplicações de bancos de dados cliente/servidor. desktop. Advanced. Internet. Rodrigo. Tópicos incluem: Componentes de nível avançado incluindo links embutidos. visando tornar o trabalho do programador mais prático e produtivo. • LOBO. Incrementando o Delphi. Ed. Esta é a edição completamente revisada e atualizada do livro de programação Delphi mais louvado de todos os tempos. inclusive a criação de suas próprias Bibliotecas de Componentes Visuais (VCL). oferecendo a cobertura mais efetiva e cuidadosa da programação Delphi que se pode encontrar. Os autores lidam com desenvolvedores todos dias e citam técnicas poderosas. etc. Escrito pelo destacado especialista em Delphi. características especiais e DLLs. Marco. este livro é dedicado a usuários iniciantes e avançados. dicas e conhecimento técnico das mais avançadas características do Delphi 4. Ed. PACHECO. e como trabalhar com eles. multimídia. Steve. Inclui CD contendo os componentes e utilitários. Xavier e TEIXEIRA. programação orientada a objeto avançada e object Pascal. Makron. Este livro oferece uma série de dicas. Dominando o Delphi 4 "A bíblia". Marco Cantú. ISBN: 0672312840 Este livro é uma referência de nível avançado mostrando aos desenvolvedores o mais importante que eles devem saber sobre o Delphi 4. utilitários e componentes para o Delphi.Bibliografia sugerida Os seguintes livros são uma boa fonte de material para aprofundar-se um pouco mais no conhecimento do Delphi. ISBN: 8534610460. CANTÙ. Englobando as áreas de banco de dados. Delphi 4 Developer's Guide (Developer's Guide Series). bem como componentes MIDAS (Multi-tier Distributed Applications Services Suite). arquivos. • • 179 . truques. ISBN: 8586916218.

Sign up to vote on this title
UsefulNot useful