ELMO BATISTA FARIA, Dr. Curso de DELPHI UNIT/MG Elmo Batista de Faria, Dr. Página: 2 Curso de DELPHI Elmo Batista de Faria, Dr. SUMÁRIO PRIMEIROS PASSOS ______________________________________________________ 3 ANATOMIA DE UMA JANELA ___________________________________________________ 4 BARRA DE MENU, BARRA DE FERRAMENTAS E PALETA DE COMPONENTES _________________ 5 Barra de Ferramentas ___________________________________________________ 5 PALETA DE COMPONENTES___________________________________________________ 6 JANELAS DO DELPHI_______________________________________________________ 10 MEU PRIMEIRO PROGRAMA_______________________________________________ 16 ADAPTAR AS PROPRIEDADES DOS OBJETOS ______________________________________ 18 ESCREVER O CÓDIGO PARA OS EVENTOS ASSOCIADOS.______________________________ 19 EXEMPLO I - CALCULADORA ______________________________________________ 26 PROPRIEDADES _______________________________________________________ 30 BorderStyle __________________________________________________________ 30 Default ______________________________________________________________ 32 Tabstop _____________________________________________________________ 32 Name _______________________________________________________________ 33 Caption _____________________________________________________________ 33 Text ________________________________________________________________ 33 MÉTODO _____________________________________________________________ 33 Setfocus_____________________________________________________________ 33 ARIÁVEIS NO DELPHI _____________________________________________________ 34 V Formas de Declarar uma Variável _________________________________________ 35 FORMATAÇÃO DE NÚMEROS _________________________________________________ 35 Formatando Data e Hora: _______________________________________________ 36 MODIFICANDO A CALCULADORA ______________________________________________ 36 EXEMPLO IV - RELÓGIO DESPERTADOR ____________________________________ 42 MÉTODOS GRÁFICOS ____________________________________________________ 46 DESENHO DE PONTO ______________________________________________________ 48 CORES _______________________________________________________________ 49 DESENHO DE LINHA _______________________________________________________ 51 EXEMPLO V - CATÁLOGO _________________________________________________ 55 INSERINDO UMA NOVA UNIDADE ______________________________________________ 57 TIPOS _________________________________________________________________ 58 REGISTROS _____________________________________________________________ 58 PONTEIRO DE REGISTROS __________________________________________________ 59 BANCO DE DADOS SIMPLES ______________________________________________ 73 DATABASE DESKTOP ______________________________________________________ 75 OBJECT PASCAL _______________________________________________________ 103 LISTA DE EXERCÍCIOS __________________________________________________ 119 UNIT/MG Página: 3 Curso de DELPHI Elmo Batista de Faria, Dr. PRIMEIROS PASSOS Vantagens : - Facilidade em alterações e implementações - Melhor Estruturação do código - Velocidade - Verdadeira orientação a objetos Delphi possui um ambiente de desenvolvimento fácil de usar, com uma grande Biblioteca de Componentes Visuais (VCL - Visual Component Library). A VCL contém código de botões campos, rótulos, gráficos, caixas de diálogo e acesso e tabelas de bancos de dados, e foi desenvolvida levando em conta as velocidades no desenvolvimento de aplicativos e na execução destes aplicativos. O rápido desenvolvimento de aplicativos é possível graças aos vários controles disponíveis na paleta de componentes, onde o programador escolhe um destes componentes, e coloca-o diretamente no local desejado, dentro de um formulário. Formulário este que será a janela do aplicativo apresentada ao usuário. O Delphi permite o uso de objetos, e sua criação. Ele trabalha com eventos que dão início à alguma rotina de trabalho, ou seja, o programa fica parado até que um evento ocorra. Um programa tradicional, feito para ser executado em DOS, é organizado em torno de estruturas de dados com um loop principal e uma série de sub-rotinas constituindo o aplicativo, com procedimentos e funções separados para manipular os dados. Um programa orientado a objetos e eventos é organizado em torno de um conjunto de objetos. Onde objeto é uma variável com propriedades que o definem, e vários códigos dando funcionalidade a este objeto. Ou seja, objetos são estruturas que combinam dados e Rotinas em uma mesma entidade. Um Objeto possui dados internos, que não podem ser acessados por outros objetos e dados externos, também chamados de propriedades, estas podendo ser acessadas de fora deste objeto. De maneira semelhante, um objeto possui rotinas internas que são usadas apenas internamente e rotinas externas, também chamadas de métodos, que podem ser acessadas externamente. UNIT/MG Página: 4 Curso de DELPHI Elmo Batista de Faria, Dr. Um carro é um objeto que possui propriedades e métodos. A tabela abaixo lista algumas propriedades e comportamentos do objeto real carro. Propriedades cor comprimento potência do motor tipo de pintura Métodos dar partida mudar marcha acelerar frear Um método é uma rotina própria do objeto que o dá funcionalidade, ou seja, torna-o vivo, e as propriedades fazem o intercâmbio entre o objeto e o programa. ANATOMIA DE UMA JANELA A figura abaixo, mostra uma janela típica do Windows e a denominação de seus componentes básicos. Moldura - Os quatro lados da janela, que definem seu tamanho. Barra de Título - Acima da moldura superior como nome da janela e documento corrente. Menu de Controle - À esquerda da Barra de Título. Um botão com um ícone que representa o programa. Botões de Tamanho - À direita da Barra de Título. São dois botões, no primeiro temos um traço, o outro com duas janelinhas ou uma janela desenhadas. Se forem duas janelinhas, mostra que a janela está maximizada, e se for uma janela um pouco maior, mostra que a janela está em seu tamanho normal e pode ser maximizada. O botão com um traço serve para minimizar a janela. Barra de Menu - Está abaixo da barra de título e contém as opções de controle do aplicativo. UNIT/MG Página: 5 Curso de DELPHI Elmo Batista de Faria, Dr. Área do Cliente - É a parte interna da janela, também chamada de área do documento, utilizada para inserir os controles da nossa aplicação. Área Externa à Janela - É sua Mesa de Trabalho onde você pode ter tantos aplicativos quantos necessitar e a memória do seu computador permitir. Janela - Uma Janela é plena quando podemos dimensioná-la (mini, maxi e restaurá-la) e movê-la. BARRA DE MENU, BARRA DE FERRAMENTAS E PALETA DE COMPONENTES Barra de Ferramentas PALETA DE COMPONENTES A Paleta de Componentes, possui todos os controles que iremos precisar para desenharmos nossa janela - formulário - como um programa de desenho livre. Para incluir um controle no formulário, existem dois métodos: UNIT/MG Página: 6 Curso de DELPHI Elmo Batista de Faria, Dr. 1 - Click Duplo no ícone da paleta de componentes. Fará com que o controle seja inserido no centro do formulário com um tamanho padrão. 2 - Selecionar o ícone na caixa de ferramentas e depois dar um clique no formulário, na posição desejada para o objeto (canto superior esquerdo deste). Podemos dimensionar estes controles, depois de inseridos, a qualquer momento durante o desenvolvimento. Primeiro, selecionamos o controle dando um clique em cima dele e depois o dimensionamos arrastando um dos oito botões dimensionadores que circundam este objeto. UNIT/MG Página: 7 Curso de DELPHI UNIT/MG Elmo Batista de Faria, Dr. Página: 8 Curso de DELPHI UNIT/MG Elmo Batista de Faria, Dr. Página: 9 Curso de DELPHI Elmo Batista de Faria, Dr. JANELAS DO DELPHI Formulário É a janela que aparece no centro da tela do Delphi. Essa é a janela que estamos projetando. Quando rodarmos o aplicativo, será ela que irá aparecer com os objetos que nós incorporamos. UNIT/MG Página: 10 Curso de DELPHI Elmo Batista de Faria, Dr. Controles Existem vários tipos de objetos no Delphi, entre eles, formas e controles. Controles são todos os objetos que compõem um formulário, inserindo-o em um formulário ou controlando os seus eventos e propriedades. Um controle é qualquer objeto que o usuário possa manipular desde que não seja uma janela (formulário). Object Inspector Nesta janela escolhemos como serão as caractereísticas de cada objeto do formulário (botões de comando, quadros de texto, formulários, e outros), e a que eventos eles responderão, definindo como eles serão apresentados e operados pelo código. Cada um desses objetos possui um conjunto específico de propriedades que podem ser associadas a eles. Ao trabalharmos nos diferentes objetos, a janela Object Inspector nos permitirá mudar as propriedades do objeto com que estamos trabalhando. Esta janela possui a divisória Events onde estão listados todos os eventos possíveis de ocorrerem com o objeto especificado. Existem propriedades que podemos mudar enquanto construímos nosso projeto, ou seja, em tempo de projeto, e outras propriedades que só podemos mudar durante a execução do projeto, neste caso em tempo de execução. UNIT/MG Página: 11 Curso de DELPHI Elmo Batista de Faria, Dr. Na Object Inspector anterior, temos algumas das propriedades do formulário assim que iniciamos o Delphi. Caixa de Objeto - Está caixa mostra o objeto atualmente selecionado, através dela também podemos selecionar o objeto que queremos mudar as suas propriedades, basta dar um clique na seta, que um menu de cortina se abrirá, onde poderemos selecionar um objeto. Nome - Contém o nome do objeto atualmente selecionado, que será utilizado pelo código. Este nome está na propriedade Name. Tipo - Nesta posição encontraremos qual é o tipo do objeto selecionado, se ele é um TForm (formulário), TButton (botão de comando), TLabel (legenda), ou então um TEdit (quadro de texto). Coluna de Propriedades - Exibe todas as propriedades que podemos modificar em tempo de projeto do referido objeto. Coluna de Valores - Exibe o valor da propriedade correspondente. UNIT/MG Página: 12 Curso de DELPHI Elmo Batista de Faria, Dr. DELPHI CARACTERÍSTICAS DO DELPHI • Gera um executável verdadeiro, independente de run-time. • Utiliza um dialeto da linguagem Object Pascal para escrever os procedimentos do programa. • Utiliza o processo de desenvolvimento Two-Way, que permite tanto escrever o código em Object Pascal gerando os objetos visuais, como utilizar os métodos visuais gerando código em Object Pascal. • Os componentes são definidos como objetos, o que permite a herança. • Permite a criação de novos componentes na própria linguagem. • Possui acesso facilitado a banco de dados. • Possui ambiente de depuração integrado. • Possui componenete para a internet Características da Programação Delphi • Um programa Delphi é uma estrutura de aplicativo • Orientada ao desenho de formulários ou janelas. • Interface com usuário feita através de componentes • Contém um conjunto de controles pré-desenvolvidos que dão acesso às características do sistema. • Os componentes são objetos • Cada controle ou componente possui propriedades, métodos e pode responder a eventos. • As propriedades podem ter seus valores definidos em tempo de desenvolvimento e alterados em tempo de execução. • Os eventos são as mensagens que cada componente pode responder, tendo associado a eles um procedimento de evento. Elementos da Programação Delphi : Elemento Formulário (Form) Unidade (Unit) Componente Propriedade Método Evento Processador de Evento Projeto (Project) Descrição É uma janela, elemento básico onde agrupamos os componentes para formar a interface com o usuário. Arquivo que contém código em object pascal. Para cada formulário existe uma unidades associada Objetos utilizados para a construção das nossas aplicações (projeto). Representam os atributos dos componentes Procedimento ou função própria do objeto. Representam a capacidade de resposta dos componentes aos estímulos Procedimento responsável por responder a determinado evento Conjunto de formulários, componentes e unidades que compõem uma aplicação UNIT/MG Página: 13 Curso de DELPHI ARQUIVOS PRODUZIDOS PELO SISTEMA EXT Tipo BMP, Arquivos gráficos ICO DCU Unidade Compilada Delphi DFM Arquivo de formulário gráfico ~DF Backup de DFM DPR Arquivo de Projeto ~DP DSK Backup de Projeto Configurações de Desktop DSM Dados do Object Browser Arquivo executável linkeditado Opções do Projeto EXE Elmo Batista de Faria, Dr. Descrição Arquivos de imagens nos formatos BitMaP e ICOne Resultam da compilação de um arquivo PAS Arquivo binário contendo as propriedades e componentes de um formulário Backup de um arquivo DFM Escrito em Object Pascal contendo os componentes de um projeto e permite uso de código de inicialização do projeto Backup de um arquivo DPR Arquivo texto contendo as informações sobre a posição das janelas, os arquivos abertos no editor e outras configurações de Desktop Armazena as informações do Object Browser Arquivo executável contendo as unidades, recursos e formulários compilados de um projeto OPT Arquivo de teste com as configurações atuais para as opções do projeto PAS Código-fonte de uma Arquivo contendo o código fonte de uma unit em object unidade pascal, o qual pode ser de um formulário ou arquivo fonte independente. Sendo de um formulário contém a sua definição de classe e código dos seus manipuladores de eventos ~PA Backup de um PAS Backup de um arquivo PAS RES Arquivo de recursos Arquivo binário associado ao projeto contendo compilado recursos compilados, por padrão contem o ícone do projeto ESTRUTURA DE UM PROJETO : PROJETO (*.DPR), UNITS (*.PAS) E FORMS (*.DFM) AMBIENTE DE DESENVOLVIMENTO DELPHI • Menu Principal • Speed Bar • Paleta de Componentes • Object Inspector (Propriedades e Eventos) • Editor de Formulário • Editor de Código • Multiplas Janelas (View/New Edit Window) • Complemeto do Código (Exibe automaticamente as Propriedades e Métodos dos Objetos) • Parâmetros Automáticos (Exibe automaticamente os Parâmetros de Métodos) • Vizualização automática de variáveis na depuração • Templates de Código (Tools/Environment Options/Code Insight – Ctrl+J) • Busca de Texto por todo o Projeto (Search/Find in Files) • Marcando Blocos em colunas (Alt+Seleção) • Marcando Posições no Código (Ctrl+K+n = Marca, Ctrl+Q+n = Movimenta) UNIT/MG Página: 14 Curso de DELPHI Elmo Batista de Faria, Dr. DESENVOLVENDO APLICATIVOS Manipulando Componentes: • Acrescentando • Selecionando • Movendo • Sobrepondo • Alinhando • Redimensionando • Cortando, Copiando e Colando • Criando Ordem de Acesso (Tab Order) • Fixando Alterando Propriedades dos Componentes em Tempo de Projeto 1. Selecione o Componente, depois mude a propriedade no Object Inspector 2. Editor de Propriedade : Simples, Lista Suspensa, Caixa de Dialogo e Propriedades Aninhadas Escrevendo Procedimentos de Eventos Selecione o Componente, escolha, na Object Inspector, o evento a ser respondido e Click-Duplo na coluna direita, e então escreva o procedimento Alterando Propriedades em Tempo de execução Componente.Propriedade := NovoValor OBS: Quando a propriedade for aninhada use Componente.Propriedade := Componente.Propriedade ± [ConstanteDaPropriedade] Utilizando métodos Componente.Método UNIT/MG Página: 15 Curso de DELPHI Elmo Batista de Faria, Dr. ESTRUTURA DE UMA UNIDADE unit Unit1; interface uses SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls, Forms, Dialogs; type TForm1 = class(TForm) private { Private declarations } public { Public declarations } end; var Form1: TForm1; implementation {$R *.DFM} end. UNIT/MG Página: 16 Curso de DELPHI Elmo Batista de Faria, Dr. MEU PRIMEIRO PROGRAMA Para iniciar, vamos construir um programa que quando for dado um clique no botão de comando, será mostrada uma mensagem. E posteriormente poderemos alterar a cor desta mensagem através de outros botões. Existem três passos principais para a escrita de uma aplicação no Delphi que iremos seguir: • Desenhar as janelas que se deseja usar. Inserir no formulário os controles que serão necessários • Adaptar as propriedades dos objetos. Alterar as propriedades dos controles às necessidades da aplicação • Escrever o código para os eventos associados. Esta é a parte mais complexa do desenvolvimento, é ela que dá a funcionalidade ao programa, são as rotinas que começam a ser executadas a partir de um evento. Desenhar as janelas que se deseja usar. 1 - Começamos inserindo um Label (Legenda) e um Botão de Comando no Formulário, de uma das duas maneiras: a) Dando um duplo clique na barra de ferramentas no controle desejado; b) Selecionando o controle e dar um clique no formulário. 2 - Observe que, quando o controle estiver selecionado, poderemos arrastá-lo e dimensioná-lo dentro do formulário. UNIT/MG Página: 17 Curso de DELPHI Elmo Batista de Faria, Dr. ADAPTAR AS PROPRIEDADES DOS OBJETOS Para se alterar a propriedade de um objeto, ele tem que estar selecionado (com os oito pontos dimensionadores visíveis), depois procurar o nome da propriedade a ser alterada, na janela Object Inspector, e selecionar (no caso de valores padrão) o seu valor, ou então escrever um valor. 1 - Dimensione o formulário da seguinte maneira: Selecionar a propriedade Height, e atribuir a ela o valor de 150. Selecionar a propriedade Width e dar o valor de 180. Estes números correspondem a Pixels, que é a quantidade de pontos do monitor . O mesmo deverá ser feito para as propriedades Name e Caption. A propriedade Name será a identificação do Objeto quando construirmos o código da aplicação. E a propriedade Caption é a palavra que aparecerá como título da janela. UNIT/MG Página: 18 Curso de DELPHI Elmo Batista de Faria, Dr. Após você alterar estas quatro propriedades (Caption, Height, Name e Width) do formulário, ela estará assim: Agora, altere as propriedades do TLabel e do TButton. UNIT/MG Página: 19 Curso de DELPHI Elmo Batista de Faria, Dr. ESCREVER O CÓDIGO PARA OS EVENTOS ASSOCIADOS. O código é escrito na janela Unit, para acessá-la, selecione o botão Iniciar e na janela Object Inspector, chame a divisória Events e dê um duplo clique na parte direita da linha que contém o evento OnClick - a rotina escrita para este evento, será executada quando o botão Iniciar for clicado. Isto traz a janela Unit para a frente. UNIT/MG Página: 20 Curso de DELPHI Elmo Batista de Faria, Dr. Janela Unit Nesta janela observamos o nome da procedure, identificando qual o objeto e o evento que dará início à execução do código, e onde está localizado este objeto. Todas as instruções a serem executadas por um procedimento devem estar entre as palavras reservadas Begin e End. A Janela Unit também pode ser acessada dando-se um duplo clique no objeto que se quer criar um código. Cada objeto tem um evento que é mais comumente utilizado, e é com este evento que o Delphi iniciará a Janela Unit quando acessada desta forma, isto não impede que criemos outros códigos utilizando mais de um evento ao mesmo tempo. O nosso projeto de Início, mostrará uma mensagem no Label (objeto) com um Click (evento) no Botão “Iniciar” (objeto). Ou seja, iremos alterar a propriedade Caption de lblMensagem, esta propriedade contém o que será mostrado ao usuário. Atribuímos valores a uma propriedade de objeto seguindo o padrão: objeto + . + propriedade + := + valor da propriedade ; Abra a Janela Unit para o botão de comando e digite o código conforme a figura a seguir. Repare que ao digitar o ponto após LabelMensagem, e aguardando alguns instantes, o Delphi exibirá uma lista de propriedades e métodos do controle Label. UNIT/MG Página: 21 Curso de DELPHI Elmo Batista de Faria, Dr. Esta ajuda do Delphi pode ser acionada para qualquer controle ou função, quando digitamos o nome de uma função, ele exibe os parâmetros necessários para a execução desta função. Para escolher uma propriedade do LabelMensagem, selecione-a com as setas de direção e então pressione Enter, inserindo-a na linha de comando. Ou então, digite a primeira letra da propriedade, selecionando-a. UNIT/MG Página: 22 Curso de DELPHI Elmo Batista de Faria, Dr. Continue com o código, seguindo a figura mostrada abaixo. Quando for dado um clique em Iniciar, será mostrada a mensagem “Você deu um Clique em Iniciar”. Clique sobre o botão Run da barra de ferramentas ( ) para que o Delphi inicie a compilação do projeto. Em seguida, selecione o botão Iniciar para ver o resultado. Finalize a execução do projeto teclando Alt+F4 ou no botão Finalizar ( título da janela. UNIT/MG ) da barra de Página: 23 Curso de DELPHI Elmo Batista de Faria, Dr. Para alternar a visualização entre o Formulário e a janela de código Unit, utilize o botão Toggle Form/Unit ( ) na barra de ferramentas. Existem propriedades que possuem valores predefinidos, quando escolhemos a propriedade Alignment e damos um clique na seta da caixa de valor, aparecem os tipos de alinhamento para o texto. Selecione o objeto TLabel através da Caixa de Objeto da janela Object Inspector, e altere a propriedade Alignment para taCenter, para que o texto no TLabel fique centralizado. Altere também a propriedade AutoSize para False, e no Formulário aumente a largura do TLabel. UNIT/MG Página: 24 Curso de DELPHI Elmo Batista de Faria, Dr. Além das propriedades descritas acima, com padrões pré-definidos, existem outras que possuem inúmeras escolhas, neste caso, ao invés de uma seta, observaremos três pontos, este é o caso da propriedade Font. Quando selecionamos os três pontos, aparece um Quadro de Diálogo onde escolheremos o formato da fonte que será apresentada a mensagem. No seu projeto Iniciar, teste as alterações de fonte e observe as mudanças. Na figura a seguir, foi utilizada a fonte Arial com tamanho de 14 pontos. Observe na figura acima que o texto não coube na área de exibição do TLabel e nem do Formulário, nós temos duas opções para que este texto apareça integralmente. A primeira, é alterar para True, a propriedade WordWrap do TLabel, esta propriedade insere uma mudança de linha quando o texto atinge a margem direita do objeto. A segunda, é redimensionar os tamanhos da TLabel e do Formulário. Como mostram as figuras a seguir. UNIT/MG Página: 25 Curso de DELPHI UNIT/MG Elmo Batista de Faria, Dr. Página: 26 Curso de DELPHI Elmo Batista de Faria, Dr. EXEMPLO I - CALCULADORA Para iniciar um novo projeto, escolha a opção New Application do menu File. Não salvando o projeto Iniciar anterior. Dimensione e insira os controles, utilizando a Paleta de Componentes, no formulário como o exemplo abaixo. Dimensionamos o formulário no Delphi da mesma forma que no Windows dimensionamos as janelas. Para inserir vários objetos repetidos no Formulário, damos um clique no ícone do objeto escolhido enquanto pressionamos a tecla Shift, ele ficará conforme a figura abaixo mostra. Logo após, basta ir inserindo o objeto (no caso, o Edit) dentro do Formulário, sem se preocupar com a estética. Após inserir todos os componentes repetidos, clique no cursor bitmap em forma de seta, isto desativará o botão selecionado anteriormente. Observe que os objetos TEdit estão desalinhados, o Dephi nos oferece um recurso para realizar rapidamente um alinhamento entre objetos. Primeiro deveremos selecionar os objetos que queremos alinhar. Pressione a tecla Shift enquanto você dá um clique em cada um dos TEdit, selecionando todos ao mesmo tempo como mostra a figura a seguir. UNIT/MG Página: 27 Curso de DELPHI Elmo Batista de Faria, Dr. Depois disto, pressione o botão direito do mouse em cima de um TEdit, para aparecer o pop-memu. Escolha Align..., aparecendo a janela Alignment. Escolha Space equally (igualmente espaçado) para alinhamento horizontal, e Tops (topo) para o alinhamento vertical. UNIT/MG Página: 28 Curso de DELPHI Elmo Batista de Faria, Dr. Após o alinhamento, nosso Formulário estará conforme a figura abaixo: Insira os objetos restantes da maneira que preferir, posicionando-os de acordo com a figura abaixo: Agora, altere as propriedades assinaladas dos Objetos conforme a figura a seguir: Neste exemplo de projeto, digitaremos um número em Edit1, outro em Edit2, e quando for dado um Click em Button1, o resultado da multiplicação aparecerá em Edit3. Para limpar os Quadros de texto, usaremos o Button2. UNIT/MG Página: 29 Curso de DELPHI Elmo Batista de Faria, Dr. O projeto irá trabalhar basicamente com dois eventos : Click em Button1 (=) Click em Button2 (Limpar) Então, para escrevermos o código, daremos dar um Duplo Click no Button1 - janela Unit será mostrada. Entre com o código mostrado na figura a seguir: Alterne para o procedimento do Button2. E entre com os comandos a seguir: UNIT/MG Página: 30 Curso de DELPHI Elmo Batista de Faria, Dr. Execute o projeto. Para utilizá-lo, entre com um número em Edit1, outro em Edit2 e dê um Click em “=”, e o resultado da multiplicação aparecerá em Edit3. Note que alternamos os campos ativos com a tecla Tab. A ordem de tabulação corresponderá à ordem em que os controles foram colocados no formulário. Esta ordem é determinada pela propriedade TabOrder dos controles, caso o seu projeto não esteja, coloque-o na seguinte ordem: Objeto Edit1 Edit2 Edit3 Button1 Button2 TabOrder 0 1 2 3 4 Para alterar esta propriedade basta selecionar o controle, e na janela Object Inspector, procure TabOrder e altere o seu valor, o Delphi não aceita controles com TabOrder de mesmo valor. Execute o projeto e observe a alteração. Note que podemos alterar o valor de Edit3 mesmo após a multiplicação ter sido efetuada. Para evitar isso, defina a propriedade TabStop=False para Edit3 e verá que o usuário não terá mais acesso com a tecla Tab ao Edit3. Existem, nas aplicações para Windows, botões de comando que são acionados com a tecla Enter ou com um Click neles. No nosso projeto este botão será o Button1, por isso, a propriedade Default foi selecionada para True. Fazendo aparecer um contorno mais espesso no botão, dando a indicação que se a tecla Enter for acionada, a procedure associada a este botão será executada. PROPRIEDADES UNIT/MG Página: 31 Curso de DELPHI Elmo Batista de Faria, Dr. BorderStyle Retorna ou dá o estilo de borda de um objeto; objeto.BorderStyle := [valor] Existem 6 tipos de bordas: 1 - bsDialog O formulário não possui os botões de maximizar e nem de minimizar. Não redimensionável. é 2 - bsNone Nenhuma UNIT/MG Página: 32 Curso de DELPHI 3 - bsSingle Elmo Batista de Faria, Dr. Fixa Simples, o formulário só é dimensionável através dos botões de minimizar e maximizar. 4 - bsSizeable Redimensionável 5 - bsSizableToolWindow Semelhante à bsToolWindow, dimensionável. mas é 6 - bsToolWindow e redimensionável, e botão de fechar e a com a fonte reduzida. E formulário não aparece na barra de Não mostra os botões de maximizar de minimizar. Não é mostra somente o barra de título o tarefa do Windows 95. As Bordas Fixas não podem ser dimensionadas em tempo de execução. Ou seja, o usuário não poderá mudar o tamanho do formulário. UNIT/MG Página: 33 Curso de DELPHI Elmo Batista de Faria, Dr. Default Retorna ou dá o valor de um botão de comando em um formulário; object.Default :[= booleano] Default= False True Quando esta propriedade de um TButton estiver como True o Delphi chamará o evento Click sempre que a tecla Enter for pressionada. Ex: Desejo que o botão BtnMultiplicar seja o default: btnMultiplicar.Default := True; Desejo saber se o botão cmdMultiplicar é default ou não, e o resultado será armazenado na variável booleana Estado: Estado := btnMultiplicar.Default; Tabstop Retorna ou dá o valor ao objeto indicado; objeto.TabStop: [= booleano] TabStop = False True Ex: Para alterar a ordem de tabulação dos botões em tempo de execução basta incluir estas linhas em algum procedimento: btnMultiplicar.TabStop := 0; btnDividir.TabStop := 1; btnSomar.TabStop := 2; btnSubtrair.TabStop := 3; Para saber qual a ordem de tabulação do objeto txtNum1 e armazená-la em uma variável que conterá a ordem de tabulação do objeto: Ordem_Tab:= editNum1.TabStop; No ambiente Windows é comum mudarmos o foco entre os controles com a tecla Tab. Quando não quisermos que o usuário acesse determinado controle usando Tab, definimos a propriedade TabStop desse controle como False. Name UNIT/MG Página: 34 Curso de DELPHI Elmo Batista de Faria, Dr. Nome que é dado ao objeto como referência para o código e definição de propriedades. Em tempo de execução, retorna o nome usado por um controle; objeto.Name Ex: Desejo exibir o Name do Formulário em um Edit: editNome_Form.Text := frmCalculadora.Name; Caption objeto.Caption :[= string] Determina o texto mostrado na barra de título do formulário, o texto dentro de um controle ou um título na barra de menu. Ex: Alterar o Caption do botão Limpar após o seu uso, basta inserir esta linha no procedimento cmdLimpar_Click: btnLimpar.Caption := ‘Iniciar’ Text Retorna o texto que está escrito na área de edição de um quadro de texto (TextBox), ou escreve um String nesta área; objeto.Text :[= string]; MÉTODO Setfocus Dá o foco ao objeto indicado; objeto.SetFocus Fixa o foco a um formulário ou controle. Somente pode ser usado para um formulário ou controle visíveis. VARIÁVEIS NO DELPHI Variável é um local nomeado da memória, onde são guardados dados que podem ser mudados em tempo de execução. O nome de uma variável pode ter até 255 caracteres, tem que começar com uma letra, não pode conter caracteres brasileiros e ser única. O nome pode conter números e sublinhados e não pode ser uma palavra reservada. UNIT/MG Página: 35 Curso de DELPHI Elmo Batista de Faria, Dr. Existem vários tipos de variáveis, dependendo do tipo de dados que queremos que ela armazene. Tipos Inteiros ShortInt Integer LongInt Byte Word Tipos Booleanos Boolean ByteBool WordBoll LongBoll Tipos Reais Real Single Double Extended Comp Número de Bytes 1 2 4 1 2 Faixa -128 a 127 -32768 a 32767 -2147483648 a 2147483647 0 a 255 0 a 65535 1 1 2 4 1 byte booleano Byte - sized Booleano Word - sized Booleano Double - word - sized Booleano 6 4 8 10 8 2,9.10-39 a 1,7.1038 1,5.10-45 a 3,4.1038 5.10-324 a 1,7.10308 3,4.10-4932 a 1,1.104932 -263+1 a 263-1 UNIT/MG Página: 36 Curso de DELPHI Elmo Batista de Faria, Dr. Formas de Declarar uma Variável As variáveis são declaradas usando-se a palavra reservada Var, o nome da variável, dois pontos e o tipo Var Valor1: Real; Elas podem ser declaradas em três locais diferentes, conforme a sua abrangência: 1 - Variável Local; ela será utilizada somente pelo procedimento onde está declarada, terminado o procedimento ela desaparecerá da memória. É declarada logo após o cabeçalho do procedimento. 2 - Variável a nível de Unidade (Unit); a variável será utilizada por todos os procedimentos e funções da unidade. É declarada logo após a palavra reservada implementation. 3 - Variável a nível de projeto; é a variável que poderá ser utilizada por toda a aplicação, ou seja, poderá ser utilizada por outras unidades. É declarada na seção interface da unidade. FORMATAÇÃO DE NÚMEROS A função FloatToStr, transforma um número em texto, mas não padroniza a sua apresentação. Caso necessitemos formatar um dado a ser exibido, usaremos a função; FormatFloat(formato , expressão), onde: - formato = a maneira como deverá ser mostrada a expressão. - expressão = expressão numérica ou string a ser formatado. Formatando números: Formato 0 0,00 #.##0 #.##0,0 $#.##0;($#.##0) $#.##0,00;($#.##0,00) 0% 0,00E+00 5 positivo 5 5,00 5 5,0 $5 $5,00 500% 5,00E+00 5 negativo -5 -5,00 -5 -5,0 ($5) ($5,00) -500% -5,00E+00 5 decimal 1 0,50 1 0,5 $1 $0,50 50% 5,00E-1 Em “formato” o número 0 será mostrado ou trocado pelo caractere em sua posição, já o nirus (#) não será mostrado. Podemos inserir símbolos na função Format, como no exemplo: $ , % ou E. UNIT/MG Página: 37 Curso de DELPHI Elmo Batista de Faria, Dr. Formatando Data e Hora: Para formatar data e hora usamos a função: FormatDateTime (formato , data); Formato Exibido d/m/yy dd-mm-yyyy dd-ddd hh:mm AM/PM h:mm:ss a/p d/m/yy h:mm 10/7/96 01-Jun-1996 02-dom 08:50 AM 8:50:20 a 03/12/95 9:30 MODIFICANDO A CALCULADORA No Formulário da calculadora, selecione o botão de comando Button1 e pressione a tecla Delete. O botão de igual desaparecerá do formulário, mas o seu código continuará na janela Unit. Selecione a janela Unit, e observe que a procedure TfrmCalculadora.Button1Click continua no mesmo lugar. Agora, deixe o formulário TfrmCalculadora como o exemplo a seguir: Na figura aparecem as propriedades Name de cada objeto Para que o Button5 exiba o símbolo correto da divisão, primeiro altere a sua fonte para Symbol. Depois, abra o Mapa de caracteres do Windows e procure pelo símbolo da divisão na fonte Symbol, e então utilize o recurso de copiar e colar na propriedade Caption deste botão de comando. Provavelmente o caractere que aparecerá na caixa de propriedade não será o mesmo do botão, mas não se preocupe com este problema. UNIT/MG Página: 38 Curso de DELPHI Elmo Batista de Faria, Dr. Chame o procedimento para o Button1 dando um duplo clique no botão de comando. Note que antes este procedimento executava uma multiplicação, agora deverá executar uma soma. Usaremos também a função FormatFloat para formatar a apresentação do resultado. As duas variáveis Valor1 e Valor2 que antes pertenciam a apenas um procedimento, agora deverão ser utilizadas pelos procedimentos das outras operações. Para que isso ocorra, retire-as do procedimento TfrmCalculadora.Button1Click e declare-as na seção Implementation da Unidade. Substitua o tipo de operação em Button1Click, e nos demais botões, utilizando as ferramentas de Copiar e Colar. UNIT/MG Página: 39 Curso de DELPHI Elmo Batista de Faria, Dr. Teste os vários formatos de apresentação dos números, alterando o formulário de apresentação da função FormatFloat. Um projeto em Delphi trabalha com vários arquivos. Um arquivo para cada Formulário, outro para Unidade e um arquivo para o Projeto. Os arquivos de Unidades possuem a extensão .PAS, o arquivo do Projeto .DPR e o do Formulário, .DFM. Quando salvamos nosso projeto o Delphi solicita apenas os nomes dos arquivos de Unidade e Projeto, o do formulário ele cria automaticamente. Vamos salvar o nosso projeto Calculadora. No menu, selecione File / Saveall e aparecerá o quadro de diálogo de salvar do Windows, pedindo para dar um nome ao arquivo do Formulário, extensão .pas, dê o nome de calculadora e clique em Salvar. A seguir, aparecerá o mesmo quadro pedindo para dar um nome ao arquivo de projeto, extensão .dpr, dê o nome de calculador.dpr e clique em Salvar. Os nomes dos arquivos da Unidade e do Projeto deverão ser diferentes, apesar da extensão já o ser. UNIT/MG Página: 40 Curso de DELPHI Elmo Batista de Faria, Dr. O nosso projeto está salvo. Agora, precisamos escolher um ícone que o representará na tela do Windows. No menu principal do Delphi, selecione Project / Options..., e escolha a página Application: UNIT/MG Página: 41 Curso de DELPHI Elmo Batista de Faria, Dr. Clique no botão Load Icon... , e procure o ícone Finance.ico, no diretório \Images\Icons do Delphi, escolha Abrir para voltar à janela Project Options. Dê um título ao programa e pronto, o programa já possui um ícone e um título associados. Verifique no Explorando. Execute novamente o projeto para o Delphi gerar um novo arquivo executável contendo as últimas alterações realizadas. Agora, você tem um programa executável em qualquer microcomputador que possua o sistema Windows 95, sem necessariamente ter o DELPHI instalado. UNIT/MG Página: 42 Curso de DELPHI Elmo Batista de Faria, Dr. EXEMPLO IV - RELÓGIO DESPERTADOR Este projeto contém outro componente não visível - o TTimer. Este componente gera o evento OnTimer a intervalos regulares determinados em sua propriedade Interval. Esta propriedade esta expressa em milisegundos, ou seja, para que o evento OnTimer ocorra a cada segundo: Interval:=1000. Se Interval:=0 o Timer estará desativado. Devemos ter cuidado na programação do Timer, porque mesmo ele sendo capaz de gerar um evento a cada milisegundo, o procedimento que trata o evento pode demorar mais do que o valor de Interval, ocorrendo perda de algumas execuções do procedimento ligado a ele. Construa o Formulário como mostrada abaixo. A propriedade Caption dos Label1 e Label3 deverá estar em branco. No Label1, será apresentada a hora do sistema, e em Label3 a data atual. O componente RadioGroup permite construir um grupo de botões de opção, utilizamos estes botões quando precisarmos selecionar opções mutuamente excludentes. Só poderá haver um botão de opção selecionado por vez, em cada grupo ou no Formulário, caso o botão esteja fora de algum grupo. As opções de escolhas do RadioGroup estão na propriedade Items. Quando selecionamos esta propriedade, a janela String list editor é mostrada, onde poderemos editar os botões de opção do grupo. Entre com as duas opções, como mostrado a seguir. UNIT/MG Página: 43 Curso de DELPHI Elmo Batista de Faria, Dr. Feito o Formulário, vamos digitar o código para os eventos associados. Declare primeiro as variáveis Ligado e Tecla. Ligado indicará qual o botão de opção está selecionado, e Tecla armazenará um caractere digitado no teclado. implementation var Ligado: Boolean; Tecla: Char; {$R *.DFM} Quando o Formulário for criado, selecionaremos o botão Desligado, utilizando a sintaxe “RadioGroup1.ItemIndex:= 0”, a propriedade ItemIndex, indica qual o botão do grupo estará selecionado. UNIT/MG Página: 44 Curso de DELPHI Elmo Batista de Faria, Dr. Colocaremos a data do sistema em Label3 usando a função FormatDateTime, de acordo com a tabela mostrada no projeto da Calculadora. procedure TForm1.FormCreate(Sender: TObject); begin RadioGroup1.ItemIndex := 0; Label3.Caption:=FormatDateTime('dddd,dd "de" mmmm "de" yyy' ,Date); {a função Date retorna a data do sistema} end; A propriedade ItemIndex do RadioGroup1 será igual a 1 se o botão Ligado for selecionado, e igual a 0, caso Desligado esteja selecionado. procedure TForm1.RadioGroup1Click(Sender: TObject); begin if RadioGroup1.ItemIndex = 1 then Ligado:=True else Ligado:=False; end; Quando o usuário digita algo em um quadro Edit, o evento KeyPress ocorre. No procedimento a seguir, é realizada uma validação dos caracteres para definir a hora de acionamento do despertador. Caso não seja um caractere válido, é soado um alarme e este caractere excluído do Edit. O evento KeyPress envia para a procedure, mostrada abaixo, a variável Key do tipo Char, e será esta variável que o programa verificará. procedure TForm1.Edit1KeyPress(Sender: TObject; var Key: Char); begin Tecla:=(Key); if ((Tecla < '0') or (Tecla > '9')) and (Tecla <> ':') then begin Beep; Key:=chr(0); {a função chr(X:byte), retorna o caractere correspondente ao número X na tabela ASCII} end; end; UNIT/MG Página: 45 Curso de DELPHI Elmo Batista de Faria, Dr. Quando o evento Timer ocorrer (no caso a cada segundo - Interval:=1000), será feita uma verificação no conteúdo do Edit1 e se o alarme está Ligado ou não. O Timer também atualiza a hora mostrada no Label1. Se a hora no Edit1 for menor ou igual a hora do sistema e a variável Ligado verdadeira, o Beep soará. procedure TForm1.Timer1Timer(Sender: TObject); begin if (Edit1.Text <= TimeToStr(Time))and (Ligado) then begin Beep; Beep; end; Label1.Caption:=TimeToStr(Time); end; UNIT/MG Página: 46 Curso de DELPHI Elmo Batista de Faria, Dr. MÉTODOS GRÁFICOS Embora o uso dos métodos gráficos - que permitem desenhos de linhas, círculos e retângulos - sejam complexos, poderá ser divertido e útil para quem deseja sofisticar seus programas. A seguir, conheceremos tais recursos através de exemplos simples. O Sistema de coordenadas do Delphi, possui o seu ponto de origem (0,0) no canto superior esquerdo da tela, ao contrário do que nós estamos acostumados desde Descartes. A escala utilizada no Delphi é o Pixel, que representa um ponto visível na tela, de acordo com a resolução do monitor. As funções e procedimentos para desenho, estão agrupadas em um objeto da classe TCanvas, o Delphi cria para nós um objeto deste tipo de nome Canvas. É com este objeto que desenhamos na tela pois, a tela é realmente um objeto da classe TCanvas. DESENHO DE PONTO Para desenhar um ponto usamos a propriedade Pixels, do objeto Canvas; Canvas.Pixels [x,y]:= cor; Onde: Canvas - é o objeto do tipo TCanvas, declarado desta forma, o ponto será desenhado na área do cliente - Formulário. x,y - coordenadas horizontal e vertical, respectivamente. Elas são absolutas, ou seja, a partir da origem. cor - especifica uma cor para o ponto. O exemplo abaixo desenha um ponto nas coordenadas (50,50) do formulário na cor vermelha, quando o botão for selecionado. UNIT/MG Página: 47 Curso de DELPHI Elmo Batista de Faria, Dr. CORES Para determinarmos a cor de um gráfico, temos 3 formas diferentes de atribuir valores para o parâmetro cor, são elas: a) RGB - (NRed, NGreen, NBlue), onde NRed, NGreen e NBlue pode variar de 0 a 255. Ponto vermelho: Canvas.Pixels[x,y,]:= RGB(255,0,0); b) $00bbggrr - onde bb, gg e rr variam em hexadecimal de 00 a FF. Ponto Amarelo: Canvas.Pixels[x,y]:= $0000FFFF; c) Usando uma das constantes válidas para o objeto TColor. - Para cores fixas :clAqua, clBlack, clBlue, clDkGray, clFuchsia, clGray, clGreen, clLime, clLtGray, clMaroon, clNavy, clOlive, clPurple, clRed, clSilver, clTeal, clWhite, and clYellow. - Para cores definidas pelo sistema: clActiveBorder, clActiveCaption, clAppWorkSpace, clBackground, clBtnFace, clBtnHighlight, clBtnShadow, clBtnText, clCaptionText, clGrayText, clHighlight, clHighlightText, clInactiveBorder, clInactiveCaption, clInactiveCaptionText, clMenu, clMenuText, clScrollBar, clWindow, clWindowFrame, and clWindowText. Exemplo: Ponto Azul - Canvas.Pixels[x,y]:= clBlue: UNIT/MG Página: 48 Curso de DELPHI Elmo Batista de Faria, Dr. DESENHO DE LINHA Para desenharmos no Windows, usamos a propriedade Pen, que nada mais é que uma caneta invisível. Podemos alterar o modo como esta caneta desenha em nossa tela. O Delphi indica a posição desta caneta através da propriedade PenPos. Uma linha é desenhada utilizando-se os métodos MoveTo e LineTo para mover a Pen (caneta). MoveTo posiciona a caneta em um determinado lugar no Formulário. LineTo traça uma linha, que vai da posição corrente (PenPos) até as coordenadas especificadas. Copie o procedimento abaixo, inserindo-o no mesmo Formulário do exemplo do ponto. procedure TForm1.Button1Click(Sender: TObject); begin With Canvas do begin MoveTo(0,0); LineTo(100,ClientHeight); {ClienteHeight:=Altura da área de cliente no Formulário} LineTo (200,150); end; end; Quando queremos alterar várias propriedades ou métodos de um mesmo objeto, nós não precisamos indicar o seu nome em todos as linhas, basta usarmos a instrução With. Esta instrução significa que entre as palavras reservadas Begin .. End, o uso do objeto fica implícito para qualquer acesso a uma de suas propriedades ou métodos. No exemplo acima, utilizamos este recurso com o objeto TCanvas e seus métodos MoveTo e LineTo. O tipo TCanvas usa como propriedades outros dois tipos de objetos: o TPen e TBrush. O TPen é a nossa caneta, este tipo possui propriedades que modificam a forma das linhas a serem desenhadas, são elas: Color - define a cor da linha UNIT/MG Página: 49 Curso de DELPHI Elmo Batista de Faria, Dr. Width - define a espessura da linha - em pixels Style - determina o tipo de linha. Modifique o exemplo anterior, como mostrado a seguir: procedure TForm1.Button1Click(Sender: TObject); begin With Canvas do begin MoveTo(0,0); LineTo(100,ClientHeight); Pen.Color:=clBLue; LineTo (200,150); end; Note que a segunda linha desenhada é da cor azul. Vamos montar exemplos que usem as outras duas propriedades - Width e Style. procedure TForm1.Button1Click(Sender: TObject); var Estilo: array [0..6] of TPenStyle; i: Integer; SX: Integer; SY: Integer; begin Estilo[0]:= psSolid; Estilo[1]:= psDash; Estilo[2]:= psDot; Estilo[3]:= psDashDot; Estilo[4]:= psDashDotDot; Estilo[5]:= psClear; Estilo[6]:= psInsideFrame; SX := ClientWidth; SY := ClientHeight; With Canvas do begin SY:=Trunc(SY/8); {a procedure Trunc, transforma um valor do tipo Real em tipo Inteiro} for i:= 0 to 6 do begin Pen.Style:= Estilo[i]; MoveTo(0,(i*SY)+20); LineTo(SX,(i*SY)+20); end; end; UNIT/MG Página: 50 Curso de DELPHI Elmo Batista de Faria, Dr. end; Começamos declarando uma matriz - Estilo - com o tipo TPenStyle. armazenaremos todos os estilos da caneta. Nesta matriz ClientWidth e ClientHeight, retornam um valor do tipo inteiro indicando o tamanho da área do cliente no Formulário, quando este número é dividido ele passa a ser um tipo Real, então nós precisamos convertê-lo novamente em Inteiro para que os métodos MoveTo e LineTo possam aproveitá-lo. Canvas.Pen.Style:= psDot; Canvas.Pen.Style:= psDot; ou With Canvas do begin Pen.Style:= psDot; Pen.Color:=clBlue; end; Antes de executar o exemplo acima, altere a propriedade Color de Form1 para clWhite (Color:=clWhite) para uma visualização melhor das linhas, teremos então todos os estilos de linha desenhados no Formulário mostrado abaixo: UNIT/MG Página: 51 Curso de DELPHI Elmo Batista de Faria, Dr. Altere o procedimento anterior, para serem mostradas as várias espessuras de linha. procedure TForm1.Button1Click(Sender: TObject); var i: Integer; SX: Integer; SY: Integer; begin SX := ClientWidth; SY := ClientHeight; With Canvas do begin SY:=Trunc(SY/8); {a procedure Trunc, transforma um valor do tipo Real em tipo Inteiro} {Os comentários ficam entre chaves} for i:= 0 to 6 do begin Pen.Width:= i+1; MoveTo(0,(i*SY)+20); LineTo(SX,(i*SY)+20); end; end; end; Para desenharmos retângulos usamos o método Retangle do TCanvas. Como parâmetros são utilizadas as coordenadas do canto superior esquerdo e inferior direito do retângulo. UNIT/MG Página: 52 Curso de DELPHI Elmo Batista de Faria, Dr. Canvas.Retangle (X1, Y1 , X2, Y2); Digite o exemplo abaixo. procedure TForm1.Button1Click(Sender: TObject); begin With Canvas do begin Rectangle (10,10,110,110); Rectangle (130,10,330,110); end; end; Observe que o desenho ficou por trás do botão, isto ocorre por que o botão está acima do Formulário e o desenho faz parte da tela do Formulário, seria como uma borracha em cima de um papel desenhado. Para preenchermos este retângulos, usamos o tipo TBrush que como TPen, está contido em TCanvas. As propriedades mais comuns do TBrush são: Color - define a cor do interior da figura Style - indica o padrão de preenchimento As cores são as mesmas da Pen e os estilos são: bsSolid, bsClear, bsBDiagonal, bsFDiagonal, bsCross, bsDiagCross, bsHorizontal e bsVertical. UNIT/MG Página: 53 Curso de DELPHI Elmo Batista de Faria, Dr. Faça o exemplo a seguir. procedure TForm1.Button1Click(Sender: TObject); begin With Canvas do begin Brush.Style:=bsFDiagonal; Brush.Color:=clBlack; Rectangle (10,10,110,110); Brush.Color:=clRed; Brush.Style:=bsHorizontal; Rectangle (130,10,330,110); end; end; UNIT/MG Página: 54 Curso de DELPHI Elmo Batista de Faria, Dr. O desenho de elipses é feito com o método Ellipse. A elipse ou o círculo são desenhados usando-se as duas coordenadas de um retângulo delimitador - imaginário - onde a figura estará inscrita. Siga o exemplo a seguir. procedure TForm1.Button1Click(Sender: TObject); begin With Canvas do begin Rectangle (10,10,100,80); Ellipse (10,10,100,80); Ellipse (110,10,200,80); end; end; UNIT/MG Página: 55 Curso de DELPHI Elmo Batista de Faria, Dr. EXEMPLO V - CATÁLOGO Neste projeto de catálogo telefônico, trabalharemos com acesso a arquivos do tipo aleatório. Ele será constituído por três Units e dois Formulários. Duas Units serão associadas aos formulários e a outra Unit conterá apenas códigos de acesso ao disco (HD) sem estar associada a nenhum formulário. Inicie um novo projeto e crie o Formulário, inserindo e modificando as propriedades dos objetos, como a figura abaixo. Altere a propriedade Filter do controle SaveDialog. Será então mostrada a janela Filter Editor, edite-a como mostra o modelo abaixo. UNIT/MG Página: 56 Curso de DELPHI Elmo Batista de Faria, Dr. Dê um duplo clique no controle MainMenu e edite o menu. Deveremos inserir um novo formulário ao nosso projeto que será utilizado para selecionar um determinado registro no nosso arquivo de dados. Para inserir um novo formulário ao projeto, escolha a Opção New Form do menu File ou selecione o botão ferramentas. Monte este novo Formulário como mostrado abaixo. na barra de Este novo formulário irá apresentar ao usuário os nomes de pessoas - registros no arquivo - contidos no catálogo através do componente ComboBox (caixa combinada). O ComboBox, é um controle de edição associado à uma lista contendo itens disponíveis para a escolha do usuário. O usuário poderá tanto digitar uma opção no quadro de edição, quanto escolher uma opção fornecida pela lista associada. A propriedade Style, determina o tipo de ComboBox que iremos trabalhar, que pode ser: csDropDown - Cria uma lista drop-down com uma caixa de texto, para entrada de texto manualmente. Todos os itens são Strings de qualquer comprimento. CsSimple - Cria uma caixa de texto associada a uma caixa de lista suspensa. Esta lista não aparecerá em tempo de execução a menos que o ComboBox seje dimensionado para acomodá-la. CsDropDownList - Cria uma lista drop-down com uma caixa de texto, mas o usuário não poderá entrar com texto manualmente. UNIT/MG Página: 57 Curso de DELPHI Elmo Batista de Faria, Dr. csOwnerDrawFixed - Cria uma lista drop-down com uma caixa de texto, para entrada de texto manualmente. Mas cada item do ComboBox terá seu comprimento em caracteres determinado pela propriedade ItemHeight. CsOwnerDrawVariable - Cria uma lista drop-down com uma caixa de texto, para entrada de texto manualmente. Os itens neste ComboBox podem ter comprimento variável. Vamos alterar a propriedade Style do nosso quadro combo, para csDropDownList, pois não queremos que o usuário altere o conteúdo do combo. Evitando que o usuário entre com um nome de pessoa inexistente. INSERINDO UMA NOVA UNIDADE Uma Unit pode estar vinculada a um formulário ou não, nós iremos criar uma Unit não vinculada a nenhum formulário. Escolha a opção New... do menu File e aparecerá a janela New Itens, escolha Unit. O Delphi criará uma nova Unit não vinculada a nenhum formulário, já com o cabeçalho pronto. Onde iremos digitar as rotinas de acesso ao disco. UNIT/MG Página: 58 Curso de DELPHI Elmo Batista de Faria, Dr. TIPOS No Delphi nós podemos criar nossos próprios tipos de dados, para fazer isto, declare o seu tipo de dado dentro de um bloco Type, antes do bloco de definição de variáveis Var: type TMeusValores = ShortInt; var Venda, Custo : TMeusValores; É interessante definir um tipo de variável, porque quando tivermos uma família de variáveis relacionadas e for necessário mudar o tipo de todas elas, basta alterar a declaração de definição de tipo destas variáveis: type TMeusValores = LongInt; Venda e Custo eram variáveis ShortInt, e após a nova definição passam a ser LongInt. REGISTROS Para armazenar os dados de uma pessoa (Nome, Endereço e Telefone), usamos um registro. Registro é um tipo de dado que reúne alguns itens de tipos diferentes, nosso tipo registro terá o nome de TPessoasReg. Em um projeto podem existir várias variáveis do tipo TPessoasReg. UNIT/MG Página: 59 Curso de DELPHI Elmo Batista de Faria, Dr. Declare o novo tipo na seção Interface da Unit nova (ArqUnit - nome salvo em disco). unit ArqUnit; interface type {registro com dados pessoais} TPessoasReg=record CNome: String[30]; CTelefone: String[15]; CEndereco: String[40]; end; TPessoas = file of TPessoasReg; var PesArq: Pessoas; O Delphi possui um tipo denominado arquivo, que permite escrever e ler arquivos em disco. Para declarar um tipo arquivo, associamos o nome da variável a um tipo de dado previamente existente. No nosso caso: TPessoasReg. Na listagem acima definimos além do tipo TPessoasReg, o tipo Tpessoas, definindo-o como um tipo de arquivo formado por registros do tipo TPessoasReg. Os campos são declarados como String de tamanhos fixos pois, caso não fossem declarados os tamanhos, eles iriam ocupar o espaço de 255 Bytes. Logo após, informamos ao Delphi que existe um tipo de arquivo composto por esse registro, e declaramos uma variável do tipo desse arquivo de registros, essa variável conterá o nome do arquivo aberto em disco. Algumas procedures e functions, precisam de parâmetros para trabalharem, nós declaramos esses parâmetros no cabeçalho da procedure, indicando um nome de referência, o seu tipo de dado e o prefixo var. Primeiro declaramos as procedures na seção Interface e depois implementamos na seção Implementation. procedure AbrirArq(var A:Pessoas; var NomeArq:String; var N:Boolean); procedure FecharArq(var A:Pessoas); procedure GravarArq(var A:Pessoas;var RegN:Integer; var Reg:PessoasReg); procedure LerArq(var A:Pessoas;var RegN:Integer; var Reg:PessoasReg); implementation UNIT/MG Página: 60 Curso de DELPHI Elmo Batista de Faria, Dr. procedure AbrirArq(var A:Pessoas; var NomeArq:String; begin Assign (A, NomeArq); if N then Rewrite (A) else Reset (A); end; var N:Boolean); procedure FecharArq (var A:Pessoas); begin Close (A); end; procedure GravarArq (var A:Pessoas;var RegN:Integer; var Reg:PessoasReg); begin Seek (A,RegN); Write (A,Reg); end; procedure LerArq (var A:Pessoas;var RegN:Integer; var Reg:PessoasReg); begin Seek (A,RegN); Read (A,Reg); end; Antes de abrir um arquivo para leitura e gravação, nós temos que associá-lo a uma variável do mesmo tipo dos registros contidos no arquivo em disco. Para isso usamos a procedure Assign. Assign diz ao Delphi que todas as operações com a variável terão ligação com um arquivo em particular. Assign(variável, nome do arquivo); Após a associação, abriremos o arquivo, que pode ser de duas formas: 1) Reset - abre o um arquivo existente para leitura ou gravação. 2) Rewrite - abre um arquivo novo para leitura ou gravação. Caso já exista o arquivo, todos os dados anteriores serão perdidos. Reset(nome do arquivo); Rewrite(nome do arquivo); UNIT/MG Página: 61 Curso de DELPHI Elmo Batista de Faria, Dr. Para gravar ou ler um registro, usamos as funções Write e Read, informando a variável do arquivo e em qual variável estará o registro. Write(PessArq, Reg); Read(PessArq, Reg); PONTEIRO DE REGISTROS O ponteiro do arquivo indica qual o registro será afetado com a próxima operação de leitura ou gravação. Sempre que um arquivo é aberto, o ponteiro é posicionado no início do arquivo. Cada operação de leitura ou gravação, move o ponteiro um registro à frente. Ou seja, se o registro 3 for lido, o ponteiro estará apontando para o registro 4, e a próxima operação será realizada com o registro 4. Para acessar um registro aleatoriamente, usamos a procedure Seek. Esta procedure posiciona o ponteiro no registro que quisermos, antes de uma leitura ou gravação. Seek(PessArq, RegN); Os registros em um arquivo são numerados seqüencialmente a partir do registro 0. Existem mais duas funções úteis para manipulação de arquivos, FileSize e FilePos. A primeira indica quantos registros o arquivo tem, e a segunda indica a posição do ponteiro. Para ligarmos as Units, devemos colocar o nome das Units acessadas na seção uses. Uma vez nomeada uma unidade na seção uses de outra unidade em que esteja trabalhando, você poderá referenciar qualquer coisa na seção de interface da unidade nomeada. Poderemos acessar as variáveis e procedures da outra unidade. O nosso formulário frmCatalogo (Unit Catalogo), terá acesso aos procedimentos da Unit IrPara e ArqUnit. Então, declaramos estas duas unidades logo após às unidades já colocadas pelo Delphi. unit Catalogo; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, Menus, StdCtrls, ArqUnit, IrPara; UNIT/MG Página: 62 Curso de DELPHI Elmo Batista de Faria, Dr. Declare as variáveis que iremos utilizar, como mostrado abaixo. private { Private declarations } ArqNovo : String; ArqAtual: String; Novo: Boolean; ArquivoAberto: Boolean; public { Public declarations } end; Comece a implementação dos procedimentos associados aos objetos e seus eventos, seguindo as listagens abaixo. procedure TfrmCatalogo.Sair1Click(Sender: TObject); begin Close; end; procedure TfrmCatalogo.Novo1Click(Sender: TObject); begin Nome.Text:=''; Telefone.Text:=''; Endereco.Text:=''; Novo:=True; ArqNovo:='Temp.dat'; ArqAtual:= ArqNovo; ArqUnit.AbrirArq (PesArq, ArqNovo, Novo); ArquivoAberto:=True; end; procedure TfrmCatalogo.Abrir1Click(Sender: TObject); begin Nome.Text:=''; Telefone.Text:=''; Endereco.Text:=''; if OpenDialog1.Execute then begin ArqAtual:=OpenDialog1.Filename; Novo:=False; ArqUnit.AbrirArq (PesArq, ArqAtual, Novo) end else Exit; ArquivoAberto:=True; end; UNIT/MG Página: 63 Curso de DELPHI Elmo Batista de Faria, Dr. Para se referir a um procedimento em outra unidade, nós informamos primeiro o nome da unidade e depois o nome do procedimento: ArqUnit.AbrirArq(...);. procedure TfrmCatalogo.btnNovoClick(Sender: TObject); var Reg: ArqUnit.PessoasReg; RegN: Integer; begin Nome.SetFocus; if ArquivoAberto=false then begin ShowMessage ('Abra primeiro um arquivo'); Exit; end; if btnNovo.Caption='&Novo Registro' then begin Nome.Text:=''; Telefone.Text:=''; Endereco.Text:=''; btnNovo.Caption:='A&dicionar'; end else begin with Reg do begin CNome:=Nome.Text; CTelefone:=Telefone.Text; CEndereco:=Endereco.Text; end; frmProcurar.Lista.Items.Add (Nome.Text); RegN:= FileSize(PesArq); ArqUnit.GravarArq (PesArq, RegN, Reg); btnNovo.Caption:='&Novo Registro'; end; end; procedure TfrmCatalogo.btnAtualizarClick(Sender: TObject); var Reg : PessoasReg; RegN :integer; begin with Reg do begin CNome:=Nome.Text; CTelefone:=Telefone.Text; CEndereco:=Endereco.Text; end; frmProcurar.Lista.Items.Add (Nome.Text); RegN:= FilePos(PesArq)-1; ArqUnit.GravarArq (PesArq, RegN, Reg); end; UNIT/MG Página: 64 Curso de DELPHI Elmo Batista de Faria, Dr. procedure TfrmCatalogo.FormCreate(Sender: TObject); begin ArquivoAberto:=False; end; procedure TfrmCatalogo.Salvar1Click(Sender: TObject); begin if SaveDialog1.Execute then begin ArqNovo:=SaveDialog1.Filename; ArqUnit.FecharArq (PesArq); RenameFile(ArqAtual,ArqNovo);{a função RenameFile,} Novo:=False; {renomeia um arquivo} ArqUnit.AbrirArq (PesArq, ArqNovo, Novo); end; end; procedure TfrmCatalogo.btnProcurarClick(Sender: TObject); begin frmProcurar.ShowModal; end; Para mostrar outro Formulário, usamos o método Show ou ShowModal. Show abre uma janela onde podemos alternar com outras janelas do aplicativo, enquanto ShowModal não aceita uma troca da janela ativa. Com ShowModal o usuário só poderá ir para outra janela, após ter fechado a janela Modal. Comece a construção do código para o Formulário frmProcurar, informando ao Delphi que ela irá acessar a ArqUnit. unit IrPara; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ArqUnit; Declare as variáveis ReN e Reg. private { Private declarations } RegN: Integer; Reg: PessoasReg; Siga a listagem abaixo para os eventos associados. UNIT/MG Página: 65 Curso de DELPHI Elmo Batista de Faria, Dr. procedure TfrmProcurar.FormActivate(Sender: TObject); begin Lista.Clear; {limpa o conteúdo do ComboBox} Seek (PesArq,0); while Not Eof (PesArq) do {enquanto não chegar ao final do arquivo, faça...} begin Read(PesArq,Reg); Lista.Items.Add (Reg.CNome); end; end; procedure TfrmProcurar.btnCancelarClick(Sender: TObject); begin frmProcurar.Close; end; procedure TfrmProcurar.btnOkClick(Sender: TObject); begin RegN:=Lista.ItemIndex; ArqUnit.LerArq (PesArq,RegN,Reg); With frmCatalogo do begin Nome.Text:=Reg.CNome; Endereco.Text:=Reg.CEndereco; Telefone.Text:=Reg.CTelefone; end; frmProcurar.Close; end; Para preencher um quadro combo com dados, temos duas possibilidades: 1) Usar o método Add para a sua propriedade Items. Em tempo de execução. 2) Editar a propriedade Items em tempo de projeto. Por fim, declare Catalago na seção Implementation. Porque a unidade IrPara também se referencia à Catalogo, mas se Catalogo for declarada na seção uses da interface, o Delphi gerará um erro de referência circular. implementation uses Catalogo; {$R *.DFM} UNIT/MG Página: 66 Curso de DELPHI UNIT/MG Elmo Batista de Faria, Dr. Página: 67 Curso de DELPHI Elmo Batista de Faria, Dr. LISTA DE EXERCÍCIOS 1. Qual a diferença entre um programa feito para trabalhar sob o DOS e outro construído através do Delphi? 2. O que encontramos na Paleta de Componentes? 3. Qual a função da janela Object Inspector? 4. Quais os passos para desenvolvermos um programa em Delphi após a análise do projeto? 5. No primeiro programa que desenvolvemos, coloque um botão de comando que apague o conteúdo do label, e outro que finalize o programa. 6. Na calculadora, mesmo redefinindo a propriedade TabStop do Edit de resultado, o usuário poderá alterar o resultado da operação. Que outro controle poderíamos utilizar no lugar de um TEdit para exibir o resultado sem que o usuário possa alterar seu valor? Altere o projeto. 7. O ícone escolhido para representar o projeto, não estará presente no formulário. Qual propriedade deveremos alterar para que o ícone representante do projeto também esteje no formulário? Responda e execute. 8. Altere os botões do Jogo da Velha para o tipo BitBtn, e reconstrua o projeto para alterar as propriedades Kind e Caption, exibindo nos botões os ícones - e . 9. No Jogo da Velha, sempre o computador inicia uma nova partida. Altere o código para que o programa pergunte ao usuário quem iniciará uma nova partida. 10. No projeto Bloco de Notas, quando escolhemos a opção Sair, o programa não pergunta se queremos salvar as alterações realizadas no texto. Inclua uma variável booleana na seção Implementation, alterando o seu valor no procedimento Memo1Change e verificando-a no momento de encerrar o programa. 11. Inclua mais um botão no Relógio Despertador com a opção de Soneca, soando o Beep dez minutos após o primeiro despertar. 12. Construa um projeto que mostre todos os tipos de preenchimentos (hachuras) dentro de círculos em um único formulário. 13. Substitua o controle ComboBox por um ListBox pesquisa pelo número do telefone. no exemplo de Catálogo, com 14. No último exemplo, crie mais uma tabela de Estoque, e a cada venda realizada os valores de estoque deverão ser atualizados. UNIT/MG Página: 68 Curso de DELPHI Elmo Batista de Faria, Dr. BANCO DE DADOS SIMPLES Um banco de dados pode ser definido como um conjunto unificado de informação que vai ser compartilhado pelas pessoas autorizadas de uma organização. A função de um Banco de Dados é permitir o armazenamento e a recuperação da informação necessária para as pessoas da organização tomarem decisões. Um Banco de Dados é formado por um conjunto de arquivos de dados, também chamados de tabelas. Em uma tabela temos, linhas e colunas. Onde uma linha contém informações a respeito de um item em particular, e a coluna possui uma parte das informações de uma linha. A figura a seguir ilustra uma tabela de Clientes. Código 001 002 005 012 150 Nome Aldair Marina Aline José Márcio Telefone 554-8788 879-9687 572-2258 7070-8580 446-3987 A tabela mostrada acima possui os campos ou colunas: Código, Nome e Telefone. E em cada linha temos a identificação de um cliente em particular. Cada tabela em um banco de dados possui um campo que identifica unicamente cada registro. O conjunto de atributos ou campos utilizados para gerar este índice é conhecido como chave primária. Nós podemos escolher qualquer campo de uma tabela para ser uma chave primária, sempre levando em consideração que ela deve ser curta. Por exemplo, usar um campo numérico é melhor do que um campo formado por Strings. Como a chave primária determina a singularidade de um registro, quando se usa um string não poderemos ter dois registros com o mesmo nome de cliente. Na tabela do exemplo acima, o mais sensato é determinar o campo Código como nossa chave primária. Além de determinarmos os campos e a chave primária da nossa tabela, também teremos que definir o tipo de dado, comprimento, formato e o domínio para cada campo desta tabela. Tipo de Dado: refere-se ao conteúdo do dado, podendo ser numérico, alfabético, data, hora ou cadeia de caracteres longa ou curta. Comprimento: refere-se ao tamanho ou número máximo de posições que poderá assumir o valor ou conteúdo de cada dado. Formato: refere-se à forma com que os dados deverão ser editados ou apresentados, definindo-se as posições de símbolos. Domínio: especifica se os valores dos dados pertencem a uma lista de valores pré definidos, podendo estar em uma lista, ou satisfazer uma regra. UNIT/MG Página: 69 Curso de DELPHI Elmo Batista de Faria, Dr. Objetivos: Uma completa aplicação utilizando banco de dados ( Um sistema de livrarias ). Introdução teórica: Para se desenvolver uma aplicação em Delphi ligada a um banco de dados é bastante simples. Em resumo são necessários três passos: 1- Inserir no formulário da aplicação componentes que acessarão as tabelas, consultas e campos: São componentes de acesso a banco de dados; 2- Inserir no formulário da aplicação componentes que mostrarão os dados: São os componentes de visualização de dados; 3- Inserir no formulário da aplicação um componente especial, que fará a ponte entre os componentes que acessam os dados e os componentes que os mostram. 1) Componentes de acesso a dados A paleta de componentes de acesso a dados DataAccess pode por exemplo associar componentes Table(tabelas) e o componente Query (pesquisa), como mostrado Table abaixo: DataSource StoredProc Session Database Query UpdateSQL BatcMove Report 2) Componentes de visualização de dados A paleta Data Control contém os componentes de visualização de dados: DBComboBox DBEdit DBNavigator DBGrid DBGrid DBText DBImage DBLookupCombo DBRadioGroup DBMemo DBListBox DBLookupList DBCheckBox DBCtrlGrid COMO O DELPHI SE RELACIONA COM OS BANCOS DE DADOS Uma aplicação desenvolvida em Delphi utilizando banco de dados é construída utilizando-se os recursos do próprio Delphi ( componentes de acesso e visualização de dados), e os utilitários Database Desktop, ReportSmith entre outros. O delphi utiliza um dispositivo residente em memória que faz a ligação dos componentes UNIT/MG Página: 70 Curso de DELPHI Elmo Batista de Faria, Dr. acima com os seus respectivos bancos de dados. Este dispositivo é o Borland Database Engine (BDE). São um conjunto de funções e drivers de acesso aos mais variados tipos de banco de dados, como mostrado na figura abaixo: Delphi IDE ReportSmith BDE Configuration Utility Database Desktop (DBD) Delphi Aplication Report Borland Database Engine (BDE) / IDAPI Dbase Paradox ASCII Interbase for Windows SQL Links ODBC Drivers ReportSmith Drivers TCP/IP, spx/ipx, etc Remoto Database: Oracle, Sybase, Informix, Interbase, etc; - Tipos de bancos de dados acessáveis ao Delphi. Ao instalar o Delphi são instalados automaticamente Drivres para acesso a banco de dados Paradox e Dbase. Para acessar outros tipos de banco de dados deve-se utilizar utilitários de configuração do BDE (Database Engine Configuration) para criar uma conexão com este banco de dados. Como Utilizar o Database Desktop Database Desktop permite criar e manipular banco de dados no formato dBase, Paradox ou SQL. - Criando uma tabela no Database Desktop • Inicialize o Programa DataBase Desktop escolha File a opção New. UNIT/MG Página: 71 Curso de DELPHI Elmo Batista de Faria, Dr. • Escolha o tipo de arquivo a ser criado no caso Table. • No quadro escolha Paradox7. Os campos da tela indicam: 1- Entre com o nome do campo, tipo e tamanho; 2- Um clique duplo em Key transforma o campo em campo chave. 3- Presione Enter para passar para o próximo campo; 4- O botão Borrow serve para copiar a estrutura de outras tabelas. 5- Required Field serve para obrigar o usuário a sempre entrar com um valor para o campo. 6- Os campos mínimos definem um valor mínimo para o campo, o campo máximo define um valor máximo para o campo ou default para definir um valor padrão. Obs.: Key (chave) é um campo ou um grupo de campos usado para ordenar registros garantindo a integridade referencial o uso da chave implica em três consequências: • Faz com que a tabela não possua registros duplicados para este campo. • Os registros são mantidos em ordem neste campo. • Um índice primário é criado para esta tabela. Exercícios (vamos iniciar o sistema proposto) Montando uma tabela para aplicação do gerente de livrarias UNIT/MG Página: 72 Curso de DELPHI Elmo Batista de Faria, Dr. - Inicialize o Database Desktop. - Escolha, no menu File, a opção New, Sub-opção Table. - No quadro Table Type, escolha a tabela do tipo Paradox - No quadro Create Table, crie os campos como ao lado. - Crie um índice secundário (o primeiro corresponde ao campo Código, com o nome icodigo). No quadro Table Proprierties, escolha a opção Seconary Indexes, dê um duplo clique sobre o campo Nome, e clique OK. Dê o nome iNome para o índice, faça o mesmo para o índice icodigo. - Salve a estrutura da tabela no botão Save As escolha o disquete e crie um diretório para o banco de dados com o nome de ‘DataBase’ e o nome da tabela de Livros.db. - Escolha a opção Open, sub-opção Table. - Recupere a tabela Livros. Escolha no menu Table ,a opção Edit Data, para entrar no modo de edição. Escolha pelo menos três dados e insira na tabela. Em seguida salve os dados. Ex: Navega pelos registros Edita dados Obs.: para se apagar um registro inteiro basta digitar Ctrl + Del sob alinha isto vale também para apagar linhas quando estiver estruturando a tabela. UNIT/MG Página: 73 Curso de DELPHI Elmo Batista de Faria, Dr. - Repita o processo escolhendo New Table e vamos criar uma tabela para clientes chamada Clientes.db e um última tabela chamada vendas.db A estrutura destas tabelas estão abaixo. - Defina Código como chave e nome como índice secundário para esta tabela como descrito anteriormente. - Inicialize as tabelas com dados hipotéticos. - Nesta fase teremos então no disquete A: um diretório com as tabelas principais de nossa aplicação Livros.db, Clientes.db, Vendas.db. Fim desta parte da aplicação Configurando o acesso a banco de dados Como discutido anteriormente o Delphi acesa seus bancos de dados através do BDE (Borland Database Engine), o BDE permite que o local onde estão as tabelas de um banco de dados sejam acessadas através de um ‘Apelido’ e o Alias. Quando inserimos um componente TTable ou TTquery em um formulário, precisamos configurar a propriedade DatabaseName com o path (caminho) do banco de dados (ex.: na aplicação anterior o path é a:\database). Se por qualquer motivo mudarmos a localização do banco de dados, precisamos então mexer em todos os formulários que usem este banco de dados, o que pode ser um trabalho exaustivo e perigoso, sujeito a erros. Para evitar isto, podemos criar um alias para o banco de dados. Ao invés de colocarmos o path do arquivo na propriedade DatabaseName , colocaremos o alias do banco de dados. O alias é criado no Database Engine Configuration. Escolha a página Aliases, em seguida: UNIT/MG Página: 74 Curso de DELPHI Elmo Batista de Faria, Dr. 1- Para criar um novo alias, clique sobre o botão New Alias no quadro ao lado. Aparecerá o quadro de Add New Alias abaixo: 2 1 4 3 iniciar 2- Na caixa New Alias Name escreva o nome do novo alias; 3- Na caixa Alias type, escolha o tipo do alias para banco de dados Dbase e Paradox, escolha Standard, e finalize com OK; 4- Voltando a caixa de diálogo principal podemos ver a configuração do alias que criamos como o path, o driver do banco de dados que vamos utilizar e demais informações. 5- Finalize salvando o alias no IDAPI.CFG padrão do BDE. Exercícios (vamos criar um aliases para o sistema exemplo) 1- Inicialize o DBE configuration clicando sobre o ícone na pasta do delphi; 2- Clique na parte inferior aliases (observe na figura acima quadro iniciar); 3- selecione New alias (caixa de diálogo figura acima posição 1); 1- Preencha o quadro New alias Name com o nome AplicaçãoExemploLC , como na figura ao lado: 2- O tipo de alias na opção seguinte continua como padrão pois os banco de dados são do tipo Paradox, finalize com OK. 3- Voltando a tela principal atualize o caminho ( mostrado na figura acima posição 4) clique sobre o PATH e insira a:\DataBase ,em seguida escolha File e salvar esta configuração e esta pronto o alias para o banco de dados da aplicação (Obs.: Pode escolher ‘salvar como’ e salvar o arquivo de configuração no próprio disco, evitando assim que ao utilizar outro computador tenhamos de fazer todo este procedimento novamente a fim de criar uma nova configuração ao BDE local desta nova máquina). UNIT/MG Página: 75 Curso de DELPHI Elmo Batista de Faria, Dr. Definindo os Formulários Que serão Utilizados na aplicação 1. Inicialize o programa Delphi - iniciaremos com a montagem das telas apropriadas primeiro a Janela principal: 1 1- Inicialize o programa Delphi e utilize a nova aplicação que se inicializa junto com o programa ou ainda pode-se selecionar New Aplication no menu File que um formulário branco aparecerá. 2- mude a propriedade caption do formulário para o título “Sistema de Gerenciamento de Livrarias - LC”. 3- Insira os componentes Button no formulário, Button1 - Clientes, Button2 - Livros, Button3 - Vendas, e 2 utton4 - Sair. 4- A unit ficará da seguinte forma: unit FrmPrin; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm1 = class(TForm) Button1: TButton; Button2: TButton; Button3: TButton; Button4: TButton; procedure Button4Click(Sender: TObject); procedure Button1Click(Sender: TObject); procedure Button2Click(Sender: TObject); procedure Button3Click(Sender: TObject); private { Private declarations } public { Public declarations } end; UNIT/MG Página: 76 Curso de DELPHI var Form1: TForm1; implementation {$R *.DFM} procedure TForm1.Button4Click(Sender: TObject); begin Close; Insira o código apenas para o botão SAIR end; end. Elmo Batista de Faria, Dr. Botão de salvamento completo 5- Agora salvaremos a aplicação, utilize o botão de salvamento total da aplicação, mostrado acima. Após pressionado aparecerá a caixa de diálogo solicitando um nome para o código fonte *.pas selecione Salvar em : escolha drive A: em seguida digite FRMPRIN para o nome do arquivo, neste instante uma outra caixa idêntica para o projeto aparecerá digite LIVRARIA para o nome do projeto, observe abaixo: Selecione o drive A: 6 - Os arquivos do drive A: neste momento deve conter: - 1 arquivo .DFM - Arquivo binário com especificação do layout do formulário; - 1 arquivo .PAS - arquivo de código; - 1 arquivo .DPR - arquivo de projeto; entre outros. Obs.: A aplicação proposta de acordo com o formulário principal deverá ter um formulário para o botão de clientes um formulário para cadastro e pesquisa de livros e um formulário final para vendas. O próximo passo é o desenvolvimento do formulário de clientes cadastro e consultas. Montagem do formulário de clientes Neste ponto se sua aplicação foi salva em disquete e interrompida, necessitamos que seja novamente inicializado o programa Delphi e escolha OPEN PROJECT escolha o drive A e abra a aplicação Livraria o formulário principal mostrado anteriormente deve aparecer. Montaremos agora o formulário de clientes: 1- Após visualizar o formulário principal, escolha agora a opção NEW FORM no menu FILE ou pressione o botão da barra de ferramenta como mostrado abaixo. Botão NEW FORM UNIT/MG Página: 77 Curso de DELPHI Elmo Batista de Faria, Dr. 2- Aparecerá um formulário novo e uma unit nova. Inicialmente mude a propriedade Caption do formulário para Cadastro de Clientes, e a propriedade Name para Form2 se já não estiver. 3- Insira os componentes que serão usados neste formulário com os seus respectivos nomes, observe o código fonte abaixo inicial do formulário: unit FrmCli; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ExtCtrls, Mask, DBCtrls; 2 type TForm2 = class(TForm) 1 → Panel1: TPanel; 2 → DBNavigator: TDBNavigator; 13 3 → Panel2: TPanel; 9 10 4 → ScrollBox: TScrollBox ; 5 5 → Label1: TLabel; 6 6 → Label2: TLabel; 7 7 → Label3: TLabel ; 8 → Label4: TLabel; 12 11 8 14 9 → EditCODIGO: TDBEdit; 10 → EditNOME: TDBEdit ; 11 → EditENDERECO: TDBEdit; 15 12 → EditTELEFONE: TDBEdit ; 13 → Button1: TButton; 14 → Button2: TButton; 15 → RadioGroup1: TRadioGroup; private { Private declarations } public { Public declarations } end; var Form2: TForm2; implementation {$R *.DFM} end. 4- A propriedade Caption do componente RadioGroup no formulário, deve ser mudada para ORDENADO POR: e criando dois botões de rádio, o primeiro de título Código e o segundo de título Nome. Mude a propriedade ItemIndex para 0, para que fique marcado o botão código. 5- Salve todo o trabalho selecionando o botão SAVE ALL como mencionado anteriormente. Observe agora que aparecerá uma nova caixa de diálogos para que você possa inserir um nome para o formulário 2 digite FORMCLI e OK. 6- Agora insira no formulário principal na UNIT FORMPRIN na seção USES, o nome do formulário de clientes, FRMCLI. Como abaixo: unit FrmPrin; (Código do Formulário Principal interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, FrmCli; UNIT/MG Página: 78 1 3 4 Curso de DELPHI Elmo Batista de Faria, Dr. 7- Agora dê um duploclique no botão Clientes no formulário principal, e na sua procedure que se abre, insira o código abaixo: begin Form2.Show; end; DataSource 8- Finalmente vamos inserir os componentes de acesso aos bancos de dados ao formulário 2. Escolha o componente Table e o componente Table DataSource na peleta DataAccess . 9- Podemos neste ponto fazer um teste executando o programa. Ao prossionarmos o botão Cliente no formulário principal deverá aparecer o formulário 2 , se tudo estiver OK agora podemos concluir esta parte do projeto inserindo os códigos necessários e ajustando as propriedades devidas de alguns componentes. É o próximo passo. AGORA VAMOS CRIAR ALGUNS CÓDIGOS ASSOCIADOS AO FORMULÁRIO 1- Quando o usuário clicar no botão de rádio NOME, os registros serão ordenados pelo nome dos clientes, através do índice previamente criado iNome (Definido na criação do banco de dados como índice secundário). 2- Quando o usuário clicar no botão de rádio Código, os registros serão ordenados pelo código dos clientes, através do índice previamente criado iCODIGO.(Também definido anteriormente) O código fonte para este componente fica: procedure TForm2.RadioGroup1Click(Sender: TObject); begin If RadioGroup1.ItemIndex=0 then Table1.IndexName:='icodigo' else Table1.IndexName:=’inome'; end; Obs: Para que a seleção acima do botão RadioGroup tenha efeito certifique que os índices icodigo e inome foram realmente criados, isto é possível abrindo-se o DATABASE DESKTOP e fazendo a seguinte verificação: 1- Escolha no menu principal FILE - OPEN - TABLE e abra a tabela CLIENTES.DB no disquete A:\DATABASE. 1- Após a tabela aparecer no DESKTOP escolha no menu TABLE a opção Secundary Index RESTRUTURE . 2- Escolha no Table Properties do lado direito da caixa de diálogos a opção Secundary Indexes, aparecerá então todos os índices definidos para esta Os índices definidos para tabela verifique se os índices icodigo e esta tabela apareceram aqui inome aparecem neste quadro. 3- Caso algum deles não apareça escolha a opção do botão DEFINE e defina um índice para o campo que está faltando como mostrado na janela ao lado (exemplo para o índice icodigo). UNIT/MG Página: 79 Curso de DELPHI Elmo Batista de Faria, Dr. 1- A tela ao lado aparecerá após pressionarmos o botão DEFINE. 1- E finalize a operação digitando o nome para o índice escolhido, ao pressionar OK este índice aparecerá na tela anterior logo abaixo do define. Selecione o índice desejado Agora estudaremos os componentes de acesso a banco de dados e como se relacionam com a programação Delphi. Fim desta parte da aplicação COMPONENTES DE ACESSO A DADOS Componentes de acesso a dados (Data Access Components) são componentes que acessam tabelas, consultas e campos de um banco de dados. Estão dispostos na página Data Access, da Paleta de componentes mostrado abaixo. Os componentes se relacionam da seguinte forma: Table StoredProc Query DataSource Paleta de componentes Data - Access O componente Table: O componente Table serve para acessar a tabela de um banco de dados. Um objeto Table simplesmente refere-se a uma única tabela de um determinado banco de dados (ou a outras por integridade referencial). Quando você usar o componente Table precisará indicar o nome do banco de dados que quer usar na propriedade DatabaseName no Object Inspector. Podendo informar a esta propriedade o nome do caminho do banco de dados diretamente ou indicando um alias. Nesta condição o Object Inspector listará as tabelas disponíveis neste diretório, podendo em seguida ser selecionada através da propriedade TableName. Um duplo clique sobre o componente Table , abrirá o editor de campos (Field Editor), podendo definir que campos da tabela serão mostrados, e como mostrá-los. Isto porque, por padrão, os componentes de visualização de dados mostrarão todos os campos da tabela. Entre as propriedades mais importantes pode-se destacar: UNIT/MG Página: 80 Curso de DELPHI Elmo Batista de Faria, Dr. 1. DatabaseName: já mencionado serve para especificar o caminho (path) ou alias criado no utilitário de configuração do BDE, onde se encontra as tabelas de um determinado 4 banco de dados Paradox ou Dbase. 1. Observe o alias 2. TableName: Especifica a tabela do banco de dados a ser usado na aplicação acessada. 3. IndexName: especifica o índice a ser utilizado com a tabela, construídos anteriormente na confecção da tabela, são os índices secundários (Secundary Index). Para utilizar 3 o índice primário do Paradox deixe esta propriedade em branco . 4. Active: Se for igual a TRUE, torna a tabela ativa, mostrando os dados nos componentes de visualização ainda no projeto. Se for igual a FALSE , desativa a tabela, mostrando os dados somente durante a execução da 2. A tabela a ser aplicação, caso inclua a opção Table.Open no formulário. acessada e a de Outras duas propriedades são de relevante importância clientes para o componente Table são elas, ReadOnly, usada para prevenir a possível alteração ou não de dados pelo usuário, e a propriedade Exclusive , usada para proibir o acesso concorrente para uma tabela trabalhando em rede ou não por diversas aplicações ao mesmo tempo. Aqui seleciona-se qual DataSouce fará a ligação da query com os componentes de visualização O componente Query: O componente query é um pouco mais complexo que a table , por que a query reque comandos SQL. Porém pode-se conseguir maior acessabilidade e rapidez em consultas usando as query. Basta para isto conhecer alguns comandos básicos SQL. O componente Query tem uma propriedade DatabaseName porém não possui uma propriedade TableName. A tabela é acesada através da declaração de Selecione o alias comandos SQL. Pode-se usar as instruções SQL em tempo de projeto, abrindo o editor String SQL no Object Inspector ou em tempo de execução. Por exemplo você pode escrever uma instrução SQL simples como esta: select * from Clientes Em que clientes é um tabela e o asterístico indica que você Entrada de quer usar todos os campos da tabela. código SQL Entre as propriedades mais importantes do componente temos: 1- DatabaseName: assim como no Table especifica o caminho ou aliases do banco de dados a ser acessado. 2- SQL: especifica o comando SQL de acesso a tabela do banco de dados. 3- Active: se for igual a TRUE, torna a pesquisa ativa. Se for FALSE, desativa a pesquisa. O componente StoredProc: Permite que uma aplicação acesse procedures armazenadas no servidor. Utilizadas em aplicações client\server. UNIT/MG Página: 81 Curso de DELPHI Elmo Batista de Faria, Dr. O componente DataSource: DataSource liga os componentes de acesso a dados aos componentes de visualização de dados. Ou seja é uma ponte entre componentes do tipo Ttable ou Tquery e um ou mais componentes de visualização de dados (Data Controls). Entre as propriedades mais importantes temos: 1- Dataset: nome do componente de acesso a dados (Table ou Query) associado ao DataSource. Componentes de visualização de dados DBComboBox DBEdit DBNavigator DBGrid DBGrid DBText DBImage DBLookupCombo DBRadioGroup DBMemo DBListBox DBLookupList DBCheckBox DBCtrlGrid O componente TDBGrid: componente TDBGrid permite que você visualize os dados de uma tabela ou pequisa em uma grade, mostrando todos os campos ou apenas aqueles estabelecidos no Fields Editor (acessado através de um duplo clique no componente TTable ou Tquery, como visto anteriormente). Entre as propriedades mais importantes temos: 1- DataSource: Define o nome do componente DataSource associado à tabela ou pesquisa a ser visualizada. 2- Options: Comporta o comportamento e a aparência da grade, permitindo ou não, por exemplo, a edição de dados, a visualização dos nomes dos campos, o redimensionamento das colunas, etc. 3- DefaultDrawing: Controla como o Delphi desenha células individuais em uma grade. O componente TDBNavigator: Este componente permite o usuário navegar por entre um conjuto de dados, manipulando-os se necessário. Isto é feito através de um conjunto de botões que permite ao usuário ir para o primeiro ou último registro para próximo registro ou para o registro anterior, inserir um novo registro, editar, gravar ou deletar um registro, cancelar modificações ou refazer a visualização dos dados. Entre as propriedades mais importantes temos: 1- DataSource: Assim como o componente anterior, associando-se a tabela ou pesquisa que você quer navegar. 2- VisibleButtons: define quais botões do componente TDBNavigator estarão visíveis. 3- ShowHints: Se for igual a TRUE, exibe a legenda dos botões, identificando-os para o usuário (são pequenos quadros amarelos com informações sobre os componentes, este procedimento faz parte do padrão de software desenvolvidos sob o padrão Microsoft Windows). O componente TDBText: Este componente mostra os dados de um campo em uma etiqueta (label). UNIT/MG Página: 82 Curso de DELPHI Elmo Batista de Faria, Dr. As propriedades mais importantes são: 1- DataSouce: Como definido anteriormente. 2- DataField: Define o nome do campo da tabela a que o componente está associado. 3- Autosize: Permite que o componente se redimensione, para mostrar dados de diversos tamanhos. O componente TDBEdit: Este componente mostra o valor corrente de um campo em uma caixa de edição, permitindo que o usuário modifique seu valor. As propriedades mais importantes são o DataSource e o DataField definidos anteriormente. Agora voltaremos a aplicação e definiremos os formulários de clientes e posteriores. Exercícios (vamos reiniciar o sistema proposto) Abra novamente a aplicação no menu FILE opção OPEN, escolha o formulário FORM2 na opção do menu principal VIEW - FORMS. O formulário e mostrado ao lado. Agora vamos alterar as propriedades do componentes de acesso ao banco de dados Clientes.db que se encontra no diretório A:\DataBase, sob o alias criado anteriormente de nome AplicaçãoExemploLC. Siga os passos necessários: 1- Clique sobre o componente TABLE e observe as propriedades que este componente deve ter, figura abaixo: Propriedade que colocará a tabela ativa e os dados já estarão disponíveis para serem usados, esta propriedade deve se colocada para TRUE no final da configuração de todos os componentes deste formulário. Neste campo deve-se informar o caminho do banco de dados ou o alias neste caso já temos um alias definido para esta aplicação, isto é possível de se verificar clicando no botão ao lado do campo onde todos os aliase definidos serão mostrados Escolha a opção deste campo como índice de código definido na construção da tabela, serve para iniciar a pesquisa por código do componente RadioGroup1 definido anteriormente Este nome é padrão e será usado desta forma Por último escolha o nome do banco de dados que iremos 2- Agora associe o Componente acessar DataSource a esta tabela, selecionando a propriedade adequada como no exemplo ao lado, Observe que o nome do componente se mantém o nome padrão DataSouce1. Escolha a tabela a ser associada neste caso Table1 UNIT/MG Página: 83 Curso de DELPHI Elmo Batista de Faria, Dr. 3- Determine as propriedades do componente Navigator como abaixo: A propriedade que determina qual elemento fará o elo de ligação do navegador a tabela do banco de dados, neste caso o DataSource1. Mantenha o nome padrão para este componente 4- Agora finalmente definiremos os componentes DBEdit do formulário. Todos terão basicamente as mesmas propriedades definiremos apenas as propriedades necessárias de um deles, o TBEdit para o campo código, observe as figuras a baixo: -As propriedades são: DataField que será Este botão serve para que se faça a seleção Codigo para TBEdit1 do campo diretamente com o mouse Nome para TBEdit2 Endereco para TBEdit3 e Telefone para TBEdit 4 . -O campo DataSource será preenchido com o nome DataSouce1. -E o nome dos Botão de componentes na pesquisa propriedade Name será: EditCODIGO Propriedade que define o nome EditNOME, de cada componente TBEdit EditENDERECO e EditTELEFONE assim como definidos anteriormente. 5- Definiremos os códigos do botão de pesquisa IR PARA, dê um duplo clique no botão e insira os códigos abaixo iremos estuda-los em detalhe. A procedure então fica: procedure TForm2.Button1Click(Sender: TObject); var strcod:string; Declaração de variaveis valcod:integer; strnome:string; Verifica de a propriedade IndexName da tabela begin esta indexada por icodigo quem determina isto é o If Table1.IndexName='icodigo' then componente RadioGroup anteriormente definido. begin strcod:=inputbox('Ir Para','Codigo do cliente',''); Mostra uma caixa de diálogos onde pode-se if strcod <> ''then informar um código para procura no banco valcod:=StrToInt(strcod); de dados. Table1.FindKey([valcod]); Procura na tabela usando o evento FindKey pela end variável entre colchetes. else begin Repete-se o procedimento UNIT/MG Página: para procura por 84 nome Curso de DELPHI Elmo Batista de Faria, Dr. strnome:=inputbox('Ir Para','Nome do cliente',''); if strnome <> '' then Se diferente de vazio Table1.FindKey([strnome]); end; end; Final da procedure 6- finalmente o programa até este ponto fica da seguinte forma: ! os formulários : Formulário principal Formulário de cadastro de clientes ! As UNITs - UNIT Formulário principal (FrmPrin) unit FrmPrin; var Form1: TForm1; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls,FrmCli; type TForm1 = class(TForm) Button1: TButton; Button2: TButton; Button3: TButton; Button4: TButton; procedure Button4Click(Sender: TObject); procedure Button1Click(Sender: TObject); private { Private declarations } public { Public declarations } end; implementation {$R *.DFM} procedure TForm1.Button4Click(Sender: TObject); begin Close; end; procedure TForm1.Button1Click(Sender: TObject); begin Form2.Show; end; end. ! As UNITs - UNIT Formulário Clientes (FrmCli) unit FrmCli; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ExtCtrls, Mask, DBCtrls, DB, DBTables; type UNIT/MG implementation {$R *.DFM} procedure Tform2.RadioGroup1Click(Sender: TObject); begin if RadioGroup1.ItemIndex=0 then Table1.indexName:='icodigo' else Página: 85 Curso de DELPHI Tform2 = class(TForm) Panel1: Tpanel; DBNavigator: TDBNavigator; Panel2: Tpanel; ScrollBox: TScrollBox; Label1: Tlabel; Label2: Tlabel; Label3: Tlabel; Label4: Tlabel; EditCODIGO: TDBEdit; EditNOME: TDBEdit; EditENDERECO: TDBEdit; EditTELEFONE: TDBEdit; Button1: Tbutton; Button2: Tbutton; RadioGroup1: TRadioGroup; Table1: TTable; DataSource1: TDataSource; procedure RadioGroup1Click(Sender: TObject); procedure Button2Click(Sender: TObject); procedure Button1Click(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form2: TForm2; Elmo Batista de Faria, Dr. Table1.IndexName:='inome'; end; procedure TForm2.Button2Click(Sender: TObject); begin close; end; procedure TForm2.Button1Click(Sender: TObject); var strcod:string; valcod:integer; strnome:string; begin If Table1.IndexName='icodigo' then begin strcod:=inputbox('Ir Para','Codigo do cliente',''); if strcod <> ''then valcod:=StrToInt(strcod); Table1.FindKey([valcod]); end else begin strnome:=inputbox('Ir Para','Nome do cliente',''); if strnome <> '' then Table1.FindKey([strnome]); end; end; end. ! E as propriedades dos componentes Table1 do formulário 2 (clientes) Verifique se a tabela esta ativada ser estiver tudo certo os campo do DBEdite já estarão preenchidos com os dados da tabela Se você não definiu um alias entre aqui com o caminho (path) de onde se encontra as tabelas criadas OBS: Antes de mandar executar a aplicação acima não esqueça de habilitar a tabela1 mudando sua propriedade ACTIVE de falso para verdadeiro neste instante se a tabela não for encontrada ou o alias não especificado ou qualquer outro problema na abertura do banco de dados for detectado o BDE não fará o link para a sua tabela especificada não habilitando a opção ACTIVE de sua tabela e sim informando com uma mensagem de erro. No próximo passo iremos definir o restante da aplicação programando os botões de Livro, que é muito semelhante ao botão anterior de clientes do formulário principal, e o botão de vendas onde aprenderemos criar na tabela um campo calculado. Fim desta parte da aplicação A LINGUAGEM SQL Inicialmente abordaremos alguns comandos da linguagem SQL que podem ser usados no Delphi para a manipulação de dados de bancos de dados locais. A linguagem SQL (Structured Query Language - Linguagem Estruturada de Pesquisa) foi criada para ser uma linguagem padrão para consultas, atualização e manipulação de dados em um banco de dados relacional. UNIT/MG Página: 86 Curso de DELPHI Elmo Batista de Faria, Dr. Comercialmente implementada pela IBM, se tornou um padrão de linguagem de acesso a dados em vários bancos de dados relacionais, como Oracle, DB2, SQL, Server, Sybase, etc. Usaremos as declarações em SQL para extrair/atualizar registros de uma ou mais tabelas que atendam as condições especificadas, manipulando, assim, somente os dados que sejam de nosso interesse. Por exemplo, a declaração a seguir permite que somente os registros cujo o campo Nome começando pela letra A da tabela de Clientes sejam exibidos na tela: Select from Clientes Where Nome Like ‘A %’ Podemos dividir os comandos da linguagem SQL em três categorias distintas: Comandos de Definição de Dados: permitem definir ou alterar tabelas em um banco de dados. Comandos para o Controle de Dados: servem para gerenciar o acesso dos usuários a determinadas tabelas. Comandos para a Manipulação de Dados: servem para manipular os dados contidos nas tabelas. COMANDOS DE MANIPULAÇÃO DE DADOS Select Recupera registros de uma ou mais tabelas que satisfaçam a uma determinada condição. Sintaxe: SELECT <lista de campos separados por vírgula> FROM <tabela> OBS: Você pode usar um asterisco (*) no lugar da lista de campos, se quiser selecionar todos os campos de uma tabela. Update Atualiza registros em uma tabela. Sintaxe: UPDATE <Tabela> SET campo = valor. Delete Deleta registros de uma tabela. Sintaxe: DELETE FROM <Tabela> Insert Insere um novo registro em uma tabela. Sintaxe: INSERT INTO Tabela (campo1, campo2...) VALUES (valor1, valor2,...) OPERADORES Nas expressões SQL podemos usar os seguintes operadores: Aritmétricos: +, -, *, / Comparação: =, >, <, <>, IS NULL Lógicos: AND, OR e NOT Outros: Between...And; In e Not In; Like; All; Some; Any. CLÁUSULAS Podemos construir uma declaração SQL usando as seguintes cláusulas: Where : Especifica uma condição para a seleção ou deleção de registros. Group : Separa os registros pelo grupo especificado. Having : Estabelece a condição que cada grupo deve atender. Order by : Especifica a ordenação dos registros selecionados. FUNÇÕES Funções Agregadas Em um comando SQL podemos utilizar as seguintes funções de agregação: Sum (): para totalizar valores de um campo. UNIT/MG Página: 87 Curso de DELPHI Elmo Batista de Faria, Dr. Avg (): para calcular a média de valores de um campo. Min (): para calcular o valor mínimo de um campo. Max (): para calcular o valor máximo de um campo. Count (): para contar o número de valores de um campo. Funções de String Em um comando SQL podemos utilizar as seguintes funções de agregação: Upper (): para colocar uma string em maiúsculas. Lower (): para colocar uma string em minúsculas. Substring (): para retornar uma parte específica da string. Trim (): para remover repetições de um caracter especificado da esquerda, direita ou de ambos os lados de uma string. Exemplos 1. Select * From Clientes Seleciona todos (*) os campos de todos os registros da tabela Clientes. 2. Select Codigo, Nome from Clientes Where Codigo>10 AND Codigo<200 Seleciona os campos Codigo e Nome da tabela Clientes para os registros que tenham o campo Codigo maior que 10 e menor que 200. 3. Select * from Clientes Group By Cidade Todos os campos e registros da tabela Clientes serão agrupados pelo campo Cidade. 4. Select * from Clientes Order By Codigo Seleciona todos os campos e registros da tabela Clientes ordenada pelo campo Codigo 5. Select * from Fornecedores, Produtos Where Fornecedores.Codigo = Produtos.Codigo Seleciona todos os campos e registros das tabelas de Fornecedores e Produtores que tenham o campo codigo de Fornecedores igual ao campo código de Produtos. 6. Select * from Clientes Where Nome Like “S%” Seleciona todos os campos e registros da tabela de Clientes cujo o campo Nome comece pela letra S. 7. Update Funcionarios Set Salario=Salario*1.2 Atualiza o campo Salario de todos os registros da tabela de Funcionarios para o conteúdo atual multiplicado por 1.2 (aumento de 20%). 8. Update Funcionarios Set Salario=Salario*1.2Where Cargo=’Diretor Atualiza o campo Salario dos registros da tabela de Funcionarios que tenham cargo de Diretor, para o conteúdo atual multiplicado por 1.2 (aumento de 20%). 9. Delet from Produtos Where Codigo > 5 AND Codigo < 20 Apaga todos os registros da tabela Produtos para codigo maior que 5 e menor que 20. 10. Insert into Clientes (Codigo, Nome) values (1, ‘Teste’) Insere na tabela Clientes o valor 1 no campo Codigo e o valor Teste no campo Nome. O COMPONENTE TQUERY EM DETALHES O componente Tquery mostrado nesta apostila na página 12, tem a capacidade de criar um conjunto de dados (dataset) usando comandos SQL, ou seja, cria uma pesquisa relacionada a determinada tabela. Ao contrário do componente TTable, Tquery não usa a propriedade TableName para especificar a tabela do banco de dados a ser acessada. Esta tabela é especificada através da propriedade SQL. Da mesma forma que no componente TTable, se você der um duplo clique sobre o componente Tquery, entrará no FieldsEditor (editor de campos), podendo definir que campos mostrar e como mostrá-los. Veja detalhes sobre o FieldsEditor na próxima parte da apostila. PROPRIEDADES UNIT/MG Página: 88 Curso de DELPHI Elmo Batista de Faria, Dr. SQL : Especifica o comando SQL de acesso a tabela do banco de dados. Se você der um duplo clique sobre esta propriedade, entrará no Editor de Lista de Strings (String List Editor): Você deve escrever apenas um comando em cada linha. Por exemplo, ao invés de escrever em uma só linha: Select * from “clientes.dbf”where codigo = 1 escreva: Select * from “clientes.dbf” where codigo = 1 Para especificar o texto da propriedade SQL durante a execução do programa, utilize os métodos Clear e Add: Query1.Close; Query1.SQL.Clear; Query1.SQL.Add(‘Select * from “clientes.dbf’”); Query1.SQL.Add(‘Where codigo = 1’); O uso do método Clear (limpando o conteúdo da propriedade) é importante para evitar que o comando SQL seja adicionado a um já existente. DatabaseName : Especifica o nome do banco de dados associado. Para bancos de dados dBASE e Parodox, você define o caminho (path) para o banco de dados. Para outros bancos de dados, defina o nome do banco de dados a ser acessado ou coloque o alias do banco de dados. O alias para o banco de dados é criado no utilitário de configuração do BDE. Active : Se for igual a True, torna a pesquisa ativa, e os componentes de visualização de dados, como TDBGrid, mostrarão os dados da pesquisa durante o projeto. Se for igual a False, desativa a pesquisa, e os componentes de visualização de dados, como TDBGrid, só mostrarão os dados da pesquisa quando a aplicação for executada. BOF : Se for igual a True, indica se a pesquisa está no primeiro registro. EOF : Se for igual a True, indica se a pesquisa está no último registro. RequestLive : Por default, uma pesquisa sempre retorna um valor read-only (apenas para leitura). Para retornar um resultado com privilégios de leitura e escrita, defina a propriedade RequestLive para True. Params : Esta propriedade contém uma lista de parâmetros para a pesquisa que podem ser acessados durante a execução do programa. Os parâmetros devem estar separados por ponto e vírgula. Você acessa os parâmetros através de seu número de ordem. O primeiro parâmetro tem número de ordem igual a 0. Por exemplo, suponha que você estabeleça o seguinte comando na propriedade SQL: select * from “clientes,dbf”where telefone = :tel onde tel é um parâmetro definido na propriedade Params. Para atribuir o valor da caixa de edição Edit1 ao parâmetro tel, faça: Query1.Params[0].AsStrings:= Edit1.Text; MÉTODOS Open : Executa a pesquisa, se esta incluir o comando Select. ExecSQL : Executa a pesquisa, se esta incluir outros comandos que não Select. Close : Fecha a pesquisa. First : Leva o ponteiro para o primeiro registro. Next : Leva o ponteiro para o próximo registro. Prior : Leva o ponteiro para o registro anterior. UNIT/MG Página: 89 Curso de DELPHI Elmo Batista de Faria, Dr. Last : Leva o ponteiro para o último registro. Moveby : Leva o ponteiro um número determinado de registros adiante (se o parâmetro for positivo), ou para trás (se o parâmetro for negativo). Append : Adiciona um registro em branco no final da pesquisa. Insert : Adiciona um registro em branco após o registro corrente. AppendRecord : Adiciona um registro no final da pesquisa, colocando nos campos os valores passados como parâmetro. Por exemplo, para inserir um registro que possui três campos, com os valores João, R. XV e 234, faça: Table1.AppendRecord([‘João’,’R.XV”,234]); InsertRecord : Adiciona um registro após o registro corrente, colocando nos campos os valores passados como parâmetro. Por exemplo, para inserir um registro que possui três campos, com os valores João, R. XV e 234, faça: Table1.InsertRecord([‘João’,’R.XV’,234]); Delete : Apaga um registro na pesquisa. Edit : Coloca a pesquisa no modo de edição, permitindo modificar dados na pesquisa. Post : Grava as mudanças feitas na pesquisa. Cancel : Descarta as modificações feitas na pesquisa. O COMPONENTE DE VISUALIZAÇÃO TDBGrid O componente TDBGrid permite que você visualize os dados de uma tabela ou pesquisa em uma grade, mostrando todos os campos ou apenas aqueles estabelecidos no FieldsEditor. PROPRIEDADES DataSource : Define o nome do componente TDataSource associado. Fields : É um array contendo os nomes dos campos mostrados pelo componente. SelectedField : Contém o nome do campo selecionado na grade. FieldCount : Contém o número de campos mostrados na grade. ReadOnly : Se for igual a True, o usuário só pode ver os dados na grade, e não editá-los. TitleFont : Determina o estilo da fonte do título da coluna. Options : Controla o comportamento e aparência da grade. DefaultDrawing : Controla como o Delphi desenha células individuais em uma grade. BorderStyle: Determina o estilo da borda da grade. EditorMode : Determina se a grade está automaticamente em modo de edição. FixedColor : Determina a cor das colunas fixas. SelectedIndex : Determina o número de ordem do campo no Dataset. TopRow : Determina qual linha do Dataset aparecerá no topo Exercícios (vamos reiniciar o sistema proposto) Voltaremos ao sistema de livrarias para isto inicialize o Delphi e siga os seguintes passos: 1- Insira o disco com a primeira parte da aplicação no drive A: 2- Escolha no menu File a opção Open, escolha o drive A em seguida abra o projeto sob o nome de livraria. 3- O formulário principal de então aparecer. Com o sistema já recuperado iremos montar o formulário de cadastro de livros que é muito semelhante ao formulário anterior, porém agora usaremos um outro componente de acesso a dados que é a Query. Acompanhe abaixo: 1- escolha no menu File ou clique na barra de botões a opção de New Form , ou seja, um novo formulário. 2- A este formulário atribua o título de CADASTRO DE LIVROS (use a opção caption do formulário para isto), então insira os seguintes componentes: 4-Botão2 peleta Standard UNIT/MG Página: 90 Curso de DELPHI 1-DataSouce peleta DataAcess type TForm3 = class(TForm) 1 - DataSource1: TDataSource; 2 - Query1: TQuery ; 3 - Button1: TButton; 4 - Button2: TButton ; 5 - DBGrid1: TDBGrid ; 6 - DBNavigator1: TDBNavigator; 7 - RadioGroup1: TRadioGroup ; Elmo Batista de Faria, Dr. 2-Query peleta DataAcess 5-DBGrid peleta DataControl 7-RadioGroup peleta Standard 3-Botão1 peleta Standard 6-DBNavigator peleta DataAcess Salve o formulário como anteriormente com o nome de FrmLiv. Podemos então configurar os componentes de acesso a dados. Observe as propriedades mais importantes do componente Query. 1- Na propriedade DatabaseName escolha o alias AplicaçãoExemploLC 2- Observe não há o campo de seleção da tabela isto é feito inserindo-se uma cláusula de comando na propriedade SQL logo abaixo. 3- O nome do objeto permanecerá Query1 como Pode-se ativar a proposto como padrão. query para ver se 4- Clique duas vezes sobre a opção SQL no lado esta funcionando (Tstrings), isto fará com que o editor de comandos perfeitamente SQL seja acionado e a tela abaixo surgira, insira a seguinte linha de comando: select * from livros Alias Comando SQL de seleção de tabelas Aciona o editor de comandos SQL Esta linha de comando informa a query que este componente deverá selecionar todos os campos (*) da tabela livros. Isto é preciso para que ao executar o programa este se inicialize com a tabela já acessível nos componentes de visualização. 5- O próximo passo é configurar as propriedades do componente DataSource que deve ter uma única propriedade alterada que é a Dataset, selecionando o objeto query1. O nome permanece DataSouce1, como na figura ao lado: 6- Agora direcione os dados do componente DataSouce para o componente DBGrid, bastando para isto selecionar o componente DBGrid e escolher na propriedade DataSouce o DataSouce1, a propriedade Name continuará DBGrid1. UNIT/MG Query1 selecionada Página: 91 Curso de DELPHI Elmo Batista de Faria, Dr. 7- Repita o mesmo procedimento procedimento para a propriedade DataSouce do componente Navigator. 8- Agora configuraremos o componente RadioGroup. Observe as propriedades a serem alteradas: ! Após ter inserido o componente RadioGroup na posição indicada, este deve aparecer sem nenhum botão de seleção. Neste instante atue na propriedade de Itens e insira no editor os dois botões necessários de Código e Nome observe: Faça o ItenIndex para 0 e o botão de radio Codigo aparecerá marcado Itens que são os botões de radio de código e nome Insere Itens no RadioGroup Componente RadioGroup inserido no formulário cadastro de clientes os botões de rádio Codigo e Nome aparecerão no radiogroup assim que forem inseridos no editor de itens e o primeiro ficará marcado quando o ItenIndex for selecionado para 0 9- Agora mude a propriedade caption do RadioGroup para Ordenado Por. Começaremos inserindo as linhas de código de programa pelo componente RadioGroup, para isto dê um duplo clique sobre o componente RadioGroup e abra a procedure abaixo: procedure TForm3.RadioGroup1Click(Sender: TObject); begin Esta linha verifica se o botão de radio selecionado foi o primeiro ou seja Código se for verdade executa os códigos dentro de begin if RadioGroup1.itemindex=0 then begin Desativa a Query Propriedade query1.active:=false; SQL da query query1.sql.clear ; Limpa todos os comandos do editor de códigos da propriedade SQL query1.sql.add('select * from livros order by codigo'); Adiciona esta linha de código na query1.active:=true; propriedade SQL, esta linha abre todos os Torna a query ativa e executando registros da tabela livros indexando-a por end assim os códigos da propriedade código SQL ou seja o comando select acima else begin Caso o ItemIndex não seja 0, ou seja, a opção de código não for pressionada então o query1.active:=false; botão de radio pressionado neste caso é o de Nome e portanto ItenIndex vale 1 ≠ 0 query1.sql.clear; Repetindo o mesmo procedimento query1.sql.add('select * from livros order by nome') ; UNIT/MG anterior, neste caso, adiciona-se esta linha de código na Página: propriedade 92 SQL, esta linha abre todos os registros da tabela livros indexando-a por Nome Curso de DELPHI Elmo Batista de Faria, Dr. query1.active:=true; end ; Ativa-se a query e consequentemente end; executa-se o comando da linha anterior Examinaremos agora o programa da procedure referente ao botão de localização de registro o botão Ir Para . procedure TForm3.Button1Click(Sender: TObject); var Inicializa-se uma variavél do tipo string strcod:string; Inicio da procedure begin if RadioGroup1.itemindex=0 then Verifica se a tabela esta indexada por código begin Cria se uma caixa de entrada strcod:=inputbox('Ir Para','Codigo do livro',''); de dados com a mensagem if strcod <> '' then Se alguma coisa foi digitado então executa Código do Livro begin Desativa a query query1.active:=false; Limpa linhas de códigos SQL anteriores no editor query1.sql.clear; query1.sql.add('select * from livros '); Adiciona alinha de comando SQL que seleciona todos os campos da tabela livros query1.sql.add('where codigo="'+strcod+'"'); query1.active:=true; Esta nova linha de comando será adicionada ao editor abaixo da anterior. O comando Where end; Ativa-se novamente a Query procura por um campo de código igual ao código end Caso a indexação não seja por código digitado na entrada de dados acima. else será então po Nome como abaixo begin Cria se uma caixa de entrada strcod:=inputbox('Ir Para','Nome do livro',''); de dados com a mensagem if strcod <> '' then Nome do Livro begin query1.active:=false; query1.sql.clear; query1.sql.add('select * from livros '); Esta nova linha de comando será adicionada ao query1.sql.add('where nome="'+strcod+'"') ; editor abaixo da anterior. O comando Where query1.active:=true; procura por um campo de Nome igual ao Nome end; digitado na entrada de dados acima. Estas Linhas finalizam a end; condição if, o else e a procedure end; 10- Insira o método close ao botão Sair. 11- Clique duas vezes sobre o formulário e insira na procedure do formulário a seguinte linha de código, que inicializa a query e a torna ativa mostrando assim os registros da tabela nos componentes de visualização quando acionado o botão de Livros do formulário principal. procedure TForm3.FormCreate(Sender: TObject); begin query1.open; end; 12- Para finalizar Salve então toda a aplicação e insira no inicio do formulário principal na USE o nome da unit nova frmlvi e clique duas vezes sobre o botão Livros fazendo a chamada ao formulário 3 desta aplicação: procedure TForm1.Button2Click(Sender: TObject); begin form3.show; end; A unit Frmliv após a inserção dos códigos deverá finalmente ficar desta forma: UNIT/MG Página: 93 Curso de DELPHI unit Frmliv; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ExtCtrls, DBCtrls, Grids, DBGrids, DB, DBTables; type TForm3 = class(Tform) DataSource1: TdataSource; Query1: Tquery; DBGrid1: TDBGrid; DBNavigator1: TDBNavigator; RadioGroup1: TradioGroup; Button1: Tbutton; Button2: Tbutton; procedure RadioGroup1Click(Sender: TObject); procedure Button1Click(Sender: TObject); procedure Button2Click(Sender: TObject); procedure FormCreate(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form3: Tform3; implementation {$R *.DFM} procedure Tform3.RadioGroup1Click(Sender: TObject); begin if RadioGroup1.itemindex=0 then begin query1.active:=false; query1.sql.clear ; query1.sql.add('select * from livros order by codigo'); query1.active:=true; end else begin query1.active:=false; query1.sql.clear; Elmo Batista de Faria, Dr. query1.sql.add('select * from livros order by nome') ; query1.active:=true; end ; end; procedure TForm3.Button1Click(Sender: TObject); var strcod:string; begin if RadioGroup1.itemindex=0 then begin strcod:=inputbox('Ir Para','Codigo do livro',''); if strcod <> '' then begin query1.active:=false; query1.sql.clear; query1.sql.add('select * from livros '); query1.sql.add('where codigo="'+strcod+'"'); query1.active:=true; end; end else begin strcod:=inputbox('Ir Para','Nome do livro',''); if strcod <> '' then begin query1.active:=false; query1.sql.clear; query1.sql.add('select * from livros '); query1.sql.add('where nome="'+strcod+'"') ; query1.active:=true; end; end; end; procedure Tform3.Button2Click(Sender: TObject); begin close; end; procedure Tform3.FormCreate(Sender: TObject); begin query1.open; end; end. Fim desta parte da aplicação OPERAÇÕES COM REGISTROS E CAMPOS OPERAÇÕES COM CAMPOS O Editor de Campos Você manipula componentes TFields durante o projeto através do Fields Editor (Editor de Campos). Este editor permite que você defina quais campos de determinada tabela você quer mostrar no formulário. Para acessar o Fields Editor: Edtor Fields UNIT/MG Página: 94 Curso de DELPHI Elmo Batista de Faria, Dr. • dê um duplo clique sobre o componente TTable inserido no formulário. Aparece o Fields Edditor: • Use Add para abrir uma caixa de diálogo listando os campos da tabela associada a TTable, para isto posicione o mouse sobre o navigator desta janela e clique o mouse do lado direito (Speed Menu) e a opção Add aparecerá. • selecione os campos que você quer mostrar no formulário, dando um clique sobre eles, e clique OK; • caso queira, mude a ordem de disposição dos campos, bastando para isto arrastar o campo para a posição desejada; • clique em Close, no menu de controle, para fechar o Fields Editor. Navigator Opção adicione campo para o editor, acessada clicando o botão direito do mouse Mudando Propriedades de Componentes TFields Para modificar determinada propriedade de um componente TField, relacionado a um campo da tabela: • entre no Fields Editor; • clique sobre o campo para o qual você quer mudar a propriedade; • acesse o Object Inspector, e mude o valor da propriedade desejada. Obs.: A propriedade Name do componente TField é estabelecida automaticamente pelo Delphi, através da associação do nome do componente TTable com o nome do campo na tabela. Lendo Valores de Campos Você lê valores de um campo através da propriedade Value do componente TField. Por exemplo, para ler o valor de um campo NomedoCliente (representado pelo componente TField chamado Table1NomedoCliente), do tipo texto, na caixa de edição Edit1, faríamos: Edit1.Text:= Table1NomedoCliente.Value; onde Table1 é o nome do componente TTable associado a Componente field tabela de onde veio o NomedoCliente. Cada campo escolhido no Fields Editor representa um componente TField criado pelo Delphi. Cada tipo de um campo cria um componente TField diferente. Por exemplo, se o campo for do tipo texto, o componente TField criado é do tipo TStringField. Para associar outros tipos de campos que não texto a uma caixa de edição (que só aceita valores do tipo string), devemos utilizar as propriedades de conversão do componente TField: AsBoolean, AsDateTime, AsFloat, AsInteger, AsString. Por exemplo, para ler o valor de um campo CodigodoCliente (representado pelo componente TField chamado Table1CodigodoCliente), do tipo numérico, na caixa de edição Edit1, faríamos: Edit1.Text:= Table1CodigodoCliente.AsString; Estabelecendo Valores de Campos Quando você modifica valores de componentes TField baseado em dados entrados em caixas de edição (ou outro componente de entrada de dados), você precisa mudar o estado do dataset para permitir a edição. Isto é feito através dos métodos Edit e Post. UNIT/MG Página: 95 Curso de DELPHI Elmo Batista de Faria, Dr. Por exemplo, para atribuir ao campo NomedoCliente (representado pelo componente TField chamado Table1NomedoCliente) o valor digitado na caixa de edição Edit1, Faríamos: Table1.Edit; Table1NomedoCliente.Value:= Edit1.Text; Table1.Post; Inicialmente, chamaríamos o método Edit para permitir a edição dos dados associados ao componente Table1. Depois, faríamos a atribuição. Finalmente, chamaríamos o método Post para gravar no campo o dado inserido em Edit1. O componente TField e o valor que você lhe atribuie precisam ser compatíveis. Para isto, devemos utilizar as propriedades de conversão do componente TField: AsBoolean, AsDateTime, AsFloat, AsInteger, AsString. Por exemplo, para atribuir ao campo CodigodoCliente (representado pelo componente TField chamado Table1CodigodoCliente), do tipo numérico, o valor digitado na caixa de edição Edit1, faríamos: Table1.Edit; Table1CodigodoCliente.AsString:= Edit1.Text; Table1.Post; Definindo um Campo Calculado Um campo calculado é aquele que é resultado da interação entre dois ou mais campos de uma tabela. Para criar um campo calculado: • Entre no Fields Editor, dando um duplo clique sobre o componente Table ou Query: • Clique no botão direito do mouse e escolha New Field Aparece o quadro abaixo: Janela New Field que cria um campo calculado na tabela . Neste exemplo o campo result será adicionado a tabela Table1 • o quadro Field Properties, entre com o nome do campo calculado. Ex: Result; • no quadro Component Name, o Delphi automaticamente coloca o nome do componente TField criado, ao associar o nome do componente TTable com o nome do campo calculado, estabelecido acima; • no quadro Type, escolha o tipo do campo calculado (datetime, float, currency, etc); • no quadro Size, entre com o tamanho do campo; • marque a caixa Calculated para informar que é um campo calculado que está sendo criado; • clique OK quando terminar. No formulário é acrescentado, à grade que mostra os dados, uma coluna contendo o campo calculado. Para criar um código associado ao campo calculado: • selecione o componente TTable associado; UNIT/MG Página: 96 Curso de DELPHI Elmo Batista de Faria, Dr. • no Object Inspector, vá para a página Events dê um duplo clique sobre o evento OnCalcFields, entrando no Editor de Código; • escreva as linhas de código necessárias, dentro da procedure relacionada ao evento acima. Obs.: No evento OnCalcFields, você só pode atribuir valores a campos calculados. Formatando Campos Você pode formatar o valor de um campo durante o projeto através das seguintes propriedades, presente no Object Inspector: DisplayFormat: especifica o formato do dado no componente que o visualiza. DisplayWidth: especifica o número de caracteres que a coluna da grade mostrará. EditMask: especifica a forma como o valor deve ser entrado, oferecendo uma “máscara” para o valor. Alignment: especifica o alinhamento do valor do campo, dentro do componente de visualização. Durante a programação você poderá utilizar o evento OnGetText para formatar valores de campos. Este evento ocorre sempre que o Delphi vai mostrar o conteúdo do campo, e ignora as definições impostas pelas propriedades DisplayFormat e EditMask. Procurando Dados Para procurar por um determinado valor de um campo de uma tabela, use o método FindKey. O campo precisa estar indexado, para utilizarmos este método. Por exemplo, para encontrarmos o nome Joelma armazenado no campo NomedoCliente, que indexa a tabela, faríamos: Table1.FindKey([‘Joelma’]) Se o índice for composto de mais de um campo, você poderá utilizar o método FindKey da seguinte forma: Table1.FindKey([‘valor1’, ‘valor2’, ‘valor3’]) A Propriedade Fields Você pode acessar o valor de um campo com a propriedade Fields de um componente de acesso a dados. Para isto, use como parâmetro o número de ordem do campo na tabela, começando por 0. Por exemplo, para atribuir a caixa de edição Edit1 o valor do campo Nome, que é o seguinte campo da tabela Clientes.db associada ao componente Table1, faça: Edit1.Text:= Table1.Fields[1]; Se o campo não for do tipo string, utilize a função de conversão AsString: Edit1.Text:= Table1.Fields[1].AsString; O Método FieldByName Outra forma de se acessar o valor de um campo é através do método FieldByName de um componente de acesso a dados. Você deve passar como parâmetro para este método o nome do campo a ser acessado. Por exemplo, para atribuir a caixa de edição Edit1 o valor do campo Nome, da tabela Cliente.db, associada ao componente Table1, faça: Edit1.Text:= Table1.FieldsByName(‘Nome’); Se o campo não for do tipo string, utilize a função de conversão AsString: Edit1.Text:= Table1.FieldsByName(‘Nome’).AsString; Filtrando Registros Você pode filtrar registros de uma tabela através de métodos específicos: SetRangeStart: estabelece o limite inicial do filtro. UNIT/MG Página: 97 Curso de DELPHI Elmo Batista de Faria, Dr. SetRangeEnd: estabelece o limite final do filtro. SetRange([ValorInicial], [ValorFinal]): estabelece o limite inicial e final do filtro. ApplyRange: aplica o filtro à tabela. CancelRange: cancela o filtro aplicado à tabela. Obs.: Em tabelas do tipo Paradox ou dBASE, estes métodos só funcionam para campos indexados. Por exemplo, se quiser filtrar todos os registros da tabela associada ao componente Table1, cujo campo Codigo for maior que 100 e menor que 200, faça; Table1.SetRangeStart; Table1.FieldByName(’Codigo’) := 100; Table1.SetRangeEnd; Table1.FieldByName(‘Codigo’) := 200; Table1.ApplyRange; Se você quiser atualizar o filtro, ao invés de eliminá-lo, utilize os métodos EditRangeStart e EditRangeEnd. Estes métodos mantém os valores do filtro anterior, atualizando-o com as atribuições feitas posteriormente. Se seu índece é composto, faça as atribuições para os campos separadamente. Por exemplo, se sua tabela está indexada pelos campos Codigo e Nome, e você quer filtrar os dados dos clientes com codigo igual ou maior que 1, e nome igual a “Joelma’, faça o seguinte: Table1.SetRangeStart; Table1.FieldByName(’Codigo’) := 1; Table1.FieldByName(‘Nome’) := ‘Joelma’; Table1.SetRangeEnd; Table1.ApplyRange; Navegando pelo Dataset Para navegar pelo conjunto de dados (dataset), utilize os seguintes métodos: First: move o ponteiro para o primeiro registro. Last: move o ponteiro para o último registro. Next: move o ponteiro para o próximo registro. Prior: move o ponteiro para o registro anterior. Por exemplo, para mover o ponteiro para o primeiro registro da tabela associado ao componente Table1, faça: Table1.First; As Propriedades BOF e EOF Para verificar se o ponteiro se encontra no primeiro ou último registro, utilize as propriedades abaixo: BOF: se for igual a True, indica que o ponteiro se encontra no primeiro registro do dataset. EOF: se for igual a True, indica que o ponteiro se encontra no último registro do dataset. O exemplo abaixo irá realizar a rotina FaçaAlgo enquanto não for atingido o início do arquivo: while not Table1.BOF do begin FaçaAlgo; Table1.Prior; end; Método Moveby Este método permite a aplicação se mover para frete ou para trás no dataset (Tabela do banco de dados) um número específico de registros. Valores positivos indicam movimento para frente. Valores negativos indicam movimentos para trás. UNIT/MG Página: 98 Curso de DELPHI Elmo Batista de Faria, Dr. Por exemplo, para mover o ponteiro dois registros para frete, faça; Table1.MoveBy(2); Modificando Registros Para modificar registros, você deverá utilizar um dos seguintes métodos: Edit, Append, Insert, Post, Cancel e Delete. Editando Registros Um dataset precisa estar no modo de edição para possibilitar a atualização de dados. Para isso, você deve utilizar o método Edit. Ao final da edição, utilize o método Post para gravar os novos dados no registro. Por exemplo; Table1.Edit; Table1.NomedoCliente.Value:= Edit1.Text; Table1.Post; Adicionando Registros Para adicionar um novo registro, utilize o método Insert ou método Append. O método Insert irá inserir um registro em branco após o registro corrente. O método Append irá inserir um registro em branco após o último registro. Caso haja um índice para os registros, quando a aplicação chamar o método Post, o registro será inserido na posição estabelecida pelo índice. Deletando Registros Para deletar um registro, utilize o método Delete. Cancelando Alterações Para cancelar alterações feitas pelo usuário, antes da chamada ao método Post, utilize o método Cancel. O registro retornará aos valores originais. COMPONENTE TFIELD Apesar de não ser visível no formulário, o componente TField é importante porque prevê uma ligação direta com os campos de uma tabela. Por padrão, um conjunto de componentes TField é criado automaticamente cada vez que um componente como TTable ou TQuery é ativado. Durante o projeto, você pode usar o Fields Editor para criar um conjunto de componentes TField, ao escolher que campos da tabela serão mostrados, e em que ordem. Utilizar o Fields Editor é mais seguro porque, mesmo que você mude a ordem dos campos na estrutura de seu banco de dados, a aplicação manterá a ordem estabelecida no Fields Editor. Há componentes TField correspondentes a todos os tipos de dados. Entre eles: TSTringField, TSmallIntField, TIntegerField, TWordField, TBooleanField, TFloatField, TCurrencyField, TBCDField, TDateField, TTimeField, TDateTimeField. O formato padrão para os campos TCurrencyField e TDateTimeField são dados pela definição feita na seção International do Painel de Controle do Windows. PROPRIEDADES Propriedades de Conversão O componente TField possui diversas propriedades de conversão. Podem ser utilizadas de duas formas: UNIT/MG Página: 99 Curso de DELPHI Elmo Batista de Faria, Dr. • para transformar o valor de um campo não texto em string, podendo ser associado a qualquer componente de visualização de dados (a propriedade Text ou Caption sá aceita valores do tipo string). Por exemplo, para ler o valor de um campo CodigodoCliente, do tipo numérico, na caixa de edição Edit1, faríamos: Edit1.Text:= Table1CodigodoCliente.AsString; • para transformar um valor string obtido de um componente de visualização de dados no tipo de dado do campo. Por exemplo, para atribuir o texto da caixa de edição Edit1 ao campo CodigodoCliente, do tipo numérico, faríamos: Table1CodigodoCliente.AsString:- Edit1.Text; Entre as propriedades de conversão temos: AsString: converte para texto. AsDateTime: converte para data/hora. AsFloat: converte para float. AsInteger: converte para integer. AsBoolean: converte para boolean. EditMask: Coloca uma máscara na entrada de dados, delimitando o formato do dado a entrar. Você pode entrar este formato manualmente ou usar o Editor de Máscara (Input Mask Editor). Para acessar este editor, dê um duplo clique sobre a propriedade EditMask, e selecione a máscara desejada. CanModify: Se for igual a True, o valor do campo pode ser modificado. DataType: Identifica o tipo de dado do componente TField. DisplayLabel: Contém o cabeçalho da coluna que mostra o campo em um TDBGrid. DisplayText: Formata o campo para efeitos de visualização. Text: Formata o campo para efeitos de edição. DisplayWidth: Controla a largura da coluna que mostra o campo em um TDBGrid. FieldName: Contém o nome do campo na tabela. IsNull: Verifica se há algum valor atribuído ao campo. ReadOnly: Se for igual True, o usuário não poderá modificar o valor do campo. Visible: Se for igual a False, o campo não aparecerá na grade de dados. MÉTODOS Clear: Apaga o valor atribuído ao campo. GetData: Acessa o dado em formato nativo. FocusControl: Leva o foco para o componente TField. Exercícios ( Montaremos agora o formulário cadastro de livros) 1- Inicialize o Delphi e recupere a aplicação em desenvolvimento (Livraria.prj) selecionando Open Project no botão do menu principal. Veja página 22 ítens 1 e 2. 2- Observe o formulário principal abaixo: Trabalharemos sob o botão de vendas. UNIT/MG Página: 100 Curso de DELPHI Elmo Batista de Faria, Dr. 3- Inicialmente crie um novo formulário, o formulário Cadastro de Vendas. Para isto basta clicar sob o botão NEW FORM da barra de menu principal do DLPHI 4- Após o aparecimento do formulário em branco inclua os seguintes objeto no formulário ele deverá ficar com a seguinte aparência. Table1 e DataSource1 Table2 e DataSource2 Table2 e DataSource2 Navigator Label1: Label2: Label3: Label4: Label5: 1 Button1 2 3 Button2 4 5 Button3 DBRadio Group1 Button4 6 Button5 Button7 Panel1: TPanel; Panel2: TPanel; ScrollBox: TScrollBox; 1-EditDATAVENDA: TDBEdit; 2-DBLookupCombo1: TDBLookupCombo; 3-DBLookupCombo2: TDBLookupCombo; 4-EditPRECO: TDBEdit; 5-EditQUANTIDADE: TDBEdit; 6-EditDATAPG: TDBEdit; Button6 Os demais Label estão GroupBox1: indicados no desenho. Antes de Iniciarmos os códigos que definirão o formulário, abra o DataBase ComboBox2 Edit1 ComboBox1 Desktop e verifique se a estrutura da tabela vendas.db tem a forma abaixo, observando o índice secundário definido para o campo data pelo nome idtvenda. Se este índice não foi definido anteriormente defina-o agora. Índice secundário definido para a tabela Vendas.db Agora iniciaremos montando todos os códigos para cada componente do formulário e adequando suas respectivas propriedades: 1- Primeiramente de um duplo clique sobre o próprio formulário e insira os códigos de abertura da tabela1 ( tabela de vendas). Quando o formulário for aberto ao ser pressionado o botão VENDAS na tela principal do programa abrirá também a tabela1 para utilização. Insira também duas UNIT/MG Página: 101 Curso de DELPHI Elmo Batista de Faria, Dr. variáveis que serão usadas ao longo do programa, o formulário de vendas sob o nome de Frmven neste estágio ficará da seguinte forma: unit Frmven; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, DBTables, DB, ExtCtrls, DBCtrls, DBLookup, StdCtrls, Mask; type Todos os objetos usados no formulário TForm4 = class(TForm) apareceram aqui. { declarações dos objetos } var Variáveis a Form4: TForm4; serem inseridas varopera:string; varvalor:string; Procedure implementation criação {$R *.DFM} formulário procedure TForm4.FormCreate(Sender: TObject); begin Table1.open; end; end. de do 2- Insira na linha USES do formulário principal o nome Frmven, que fará a chamada ao formulário de vendas. E dê um duplo clique no botão de vendas do formulário principal para inserir na procedure o código de chamada do formulário Cadastro de Vendas. procedure TForm1.Button3Click(Sender: TObject); begin form4.show; end; 3- Agora pode-se executar o programa e verificar se ao pressionar o botão de VENDAS do formulário principal abrirá o formulário cadastro de vendas. Certifique que tenha gravado todas as alterações. 4- Voltaremos agora ao formulário Cadastro de Vendas. Reiniciaremos inserindo os códigos do botão1 (Ir Para) observe a procedure abaixo: UNIT/MG Página: 102 Curso de DELPHI Elmo Batista de Faria, Dr. 1- Inicialize o Delphi e recupere a aplicação em desenvolvimento (Livraria.prj) selecionando Open Project no botão do menu principal. Veja página 22 ítens 1 e 2. 1- Abra o formulário 3 no botão de seleção de formulários. Então o formulário ao lado aparecerá. Observe que o DBGrid foi ampliado para que possamos visualizar todos os campos da tabela. 2- Agora repetindo os passos anteriores de criação de um campo calculado para este formulário, descrito nos tópicos anteriores, selecione o componente Query deste formulário. 3- Clique o botão do lado direito do mouse (menu rápido ), e selecione Fields Editor. 4- O editor de campos então aparecerá. Neste instante clique novamente o mouse do lado direito dobre o navigator da janela do editor de campos e selecione New Field. 5- A tela de edição de um campo novo se abrirá preencha os campos da seguinte forma: UNIT/MG Página: 103 Curso de DELPHI Elmo Batista de Faria, Dr. FUNDAMENTOS DE OBJECT PASCAL CONCEITOS DE PROGRAMAÇÃO ORIENTADA A OBJETOS Antes de partir para a linguagem propriamente dita, vamos revisar alguns conceitos básicos de Programação Orientada a Objetos. Classe: Definição de tipo dos objetos, modelo de objeto. Objeto: Instância de classe, variável cujo tipo é uma classe. Atributos: Variáveis de instância, são os dados de um objeto. Métodos: Funções e procedimentos de um objeto. Propriedades: Apelido usado para evitar o acesso direto aos atributos de um objeto, onde podemos especificar métodos que serão usados para ler e atribuir seus valores a esses atributos. Mensagens: Chamada de métodos, leitura e atribuição de propriedades. Encapsulamento: Conjunto de técnicas usadas para limitar o acesso aos atributos e métodos internos de um objeto. Herança: Possibilidade de criar uma classe descendente de outra, aproveitando seus métodos, atributos e propriedades. Ancestral: Super classe ou classe de base, a partir da qual outras classes podem ser criadas. Descendente: Subclasse. Hierarquia de Classes: Conjunto de classes ancestrais e descendentes, geralmente representadas em uma árvore hierárquica. UNIT/MG Página: 104 Curso de DELPHI Elmo Batista de Faria, Dr. Polimorfismo: Capacidade de redefinir métodos e propriedades de uma classe em seus descendentes. ESTRUTURA DE UNITS Vamos examinar o código gerado para um novo Form, identificando as principais seções de uma Unit típica. Crie uma nova aplicação e observe na Unit principal as seguintes cláusulas. Unit: A primeira declaração de uma unit é seu identificador, que é igual ao nome do arquivo. Interface: Seção interface, onde ficam declarações que podem ser usadas por outras Units. Uses: Na cláusula uses fica a Lista de Units usadas. Type: Na cláusula type fica a definição de tipos, aqui temos a declaração da classe do Form. Var: Na cláusula var são declaradas as variáveis, aqui temos a declaração da instância do Form. Implementation: Na seção implementation ficam as definições dos métodos. End: Toda Unit termina com um end a partir de onde qualquer texto é ignorado. VARIÁVEIS No Delphi, toda variável tem que ser declarada antes de ser utilizada. As declarações podem ser feitas após a palavra reservada var, onde são indicados o nome e o tipo da variável. Os nomes de variáveis não podem ter acentos, espaços ou caracteres especiais como &, $ ou % e o primeiro caractere de um nome de variável tem que ser uma letra ou um sublinhado. O Delphi ignora o caso das letras. Variáveis Globais As variáveis abaixo são globais, declaradas da Interface da Unit. Podem ser acessadas por qualquer Unit usuária. var I: Integer; Usuario: string; A, B, Soma: Double; Ok: Boolean; Variáveis Locais As variáveis abaixo são locais ao método, ou seja elas só existem dentro do método, não podem ser acessadas de fora, mesmo que seja na mesma Unit. Na verdade essas variáveis são criadas quando o método é chamado e destruídas quando ele é encerrado, seu valor não é persistente. procedure TFrmExemplo.BtnTrocarClick(Sender: TObject); var Aux: string; begin Aux := EdtA.Text; EdtA.Text := EdtB.Text; EdtB.Text := Aux; end; UNIT/MG Página: 105 Curso de DELPHI Elmo Batista de Faria, Dr. ATRIBUTOS Os atributos são variáveis de instância. Para declarar um atributo em uma classe basta definir o identificador e o tipo do atributo na declaração da classe, feita na seção type da Interface da Unit, como abaixo. type TFrmSomar = class(TForm) private { Private declarations } A, B: Double; public { Public declarations } Soma: Double; end; ENCAPSULAMENTO Os principais níveis de visibilidade dos atributos e métodos de uma classe são mostrados abaixo. Nível Visibilidade Private Os itens declarados nesse nível só podem ser acessados na mesma unit. Public Nesse nível, qualquer unit usuária poderá acessar o item. Protected Os itens só poderão ser acessados em outra unit se for em uma classe descendente Published É o nível default, igual ao Public, mas define propriedades e eventos usados em tempo de projeto CLASSES Classes são tipos de objetos, uma classe é declarada na cláusula type da seção interface e os métodos são definidos na seção implementation. Examine o código de um Form para identificar os elementos de sua classe. interface type TFrmSomar = class(TForm) EdtA: TEdit; EdtB: TEdit; BtnSoma: TButton; procedure BtnSomaClick(Sender: TObject); private { Private declarations } public { Public declarations } end; implementation procedure TFrmSoma.BtnSomaClick(Sender: TObject); begin ShowMessage(EdtA.Text + EditB.Text); end; UNIT/MG Página: 106 Curso de DELPHI Elmo Batista de Faria, Dr. OBJETOS Um Objeto é tratado como uma variável cujo tipo é uma classe. A declaração de objetos é igual à declaração de uma variável simples, tendo no lugar do tipo a classe do objeto. var FrmSomar: TFrmSomar; LITERAIS Valores literais são valores usados em atribuições e expressões. Cada tipo tem uma sintaxe diferente. Tipo Definição Inteiro Seqüência de dígitos decimais (0 a 9), sinalizados ou não Inteiro Seqüência de dígitos hexadecimais (0 a F), precedidos por um sifrão ($) Hexadecimal Real Igual ao tipo Inteiro, mas pode usar separador decimal e notação científica Caractere Letra entre apóstrofos ou o caracter # seguido de um número inteiro entre 0 e 255 (ASCII) String Seqüência de caracteres delimitado por apóstrofos CONSTANTES São declaradas na seção const, podem ser usadas como variáveis, mas não podem ser alteradas. Geralmente o nome das constantes é escrito em letras maiúsculas e na declaração dessas constantes não é indicado o tipo. const G = 3.94851265E-19; NUM_CHARS = '0123456789'; CR = #13; SPACE = ' '; MAX_VALUE = $FFFFFFFF; Constantes Tipadas Na verdade, constantes tipadas são variáveis inicializadas com valor persistente, que podem ser alteradas normalmente, como qualquer variável. A única diferença de sintaxe entre constantes tipadas e simples é que o tipo da constante é indicado explicitamente na declaração. Se uma constante tipada for declarada localmente, ela não será destruída quando o método for encerrado. Para diferenciar das constantes normais, costuma-se declarar estas com letras de caso variável, como abaixo. const Cont: Integer = 1; Peso: Double = 50.5; Empresa: string = 'SENAC'; INSTRUÇÕES Os programas são compostos por instruções, que são linhas de código executável. Exemplos de instruções simples são atribuições, mensagens entre objetos, chamadas de procedimentos, funções e métodos, como mostradas abaixo. As instruções podem ser divididas em várias linhas, o que indica o fim de uma instrução é o ponto e vírgula no final. Quando uma instrução é quebrada, costuma-se dar dois espaços antes das próximas linhas, para melhorar a leitura do código. Caption := 'Gabba Gabba Hey!'; Form2.ShowModal; UNIT/MG Página: 107 Curso de DELPHI Elmo Batista de Faria, Dr. Application.MessageBox('Você executou uma operação ilegal, o programa será finalizado.', 'Falha geral', MB_ICONERROR); Você pode usar várias instruções agrupadas em uma instrução composta, como se fosse uma só instrução. Uma instrução composta delimitada pelas palavras reservadas begin e end. Toda instrução, simples ou composta, é terminada com um ponto-e-vírgula. if CheckBox1.Checked then begin ShowMessage('O CheckBox será desmarcado.'); CheckBox1.Checked := False; end; Estilo de Codificação As instruções e todo o código de uma Unit devem ser distribuídos para facilitar o máximo a leitura. Para isso, podemos usar a indentação, geralmente de dois espaços para indicar os níveis de código. Procure criar um estilo próprio, que melhor se molde à sua realidade. Se for desenvolver em grupo, é melhor que todos usem o mesmo estilo para evitar confusões. COMENTÁRIOS Existem 3 estilos de comentário no Delphi, como mostrado abaixo. (* Comentário do Pascal Padrão *) { Comentário do Turbo Pascal } // Comentário de linha do C++ Cuidado com as diretivas de compilação, pois elas são delimitadas por chaves e podem ser confundidas com comentários. A diretiva de compilação mostrada abaixo é incluída em todas as Units de Forms. {$R*.DFM} TIPOS DE DADOS PADRÃO O Delphi trata vários tipos de dados padrão, segue uma descrição sucinta desses tipos. Tipos Inteiros São tipos numéricos exatos, sem casas decimais. O tipo Integer é o tipo inteiro padrão. Tipo Tamanho em Valor Mínimo Valor Máximo Bytes ShortInt 1 -128 127 SmallInt 2 -32768 32767 Longint 4 -2147483648 2147483647 Byte 1 0 255 Word 2 0 65535 Integer 4 -2147483648 2147483647 Cardinal 4 0 2147483647 Tipos Reais São tipos numéricos com casas decimais. O tipo Double é o tipo real padrão. Tipo Tamanho em Valor Mínimo Valor Máximo Dígitos Bytes Significativos Real 6 10-39 1038 11-12 -45 38 Single 4 10 10 7-8 UNIT/MG Página: 108 Curso de DELPHI Double Extended Comp Currency 8 10 8 8 10-324 10-4932 -1018 -1012 Elmo Batista de Faria, Dr. 10308 104932 1018 1012 15-16 19-20 19-20 19-20 Tipos Texto Os tipos texto podem operar com caracteres simples ou grupos de caracteres. O tipo texto padrão é o tipo string. Tipo Descrição Char Um único caractere ASCII String Texto alocado dinamicamente, pode ser limitado a 255 caracteres conforme configuração PChar String terminada em nulo (#0), usada geralmente nas funções da API do Windows O operador + pode ser usado para concatenar strings e você pode usar uma variável do tipo string como uma lista de caracteres. ShowMessage('5ª letra do título da janela: ' + Caption[5]); Label1.Text := '2ª letra do Edit: ' + Edit1.Text[2]; Existem várias funções de manipulação de strings, veja algumas das mais importantes mostradas abaixo. Função Descrição AnsiCompareTex Compara 2 strings sem sensitividade de maiúsculas/minúsculas t AnsiLowerCase Converte todas as letras de uma string para minúsculas AnsiUpperCase Converte todas as letras de uma string para maiúsculas Copy Retorna parte de uma string Delete Apaga parte de uma string Insert Insere uma string em outra Length Número de caracteres de uma string Pos Posição de uma string em outra Trim Remove todos os espaços de uma string TrimLeft Remove os espaços à esquerda de uma string TrimRight Remove os espaços à direita de uma string Format Formata uma string com uma série de argumentos de vários tipos Por exemplo, para comparar o texto de dois Edits, poderíamos usar a função AnsiCompareText. if AnsiCompareText(EdtA.Text, EdtB.Text) = 0 then ShowMessage('O texto dos dois Edits são iguais.'); A função Format é especialmente útil na formatação de strings, veja alguns exemplos. ShowMessage(Format('O número %d é a parte inteira do número %f.', [10, 10.5])); ShowMessage(Format('Este texto%sfoi formatado%susando o caractere #%d.', [#13, #13, 13])); ShowMessage(Format('O preço do livro %s é %m.', ['Como Programar em Delphi', 50.7])); Um detalhe que deve ser observado é que as propriedades dos objetos não podem ser usadas como variáveis em funções. Veja a declaração do procedimento Delete no help. procedure Delete(var S: string; Index, Count:Integer); Digamos que você deseje apagar as 5 primeiras letras de um Edit, como a string do Delete é variável, não poderia usar o código abaixo. Delete(Edit1.Text, 1, 5); UNIT/MG Página: 109 Curso de DELPHI Elmo Batista de Faria, Dr. Para você poder fazer a operação desejada, teria que usar uma variável como variável auxiliar. var S: string; begin S := Edit1.Text; Delete(S, 1, 5); Edit1.Text := S; end; Tipos Ordinais Tipos ordinais são tipos que tem uma seqüência incremental, ou seja, você sempre pode dizer qual o próximo valor ou qual o valor anterior a um determinado valor desses tipos. São tipos ordinais o Char, os tipos inteiros, o Boolean e os tipos enumerados. Algumas rotinas para ordinais são mostradas abaixo. Função Descrição Dec Decrementa variável ordinal Inc Incrementa variável ordinal Odd Testa se um ordinal é ímpar Pred Predecessor do ordinal Succ Sucessor do ordinal Ord Ordem de um valor na faixa de valores de um tipo ordinal Low Valor mais baixo na faixa de valores High Valor mais alto na faixa de valores Por exemplo, use o código abaixo no evento OnKeyPress de um Edit e veja o resultado. Inc(Key); Boolean Variáveis do tipo Boolean podem receber os valores lógicos True ou False, verdadeiro ou falso. Uma variável Boolean ocupa 1 byte de memória. TDateTime O tipo TDateTime guarda data e hora em uma estrutura interna igual ao tipo Double, onde a parte inteira é o número de dias desde 31/12/1899 e a parte decimal guarda a hora, minuto, segundo e milissegundo. As datas podem ser somadas ou subtraídas normalmente. Existem várias rotinas de manipulação de datas e horas, usadas com o tipo TDateTime, veja algumas abaixo. Rotina Descrição Date Retorna a data do sistema Now Retorna a data e hora do sistema Time Retorna a hora do sistema DayOfWeek Retorna o dia da semana de uma data especificada DecodeDate Decodifica um valor TDateTime em Words de dia, mês e ano DecodeTime Decodifica um valor TDateTime em Words de hora, minuto, segundo e milissegundos EncodeDate Retorna um TDateTime a partir de Words de dia, mês e ano EncodeTime Retorna um TDateTime a partir de Words de hora, minuto, segundo e milissegundos UNIT/MG Página: 110 Curso de DELPHI Elmo Batista de Faria, Dr. No help de cada uma das funções acima você vai encontrar alguns exemplos, veja os colocados abaixo. if DayOfWeek(Date) = 1 then ShowMessage('Hoje é Domingo, pé de cachimbo!') else ShowMessage('Hoje não é Domingo, pé de cachimbo!'); var A, M, D: Word; begin DecodeDate(Date, A, M, D); ShowMessage(Format('Dia %.2d do mês %.2d de %d.', [D, M, A])); end; Variant Tipo genérico, que pode atribuir e receber valores de qualquer outro tipo. Evite usar variáveis do tipo Variant, pois o uso dessas variáveis podem prejudicar a performance do programa, além de diminuir a legibilidade do código fonte e a integridade do executável, veja o trecho de código abaixo e note como esse tipo de variável tem um comportamento estranho. var V1, V2, V3: Variant; begin V1 := True; V2 := 1234.5678; V3 := Date; ShowMessage(V1 + V2 + V3); end; CONVERSÕES DE TIPO Freqüentemente você vai precisar converter um tipo de dado em outro, como um número em uma string. Para essas conversões você pode usar duas técnicas, o TypeCasting e as rotinas de conversão de tipos. TypeCasting TypeCast é uma conversão direta de tipo, usando o identificador do tipo destino como se fosse uma função. Como o Delphi não faz nenhuma verificação se a conversão é válida, você deve tomar um certo cuidado ao usar um TypeCast para não criar programas instáveis. var I: Integer; C: Char; B: Boolean; begin I := Integer('A'); C := Char(48); B := Boolean(0); Application.MessageBox(PChar('Linguagem de Programação' + #13 + 'Delphi 3'), 'SENAC', MB_ICONEXCLAMATION); end; UNIT/MG Página: 111 Curso de DELPHI Elmo Batista de Faria, Dr. Rotinas de Conversão As principais rotinas de conversão estão listadas na tabela abaixo. Caso você tente usar uma dessas rotinas em uma conversão inválida, pode ser gerada uma exceção. Rotina Descrição Chr Byte em Char StrToInt String em Integer IntToStr Integer em String StrToIntDef String em Integer, com um valor default caso haja erro IntToHex Número em String Hexadecimal Round Arredonda um número real em um Integer Trunc Trunca um número real em um Integer StrToFloat String em Real FloatToStr Real em string FormatFloat Número real em string usando uma string de formato DateToStr TDateTime em string de data, de acordo com as opções do Painel de Controle StrToDate String de data em TDateTime TimeToStr TDateTime em Strind de Hora StrToTime String de hora em TDateTime DateTimeToStr TDateTime em string de data e hora StrToDateTime String de data e hora em TDateTime FormatDateTime TDateTime em string usando uma string de formato VarCast Qualquer tipo em outro usando argumentos do tipo Variant VarAsType Variante em qualquer tipo Val String em número, real ou inteiro Str Número, real ou inteiro, em String Veja alguns exemplos de como usar essas rotinas. Conversão de dados é uma operação muito comum na programação em Object Pascal, seeria interessante dar uma olhada no help de cada uma das funções acima. var I: Integer; D: Double; S1, S2: string; begin D := 10.5; I := Trunc(D); S1 := FloatToStr(D); S2 := IntToStr(I); ShowMessage(S1 + #13 + S2); end; var A, B, Soma: Bouble; begin A := StrToFloat(EdtA.Text); B := StrToFloat(EdtB.Text); Soma := A + B; ShowMessage(Format('%f + %f = %f', [A, B, Soma]); end; UNIT/MG Página: 112 Curso de DELPHI Elmo Batista de Faria, Dr. EXPRESSÕES Uma expressão é qualquer combinação de operadores, variáveis, constantes, valores literais e chamadas de funções que resultem em um valor de determinado tipo. Uma expressão é usada sempre que precisamos de uma valor que possa ser obtido por uma expressão. A + 12 * C Date - 4 StrToInt(Edit1.Text + Edit2.Text) StrToDate(Edit2.Text) - StrToDate(Edit1.Text) 12 * A / 100 A<B OPERADORES Os operadores são usados em expressões e a ordem em que as expressões são executadas depende da precedência desses operadores. Veja abaixo a lista de operadores em ordem descendente de precedência. Operador Descrição Operadores Unários @ Endereço Não booleano ou bit voltado para não not Operadores Multiplicativos e de direção de Bit * Multiplicação ou interseção de conjuntos / Divisão de Real div Divisão de Inteiro mod Resto de divisão de Inteiros as TypeCast seguro quanto ao tipo (RTTI) E booleano ou bit voltado para e and shl Deslocamento de bits à esquerda shr Deslocamento de bits à direita Operadores Aditivos + Adição ou união de conjuntos Subtração ou diferença de conjuntos Ou booleano ou bit voltado para ou or Ou exclusivo booleano ou bit voltado para ou exclusivo xor Operadores Relacionais = Igual <> Diferente < Menor > Maoir <= Menor ou igual >= Maior ou igual in Pertinência a conjuntos is Compatibilidade de tipos (RTTI) Para forçar uma expressão de menor precedência a ser executada antes, você pode usar os parênteses, como mostrado abaixo. (5 - 2) * 3; (A > B) and (A < C) Para fazer potenciação, use a função Power, abaixo temos que A é igual a A elevado a 4. A := Power(A, 4); UNIT/MG Página: 113 Curso de DELPHI Elmo Batista de Faria, Dr. ESTRUTURAS DE DECISÃO If O if é uma estrutura de decisão usada para realizar instruções em determinadas condições. O if é considerado uma só instrução, por isso, só encontramos o ponto-evírgula no final. O else é opcional. if Opn.Execute then Img.Picture.LoadFromFile(Opn.FileName); if Nota < 5 then ShowMessage('Reprovado') else ShowMessage('Aprovado'); Case Permite que o fluxo da execução seja desviado em função de várias condições de acordo com o valor do argumento, que tem que ser ordinal, caso o valor do argumento não corresponda a nenhum dos valores listados, podemos incluir um else. case Ch of ' ': ShowMessage('Espaço'); '0'..'9': ShowMessage('Dígito'); '+', '-', '*', '/': ShowMessage('Operador'); else ShowMessage('Caractere especial'); end; case CbbBorda.ItemIndex of 0: BorderStyle := bsDialog; 1: BorderStyle := bsSingle; 2: BorderStyle := bsSizeable; end; ESTRUTURAS DE REPETIÇÃO While O laço while executa uma instrução até que uma condição seja falsa. I := 10; while I >= 0 do begin ShowMessage(IntToStr(I)); Dec(I); end; For O laço for executa uma instrução um número determinado de vezes, incrementando uma variável de controle automaticamente a cada iteração. Caso seja preciso que a contagem seja decremental, pode-se usar downto em vez de to. for I := 1 to ComponentCount do ShowMessage('O ' + IntToStr(I) + 'º Componente é ' + Components[I - 1].Name); UNIT/MG Página: 114 Curso de DELPHI Elmo Batista de Faria, Dr. for I := Length(Edit1.Text) downto 1 do ShowMessage(Edit1.Text[I]); Repeat O laço repeat executa instruções até que uma condição seja verdadeira. I := 1; repeat S := InputBox('Acesso', 'Digite a senha', ''); Inc(I); if I > 3 then Halt; until S = 'fluminense'; Quebras de Laço Em qualquer um dos laços mostrados podemos usar o procedimento Break para cancelar a repetição e sair do laço, podemos também forçar a próxima iteração com o procedimento Continue. I := 1; while true do begin Inc(I); if I < 10000000 then Continue; ShowMessage('Chegamos a dez milhões'); Break; end; TIPOS DEFINIDOS PELO USUÁRIO O usuário também pode declarar tipos não definidos pelo Delphi. Essas declarações são feitas na seção type, da interface ou implementation, sendo que na implementation esses tipos não poderão ser usados em outras Units. Dificilmente você terá que definir tipos, a não ser classes, pois os tipos padrão do Delphi são o bastante para a maioria das aplicações. Strings Limitadas Caso se deseje limitar o número de caracteres que uma string pode receber, podemos criar um tipo de string limitada. TNome = string[40]; TEstado = string[2]; Tipo Sub-Faixa É um subconjunto de um tipo ordinal e possui as mesmas propriedades do tipo original. TMaiusculas = 'A'..'Z'; TMes = 1..12; Enumerações Define uma seqüência de identificadores como valores válidos para o tipo. A cada elemento da lista de identificadores é associado internamente um número inteiro, iniciando pelo número 0, por isso são chamados de tipos enumerados. TBorderIcon = (biSystemMenu, biMinimize, biMaximize, biHelp); UNIT/MG Página: 115 Curso de DELPHI Elmo Batista de Faria, Dr. TDiaSemana = (Seg, Ter, Qua, Qui, Sex, Sab, Dom); Ponteiros Ponteiros armazenam endereços de memória, todas as classes em Object Pascal são implementadas como ponteiros, mas raramente o programador vai precisar usá-los como tal. TIntPtr: ^Integer; Records O tipo record é uma forma de criar uma única estrutura com valores de diferentes tipos de dados. Cada um dos dados de um record é chamado de campo. TData = record Ano: Integer; Mes: TMes; Dia: Byte; end; var Festa: TData; begin Festa.Ano := 1997; Festa.Mes := Mai; Festa.Dia := 8; end; Arrays Arrays fornecem uma forma de criar variáveis que contenham múltiplos valores, como em uma lista ou tabela, cujos elementos são do mesmo tipo. Veja abaixo alguns exemplos de arrays de dimensões variadas. TTempDia = array [1..24] of Integer; TTempMes = array [1..31, 1..24] of Integer; TTempAno = array [1..12, 1..31, 1..24] of Integer; var TD: TTempDia; I: Integer; begin for I := 1 to 24 do TD[I] := StrToIntDef(InputBox('Temperaturas', 'Digite a temperatura na hora ' + IntToStr(I), ''), 30); end; Um array pode ser definido como constante tipada, onde todos os seus elementos devem ser inicializados. FAT: array[1..7] of Integer = (1, 2, 6, 24, 120, 720, 5040); O tipo dos elementos de um array pode ser qualquer um, você pode ter uma array de objetos, de conjuntos, de qualquer tipo que quiser, até mesmo um array de arrays. TTempMes = array [1..31] of TTempDia; TBtnList = array [1..10] of TButton; UNIT/MG Página: 116 Curso de DELPHI Elmo Batista de Faria, Dr. Sets São conjuntos de dados de um mesmo tipo, sem ordem, como os conjuntos matemáticos. Conjuntos podem conter apenas valores ordinais, o menor que um elemento pode assumir é zero e o maior, 255. TBorderIcons = set of TBorderIcon; BorderIcons := [biSystemMenu, biMinimize]; if MesAtual in [Jul, Jan, Fev] then ShowMessage('Férias'); Os conjuntos podem ser definidos como constantes ou constantes tipadas, como abaixo. DIG_HEXA = ['0'..'9', 'A'..'Z', 'a'..'z']; DIG_HEXA: set of Char = ['0'..'9', 'A'..'Z', 'a'..'z']; PROCEDIMENTOS, FUNÇÕES E MÉTODOS As ações de um objeto devem ser definidas como métodos. Quando a ação não pertence a um objeto, como uma transformação de tipo, essa ação deve ser implementada em forma de procedimentos e/ou funções. Procedimentos Procedimentos são sub-rotinas, que realizam uma tarefa e não retornam um valor. A declaração de um procedimento é feita na seção interface e a definição, na seção implementation. Ao chamar o identificador do procedimento, com os parâmetros necessários, esse procedimento será executado. Veja abaixo o exemplo de uma unit com a implementação um procedimento. unit Tools; interface procedure ErrorMsg(const Msg: string); implementation uses Forms, Windows; procedure ErrorMsg(const Msg: string); begin Application.MessageBox(PChar(Msg), 'Operação inválida', MB_ICONERROR); end; end. Funções Funções são muito semelhantes a procedimentos a única diferença é que as funções retornam um valor. O tipo do valor de retorno deve ser informado no cabeçalho da função. Na implementação da função deve-se atribuir o valor de retorno à palavra reservada Result ou ao identificador da função. Pode-se então usar a função em expressões, atribuições, como parâmetros para outras funções, em qualquer lugar onde o seu valor possa ser usado. function Average(A, B: Double): Double; UNIT/MG Página: 117 Curso de DELPHI Elmo Batista de Faria, Dr. begin Result := (A + B) / 2; end; Métodos Métodos são funções ou procedimentos que pertencem a alguma classe, passando a fazer parte de qualquer objeto dessa classe. Na implementação de um método precisamos indicar qual a classe à qual ele pertence. Para chamar um método em algum lugar não pertencente à sua classe, como procedimentos, funções ou métodos de outras classes, deve ser indicado o objeto que deve executar o método. Os métodos usam os mesmos níveis de encapsulamento dos atributos. type TFrmMsg = class(TForm) LblMsg: TLabel; BtnOk: TButton; BtnCancelar: TButton; ImgMsg: TImage; public procedure ShowMsg(const Msg: string); end; procedure TFormMsg.ShowMsg(const Msg: string); begin LblMsg.Caption := Msg; ShowModal; end; Parâmetros Existem três tipos de passagem de parâmetros, que devem ser indicados na declaração da função ou procedimento. Parâmetros de tipos diferentes de vem ser separados por ponto e vírgula. function MultiStr(const S: string; N: Double; var Erro: Integer): string; • Quando não é indicado o tipo de passagem, é passado o valor do parâmetro, como constante. • Ao usar a palavra-chave var, não será enviado o valor do parâmetro e sim uma referência a ele, tornando possível mudar o valor do parâmetro no código do procedimento. • Como alternativa você pode passar um parâmetro por referência constante, para isso use a palavra const antes da declaração do parâmetro. WITH Usado para facilitar o acesso às propriedades e métodos de um objeto. with Edt do begin CharCase := ecUpperCase; MaxLenght := 10; PasswordChar := '*'; Text := 'Brasil'; end; UNIT/MG Página: 118 Curso de DELPHI Elmo Batista de Faria, Dr. SELF Self é usado quando se quer referenciar a instância atual da classe. Se você precisar referenciar a instância atual de uma classe, é preferível usar Self em vez de usar o identificador de um Objeto, isso faz com que o código continue funcionando para as demais instâncias da classe e em seus descendentes. CRIANDO E DESTRUINDO OBJETOS Antes de tudo, você deve declarar o objeto, se quiser referenciá-lo. Para criá-lo, use o método Create, que é um método de classe. Para você usar um método de classe, referencie a classe, não o Objeto, como mostrado abaixo. var Btn: TBitBtn; begin Btn := TBitBtn.Create(Self); With Btn do begin Parent := Self; Kind := bkClose; Caption := '&Sair'; Left := Self.ClientWidth - Width - 8; Top := Self.ClientHeight - Height - 8; end; end; Porém, se você não precisar referenciar o Objeto, poderia criar uma instância sem referência. with TBitBtn.Create(Self) do begin Parent := Self; Kind := bkClose; Caption := '&Sair'; Left := Self.ClientWidth - Width - 8; Top := Self.ClientHeight - Height - 8; end; Para destruir um objeto, use o método Free. Para Forms, é recomendado usar o Release, para que todos os eventos sejam chamados. O parâmetro do método Create é usado apenas em Componentes, para identificar o componente dono. Ao criar Forms, poderíamos usar o Objeto Application. FrmSobre := TFrmSobre.Create(Application); FrmSobre.ShowModal; FrmSobre.Release; Para criar objetos não componentes, você não precisa de nenhum parâmetro no método Create. var Lst: TStringList; begin Lst := TStringList.Create; Lst.Add('Alô, Teresinha!'); Lst.Add('Uhh uhh...'); Lst.SaveToFile('Teresinha.txt'); Lst.Free; end; UNIT/MG Página: 119 Curso de DELPHI Elmo Batista de Faria, Dr. RTTI Run Time Type Information é a informação de tipo dos objetos em tempo de execução. O operador is é usado para fazer comparações e o operador as é usado para fazer um TypeCast seguro com objetos. for I := 0 to ComponentCount - 1 do if Components[I] is TEdit then TEdit(Components[I]).Clear; (Sender as TEdit).Color := clYellow; EXERCÍCIOS 1. Faça um Form, com um Edit e botões para passar o texto do Edit para maiúsculas, minúsculas e apagar todos os espaços. 2. Crie um Form com dois Edits, um botão para verificar se os dois textos são iguais sem levar em consideração o caso, um botão para inserir o texto do primeiro Edit no meio do segundo e outro botão para verificar se o texto do primeiro Edit está dentro do texto do segundo. 3. Crie um projeto com um Form de múltiplas páginas, onde possa ser feita uma analise de balanço. Na primeira guia, devem ser informados o patrimônio líquido da empresa, os valores circulante, realizável a longo prazo e permanente. Na Segunda guia mostre uma análise vertical, tome o patrimônio líquido como 100% e mostre o percentual de cada um dos outros valores informados. Na terceira guia, mostre um gráfico com panels representando cada um dos percentuais mostrados na segunda guia. 4. Faça um programa que sugira que o usuário pare de trabalhar quando o relógio do sistema não estiver em horário comercial. 5. Sabendo que M e N são inteiros, o que podemos concluir desses números se a expressão M div N * N = M retornar true e qual outra expressão poderia ser usada para testar a mesma condição? 6. Sendo I um número inteiro, R um real e S uma string com um texto numérico como encontrar o resultado da soma dos 3 valores, e de que tipo será esse resultado? 7. Como poderíamos mandar o texto de um Edit chamado Edit1 para uma caixa de mensagem do tipo MessageBox, que recebe parâmetros do tipo PChar? 8. Faça um programa para encontrar as raízes de uma equação de 2º grau cujos coeficientes sejam informados pelo usuário. Para relembrar, a fórmula é ax2 + bx + c = 0, o delta é ∆ = b2 - 4ac e as raízes são dadas como x1 = (- b + RAIZ(∆))/2a e x2 = (- b - RAIZ(∆))/2a. 9. Qual expressão podemos usar para encontrar a média aritmética entre M e N, sabendo que M é uma string numérica e N é um caractere numérico? 10. Sabendo que no SENAC a média mínima é 7,0 e a tolerância de faltas é 15 % da carga horária do curso, faça um programa que peça as informações necessárias e informe a situação do usuário. 11. Faça uma função que retorne o número de caracteres numéricos que existem em uma string. 12. Faça uma função que defina se o ano é bissexto ou não. Sabendo que para ser bissexto, o ano precisa ser divisível por 4 e, além disso, não ser divisível por 100. Se for divisível por 100 o ano tem que ser divi'sivel por 400 para ser bissexto. UNIT/MG Página: 120 Curso de DELPHI Elmo Batista de Faria, Dr. 13. Sabendo que a chamada de função Pos(Str1, Str2) retorna a posição da string Str1 dentro de Str2, que Delete(S, 4, 6) remove 6 caracteres da string S a partir do caractere 4, e que Lenght(S) retorna o número de caracteres da string S, crie um procedimento chamado Remover que remova as ocorrências de uma string dentro de outra. 14. Crie uma função que retorne a string enviada como parâmetro de trás para frente. 15. Usando a função anterior crie um Form com dois Edits, onde ao digitar um texto no primeiro Edit, esse texto apareça invertido no segundo. 16. Usando a função anterior faça uma função que receba como parâmetro uma data e retorne quantos dias há no mês e ano dessa data. Como fazer com que um Edit só aceite que sejam digitados caracteres numéricos em seu interior? 17. Faça um programa onde o usuário informe 2 datas e seja mostrado o número de anos, meses e dias entre elas. 18. Faça um programa que peça a data de nascimento do usuário, converta o texto dessa data para uma forma de ano com 4 dígitos e mostre a idade do usuário. 19. Digamos que peso ideal de uma pessoa em quilos seja sua altura menos 1,15 m. Faça um programa que peça a altura e o peso do usuário e informe quanto ele precisa engordar ou emagrecer. 20. Faça um programa que mostre quantos caracteres numéricos e quantos alfabéticos existem em um Memo UNIT/MG Página: 121