Professional Documents
Culture Documents
Delphi 4.0
Captulo 1
CAPTULO 1 ..............................................................................................................................................2 CAPTULO 01 - INICIANDO O DELPHI...............................................................................................8 ......................................................................................................................................................................8 PRINCPIOS DA PROGRAMAO WINDOWS ................................................................................................9 INICIANDO O DELPHI ...............................................................................................................................10 CRIANDO UM PRIMEIRO PROGRAMA........................................................................................................12 Propriedades do Formulrio ..............................................................................................................12 Colocando Componentes ....................................................................................................................12 Alterando as Propriedades dos Componentes ....................................................................................13 Respondendo a Eventos ......................................................................................................................13 Testando o Programa .........................................................................................................................14 Salvando o Programa .........................................................................................................................14 AMBIENTE DE PROGRAMAO ................................................................................................................14 Programao Orientada a Objeto (POO) ..........................................................................................14 EVENTOS E PROCEDIMENTOS...................................................................................................................14 COMPONENTES ........................................................................................................................................15 Viso Geral dos Componentes............................................................................................................15 PROPRIEDADES ........................................................................................................................................16 MTODOS ................................................................................................................................................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 EDIES DO DELPHI ................................................................................................................................19 CAPTULO 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 CAPTULO 4 VARIVEIS E TIPOS DE DADOS ...............................................................................25 TIPOS DE DADOS......................................................................................................................................26 Tipos Numricos .................................................................................................................................26 O tipo Char .........................................................................................................................................27 O tipo String .......................................................................................................................................27 O tipo Boolean ....................................................................................................................................28 O tipo TDateTime ...............................................................................................................................28 FUNES DE CONVERSO........................................................................................................................29 OPERAES ARITMTICAS ......................................................................................................................29 TIPOS ORDINAIS ......................................................................................................................................30 ESCOPO DE VARIVEIS ............................................................................................................................31 Variveis Locais .................................................................................................................................31 Variveis Globais da Unidade............................................................................................................31 Variveis Globais do Projeto..............................................................................................................31
CONSTANTES ...........................................................................................................................................31 CAPTULO 5 ESTRUTURAS DE CONTROLE ..................................................................................33 INSERINDO COMANDOS COM O CODEINSIGHT ..........................................................................................34 ESTRUTURAS DE DECISO .......................................................................................................................34 O Comando if...then...else...................................................................................................................34 O Comando case...of...........................................................................................................................35 ESTRUTURAS DE LAOS...........................................................................................................................37 O comando for ....................................................................................................................................37 O comando while...do... ......................................................................................................................37 O comando repeat..until .....................................................................................................................37 OUTROS COMANDOS ...............................................................................................................................38 Comandos para sair de laos .............................................................................................................38 O comando exit ...................................................................................................................................38 CAPTULO 6 PROPRIEDADES E EVENTOS COMUNS..................................................................39 TIPOS DE PROPRIEDADES .........................................................................................................................40 PROPRIEDADES MAIS USADAS .................................................................................................................41 Propriedades para Todos os Componentes ........................................................................................41 Propriedades de Tamanho e Posio .................................................................................................41 Propriedades do Formulrio ..............................................................................................................41 Propriedades de Controles .................................................................................................................42 EVENTOS COMUNS ..................................................................................................................................43 Eventos de Mouse ...............................................................................................................................43 Eventos de Teclado .............................................................................................................................43 Eventos do Formulrio .......................................................................................................................44 Outros Eventos....................................................................................................................................44 DETALHES DO TRATAMENTO DE EVENTOS ..............................................................................................45 Tratando um Evento para Vrios Controles: OnKeyPress.................................................................45 Renomeando um Procedimento de Evento..........................................................................................45 Associando um Procedimento Existente .............................................................................................46 Eliminando um Procedimento de Evento............................................................................................46 CAPTULO 7 USANDO VRIOS FORMULRIOS...........................................................................47 CAIXAS DE DILOGO ...............................................................................................................................48 FUNES DE MENSAGEM.........................................................................................................................48 Mensagens Informativas .....................................................................................................................48 Mensagens de Confirmao................................................................................................................48 EXEMPLO: CALCDATA ............................................................................................................................49 Pedindo Confirmao ao Usurio ......................................................................................................50 Criando um Novo Formulrio ............................................................................................................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 FORMULRIO PRINCIPAL ...................................................................................................56 CAPTULO 8 ESTRUTURA DAS UNIDADES ....................................................................................57 ESTRUTURA GERAL DAS UNIDADES ........................................................................................................58 O CDIGO GERADO PELO DELPHI ............................................................................................................58 Seo de Interface...............................................................................................................................58 UNIDADES ASSOCIADAS E INDEPENDENTES.............................................................................................59 COMPILAO DE UNIDADES ....................................................................................................................60 USANDO UMA UNIDADE ..........................................................................................................................60 RESOLVENDO CONFLITOS DE NOMES ......................................................................................................62 CAPTULO 9 OUTROS TIPOS DE DADOS E DEPURAO ..........................................................63 TIPOS ENUMERADOS................................................................................................................................64
Operaes com Ordinais ....................................................................................................................64 Tipos Enumerados no Delphi..............................................................................................................64 TIPOS FAIXA ............................................................................................................................................65 Opo "Range Checking" ...................................................................................................................65 VETORES .................................................................................................................................................65 Vetores Estticos.................................................................................................................................65 Verificao de Faixa para Vetores .....................................................................................................66 Usando Outros Tipos de ndice ..........................................................................................................66 Vetores Dinmicos..............................................................................................................................67 Vetores Multidimensionais..................................................................................................................67 EXEMPLO: CLCULO DE MDIA ..............................................................................................................68 Declarando o Vetor ............................................................................................................................68 Adicionando um Elemento ..................................................................................................................68 Limpando a Lista ................................................................................................................................69 Calculando a Mdia dos Elementos....................................................................................................69 Testando o Programa .........................................................................................................................69 Salvando o Projeto..............................................................................................................................70 CONJUNTOS .............................................................................................................................................70 Verificando Elementos ........................................................................................................................70 Operaes com Conjuntos ..................................................................................................................70 Propriedades de Conjunto ..................................................................................................................71 DEPURAO ............................................................................................................................................72 Colocando um Ponto de Parada.........................................................................................................72 Executando Passo a Passo..................................................................................................................72 Executando At o Cursor ....................................................................................................................72 Vendo Valores de Variveis................................................................................................................73 Monitorando o Valor de uma Varivel Dinamicamente .....................................................................73 Forando a Finalizao do Programa ...............................................................................................74 Outras Ferramentas de Depurao ....................................................................................................74 10 - PROCEDIMENTOS E FUNES..................................................................................................75 PROCEDIMENTOS GERAIS ........................................................................................................................76 Criando um Procedimento Geral........................................................................................................76 UNIDADES INDEPENDENTES.....................................................................................................................76 Criando uma Unidade Independente ..................................................................................................77 Transferindo o Procedimento .............................................................................................................77 Usando a Unidade no Mesmo Projeto ................................................................................................77 Usando a Unidade em Outros Projetos ..............................................................................................77 Gerenciando um Projeto com Unidades Independentes .....................................................................78 Criando uma Biblioteca de Rotinas ....................................................................................................78 FUNES .................................................................................................................................................79 Criando uma Funo ..........................................................................................................................79 Retornando um Valor..........................................................................................................................79 Chamando a Funo...........................................................................................................................79 PASSAGEM DE PARMETROS ...................................................................................................................80 Declarao de Parmetros e Argumentos ..........................................................................................80 Tipos de Passagem..............................................................................................................................80 CAPTULO 11 OBJETOS .......................................................................................................................82 O QUE CONTM UM OBJETO....................................................................................................................83 CLASSES E OBJETOS ................................................................................................................................83 HERANA ................................................................................................................................................84 Hierarquia de Classes do Delphi........................................................................................................84 O Object Browser ...............................................................................................................................84 Simplificando o Acesso aos Campos...................................................................................................84 FORMULRIOS COMO OBJETOS ................................................................................................................86 A Classe de Formulrio ......................................................................................................................86 Procedimentos na classe de formulrio..............................................................................................87 VARIVEIS DE OBJETO ............................................................................................................................87
LISTAS DE STRINGS .................................................................................................................................90 Propriedades da String List ................................................................................................................90 Mtodos da String List ........................................................................................................................90 Criando String Lists Independentes....................................................................................................90 OBJETOS PREDEFINIDOS ..........................................................................................................................91 O Objeto Application ..........................................................................................................................91 O Objeto Clipboard ............................................................................................................................91 O Objeto Screen..................................................................................................................................92 CODE EXPLORER .....................................................................................................................................92 PROGRAMAO ORIENTADA A OBJETOS .................................................................................................93 CAPTULO 12 APLICAES DE BANCO DE DADOS ....................................................................95 TERMOS USADOS .....................................................................................................................................96 DESKTOP X CLIENTE/SERVIDOR ..............................................................................................................97 FORMATOS DE BANCOS DE DADOS ..........................................................................................................97 CRIANDO TABELAS..................................................................................................................................98 Definindo um Diretrio de Trabalho ..................................................................................................98 Definindo a Estrutura dos Campos.....................................................................................................98 Salvando a Tabela ..............................................................................................................................99 Entrando com Dados ..........................................................................................................................99 EXEMPLO: USANDO O DATABASE FORM WIZARD .................................................................................101 Criando um campo autoincremento..................................................................................................101 Criando um Formulrio para Acessar a Tabela com Form Wizard.................................................101 Testando o Programa .......................................................................................................................102 Salvando o Projeto............................................................................................................................102 RESUMO DOS COMPONENTES DE DADOS ...............................................................................................102 APELIDOS DE BANCOS DE DADOS ..........................................................................................................103 CAPTULO 13 RECURSOS ADICIONAIS ........................................................................................105 DEFININDO TABELAS .............................................................................................................................106 Reestruturando a Tabela "Cliente"...................................................................................................106 Criando um ndice Secundrio .........................................................................................................107 Criando a Tabela "Venda"................................................................................................................107 Criando Integridade Referencial ......................................................................................................107 Criando a Tabela de Itens.................................................................................................................107 Criando a tabela Fornecedores ........................................................................................................108 CRIANDO O MENU PRINCIPAL................................................................................................................109 O MenuDesigner: criando menus .....................................................................................................109 Tratando Eventos de Menus..............................................................................................................111 Teclas de Acesso e Teclas de Atalho.................................................................................................111 ALTERANDO O MENU PRINCIPAL...........................................................................................................112 Alterando Propriedades....................................................................................................................112 Acrescentando os formulrios anteriores .........................................................................................112 Associando os formulrios aos itens de menu ..................................................................................112 USANDO O CONTROLE DBGRID ............................................................................................................113 Criando os Componentes de Dados..................................................................................................113 Manipulando dados no DBGrid........................................................................................................113 Usando o Editor de Campos .............................................................................................................114 Alterando a Mscara de Edio .......................................................................................................114 CAPTULO 14 VALIDAO E PESQUISAS ....................................................................................116 EXEMPLO: CLIENTE POR ESTADO ..........................................................................................................117 EXEMPLO: CLIENTES - ALTERANDO ......................................................................................................117 VALIDAO DE CAMPOS E REGISTROS ..................................................................................................118 Validando Campos............................................................................................................................118 Validando Registros..........................................................................................................................120 TRATAMENTO DE EXCEES .................................................................................................................121 Visualizando Informaes sobre Excees .......................................................................................122 Classes de Excees..........................................................................................................................122
PESQUISAS NA TABELA ..........................................................................................................................122 Adicionando um DBGrid ..................................................................................................................122 Utilizando um ndice Secundrio......................................................................................................123 Pesquisando pelo Nome....................................................................................................................124 Pesquisando pelo Cdigo .................................................................................................................124 BLOCOS PROTEGIDOS ............................................................................................................................125 CAPTULO 15 ACESSO S/ CONTROLE DE DADOS ......................................................................126 ESTADOS DE UMA TABELA ....................................................................................................................127 MTODOS PARA PERCORRER DADOS .....................................................................................................128 Mtodos de Abertura e Fechamento .................................................................................................128 Mtodos para Percorrer Registros ...................................................................................................128 Exemplo: Percorrendo a Tabela de Itens .........................................................................................129 MTODOS PARA MODIFICAR DADOS .....................................................................................................131 Editando Registros............................................................................................................................131 Acrescentando Registros...................................................................................................................131 Excluindo Registros ..........................................................................................................................132 Outros Mtodos.................................................................................................................................132 EVENTOS DOS COMPONENTES DE DADOS ..............................................................................................134 Eventos do Componente Table..........................................................................................................134 MANIPULAO DE DATAS .....................................................................................................................135 EXEMPLO: CRIANDO FORMULRIO SEM UTILIZAR O DBNAVIGATOR......................................................137 TRATAMENTO DO ERRO 'KEY VIOLATION.' ............................................................................................140 USANDO UM CONTROLE DBLOOKUPCOMBOBOX .................................................................................140 CAPTULO 16 UTILIZANDO MESTRE/DETALHE .......................................................................142 CRIANDO UM FORMULRIO MESTRE/DETALHE .....................................................................................143 Usando o DFW para criar o formulrio...........................................................................................143 Testando o Formulrio Gerado ........................................................................................................144 Analisando o Formulrio..................................................................................................................144 Alterando Propriedades do Formulrio ...........................................................................................145 Salvando o Projeto............................................................................................................................145 USANDO TRS TABELAS NO FORMULRIO ............................................................................................146 Ligando os Componentes de Dados..................................................................................................146 Criando Controles de Dados ............................................................................................................146 Criando Campos Calculados............................................................................................................147 Usando um campo Lookup................................................................................................................147 Testando e Salvando o Projeto .........................................................................................................148 Atualizando Quantidade em Estoque ...............................................................................................149 CAPTULO 17 CONSULTAS E SQL ..................................................................................................151 EXEMPLO: USANDO CONSULTAS ...........................................................................................................152 Criando o Formulrio ......................................................................................................................152 Obtendo um Resultado Modificvel ..................................................................................................153 Simplificando o Select.......................................................................................................................153 Alterando a Consulta ........................................................................................................................153 Alterando a Consulta Dinamicamente ..............................................................................................153 Alterando Outras Partes da Consulta...............................................................................................155 EXEMPLO: CONSULTANDO VRIAS TABELAS ........................................................................................156 Consulta com Duas Tabelas .............................................................................................................156 Consultando Trs Tabelas ................................................................................................................157 Usando Campos Calculados no SQL................................................................................................157 Usando Funes de Resumo .............................................................................................................157 OUTROS COMANDOS SQL .....................................................................................................................158 Testando Comandos SQL..................................................................................................................158 Alterando Registros ..........................................................................................................................158 Excluindo Registros ..........................................................................................................................159 Inserindo e Copiando Registros........................................................................................................159 Executando um Comando de Atualizao.........................................................................................159
CONSULTAS NUM AMBIENTE CLIENTE/SERVIDOR .................................................................................159 MTODOS E EVENTOS DO COMPONENTE QUERY ...................................................................................160 CAPTULO 18 INSTALADOR E ALIAS LOCAL .............................................................................161 USANDO UM ALIAS LOCAL ....................................................................................................................162 Usando o Componente Database......................................................................................................162 Alterando os Componentes de Dados ...............................................................................................163 Alterando o Caminho em Tempo de Execuo .................................................................................163 CRIANDO UM PROGRAMA INSTALADOR .................................................................................................164 Iniciando o InstallShield ...................................................................................................................164 Criando um Instalador......................................................................................................................164 Definindo as Opes de Instalao ..................................................................................................165 Definindo os Arquivos Utilizados .....................................................................................................165 Escolhendo as caixas de dilogo ......................................................................................................165 Definindo os cones do Programa ....................................................................................................166 Gerando os disquetes de instalao..................................................................................................167 CAPTULO 19 RELATRIOS.............................................................................................................167 CONCEITOS DO QUICKREPORT ..............................................................................................................168 A pgina QReport .............................................................................................................................168 Construindo o Relatrio ...................................................................................................................169 USANDO O QUICKREPORT WIZARD .......................................................................................................170 Imprimindo o Relatrio ....................................................................................................................170 Analisando o Relatrio Gerado ........................................................................................................171 CRIANDO UM RELATRIO COM VRIAS TABELAS .................................................................................171 Inserindo um Nmero de Pgina ......................................................................................................172 Visualizando o Relatrio...................................................................................................................173 Acrescentando Vrias Tabelas ao Relatrio.....................................................................................173 Conectando as Tabelas .....................................................................................................................173 Criando Sub-detalhes para Vendas ..................................................................................................174 Criando Sub-detalhes para Itens de Venda ......................................................................................174 Formatando os Campos....................................................................................................................175 Criando um Campo Calculado .........................................................................................................175 Criando um Sub-total........................................................................................................................177 Chamando o Relatrio a Partir do Menu .........................................................................................177 BIBLIOGRAFIA SUGERIDA ......................................................................................................................179
Iniciando o Delphi
Inicie o Delphi atravs do seu cone no Windows, se voc j tiver um atalho para o do Windows e depois em programa na sua rea de trabalho. Seno, clique no menu Programas|Borland Delphi 4|Delphi 4. A tela bsica do Delphi tem os seguintes elementos:
Nota: para criar um atalho para o Delphi, consulte a documentao do Windows. Localize o arquivo executvel DELPHI32.EXE sob o diretrio de instalao. Formulrio (Form1): Um formulrio a janela do seu programa, o local onde voc projeta a sua interface com o usurio. Durante o projeto, o formulrio aparece de forma praticamente
10
idntica ao que o usurio final ver, mas permite que voc faa alteraes no posicionamento dos componentes (elementos de tela) e em suas propriedades (caractersticas); Speedbar: Uma barra de botes na janela principal do Delphi, que contm botes para executar os comandos mais usados do Delphi; Paleta de Componentes: Tambm na janela principal, dividida em vrias pginas, onde cada uma contm vrios tipos de componentes que voc pode escolher para colocar no formulrio; Object Inspector: [inspetor de objeto]: Dividido em duas pginas, onde uma contm as propriedades do componente selecionado, e a outra uma lista de eventos associados a este componente, que define as aes externas as quais voc pode tratar; Menu Principal: Contm os comandos do ambiente de programao do Delphi, por exemplo, para tratamento de arquivos, definio de opes, etc. Code Editor: (Aparece atrs do formulrio, inicialmente). Contm o cdigo-fonte do projeto. Com ele, voc pode facilmente mudar entre os vrios arquivos utilizados no projeto ou mesmo abrir um arquivo de texto qualquer.
11
Para cri-lo, precisamos alterar propriedades do formulrio e colocar componentes em cima dele.
Propriedades do Formulrio
Propriedades do formulrio so as caractersticas que definem sua aparncia, e algumas vezes, seu comportamento. O Object Inspector lista todas as propriedades do formulrio, que so inicializadas com valores padro quando o projeto criado. Por exemplo, o ttulo que aparece no formulrio (inicialmente Form1) uma propriedade que voc pode alterar no Object Inspector. Selecione a propriedade Caption no Object Inspector. Clique na coluna da direita (que contm o valor da propriedade) e digite o texto Primeiro Programa Delphi. medida que voc digita, o formulrio reflete essa alterao na sua barra de ttulo.
Colocando Componentes
Um formulrio vazio no muito til, portanto vamos colocar componentes nesse formulrio. A Paleta de Componentes contm vrios cones, onde cada um representa um tipo de componente que voc pode colocar no formulrio. Ela tambm dividida em pginas, que podem ser acessadas clicando no marcador de pgina correspondente. Quando voc passa o cursor do mouse por cima de um cone, ela mostra o nome daquele componente. Clique na pgina Standard e depois clique no cone (Edit). Agora clique no formulrio. Vai aparecer um quadro de edio chamado "Edit1". Depois iremos alterar esse nome padro. Para mud-lo de posio no formulrio, posicione o cursor em cima dele, pressione e segure o boto do mouse, e arraste-o para outra posio, ao arrastar o componente ser mostrado as coordenadas (x, y) indicando a posio do componente no formulrio . Ou, se preferir, usando o teclado, segure a tecla [Ctrl] e use as teclas de seta para moviment-lo. Agora precisamos de um quadro de lista. Clique no cone (ListBox) da paleta de componentes, na mesma pgina Standard, depois clique no formulrio, um pouco abaixo do quadro de texto (no se preocupe com alinhamento). Para aumentar seu tamanho lateral, clique na ala mais direita, segure o boto do mouse e arraste-o para a direita. Ou, usando o teclado, segure [Shift] e pressione a seta para a direita.
12
Vamos colocar trs botes no formulrio. Como so vrios controles do mesmo tipo, podemos fazer o seguinte: segure [Shift] e clique no cone (Button) da paleta de componentes. Agora clique trs vezes no formulrio, colocando um boto abaixo do outro. No se preocupe com o alinhamento por enquanto Depois clique no cone do ponteiro ( formulrio deve ficar parecido com o seguinte: ).O
Clique no boto (Run) da SpeedBar. O Delphi ir compilar o programa, gerando um arquivo executvel e vai iniciar sua execuo. Durante a execuo, voc pode digitar texto no quadro de texto, e clicar nos botes. Depois tecle [Alt+F4] para terminar o programa (ou feche a janela com o mouse). Repare que o Delphi cuida de toda a parte de interface com o usurio. Voc no precisa escrever cdigo para mostrar uma janela na tela nem seus componentes. Mas para definir o que o programa vai fazer, isto , como ele reage aos eventos externos, voc precisa escrever cdigo.
Respondendo a Eventos
Todo o cdigo no Delphi executado, direta ou indiretamente, em resposta a eventos. Quando voc (ou o usurio) clica em um boto por exemplo, isso provoca um evento. Se existir um trecho de programa associado a esse evento (um procedimento de evento), esse trecho ser executado. Seno, o evento no vai fazer nada. Clique no boto Adicionar para selecion-lo. No Object Inspector, clique no marcador de pgina "Events". Essa pgina lista quais eventos so reconhecidos pelo componente. O primeiro deles, OnClick, acontece quanto o boto recebe um clique do mouse. Clique duas vezes na coluna da direita, e o Delphi vai abrir o editor de cdigo, contendo o seguinte texto: procedure TForm1.Button1Click(Sender: TObject); begin end; O cursor est posicionado entre os delimitadores begin e end, indicando onde voc deve escrever o cdigo, que ser executado ao clicar no boto Adicionar. Escreva o seguinte (diferenas entre maisculas e minsculas no importam): ListBox1.Items.Add(Edit1.Text);
13
Edit1.Clear; Pressione a tecla [F12] para voltar ao formulrio. Clique no boto Ordenar e depois clique duas vezes no valor do evento OnClick. Isso vai gerar um tratador de evento para o boto Ordenar. Escreva o seguinte entre o begin e o end: ListBox1.Sorted := True; Finalmente retorne ao formulrio, selecione o boto Limpar e siga o mesmo processo. Digite o seguinte cdigo: ListBox1.Clear; ListBox1.Sorted := False;
Testando o Programa
Agora execute o programa clicando no boto . Voc pode digitar um valor no quadro de texto, e clicar no boto Adicionar (ou teclar [Enter]). O item digitado ser acrescentado lista. Depois de acrescentar alguns itens, clique em Ordenar. A lista ser colocada em ordem alfabtica. Para esvaziar a lista, clique em Limpar.
Salvando o Programa
Para que voc possa usar esse programa mais tarde, clique em File|Save All (menu File, item Save All) ou no boto da SpeedBar. O Delphi vai pedir um nome para o arquivo do formulrio. Digite AULA1 e clique Ok. Depois o Delphi vai perguntar o nome do arquivo de projeto. Digite AULA1P e clique Ok (no use o mesmo nome que o formulrio). Nota: Voc tambm pode clicar no formulrio ou no editor de cdigo com o mouse, mas geralmente o mtodo mais rpido de alternar entre os dois usar a tecla [F12].
Ambiente de Programao
O Delphi possui um ambiente integrado de desenvolvimento (IDE - Integrated Development Environment) onde voc utiliza a maioria das funes de desenvolvimento. Nesse ambiente voc projeta o programa e depois executa o programa para testar o seu funcionamento. Sempre que voc executa o programa, o Delphi compila o programa, isto , gera um programa executvel com cdigo de mquina a partir do programa fonte que voc criou. Esses programas executveis se tornam independentes do Delphi e podem rodar separadamente.
Eventos e Procedimentos
Programas DOS convencionais seguem um fluxo seqencial, em que um comando segue o outro de forma definida pelo programador. O usurio deve agir de acordo com os "modos" de operao do programa e saber o momento certo para entrar com comandos. Programas em uma interface multitarefa, como o Windows, apresentam todas as opes ao usurio, para que ele possa selecion-los na ordem em que desejar. O Windows intercepta as aes realizadas pelo usurio e informa ao programa onde, como e quando elas acontecem. O programa deve reagir de forma apropriada nos momentos determinados pelo usurio. Cada resultado de uma ao do usurio chamada de evento, por exemplo: clique do mouse, digitao de uma tecla, etc.
14
Como conseqncia, o programa no mais um bloco nico, mas dividida em pequenas sees, cada uma responsvel pela tarefa a realizar em resposta a um determinado evento. Essas sees so os procedimentos de evento do Delphi. Cada evento associado a um componente e cada componente tem uma lista de eventos que so acionados por ele em situaes especficas (o Object Inspector mostra esta lista na pgina Events). Com isso, o projeto de um programa feito iniciando pelo projeto de sua interface (seus componentes) e depois escrevendo-se os procedimentos de evento. No obrigatrio definir todos os eventos para um componente. Se no existe um procedimento para um evento especfico, simplesmente no acontece nada para aquele evento. Como veremos mais tarde, alm dos procedimentos de evento, voc pode dividir o seu programa, usando rotinas auxiliares. Nota: para melhor utilizao do ambiente de programao e da linguagem, consulte o help do Delphi. Os procedimentos de evento so armazenados na unidade, que um arquivo de texto associado ao formulrio. Voc pode editar todas as unidades no editor de cdigo do Delphi.
Componentes
A paleta de componentes lista tipos de componentes que podem ser utilizados no programa, como botes de pressionar, barras de rolagem, grades de dados e editores de texto. Para criar um componente, voc seleciona o cone correspondente e depois clica no formulrio para coloc-lo. Voc tambm pode cri-lo j com o tamanho desejado, pressionando o boto do mouse sobre o formulrio e arrastando para definir o tamanho. Nota: todos os componentes so descritos em detalhe no Help do Delphi, com todas suas propriedades, mtodos e eventos. Clique em um cone de componente e pressione F1 para ver o texto de help sobre ele. Note que h mais pginas do que cabe na tela em dado momento. Para ver as pginas que restantes, como Dialogs, Midas, Win 3.1, Samples e ActiveX, clique nos botes ficam na extremidade direita da janela do Delphi. Alguns componentes no aparecem para o usurio durante a execuo do programa, apesar de aparecer no formulrio, e serem manipulados pelo cdigo do programa. So os componentes no-visuais (veremos alguns deles no decorrer do curso). Mas a maioria aparece como um objeto de interface durante a execuo. So os controles (ou componentes visuais). importante lembrar que todo controle um componente, mas nem todo componente um controle. O prprio formulrio tambm considerado um componente, embora seja tratado de forma diferente, e geralmente contm vrios outros componentes.
15
formatado, barras de progresso, exibio de animaes, exibio de dados em rvore ou em forma de cones, barras de status e de ferramentas etc. System: componentes que utilizam funes avanadas do sistema operacional, como temporizao, multimdia, OLE e DDE. Internet: componentes para acesso aos recursos e protocolos da Internet, como criao de pginas Web dinmicas, acesso aos protocolos FTP, NNTP, POP, SMTP, TCP, UDP. Data Access: componentes para acesso a banco de dados. Data Controls: componentes visuais para mostrar dados em aplicaes de bancos de dados. So semelhantes aos componentes padro (Standard). Decision Cube (apenas Delphi Client/Server): componentes para anlise multidimensional de dados, com capacidades de tabulao cruzada [crosstab], criao de tabelas e grficos etc. QReport: QuickReport um gerador de relatrios que acompanha o Delphi. Os componentes desta pgina permitem desenhar o seu relatrio dentro do Delphi. Dialogs: O Windows tem caixas de dilogo comuns, como veremos, que facilitam mostrar uma interface padro dentro do seu programa para as tarefas comuns, como abrir e salvar arquivos, impresso, configurao de cores e fontes etc. Esta pgina tem componentes que permitem utilizar essas caixas de dilogo comuns. Midas (apenas Delphi Client/Server e Enterprise) : componentes utilizados para criar aplicaes multi-tiered. Win3.1: Esta pgina contm controles considerados obsoletos, que esto disponveis apenas para compatibilidade com programas antigos. No crie programas novos que utilizam esses controles. Samples: contm exemplos de componentes para que voc possa estud-los e aprender a criar seus prprios componentes. O cdigo fonte desses exemplos est no subdiretrio SOURCE\SAMPLES do diretrio de instalao do Delphi. ActiveX: um componente ActiveX um tipo de componente que pode ser criado em outra linguagem e utilizado no Delphi. Esta pgina contm alguns exemplos de componentes ActiveX prontos para utilizar, que tm funes de grficos, planilha, etc.
Propriedades
Componentes tm propriedades [properties], que definem suas caractersticas especficas e eventos, que so acontecimentos externos, geralmente relacionados com aes do usurio. Por exemplo o formulrio tem como propriedades o ttulo da janela (Caption), sua cor (Color), sua posio na tela (Left e Top). Um quadro de texto tem uma propriedade que define o texto que este contm (Text), entre outras. Quando o usurio clica com o mouse em um controle, isso causa um evento OnClick, e quando ele pressiona uma tecla, causa um evento OnKeyDown (entre outros). Para alterar propriedades durante o projeto da interface, voc seleciona o componente desejado (por exemplo Edit1), depois seleciona a propriedade desejada (por exemplo, Text) no Object Inspector e digita seu valor. Durante a execuo do programa, o cdigo pode alterar uma propriedade dinamicamente (em resposta a um evento). Para isso, basta inserir no cdigo de programa um comando como o seguinte: Edit1.Text := 'Bem-vindo ao Delphi'; Nota: se voc clicar em uma propriedade e teclar [F1], o Delphi mostrar o texto de help relacionado quela propriedade.
Mtodos
Mtodos so nomes para aes executadas por um componente. No programa anterior, por exemplo, usamos o mtodo Clear, que quando executado, limpa o contedo de um controle. Por exemplo, no programa anterior, o procedimento de evento do boto Adicionar faz: Edit1.Clear;
16
Quando esse comando executado, o controle esvaziado. Repare que todo mtodo chamado usando-se primeiro o nome do componente, depois o nome do mtodo, da mesma forma que uma propriedade. Mtodos s tem utilidade no cdigo do programa, por isso no aparecem no Object Inspector (mas veremos mais tarde que possvel consultar a lista de mtodos disponveis).
Objetos
Componentes so apenas um tipo de objetos, que um termo bastante utilizado no Delphi. O prprio nome Object Pascal indica que se trata de uma linguagem orientada a objetos. Um objeto, numa definio prtica, uma rea de memria separada, contendo dados (variveis) e o cdigo que manipula esses dados. No caso de um componente, os dados aparecem como propriedades e o cdigo que os manipula composto de mtodos. Basicamente todo objeto contm propriedades e mtodos, mesmo que ele no possa ser colocado num formulrio e editado. Mais tarde veremos vrios exemplos de objetos que no so componentes
Resumo
Para dominar a programao em Delphi, preciso conhecer os componentes da VCL, os objetos das bibliotecas do Delphi e a linguagem Object Pascal, que o fundamento no qual tudo se baseia.
Projetos
O Delphi trata cada aplicativo que voc cria como um projeto, que uma lista dos arquivos necessrios para construir um programa. Para saber quais so os formulrios, as unidades correspondentes, etc., o Delphi nos fornece o Project Manager, que pode ser acessado atravs
17
do Menu View, opo Project Manager. A janela de ttulo do Delphi sempre tem, no ttulo, o nome Delphi - Nome do projeto. Um projeto em Delphi se compe de: Formulrios: um formulrio uma janela que projetamos no Delphi. Normalmente toda aplicao contm um ou mais formulrios. Cada formulrio tem uma unidade associada, que um arquivo contendo todo o cdigo associado a eventos; Unidades independentes: uma unidade independente contm cdigo do Delphi que no est necessariamente associado a nenhum formulrio ou controle em particular. Unidades independentes geralmente contm variveis e rotinas usadas por toda aplicao. Lembre-se que um projeto apenas uma lista dos arquivos usados para construir o programa, mas no os contm propriamente.
18
Fecha o arquivo atual. Close Fecha todos os arquivos e o projeto atual. Close All Alm desses comandos, existem cones na SpeedBar que podem ser usados para essas tarefas: Equivale a File|Open, mas mostra apenas os arquivos de projeto. (Open project) O mesmo que File|Save all (Save all) O mesmo que File|Open Project... (Open Project) O mesmo que File|Save (Save ) Adiciona um arquivo ao projeto atual. (Add file to project) Remove um arquivo do projeto atual. (Remove file from project)
Grupos de Projetos
O delphi 4.0 permite trabalhar com mais de um projeto aberto, esses projetos podem ser definidos em um grupo. No menu View|Project Manager informado os projetos que pertencem a um determinado grupo.O arquivo de um grupo tem a extenso ".BPG"
Edies do Delphi
O Delphi est atualmente na verso 4. Essa verso geralmente compatvel com programas desenvolvidos nas verses anteriores, embora alguns necessitem de modificao para funcionar, especialmente os feitos para a verso 1.0. importante saber tambm que existem vrias edies diferentes do Delphi, desde a Standard (a mais simples), passando pela Professional, que tem mais recursos, at a edio Client/Server Suite, mais sofisticada e com recursos teis para grandes empresas: Standard: muito limitada em recursos. Indicada apenas para quem tem interesse em desenvolvimento de pequenos programas ou para fins de aprendizado. Professional: inclui mais recursos que a edio Standard. Recomendada para desenvolvedores profissionais. Client/Server : inclui mais recursos que a Professional, especificamente voltados para grandes desenvolvedores que utilizam bancos de dados no padro cliente/servidor.
19
Note que o Delphi 4 s funciona para ambientes de 32 bits, ou seja, Windows 95/98/etc. e Windows NT. Se voc quiser desenvolver programas compatveis com Windows 3.x, voc deve utilizar a verso 1.0.
20
21
Exemplo: Calculadora
O nosso objetivo criar uma calculadora simples, que apenas soma dois nmeros fornecidos e mostra o resultado, semelhante figura:
Criando os Componentes
Para comear, inicie o Delphi ou, se o Delphi estiver aberto, crie um novo projeto com File |New Application e altere a propriedade Caption da janela principal (Form1) para "Calculadora". Agora grave o projeto usando File | Save All no menu do Delphi. D os nomes de CALC ao formulrio e CALCP ao projeto. Isso vai salvar trs arquivos em disco, como j vimos: CALC.PAS A unidade unidade associada ao formulrio CALC.DFM Contm a definio do formulrio e seus controles. CALCP.DPR O arquivo de projeto, que lista os nomes dos outros. D dois cliques no cone Edit para criar um quadro de edio no formulrio. Mova-o at o topo do formulrio e altere a sua propriedade Name, para "editOperando1". A propriedade Name determina o nome que ser usado no programa para manipular esse componente, que ser usado para receber o primeiro operando digitado. Repita as mesmas aes para criar outro quadro de texto para o segundo operando. Ele dever ficar logo abaixo do primeiro. D o nome "editOperando2". Agora crie um boto de comando, com um clique duplo na ferramenta . Altere o seu tamanho para ficar igual ao dos quadros de texto. Nota: Quando voc cria um componente, ele recebe um nome default como Edit1, Button1, etc. recomendvel dar um nome mais descritivo para que seja mais fcil entender o programa mais tarde. Nota: No curso adotaremos um padro para nomes de componentes: um prefixo de trs ou quatro letras que diz o tipo de componente (edit para Edit, btn para Button, etc.) seguido de um nome descritivo (no caso, Operando1). Veremos que esse padro facilita a compreenso dos programas.
Altere sua propriedade Caption para "=" (sinal de igual). Altere Name para "btnCalcula". Finalmente crie um quadro de texto, posicionando-o abaixo do boto de comando, que vai conter o resultado. D o nome de "editResultado".
22
Agora, para mostrar o sinal de "+" vamos usar um componente Label (rtulo), que apenas mostra um texto para o usurio, no permitindo alterao. Selecione o cone e desenhe um rtulo esquerda do editOperando2, como na figura. Altere sua propriedade Caption para conter um sinal de +. Para fazer com que esse sinal fique maior, selecione a propriedade Font, que corresponde s caractersticas do texto, e clique duas vezes do seu lado direito. Selecione "MS Sans Serif" na lista de fontes e um tamanho maior na lista "Tamanho". Depois clique Ok.
Tratando os Eventos
A interface da calculadora est pronta, mas ela ainda no executa a funo desejada. Precisamos acrescentar cdigo que leia os dois operandos, some os seus valores e coloque o resultado no ltimo quadro de texto. Clique duas vezes no boto 'btnCalcula', no formulrio. Isso vai criar um tratador de eventos para o evento padro do boto, que o evento OnClick. O Delphi vai gerar o seguinte cdigo: procedure TForm1.btnCalculaClick(Sender: TObject); begin end; Para fazer o clculo precisaremos de variveis. Uma varivel uma rea de memria que tem um nome e armazena um determinado valor. No Delphi, toda varivel tambm tem um tipo, que determina quais os valores que ela pode conter. Depois veremos todos os tipos de dados em detalhes, mas por enquanto, usaremos o tipo de dados 'double', que permite armazenar valores numricos com parte fracionria, com a preciso de 15 a 16 dgitos significativos. Nota: Voc pode tambm selecionar o evento no Object Inspector e criar o tratador a partir do nome dele, mas para o evento padro, mais rpido um clique duplo no prprio componente. Variveis so declaradas com a palavra var, informando-se o nome e o tipo das variveis. Antes da palavra reservada begin, acrescente o seguinte: var op1, op2: double; res: double; Isso declara trs variveis: 'op1', 'op2' e 'res', todas do tipo double. Repare que duas variveis do mesmo tipo podem ser declaradas separando-as por vrgula antes do tipo ou em uma declarao separada.No necessrio repetir o var para vrias declaraes, pois elas terminam quando se encontra o begin. Agora vamos utilizar essas variveis para obter os valores digitados pelo usurio. Para ler o valor digitado em um controle Edit, devemos ler a propriedade Text, s que essa propriedade tem um valor alfanumrico (pode conter letras e nmeros), logo precisamos convert-la para numrico. Isso feito com a funo StrToFloat: op1 := StrToFloat(editOperando1.Text); op2 := StrToFloat(editOperando2.Text); Depois basta somar as variveis e mostrar o resultado, utilizando novamente uma funo de converso: res := op1 + op2; editResultado.Text := FloatToStr(res); O resultado final, com todo o cdigo acrescentado, ser o seguinte: procedure TForm1.btnCalculaClick(Sender: TObject); begin op1 := StrToFloat(editOperando1.Text); op2 := StrToFloat(editOperando2.Text); res := op1 + op2; editResultado.Text := FloatToStr(res); end; Repare que foi utilizada a identao (deslocamento direita) dos comandos, mas isso no obrigatrio no Delphi. Foi utilizado apenas para facilitar a legibilidade. Nota: Nomes de variveis em Object Pascal podem ter at 63 caracteres e podem conter letras (A-Z, a-z), nmeros e o caractere '_'. O primeiro caractere no pode ser nmero. O Object Pascal no diferencia maisculas de minsculas (no case-sensitive).
23
Executando o Programa
Execute o programa com o boto ou a tecla [F9]. Digite um nmero no editOperando1 e outro no editOperando2 e depois clique no btnCalcula. Repare que voc pode usar a tecla [Tab] para passar de um controle para outro utilizando o teclado (e no [Enter], como no DOS). O controle que responde s teclas em determinado momento tem o foco de teclado. Cada controle indica o foco de forma diferente. Por exemplo, um controle Edit mostra o cursor de texto quando ele tem o foco, j um controle Button mostra um retngulo tracejado em volta do texto. Como veremos, esta ordem de foco pode ser alterada.
Melhoras de Interface
Alguns detalhes podem ser melhorados: primeiro, o quadro de edio 'editResultado' no deveria receber o foco quando o usurio pressiona [Tab] e no deveria permitir edio do texto, pois no faz muito sentido. Para isso, selecione o controle e altere sua propriedade TabStop para False. Voc pode fazer isso selecionando o valor a partir da lista (com o boto de seta) ou com um clique duplo no valor da propriedade, que alterna de True para False. Essa propriedade, quando False, faz com que o controle seja "pulado" pela tecla [Tab]. Tambm altere a propriedade ReadOnly para True, o que faz com que o controle no permita edio de seu valor. Outra mudana: como o usurio no usar a tecla [Enter], podemos fazer com que ela acione o boto "=". Basta alterar a propriedade Default do boto 'btnCalcula' para True (verdadeiro). Isso faz com que ele seja o boto default, que sempre acionado quando o usurio tecla [Enter]. Execute o programa e teste as modificaes. Ao executar o projeto podemos observar que os quadros de edio 'editOperando1', 'editOperando2' e 'editResultado' aparecem com seus respectivos nomes , o ideal seria aparecer inicialmente sem nenhuma informao, para fazer esta modificao vamos retornar ao projeto e alterar a propriedade Text de cada componente edit . a propriedade Text que indica o contedo do componente naquele momento, ao criar o componente edit e modificar a propriedade Name o delphi automaticamente coloca o mesmo contedo desta propriedade na propriedade Text, caso esta no tenha sido modificada antes.
Salvando o Projeto
Para salvar o projeto e todos os arquivos, basta usar File|Save All ou clicar no boto da SpeedBar. Com isso o Delphi vai salvar todas as alteraes feitas no projeto, como foi informado o nome do projeto e da unit ele no ir pedir novamente.
24
25
Tipos de Dados
Toda varivel tem um tipo, que determina quais os valores que voc pode colocar nessa varivel e quais as operaes que podem ser executadas sobre ela. Uma varivel de um tipo numrico, por exemplo, s pode receber valores numricos. Esses valores podem ser constantes, valores de outras variveis, ou expresses com operaes sobre valores. Para colocar um valor em uma varivel, usa-se o operador de atribuio: ':=' (dois-pontos-igual), que lido como "recebe". Por exemplo: procedure TForm1.Button1Click(Sender: TObject); var a: integer; { 'a' uma varivel do tipo Integer } b: integer; { 'b' idem } begin a := 2; b := a; b := b + 3; end; Geralmente, com algumas excees, uma varivel de um determinado tipo s pode receber valores deste tipo. No permitido, por exemplo, o seguinte: a := 'Nome'; ...pois apenas valores numricos podem ser colocados na varivel 'a'. Existem vrios tipos de dados numricos, e cada um tem uma determinada faixa de valores e ocupa um certo espao de memria. No permitido colocar em uma varivel um valor que esteja fora da faixa do seu tipo.
Tipos Numricos
A linguagem Object Pascal tem vrios tipos de dados para variveis numricas, que so os seguintes: Tipo Bytes Faixa de Valores Preciso(dgitos) 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 bilhes a 2 bilhes N/A (-2.147.483.648 a 2.147.483.647) Longint 4 -2.147.483.648 a 2.147.483.648 N/A Cardinal 4 0 a 4.294.967.295 N/A Longword 4 0 a 4.294.967.295 N/A Int64 8 - 2 63 a 2 63 N/A Tipos Reais Single Real48 Real Double Comp Currency Extended 1.5x10-45 a 3.4x1038 2.9x10-39 a 1.7x1038 5x10-324 a 1.7x10308 5x10-324 a 1.7x10308 -263 a 263
-922337203685477.5808 a 922337203685477.5807
4 6 8 8 8 8 10
3.6x10-4951 a 1.1x104932
*Nota: No Delphi 4, o tipo Real idntico ao tipo Double. No Delphi 3, o tipo Real tem uma faixa de valore menor que o Double e equivale ao tipo Real48 do Delphi 4. No recomendvel utilizar Real48, porque ele muito mais lento para clculos. A coluna "bytes" diz quantos bytes de memria so ocupados por uma varivel do tipo. Quanto maior a faixa de valores, em geral, maior o espao de memria. Os tipos numricos se dividem em tipos inteiros (ou integrais), que s permitem valores inteiros e tipos reais (ou de ponto flutuante [floating point]), que permitem valores com parte fracionria. Uma forma de entender a diferena que tipos inteiros so usados para contagem de
26
elementos, enquanto tipos reais so usados para medir alguma coisa. E essa medida nem sempre exata. Ao fazer clculos com variveis reais, nem sempre o resultado igual ao esperado. Por exemplo: var fracao, a, b: real; {'real' um tipo real} begin a := 1.0; { o mesmo que 1 } fracao := a / 3; b := fracao * 3; if a = b then ... { faz alguma coisa } end; Teoricamente no programa, 'a' igual a 'b', mas como tipos reais no representam valores exatos, a igualdade no exata. A varivel 'b' pode ter um valor de 0.99999999..., que ao ser comparado, no igual a 1.0. Cada tipo real tem uma certa preciso, indicada na tabela, que diz quantos dgitos significativos (dgitos excetuando zeros esquerda e direita) a varivel pode guardar, sem perda de preciso nos clculos. Assim, importante lembrar que os valores guardados em um desses tipos nem sempre exato. Geralmente os tipos inteiros so mais eficientes para clculos, e tambm mantm valores exatos para qualquer operao, desde que o resultado no saia da sua faixa de valores. Os tipos mais utilizados so smallint, para valores inteiros pequenos, integer ou Longint para valores inteiros maiores, e Double para valores reais com uma preciso razovel. Os tipos Shortint e Byte so utilizados quando preciso guardar um contador bem pequeno e necessrio economizar memria.Quando os tipos integer ou longint no so suficientes podemos usar os tipos longWord e int64 que existe somente nesta verso. O tipo Comp considerado como real, mas ele permite apenas valores inteiros. Ele til para valores monetrios.
O tipo Char
O tipo Char permite criar variveis que guardam caracteres individuais, como letras, dgitos, sinais de pontuao e caracteres de controle. Cada varivel do tipo Char s pode conter um caractere. Caracteres comuns (imprimveis) so representados entre aspas simples (apstrofos): var minhaVariavel: Char; ... ... minhaVariavel := 'A'; Um caractere tambm pode ser representado atravs do cdigo ASCII/ANSI correspondente. Isso til principalmente com caracteres de controle, que no podem ser impressos nem digitados normalmente no programa, como caracteres de backspace, fim de linha, retorno de carro etc. Por exemplo, para guardar o caractere 13 (retorno de carro), usa-se a sintaxe: minhaVariavel := #13; Se o cdigo estivesse numa varivel em vez de uma constante, no pode ser usada essa sintaxe. Nesse caso, pode-se usar a funo Chr: codigoASCII := 13; minhaVariavel := Chr(codigoASCII); Nota: para ver os caracteres da tabela ANSI (exceto os de controle), use o aplicativo Mapa de Caracteres do Windows (em Iniciar | Programas | Acessrios).
O tipo String
Para guardar mais de um caractere, preciso usar o tipo String. Um valor constante do tipo String representado entre apstrofos, como por exemplo: var nome: string; begin nome := 'Joo da Silva'; Uma varivel string normalmente no tem limite de tamanho definido. O espao de memria que ela ocupa muda dinamicamente de acordo com o contedo atribudo a ela, por exemplo: nome := '123'; {3 caracteres}
27
nome := 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'; {26 caracs.} nome := ''; {zero caracteres} No ltimo caso, tem-se uma string vazia, que representada por '' (apstrofos sem caracteres dentro), que ocupa zero caracteres. Ela usada para "limpar" o contedo de uma varivel. Nota: O Windows usa uma tabela de caracteres chamada tabela ANSI, que associa um cdigo numrico a cada caractere. Nota: o Windows permite caracteres acentuados e especiais, como , , , , , , etc. Mas uma varivel string pode ser declarada com um tamanho fixo, da seguinte forma: var nome: string[50]; telefone: string[10]; Nesse caso, a varivel ocupa um espao fixo de memria, de acordo com o tamanho declarado. No exemplo, nome ocupa 50 caracteres e telefone ocupa 10. Se voc tentar atribuir mais caracteres do que cabe na varivel, os caracteres restantes so ignorados. Se voc atribuir menos, o tamanho lgico da string passa a ser menor que o tamanho fsico. O Object Pascal usa um byte a mais para armazenar o tamanho lgico. Voc pode concatenar (juntar) duas ou mais strings com o operador +. Por exemplo: var prefixo, linguagem, titulo: string; begin prefixo := 'Curso'; linguagem := 'Delphi'; titulo := prefixo + ' de ' + linguagem; { O resultado uma string 'Curso de Delphi' } Para obter caracteres individuais de uma string, voc pode usar o nome da varivel e mais um valor entre colchetes. Por exemplo, se voc quiser guardar o 7 caractere do nome numa varivel char, basta fazer: c := nome[7]; Existem vrias propriedades que tambm so do tipo String, como Caption e Text, por exemplo. Assim, possvel atribuir uma constante ou varivel do tipo String para elas, por exemplo: btnIniciar.Caption := '&Iniciar'; memoTempoTotal.Text := s; Nota: existem vrias funes de manipulao de strings, por exemplo, para obter uma parte de uma string. Consulte o help do Delphi e procure por 'String manipulation functions'.
O tipo Boolean
Vrias propriedades (e variveis tambm) podem conter os valores True (verdadeiro) e False (falso), indicando uma condio lgica ou um "flag" (ligado/desligado, habilitado/desabilitado, sim/no). Para isso utiliza-se o tipo Boolean, que s tem dois valores possveis: True e False. Por exemplo: tmrMarca.Enabled := False; O Delphi tambm utiliza o tipo Boolean internamente, ao fazer qualquer comparao lgica, em um comando if, por exemplo. E uma varivel do tipo Boolean sozinha j uma condio lgica, portanto pode ser usada em um comando if diretamente, por exemplo: var ValorCorreto: Boolean; begin ... if ValorCorreto then ... ... { Enabled uma propriedade do tipo Boolean } if tmrMarca.Enabled then ... ... end;
O tipo TDateTime
Para trabalhar com datas em Delphi, voc pode usar o tipo TDateTime. Veremos as operaes de data mais em detalhe em Manipulao de datas.
28
Funes de Converso
Qualquer varivel numrica pode receber um valor do mesmo tipo ou de um outro tipo numrico, exceto que uma varivel inteira (Integer, Longint, Word etc.) no pode receber um valor real, pois este pode conter uma parte fracionria. Por exemplo: var a: integer; b: longint; x: double; y: extended; begin b := 10; a := b; {ok: inteiro recebe inteiro} x := a; {ok: real recebe inteiro} y := x; {ok: real recebe real} x := 3.7; b := x; {errado: inteiro recebe real} end; Nesse caso preciso usar uma funo de converso, que ou descarta a parte fracionria (funo trunc) ou arredonda o valor (funo round): x := 3.7; a := trunc(x); {a vai valer 3} b := round(x); {b vai valer 4} Existem vrias funes que convertem valores de tipos numricos para o tipo String e viceversa. Ns j vimos algumas em programas-exemplo: var varReal: double; varInteira: integer; varString: string; begin { de String para numrico: } varReal := StrToFloat(varString); varInteira := StrToInt(varString); varInteira64 := StrToInt64(varInteira64); { de numrico para String: } varString := FloatToStr(varReal); varString := IntToStr(varInteira); {VarInteira pode ser de qualquer tipo inteiro,inclusive int64 } end; Alm dessas, existe a funo Str, do Pascal padro, que converte um nmero qualquer para String, permitindo especificar uma largura de campo (o nmero alinhado direita com espaos) e a quantidade de casas depois da vrgula. Por exemplo: segundos := 34.749; Str(segundos:7:2, s); A varivel 's' vai ser preenchida com uma string 'oo34.75' (cada o representa um espao em branco). Ou seja, vai conter no mnimo 10 caracteres, com os dgitos alinhados direita e duas casas depois da vrgula (casas a mais so arredondadas).
Operaes Aritmticas
Os tipos de dados inteiros suportam as operaes aritmticas usuais: soma: a := x + y; subtrao: a := x - y; multiplicao: a := x * y; diviso: a := x / y;
29
Se os dois operandos so do mesmo tipo, o resultado desse tipo. Se um deles tem uma faixa de valores maior (por exemplo, um Double e um Integer), o resultado ser do tipo deste operando (no exemplo, Double). Para os nmeros inteiros o resultado ser do tipo int64 somente se tiver uma varivel deste tipo, caso contrrio o resultado ser do tipo integer. Se os dois operandos so inteiros, o resultado ser inteiro e pode ser atribudo para uma varivel inteira. Uma exceo que no caso da diviso, o resultado sempre real, mesmo quando os dois operandos so inteiros. Portanto, no permitido fazer: a := b / c; quando 'a' uma varivel inteira. Mas pode-se utilizar uma funo de converso, como trunc: a := trunc( b /c ); ou usa-se o operador de diviso inteira div (os dois operandos dever ser inteiros), por exemplo: b := 13; c := 4; a := b div c; {retorna a parte inteira da diviso = 3} Existe tambm o operador mod, que calcula o resto da diviso: x := b mod c; {retorna o resto de 13 div 4, que = 1} Expresses podem ser combinadas com vrios operadores e operandos. Multiplicao e diviso so executadas primeiro, depois soma e subtrao, a menos que sejam usados parnteses, por exemplo: x := a + b * c; {multiplica 'b' e 'c' e soma com 'a'} y := (a + b)*c; {soma 'a' e 'b' e multiplica por 'c'}
Tipos Ordinais
Um tipo de dados considerado um tipo ordinal quando existe uma seqncia definida entre seus elementos, ou seja, a partir de um elemento sempre possvel passar para o prximo elemento do tipo. Os tipos ordinais predefinidos pela linguagem (veremos que voc pode criar outros) so: Todos os tipos inteiros (Integer, Word, Cardinal, Longint,Enumerados...); O tipo Char (os caracteres so ordenados pela tabela ASCII/ANSI); O tipo Boolean (s tem dois elementos: False,True nessa ordem). Notas: Os tipos reais no so considerados tipos ordinais. Algumas operaes podem ser feitas com qualquer tipo ordinal. A funo succ retorna o prximo elemento do tipo, enquanto pred retorna o anterior: var c1, c2: char; x, y: integer; a, b: boolean; begin c1 := 'G'; c2 := succ(c1); {vai ser = 'H'} c2 := pred(c1); {vai ser = 'F'} x := 299; y := succ(x); {succ(x) = x + 1 e pred(x) = x - 1} a := False; b := succ(a); {vai ser = True} end; Se voc chamar succ para o ltimo elemento da seqncia ou pred para o primeiro elemento, isso vai causar um erro de execuo (por exemplo, 'succ(True)' no permitido). A funo ord retorna a posio numrica do elemento dentro do tipo. No caso de um nmero inteiro, retorna o prprio nmero, portanto no tem utilidade prtica. No caso de um caractere, retorna o cdigo ASCII (ANSI) do caractere, que sua posio na tabela ASCII (ANSI): x := ord('G'); {x vai ser 71} No caso do tipo Boolean, ord(False) = 0 e ord(True) = 1. Isso pode ser usado para converter uma condio lgica em valor numrico. Mais tarde veremos outras operaes que podem ser executadas em tipos ordinais. Notas : As funes succ e pred podem ser utilizadas para variveis do tipo int64, mas o mesmo no vlido para a funo ord.
30
Escopo de Variveis
O lugar onde declarada uma varivel determina o escopo de uma varivel, ou seja, qual a regio do programa onde a varivel pode ser acessada e o tempo de vida da varivel, ou seja, qual o intervalo de tempo durante o qual ela mantm seu valor. Qualquer varivel s pode ser utilizada no programa depois do ponto onde foi declarada.
Variveis Locais
Uma varivel declarada dentro de um procedimento uma varivel local. Ela s pode ser utilizada dentro do procedimento (o escopo da varivel o corpo do procedimento). O tempo de vida de uma varivel local o tempo durante a execuo do procedimento. Quando a execuo do procedimento iniciada, a varivel est indefinida, ou seja, seu valor pode ser qualquer dado que existia anteriormente na memria. Se esse valor for utilizado, os resultados so imprevisveis. Depois que o procedimento termina, a memria ocupada pela varivel liberada, e seu valor anterior perdido. Como j vimos, variveis locais so declaradas com a palavra var, logo aps o cabealho do procedimento, mas antes do begin que inicia os comandos: procedure btnCalculaClick(Sender: TObject); var op1, op2, res: double; begin ... end;
Constantes
Constantes so valores que podem ser colocados em variveis, usados em expresses etc. Uma constante literal um valor sem nome, escrito explicitamente, como os seguintes: 20 3.5 (constantes numricas - integer e double) 'Testando' (constante do tipo string) False True (constantes do tipo boolean) 'x' #8 (constantes do tipo char)
31
O tipo de dados de uma constante determinado pela forma desta. Nmeros sem parte fracionria so considerados constantes inteiras (isso se o nmero couber na faixa de valores de um tipo inteiro). Uma constante inteira tambm pode ser especificada como um valor hexadecimal, prefixado por '$', por exemplo: x := $2F3; Nmeros hexadecimais contm tambm os dgitos A at F, alm de 0 a 9. Uma constante real tambm pode ser escrita em notao cientfica, especificando-se um valor e uma potncia de 10: y := 3.5e4; { = 3.5 x 104 = 35000 } z := 2.78e-6; { = 2.78 x 10-6 = 0.00000278 } Voc pode criar constante especificando o tipo que esta constante ir retornar , por exemplo: const Inteiro64 = int64(17) Desta forma o tipo que a constante ir retornar int64. Voc tambm pode criar constantes nomeadas, que so simplesmente substitudas pelos valores correspondentes durante a compilao do programa. Elas facilitam a manuteno do programa, quando um valor utilizado em vrios lugares. Para isso, usa-se a declarao const: const TAMANHO = 30; METADE = TAMANHO/2; PI = 3.1415926536; MENS_ERRO = 'Valor incorreto. Digite novamente.'; > Constantes nomeadas so utilizadas como qualquer outra constante: x := TAMANHO * 8; angulo := PI*graus/180; Mas no so variveis, portanto no podem receber outro valor: TAMANHO := 15; { erro de compilao } Da mesma forma que variveis, uma constante pode ser local (se declarada em um procedimento) ou global (se declarada fora).
32
33
Estruturas de Deciso
O Comando if...then...else...
Ns j vimos o comando if em vrias situaes. A sua sintaxe bsica : if condio then comando1 else comando2; { OU sem o else: } if condio then comando1; A identao de comandos, ou a separao do comando em vrias linhas no so obrigatrias em nenhuma situao no Object Pascal. Mas geralmente um comando if escrito em vrias linhas, para maior legibilidade: if condio then comando1 else comando2; Dica: No editor de cdigo, para identar um bloco de comandos (deslocar direita), use [Ctrl+Shift+I]. Para deslocar esquerda, use [Ctrl+Shift+U]. Nessa sintaxe, condio qualquer expresso que gere um resultado do tipo Boolean (True para verdadeiro, False para falso), podendo ser uma nica varivel booleana, embora na maioria das vezes seja construda usando operadores de comparao, como '=', '>' etc. Note que no permitido o ';' (ponto-e-vrgula) logo depois do then ou logo antes ou depois do else. S pode haver ';' depois do fim do comando if. Se no houver o else, o ';' colocado depois do comando1. Por exemplo: if memoEditor.SelLength <> 0 then menuEdiRecortar.Enabled := True else menuEdiRecortar.Enabled := False; Quando, em lugar de comando1 ou comando2 preciso executar vrios comandos, usa-se os delimitadores begin e end para criar um comando composto. Um comando composto tratado pelo Object Pascal como um nico comando, por exemplo: if condio then begin comando1; comando2;
34
end else begin comando3; comando4; end; Dentro do comando composto, os comandos so separados por ';', mas fora dele se aplicam as regras do if. Um comando if pode ser usado dentro de outro, mas isso pode dificultar o entendimento se um deles inclui uma clusula else. Nesse caso o else fica ligado ao if mais prximo. Mais de uma condio pode ser usada no if, combinando-as com and (e), or (ou) e not (no). Mas nesse caso, so obrigatrios parnteses em volta das condies: if (Key < '0') or (Key > '9') then Key := #0; O operador and tem precedncia sobre o or, e o not tem precedncia sobre os dois, portanto preciso levar isso em conta em condies mais complexas, e utilizar parnteses para especificar o que se deseja avaliar primeiro: if ((Key < '0') or (Key > '9')) and (Key <> #8) then Key := #0; E o operador not pode ser usado para inverter o resultado de uma condio: if ((Key < '0') or (Key > '9')) and not (Key = #8) then Key := #0; Dica: para encontrar um fecha-parnteses perdido, coloque o cursor antes do abre-parnteses e tecle [Ctrl+Q+[ ] (ctrl+Q+abre-colchetes).
O Comando case...of...
Muitas vezes preciso comparar uma varivel com vrios valores. Isso pode ser feito com vrios comandos if aninhados: if dia = 1 then desconto = 30 else if dia = 2 then desconto = 20 else if dia = 3 then desconto = 10; Mas o mesmo pode ser feito com o comando case, especificando a varivel, e seus valores possveis: case dia of 1: desconto = 30; 2: desconto = 20; 3: desconto = 10; end; A sintaxe geral desse comando : case expresso of rtulo1: comando1; rtulo2: comando2; ... else comandoElse; end; Onde expresso pode ser qualquer varivel ou expresso que retorne um valor de um tipo ordinal. Cada rtulo pode ser uma constante sozinha, vrias constantes separadas por vrgulas, ou uma faixa de valores. Por exemplo: case dia of 1: nome := 'primeiro'; { constante } 2: nome := 'segundo'; 3..10: nome := 'terceiro'; { valores entre 3 e 10 } 11,13,15: nome := 'quarto'; { valores 11, 13 e 15 } end; Cada comando na sintaxe pode ser um comando simples ou um comando composto formado pelos delimitadores begin e end.
35
A parte do else opcional e indica um comando a ser executado se nenhum dos valores corresponde ao valor da expresso.
36
Estruturas de Laos
Estruturas de lao permitem repetir um conjunto de comandos. Cada um dos comandos de lao especifica uma forma diferente de iniciar e testar o lao.
O comando for
O comando for permite repetir um lao um nmero especificado de vezes, incrementando ou decrementando uma varivel a cada passagem do lao. Voc deve especificar o valor inicial e final da varivel. A forma de uso a seguinte: for varivel := valor_inicial to valor_final do comando; O comando, como antes, pode ser um comando simples, ou um comando composto. A varivel, o valor inicial e o valor final devem ser todos de um tipo ordinal. Se no incio da execuo o valor inicial maior do que o final, o comando nem chega a ser executado. O seguinte lao mostra os valores numricos de 1 at 20 dentro de um componente ListBox: var valor: integer; s: string; begin for valor := 1 to 20 do begin s := IntToStr(valor); ListBox1.Items.Add(s); end; end; A varivel tambm pode ser do tipo Char, pois este um tipo ordinal: for letra := 'A' to 'Z' do ... Para decrementar a varivel durante o lao, ao invs de incrementar, usa-se downto no lugar da palavra to: for letra := 'Z' downto 'A' do ... for valor := 20 downto 1 do ... Note que o incremento ou decremento sempre 1.
O comando while...do...
O lao while repete um comando enquanto determinada condio verdadeira. Sua sintaxe de forma geral : while condio do comando; Por exemplo: i := valorAnt; while i < 1000 do begin Processar(i); i := i + incremento; end; Antes da primeira iterao do lao, a condio verificada. Se ela for falsa, o comando no chega a ser executado. Se for verdadeira, o comando executado, e a condio verificada novamente e assim por diante.
O comando repeat..until
O repeat..until semelhante ao while, mas testa a condio no final, depois de executar o comando, e termina a execuo se a condio for verdadeira (o contrrio do while). Sua sintaxe geral : repeat comando1; comando2; ...
37
until condio; Por exemplo: i := valorAnt; repeat Processar(i); i := i + incremento; until i >= 1000; O comando repeat sempre executa uma iterao do lao pelo menos. Note que ele no precisa de begin e end para delimitar a lista de comandos, pois as prprias palavras repeat e until j formam delimitadores.
Outros Comandos
Comandos para sair de laos
Durante a execuo de um lao, comum precisar terminar sua execuo antes do tempo. Para isso, pode ser usado o comando break. Este comando sai imediatamente do lao mais interno (seja for, while, ou repeat) e vai para o prximo comando depois do lao. Por exemplo: for i := 1 to 1000 do begin encontrou := ProcuraValor(i); if Encontrou(i) then break; end; { o break salta para esta linha } Alm desse, existe o comando continue. Ele fora a execuo da prxima iterao (repetio) do lao, ignorando os comandos restantes dentro do bloco do lao. Por exemplo, o prximo lao mostra em uma list box os nmeros de 1 a 300, exceto os mltiplos de 7: for x := 1 to 300 do begin if x mod 7 = 0 then { um mltiplo de 7? } continue; { vai para o prximo } s := IntToStr(x); ListBox1.Items.Add(s); end;
O comando exit
Para sair imediatamente de um procedimento, usa-se o comando exit. Use-o quando ocorre alguma condio de erro, por exemplo: if valorErrado then begin mostrarMensagem; exit; end;
38
39
Tipos de Propriedades
Existem vrias formas de editar o valor de uma propriedade, dependendo da propriedade especfica. Ns j vimos a maioria delas, que so basicamente as seguintes: Propriedades que aceitam qualquer valor: voc precisa digitar o valor diretamente. Exemplo: Caption, Text. A propriedade Name s aceita um identificador vlido (mesmas regras que nomes de variveis). Propriedades numricas: O Delphi permite digitar qualquer coisa, mas quando voc teclar [Enter] ou sair, ele vai verificar se um valor numrico. Exemplo: Left, Top, MaxLength (do componente Edit). Propriedades de lista: Um boto aparece ao lado do valor. Ao clicar nele, abre-se uma lista de valores, e possvel selecionar um deles:
Exemplo: BorderStyle, Color, WindowState, Align. Geralmente o valor s pode ser um dos disponveis na lista, mas algumas propriedades permitem digitar outros valores, como Color. Propriedades booleanas: uma propriedade do tipo Boolean, que s tem dois valores possveis: False e True. Exemplo: Enabled, Visible, Ctl3D. Voc pode selecionar um deles na lista, mas mais fcil usar , com um clique duplo no valor, o contedo ser alternado entre True e False ou clicar no boto . Propriedades expansveis: um sinal de "+" aparece ao lado da propriedade e, clicando duas vezes no nome, ela se expande em sub-propriedades. Exemplo: Font.
Para fechar a lista de sub-propriedades, clique duas vezes no nome da propriedade. Para usar essa propriedade em tempo de projeto, utiliza-se um ponto a mais e o nome da subpropriedade, por exemplo: memoEditor.Font.Color := clBlack; Propriedades de conjunto: So parecidas com propriedades expansveis. As "subpropriedades" que aparecem so todas booleanas (True/False). Exemplo: BorderIcons, Font.Style. O valor que aparece um conjunto de valores, que como veremos mais tarde, exige uma sintaxe diferente para ser usado no programa.
Para alterar a propriedade dentro do programa, use por exemplo: BorderIcons := [biSystemMenu, biMaximize]; Propriedades com editor: Algumas propriedades mostram um valor como (TFont) ou (TStringList), que no pode ser editado, e um boto , que quando clicado mostra um editor de propriedade especializado. Exemplo: Lines (do componente Memo), Font (que tambm
40
pode ser editada abrindo as sub-propriedades). O editor tambm pode ser chamado com um clique duplo na coluna de valor.
Para um formulrio, Left a distncia deste extremidade esquerda da tela, Top a distncia em relao ao topo da tela. Para um controle, essas medidas so feitas em relao rea interna do formulrio (excluindo as bordas). O tamanho do formulrio ou controle especificado por Width (na horizontal) e Height (na vertical). Todas essas propriedades podem ser alteradas tambm atravs de comandos de programa, para alterar dinamicamente a posio e tamanho de um controle.
Propriedades do Formulrio
Outras propriedades alteram o posicionamento e tamanho do formulrio. A maioria dessas propriedades s mostra efeito ao executar o programa. A propriedade WindowState controla como o formulrio vai aparecer: wsNormal 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 posio ou o tamanho que voc definiu para o formulrio. O valor padro 'poDesigned': poDesigned posio e tamanho de acordo com o projetado poScreenCenter centraliza o formulrio na tela poDefault o Windows pode mudar a posio e tamanho poDefaultPosOnly o Windows s pode mudar a posio poDefaultSizeOnly o Windows s pode alterar o tamanho A propriedade BorderStyle controla o estilo da borda do formulrio: bsSizeable permite o usurio alterar o tamanho da janela bsSingle no permite alterar tamanho (estilo de borda fina) bsDialog no permite alterar tamanho (estilo de borda dupla) bsNone nenhuma borda, nem barra de ttulo (no permite mover) bsToolWindow como bsSingle, mas com ttulo menor bsSizeToolWin como bsSizeable, mas com ttulo menor
41
O valor padro 'bsSizeable'. A diferena entre 'bsSingle' e 'bsDialog' uma questo de padres de interface, como veremos depois. A propriedade BorderIcons, que se expande em "sub-propriedades", determina quais cones de controle aparecem na barra de ttulo do formulrio. Cada valor correspondente aos elementos da barra, e alterando-o para True ou False pode-se ativar ou desativar um deles (o efeito s aparece ao executar o programa):
O outro valor, biHelp, coloca um boto de ajuda com uma interrogao na borda. Esse boto pode ser usado para chamar uma tela de help. S funciona se biMinimize e biMaximize estiverem desativados. A propriedade AutoScroll, como padro, verdadeira (contm o valor True). Isso faz com que o formulrio mostre barras de rolagem automaticamente quando os controles no cabem na rea visvel da tela. Para testar, crie um controle qualquer, como um Edit e mova-o at deixar metade dele fora do formulrio em alguma das extremidades. Vai aparecer uma barra de rolagem (horizontal ou vertical), que voc pode usar para ver a rea que atualmente no visvel. Se voc quiser, pode desativar AutoScroll, colocando um valor False. Com isso, controles que estiverem fora da rea do formulrio no podem ser acessados pelo usurio.
Propriedades de Controles
Controles (ou componentes visuais), alm das quatro propriedades de posio (Left, Top, Width e Height) tm propriedades que alteram sua aparncia, a maioria existe tambm no formulrio. A propriedade Font determina as caractersticas do texto mostrado pelo controle. No caso do formulrio, ela afeta os controles contidos nele, no o prprio. Para testar, coloque trs controles Label no formulrio. Altere a propriedade Font do formulrio, mudando o nome da fonte para "Times New Roman". Isso vai afetar os dois controles. Agora altere a propriedade Font de um dos controles, "Label1", mudando Font.Name para "Arial". S esse controle ser afetado. Se voc novamente alterar a fonte do formulrio, apenas "Label2" e "Label3" sero alterados. O que determina se um controle usa uma fonte prpria ou a do formulrio a propriedade ParentFont. Note que ParentFont False para o "Label1" (que foi alterado) e True para os outros dois. Quando voc altera a fonte individualmente de um controle, ParentFont automaticamente mudado para False. Se voc mudar ParentFont para True, a fonte do controle vai ser alterada para ficar igual do formulrio. A propriedade Color determina a cor do formulrio ou controle. Existem vrias formas de escolher uma cor. Voc pode selecionar da lista o nome de uma cor especfica (clBlack = preto, clBlue = azul, etc.) e nesse caso, a cor ser sempre a que voc especificou. Outra opo usar nomes de cores relativas configurao do Windows, como clWindow = cor de janela, clBtnFace = cor de boto, clWindowText = cor de texto de janela etc. Nesse caso, a cor real que ser utilizada depende da configurao de cores do Windows no computador do usurio. Para cada controle que tem a propriedade Color, existe tambm uma propriedade ParentColor, que determina se o controle usa a cor definida pelo formulrio ou sua prpria cor individual (de forma anloga a Font e ParentFont). Como j vimos, um controle ou um item de menu pode ser habilitado ou desabilitado com a propriedade Enabled (True ou False). Voc tambm pode esconder um controle ou item de menu do usurio alterando a propriedade Visible para False. Ele continua aparecendo em tempo de projeto, e voc ainda pode utiliz-lo no programa, mas o usurio no vai v-lo durante a execuo. O texto mostrado por um controle definido pela propriedade Caption, se ele no permite edio, ou Text, se ele permite edio pelo usurio. Uma facilidade que o Delphi fornece a capacidade de colocar "dicas" [hints] que so mostradas quando o usurio passa o mouse por cima de um controle. A propriedade Hint de um controle define qual o texto da dica. Para que a dica seja exibida, a propriedade ShowHint deve ter o valor True. Essa propriedade pode ser definida para cada controle individualmente, ou para o formulrio (nesse caso, ParentShowHint, em cada controle, define qual das duas usada).
42
A propriedade Cursor define qual o tipo de ponteiro (ou cursor) do mouse que ser mostrado. O valor padro (crDefault) diz para utilizar o cursor padro atual (geralmente uma seta). Outros valores determinam ponteiros diferentes, por exemplo crArrow (seta), crHourglass (ampulheta).
Eventos Comuns
Crie um novo projeto. Nesse projeto, veremos os eventos mais utilizados pela maioria dos componentes, e tambm algumas propriedades vistas anteriormente.
Eventos de Mouse
O evento OnClick, como j vimos, ocorre quando o boto do mouse pressionado e solto sobre o controle (mas alguns controles, como botes, tambm acionam este evento quando so ativados pelo teclado). Esse evento no fornece nenhuma informao sobre as coordenadas do mouse. Alm desse, existe o evento OnDblClick, que informa um clique duplo (dois cliques em seqncia rpida). Os eventos OnMouseDown e OnMouseUp so acionados quando um boto do mouse pressionado ou liberado, respectivamente, quando o cursor do mouse est posicionado sobre o controle. Esses eventos informam a posio do mouse, qual boto foi pressionado e quais das teclas de modificao ([Shift], [Ctrl] e [Alt]) estavam pressionadas no momento. O evento OnMouseMove ocorre quando o cursor do mouse movimentado sobre o controle. Ele informa a posio atual do cursor do mouse. Vamos tratar o evento OnClick para o formulrio. Digite o seguinte no procedimento de evento: procedure FormClick(Sender: TObject); begin if Cursor = crDefault then {cursor o padro?} Cursor := crHourglass {muda para ampulheta} else Cursor := crDefault; {seno muda pra default} end; importante notar que Cursor uma propriedade do formulrio. Nesse caso, no preciso escrever o nome do formulrio na frente (o que seria Form1.Cursor), basta o prprio nome. Execute para testar. Agora quando voc clicar no formulrio, o ponteiro vai mudar para uma ampulheta. Clicando novamente ele retorna ao valor padro.
Eventos de Teclado
Existem trs eventos de teclado, que so acionados em momentos diferentes. Cada um deles fornece informao sobre a tecla pressionada, mas de formas diferentes. Para cada tecla que pressionada, o evento OnKeyDown acionado, e quando a tecla solta, OnKeyUp acionado. Ambos informam para o procedimento de evento o cdigo da tecla pressionada. Esse cdigo identifica a tecla, mas no o caractere digitado. Por exemplo, no possvel distinguir entre maisculas e minsculas, ou entre dois caracteres na mesma tecla. Alm disso, um caractere pode ser gerado pelo pressionamento de mais de uma tecla. Quando necessrio distinguir os caracteres digitados, e no as teclas, pode ser utilizado o evento OnKeyPress. Ele informa o caractere digitado como uma varivel do tipo Char. Note que nem toda tecla aciona um evento OnKeyPress. Teclas que no geram digitao, como [F1], [Insert], [Home], [Ctrl], acionam apenas os eventos OnKeyDown e OnKeyUp. Vamos tratar esses eventos para o formulrio. Crie o seguinte procedimento de evento, associado ao OnKeyPress: procedure TForm1.FormKeyPress(Sender: TObject; var Key: Char); begin if Key = '*' then Close; end; Nota: A varivel 'Key' um parmetro do procedimento de evento, que preenchido pelo Delphi. Alguns eventos tm parmetros, que contm informaes adicionais fornecidas pelo Delphi.
43
Com isso, quando for pressionada a tecla ('*'), o formulrio ser fechado, usando o mtodo Close. Agora vamos tratar as teclas de seta, fazendo a movimentao do formulrio na direo da seta utilizada. Inicialmente, crie um procedimento de evento para OnKeyDown: procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); begin end; Repare que o procedimento tem vrios parmetros: 'Key', que desta vez numrica (tipo Word) informa o cdigo da tecla pressionada e 'Shift' informa o estado das teclas de modificao. Para tratar as setas, precisamos comparar o valor de Key com cada um dos cdigos de teclas de seta. Na verdade no preciso saber o valor numrico de todos os cdigos. O Delphi tem constantes predefinidas correspondentes aos valores. Entre o begin e o end digite o seguinte: case Key of vk_Left: Left := Left - 10; vk_Right: Left := Left + 10; vk_Up: Top := Top - 10; vk_Down: Top := Top + 10; end; O comando case..of.., como veremos, compara uma varivel com vrios valores numricos e executa um comando dependendo do valor. No caso os valores so dados pelas constantes 'vk_Left', 'vk_Right',... As propriedades Left e Top determinam a posio do formulrio na tela. Para mover o formulrio, basta alterar seus valores. Execute e teste as teclas de seta para movimentar e a tecla '*' para fechar o formulrio. Salve esse projeto como EVENTOS.PAS e EVENTOSP.DPR.
Eventos do Formulrio
Outros eventos do formulrio correspondem a situaes importantes de serem tratadas, por exemplo: OnCreate: Quando o formulrio criado, ou seja, na inicializao do programa. executado antes de qualquer outro evento do formulrio. Voc pode usar para inicializar componentes. OnDestroy: Quando o formulrio est sendo destrudo, ou seja, a sua rea de memria ser liberada. Ocorre geralmente quando o programa est terminando. OnShow: Logo antes do formulrio ser mostrado na tela (pode ocorrer vrias vezes durante a execuo). OnCloseQuery: O usurio est tentando fechar o formulrio. Voc pode cancelar o fechamento (fazendo CanClose := False) ou, por exemplo, confirmar se ele deseja salvar os dados. OnClose: O formulrio est sendo fechado. Voc pode cancelar o fechamento ou determinar uma ao diferente, como minimizar, ou destruir o formulrio. OnActivate: O formulrio passou a ser a janela ativa (recebeu o foco). OnDeactivate: O formulrio passou a ser uma janela inativa. OnResize: Quando o usurio altera o tamanho do formulrio. OnPaint: til para desenho de grficos.
Outros Eventos
Os controles que podem receber o foco de teclado tm eventos que so acionados quando o foco de teclado muda. O evento OnEnter acionado quando o controle recebe o foco de teclado, depois de um clique do mouse, por exemplo, ou depois que o usurio tecla [Tab] a partir do controle anterior. J o evento OnExit acionado quando o controle perde o foco de teclado, depois que o usurio passa para outro controle por exemplo. Controles de edio e similares possuem um evento OnChange. Esse evento acionado quando ocorre uma modificao no contedo do texto, por exemplo, acrescentar ou apagar um caractere.
44
45
procedure TForm1.TratarTecla(Sender: TObject; var Key: Char); begin if ((Key < '0') or (Key > '9')) and (key <> #8) then Key := #0; { rejeita a tecla } end; Voc no deve mudar o nome diretamente no texto da unidade. Se fizer isso, o Delphi no conseguir localizar mais o procedimento e mostrar vrias mensagens de erro.
46
47
Caixas de Dilogo
Um programa em Delphi geralmente tem um formulrio principal, que aparece inicialmente, e com o qual o usurio interage. A partir desse formulrio, o usurio pode abrir outros formulrios do programa. Os formulrios auxiliares, chamados a partir do principal, geralmente so caixas de dilogo. Uma caixa de dilogo uma janela com a qual o usurio interage e depois retorna ao principal. Algumas funes do Delphi mostram caixas de dilogo predefinidas e voc no precisa criar um formulrio para us-las. Mas geralmente, quando voc precisa de alguma coisa a mais, voc deve criar um formulrio e utiliz-lo como uma caixa de dilogo.
Funes de Mensagem
Mensagens Informativas
O procedimento ShowMessage permite mostrar uma mensagem simples para o usurio, contendo apenas um boto de Ok. O ttulo da aplicao aparece no ttulo da mensagem. Por exemplo, a chamada: ShowMessage('Erro de digitao no campo Nome. ' + 'Digite novamente.'); mostra uma mensagem como a seguinte (supondo que o ttulo da aplicao 'Meu Programa'):
Nota: para definir o ttulo da aplicao, abra o menu Project|Options, clique no marcador "Application", e digite o novo ttulo em Title. Esse ttulo ser usado em todas as mensagens de agora em diante. Esse procedimento geralmente usado para mensagens curtas, que no precisam de nenhum retorno do usurio. Note que se o texto da mensagem muito longo, voc pode dividir a string em partes, usando o operador "+". Se voc precisar de quebras de linha na mensagem, voc pode inserir os caracteres de fim de linha, #13 e #10. Por exemplo: ShowMessage('Erro de digitao no campo Nome. '#13#10 + 'Digite novamente.');
Mensagens de Confirmao
A funo MessageBox, que um mtodo do objeto Application, mostra uma mensagem com botes que o usurio pode clicar para responder. De forma geral, a sintaxe para usar essa funo : varivel := Application.MessageBox(mensagem, ttulo, flags); onde: mensagem: o texto da mensagem ttulo: o ttulo que aparece na janela de mensagem. flags: uma combinao de valores que determina quais botes ou cones so usados na janela de mensagem. (Ver abaixo) varivel:recebe um valor inteiro que indica qual boto foi pressionado. Esse valor pode ser um dos seguintes: IDOK boto Ok IDCANCEL boto Cancelar IDABORT boto Anular IDRETRY boto Repetir IDIGNORE boto Ignorar IDYES boto Sim IDNO boto No
48
O valor de flags pode ser uma combinao de um ou mais dos seguintes valores: MB_OK 0 s boto Ok (default) MB_OKCANCEL 1 botes Ok e Cancelar MB_ABORTRETRYIGNORE 2 botes Anular, Repetir e Ignorar MB_YESNOCANCEL 3 botes Sim, No e Cancela MB_YESNO 4 botes Sim e No MB_RETRYCANCEL 5 botes Repetir e Cancelar MB_ICONERROR 16 sinal de erro crtico MB_ICONQUESTION MB_ICONEXCLAMATION MB_ICONINFORMATION 32 sinal de pergunta 48 sinal de advertncia 64 sinal de informao MB_DEFBUTTON1 0 primeiro boto tem o foco (default) MB_DEFBUTTON2 256 segundo boto tem o foco MB_DEFBUTTON3 512 terceiro boto tem o foco Veremos exemplos dessas funes no prximo projeto.
Exemplo: CalcData
Vamos criar um pequeno programa que permite mostrar um calendrio e executa a calculadora do Windows . Crie um novo projeto. No ttulo do formulrio coloque "Menu Principal" e na propriedade Name, troque "Form1", que o nome default, por "FormPrincipal".Para o formulrio ficar centralizado altere a propriedade Position para "poScreenCenter". Em outros projetos, no colocamos nome no formulrio porque ele no era utilizado dentro do cdigo do programa. Coloque no formulrio trs componentes "Button" ( ) , um componente "Edit"( )e
) . Altere as seguintes propriedades: um componente "Label" ( "Button1" btnCalendario Name Caption Calendrio "Button2" Name btnCalculadora Calculadora Caption "Button3" btnFechar Name Fechar Caption "Edit" Name editData Text "Label" Data Caption O formulrio ir ficar da seguinte forma:
49
50
Este componente mostra um calendrio. Seu formulrio ir ficar como a figura abaixo:
Agora vamos acrescentar dois botes neste formulrio, vamos usar o componente "BitBtn" da . Esse tipo de componente permite pgina "Additional" - o primeiro cone da pgina, mostrar figuras junto com o texto. Para o primeiro boto, defina a propriedade Kind [espcie] com o valor 'bkOk'. Isso altera automaticamente as propriedades Caption (para "Ok"), Default (para True), ModalResult (para 'mrOk') e Glyph (para conter uma imagem correspondente ao Ok). Para o outro boto, defina Kind com o valor 'bkCancel'. Isso vai alterar Caption para "Cancel", Cancel para True, ModalResult para mrCancel, e Glyph para conter o desenho de um "x". Altere Caption para o valor "Cancelar". A propriedade ModalResult de um boto (de um Button "normal" ou de um BitBtn) importante com caixas de dilogo. Quando ModalResult contm um valor diferente de 'mrNone' (o default), o boto fecha o formulrio e retorna esse valor para quem "chamou" o formulrio. Esse valor numrico, mas existem constantes predefinidas para facilitar, como 'mrOk' e 'mrCancel'. A propriedade Default, como j vimos, faz com que o boto seja acionado por [Enter] e a propriedade Cancel faz com que o boto seja acionado pela tecla [Esc]. Notas: A propriedade no componente "BitBtn" que permite colocar imagem a propriedade Glyph.
Salvando o Projeto
Salve o projeto nesse ponto para dar nome aos arquivos. O Delphi vai pedir os nomes na ordem segundo formulrio,: formulrio principal e projeto. Chame-os respectivamente de: EXECCALEN.PAS (era "Unit2.PAS", segundo formulrio) EXECPRIN.PAS (era "Unit1.PAS", primeiro formulrio) CALCDATA.DPR (era "Project1.DPR", arquivo de projeto) Em projetos com mais de um formulrio, no usaremos o mesmo padro de nomes dos outros, que era acrescentar um "P" ao nome do projeto. melhor salvar o projeto agora porque vamos precisar dos nomes de unidades do projeto bem definidos para o prximo passo.
Executando um Arquivo
O boto "Calculadora" vai executar o calculadora do Windows , cujo arquivo "Calc.exe". No procedimento de evento OnClick , faa o seguinte: begin WinExec('calc.exe', SW_SHOWNORMAL); end; A funo WinExec uma funo do Windows que executa um programa. Ela recebe como parmetros o nome do programa e um valor que indica como a janela do programa deve aparecer. Para isso existe um comando que converte a string em PChar. Execute o programa e verifique o resultado. Vamos retornar ao formulrio principal, para fazer isto clique no cone menu View/forms, ir aparecer a seguinte tela: ou [Shift+F12] ou
51
Escolha a opo "formPrincipal" e clique em "OK". Ele ir mostrar o formulrio principal, no evento OnClick do boto "Calendrio" iremos chamar o formulrio "formCalendrio". Para mostrar um outro formulrio basta usar o mtodo Show ou o mtodo ShowModal, da seguinte forma: nome_do_formulrio.Show; { ou } nome_do_formulrio.ShowModal; A diferena entre os dois que ShowModal mostra o formulrio de forma modal. Quando uma janela modal est na tela, o usurio no pode utilizar outras janelas do programa. Ele deve terminar de executar a tarefa atual e fechar a janela modal para poder retornar principal. Se uma janela no modal, o usurio pode alternar livremente entre ela e outras janelas no modais. Uma janela modal a interface recomendada para caixas de dilogo, por isso utilizaremos ShowModal. No cdigo do procedimento criado coloque: if FormCalendario.ShowModal = mrOk then editData.Text := DatetoStr(FormCalendario.MtCData.Date); Primeiro o mtodo ShowModal chamado e o valor retornado verificado. Se esse valor for 'mrOk', o boto "Ok" foi pressionado. Se ele for 'mrCancel', o boto "Cancelar" foi pressionado. Quando o valor 'mrOk', o componente 'editData' vai receber a data que foi escolhida , essa valor iremos obter pela propridade Date do componente MtCData no formulrio formCalendario. Repare que isso feito com a sintaxe: FormCalendario . MtCData . Date Mas para esse cdigo funcionar falta uma coisa. Se um formulrio precisa acessar outro que est em outra unidade, preciso adicionar uma referncia unidade, atravs de uma clusula uses. No arquivo da unidade EXECPRIN.PAS, procure a palavra implementation, e acrescente o seguinte logo depois do {$R *.DFM}: uses ExecCalen; "ExecCalen" o nome da outra unidade, que contm o formulrio "FormCalendario". Se no houvesse essa clusula, o cdigo no conseguiria acessar o outro formulrio. Como a propriedade Text do componente "Edit" do tipo String e a propriedade Date do componente MonthCalendar e do tipo TDate, temos que converte o contedo da propriedade Date para String, por isso foi necessrio usar a funo StrtoDate. Execute o programa e clique no boto "Calendrio". O segundo formulrio aparece como uma janela modal(se voc clicar no formulrio principal, no vai conseguir us-lo). Para retornar ao principal clique no boto "Ok". Salve novamente o projeto. Mantenha ele aberto no Delphi, pois vamos analisar algumas opes do Delphi utilizando esse mesmo projeto.
52
E voc tambm pode alternar para uma unidade e, a partir dela, abrir o formulrio associado. Para isso use a tecla [F12] ou o boto (Toggle Form/Unit) da SpeedBar. claro que se voc puder ver os dois (ou mais formulrios) ao mesmo tempo na tela, voc pode alternar entre eles com um clique de mouse. Voc tambm pode adicionar um arquivo ao projeto (como um formulrio que voc criou em outro projeto) usando o boto da SpeedBar ou o item de menu Project|Add to project....
ou o item Project|Remove from Para remover um arquivo do projeto, use o boto project... e selecione qual voc quer remover. Nota: Quando voc adiciona um arquivo ao projeto, o Delphi no faz uma cpia do arquivo. Se outros projetos estiverem utilizando o arquivo, ele ser compartilhado entre eles. Quando voc remove um arquivo do projeto, o arquivo no excludo do disco. Ele continua no diretrio do projeto e pode ser utilizado novamente no mesmo projeto ou em outros projetos.
53
O Project Manager mostra uma tabela com os nomes de cada unidade do projeto e ao expandir essas unidades ele mostra o formulrio correspondente , a no ser no caso de uma unidade independente. Na coluna "Path", aparece o diretrio do arquivo, isto se no estiver no mesmo diretrio do projeto. Podemos trabalhar com mais de um projeto ao mesmo tempo . Isso muito til , se voc quer desenvolver um desenvolver um programa EXE e uma DLL que trabalham em conjunto. Os arquivos podem ser salvos nos "grupo de projetos", que serve para manter agrupados todos os itens adicionados. Podemos adicionar um novo projeto e tambm um projeto j existente, para isso clique com o boto direito do mouse na palavra ProjectGroup1(caso no tenha mudado o nome do grupo). Com isso iro aparecer as seguintes opes:
Estas opes so utilizadas para: Add New Project : Adicionar um novo projeto ao grupo. Add Existing Project : Caso o projeto j exista , podemos adicion-lo ao grupo atravs desta opo. Save Project Group : Salva todas as alteraes feitas neste grupo. Save Project Group As: Salva as configuraes deste grupo com outro nome. View Project Group source : Para cada grupo criado gerado um arquivo com a extenso bgp, e neste arquivo contm todos os projetos associados ao grupo.Esta opo mostra o contedo do arquivo cuja extenso bgp. ToolBar: Se est opo estiver marcada , mostrado uma barra de ferramento onde apareem as opes:
Status Bar: Mostra o nome e o caminho do arquivo de projeto. Dockable: Permite encaixar a janela atual em outra janela, como por exemplo, o editor de cdigo, o object inspector, etc..
54
55
56
57
Quando voc cria um formulrio no Delphi, automaticamente criada uma unidade associada, que contm algum cdigo gerado automaticamente pelo Delphi, alm do cdigo que voc acrescenta nos procedimentos de evento. Voc tambm pode criar uma unidade independente, para usar como uma biblioteca de funes e procedimentos, por exemplo. Neste captulo veremos como a estrutura do cdigo gerado pelo Delphi, e qual a forma geral da estrutura de uma unidade.
Seo de Interface
interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,StdCtrls; A seo de interface comea com uma clusula uses, que contm uma lista de nomes de outras unidades que so utilizadas por esta. Nesse caso esses nomes so de unidades do Delphi (Windows, SysUtils, ...) que compem a biblioteca do Delphi. Essa lista mantida automaticamente, mas voc pode acrescentar outros nomes lista. Aps a clusula uses, voc pode acrescentar declaraes de tipos de dados, variveis, procedimentos e funes. A primeira declarao, colocada automaticamente, a da classe de formulrio. A classe uma definio dos componentes que o formulrio contm, e dos procedimentos de evento definidos nele. Ns veremos a classe de formulrio mais em detalhes posteriormente. type TformPrincipal = class(TForm) btnCalendario: TButton; btnCalculadora: TButton; btnFechar: TButton; editData: TEdit; Label1: TLabel; procedure btnFecharClick(Sender: TObject); ... private
58
{ Private declarations } public { Public declarations } end; Com a palavra end, termina a definio da classe. Depois o Delphi acrescenta uma declarao de varivel para o formulrio. var FormPrincipal: TFormPrincipal; Depois dessas declaraes, vem a seo de implementao da unidade, que contm o seguinte: implementation {$R *.DFM} uses execcalen; procedure TformPrincipal.btnFecharClick(Sender: TObject); begin .... end; procedure TformPrincipal.FormCloseQuery(Sender: TObject;var CanClose: Boolean); begin .... end; ... end. A declarao {$R *.DFM} no um comentrio, apesar de parecer com um. Esse tipo de declarao chamada de diretiva do compilador e uma instruo para o compilador interno do Delphi. No caso, o que ela faz associar o arquivo de formulrio (EXECPRIN.DFM) com o arquivo de unidade. Essa diretiva necessria para o funcionamento do programa, portanto no a remova. Depois vem o corpo de cada um dos procedimentos de evento, Note que em cada um deles, o nome da classe de formulrio ("TFormPrincipal") includo como prefixo no cabealho do procedimento. Aps todos os procedimentos existe uma linha contendo apenas "end." (end seguido de ponto final). Essa linha sinaliza o final do arquivo da unidade. O compilador ignora tudo que for digitado depois dessa linha, mesmo sem especificar comentrios.
59
implementation end. Quando voc salva o arquivo da unidade, fornecendo um outro nome, o Delphi vai alterar a declarao no cabealho para refletir esse nome.
Compilao de Unidades
O Delphi compila o seu projeto quando voc executa o programa, ou quando voc aciona Project|Compile (nome do projeto ativo). Caso queira compilar todos os projetos existente no grupo escolher Project|Compile All Projects. Para compilar o programa, o Delphi rene todas as unidades do projeto e cria um arquivo executvel, com o mesmo nome do projeto e extenso EXE. Essa compilao feita em vrias fases. Da primeira vez que o projeto compilado, para cada arquivo de unidade (.PAS), gerado um arquivo de unidade compilada (.DCU), e esses arquivos DCU so mantidos no disco. Depois todos os arquivos DCU, mais os arquivos (RES) e o arquivo DPR so combinados em um nico arquivo EXE independente. Da prxima vez que o projeto for compilado, apenas as unidades alteradas desde a ltima compilao so recompiladas (.PAS -> .DCU). O Delphi verifica isso comparando a data/hora do arquivo PAS com a data/hora do arquivo DCU correspondente. Se o arquivo fonte for mais recente, ele recompila. Voc pode tambm forar o Delphi a recompilar todas as unidades sem verificar a data. Para isso, use o comando Project|Build (nome do projeto ativo) , caso queira recompilar todos os projetos pertencentes ao grupo escolher Project|Build All Projects. O processo de compilao pode ser resumido com o diagrama:
60
begin Contador := 30; AumentaCont; end; ... end. unidade ROTINAS.PAS: unit Rotinas; interface var Contador: integer; procedure AumentaCont; implementation ... end. Quando uma unidade (FrmTeste), utiliza outra (Rotinas), ela passa a ter acesso a todos os identificadores, como variveis e procedimentos, que esto declarados na seo de interface da outra (ela no tem acesso a identificadores declarados apenas na seo de implementao da outra). Existem dois lugares onde pode ser colocada a clusula uses: no incio da seo de interface, ou no incio da seo de implementao. Os identificadores da outra unidade s se tornam visveis a partir do ponto onde a outra unidade foi referenciada. Se voc colocar a referncia outra unidade na clusula uses da interface, ento os identificadores da outra podem ser usados j na parte de interface. Se voc referenciar a outra unidade na clusula uses da parte de implementao, os identificadores s podem ser usados a partir da parte de implementao. Se duas unidades dependem uma da outra atravs da seo de interface, ento o Delphi recompila a unidade dependente (gera o arquivo .DCU) sempre que a outra alterada. Nesse exemplo, toda vez que a unidade ROTINAS alterada, a unidade FRMTESTE, que depende dela, recompilada primeiro. Duas unidades podem se "utilizar" mutuamente, isto , pode haver tambm uma clusula uses em ROTINAS, que referencia FRMTESTE. Mas se ambas as referncias estiverem na parte interface das unidades, o Delphi no consegue determinar a ordem de compilao das duas, e gera uma mensagem de erro ("Circular unit not allowed"). Por isso, sempre melhor acrescentar a referncia para a outra unidade na seo implementation. S realmente necessrio colocar a referncia na interface quando voc precisa usar algo da outra unidade ainda dentro da parte interface (s acontece no caso de constantes e tipos de dados que sejam usados por outros tipos de dados ou constantes).
61
62
63
Tipos Enumerados
Um tipo enumerado composto por uma lista seqencial de valores simblicos. Uma varivel desse tipo pode assumir qualquer um desses valores. Para criar um tipo enumerado, usa-se uma declarao type: type EstadoCivil = (Solteiro, Casado, Desquitado, Viuvo); Aps criar um tipo de dados, podem ser criadas variveis desse tipo, com uma declarao de variveis normal: var estCiv: EstadoCivil; A varivel 'estCiv' s vai poder assumir um dos valores do tipo: Solteiro, Casado, etc. Esses valores no so numricos e no so strings de texto. So apenas constantes simblicas que representam uma informao. Por exemplo: estCiv := Casado; ... if estCiv = Viuvo then begin ... end; Tipos enumerados melhoram a legibilidade do programa, evitando que voc precise codificar uma varivel com valores numricos (p.ex.: 0 para Solteiro, 1 para Casado, etc.). Mas eles so manipulados de forma eficiente pelo Object Pascal, pois internamente so tratados como constantes numricas.
64
do programa. Se eles fossem codificados como strings de texto ('bsNone' etc.), seria muito ineficiente o armazenamento e manipulao dos valores.
Tipos Faixa
Se voc sabe que determinada varivel s pode pertencer a uma faixa de valores definida, pode utilizar um tipo faixa para que o prprio Delphi se encarregue de verificar isso automaticamente. Um tipo faixa uma restrio sobre os valores de um tipo ordinal qualquer. Por exemplo: type EstadoCivil = (Solteiro, Casado, Desquitado, Viuvo); DiaMes = 1..31; LetraMaiuscula = 'A'..'Z'; EstadoNaoViuvo = Solteiro..Desquitado; O tipo faixa declarado com o valor inicial e final da faixa, separados por '..' (um ponto seguido de outro). Os valores inicial e final devem pertencer a um tipo ordinal: inteiro, Char, ou enumerado. Depois de declarar o tipo, voc pode criar variveis baseadas no tipo: var dm: DiaMes; letra1, letra2: LetraMaiuscula; est1: EstadoNaoViuvo; x:integer; Qualquer atribuio a uma varivel do tipo faixa verificada, para saber se o valor est dentro dos limites. Por exemplo, os seguintes comandos geram erro de execuo, com uma mensagem "Range Check Error": x := 32; dm := x; {erro: 32 est fora da faixa} letra1 := Chr(32); {erro: ' '(espao) est fora de faixa} estCivil := Viuvo; est1 := estCivil; {erro: Viuvo est fora da faixa}
Vetores
Um vetor (tambm chamado matriz) uma varivel que contm vrios elementos do mesmo tipo de dados. Cada elemento possui um ndice que identifica esse elemento no vetor. Podemos criar os vetores de duas formas : Esttica e Dinmica. Um vetor esttico tem um tamanho definido, enquanto que um vetor dinmico no tem tamanho declarado e seu tamanho pode ser mudado durante a execuo do programa.
Vetores Estticos
Para criar um tipo de dados que representa um vetor, usa-se uma declarao array, informando o tipo do ndice e o tipo dos elementos do vetor (ou tipo base). Por exemplo: type TVetor = array [1..30] of double;
65
Essa declarao cria um tipo de vetor, com ndices na faixa de 1 a 30 (um tipo faixa) e elementos do tipo Double. Esse tipo pode ser usado para declarar uma ou mais variveis: var vetA: TVetor; vetB, vetC: TVetor; ind, x: integer; Cada varivel declarada um vetor com 30 elementos do tipo Double, e seus elementos individuais podem ser acessados informando o ndice do elemento entre colchetes: begin vetA[3] := 1000; x := vetA[5]; ind := 10; vetB[ind] := x; end; Na verdade no necessrio definir um tipo, quando voc s precisa de uma varivel daquele tipo. Voc pode inserir a definio do tipo na prpria declarao de varivel: var vetA: array [1..30] of double;
66
maior := freq['A']; ... end; Outros exemplos so: type TVetIndBool = array [False..True] of integer; TVetIndEnum = array [Solteiro..Viuvo] of string;
Vetores Dinmicos
Para criar um vetor dinmico tambm temos que utilizar a declarao array, informando o tipo dos elementos do vetor (ou tipo base). A diferena do vetor esttico que no informamos os tipo do ndice e o seu tamanho. Essa informao fornecida em tempo de execuo atravs do procedimento SetLength. O ndice inicial do vetor sempre zero. var Vetor : array of double; N:integer; begin N := 10; SetLength(Vetor, N); // muda o tamanho do vetor Vetor[5] := 5; // ele tem elemento de 0 a 9 end; Para redefinir o tamanho do vetor , usa-se a propriedade Setlength novamente com o novo tamanho que deseja . Por exemplo: continuando o exemplo anterior acrescente as seguinte linhas: SetLength(Vetor, 20); // Redefine o tamanho para 20 Vetor[20] := 5; O contedo do vetor na posio 20 5.
Vetores Multidimensionais
Um vetor tambm pode ter mais de uma dimenso, permitindo representar um vetor de vetores. Nesse caso, cada elemento possui dois ou mais ndices. Um vetor multidimensional pode ser criado definindo vrios tipos de ndices: type TMatriz = array [1..10, 1..30] of double; TMarcador = (marcaX, marcaO, marcaNada); TJogoDaVelha = array [0..2, 0..2] of TMarcador; TCubo = array [1..10, 1..10, 1..10] of integer; var m, n: TMatriz; i,j,k:integer; jogo: TJogoDaVelha; lin,col:integer; cubo: TCubo; begin { para acessar um elemento, usa-se dois ndices } m[i,j] := 100.0; for lin := 0 to 2 do for col := 0 to 2 do jogo[lin, col] := marcaNada; cubo[i,j,k] := 0; {trs ndices} end; Podemos tambm criar vetores multidimensionais dinmicos. A idia a mesma do anterior, mas no informamos o tamanho do vetor durante a definio, seu tamanho definido durante o tempo de execuo utilizando tambm o mtodo SetLength e alm disso permito criar para cada linha um nmero diferente de elementos, por Exemplo: var Matriz : array of array of double; begin setLength (Matriz, 2); // muda o tamanho do vetor multidimensional setLength (Matriz[0], 2);
67
Crie um rtulo (componente Label) com Caption "Nmero:" e ao lado dele um componente Edit com nome "editNumero" , coloque a propriedade Text vazia . Crie os botes como mostrado, e mude seus nomes, respectivamente para 'btnAdicionar', 'btnLimpar' e 'btnCalcular'. Ao lado do rtulo "Mdia:", coloque um componente Edit que vai apenas mostrar o resultado. Defina seu nome como 'editMedia'. Coloque sua propriedade Text vazia.Altere sua propriedade ReadOnly para True, o que vai proibir a edio do valor. Altere tambm a propriedade Color escolhendo o valor 'clBtnFace'. Com isso, ele vai ficar da mesma cor do formulrio e dos botes, o que fornece ao usurio uma indicao visual de que ele no pode ser editado. Para o 'btnAdicionar', faa a propriedade Default = True, para que ele possa ser "pressionado" usando a tecla [Enter].
Declarando o Vetor
Antes de fazer qualquer tratamento de eventos, vamos adicionar na unidade uma declarao para o tipo do vetor e uma declarao de varivel desse tipo. Pressione [F12] para abrir o arquivo da unidade. No incio da seo de implementao, aps a palavra implementation, digite o seguinte: type TVetorInt = array [1..3] of double; var Valores: TVetorInt; ContValores: integer; A varivel 'Valores' um vetor do tipo 'TVetorInt', ou seja, um vetor com elementos do tipo 'double' e ndices de 1 a 3. A varivel 'ContValores' ser um contador usado para especificar quantos elementos do vetor esto sendo usados no momento. A cada vez que for clicado o boto "Adicionar", essa varivel ser incrementada.
Adicionando um Elemento
No cdigo do boto 'btnAdicionar', vamos adicionar o nmero que foi digitado (em 'editNumero') ao vetor. A cada clique, vamos tambm incrementar o contador. Digite o seguinte: procedure TForm1.btnAdicionarClick(Sender: TObject); var numero: double; begin numero := StrToFloat(editNumero.Text);{conv. p/ inteiro} ContValores := ContValores + 1; {increm. contador}
68
Valores[ContValores] := numero; {guarda o elemento} { Facilita a digitao do prximo nmero } editNumero.Clear; editNumero.SetFocus; end; Repare que depois de adicionar o elemento, o programa limpa o controle 'editNumero', usando o mtodo Clear. Isso facilita que o usurio digite seqencialmente os nmeros. Tambm para facilitar, o programa devolve o foco de teclado para o controle, no caso de ele ter usado o mouse para clicar no boto. Isso feito com o mtodo SetFocus.
Limpando a Lista
O boto 'btnLimpa' vai "limpar" a lista de valores. Na verdade no precisamos percorrer todos os elementos do vetor, apenas zerar o contador, para indicar que no h nenhum elemento guardado. Faa o seguinte: procedure TForm1.btnLimparClick(Sender: TObject); begin ContValores := 0; end;
Testando o Programa
Execute o programa. Digite um nmero e clique no "Adicionar", ou tecle [Enter]. Repita o processo para adicionar alguns nmeros lista. (Repare que, como o programa no faz ainda verificao de erro, se voc digitar um valor no numrico e clicar em Adicionar, vai ver uma mensagem de erro do Delphi). Depois clique em "Calcular" para calcular o resultado. Se voc digitar, por exemplo, 13, 28 e 34, o resultado final ser: 25. No menu Project|Options na pasta Compiler se a opo RangeCheck estiver marcada , desmarque esta opo e pede para recompilar todo o projeto novamente (Project|Compile Mediap). Com isso se pedir para informar mais de 3 nmeros para ser adicionados a mdia , o Delphi no ir fazer a verificao se ultrapassou o tamanho do vetor, seu exemplo pode at continuar funcionando, vai depender da rea de memria que foi utilizada para acrescentar esses valores que foram colocados a mais, para que ocorre esta verificao a opo RangeCheck tem que estar marcada.
69
Salvando o Projeto
Vamos retornar a esse projeto mais tarde, portanto salve-o como MEDIA.PAS (unidade) e MEDIAP.DPR (projeto).
Conjuntos
O tipo de dados conjunto representa a noo matemtica de conjuntos, permitindo fazer todas as operaes padro de conjuntos. Um conjunto pode conter elementos de qualquer tipo ordinal (ou faixa). Para criar um tipo conjunto, usa-se a declarao set: type TConjCarac = set of char; TConjLetra = set of 'A'..'Z'; TConjDia = set of 1..31; TConjEstado = set of EstadoCivil; Para atribuir um valor (constante) a uma varivel conjunto, especifica-se os elementos do conjunto entre colchetes: var vogais: TConjLetra; diasUteis: TConjDia; begin vogais := ['A','E','I','O','U']; diasUteis := [1..10, 13, 15, 20..23]; Note que uma faixa de valores pode ser colocada, para evitar enumerar todos os valores.
Verificando Elementos
Voc pode verificar se um elemento pertence a um conjunto, com o operador in, que equivale em matemtica operao x c. Por exemplo: if caractere in vogais then texto := 'Vogal' else texto := 'Consoante'; if dia in diasUteis then ... if estCivil in [Desquitado, Viuvo] then ... Esse tipo de teste mais eficiente do que uma srie de ifs, alm de mais legvel. Vamos abrir o projeto CALCP para fazer uma alterao semelhante em um dos testes. No cdigo associado ao evento OnKeyPress, do 'editOperando1', existe um if que testa os valores possveis da varivel 'Key': if ((Key < '0') or (Key > '9')) and (Key<> #8) then Key := #0; { rejeita a tecla } Vamos alterar esse if para utilizar um conjunto. Substitua pelo seguinte: if not (Key in ['0'..'9', #8]) then Key := #0; ou seja, se a tecla no estiver no conjunto formado por '0'..'9', mais o backspace (#8), ela ser rejeitada. Esse teste bem mais simples e mais eficiente do que o teste anterior.
70
Interseo: C = A B. O resultado da interseo um conjunto que contm um elemento em comum entre os dois conjuntos. A interseo feita com o operador "*", por exemplo: C := A * B; { O resultado ser [1, 3, 5, 7] } Diferena: C = A - B. O resultado de A menos B o conjunto com os elementos de A que no existem em B. A diferena feita com o operador "-": C := A - B; { O resultado ser [2, 11] } C := B - A; { O resultado ser [9] } Contido: A B (A est contido em B) ou B A (B contm A). Verifica se todos os elementos de um conjunto pertencem tambm ao outro conjunto. No Object Pascal, o operador (est (contm) por >= Por exemplo: contido) representado por <= e {verifica se os elementos 1 e 3 pertencem ao conjunto A} if [1,3] <= A then ... {verifica se B contm A} if B >= A then ...
Propriedades de Conjunto
Algumas propriedades de componentes do Delphi utilizam tipos de conjunto. Por exemplo, a propriedade BorderIcons de um formulrio contm um conjunto de valores, onde cada um determina se o formulrio ter ou no um determinado item da borda. Essas propriedades aparecem no Object Inspector com um sinal de "+" e o seu valor aparece com a sintaxe de conjunto. Quando voc clica duas vezes no nome da propriedade, aparecem subitens, que permitem adicionar ou remover elementos do conjunto. Para atribuir um valor para este tipo de propriedade no programa, voc deve usar a sintaxe de conjunto, por exemplo: BorderIcons := [biSystemMenu, biMinimize, biMaximize]; Para alterar o valor, por exemplo, adicionando um elemento, voc deve usar os operadores de conjuntos: BorderIcons := BorderIcons + [biMinimize]; Para verificar se um elemento est presente, voc deve usar o operador in: if biMaximize in BorderIcons then ...
71
Depurao
Para encontrar as causas de uma exceo, ou para detectar erros de lgica no programa (erros que s voc pode saber que esto acontecendo), voc pode usar os mecanismos de depurao do Delphi. O processo de depurao [debugging] consiste em analisar o funcionamento do programa durante e execuo, vendo os valores de variveis, o fluxo da execuo, e assim por diante.
A diferena entre "Trace Into/F7" e "Step Over/F8" s importante quando voc passa por uma chamada de procedimento. "Trace Into" entra no procedimento e executa cada linha dele passo a passo tambm. Isso pode ser o que voc quer, mas em alguns casos um procedimento j foi totalmente testado e voc no precisa acompanhar sua execuo de novo. Nesse caso, use "Step Over", que executa o procedimento inteiro em modo de execuo normal e depois volta ao modo depurao, depois da chamada do procedimento.
Executando At o Cursor
s vezes, durante a depurao voc quer "pular" para uma determinada linha diretamente, executando todo um trecho em velocidade normal de execuo. Por exemplo, durante a
72
execuo, voc pode querer ir diretamente ao fim do lao for, em vez de acompanhar cada passagem. Para isso coloque o cursor na linha onde quer parar (por exemplo, no if depois do for) e use o item de menu Run|Run To Cursor ou sua tecla de atalho, [F4]. Nota: se a execuo nunca chegar linha do cursor, o programa entrar em modo de execuo normal ("Running") e no voltar automaticamente ao modo de depurao.
Voc tambm pode digitar o nome de outra varivel ou uma expresso qualquer em "Expression", por exemplo, "soma * 10 / 7", usando a janela como uma calculadora. Ou voc pode digitar o nome de uma constante (para saber o valor de uma constante predefinida do Delphi por exemplo), ou uma propriedade de um componente. Ao clicar em "Evaluate", voc ver o valor da expresso, varivel ou constante. Se for uma varivel, voc ter a opo de modificar o valor.
73
Para editar um "watch", clique duas vezes em cima dele na janela "Watch List" e altere suas opes. Para remov-lo, clique na lista e pressione [Delete]. Para adicionar um novo, com a janela "Watch List" aberta, clique duas vezes na linha vazia depois do fim da lista.
74
10 - Procedimentos e Funes
Procedimentos Gerais Unidades Independentes Funes Passagem de Parmetros
75
Procedimentos Gerais
Um procedimento um trecho de programa que tem um nome e pode ser utilizado (chamado) por outras partes do programa. Um procedimento de evento um procedimento que est diretamente ligado a um evento e chamado diretamente por um componente quando acontece aquele evento. Como j vimos, procedimentos de evento geralmente so criados pelo Delphi de forma automtica. Mas voc pode criar tambm procedimentos gerais, que no so associados a nenhum componente, e s so chamados quando voc determinar. Procedimentos gerais tornam o programa mais legvel e evitam repetio desnecessria de cdigo, facilitando a manuteno do programa. Em muitos casos, eles tambm contribuem para a reduo do tamanho do programa. Eles tambm podem ser reutilizados em vrios projetos, evitando "reinventar a roda" a cada novo programa que voc desenvolve.
Unidades Independentes
Da forma que o procedimento est, ele s pode ser usado na unidade CALC.PAS, associada ao formulrio da calculadora. Se quisermos que o procedimento seja usado por outras unidades do projeto, devemos colocar uma declarao do procedimento na interface da unidade. Mas essa ainda no a soluo ideal, pois para utilizar uma unidade associada em outro projeto, necessrio tambm utilizar o seu formulrio, mesmo que ele no seja necessrio. O melhor colocar o procedimento em uma unidade independente, ou seja, uma unidade no
76
associada a nenhum formulrio. Unidades independentes facilitam a reutilizao, especialmente entre vrios projetos.
Transferindo o Procedimento
Voltando unidade Calc (use as abas do editor de cdigo para mudar entre as duas), selecione todo o procedimento 'ValidarTecla', inclusive o cabealho. Tecle [Ctrl+X] para recort-lo da unidade. Agora alterne para a unidade Geral, coloque o cursor depois da palavra implementation e "cole" o texto, usando [Ctrl+V]. O corpo do procedimento deve ficar na seo de implementao, mas se ele precisar ser usado externamente, o cabealho do procedimento deve ser copiado para a seo de interface. Coloque o cursor na seo de interface e tecle [Ctrl+V]. Apague do begin ao end, porque s necessrio (e s permitido) o cabealho. A unidade ficar assim: unit Geral; interface procedure ValidarTecla(var tecla: char); implementation procedure ValidarTecla(var tecla: char); begin if not (tecla in ['0'..'9', #8]) then tecla := #0; end; end.
77
projeto. Primeiro acrescente a unidade ao projeto atual, usando File|Add to project... ou o da SpeedBar e escolhendo GERAL.PAS. Esse passo no estritamente boto necessrio(caso a unit GERAL esteja no mesmo diretrio que o projeto MEDIAP), mas importante para facilitar o gerenciamento do projeto, como veremos. Depois, voc deve acrescentar o nome da unidade clusula uses da unidade MEDIA.PAS, associada ao formulrio. A forma mais fcil de fazer isso a seguinte: selecione a unidade "Media" no editor de cdigo, e use o item de menu File|Use unit.... Na lista, clique em "Geral" e depois em Ok. O Delphi ir adicionar o seguinte seo de implementao da unidade: uses Geral; Agora crie um procedimento de evento para o controle 'editNumero', evento OnKeyPress. Dentro do procedimento, coloque uma chamada a 'ValidarTecla'. Inicialmente digite apenas o seguinte e deixe o cursor posicionado aps o parntese: ValidarTecla( Repare que o Delphi mostra uma descrio dos parmetros do procedimento (no caso apenas var tecla: char). Essa uma caracterstica do Code Insight que permite saber facilmente quais so os parmetros que um determinado procedimento exige e o CodeExplorer mostra o procedimento na lista. Complete a linha como abaixo: ValidarTecla(Key); Ou seja, vamos passar como argumento a varivel 'Key'. Execute o programa. Note que agora o controle 'editNumero' agora tem a mesma validao de tecla, no permitindo valores no numricos.
78
Funes
Funes so semelhantes a procedimentos, mas so chamadas geralmente dentro de uma expresso. Uma funo retorna um valor para quem chamou, e esse valor inserido na expresso onde a funo foi chamada, por exemplo: x := 3 * Soma(a,b); Durante a execuo, a funo 'Soma' chamada, com os seus parmetros preenchidos de acordo com os argumentos fornecidos (a e b). A funo ento devolve um resultado, que inserido na expresso. Depois continua o clculo do restante da expresso.
Retornando um Valor
O nome 'Result' uma varivel automaticamente criada (no precisa ser declarada) dentro de uma funo. O valor colocado nessa varivel ser o valor retornado pela funo, que ser inserido no ponto de chamada. No caso, o valor calculado como a soma dos valores dos dois parmetros (x e y). O tipo dessa varivel o tipo de retorno da funo, no caso double. Para determinar o valor de retorno, tambm pode ser usada a sintaxe de antigas verses do Pascal, com o nome da funo do lado esquerdo: Soma := x + y; A desvantagem dessa sintaxe que no possvel usar o nome 'Soma' do lado direito de uma atribuio, como possvel fazer com 'Result'. Ex: Soma := Soma + y;
Chamando a Funo
No formulrio principal, clique duas vezes no boto com o sinal de "=" (btnCalcula) para abrir o procedimento de evento associado. Neste procedimento substitua a linha: res := op1 + op2; por uma chamada funo. Inicialmente digite apenas o seguinte e deixe o cursor aps o abre parnteses: res := Soma( Note que o recurso de Code Insight do Delphi automaticamente mostra a descrio dos parmetros (x: double; y: double). Caso voc no se lembre mais dos parmetros exigidos, esse recurso facilita bastante. Complete o restante da linha, com os argumentos: res := Soma(op1, op2); Note que os argumentos so separados por "," (vrgula) na chamada. Execute o programa e verifique que ele continua funcionando como antes. Notas: Se deseja ver o contedo de um procedimento ou funo ,clique com Ctrl+Clique . Notas: Se colocou o cabealho de um procedimento ou funo na seo interface, e deseja cri-los pressione Ctrl+Shift+C.
79
Notas: Para alternar da seo implementation , para seo interface pressione Ctrl + Shift + ( ) , o contrrio utilize Ctrl+Shift + ( ).
Passagem de Parmetros
Quando um procedimento ou funo possui parmetros, ele deve ser chamado com argumentos correspondentes, na mesma ordem. Nenhum argumento deve ser omitido. (A documentao do Delphi chama os parmetros de formal parameters e argumentos de actual parameters). Por exemplo: begin ValidarTecla(Key); end; ... procedure ValidarTecla(var tecla: char);
Tipos de Passagem
Existem vrias opes disponveis para passagem de parmetros de procedimentos ou funes. (Os nomes entre colchetes esto como aparecem na documentao do Delphi): Passagem por Valor [value parameter]: o valor do argumento (que pode ser uma varivel, constante ou uma expresso) simplesmente copiado para o parmetro. Isso significa tambm que qualquer alterao no parmetro no afeta o argumento original, mas apenas uma cpia
80
local. Esse o mtodo padro de passagem, ou seja, um parmetro passado por valor se no for especificado em contrrio. A funo 'Soma' usa esse mtodo para os dois parmetros. Se o parmetro Tecla da funo Validar tecla for do tipo passagem por valor , o programa que chamar este procedimento no vai funcionar, porque o programa ir escrever os caracteres invlidos, portanto , necessrio alterar o argumento original. Passagem por Referncia [variable parameter]: o argumento deve ser uma varivel do mesmo tipo de dados do argumento. Qualquer alterao no parmetro afeta imediatamente o argumento original. Para indicar passagem por referncia, usa-se a palavra var antes do nome do parmetro. O procedimento 'ValidarTecla', por exemplo, usa passagem por referncia, porque precisa alterar o argumento original. Passagem Constante [constant parameter]: um parmetro constante (declarado com const antes do nome) no pode ser modificado dentro do procedimento. Essa caracterstica pode ser usada para impedir alteraes acidentais que violariam a lgica do programa. O argumento pode ser uma expresso qualquer. No caso de parmetros grandes, como vetores e registros, a passagem constante evita que seja feita uma cpia do argumento, como na passagem por valor, portanto bem mais eficiente. No mesmo procedimento ou funo, um parmetro pode ser passado por valor e outros por referncia ou constantes, independentemente um do outro. Funes especificamente no precisam ter parmetros por referncia, pois elas j retornam um valor atravs da prpria chamada de funo, mas em alguns casos a passagem por referncia pode ser til.
81
Captulo 11 Objetos
O que Contm um Objeto Classes e Objetos Herana Formulrios como Objetos Variveis de Objetos Listas de strings Objetos Predefinidos Code Explorer Programao Orientada a Objeto
82
Classes e Objetos
Todo objeto pertence a uma classe. Uma classe um esquema que deve como sero os objetos, quais suas caractersticas, e quais os mtodos que podem ser usados para manipular o objeto. Cada objeto especfico uma instncia da classe, criada de acordo com o modelo definido pela definio da classe. Por exemplo, cada cone da paleta de componentes corresponde a uma classe. O nome dessa (Edit) corresponde classe tem a letra 'T' antes do nome que aparece. Por exemplo, o cone classe TEdit. Quando voc seleciona esse cone e clica no formulrio, voc est criando um objeto da classe TEdit, que chamado (inicialmente) de "Edit1". Voc pode criar quantos objetos quiser da mesma classe, limitado apenas pela memria do computador. Se voc criar outros, eles sero chamados de "Edit2", "Edit3". O Object Inspector sempre mostra o nome do componente e o nome de sua classe, por exemplo:
Todos os objetos de uma mesma classe tm as mesmas caractersticas (propriedades), mas cada um tem seus prprios valores para essas caractersticas. Quando voc cria um objeto, ele comea como uma cpia idntica do modelo definido pela classe, e suas propriedades (exceto Name, que deve ser nico) comeam com os mesmos valores padro que a classe define. Depois voc pode alterar essas propriedades, diferenciando um objeto do outro. Voc pode tambm criar um objeto dinamicamente, durante a execuo do programa, conforme veremos.
83
Herana
Classes geralmente no so criadas a partir do zero. Quando voc cria uma nova classe, ela pode ser baseada em uma classe que j existe. Com isso, a classe herda todos os dados e mtodos da outra classe, mas pode acrescentar ou redefinir alguns de acordo com o que necessrio. O mecanismo de herana [inheritance] permite que voc programe apenas o que diferente entre a sua classe e a outra (programao por exceo). A classe da qual so herdadas as caractersticas chamada de classe base ou ancestral [ancestor] e a classe criada chamada de classe derivada ou descendente [descendent]. Herana no apenas uma cpia esttica de caractersticas. Qualquer alterao feita em uma classe ancestral automaticamente repercute nas classes descendentes. Quando a herana usada sucessivamente, com uma classe derivada tambm tendo classes derivadas, criada uma hierarquia [hierarchy] de classes, que pode ser representada com uma estrutura em rvore.
O Object Browser
Para visualizar a hierarquia de classes do Delphi e da sua aplicao, existe uma ferramenta que pode ser usada para isso. o Object Browser, que pode ser aberto no Delphi com o menu View|Browser (s est disponvel depois que voc compilou o projeto ao menos uma vez). Alm de classes, o Object Browser permite ver quais as constantes, tipos de dados e variveis das unidades utilizadas no projeto.
84
Campos, propriedades e mtodos de um objeto so acessados, geralmente, usando-se a sintaxe que j vimos, com o nome do objeto, seguido de um ponto e o nome do campo, propriedade ou mtodo: editTamanho.Clear; editTamanho.Enabled := True; editTamanho.SetFocus; Mas quando se acessa vrios campos do mesmo objeto, preciso repetir o nome do objeto em cada comando. Para evitar isso, existe o comando with. Dentro do bloco do comando with, o nome do objeto fica implcito: with editTamanho do begin Clear; Enabled := True; SetFocus; end;
85
A Classe de Formulrio
Abra o projeto CalcData.DPR(Captulo 8). Voc ver inicialmente o formulrio principal. Tecle [F12] para ver a unidade do formulrio. Na seo de interface da unidade, logo aps a clusula uses, voc ver a declarao da classe de formulrio: type TFormPrincipal = class(TForm) btnCalendario: TButton; btnCalculadora: TButton; btnFechar: TButton; editData: TEdit; Label1: TLabel; procedure btnFecharClick(Sender: TObject); procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean); procedure btnCalculadoraClick(Sender: TObject); procedure btnCalendarioClick(Sender: TObject); private { Private declarations } public { Public declarations } end; var formPrincipal: TFormPrincipal; A primeira linha: TFormPrincipal = class(TForm) quer dizer que a classe do formulrio baseada na classe 'TForm', que define um formulrio genrico. Veremos mais sobre isso mais tarde. Dentro da definio da classe (que vai at a palavra end), existe uma declarao para cada componente do formulrio (no caso Button ,Edit e Label). Se voc adicionar, remover, ou renomear qualquer componente, o Delphi altera automaticamente essa seo. Para testar, alterne para o formulrio com [F12] e acrescente um componente Button. Quando voc volta unidade, pode verificar que o Delphi acrescentou uma declarao para esse componente: Button1: TButton; onde 'Button1' o nome do componente e 'TButton' o nome da classe do componente, como veremos adiante. Volte ao formulrio, remova o boto e o Delphi vai tambm remover essa declarao. Depois das declaraes de componentes, comeam as declaraes para os procedimentos de evento. Para cada procedimento de evento, o Delphi adiciona uma declarao dentro da classe, como: procedure btnFecharClick(Sender: TObject); O corpo do procedimento, que fica na seo de implementao, contm os comandos que implementam realmente o procedimento. O cdigo at a palavra private mantido automaticamente pelo Delphi e voc no deve alterlo. Geralmente no existe motivo para fazer alteraes manuais. As sees private e public dentro da definio da classe so onde voc pode adicionar mais elementos. O Delphi no troca o que voc colocar em uma dessas sees. O que fica na seo private acessvel apenas na unidade atual, mas o que for declarado na seo public visvel externamente em outras unidades.
86
Com a palavra end, termina a definio da classe. Depois o Delphi acrescenta uma declarao de varivel para o formulrio. Essa declarao cria um formulrio baseado na classe definida antes:
Variveis de Objeto
Uma varivel de objeto declarada utilizando o nome da classe como um tipo de dados, como j vimos: var btnCalendario: TButton; Edit1:TEdit; formPrincipal: TFormPrincipal; O contedo de uma varivel de objeto uma referncia a um objeto, internamente armazenada como o endereo de memria onde o objeto fica armazenado. Inicialmente o contedo da varivel lixo ou, no caso de uma varivel global, ela inicializada com o valor nil. Esse um valor especial que significa no caso "nenhum objeto". Se voc tentar usar uma varivel que contm nil, isso vai causar um erro de execuo. Voc pode inicializar a varivel, criando um objeto. Para isso, use o mtodo Create (o construtor da classe), com o nome da classe, por exemplo: lista := TStringList.Create; O construtor aloca um espao de memria para conter os dados do objeto e retorna o endereo dessa memria. Dependendo da classe, o construtor pode ter parmetros usados para inicializar o objeto. Algumas classes tm construtores com outros nomes ao invs de Create. Para liberar a memria usada pelo objeto, use o mtodo Free (definido na classe TObject e herdado por todas as classes). Se voc no liberar, o espao de memria do objeto continua alocado, mesmo que no existam mais variveis para acess-lo. Por exemplo, depois de terminar de usar uma string list, voc deve liberar a memria ocupada por ela: lista.Free;
87
Quando voc atribui uma varivel de objeto a outra, no feita uma cpia fsica do objeto. A nica coisa copiada a referncia ao objeto. Depois da atribuio, ambas as variveis referenciam o mesmo objeto, por exemplo: var btn: TButton; begin btn := btnDuplicar; btn.Caption := 'Duplicar de novo'; {afeta btnDuplicar indiretamente} ... end; Vamos criar um exemplo, que quando for clicado o mouse no formulrio, vamos criar componente TButton na posio do cursor. No formulrio, altere o nome para formCriaComp e o ttulo para "Criao de Componentes". Coloque dois componente Button , faa as seguintes alteraes: Button1 btnCriar Name Caption Criar Button2 btnDestruir Name Caption Destruir Vamos criar uma propriedade na classe de formulrio 'TformCriaComp', para isto basta criar uma varivel nesta classe, como iremos armazenar nesta varivel a quantidade de botes criados,esta varivel ser publica. Na classe de formulrio 'TformCriaComp' na parte public , acrescente: TForm1 = class(TForm) ....... private { Private declarations } public { Public declarations } QuantBotao:integer; end; No evento OnClick do boto "btnCriar", faa o seguinte: var botao : TButton; begin quantBotao := quantBotao + 1; botao := TButton.create(self); with botao do begin parent := self; caption := 'Boto' + inttostr(quantBotao); left : = 0; top := 0; visible := true; end; end; Antes de criar o Boto iremos adicionar o valor 1 a propriedade quantBotao. Quando voc cria um componente,usa o construtor Create da classe TComponent. Esse construtor exige como parmetro o formulrio onde o componente ser criado. No caso, passamos 'Self'(o formulrio atual), que o mesmo que 'FormCriaComp' nesse caso. O formulrio 'Self' ser o dono[owner] do componente.Mas no caso de um controle(componente visual) preciso dizer tambm quem ser o pai[parent] desse controle. Se for o prprio formulrio, o controle fica sobre o formulrio. Mas se houver outro controle que capaz de conter controles, o pai pode ser esse outro controle. Por Exemplo: O controle Panel, se colocar esse controle sendo o pai do Boto, este ser criado em cima do Panel. Quem determina o pai do componente a propriedade Parent. Depois a propriedade caption alterada para 'Boto' mais o contedo da propriedade quantBotao, e a posio do
88
componente(propriedades Top e Left) definida com o valor Zero.A propriedade Visible faz com que o componente aparea no formulrio. No evento OnClick do boto "btnDestruir", vamos destruir o boto criado, o mtodo utilizado para liberar a memria o Free. Ento acrescente: var botao :TButton; begin botao.free end; Execute o programa. Para testar clique no boto 'Criar'. A cada clique no boto ser criado um componente da classe TButton, mas quando for destruir o componente no ir funcionar , pois, a referencia que existia para os botes que foram criados anteriormente foram perdidas. Um dos problemas ocorre porque a varivel que contm a referncia do objeto da classe TButton local, existindo somente no procedimento que foi criada. Para solucionar este problema vamos criar a varivel botao sendo global, ento vamos retirar a declarao desta varivel nos procedimentos de eventos TCriaComp.btnCriarClick e TCriaComp.btnDestruirClick. E na seo implementation acrescente a declarao desta varivel. Implementation {$R *.DFM} var botao:TButton; Mesmo colocando esta varivel sendo global o problema ainda no foi resolvido , pois, o boto 'Criar' continua permitindo a criao de mais de um boto, com isso a varivel botao sempre ir conter a referncia para o ltimo boto criado. Vamos considerar que queremos criar somente um boto de cada vez, inicialmente o boto 'Destruir' vai aparecer desabilitado, porque no temos nenhum boto criado, ao criar iremos habilitar o boto 'Destruir' e desabilitar o boto 'Criar' e quando destruir o boto vamos desabitilitar o boto 'Destruir' e habilitar o boto 'Criar'. Na propriedade Enabled do boto 'Destruir' altere seu valor para false. No envento OnClick do boto 'Criar' acrescente o cdigo a seguir: btnDestruir.enabled := true; btnCriar.enabled = false; E no evento OnClick do boto 'Destruir' acrescente: btnDestruir.enabled := true; btnCriar.enabled = false; Vamos salvar o projeto como CRIACOMP.PAS e CRIACOMPP. Execute e teste o projeto.
89
Listas de Strings
O Delphi possui um tipo de objeto que til quando se trabalha com vetores de strings. So as chamadas listas de strings [string lists]. importante saber trabalhar com esse tipo de objeto, pois vrias propriedades de componentes so do tipo lista de strings, como a propriedade Items dos controles ListBox e ComboBox, a propriedade Lines de um controle Memo, entre outras. Vamos abrir o primeiro projeto criado, AULA1P. Nesse projeto, existe um componente ListBox chamado 'ListBox1' (o nome default). No cdigo do boto Adicionar, o programa faz o seguinte: ListBox1.Items.Add(Edit1.Text); Nesse cdigo, 'ListBox1.Items' uma string list, e nesse caso, est sendo utilizado o mtodo Add da string list, que adiciona um elemento. Como essa string list est associada a 'ListBox1', o item adicionado tambm aparece na lista.
90
Voc tambm pode criar string lists independentemente de qualquer componente, declarando uma varivel do tipo TStringList, e usando o mtodo Create. Aps terminar de usar a string list, voc deve liberar a memria ocupada por ela com o mtodo Free: var lista: TStringList; begin lista := TStringList.Create; lista.Sorted := True; lista.Add('Curso'); lista.Add('Delphi'); lista.Delete(0); lista.Free; {libera memria} end;
Objetos Predefinidos
A biblioteca do Delphi contm vrios objetos predefinidos, que voc pode usar no programa sem precisar de declarar variveis para eles. Com esses objetos, voc pode utilizar funcionalidade adicional no seu programa.
O Objeto Application
O objeto Application representa a sua aplicao como um todo. Ele tem vrias propriedades e mtodos usadas internamente pelo Delphi, mas algumas delas so teis no seu prprio cdigo. A propriedade Title determina qual o ttulo que aparece no cone quando o programa minimizado. A propriedade ExeName (somente de leitura) permite voc consultar qual o nome do arquivo executvel do seu programa. Voc pode terminar a execuo do programa, em qualquer ponto, usando o mtodo Terminate. Quando voc passa muito tempo em um lao de processamento, o Delphi no tem uma oportunidade para verificar os eventos do usurio. Isso pode fazer o seu programa aparecer como se estivesse "travado" para o usurio. Para evitar isso, voc pode chamar o mtodo ProcessMessages do objeto Application, de tempos em tempos dentro do lao, o que d a oportunidade ao seu programa de processar os eventos: while not fim do begin ... Application.ProcessMessages; ... end;
O Objeto Clipboard
O objeto Clipboard representa a rea de transferncia [clipboard] do Windows, uma rea de memria usada para passar informaes entre programas. O clipboard pode ser usado para guardar texto ou imagens. Para ler ou colocar um texto no Clipboard, use a propriedade AsText, por exemplo: Clipboard.AsText := edit1.text; ... s := Clipboard.AsText; {se houver texto no clipboard, pega o valor desse texto} O mtodo Assign pode ser usado para copiar uma imagem para o Clipboard, a partir de um componente Image, por exemplo: Clipboard.Assign(image1.Picture); Para fazer o contrrio, voc pode trazer a imagem que est no Clipboard dentro de um componente Image, por exemplo: image1.Picture.Assign(Clipboard); Para saber se um determinado formato est disponvel, use o mtodo HasFormat, que retorna um valor do tipo boolean:
91
if Clipboard.HasFormat(CF_TEXT) then ... O parmetro de HasFormat pode ser: CF_TEXT para verificar se existe um texto, ou CF_BITMAP, CF_DIB, CF_IMAGE para verificar se existe uma imagem. Para usar o objeto Clipboard no programa, voc precisa acrescentar a unidade Clipbrd sua clusula uses.
O Objeto Screen
O objeto Screen representa a tela do computador e tem propriedades que permitem consultar a resoluo da tela, e saber qual o controle ou formulrio que tem o foco atualmente. As propriedades Width e Height contm, respectivamente, a largura e altura da tela em pixels. A propriedade PixelsPerInch um fator de converso, que diz quantos pixels existem em uma polegada. Com isso voc pode converter pixels em unidades fsicas e vice-versa. A propriedade Fonts um objeto TStringList que contm todos os nomes de fontes disponveis no Windows. Voc pode acessar o formulrio ativo (o que tem o foco de teclado) atravs da propriedade ActiveForm e o controle que tem o foco com a propriedade ActiveControl (do tipo TControl). A propriedade Cursor, se alterada, vai mudar o cursor do mouse de forma global para todos os formulrios. Voc pode tambm alterar o cursor para um formulrio individual, com a propriedade Cursor do formulrio.
Code Explorer
O code explorer aparece quando estamos editando uma Unit. Vamos abrir o projeto CRIACOMPP.DPR, e vamos no editor de codigo da Unit 'CriaComp', ir aparecer a seguinte janela:
O code Explorer o que parece do lado esquerdo desta janela, nele conseguimos visualizar quais so as constantes, variveis , uses e as classes utilizados na unidade que aparece no editor de cdigo. Vamos expandir cada item que aparece no code explorer e teremos o seguinte resultado:
92
Como a nica classe que foi definida dentro desta Unit 'TFormCriaComp', apareceu somento o nome dela. Nesta classe mostrado o que foi definido nas partes Public e Private. Na opo 'Variables/Constant' conseguimos obter todas as variveis globais que foram declaradas e em 'Uses' identificamos as units utilizadas.
93
Herana permite criar uma classe derivada a partir de uma classe base. A classe derivada herda a implementao da base, reutilizando o cdigo que j existe, que j foi testado e aprovado. A classe derivada pode modificar ou estender o funcionamento de mtodos j existentes. Uma classe derivada herda tambm a mesma interface da classe base. Isso quer dizer que em qualquer lugar que possa ser usado um objeto da classe TBase, ele pode ser substitudo por um objeto da classe TDerivada (porque ele suporta os mesmos mtodos). Essa possibilidade, de substituir um objeto por um de outra classe derivada, chamado polimorfismo. Com o polimorfismo, um "cliente" de uma classe (procedimento que usa objetos da classe) pode ser escrito sem se preocupar com a subclasse especfica que ele vai manipular. Futuramente, se novas subclasses so criadas, com capacidades adicionais, o cliente no precisa nem mesmo saber que elas existem, mas pode us-las como objetos da classe TBase.Claro que ainda possvel criar programas mal-estruturados, confusos, e instveis com POO. Mas se voc entender corretamente os conceitos e aplicar da forma correta os recursos da linguagem, corre um risco menor de acontecer isso.
94
95
Termos Usados
Os sistemas de programao necessrios ao funcionamento de uma empresa precisam manter dados de forma permanente, e fornecer recursos para atualizar e pesquisar nesses dados. Os recursos de linguagem que permitem isso so chamados de acesso a bancos de dados. Um registro [record] um grupo de variveis com tipos de dados diferentes, que armazenam dados relacionados. Por exemplo, um registro pode conter os dados relativos a um produto vendido pela empresa, como descrio, cdigo de identificao, quantidade em estoque. Um campo [field] um dos itens de informao dentro do registro, como a descrio do produto. Uma tabela [table] no Delphi um conjunto de registros com a mesma estrutura, armazenados de forma permanente em disco. Uma tabela pode ser um arquivo fsico, mas no necessariamente, como veremos. Algumas documentaes se referem aos registros de uma tabela como linhas [rows] e aos campos como colunas [columns]. Um banco de dados [database] um conjunto de tabelas que contm dados relacionados. Por exemplo, um sistema de contas a pagar poderia ter um banco de dados de contas a pagar, com uma tabela para duplicatas, uma tabela para bancos etc. Geralmente sistemas pequenos ou mdios usam apenas um banco de dados contendo todos os dados. Um apelido [alias] no Delphi um nome que representa um banco de dados, independente de sua localizao. Isso permite mover os dados para outro local, sem alterar o programa. Existem vrios formatos de bancos de dados que podem ser acessados pelo Delphi. Dependendo do formato, um banco de dados pode ser fisicamente um subdiretrio do disco, ou um nico arquivo. Um ndice [index, plural 'indexes' ou 'indices'] um mecanismo que permite pesquisar rapidamente um registro em uma tabela, dado o valor de um determinado campo (ou alguns campos) da tabela. Durante a execuo, cada tabela possui um registro atual ou corrente [current record], cujos dados esto disponveis para o programa. Voc pode alterar a posio de registro atual, movimentando-se seqencialmente pelos registros, ou ento usando um ndice para procurar um registro. Um recurso extremamente poderoso do acesso a bancos de dados do Delphi a consulta [query], que permite obter todo um subconjunto da tabela ou de vrias tabelas, especificando as condies de seleo. Nota: Voc pode criar um registro no Object Pascal com uma estrutura do tipo record, e manipular um arquivo de registros. Mas esse tipo de acesso no tem muitos recursos, como a possiblidade de alterar a estrutura de um arquivo, ou excluir um registro, ou pesquisar um valor.
96
Desktop x Cliente/Servidor
Uma aplicao que utiliza bancos de dados composta de trs partes: Interface com o usurio: responsvel por validar as entradas do usurio, e iniciar pesquisas de acordo com um pedido do usurio. Mecanismo de acesso a banco de dados: [database engine]: responsvel pela manuteno das estruturas de dados necessrias em arquivos, pelos detalhes internos do acesso aos dados, e pela manuteno da integridade dos dados. Armazenamento de dados: arquivos que contm os dados em si. Num computador isolado, todos os trs componentes ficam no mesmo computador. J numa rede, que envolve no mnimo uma estao e um servidor, a configurao pode ser diferente. Um banco de dados "desktop" (ou baseado em arquivos) aquele no qual a interface com o usurio e o mecanismo de acesso ficam no mesmo computador (a estao) e apenas os arquivos dados ficam num servidor de rede. Operaes de consulta ou pesquisa devem passar atravs da rede. Por exemplo, quando um usurio quer ver uma relao de contas a pagar, mas apenas em determinado perodo, o sistema deve selecionar alguns registros baseado na data informada. No ambiente desktop, a estao traz todos os registros atravs da rede, mesmo os que no so utilizados. O trfego gerado na rede grande, principalmente quando vrias estaes acessam simultaneamente o servidor. J num banco de dados cliente/servidor, a interface com o usurio fica na estao e se comunica remotamente com o mecanismo de acesso, que um sistema gerenciador de banco de dados (SGBD) rodando no servidor. Quando o SGBD recebe um pedido para selecionar alguns dados, ele acessa localmente os dados no servidor e retorna apenas o resultado pedido. No caso de uma atualizao, no necessrio nem mesmo retornar um resultado, apenas informar que a atualizao foi feita. O diagrama abaixo resume as diferenas entre os ambientes: Desktop Cliente/Servidor
Bancos de dados desktop funcionam relativamente bem quando so poucos os dados a serem acessados, ou poucas consultas feitas simultaneamente, de forma que o trfego na rede seja pequeno. Em redes maiores, recomendvel utilizar o mecanismo cliente/servidor. No Delphi voc pode comear a desenvolver sua aplicao usando um banco de dados desktop e depois migrar para cliente/servidor, com poucas modificaes no programa, pois a forma de acesso atravs do programa praticamente a mesma. Nota: De acordo com a Borland, com menos que 12 usurios simultneos, um ambiente desktop pode fornecer um timo desempenho. Mas para mais usurios, recomenda-se um sistema cliente/servidor, como o InterBase ou SQL Server por exemplo. Ambientes c/s tambm so mais confiveis.
97
de dados "nativos", mas atravs de interfaces adicionais, permite acessar praticamente qualquer banco de dados padro de mercado. Em resumo, os formatos disponveis so os seguintes: Formatos Desktop: o BDE acessa "nativamente" vrios formatos de dados no padro desktop, como Paradox, dBase, Microsoft Access e FoxPro: Paradox: correspondem ao formato utilizado pelo Paradox, um banco de dados da Borland. Cada tabela tem um arquivo separado, com a extenso DB. dBASE/FoxPro: formatos semelhantes, com pequenas diferenas. Cada tabela um arquivo separado, com a extenso DBF. Access: usado pelo Access, da Microsoft. Cada banco de dados um nico arquivo .MDB, que contm vrias tabelas. InterBase: o InterBase um banco de dados da Borland que pode ser usado para desenvolver e testar aplicaes cliente/servidor. As edies Professional e Client/Server vm com uma verso reduzida do InterBase, chamado "InterBase Local", e com drivers que podem ser usados para acessar essa verso. A edio Client/Server vem com o InterBase para Windows NT, para ambientes cliente/servidor com at 4 usurios. O InterBase armazena o banco de dados inteiro, com todas suas tabelas, num nico arquivo de extenso GDB. SQL Links: na edio Client/Server, o Delphi inclui os drivers "SQL Link", para acesso nativo a vrios formatos de bancos de dados cliente/servidor, como: Oracle, Sybase SQL Server, Microsoft SQL Server, Informix, IBM DB/2 e InterBase. ODBC: permite utilizar drivers ODBC, que um padro definido pela Microsoft, mas utilizado por vrios fabricantes de bancos de dados. Atravs do ODBC voc pode utilizar outros bancos de dados que no so suportados das outras formas. ODBC pode ser usado a partir da edio Professional. O formato que voc vai utilizar depende de se voc est acessando um banco de dados j existente, que exige um determinado formato, ou se voc est criando o banco de dados a partir do incio. Neste ltimo caso, voc pode optar por um formato desktop ou cliente/servidor, dependendo do custo necessrio e do tamanho e quantidade de acessos previsto para os seus dados.
Criando Tabelas
Aps definir qual a estrutura que devem ter suas tabelas, voc deve criar fisicamente o seu banco de dados. Dependendo do formato de dados, voc pode utilizar um programa especfico do banco de dados ou usar um utilitrio fornecido juntamente com o Delphi o Database Desktop (DBD). Chame esse utilitrio a partir do Delphi, atravs de seu cone em: |Programas|Borland Delphi 4|Database Desktop.
98
Digite o nome do campo "CodCliente" na coluna "Field Name" e tecle [Tab] ou a seta [ ] para mudar para a coluna "Type". Em tabelas Paradox, nomes de campos podem ter at 25 caracteres, e podem incluir letras, dgitos e espaos. (outros formatos de dados tm regras diferentes). Os tipos de dados em tabelas Paradox so representados por letras. Clique com o boto direito na coluna "Type" para escolher um tipo de dados ou digite diretamente a letra correspondente. Para esse campo, escolha o tipo "S" (short), que corresponde a um nmero inteiro binrio, com a mesma faixa de valores do tipo smallint do Object Pascal. O tamanho do campo determinado automaticamente, ento pule a coluna "Type". Em qualquer tipo de tabela, ndices pode ser usados para pesquisa ou ordenao de valores. Mas em tabelas Paradox, existem dois tipos de ndices. O ndice primrio [primary index] ou chave primria [primary key] determina um valor que deve ser nico para todos os registros da tabela, e tambm determina a ordem default em que os registros sero percorridos. Um ndice secundrio [secondary index] usado apenas para pesquisa e ordenao. A coluna "Key", se estiver marcada, diz que o campo parte da chave primria da tabela. (S os primeiros campos da tabela podem fazer parte da chave primria). No nosso caso, marque a coluna "Key" apenas para o campo "CodCliente". Faa isso com um duplo clique do mouse ou pressionando qualquer tecla. Tecle [ ] (seta para baixo) para definir os outros campos. Digite as caractersticas dos campos nas colunas apropriadas. Os campos "Nome" e "Telefone" so alfanumricos, isto , do tipo "Alpha". Note que eles exigem a definio do tamanho do campo, enquanto outros tipos como "Short" e "Date" no permitem uma determinao de tamanho, porque utilizam um tamanho automtico. O campo "DataNasc" do tipo "Date", que armazena datas. Note que o ano sempre armazenado com quatro dgitos, embora normalmente ele esteja configurado para mostrar apenas dois dgitos.
Salvando a Tabela
Para salvar a tabela, clique no boto "Save As...". Note que o DBD vai mostrar o diretrio de trabalho (definido anteriormente), mas tambm permite salvar em qualquer outro diretrio. Digite o nome "CLIENTE" e clique Ok. Como uma tabela Paradox, a extenso de arquivo ".DB" ser adicionada automaticamente, criando um arquivo CLIENTE.DB.
99
100
Mantenha as opes padro: "Create a simple form" em "Form Options" indica que vamos criar um formulrio "simples", que acessa uma nica tabela e "Create a form using TTable objects" em "DataSet Options" indica o tipo de componente de acesso a dados utilizado. Veremos as outras alternativas mais tarde. Clique em "Next". Agora voc deve selecionar a tabela a ser utilizada. Selecione PRODUTO.DB, que foi criada anteriormente e clique em Next. Na prxima tela, voc pode
101
escolher apenas alguns campos ou todos os campos da tabela para utilizar no formulrio. Para selecionar todos os campos, clique no boto [>>] e depois em Next. Voc pode escolher um lay-out para o formulrio. Escolha o padro "Horizontally" (Horizontal) e clique em Next. A ltima tela tem uma opo "Generate a main form" [gerar um formulrio principal]. Se ela estiver marcada, o novo formulrio ser o principal do projeto. Deixe essa opo marcada, e clique no boto "Finish".
Testando o Programa
Note que o formulrio gerado tem vrios componentes j posicionados, incluindo controles de dados para cada campo da tabela. Cada controle de dados responsvel por ler e gravar os dados de um campo. Voc pode alterar a posio e o tamanho do formulrio como quiser. Altere o Caption do formulrio para "Cadastro de Produto" e a propriedade Name para formCadProduto. Note que para alterar uma propriedade do formulrio voc deve selecionar o formulrio. Se um componente estiver selecionado, tecle [Esc] at no aparecer nenhuma indicao de seleo. O que o DFW faz quando cria um novo formulrio o mesmo processo que fizemos para criar o formulrio manualmente. Vamos alterar a propriedade Name do componente table para 'tblProduto', os componentes que tiverem alguma propriedade associada com o componente Table o Delphi automaticamente muda o nome tambm , o nome s no mudado em linhas de cdigo . No componente DataSource colocar o nome sendo 'dsProduto', como o nome do componente Table foi mudado precisamos tambm alterar um trecho de cdigo no formulrio que abre a tabela (no exemplo anterior usamos a propriedade Active). Selecione o formulrio (tecle [Esc] algumas vezes se houver algum componente selecionado) e, no Object Inspector, clique na pgina de eventos. Clique duas vezes no valor do evento OnCreate, e ir aparecer um procedimento de evento contendo: Table1.Open; Altere esse comando para: tblProduto.Open;
Salvando o Projeto
Antes de salvar o projeto, devemos remover o formulrio inicial, que no tem funo nenhuma. Isso preciso porque o Database Form Wizard cria um novo formulrio, mas no altera os anteriores. Clique em Project|Remove from project..., selecione Form1 e clique OK. Agora salve o projeto, dando os nomes de CADPRODUTO e CADPRODUTOP. Execute o projeto e cadastre alguns produtos.
Os componentes de acesso a dados, como o componente Table, lem e gravam no banco de dados. O componente DataSource faz a ligao entre estes componentes e os controles de dados, como o DBEdit.
102
O Database Explorer mostra do lado esquerdo, na pgina "Databases", uma rvore contendo os apelidos que j foram definidos. Ele permite tambm visualizar e alterar os dados de qualquer tabela, atravs de um apelido. Para criar um novo alias, clique em Object|New... Voc deve escolher o tipo de banco de dados que ser usado. Os tipos disponveis dependem de quais drivers esto instalados no computador. No nosso caso, deixe selecionado o tipo STANDARD (acesso a Paradox e dBase), que o padro. Clique Ok e o novo alias aparece na lista, com o nome provisrio de "STANDARD1". Digite "CursoDelphi" para o alias. Note que um tringulo aparece esquerda do nome, que indica que esse nome ainda no foi salvo na configurao:
103
Do lado direito, esto os parmetros de configurao do alias. O nico parmetro que importa no caso o PATH. Clique neste e digite "C:\CURSODF\TABELAS" (o diretrio onde esto os arquivos do curso). Agora clique no boto (Apply) para salvar as alteraes. Se voc quiser ver as tabelas que esto neste alias, clique no sinal de [+] ao lado do nome para abrir o alias, depois abra o cone "Tables" e voc ver as tabelas definidas. Ao clicar em uma delas, por exemplo, CLIENTE.DB, voc pode visualizar informaes gerais sobre a tabela, ou visualizar e alterar os dados, clicando na pgina "Data":
Note que aparecem botes de controle na parte superior, semelhantes ao DBNavigator. Para fechar a conexo com o alias, clique em CursoDelphi e no boto (Open Close). Agora feche o Database Explorer (ou SQL Explorer) e retorne ao Delphi. Abra um dos projetos anteriores, como o projeto CADCLIENTeP. No componente Table, primeiro altere a propriedade Active para False. Depois selecione a propriedade DatabaseName, abra a lista de valores e selecione "CursoDelphi" e altere novamente a propriedade Active para True. Faa a mesma alterao para o projeto CADPRODUTOP. A lista de valores na propriedade DatabaseName, sempre mostra quais so os aliases cadastrados. O programa vai mostrar os mesmos dados que antes, mas agora ele no mais dependente do diretrio "C:\CURSODF\TABELAS". Se voc quiser mover os dados para outro lugar, basta alterar o alias novamente, usando o Database Explorer ou o Database Desktop.
104
105
Definindo Tabelas
Durante o curso, iremos desenvolver um mini-sistema de controle de vendas, no qual teremos um cadastro de clientes, um controle das vendas efetuadas para cada cliente e de itens vendidos para cada venda. Isso vai envolver vrias tabelas adicionais no nosso banco de dados. O modelo abaixo mostra como esto relacionadas as tabelas que sero utilizadas no nosso exemplo:
Volte ao Database Desktop para definir tabelas adicionais e alterar a estrutura da tabela de cliente, criada anteriormente.
106
107
Tipo S S S
Chave * *
Defina tambm um ndice secundrio no campo CodVenda. Isso necessrio para que o Delphi possa tratar o relacionamento mais tarde. Para definir um ndice secundrio, faa como antes: selecione "Secondary Indexes", clique no boto "Define...", selecione o campo CodVenda e clique Ok. D o nome de "IndVenda" para o ndice e clique Ok. Salve a tabela com o boto "Save as...", dando o nome de ITEM.db (lembre-se que a extenso no precisa ser digitada). Depois feche o DBD e retorne ao Delphi. Nota: nomes de tabelas podem ter at 253 caracteres (fora extenso), mas melhor usar um nome com oito ou menos caracteres para manter compatiblidade com programas mais antigos.
108
O Menu Designer mostra uma simulao do menu e permite voc criar os itens de menu que voc vai utilizar. medida que voc criar itens de menu, o Object Inspector vai mostrar as propriedades do item selecionado. Para criar o primeiro item, simplesmente digite "Cadastro" (sem as aspas) e tecle [Enter]. O Menu Designer vai mudar para a seguinte aparncia:
direita e abaixo do item, sempre ficam disponveis retngulos vazios que voc pode preencher para criar novos itens. Se voc no os preencher, eles no vo aparecer no menu final. Agora digite o texto do prximo item: "Cliente" e tecle [Enter]. O marcador vai passar para a prxima linha. Crie mais um item "Produto". Agora crie o item "Fornecedor". Em seguida crie uma barra separadora no prximo item. Para criar uma barra separadora, digite "-" (um sinal de menos). Depois da barra, crie um item "Venda", crie novamente uma barra separadora e finalmente crie mais um item "Sair". A aparncia final vai ficar como na figura:
109
Quando voc digita o texto do menu, voc est alterando a propriedade Caption de cada item de menu. O Object Inspector automaticamente altera a propriedade Name de cada item para ser igual ao valor do Caption, com um nmero acrescentado ao final (por exemplo, Cadastro1). Ns vamos mudar esses nomes para definir um padro mais descritivo. Clique no item "Cadastro" e na propriedade Name, troque "Cadastro1" (o nome que o Delphi colocou automaticamente), por "menuCadastro". Faa de forma semelhante para os outros itens, de acordo com a tabela: Cliente 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". Abaixo desse item, 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
Nota: O Menu Designer tem outras facilidades tambm. Para inserir um item de menu no meio, pressione a tecla [Ins]. Para excluir um item de menu, use o [Ctrl+Del]. Para definir um nvel adicional de submenu, use [Ctrl+seta para direita].
111
&Fornecedores &Sair C&onsultas Clientes por &Estado &Vendas por Cliente &Relatrio &Clientes &Vendas por Produto
Agora, o item Cadastro|Cliente, por exemplo, pode ser acionado com as teclas [Alt+C,C]. Outra forma de acionar itens de menu atravs de teclas de atalho [shortcut keys]. A diferena que teclas de atalho podem ser usadas mesmo quando o menu no est aberto, esteja onde estiver o foco de teclado, e no precisam ser letras. Se voc abrir um menu do Delphi, ver que teclas de atalho aparecem direita do item, como [Ctrl+S], [F5], [Ctrl+F7] etc. S itens de menu podem ter teclas de atalho (no os menus da barra principal). Ainda no Menu Designer, clique no item "Clientes" e na propriedade Shortcut [atalho]. Selecione da lista a opo "Ctrl+K". Para "Vendas...", coloque "Ctrl+E".Para "Produtos" , coloque "Ctrl+P". Note tambm que o item Sair no tem uma tecla de atalho. Isso porque j existe um atalho definido pelo Windows para sair de um programa qualquer: [Alt+F4]. De forma geral, bom tentar economizar teclas de atalho, e s colocar essas teclas nos itens mais utilizados do programa. Se voc tem muitas teclas de atalho, o usurio no conseguir memoriz-las, e isso desvia do propsito original desse tipo de acesso. Nota:Voc no deve repetir a mesma tecla em um grupo de itens do mesmo nvel. O Delphi permite fazer isso, mas a tecla no vai funcionar da forma esperada. J itens em menus diferentes podem usar a mesma tecla sem problemas. Nota: Teclas de atalho devem ser nicas entre todos os itens de menu. Execute o programa e teste as teclas. Voc no precisa abrir um menu para acionar a tecla correspondente a um item. Note que nos itens separadores, o Delphi coloca momes padro(N1 e N2), que voc no precisa alterar. A propriedade ShortCut fornece um acesso rpido pelo teclado em alguns itens.
112
O formulrio principal, que contm os itens de menu, ir chamar cada um dos formulrios criados. Para que ele possa fazer isso, a unidade principal deve ter uma clusula uses, com os nomes de todas as unidades. Fique posicionado na unit "VendPrin" . nessa unidade logo aps a palavra implementation, acrescente: uses CadCliente, CadProduto; Agora tecle [F12] para voltar ao formulrio. Clique no item de menu Cadastro|Clientes e, no procedimento de evento, coloque o seguinte comando: formCadCliente.Show; Iremos fazer a mesma coisa para o Produto. Clique no item de menu Cadastro|Produto e , no procedimento de evento, coloque : formCadProduto.Show; Salve o projeto e depois execute o programa.Note que no incio da execuo, aparece apenas o formulrio principal. Ao clicar em um item de menu, por exemplo Cadastro|Clientes, aparece o formulrio correspondente. Voc pode clicar novamente no formulrio principal e abrir outro formulrio. Como os formulrios no so modais, vrios formulrios podem estar na tela ativos simultaneamente.
113
begin formConsClienteEstado.show; end; Salvar esta unit como CONSCLIENTEESTADO. Acrescente na unit VendPrin na seo implementation, uma uses para a unit ConsClienteEstado. Ficando desta forma: uses CadCliente, CadProduto, ConsClienteEstado; Execute o programa, clique no menu Consultas|Clientes por Estado e verifique o funcionamento do DBGrid, que bem semelhante a uma grade de dados do Database Desktop. Voc pode usar as setas para mover entre campos (linhas) e registros (colunas). Quando voc tenta sair de um campo, se voc digitou um dado invlido, imediatamente ver uma mensagem de erro (por exemplo, no campo DataNasc). Quando voc sai de uma linha, os dados do registro so imediatamente gravados. Para alterar um campo, editando o valor existente, pressione [F2]. Para inserir um registro, voc pode descer abaixo do ltimo registro, ou teclar [Insert]. Para excluir um registro, tecle [Ctrl+Del]. Nota: voc tambm pode alterar caractersticas das colunas se voc clicar duas vezes no prprio DBGrid. Essas alteraes tm prioridade sobre as propriedades dos campos da tabela e voc tem outras opes como, por exemplo, mudar a cor do campo. Mas geralmente no necessrio alterar opes no prprio DBGrid.
114
A opo "Character for blanks" define qual o caractere que ser usado nos espaos vazios durante a digitao. Geralmente melhor manter o padro, '_' (sublinhado). Quando voc altera essa opo, o caractere adicionado ao final da mscara. Para testar a mscara, na mesma janela voc pode digitar alguma coisa em Test Input. Se voc digitar e no conseguir sair do campo (o Delphi vai mostrar uma mensagem), tecle [Esc] e tente novamente. Vamos definir uma mscara para edio no campo "DataNasc". Ento no editor de campos, clique no campo "DataNasc". No Object Inspector, clique na propriedade EditMask , em "Sample Masks" clique na opo "date" , esta opo contm uma mscara para data. O contedo de "Input Mask" ser '!99/99/00;1;_', substitua o '0' por '9', a diferena de utilizar 0 ou 9 que quando colocamos '0' fazendo parte da mscara, quer dizer que naquele local o usurio obrigado a informar algum nmero, se utilizar '9' aceita somente nmeros, mas no obirgatrio. importante que a opo "Save literal characters" esteja marcada , pois, as barras so gravadas no campo.
115
116
Altere o nome do controle de edio para 'editEstado'e sua propriedade CharCase para 'ecUpperCase', deixe a propriedade Text vazia. Isso faz com que todas as letras digitadas sejam convertidas em maisculas. Chame o boto de 'btnProcurar' e mude sua propriedade Default para True. No evento OnClick do boto 'btnProcurar', vamos alterar a propriedade Filter do componente Table dinamicamente,com esta propriedade iremos definir um filtro que ir procurar os clientes que pertencem ao estado indicado.Digite o seguinte: tblCliente.Filter := 'Estado = ''' + editEstado.text + ''''; tblCliente.Filtered := true; tblCliente.Open; Note que para modificar a propriedade Filter, usamos vrios apstrofos na sintaxe. Cada dois apstrofos na string representam um apstrofo na string resultante. Por exemplo, se editEstado = 'GO' a string do Filter vai conter : Estado = 'GO' Mas a propriedade Filter funciona somente se a propriedade Filtered for True.Aps a alterao da propriedade necessrio abrir o componente Table novamente para ver o resultado. Salve o formulrio e execute. Para testar informe alguns estados e clique no boto 'Procurar'. Notas: O paradox "case sensitive", portanto ele faz diferenciao entre letras maisculas e minsculas. Exceo somente quando cria um ndice secundrio para o campo e a opo "case sensitive" deve estar desmarcada.
117
Note que ainda faltam no formulrio controles de dados para os novos campos que foram acrescentados por ltimo: CPF, Cidade e Estado. Os objetos foram criados , falta criar os controles de dados. Clique duas vezes em 'tblCliente' (o nico componente Table do formulrio) para abrir o editor de campos. Agora arraste, um de cada vez, os campos CPF, Cidade e Estado para o formulrio. Deixe o formulrio com a aparncia semelhante a figura abaixo:
Validando Campos
Para fazer a validao de campo, voc deve tratar o evento OnValidate. Esse um evento do componente TField associado ao campo. Vamos adicionar uma validao ao campo CPF. Para este projeto foi criado uma unit independente chamada GeralVenda que contm uma funo para fazer a verificao do CPF, a idia no explicar como funciona a verificao de CPF , mas de como fazer esse tipo de verificao no Delphi, segue tambm nesta unit uma rotina para verificao de CGC.Ento iremos utiliz-la para verificar se um determinado CPF foi informado corretamente.O nome da funo ValidaCPF ela retorna true se o CPF estiver correto, temos que passar como parmetro um valor do tipo 'String'. Notas:Para verificar se um cpf vlido ou no, primeiro certifique que ele tenha 11 dgitos. Os dois ltimos dgitos so utilizados para verificao. Declare algumas variveis: var soma, somaDig, pos, resto : smallint; A constante ordZero contm a posio do nmero 0 na tabela Ascii. A verificao do penltimo dgito feita atravs da soma dos dgitos at a posio , cada dgito necessrio multiplicar por 11 e subtrair pela sua posio, necessrio tambm ter a soma de todos os dgitos at a posio 9..
118
for pos := 1 to 9 do begin soma := soma + (ord(textoCPF[pos]) - ordZero) * (11 pos); somaDig := SomaDig + (ord(textoCPF[pos]) - ordZero); end; Verificao do Penltimo Dgito: Divida o contedo da varivel soma por 11,faa a subtrao do resto pelo nmero 11 e atribua a uma varivel, se o contedo desta varivel for maior que 9, altere o contedo da variavel para 0, em seguida verifique se o contedo desta varivel diferente do penltimo digito do CPF, se for CPF invlido, caso contrrio necessrio verificar o ltimo dgito. resto := 11 - soma mod 11; if resto > 9 then resto := 0; if resto <> ord(textoCPF[10] - ordZero then exit; {DV errado} Para verificar o ltimo dgito nessrio somar os resultados encontrados nos calculos anteriores. Ento Soma + SomaDig + 2 * resto , dividir este resultado por 11, o resto subtrair por 11 , se o resultado obtido for maior que 9 , atribuir 0 a esse resultado, em seguida verificar se o resultado encontrado igual ao ltimo dgito verificador , se for igual CPF Vlido. soma := soma + somaDig + 2 * resto; resto := 11 - soma mod 11; if resto > 9 then resto := 0; if resto <> ord(textoCPF[11]) - ordZero then exit; { segundo DV errado } Result := True; { tudo certo } No formulrio "formCadCliente" abra o editor de campos para tblCliente e clique no campo CPF na lista. No Object Inspector, abra a pgina de eventos e crie um procedimento de evento para OnValidate. Neste procedimento de eventos, adicione o seguinte: begin if not ValidaCPF(tblClienteCpf.value) then begin ShowMessage('CPF Invlido!'); Abort; end; end; A funo ValidaCPF verifica se o CPF esta correto.Caso esteja errado, o procedimento mostra uma mensagem, com ShowMessage e gera uma exceo com o procedimento Abort. Qualquer exceo gerada faz com que o Delphi cancele a movimentao de campo ou de registro, mas melhor usar Abort porque ele gera uma exceo silenciosa, da classe EAbort, que no mostra nenhuma mensagem de erro alm das mensagens do seu programa. Antes de executar o programa na seo Implementation da Unit CADCLIENTE acrescente uma clausula uses para a unit independente: uses GeralVenda; Para adicionar a Unit ao projeto , no menu Project|Add to Project ( ), escolha a unit "GERALVENDAS.PAS" em seguida clique no boto "Abrir". Execute o programa e veja o que acontece. Altere um registro existente, digitando um valor para o CPF, Invlido e tecle [Tab] para tentar mudar de campo. Voc deve digitar um valor vlido ou teclar [Esc] para retornar ao valor anterior do campo. importante notar que a validao de campo s acontece quando o usurio edita o campo. Um registro j existente, que tenha um valor invlido, no passar pela validao a no ser que o usurio altere o valor do campo CPF. Nota: Quando vrios controles esto associados ao mesmo campo, as alteraes de propriedade afetam todos eles.
119
Validando Registros
Para fazer uma validao de registro, voc pode utilizar o evento BeforePost do componente Table. Esse evento executado logo antes do registro ser gravado, seja um novo registro ou do um registro j existente. Essa gravao pode ocorrer quando o usurio clica no boto DBNavigator ou quando ele muda de registro, se o registro foi alterado. Selecione o componente 'tblCliente', e na pgina de eventos, clique duas vezes no valor de BeforePost. Neste evento vamos fazer o seguinte: begin if tblClienteNome.IsNull then begin ShowMessage('O nome obrigatrio'); tblClienteNome.FocusControl; Abort; end; if tblClienteCidade.IsNull then begin ShowMessage('A cidade obrigatrio'); tblClienteCidade.FocusControl; Abort; end; end; A propriedade IsNull de um componente TField retorna True se ele tem um valor nulo, isto , vazio, no informado. Se o campo estiver vazio, o procedimento mostra uma mensagem e chama o mtodo FocusControl do componente. Esse mtodo coloca o foco no controle de dados associado (com isso no preciso saber o nome do controle DBEdit ligado ao campo). Depois de fazer isso, o procedimento chama Abort para cancelar a gravao do registro. Com a validao de registro, o usurio s tem duas opes: ou digitar valores vlidos, ou do DBNavigator. Execute o programa e note que cancelar a edio do campo, com o boto agora essa validao tambm feita se voc incluir um registro e tentar grav-lo. Salve e execute o programa. Para testar crie um novo cliente , no informe seu nome , mas coloque o nome da cidade onde ele mora, ao salvar o cliente , o cliente no ser salvo enquanto no informar o seu nome. Notas: A verificao se um campo ou no obrigatrio pode ser no banco de dados e no Delphi podemos fazer a verificao atravs de erros.Veremos nos prximos captulos.
120
Tratamento de Excees
Desmarque a opo " Stop on Delphi Exceptions" no menu Tools | Debugger Options | Language Exceptions. Mas tarde iremos entender o motivo. Observe que ao digitar uma data invlida , ocorre a seguinte mensagem:
Esta mensagem que aparece um erro de execuo, ou seja, uma mensagem do Delphi avisando de uma condio de erro.O termo usado no Delphi para essas situaes exceo.Uma exceo[exception] uma condio anormal que ocorre durante a execuo do programa, que interrompe o seu funcionamento. Quando ocorre uma exceo, o Delphi mostra uma mensagem padro e termina a execuo do procedimento de evento atual, mas continua a responder a eventos e executar o programa.Para qualquer exceo, voc pode fazer seu prprio tratamento, interceptando o tratamento do Delphi. Para tratar essa exceo voc tem que utilizar um evento que ocorra antes da mensagem de erro. Como o componente est associado a um objeto de campo , podemos fazer este tratamento nos eventos do objeto de campo. Clique duas vezes no componente tblCliente ) para abrir o editor de campos. Clique no campo "DataNasc" e crie um procedimento ( para o evento OnSetText . Esse evento executado todas as vezes que alterado o contedo do objeto de campo. Neste procedimento o parmetro "Text" contm o valor da data informada. Coloque o cdigo a abaixo: var Data : TDateTime; begin try data := strtodate(text); tblClienteDataNasc.asDatetime := data; except on EConvertError do begin showmessage('Data Invlida!'); abort; end; end; end; O comando try (tentar) um comando de tratamento de excees. Os comandos entre o try e o except so executados, mas se ocorre alguma exceo nesse bloco, o Delphi sai do bloco e entra na parte except[exceto]. Ento o Delphi procura uma clusula on correspondente classe da exceo gerada. Se ele encontra um on correspondente, ele executa o comando de tratamento associado. Depois de executar o tratador, o Delphi no termina a execuo do procedimento de evento, mas continua a execuo com o prximo comando depois do end do try. A funo strtodate converte uma varivel do tipo string para data, caso ocorra algum erro gera uma exceo da classe 'EConvertError', se ocorrer a exceo mostramos a mensagem 'Data Invlida' , em seguida o comando abort executado ,es este comando cancela o procedimento, se ele no for colocado a mensagem do Delphi ir continuar aparecendo. Quando colocamos algum procedimento para este evento , ao sair do procedimento a data
121
informada no ser colocada no objeto de campo, por isso que atribuimos o valor da data ao objeto 'tblClienteDataNasc'.
ou seja , o projeto causou uma exceo da classe 'EConvertError'. O nome da classe de exceo uma informao importante quando voc fizer o tratamento da exceo no programa. Para continuar a execuo, tecle[F9] ou clique no boto (Run). Depois ir aparecer a mensagem que colocamos ( caso no tenha tratado a exceo aparece a mensagem do Delphi).
Classes de Excees
Quando voc faz o tratamento de excees, pode trat-las a nvel especfico de cada exceo ou voc pode tratar uma classe de exceo mais geral. As classes fazem parte de uma hierarquia de excees, como a seguinte: Exception (qualquer exceo) EIntError (erros de nmeros inteiros) EDivByZero (diviso por zero de inteiro) EIntOverflow (transbordo inteiro) ERangeError (valor ou ind. vetor fora de faixa) EMathError (erros de matemtica real) EOverflow (transbordo de real) EUnderflow (valor muito peq. de real) EZeroDivide (diviso por zero de real) Se voc criar uma clusula de tratamento para uma exceo mais geral, como 'EMathError', ela ser acionada para qualquer uma das classes abaixo na hierarquia, seja diviso por zero (EZeroDivide), transbordo de valor (EOverflow) ou qualquer outra. A classe Exception o nvel mais geral de tratamento e intercepta qualquer exceo. Se num conjunto de tratadores, voc colocar um tratador primeiro para uma exceo mais geral e depois para uma exceo especfica, o tratador mais especfico nem vai chegar a ser executado. Notas: O tratamento de exceo pode ser feito em qualquer procedimento que julgar necessrio.
Pesquisas na Tabela
Uma caracterstica fundamental de um programa permitir que o usurio faa uma pesquisa em uma tabela, fornecendo o valor a ser pesquisado. Na tabela de clientes, vamos facilitar a pesquisa pelo nome do cliente.
Adicionando um DBGrid
Para isso vamos adicionar ao formulrio um controle DBGrid, que vai mostrar toda a lista de clientes, permitindo selecionar qualquer um deles. Abra um espao adicional direita do
122
formulrio e acrescente um componente Label, com o texto "Procura:" e um componente Edit (no use um DBEdit), com o nome de "editProcura". Abaixo deles acrescente um componente DBGrid (cone da pgina Data Controls). O formulrio deve ficar como o seguinte:
Agora associe a grade (DBGrid) com a tabela, alterando sua propriedade DataSource para 'dsCliente'. Com isso, se a tabela estiver ativa, ele vai automaticamente mostrar todos os campos e todos os registros da tabela. No vamos permitir que o usurio altere os dados usando o grid. Para isso basta mudar a sua propriedade ReadOnly para True. Vamos restringir os campos mostrados apenas ao campo "Nome". Para isso, clique duas vezes em 'tblCliente' para abrir o editor de campos, selecione todos os campos menos Nome e altere a propriedade Visible para False. Se preciso, reduza o DisplayWidth para que o valor do campo aparea todo no Grid. Algumas caractersticas de visualizao do DBGrid no so necessrias aqui, como as linhas divisrias de registros e campos, ou os ttulos da parte de cima. Vamos desativar essas caractersticas, alterando a propriedade Options. Expanda essa propriedade no Object Inspector e altere as seguintes opes: Opo Valor Finalidade dgEditing False no permite incluir ou excluir dgTitles False desativa os ttulos dgIndicator False desativa o indicador de registro dgColLines False desativa as linhas verticais dgRowLines False desativa as linhas horizontais dgTabs False no usa [Tab] para mudar de campo dgAlwaysShowSelection True sempre mostra a linha selecionada Se a opo 'dgAlwaysShowSelection' estiver desativada, o grid s mostra qual a linha selecionada (a do registro atual) quando ele tem o foco de teclado. Ns devemos ativ-la para que o usurio saiba qual o nome selecionado na lista a qualquer momento. Execute o programa e verifique. Voc pode clicar na grade a qualquer momento para selecionar um dos registros, ou usar o DBNavigator para percorrer os registros. Nota: existem duas opes parecidas: dgAlwaysShowEditor e dgAlwaysShowSelection. Para visualizar melhor as opes, aumente a largura do Object Inspector.
123
Para mudar a ordem dos registros, podemos usar um ndice diferente. Para ordenar por nome, que o necessrio, precisamos usar o ndice criado para o campo Nome. Para isso, basta alterar a propriedade IndexName do componente Table. Se ela estiver vazia, a ordem dos registros ser determinada pelo ndice primrio da tabela. Se voc colocar o nome de um ndice secundrio, a ordem ser de acordo com esse ndice. Essa propriedade afeta tanto a ordem virtual dos registros, quanto as pesquisas que voc fizer, como veremos. Clique na propriedade IndexName e selecione o nome "IndNome" da lista. Esse o nome do ndice secundrio criado. Note como a ordem dos registros alterada no controle DBGrid. Se voc apagar o valor de IndexName, a ordem volta a ser a do campo CodCliente. Alm da propriedade IndexName, existe outra chamada IndexFieldNames, que tem a mesma funo. O valor desta propriedade a lista dos campos que compem o ndice. Por exemplo, voc poderia colocar "Nome" em IndexFieldNames e teria o mesmo efeito. Isto til se voc no souber o nome do ndice, mas se souber quais os campos que fazem parte dele. As duas propriedades so mutuamente exclusivas: se voc altera uma, a outra ter seu valor eliminado.
Mude o Caption do label para "Cdigo:". Mude o Name do componente Edit para 'editProcCodigo' , a propriedade Text deixe vazia e o nome do boto para 'btnProcCodigo' e altere a propriedade caption para "Procurar". Agora clique duas vezes no boto Procurar. Neste procedimento, vamos usar o valor digitado para pesquisar na tabela, usando o mtodo FindKey. Como vamos pesquisar por um campo diferente, devemos alterar a propriedade IndexName do componente dinamicamente, e depois retorn-la ao original. Isso gera um pequeno problema ao alterar essa propriedade, os controles do formulrio vo mudar para refletir o novo ndice. Isso pode ser evitado com o
124
mtodo DisableControls do componente Table. Quando ele chamado, os controles de dados no atualizam mais seus valores at que o mtodo EnableControls seja chamado. Com isso, coloque o seguinte no cdigo do procedimento: var codigo: integer; begin codigo := StrToInt(editProcCodigo.Text); with tblCliente do try DisableControls; IndexName := ''; {usando ndice primrio} if not FindKey([codigo]) then ShowMessage('Codigo no encontrado'); finally IndexName := 'IndNome'; {usando ndice por Nome} EnableControls; end; end; O mtodo FindKey uma funo que retorna True se encontrou o registro. Caso ele encontre, ele posiciona no registro, seno mantm posicionado no registro atual.
Blocos Protegidos
Os tratamentos de erros no Delphi podem ser feitos para uma exceo especfica. As vezes , no necessrio tratar um exceo especfica , mas preciso realizar uma ao de finalizao, O finally utilizado quando uma determinada exceo ocorre , e necessitamos executar de qualquer forma um determinado comando ou vrios comandos antes de interromper o procedimento. Esses comandos devem ser colocados no trecho finally..end. Em geral , blocos protegidos podem ser usados em qualquer situao que envolva uma alocao e liberao de recursos(como um arquivo , por exemplo). No procedimento de evento do OnClick observe que a alterao de IndexName e a chamada de EnableControls so feitas no bloco finally. Isso significa que mesmo que acontea uma exceo, esses comandos so executados. Isso importante, pois se esse tipo de tratamento no for feito, os controles de dados podem ficar num estado desabilitado, e o usurio no conseguiria mais utilizar o programa. Execute e verifique o resultado. Se voc digitar um cdigo e clicar no boto Procurar, o programa vai tentar procurar o registro.
125
126
127
Avana 'n' registros. Se 'n' for positivo, move para frente. Se 'n' for negativo, move para trs. Repare que cada um deles, exceto MoveBy, equivalente a um boto correspondente do controle DBNavigator. Na verdade, o DBNavigator apenas chama os mtodos correspondentes do componente Table, em resposta ao clique do usurio. Lembre-se que a ordem em que os registros aparecem quando voc percorre seqencialmente a ordem determinada pelo ndice que estiver sendo utilizado no momento. Quando a tabela aberta, o ndice utilizado o ndice primrio, mas isso pode ser alterado. Para ler os campos do registro atual, existem duas formas. Se voc usou o editor de campos para criar uma lista de componentes TField, cada um deles tem um nome, que formado pelo nome do componente Table, mais o nome do campo. Com isso, basta acessar a propriedade Value do componente TField: preco := tblItemPrecoVenda.Value; quant := tblItemQuantidade.Value; Mas se voc no criou uma lista de campos, os componentes TField so criados internamente e no tm nome, mas ainda podem ser acessados com o mtodo FieldByName: preco := tblItem.FieldByName('PrecoVenda').AsFloat; quant := tblItem.FieldByName('Quantidade').AsInteger; As propriedades AsFloat e AsInteger so necessrias nesse caso, para especificar qual o tipo de dados que voc est acessando. No caso de um componente criado explicitamente, o Delphi j sabe o tipo de campo pela declarao, ento voc pode usar Value, que tem o mesmo tipo de dados do campo. Da mesma forma, existem outras propriedades "As*", como AsString, AsDate, que retornam o valor do campo convertido para um determinado tipo de dados. Voc no pode atribuir valores para a propriedade Value ou As* do componente se voc estiver em modo de percorrer registros. Quando voc est percorrendo a tabela, existem duas propriedades teis, ambas do tipo boolean. A propriedade EOF verdadeira quando voc estiver posicionado no fim da tabela,
128
depois do ltimo registro. J BOF verdadeira quando voc estiver posicionado no incio da tabela. Por exemplo, para percorrer a tabela do incio ao fim. with tblItem do begin First; { vai para o primeiro registro } while not EOF do begin preco := tblItemPrecoVenda.Value; quant := tblItemQuantidade.Value; ... Next; { vai para o prximo registro } end; end; Se ambas forem verdadeiras, a tabela est vazia, no tem nenhum registro: if tblItem.BOF and tblItem.EOF then ShowMessage('A tabela est vazia');
Coloque um label, com o texto "Total:" e um controle de edio, com o nome 'editTotal', que ir mostrar o resultado final. Finalmente coloque um boto, com o texto 'Totalizar' e nome 'btnTotalizar'. Clique duas vezes no 'tblItem' para abrir o editor de campos. Acrescente todos os campos lista. Repare que se voc clicar em um nome de campo, por exemplo 'Quantidade', voc ver que a propriedade Name do objeto de campo tblItemQuantidade. Esse o nome que voc deve utilizar no programa para acessar o valor do campo. Clique duas vezes no boto Totalizar e digite o seguinte: var total: double; begin total := 0; with tblItem do begin Open; First; while not EOF do begin total := total + tblItemQuantidade.Value ; Next; end; Close; end; editTotal.Text := FloatToStr(total); end; Dentro do with, a primeira linha chama o mtodo Open para abrir a tabela. Isso no seria necessrio se a propriedade Active j tivesse o valor True no incio da execuo. Depois First posiciona no primeiro registro. Essa chamada no realmente necessria, porque logo depois de abrir a tabela, o registro atual j o primeiro.
129
O lao while verifica o valor da propriedade EOF. Enquanto ela for falsa (not EOF), o lao percorre os registros. Para cada registro, o campo Quantidade somado com varivel 'total'. Note a forma de acesso aos campos: com os nomes dos objetos TField, usando sua propriedade Value. Depois de somar o valor, o mtodo Next muda para o prximo registro. Depois do lao, o mtodo Close fecha a tabela (faz Active = False), e finalmente o resultado final, acumulado em 'total', mostrado no controle 'editTotal'. Execute o programa e clique no boto Totalizar para ver o resultado. Salve o projeto como TOTALITEM.PAS E TOTALITEMP.DPR.
130
Acrescentando Registros
Para incluir um novo registro na tabela, voc deve chamar o mtodo Insert ou Append. Se a tabela no tem ndice primrio, Insert insere um novo registro no meio da tabela e Append acrescenta o novo registro ao final. Para uma tabela que tem chave primria, os dois mtodos fazem exatamente a mesma coisa: o registro ser inserido na posio determinada pela chave. Assim, o que discutiremos sobre Insert se aplica igualmente a Append. Quando voc chama Insert, ele no grava dados na tabela. Ele apenas cria um novo registro vazio em memria. Depois voc deve preencher os campos desse registro com os seus valores, usando os objetos TField. Para gravar os dados, chame o mtodo Post. O novo registro ser o registro atual da tabela, e vai se tornar o registro atual. A posio do registro na tabela ser determinada pelo valor da sua chave primria. Por exemplo: codigo := 20;
131
with tblItem do begin Insert; tblItemCodItem.Value := codigo; tblItemQuantidade.Value := quant; tblItemPrecoVenda.Value := preco; Post; end; Se voc quiser cancelar a insero do novo registro, use o mtodo Cancel. Quando voc cancela, a posio de registro volta ao registro onde voc estava posicionado antes de chamar Insert. Se voc mudar de registro aps chamar Insert, o componente vai verificar se voc alterou algum campo, e vai gravar o novo registro, caso tenha havido alterao, ou cancelar a incluso, caso voc tenha deixado o registro inteiro em branco. , que chama Quando voc usa o controle DBNavigator, o usurio pode clicar no boto automaticamente o mtodo Insert da tabela. Depois ele preenche os campos e clica no boto , que chama o mtodo Post, ou no boto , que chama o mtodo Cancel. Quando voc usa o controle DBGrid, o usurio pode pressionar a tecla [Insert] para chamar o mtodo Insert, preencher os campos, e mudar de registro.
Excluindo Registros
Para excluir o registro atual, use o mtodo Delete: tblItem.Delete; A operao de excluso executada imediatamente e no pode ser desfeita. Registros excludos no podem ser recuperados. Usando o controle DBNavigator, o usurio pode clicar no boto , que chama esse mtodo automaticamente. Usando o controle DBGrid, o usurio pode pressionar [Ctrl+Delete] para excluir o registro atual. Esses dois controles tm uma propriedade ConfirmDelete. Se ela estiver verdadeira (valor True), o controle mostra uma mensagem de confirmao predefinida, seno exclui o registro imediatamente.
Outros Mtodos
Quando voc trabalha com os mtodos do componente Table, o efeito dos mtodos (edio, incluso, ou movimentao) aparece imediatamente nos controles de dados (se houver). Essa atualizao dos controles geralmente desnecessrio, e toma um certo tempo, tornando muito demorada uma operao com vrios registros, por exemplo. Voc pode desabilitar temporariamente a atualizao dos controles, com o mtodo DisableControls e depois habilitar novamente a atualizao com o mtodo EnableControls. Quando voc chama EnableControls, todos os controles de dados ficam "congelados" com seus valores atuais. Por exemplo: with tblItem do begin DisableControls; while not EOF do ... EnableControls; end; Se voc no lembrar de habilitar os controles de dados, eles ficam inutilizveis pelo usurio. Note tambm que se acontecer uma exceo depois de desabilitar os controles, o Delphi vai sair do procedimento e eles no sero habilitados novamente. Para evitar essa ltima situao, use um comando try..finally: try DisableControls; while not EOF do ... finally EnableControls; end;
132
Um comando try..finally garante que a parte do finally sempre executada, seja numa execuo normal, ou quando ocorre uma exceo no bloco do try. Nesse caso, isso garante que os controles de dados so habilitados novamente. Numa rede, os registros que esto sendo visualizados podem ficar desatualizados medida que outros usurios adicionam novos registros. Para obter os registros mais atualizados da tabela, voc pode usar o mtodo Refresh: tblCliente.Refresh; Esse mtodo chamado automaticamente pelo boto do DBNavigator.
133
134
Manipulao de Datas
O Delphi permite armazenar datas e horas no banco de dados, em campos do tipo Date (apenas datas), ou do tipo Time (apenas horas), ou campos Date/Time ou Timestamp (guarda data e hora), em alguns bancos de dados. importante tambm saber nesse caso as funes disponveis para manipulao de datas. O Delphi codifica datas e horas internamente como nmeros, que representam uma contagem de dias desde 1/1/0001. Ele usa o tipo de dados TDateTime para esse formato codificado. Voc pode usar a funo EncodeDate para gerar esse valor codificado, e o procedimento DecodeDate para obter os componentes da data separados (dia, ms e ano). Por exemplo: var data: TDateTime; ... begin ... data := EncodeDate( ano, mes, dia ); .... DecodeDate( data, ano, mes, dia ); ... end; Para tratamento de horas, voc tem semelhantemente as rotinas EncodeTime e DecodeTime, que de forma genrica, so usadas assim: varHora := EncodeTime( horas, minutos, segundos, milisegs ); DecodeTime( varHora, horas, minutos, segundos, milisegs ); Voc pode fazer operaes com as datas codificadas, como por exemplo, somar um nmero a uma data, ou subtrair duas datas para saber a quantidade de dias entre elas. Voc tambm pode converter uma data/hora para sua representao textual, para trat-la como uma string, usando DateToStr, TimeToStr, ou DateTimeToStr: editData.Text := DateToStr(tblClienteDataNasc.Value); labelRelogio.Caption := TimeToStr(Now); Essas funes convertem a data usando o formato padro, que depende da configurao do Windows. Mas voc pode tambm usar outros formatos, usando FormatDateTime, por exemplo: texto := FormatDateTime(data, 'dd/mm/yyyy'); No segundo argumento de FormatDateTime, voc pode usar os marcadores de posio (entre outros): Marcador Insere d, dd O dia do ms. Se o dia de 1 a 9, "dd" acrescenta um zero esquerda. ddd O dia da semana abreviado. dddd O nome do dia da semana, completo. m, mm O ms como um nmero. Se o ms de 1 a 9, "mm" acrescenta um zero esquerda. mmm O nome do ms abreviado. mmmm O nome do ms completo. yy O ano com dois dgitos. yyyy O ano com quatro dgitos. h, hh As horas. Se de 0 a 9, "hh" acrescenta um zero esquerda. m, mm Os minutos. Se de 0 a 9, "mm" acrescenta um zero esquerda. s, ss Os segundos. Se de 0 a 9, "mm" acrescenta um zero esquerda. / O separador de datas (pode no ser uma barra). : O separador de horas (pode no ser o dois-pontos). Esses mesmos marcadores podem ser usados com a propriedade DisplayFormat de um campo do tipo data ou hora. Voc pode converter uma string em data/hora, usando as funes de converso StrToDate, StrToTime e StrToDateTime. Para saber o dia da semana, voc pode usar a funo DayOfWeek: diaSemana := DayOfWeek(data); {1=domingo,...7=sbado}
135
Finalmente, voc tem funes para consultar a data/hora atuais do computador: Now retorna a data e hora atuais codificadas, Date retorna apenas a data e Time retorna apenas a hora. Por exemplo, para mostrar a data de hoje em um controle de edio, faa: editData.Text := DateToStr(Date);
136
137
Coloque um componente Table e um DataSource no formulrio, defina suas propriedades como: Table Name: tblFornecedor DatabaseName: CursoDelphi TableName: Fornecedor DataSource Name: dsFornecedor DataSet: tblFornecedor Clique duas vezes no componente tblFornecedor, para abrir o editor de campos, em seguida adicione os objetos de campos e arraste-os para o formulrio. Organize seu formulrio de acordo com a figura abaixo:
Salve a unit como 'CADFORNCEDOR.PAS'. No evento OnShow do formulario, vamos abrir o componente tblFornecedor , crie um procedimento para este evento e coloque: tblFornecedor.Open Para que o formulrio funcione necessrio acrescentar em cada Boto , um procedimento para o evento OnClick. No procedimento do evento OnClick do boto spbIncluir colocar: procedure TformCadFornecedor.spbIncluirClick(Sender: TObject); begin tblFornecedor.insert end; O mtodo Insert do componente Table, inclui um registro em branco. No procedimento do evento OnClick do boto spbAlterar colocar: procedure TformCadFornecedor.spbAlterarClick(Sender: TObject); begin tblFornecedor.edit
138
end; O mtodo Edit que permite fazer alteraes, mas essas alteraes podem ser confirmadas ou no. No procedimento do evento OnClick do boto spbSalvar colocar: procedure TformCadFornecedor.spbSalvarClick(Sender: TObject); begin tblFornecedor.post end; O mtodo Post, confirma as alteraes feitas nos campos da tabela. No procedimento do evento OnClick do boto spbCancelar colocar: procedure TformCadFornecedor.spbCancelarClick(Sender: TObject); begin tblFornecedor.cancel end; O mtodo Cancel, cancela as alteraes feitas nos campos da tabela. No procedimento do evento OnClick do boto spbPrimeiro colocar: procedure TformCadFornecedor.spbprimeiroClick(Sender: TObject); begin tblFornecedor.first end; O mtodo First movimenta para o primeiro registro. No procedimento do evento OnClick do boto spbAnterior colocar: procedure TformCadFornecedor.spbAnteriorClick(Sender: TObject); begin tblFornecedor.prior end; O mtodo Previous movimenta para o registro anterior. No procedimento do evento OnClick do boto spbIncluir colocar: procedure TformCadFornecedor.spbProximoClick(Sender: TObject); begin tblFornecedor.next end; O mtodo Next movimenta para o prximo registro. No procedimento do evento OnClick do boto spbUltimo colocar: procedure TformCadFornecedor.spbUltimoClick(Sender: TObject); begin tblFornecedor.last end; O mtodo Last movimenta para o ltimo registro. No procedimento do evento OnClick do boto spbExcluir colocar: procedure TformCadFornecedor.spbExcluirClick(Sender: TObject); begin if application.messagebox('Deseja excluir o fornecedor?', 'Confirmao', MB_ICONQUESTION + MB_YESNO) = idyes then tblFornecedor.delete end; O mtodo Delete exclui o registro atual. Antes de excluir o registro ser mostrado uma mensagem perguntando se deseja excluir o fornecedor. Notas: Se foi feita alguma alterao no registro atual , em seguida foi aplicado algum modo de movimentao na tabela ,as alteraes sero confirmadas, antes da movimentao. Neste exemplo mostramos somente o que cada mtodo faz, no foi realizado nenhum controle de desativar o boto Salvar , se o componente Table no estiver no modo de Alterao ou
139
Incluso , esses controles podem ser feitos com a propriedade Enabled de cada componente SpeedButton.
140
No formulrio de fabricantes (FormCadFornecedor), selecione o componente 'tblFornecedor' e o componente 'dsFornecedor' e tecle [Ctrl+C] para copi-los. Agora volte para o formulrio de produtos (FormCadProduto) e tecle [Ctrl+V]. Isso vai colocar no formulrio duas cpias dos componentes, que acessam a tabela FORNECEDOR. Isso necessrio para fornecer os valores mostrados por 'cboFornecedor'. Retornando ao componente 'cboFornecedor', altere as seguintes propriedades: Propriedade Valor dsFornecedor ListSource CodFornecedor KeyField Nome ListField A propriedade ListSource determina qual a tabela que ser usada para buscar os valores a serem mostrados. Como 'dsFornecedor' est ligado tabela FORNECEDOR.DB, os dados sero lidos desta tabela. O valor de KeyField (CodFornecedor, nesse caso) o nome do campo, na tabela FORNECEDOR, que corresponde ao campo DataField na tabela PRODUTO. Finalmente ListField determina qual o campo que ser mostrado na lista, nesse caso, Nome. Falta um detalhe: voc deve ativar a tabela de fornecedores, 'tblFornecedor' nesse formulrio. Acrescente o seguinte no procedimento do evento OnCreate do formulrio: begin tblProduto.Open; tblFornecedor.Open; end; Agora execute o programa. Repare que voc pode selecionar o fornecedor pelo nome agora. Se voc quiser mostrar o cdigo tambm, alm do nome, voc pode alterar a propriedade ListField para incluir mais de um campo. Para isso, coloque os nomes dos campos, separados por ";" (sem espao entre os nomes e o ponto-e-vrgula). No nosso caso, coloque "Nome;CodFornecedor" em ListField e execute o programa. Quando a lista est fechada, aparece apenas o nome do fornecedor, mas quando voc abre a lista, vo aparecer os dois campos: nome e cdigo.
141
142
143
Agora clique em Next e depois no boto "Finish". O formulrio ser adicionado com as opes definidas.
Analisando o Formulrio
Vejamos exatamente como definido o relacionamento mestre/detalhe pelo DFW. Como antes, so utilizados os componentes Table e DataSource, s que desta vez existem dois componentes Table e dois DataSource, todos no topo do formulrio, ao lado do DBNavigator, como na figura:
O primeiro 'Table1', est associado com a tabela CLIENTE.DB, atravs da propriedade TableName. O 'DataSource1' est ligado com 'Table1', atravs da propriedade DataSet. De forma anloga, os outros dois acessam a tabela de vendas: Table2.TableName tem o valor "VENDA.DB" e DataSource2.DataSet Table2. Os dois controles DBEdit da parte superior do formulrio esto ligados ao DataSource1 e o controle DBGrid da parte inferior est ligado ao DataSource2. Vamos alterar os nomes desses componentes de dados, para facilitar o entendimento. Mude os nomes para os seguintes:
Alm das ligaes que j vimos, num formulrio mestre/detalhe, preciso relacionar as duas tabelas. Isso feito com propriedades que ligam 'tblVenda' (antes Table2) a 'dsCliente' (antes DataSource1). Selecione o componente 'tblVenda' e veja que a propriedade MasterSource est ligada com 'dsCliente'. Isso define qual tabela ser a mestre para essa tabela. A propriedade MasterFields diz qual o campo (ou campos, se mais de um) na tabela mestre, que faz o relacionamento, e nesse caso "CodCliente". A propriedade IndexFieldNames, nesse caso, define qual o campo (ou campos) na tabela detalhe, que faz o relacionamento com o outro, e nesse caso tem o mesmo nome, "CodCliente" (mas no obrigatrio que tenha o mesmo nome).
144
Nota: O valor que aparece na propriedade DataSet o nome do outro componente, mas para propriedades de ligao, o Delphi guarda internamente um ponteiro de objeto, independente do nome. Tente executar o programa o Delphi vai mostrar um erro de compilao dentro do procedimento de evento 'FormCreate' , que foi criado pelo Database Form Wizard. Os dois comandos, "Table1.Open" e "Table2.Open", so para abrir as duas tabelas em tempo de execuo. Eles no funcionaro mais, porque voc alterou os nomes dos componentes Table. Substitua pelo seguinte: begin tblCliente.Open; tblVenda.Open; end; Notas: Os comandos existente no procedimento de evento OnCreate sero executados no momente que o formulrio for criado.
( ), nbEdit ( ), nbPost ( ) e nbCancel ( ). No DBGrid da parte inferior, o campo 'CodCliente' est disponvel para visualizao e edio, mas ele sempre ter o mesmo valor que o campo CodCliente da parte superior, portanto vamos torn-lo invisvel. Para tornar o campo invisvel, clique duas vezes no componente 'tblVenda' para abrir o editor de campos. Selecione o campo CodCliente. No remova da lista, seno o Delphi no vai conseguir manter o relacionamento. Apenas altere sua propriedade Visible para False. Altere o Caption do formulrio para "Clientes e Vendas" e a propriedade Name para formCadCliVend . Altere tambm o label "CodCliente", para "Cdigo". Se quiser, reduza o tamanho do painel que contm os controles de edio para a tabela de clientes. Voc deve clicar na borda mais espessa e no no fundo do painel. Execute o programa e verifique que agora no possvel editar os campos da tabela de clientes, apenas adicionar e remover registros de vendas relacionados.
Salvando o Projeto
Salve esse projeto como CADCLIVEND.
145
146
do controle. Altere tambm DataSource para 'dsItem'. Com isso, a grade vai mostrar os dados da tabela de itens e permitir alterao. Para que o campo 'CodVenda' no aparea na grade, selecione o componente 'tblItem' e clique duas vezes para abrir o editor de campos. Adicione todos os campos, selecione 'CodVenda' na lista e altere a propriedade Visible para False.
147
Para inserir um campo Lookup, clique duas vezes em 'tblItem' para abrir o editor de campos. Clique com o boto direito e selecione "New Field...". Em "Name", especifique "NomeProduto", em "Type" selecione "string", em "Size" informe 50. Marque a opo "Lookup". Agora em "Key Fields", selecione "CodProduto" .Esse o campo que ser usado para buscar o produto na outra tabela. Em "DataSet", selecione "tblProduto", que a tabela de onde ser buscado os dados. Finalmente , em "LooKup Keys", selecione "codproduto" este o campo que ser utilizado para fazer o relacionamente da tabela produto com a tabela item e em "Result Field" coloque nome (o campo de resultado que ser mostrado). As propriedades estaro como abaixo:
Arraste o campo LookUp 'NomeProduto' , para a primeira posio e o campo 'PrecoTotal' coloque-o na ltima posio, como na figura abaixo:
148
Para funcionar, voc precisa adicionar uma clusula uses, no incio da seo de implementao (implementation) do formulrio. Adicione o seguinte: uses CadCliVend Agora execute o programa para ver o efeito das modificaes. Note que no grid da tabela Item, o campo calculado PrecoTotal , os campos LooKup PrecoVenda e Nome vo aparecer para cada registro. Se voc alterar os campos Quantidade , PrecoVenda ou o Produto, o evento OnCalcFields ser executado, e o valor do campo ser alterado. Na verdade, esse evento executado para qualquer alterao de campo, mesmo os que no afetam seu valor. Finalize a execuo e salve o projeto novamente.
149
anteriormente, finalmente podemos subtrair a quantidade vendida pela quantidade existente no estoque. Para atualizar o estoque estamos considerando que o nico campo que possa ser alterado da tabela 'Item' o campo 'Quantidade', para fazer a alterao do produto necessrio excluir o item de venda e incluir novamente. No iremos aceitar modificao no campo 'codproduto' da tabela 'item', vamos criar um procedimento no evento OnChange do objeto 'tblItemQuantidade', para criar este procedimento clique duas vezes na tabela 'Item', com isso ir abrir o editor de cdigo, escolha o campo 'Quantidade', no 'Object Inspector ', clique na pgina 'Events', em OnChange, acrescente o cdigo a seguir: procedure TformCadCliVend.tblItemCodProdutoChange(Sender: TField); begin if tblItem.state in [dsEdit] then begin showmessage('No permitido a alterao do produto!'); tblitem.cancel; abort; end end; Falta criar a varivel 'QuantidadeAnterior' e atribuir um valor, abaixo da seo implementation acrescente: Var QuantidadeAnterior : integer; Essa varivel ir conter o valor do campo 'Quantidade' antes de ser modificado, crie um procedimento para o evento OnBeforeEdit, este evento ocorre antes de fazer modificaes nas tabelas, neste procedimento coloque: procedure TformCadCliVend.tblItemBeforeEdit(DataSet: TDataSet); begin Quantidadeanterior := tblItemQuantidade.value; end; Quando o item for excludo , temos que acrescentar a quantidade que foi retirada ao estoque, portanto, no evento OnBeforeDelete (antes de excluir) , coloque o procedimento abaixo: procedure TformCadCliVend.tblItemBeforeDelete(DataSet: TDataSet); begin if tblproduto.findkey([tblItemCodProduto.value]) then begin tblproduto.edit; tblProdutoqtdEstoque.value := tblprodutoqtdEstoque.value + tblItemQuantidade.value; tblproduto.post; end; end; Neste procedimento realizado uma procura do produto pertencente ao item , caso o produto seja encontrado , ser adicionado ao campo 'qtdEstoque' a quantidade do item excludo.
150
151
Criando o Formulrio
Abra o projeto VENDAS.DRP e acione o menu Database |Form Wizard.... Na primeira tela do DFW, mantenha a opo "Create a simple form" na parte superior, mas na parte de baixo selecione "Create a form using TQuery objects". Clique em Next. Na prxima tela, na lista "Drive or alias", selecione CursoDelphi. Na lista de tabelas, selecione a tabela VENDA.DB, depois selecione todos os campos e escolha o layout "In a grid". Na ltima tela, desmarque a opo "Generate a main form" e clique em Finish. O formulrio gerado semelhante aos que j criamos com o DFW, mas ele utiliza um componente Query em vez de um Table. Os componentes de dados esto no topo do formulrio: Query1 DataSource1 Selecione o componente 'Query1' e veja suas propriedades. Note que o 'DataSource1' tem na propriedade Dataset o valor 'Query1'. Isso faz a ligao entre os dois. Vamos alterar os nomes dos componentes para 'qryVenda' e 'dsVenda', respectivamente. Depois altere tambm o cdigo do evento OnCreate do formulrio, para abrir 'qryVenda' em vez de 'Query1'. A propriedade mais importante do componente Query a propriedade SQL. Essa propriedade uma lista de strings (TStrings), que contm um comando da linguagem SQL. Clique em SQL e no boto com reticncias. Repare que o contedo da propriedade o seguinte: Select venda."CodVenda", venda."CodCliente", venda."DataVenda" From "c:\cursodelphi\venda.DB" As venda O comando select um comando SQL que consulta registros. Primeiro so especificados os campos da tabela que sero retornados pelo select. Depois do from, vem o nome da tabela. Nesse caso, um nome completo, incluindo subdiretrio. A expresso "as Venda" cria um apelido para a tabela dentro do comando, que utilizado anteriormente, na lista do select (Venda."CodCliente", por exemplo). Clique OK para fechar o editor de strings. Altere a propriedade Name do formulrio para 'formConsVendasporCliente' e a propriedade Caption para 'Vendas por Cliente". Para o usurio poder visualizar esse fomulrio temos que cham-lo no evento Onclick do menu Consultas|Vendas por Cliente da Unit VendPrin. Neste evento coloque o cdigo abaixo: formConsVendasporCliente.show; Para isso funcionar, voc precisa adicionar uma clusula uses , no incio da seo implementation do formulrio VendPrin. adicione o seguinte: uses ConsVendasCliente; Salve o formulrio criado como "CONSVENDASCLIENTE.PAS". Execute o programa e veja o resultado: voc pode percorrer os registros da tabela, mas no pode alter-los.
152
Simplificando o Select
O comando select, que retorna os dados, pode ser simplificado, e podemos evitar que o diretrio da tabela seja codificado de forma fixa. Abra novamente a propriedade SQL e substitua todas as linhas do comando pelo seguinte: select * from Venda Voc pode colocar os comandos na mesma linha, ou em linhas separadas. O "*" (asterisco) no select em vez de uma lista de campos seleciona todos os campos da tabela, independentemente da estrutura dessa tabela. Note que no preciso colocar a extenso de arquivo (.DB) e melhor no colocar porque isso torna mais fcil alterar o programa para trabalhar com outros formatos de dados (onde tabelas no so arquivos). Execute o programa e repare que ele continua funcionando como antes.
Alterando a Consulta
Uma consulta que retorna todos os registros no realmente muito utilizada. A principal funo de consultas restringir os registros retornados a um subconjunto dos dados. Para fazer isso, vamos alterar a propriedade SQL novamente, acrescentando uma clusula where ao final: select * from Venda where DataVenda = '08/02/98' Isso vai retornar todos os registros onde o campo DataVenda tenha o valor '02/08/98', e apenas esses registros. Observe que a data deve ser informada como 'mm/dd/yy' . Execute o programa e veja o resultado. Note que se voc alterar o valor do campo DataVenda, e salvar o registro, o registro vai desaparecer do resultado. Quando o tipo do campo for data ou Caracter a condio deve ser passada entre apstrofos, caso seja um valor numrico especifique somente o nmero. Nota: na sintaxe do SQL, para inserir um texto, voc pode usar " (aspas) ou ' (apstrofos).
153
Expande a propriedade Value em type escolha "Date", que ser o tipo de dados do campo , ao confirmar o Object Inspector ira ficar como a figura abaixo:
Notas: Nos parmetros colocamos as datas sendo 'dd/mm/yy', pois, nos parmetros as datas so do tipo date e ao passar para a linguagem SQL o Delphi coloca no formato que o SQL utiliza. Em "Value" voc pode, opcionalmente, fornecer um valor inicial para o parmetro, ou marcar a opo "Null Value", que significa que ele comea com o valor nulo, ou vazio. Nesse caso digite "02/08/98" e depois clique Ok. Precisamos de uma interface para alterar o parmetro dinamicamente. Na pgina ) e coloque um controle no formulrio, em Standard, selecione o cone do GroupBox ( qualquer espao vazio. Altere sua propriedade Caption para "Parmetros". Agora crie controles dentro do GroupBox "Parmetros", dentro dele acrescente o ) , seu funcionamento idntico ao Edit a diferena que ele componente MaskEdit ( permite utilizar mscaras. Altere a propriedade Name para mskDataVenda, clique na reticncias da propriedade EditMask e escolha a opo "Date", substitua os '0' por '9', em seguida clique em "Ok", com uso definimos uma mscara para o componente de edio. Acrescente um componente Button e um Label , conforme a figura abaixo:
154
Chame o boto de 'btnAlterar' e mude a sua propriedade Default para True. No cdigo associado ao 'btnAlterar', alterar os parmetros, e abrir a consulta novamente com os parmetros modificados. Com isso o usurio pode realizar a consulta para qualquer data. Digite o seguinte: begin try with qryvenda do begin Close; Params[0].AsDate := strtodate(mskDataVenda.Text); Open; end; except on EConvertError do begin showmessage('Data Invlida!'); mskDataVenda.setfocus; end; end; end; Como feito uma converso de String para Date, foi feito o tratamento de exceo , pois, se a pessoa informar uma data invlida iremos mostrar a mensagem de erro 'Data Invlida'. A propriedade Params do componente Query um vetor de objetos do tipo TParam, com ndices comeando de zero. Cada um desses objetos tem propriedades como AsString, AsInteger, ... que permitem alterar o valor do parmetro. Execute o programa e veja o que acontece quando voc altera os parmetros. Nota: Outra forma de alterar o parmetro usando a funo-mtodo ParamByName, fornecendo o nome do parmetro em vez de sua posio na lista. Por exemplo, o cdigo abaixo tambm acessa o parmetro valorData: ParamByName('valorDAta').AsDate := strtodate(mskDataVenda.Text);
155
mtodos de string lists j vistos. O exemplo abaixo mostra como mudar a propriedade SQL dinamicamente : with qryCliente.SQL do begin Clear; Add('select * from Cliente'); Add('where Estado = "' + estado1 + '"'); Add('or Estado = "' + estado2 + '"'); end; Ao abrir o componente QryCliente , a consulta ir mostrar os clientes que pertencem ao intervalo de estados pedidos. No faremos isso neste projeto, e na maioria das vezes isso no necessrio.
Isso ocorre porque antes de fazer a modificao na propriedade SQL , foi criado um objeto de campo para o cdigo do cliente , com a alterao foi retirado o campo, mas como o objeto ainda existe. Ele continua procurando o campo 'codcliente', para resolver o problema clique duas vezes no componente 'qryVenda' para abrir o objeto de campo, remove todos os objetos de campos existentes.
156
Altere a propridade Active para true e observe que cada registro do resultado tem o valor do campo Nome e do campo CodVenda. Existem vrios registros de resultado para cada cliente, ou seja, com o nome do cliente repetido, mas com cdigos de venda diferentes.
157
and vend.CodVenda = item.CodVenda and prod.codproduto = item.codproduto and datavenda =:ValorData group by cli.Nome A funo sum uma funo de resumo (ou funo agregada) do SQL, que faz o somatrio de um campo ou expresso. A clusula group by define como so formados os grupos de registros para fazer a totalizao. Outras funes de resumo que podem ser usadas em vez de sum so: avg(campo) calcula a mdia de um campo max(campo) calcula o valor mximo do campo min(campo) calcula o valor mnimo 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
Clique em
Alterando Registros
Para alterar valores de registros, use o comando update. Com ele, basta fornecer a tabela, a condio de atualizao e as alteraes de campos a serem feitas. Por exemplo, o comando a seguir atualiza a tabela Cliente, preenchendo o campo Estado, com o valor 'GO', mas apenas nos registros onde Estado era vazio (is null verifica se o campo est vazio): update Cliente
158
Excluindo Registros
Para excluir um conjunto de registros baseado numa condio, use o comando delete. Por exemplo, o seguinte comando exclui todos os registros da tabela Venda, que estejam entre 01/01/94 e 01/01/95: delete from Venda where DataVenda >= '01/01/94' and DataVenda <= '01/01/95' ou, de forma equivalente: delete from Venda where DataVenda between '01/01/94' and '01/01/95'
159
Voc pode tambm usar expresses em comandos SQL, como vimos nos exemplos. A vantagem que o clculo da expresso feito no servidor, aliviando o processamento na estao, que recebe apenas os resultados. Funes de resumo tambm repassam parte do processamento para o servidor, que vai fazer toda a operao de totalizao e retornar os resultados. Quando voc usa comandos de atualizao, como update, o comando enviado ao servidor, que o processa localmente. Nesse caso, como ele no retorna resultados, o trfego entre a estao e o servidor o mnimo possvel.
160
161
Em "Name", voc digita o nome do alias local que voc est criando. Depois, se voc escolher um valor da lista "Alias name", seu alias local ser sinnimo para um alias j existente. Seno, voc deve escolher um driver de banco de dados em "Driver name" e alterar seus parmetros de configurao em "Parameter overrides". Repare que "Alias name" e "Driver name" so mutuamente exclusivas. No nosso caso, em "Name", digite "VENDAS". Esse ser o nome do nosso alias local. Na lista "Driver name", selecione "STANDARD" e clique no boto "Defaults". Esse boto preenche a lista de parmetros, de acordo com os parmetros de configurao do driver. No caso do driver "STANDARD", usado para bancos de dados locais, s importa o parmetro PATH. A lista vai mostrar uma linha com o parmetro PATH, sem valor definido: PATH= Na lista de parmetros, coloque o diretrio atual dos dados depois do parmetro: PATH=C:\CURSODF\TABELAS Isso basta para definir o alias local. As outras opes s tem utilidade em bancos de dados cliente/servidor, onde necessrio fornecer uma senha para conectar com o gerenciador de bancos de dados: "Login prompt", se ativo, mostra uma janela que requisita o nome de usurio e senha para conexo. E "Keep inactive connection", se ativado, diz para manter a conexo com o banco de dados mesmo quando ele no estiver sendo usado.
162
Clique Ok e repare que o Database Editor altera vrias propriedades do componente Database, de acordo com as opes escolhidas: DatabaseName fica com o valor "VENDAS", DriverName com o valor "STANDARD", LoginPrompt e KeepConnection com o valor True e Params (do tipo TStrings) com os parmetros. Note que o nome do alias (DatabaseName = "VENDAS") no necessariamente igual ao nome do componente (Name = "dbVendas").
163
Iniciando o InstallShield
O InstallShield trabalha com projetos de instalao [setup projects]. Um projeto de instalao um arquivo contendo um conjunto de opes que definiro o contedo e funcionamento do seu instalador. Para o projeto Vendas, iremos criar um projeto de instalao, que criar disquetes de instalao para o programa. Esses disquetes contm um programa de instalao (SETUP.EXE) e todos os arquivos necessrios ao funcionamento do programa VENDAS.EXE, compactados para ocupar menos espao. Quando voc fornece os disquetes de instalao a um usurio, ele pode executar o programa de instalao, que copia VENDAS.EXE e os outros arquivos necessrios para o computador do do Windows, para poder executar VENDAS.EXE. usurio e cria um atalho no menu ]|Programas, no cone "IS Express Delphi Execute o InstallShield atravs do menu [ 4.0 ". Ao execut-lo, aparece uma tela com trs opes: "Open an existing Setup Project" usado para abrir um projeto de instalao feito anteriormente. "Open your last Setup Project" abre o ltimo projeto de instalao usado (se houver). No nosso caso, use "Create a new Setup Project" para criar um novo projeto de instalao. Agora voc ver a janela New Project, que permite escolher o nome do projeto de instalao e o local onde ele ser salvo. Em "Project Name", digite "VENDAS". Na lista de diretrios, selecione CURSODF, sob o drive C:. Em "New Subdirectory", digite "INSTVEND". Isso ir criar um novo subdiretrio sob CURSODF, para conter os arquivos do projeto de instalao. Finalmente clique no boto Create. O InstallShield criar um novo arquivo, chamado VENDAS.iwz, no diretrio C:\CURSODF\INSTVEND. Agora voc ver uma janela semelhante a um caderno de anotaes, que contm a chamada checklist, com as tarefas que voc deve fazer para criar um programa instalador. Nota: o InstallShield no instalado em conjunto com o Delphi. Ele deve ser instalado separadamente a partir do diretrio ISXPRESS do CD do Delphi.
Criando um Instalador
A criao de um instalador envolve diversas fases: Definir o Projeto Visual [set the visual design]: nesta fase, voc fornece informao bsica ao InstallShield sobre sua aplicao, como nome descritivo, nome do arquivo executvel etc. e informaes sobre as mensagens que sero mostradas durante a instalao. Selecionar Objetos para o Delphi[Select InstallShield Objects for Delphi]: define se o programa usa ou no o BDE para acesso a banco de dados e, caso use, quais so os drivers necessrios que devem ser includos com o programa. Especificar Componentes e Arquivos [specify components and files]: O InstallShield permite criar uma instalao com vrias opes para o usurio. Voc pode definir tipos de instalao [setup types], como "tpica", "compacta", "personalizada" que sero apresentados como escolha para o usurio. Voc pode definir componentes [components], que so conjuntos de grupos [groups] a serem includos e cada grupo um conjunto de arquivos que pode ser
164
incluido ou no na instalao. O mais importante que nesta fase voc pode acrescentar arquivos adicionais alm do seu executvel. Escolher Componentes da Interface [select user interface components]: permite configurar as vrias janelas de dilogo que o programa de instalao mostra. Fazer Mudanas no Registro [make registry changes]: O Registro [registry] o banco de dados central de configurao do Windows. Nesta fase, possvel definir modificaes que sero feitas no registro. No entraremos em detalhes sobre este tpico. 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. Aps definir as opes, voc pode gerar os discos com o Disk Builder, um processo que ir compactar todos os arquivos necessrios e dividir em disquetes. Depois voc pode testar a instalao, executando o programa de instalao no seu prprio computador para ver o funcionamento. Quando tudo estiver pronto, voc pode gerar os discos de distribuio.
165
O InstallShield tem vrias caixas de dilogo predefinidas, que so apresentadas durante a instalao do programa. Algumas delas tm opes de configurao diversas que podem ser alteradas. Para esse exemplo, no alteraremos nenhuma opo, mas vamos apenas ver quais esto disponveis. Clique em Dialog Boxes na janela do InstallShield. Se uma caixa de dilogo estiver marcada, ela ser usada no instalador. Se estiver desmarcada, ela no ser usada. Voc pode clicar no boto "Preview" para ver como a janela aparece em tela cheia. Se ela tiver opes a ser configuradas, voc pode clicar na pgina "Settings", do lado direito, para configurar. Vejamos cada uma: Welcome Bitmap [bitmap de boas-vindas]: mostra uma imagem inicial ao usurio. Na pgina Settings, voc pode escolher qualquer arquivo de imagem .BMP, de 16 cores (desenhado com o Paint, por exemplo). Welcome Message [mensagem de boas-vindas]: mensagem genrica do InstallShield, em ingls. Software License Agreement [contrato de licena do software]: voc pode escolher um arquivo texto (na pgina Settings) que ser mostrado ao usurio. Readme Information [informao tipo leia-me]: voc pode escolher um arquivo texto, que mostra informao de ltima hora sobre o software. User Information [informao de usurio]: uma janela que pede nome de usurio, senha e, opcionalmente, um nmero de srie. Choose Destination Location [escolha local de destino]: janela que permite ao usurio selecionar um diretrio qualquer para instalar o programa. Voc pode definir, em Settings, o local default. (Se voc desativar essa janela, o usurio no pode alterar esse local). Setup Type [tipo de instalao]: se voc usa tipos de instalao (tpica, personalizada, compacta), permite ao usurio selecionar uma delas. Custom Setup [instalao personalizada]: quando o usurio usa a instalao personalizada, permite escolher o que ser instalado ou no. Select Program Folder [escolher pasta do programa]: permite ao usurio escolher qual a pasta onde o programa ser instalado. Em Settings, voc pode mudar a opo padro. Recomendase usar o mesmo nome descritivo do programa. Start Copying Files [iniciar cpia de arquivos]: o instalador mostra uma janela avisando que vai comear a copiar os arquivos. Progress Indicator [indicador de progresso]: mostra a porcentagem de arquivos copiados. Billboards [anncios]: mostra vrios bitmaps enquanto o programa est sendo instalado. Em Settings, voc pode escolher um diretrio contendo seus arquivos de imagem. Desative a menos que voc tenha criado seus prprios arquivos Setup Complete: mostra uma janela avisando que a instalao foi completada e se oferece para executar o programa.
166
Agora, para testar a instalao, no seu prprio computador, clique em "Test Run". O programa de instalao ser executado. Informe as opes indicadas at finalizar a instalao. Aps a instalao, voc pode executar o programa atravs do menu [ ]|Programas, cone Controle de Vendas. Para desinstalar o programa, abra o Painel de Controle do Windows, clique no cone "Adicionar ou remover programas", selecione "Controle de Vendas" na lista e clique no boto "Adicionar/remover". Aps confirmao, o programa ser removido do Windows.
Captulo 19 Relatrios
Conceitos do QuickReport Usando o QuickReport Wizard Criando um Relatrio com Vrias Tabelas
167
Conceitos do QuickReport
O QuickReport um gerador de relatrios composto de vrios tipos de componentes que trabalham em conjunto. Com ele, voc pode criar visualmente o relatrio, sem se preocupar com detalhes como quebras de pgina, agrupamentos, subtotais etc. Os componentes do QuickReport esto na pgina QReport.
A pgina QReport
QuickRep O componente bsico sobre o qual voc monta os relatrios. Tem a aparncia de uma folha de papel. Como veremos, ele se conecta a um dataset, de onde traz os dados, e permite colocar componentes imprimveis sobre ele, que mostram os dados. QRSubDetail Faz a ligao do relatrio com outras tabelas, ligadas da forma mestre/detalhe. QRBand Uma banda uma faixa do relatrio que impressa em determinados momentos. Esse componente permite criar vrios tipos de bandas. QRChildBand Cria uma banda filha, que sempre impressa aps uma determinada banda mestra. til se uma banda muito grande e se expande, ocupando vrias pginas. QRGroup Cria um agrupamento de itens dentro do relatrio. Quando um determinado campo muda de valor, uma banda de cabealho de grupo impressa. QRLabel Funciona como um componente Label, mas para impresso. Imprime o contedo da propriedade Caption. QRDBText Imprime o contedo de um campo do banco de dados, escolhido atravs das propriedades DataSet e DataField. Pode se expandir verticalmente ou se dividir em vrias pginas se necessrio. QRExpr Imprime campos calculados e outros itens. QRSysData Imprime informaes diversas como nmero de pgina, data/hora etc. A propriedade Data define o que ser impresso. QRMemo Imprime um texto de vrias linhas, que no vem do banco de dados. Pode se expandir verticalmente ou se dividir em vrias pginas se necessrio. QRRichText Imprime texto formatado, com diferentes fontes, tamanhos e estilos. O texto deve ser definido via programao. QRDBRichText: Imprime texto formatado, com diferentes fontes, tamanhos e estilos. O texto vem de um campo do banco de dados, determinado pelas propriedades DataSet e DataField. QRShape Usado para colocar desenhos no relatrio, como linhas, retngulos, crculos etc. QRImage Imprime uma imagem no relatrio (ex.: o logotipo da empresa). QRDBImage Imprime uma imagem no relatrio, a partir de um campo do banco de dados, determinado pelas propriedades DataSet e DataField.
168
QRCompositeReport: Permite agrupar vrios relatrios para imprimir como se fossem um s QRPreview Usado para ver uma prvia de impresso do relatrio em outra janela.
Construindo o Relatrio
Um relatrio do QuickReport tira seus dados de um dataset principal (tabela ou consulta SQL) e de alguns datasets secundrios, que estejam de alguma forma ligados a ele. A propriedade DataSet do componente QuickRep determina o dataset principal. Funciona como a propriedade DataSet de um componente DataSource do Delphi. O relatrio construdo visualmente a partir de bandas, que so as diversas faixas horizontais e componentes imprimveis, que so colocados nessas bandas. Os relatrios mais simples tm uma banda de cabealho da pgina [page header], uma banda de detalhes [details] e uma banda de rodap [page footer]. Outros mais complexos podem usar outros tipos. Os tipos de bandas so: Ttulo [title]: impressa uma nica vez, na primeira pgina do relatrio, aps o cabealho de pgina. Resumo [summary]: impressa uma nica vez, no final da ltima pgina do relatrio. Usada geralmente para os totais gerais. Cabealho de pgina [page header]: impressa no topo de cada pgina. Rodap de pgina [page footer]: impressa na parte inferior de cada pgina. Cabealho de coluna [column header]: impressa no topo de cada coluna. S tem utilidade com relatrios de mltiplas colunas. (Vide propriedade Page.Columns no componente QuickRep). Detalhe [detail]: impressa uma vez para cada registro do dataset Cabealho de grupo [group header]: quando existe um agrupamento de itens, impressa uma vez para cada grupo. Ex.: se um relatrio imprime vendas agrupadas por cliente, um cabealho de grupo impresso para cada cliente, contendo o nome do cliente. Rodap de grupo [group footer]: impressa no final de um grupo de itens. Sub-detalhe [subdetail]: usada em relatrios mestre/detalhe, como veremos mais tarde. Filha [child]: banda que serve como continuao de outra. Usado apenas pelo componente QRChildBand. Voc pode construir um relatrio posicionando componentes QRBand, QRChildBand
QRGroup manualmente ou usar a propriedade HasBand do componente ou QuickRep para criar alguns tipos de bandas automaticamente. Os componentes imprimveis so colocados sobre as bandas em tempo de projeto e so impressos quando o relatrio impresso. Eles podem conter texto ou imagens fixos (como QRLabel, QRMemo, QRRichText, QRImage, QRShape), ou contedo ligado aos QRDBText, QRDBRichText, QRDBImage)
QRExpr e ou ainda contedo varivel, calculado ou determinado pelo relatrio (como QRSysData). O componente QuickRep visual e aparece num formulrio em tempo de projeto. No entanto, esse formulrio no mostrado ao usurio, mas apenas usado internamente pelo programa. Para imprimir o relatrio, usa-se o mtodo Print do componente. Para ver uma prvia de impresso numa janela, usa-se o mtodo Preview.
169
Note que existe um componente Table no formulrio. Altere o seu nome para 'tblCliente' e a sua propriedade Active para True. Mude o Name do formulrio para "FormRelCliente".
Imprimindo o Relatrio
Salve o formulrio com RELCLIENTE.PAS. Retorne ao formulrio principal (formPrincipal), clique duas vezes no menu Relatrio|Clientes e coloque o seguinte comando; FormRelCliente.QuickRep1.Preview; Note que 'FormRelCliente' o nome do formulrio que contm o componente QuickReport e 'QuickRep1' o nome desse componente (no foi alterado). Preview um mtodo do componente que mostra uma janela de prvia de impresso. Caso queira imprimeir utilize o mtodo Print. Para que os comandos acima funcionem, acrescente uma clusula uses no incio da seo de implementao da unidade: uses RelCliente; Lembre-se de que 'RelCliente' o nome da outra unidade, que contm o formulrio do QuickReport. Agora execute o programa e teste o funcionamento do relatrio que ser mostrado no vdeo. Note que a janela de visualizao modal _ voc deve fech-la para voltar ao formulrio.
170
Nota: a qualquer momento, se voc quiser ver uma prvia de impresso, basta clicar com o boto direito no componente QuickRep (a folha em branco) e no item "Preview".
171
Nota: ou, se preferir, copie o componente Table do formulrio de clientes [Ctrl+C] e cole [Ctrl+V] neste formulrio. Nota: basta clicar duas vezes em DataSet para aparecer o valor. Aumente a largura do formulrio para que ele ocupe a tela inteira, para melhor visualizao. Note que voc pode selecionar uma banda clicando nela com o o mouse. Voc pode aumentar a altura da banda, mas a largura determinada automaticamente baseado no tamanho de pgina. As medidas que aparecem no relatrio so dadas em centmetros, como padro. Vamos colocar um ttulo do relatrio, coloque um componente QRLabel na banda "Page Header". Altere o Caption para "Vendas por Cliente" e tambm as seguintes propriedades: Font.Size: 20, para aumentar o texto Alignment: taCenter, para centralizar o texto AlignToBand: True, para centralizar o componente em relao banda. Quando voc altera AlignToBand, a posio do componente se altera. Se voc mudar apenas Alignment, apenas a posio do texto em relao ao componente se altera. Agora na banda "Details", iremos mostrar somente o nome do cliente(essa seo ser impressa uma vez para cada cliente). Coloque um componente QRLabel e altere o
), com as Caption para "Nome" e, logo frente dele, um componenteQRDBText( propriedades DataSet ,selecione "tblCliente" e DataField, selecione o nome do campo, "Nome". Nota: para chamar o Object Inspector, se ele no estiver visvel, use a tecla [F11] ou [Enter].
172
Alignment: taRightJustify, para alinhar o texto direita do componente AlignToBand: True, para alinhar o componente direita da banda
Visualizando o Relatrio
Para visualizar o relatrio como ele vai estar quando impresso, altere a propriedade Active do 'tblCliente' para True, clique no componente QuickRep (fora das bandas) com o boto direito e clique na opo Preview do menu. Isso vai mostrar, como antes, a janela de prvia de impresso. Essa janela contm vrios botes de controle. Os trs primeiros permitem escolher a quantidade de zoom: 100 % ou largura da pgina. Quando o relatrio tem primeira, ou
vrias pginas, podem ser usados botes para navegar entre as pginas: anterior, prxima e
permite abrir esse arquivo novamente para visualizar. E o boto Close fecha num arquivo e a janela de visualizao. Desative a tabela (altere Active para False) porque ela ser ativada apenas durante a execuo do programa. Salve o projeto. Quando o Delphi pedir o nome da unidade do novo formulrio, informe "RVenda".
Conectando as Tabelas
Faremos ligaes mestre-detalhe para relacionar as tabelas. Primeiro vamos conectar 'Venda' a 'Cliente' (um cliente tem N vendas). Clique em 'tblVenda' e altere as propriedades: MasterSource: dsCliente, MasterFields: CodCliente, IndexName: CodCliente. Agora vamos conectar 'ITEM' e 'VENDA'. Clique em 'tblItem' e altere: MasterSource: dsVenda, MasterFields: CodVenda, IndexName: IndVenda. Finalmente, para buscar o nome do produto a partir da tabela ITEM, devemos conectar as duas. Clique em 'tblProduto' e altere: MasterSource: dsItem, MasterFields: CodProduto, IndexFieldNames: CodProduto. A aparncia do relatrio , nesse momento, ser semelhante figura:
173
Se quiser, use o Preview para visualizar o relatrio (tblVenda deve estar ativo). Note que primeiro impressa a seo 'Detail', com os dados do cliente, depois impressa vrias vezes a seo Sub-detail, contendo as vendas efetuadas. Por exemplo: Cliente: Primeiro Cdigo Venda:101 Data Venda: 04/07/97 Cdigo Venda:102 Data Venda: 05/07/97 Cdigo Venda:105 Data Venda: 13/07/97 Cliente: Segundo Cdigo Venda:107 Data Venda: 20/07/97 Cdigo Venda:108 Data Venda: 30/07/97 Cdigo Venda:110 Data Venda: 30/08/97 Cliente: Terceiro Cdigo Venda:107 Data Venda: 20/07/97 Cdigo Venda:108 Data Venda: 30/07/97 ........
174
Agora, para cada venda, devemos imprimir os itens de venda correspondentes a eles. Para isso, coloque mais um componente QRSubDetail no relatrio, que vai aparecer abaixo da banda de vendas. Altere as seguintes propriedades: Name: qrsubItem DataSet: tblItem Master: qrsubVenda A propriedade Master deve ser alterada, para dizer que essa banda sub-detalhe estar subordinada banda 'qrsubVenda', criada anteriormente ,ou seja, para cada registro de venda impresso, sero impressos vrios registros de itens de venda. Agora, para essa banda, vamos criar um cabealho de grupo e um rodap de grupo. Um cabealho de grupo uma banda impressa antes de todos os registros do grupo (no caso, todos os itens de uma determinada venda) e um rodap de grupo impresso aps todos os registros do grupo. O cabealho ser usado para mostrar os nomes de campos e o rodap ser usado para mostrar um total geral. Clique na propriedade Bands desse componente e expanda seus sub-itens. Altere os dois, HasHeader e HasFooter, para True. Isso vai criar as bandas de cabealho e rodap de grupo, acima e abaixo do 'sub-detail'. Clique na banda "Group Header". Na propriedade Font, clique no boto de reticncias, selecione "Negrito" e clique Ok. Com isso, todos os componentes colocados nessa banda ficaro em negrito. Coloque quatro rtulos de texto (QRLabel), alterando o Caption em cada um com os textos "Produto", "Quantidade", "Preo Unitrio" e "Preo Total". Deixe um espao maior entre "Produto" e "Quantidade". Agora clique na banda "sub-detail", abaixo do "Group Header" novamente. Vamos mostrar aqui o nome do produto (campo Nome de tblProduto), a quantidade vendida (campo Quantidade de tblItem) e o preo de venda (campo PrecoVenda de tblItem). O preo total um campo calculado, que ser colocado mais tarde. Coloque trs componentes QRDBText, debaixo dos rtulos correspondentes e defina suas propriedades da seguinte forma: DataSet DataField tblProduto Nome tblItem Quantidade tblItem PrecoVenda O resultado, visualmente, ser o seguinte:
Se desejar, clique com o boto direito no relatrio e depois em Preview(Para funcionar todas as tabelas tem que estar com a propriedade Active = True). Alguns detalhes ainda precisam ser acertados, como a formatao dos campos.
Formatando os Campos
Para melhorar a aparncia do relatrio, vamos mostrar os campos "Quantidade" e "PrecoVenda" alinhados direita e "PrecoVenda" formatado como um valor monetrio. Clique no componente QRDBText que mostra "[Quantidade]". Altere a propriedade AutoSize para False. Quando AutoSize True, ele muda de tamanho de acordo com o contedo. Posicione-o alinhado direita de acordo com o rtulo e mude a propriedade Alignment para 'taRightJustify'. Selecione o componente "[PrecoVenda]" e faa o mesmo: AutoSize=False e Alignment=taRightJustify. Alm disso, altere a propriedade Mask, colocando o texto "#,0.00". Essa propriedade tem o mesmo efeito de DisplayFormat para campos da tabela, como j foi visto. Agora visualize novamente a prvia de impresso. Note que os campos aparecem formatados corretamente.
175
Voc pode criar campos calculados no QuickReport, usando o componente QRExpr. Com ele, voc pode digitar uma expresso qualquer, envolvendo campos da tabela. Voc no precisa escrever cdigo de programa para fazer o clculo. Vamos usar esse componente para calcular o "Preo Total" do item, que PrecoVenda * Quantidade. Coloque no formulrio um componente QRExpr logo abaixo do rtulo "Preo Total". Clique na propriedade Expression, que define a frmula de clculo do campo e clique duas vezes no boto de reticncias. Voc ver uma janela onde poder montar uma expresso de clculo.
Clique no boto "Database Field", na lista "Select dataset", a tabela 'tblItem', que contm os valores a serem calculados. Os campos da tabela aparecem na lista abaixo do nome. Clique em 'Quantidade', em seguida pressione o boto 'OK'. No quadro de texto na parte superior da janela, aparece 'tblItem.Quantidade'. Agora, clique no boto com o sinal de multiplicao, [*]. Um sinal * ser inserido no texto da frmula. Para terminar, clique novamente em "Database Field", escolha a tabela 'tblProduto' e o campo 'PrecoVenda'. A frmula final aparecer como na figura:
A frmula de clculo do campo, portanto, 'tblItem.Quantidade * tblProduto.PrecoVenda'. Agora clique Ok para retornar ao formulrio.
176
Para visualizar esse componente melhor, altere a propriedade AutoSize para False e reduza a largura do componente de acordo com o rtulo na parte superior. Altere tambm as propriedades: Alignment: taRightJustify e Mask: "#,0.00", como foi feito antes para o preo de venda. Se voc usar o comando Preview novamente, ver que o campo calculado mostrado corretamente para cada registro.
Criando um Sub-total
Agora vamos totalizar o campo calculado criado, para mostrar o total de vendas para cada cliente. Selecione o componente QRExpr, que foi criado para calcular o preo total. Tecle [Ctrl+C] para fazer uma cpia dele. Clique na banda "Group Footer" e tecle [Ctrl+V] para trazer essa cpia. Na propriedade Expression, faa uma alterao manual (no clique no boto de reticncias, pois seria mais complicado). Onde est o valor atual: tblItem.PrecoVenda * tblItem.Quantidade substitua por: SUM(tblItem.PrecoVenda * tblItem.Quantidade) A funo SUM calcula o somatrio de uma expresso. Mas preciso tambm informar qual o conjunto de registros sobre os quais essa soma ser efetuada. No nosso caso, ser para os itens de cada venda. Para definir o escopo da soma, usada a propriedade Master do componente. Essa propriedade faz referncia a uma banda que define quando o somatrio ser atualizado. Quando essa banda for impressa, o componente atualiza internamente o total, antes de imprimir. No nosso caso, em Master, selecione 'qrsubItem', que a banda que contm os itens de venda. Com isso, a cada item de venda impresso, o componente acumular internamente o seu total. Altere tambm a propriedade ResetAfterPrint para True. Se ela for False, o componente continua acumulando o total at o fim da impresso. Quando ela True, o componente zera o seu acumulador depois de impresso. Para dar mais destaque ao sub-total, coloque-o em negrito. Agora coloque esquerda desse componente um QRLabel, com o texto "Total da venda" e em negrito. Use o comando Preview para visualizar o relatrio. Note agora que o sub-total ser impresso aps os itens de venda.
177
end; Abra a unidade do formulrio principal, VENDPRIN.PAS. Para poder chamar o outro formulrio, clique em File|Use unit... e selecione "RVenda" para acrescentar a unidade na clusula uses. No formulrio, clique no item de menu Relatrios|Vendas. Coloque os seguinte comando: FormRelVenda.VisualizarRelatorio; Execute o programa e clique em Relatrios|Vendas. O programa mostrar a janela de prvia de impresso, como j foi visto. Salve o projeto novamente.
178
Bibliografia sugerida
Os seguintes livros so uma boa fonte de material para aprofundar-se um pouco mais no conhecimento do Delphi. LOBO, Rodrigo. Incrementando o Delphi. Ed. Advanced. ISBN: 8586916218. Este livro oferece uma srie de dicas, truques, utilitrios e componentes para o Delphi, visando tornar o trabalho do programador mais prtico e produtivo. Englobando as reas de banco de dados, multimdia, Internet, arquivos, etc. Inclui CD contendo os componentes e utilitrios. CANT, Marco. Dominando o Delphi 4 "A bblia". Ed. Makron. ISBN: 8534610460. Esta a edio completamente revisada e atualizada do livro de programao Delphi mais louvado de todos os tempos. Escrito pelo destacado especialista em Delphi, Marco Cant, este livro dedicado a usurios iniciantes e avanados, oferecendo a cobertura mais efetiva e cuidadosa da programao Delphi que se pode encontrar. PACHECO, Xavier e TEIXEIRA, Steve. Delphi 4 Developer's Guide (Developer's Guide Series). ISBN: 0672312840 Este livro uma referncia de nvel avanado mostrando aos desenvolvedores o mais importante que eles devem saber sobre o Delphi 4. Os autores lidam com desenvolvedores todos dias e citam tcnicas poderosas, dicas e conhecimento tcnico das mais avanadas caractersticas do Delphi 4. Tpicos incluem: Componentes de nvel avanado incluindo links embutidos, caractersticas especiais e DLLs, inclusive a criao de suas prprias Bibliotecas de Componentes Visuais (VCL), programao orientada a objeto avanada e object Pascal. O livro discute assuntos sobre desenvolvimento de aplicaes e conceitos de estrutura para aplicaes de bancos de dados cliente/servidor, desktop, bem como componentes MIDAS (Multi-tier Distributed Applications Services Suite), e como trabalhar com eles.
179