Apostila de Delphi 4
Indice
APOSTILA DE DELPHI 4 ....................................................................................... 1 1
CURSO DE DELPHI 4.0 - APOSTILA 1 ........................................................... 3
2
CURSO DE DELPHI 4.0 - APOSTILA 2 ......................................................... 11
3
CURSO DE DELPHI 4.0 - APOSTILA 3 ......................................................... 19
4
CURSO DE DELPHI 4.0 - APOSTILA 4 ......................................................... 29
5
CURSO DE DELPHI 4.0 - APOSTILA 5 ......................................................... 38
6
CURSO DE DELPHI 4.0 - APOSTILA 6 ......................................................... 44
7
CURSO DE DELPHI 4.0 - APOSTILA 7 ......................................................... 54
8
CURSO DE DELPHI 4.0 - APOSTILA 8 ......................................................... 59
9
CURSO DE DELPHI 4.0 - APOSTILA 9 ......................................................... 69
10
CURSO DE DELPHI 4.0 - APOSTILA 10 .................................................... 78
11
CURSO DE DELPHI 4.0 - APOSTILA 11 .................................................... 88
12
CURSO DE DELPHI 4.0 - APOSTILA 12 .................................................. 108
13
CURSO DE DELPHI 4.0 - APOSTILA 13 .................................................. 118
14
CURSO DE DELPHI 4.0 - APOSTILA 14 .................................................. 130
15
CURSO DE DELPHI 4.0 - CONEXÃO DELPHI COM O MS-ACCESS...... 139
16
CURSO DE DELPHI 4.0 - PRINCIPAIS INSTRUÇÕES EM SQL.............. 141
17
CURSO DE DELPHI 4.0 - PROGRAMAÇÃO ORIENTADA A OBJETOS 153
1 Curso de Delphi 4.0 - Apostila 1 Autor: Fernando Antonio F. Anselmo eMail:
[email protected] Pré-Requisitos: • • • •
Windows 98 Delphi 4.0 versão Client/Server Suite BDE 5.00 MS-Access 97
Arquivos trabalhados juntos com esta apostila: •
PASCOA2G.BMP
Prefácio Salve, para você que está começando e participando deste curso, primeiramente gostaria de avisar que o curso é totalmente prático, com exercícios e truques que lhe ajudarão a senão dominar pelo menos a desvendar os mistérios desse maravilhoso ambiente. Deixa eu dar um conselho que eu aprendi a duras penas, tente sempre que acontecer algum erro, mostrá-lo para um colega que conheça também Delphi. Uma vez fiquei quase dois dias com um erro me incomodando, imprimi, revi linha a linha até que finalmente pedi para que um amigo do lado olhasse meu programa em menos de 1 segundo ele descobriu o erro, era um simples comando IF que tinha construído errado. Existe uma frase para o Delphi que sempre utilizo quando começo meus cursos é assim: Tudo o que parece difícil na verdade é fácil Tudo o que parece fácil na verdade é muito mais fácil. Isso sempre funcionou com o Delphi. Um abraço e bom trabalho.
☞
Solicito que quando você encontrar a seguinte simbologia Importante pare e leia com a maior atenção, pois ali você encontrará uma dica valiosa que poderá lhe ajudar a esclarecer várias dúvidas. O Delphi é um ambiente de Desenvolvimento totalmente Baseado na Orientação a Objetos, não é puro (discutiremos isso no apêndice referente a Orientação a Objetos) mas por enquanto você precisa apenas saber que ele é uma ferramenta com um incrível poder na construção tanto de softwares complexos, quanto de sistemas de manipulação a bancos de dados. Para o nosso primeiro contato com a ferramenta, selecionei algo prático, fácil, útil e até mesmo bonitinho, um cartão eletrônico, você poderá mandar para seus amigos um simples executável com uma mensagem, vou criar aqui um para a Páscoa mas é possível aproveitar a idéia para outros eventos também tais como Natal, Aniversários, nascimentos e assim vai. Vamos começar então:
Conhecendo o Ambiente Abra o Delphi, bem aí está seu ambiente de trabalho, vamos a uma rápida explicação, o Delphi é composto por quatro ambientes de trabalho:
1. Parte superior composta pelo Menu, Component Pallete e Botões de Acesso Rápido
(Speed Button): é exatamente o conjunto que está suspenso na área aberta, o Menu (localizado no topo) dá acesso as opções, a Component Pallete (localizado na parte superior direita) contém todos os objetos (divididos em classes) que você utilizará para realizar seus projetos, e os Botões de Acesso Rápido (localizado na parte superior esquerda) que são uma abreviação dos comandos do menu. Uma novidade do Delphi 4.0 é que todos eles estão colocados em janelas auto-arrastáveis, então é possível modificar as possições entre eles ou criar janelas suspensas basta para isso que você clique no canto (dessas partes duplas) segure e arraste.
2. Object Inspector: é uma janelinha lateral (chamada como a tecla F11) que contém as propriedades e os eventos dos objetos selecionados.
3. Form: este objeto será sua prancheta de trabalho é nessa janela em branco (seria melhor dizer em cinza) que criaremos nossa comunicação entre o sistema e os nossos usuários.
4. Code Editor: é a área localizada atrás do "Form", ela foi dividida em dois ambientes, uma parte que funcionará como índice, nos mostrandos os objetos existentes, as bibliotecas utilizadas e as variáveis ou constantes disponíveis, elém dos procedimentos e funções criadas e uma outra que conterá nossas o código propriamente dito (em linguagem Object Pascal), diferentemente das outras linguagens visuais, no Delphi você tem a capacidade de visualizar todo o código do seu formulário e não apenas uma determinada parte.
Projeto 1 - Cartão Eletrônico Bem, agora que estamos familiarizados com o ambiente, vamos começar como uma receita de bolo, siga um passo atrás do outro, mas antes de começar, crie uma pasta que abrigará seu projeto, para padronizar vamos criar uma pasta com o nome CursoDelphi e dentro dela criaremos uma nova pasta chamada Cartão, e coloque nela o .BMP enviado: 1. Na Component Pallete localize uma página chamada Additional e dentro dessa página de um clique no objeto Image (acredito que seja o sexto) e dê um clique no Form. (automaticamente o Delphi criou um quadrado quadriculado que representa o objeto Image1). 2. Olhe na Object Inspector e verifique as propriedades do objeto Image1 criado, e altere as seguintes propriedades: 2.1. AutoSize: True (Fará com que o tamanho do objeto fique automaticamente do tamanho da figura selecionada) 2.2. Picture: Clique nos "..." (ou dê um duplo clique em cima do objeto criado) e localize o arquivo .BMP enviado (Seleciona determinada figura) 3. Vá na Object Inspector e localize o objeto Form1 (basta clicar no Combo Box para seleciona-lo), e altere as seguintes propriedades: 3.1. BorderStyle: bsDialog (Fará com que a janela fique no formato padrão de uma janela de mensagens) 3.2. Caption: Feliz Páscoa (Conteúdo da tarja do formulário) 3.3. Color: clBlack (Cor do formulário para preto) 3.4. Font: Clique nos "..." e faça as seguintes alteções na janela de Fonts: 3.41. Cor: Branco 3.42. Tamanho: 10 3.4. Name: F_Cartao (Nome interno do formulário) 3.5. Position: poScreenCenter (Fará com que o formulário fique sempre centralizado quando for executado)
☞
Importante - Após alterarmos a Cor (propriedade Color) e a Fonte (propriedade Font) todos os outros objetos criados em cima deste Form, automaticamente herdarão essas alterações. 4. Dê uma salvadinha no seu projeto, para tanto, no menu vá em File | Save All...:
4.1. Aonde aparece Unit1.pas (o Delphi está se referindo do nome do formulário) mude para fCartao.PAS 4.2. Aonde aparece Project1.dpr (o Delphi está se referindo do nome do projeto - que será o nome do executável final) mude para Cartao.DPR 5. Na Component Pallete localize uma página chamada Standard e dentro dessa página localize o objeto Label (acredito que seja o terceiro) pressione a tecla SHIFT e clique no objeto (deve ter ficado um quadriculado azul em volta do objeto, como se ficasse marcado) e dê oito cliques no Form - um abaixo do outro e na área preta. (automaticamente o Delphi criou oito objetos chamados respectivamente Label1, Label2, Label3, Label4, Label5, Label6, Label7 e Label8) 6. Quando terminar clique dentro da Component Pallete na setinha para poder desmarcar o objeto Label. 7. Dê uma comparadinha no desenho para ver como está ficando:
Bom, todos os objetos que serão visíveis já estão aí, agora vamos criar dois objetos que servirão apenas como meros auxiliares: 7. Na Component Pallete na mesma página Standard clique no objeto Memo (acredito que seja o quinto) e dê um clique no Form (automaticamente o Delphi criou um quadrado que representa o objeto Memo1). 8. Olhe na Object Inspector e verifique as propriedades do objeto Memo1 criado, e altere as seguintes propriedades: 8.1. Font: Clique nos "..." e faça as seguintes alteções na janela de Fonts: 8.11. Cor: Preto 8.12. Tamanho: 8 8.2. Lines: Clique nos "..." e copie o seguinte texto: Recebe, Oh Senhor, em sua gloria eterna e envolve com paz e amor este sacrifício em incenso, que sobe clamando por justiça
por todos os meninos assassinados pelos pobres que morrem de fome pelas mulheres violentadas pelo povo roubado e explorado. E perdoa, Oh Senhor, perdoa o Brasil, seu presidente estratosférico, seus deputados escondidos, seus senadores omissos, sua igreja distraída, seus militares fantoches, sua polícia ausente, perdoa nós todos, Senhor, perdoa a mim e a meu irmão que nada fizemos, que não agimos, e que não vimos a imagem de seu filho Cristo na Cruz. Ou digite um outro texto que mais lhe agradar, mas anote o número de linhas (neste aqui temos 25 linhas) 8.3. Visible: False (Não mostrará o objeto em tempo de execução) 9. Na Component Pallete na página System clique no objeto Timer (acredito que seja o primeiro) e dê um clique no Form (automaticamente o Delphi criou um quadradinho com um relógio, que por sinal é uma cópia do desenho do objeto). A propriedade Interval controla a velocidade do objeto.
Codificando Tudo pronto, agora é só meter a mão no programa, mas vamos devagar, a idéia do cartão, se você ainda não entendeu, é que ao ser executado a mensagem que está guardada dentro do objeto Memo1 rolará entre os oito labels (como se tivesse subindo) para isso foi criado um Temporizador (Objeto Timer1), que é ativado a cada segundo (através da propriedade Interval, medida em milésimos de segundo) que simulará o movimento entre os labels. Então vamos começar a brincadeira: 10. Pressione a tecla F12, até você ter acesso a Code Editor, sugiro que você maximize a área para trabalhar melhor, localize as seguintes linhas: private { Private declarations } public { Public declarations } end; e altere para o seguinte: private NumLinha: Integer; public { Public declarations } end;
Você acaba de criar uma variável particular (Private) do tipo inteira (Integer) que servirá apenas a este formulário, sendo criada e destruída junto com ele. 11. Localize na Object Inspector o objeto F_Cartao, mude para a página de eventos (Events) e localize o evento OnShow, dê um duplo clique na área em branco. Automaticamente o Delphi criará para você a chamada ao evento e o transferirá para a Code Editor, insira o seguinte código: procedure TF_Cartao.FormShow(Sender: TObject); var i : Integer; begin for i := ComponentCount - 1 downto 0 do if (Components[I] is TLabel) then (Components[I] as TLabel).Caption := ''; NumLinha := 0; end; Neste evento que é disparado assim que o formulário se inicia, limparemos os oito Labels para isso simplesmente utilizaremos uma string vazia, use aspas simples (nunca duplas) e sem espaços entre elas, para chamar os oito labels utilizaremos a variável ComponentCount para contar quantos componentes tem o formulário, verificamos quais deles são label's e estes limparemos e iniciarmos a nossa variável NumLinha com 0.
☞Importante - Muitos dos procedimentos que o Delphi cria automaticamente (através dos eventos) requisitam a passagem de um objeto do tipo TObject (Sender: TObject), isso faz você saber quem foi que ativou tal evento, se foi por ação de um mouse ou de um clique num botão, e assim vai. Aqui foi preciso rastrear todos os componentes do formulário através do comando Components[n], aonde n é o número de cada componente. Isto é iniciado do 0 (assim como todo Array no Delphi começa do 0, ex: Lines, Items...), então é preciso criar um FOR que vai do 0 até o (número total de componente-1) porque o primeiro é o 0 isto explicasse imaginando uma lista de 10 números começados pelo 0, vc terá 0,1,2,3,4,5,6,7,8,9 então o último número será o número total da sua lista - 1.
☞Importante - Claro que ao invés de usarmos: for i := ComponentCount - 1 downto 0 do if (Components[I] is TLabel) then (Components[I] as TLabel).Caption := ''; poderiamos muito bem utilizar: Label1.Caption := ''; Label2.Caption := ''; Label3.Caption := ''; Label4.Caption := ''; Label5.Caption := ''; Label6.Caption := ''; Label7.Caption := ''; Label8.Caption := ''; Mas isso além de ficar um tantinho mais inchado, fica muito deselegante, é verdade que estamos tratando apenas com 8 objetos label's mas e se amanhã utilizamos 20 ou 30 ?? Além do que isso pode-se dizer que é o primeiro passo para um recurso de MacroSubstituição, como foi utilizado com o TLabel, pode também ser utilizado para o TEdit, TEditMask , TDBText ou qualquer outro que você deseje.
12. Localize na Object Inspector o objeto Timer1, mude para a página de eventos (Events) e localize o evento OnTimer, dê um duplo clique na área em branco. Automaticamente o Delphi criará para você a chamada ao evento e o transferirá para a Code Editor, entre os intervalos begin e end escreva: procedure TF_Cartao.Timer1Timer(Sender: TObject); function Monta : String; begin result := Memo1.Lines[NumLinha]; inc(NumLinha); if NumLinha > 30 then NumLinha := 0; end; begin NumLinha := NumLinha - 7; Label1.Caption := Monta; Label2.Caption := Monta; Label3.Caption := Monta; Label4.Caption := Monta; Label5.Caption := Monta; Label6.Caption := Monta; Label7.Caption := Monta; Label8.Caption := Monta; end; Neste evento é que está toda a jogada do programa, note que dentro da procedure colocamos uma função interna Monta que nos retornará o conteúdo de uma determinada linha do objeto Memo1, note que trabalhamos com 8 label's, então:
☞Importante - Note que existe uma variável chamada Result ela é uma variável definida pela própria função (no caso tipo String), poderíamos aqui usar dois nomes ou Monta ou a palavra chave Result, ambos os nomes apontam para a mesma variável que tem como função fazer a devolução da String definida pela função (para maiores referências veja a apostila Programação Orientada a Objetos) no primeiro segundo que passar: Label1 até Label7 = Branco e o Label8 com o conteúdo da primeira linha do objeto Memo1. No próximo segundo que passar: Label1 até Label6 = Branco, Label7 com o conteúdo da primeira linha do objeto Memo1 e o Label8 com o conteúdo da segunda linha do objeto Memo1. No próximo segundo que passar: Label1 até Label5 = Branco, Label6 com o conteúdo da primeira linha do objeto Memo1 e o Label7 com o conteúdo da segunda linha do objeto Memo1 e Label8 com o conteúdo da terceira linha do objeto Memo1 E assim vai aumentando segundo após segundo, até um total de 30 segundos, note aqui que são 25 linhas, aumentei mais 5 para ter um intervalo entre a última linha e o começo de uma nova montagem quando a variável monta linha é novamente reiniciada a zero. Note que para adicionar 1 a variável NumLinha utilizo a função interna INC, esta função também pode ser: Inc(variável, [quanto]) aonde "quanto" representa o número que você quer adicionar a variável, se não for enviado será por default 1. Isto seria o correspondente: variável := variável + quanto; e só de curiosidade o contrário da função INC é a função DEC.
☞Importante - os brancos são conseguidos pesquisando valores negativos dentro da propriedade Lines do
objeto Memo1. Note que eu faço [NumLin := NumLin - 7] como resultado disto teremos primeiramente o valor -7, depois -6, e assim vai até chegar a 0 no primeiro segundo.
☞
Importante - aqui não adianta tentar usar o recurso da ComponentCount pois pode avacalhar na hora da montagem, então é preferível fazer o lote da montagem dos oito label's na mão mesmo.
Enviando o projeto para um Amigo Prontinho agora basta apenas você compilar o projeto, vá ao menu nas opções Project | Compile... (ou pressione CTRL+F9 e prontinho é só mandar o executável gerado para sua(seu) namorada(o), parente, colega ou amigo(a), acredito que deva caber num único disquete (Atenção: Não precisa mandar o .BMP o Delphi já se encarrega de guardá-lo no executável).
Realizando uma pequena otimização Anote antes desses passos qual foi o tamanho em Bytes que ficou o seu executável. 1. Uma coisa que você pode (e deve fazer) é ir em Project | Options... na página Application atribua um título (Title) e um novo ícone (Icon) ao seu projeto, depois vá na página Compiler e desmarque todas as opções do Grupo Debugging (elas só servem para quando você estiver testando o aplicativo). 2. No início do programa do seu formulário deixe apenas as seguintes bibliotecas: unit fCartao; interface uses Windows, Classes, Controls, ExtCtrls, StdCtrls, Forms; 3. Dê uma compilada final escolhendo as opções Project | Build All Compare agora o tamanho do seu executável final. Mas não se preocupe esses macetes você aprenderá ao longo do nosso curso. (Atenção: também não precisa mandar o Ícone que você escolheu para seu projeto o Delphi também se encarrega de colocá-lo no executável).
Finalmente Na próxima apostila começaremos a desvendar os segredos dos bancos de dados.
2 Curso de Delphi 4.0 - Apostila 2 Autor: Fernando Antonio F. Anselmo eMail:
[email protected] Pré-Requisitos: • • • •
Windows 98 Delphi 4.0 versão Client/Server Suite BDE 5.00 MS-Access 97
Arquivos trabalhados juntos com esta apostila: • • • • • •
BRASIL.BMP NORTE.BMP NORDESTE.BMP SUL.BMP SULDESTE.BMP CENTRO.BMP
Prefácio Salve, após a construção de um Cartão você pode estar pensando o que virá a seguir ? Acertou se pensou no acesso a Banco de Dados, afinal o maior mistério com o Delphi é como ele trata Bancos de Dados. Uma das grandes vantagens do Delphi é o seu relacionamento com os diversos bancos de dados atualmente existentes, e o Delphi é um dos poucos ambientes que consegue fazer essa conexão de forma rápida e prática. Mas antes de nos enveredarmos no conceito de Banco de Dados vamos criar a nossa capa do aplicativo, garanto que você achará bastante interessante o que estamos prestes a começar a desenvolver. Vamos a uma rápida explicação o que é este projeto. Inicialmente será mostrado o mapa do Brasil para que o usuário possa escolher determinada região, após a escolha de uma região o usuário poderá dentro desta escolher qual o estado ele deseja ter uma pequena descrição, eu vou alargar um pouco e dar também a possibilidade de impressão da região escolhida.
Projeto 2 - Mapa Eletrônico (1a. Parte) Bem, agora vamos começar nosso projeto (note que eu sempre falo a palavra Projeto ao invés de Sistema, em Orientação a Objetos não existem Sistemas e sim Projetos então acostume-se com isso) agora que já ficamos familiarizados com o Delphi este projeto será um pouco diferente criarei apenas uma parte dele caberá a você a conclusão do resto do projeto, Ok ? Então vamos meter a mão na massa: 1. Abra o Delphi, como se isso já não fosse óbvio. 2. Na Component Pallete localize uma página chamada Additional e dentro dessa página de um clique no objeto Image (acredito que seja o sexto) e dê um clique no Form. (automaticamente o Delphi criou um quadrado quadriculado que representa o objeto Image1). 3. Olhe na Object Inspector e verifique as propriedades do objeto Image1 criado, e altere as seguintes propriedades:
3.1. AutoSize: True (Fará com que o tamanho do objeto fique automaticamente do tamanho da figura selecionada) 3.2. Picture: Clique nos "..." e localize o arquivo BRASIL.BMP enviado (Seleciona determinada figura) 4. Vá na Object Inspector e localize o objeto Form1 (basta clicar no Combo Box para selecioná-lo), e altere as seguintes propriedades: 4.1. BorderStyle: bsDialog (Fará com que a janela fique no formato padrão de uma janela de mensagens) 4.2. Caption: Mapa Eletrônico (Conteúdo da tarja do formulário) 4.3. Name: F_Mapa (Nome interno do formulário) 4.4. Position: poScreenCenter (Fará com que o formulário fique sempre centralizado quando for executado) 5. Dê uma salvadinha no seu projeto, para tanto, no menu vá em File | Save All...: 5.1. Aonde aparece Unit1.pas (o Delphi está se referindo do nome do formulário) mude para fMapa.PAS 5.2. Aonde aparece Project1.dpr (o Delphi está se referindo do nome do projeto - que será o nome do executável final) mude para Mapa.DPR 6. Na Component Pallete localize uma página chamada Standard e dentro dessa página localize o objeto Label (acredito que seja o terceiro) clique no objeto e dê um clique no Form e altere as seguintes propriedades: 6.1. Font: Clique nos "..." e faça as seguintes alteções na janela de Fonts: 6.11. Cor: Castanho 6.12. Estilo: Negrito 6.2. Caption: Clique sobre a Região a consultar (Conteúdo que será mostrado) 7. Na Component Pallete localize uma página chamada Additional e dentro dessa página localize o objeto Image (acredito que seja o sexto) pressione a tecla SHIFT e clique no objeto (deve ter ficado um quadriculado azul em volta do objeto, como se ficasse marcado) e dê cinco cliques no Form - de preferência um em cada região, e altere as propriedades Name e Hint de cada um para, respectivamente: Name ImgNorte ImgNordeste ImgCentro ImgSudeste ImgSul
- Hint - Mostra os estados da Região Norte - Mostra os estados da Região Nordeste - Mostra os estados da Região Centro-Oeste - Mostra os estados da Região Sudeste - Mostra os estados da Região Sul
☞Importante - A próxima modificação tem a ver com Orientação a Objetos o termo é POLIMORFISMO, isso significa que vários objetos (mesmo diferentes) possuem propriedades idênticas entre si, por exemplo a propriedade Caption de um objeto Form possui (basicamente) a mesma função da propriedade Caption de um objeto Label. 8. Clique no objeto ImgNorte segure a tecla SHIFT e clique em ImgNordeste, ImgCentro, ImgSudeste e ImgSul (o que eu queria era que todos os cinco objetos ficassem marcados simultaneamente), altere agora a propriedade ShowHint para True. (Note que na Object Inspector não aparece o nome do objeto) e a propriedade Cursor para crHandPoint (isso fará com que o cursor em cima da figura seja alterado para uma mãozinha apontando).
☞
Importante - Isso pode ser usado para alterar diversas propriedades de objetos diferentes, praticaremos isso posteriormente.
9. Quando terminar clique em qualquer região do formulário para desmarcar os objetos. 10. Para terminar nosso primeiro formulário desse projeto vá para a Component Pallete localize uma página chamada Additional e dentro dessa página localize o objeto BitBtn (acredito que seja o primeiro) clique no objeto e dê um clique no Form e altere as seguintes propriedades: 10.1. Kind: bkClose, isso fez com que três importantes propriedades se alterassem: 10.11. Caption: assumiu o valor &Close. 10.12. Glyph: ganhou uma imagem padrão de uma portinha de saída 10.13. Modal Result: apesar de não ter sofrido alteração internamente foi disparado uma Flag que fará com que quando este botão seja clicado o formulário se encerre automaticamente. 10.2. Caption: &Fechar (apenas para "aportuguesar"o nosso aplicativo). 11. Dê uma comparadinha no desenho para ver como ficou:
Bom, este será o nosso primeiro formulário, de uma série de sete, sua função é simples, ele mostrará o mapa do Brasil e ao ser clicar em qualquer parte de uma determinada região ele disparará o mapa respectivo desta.
Codificando o mapa A codificação é um tanto simples, mas pretendo aqui ensinar também alguns macetes interessantes, aperte a tecla F12 até que você tenha a janela da Code Editor aberta e localize para mim as seguintes linhas: ImgSul: TImage; ImgSudeste: TImage; private Inclua a seguinte chamada a um procedimento antes da parte private: ImgSul: TImage; ImgSudeste: TImage;
procedure ChamaRegiao(Sender: TObject); private Agora localize a linha: implementation {$R *.DFM} end. E faça as seguintes alterações implementation {$R *.DFM} uses fNorte, fNordeste, fSul, fSudeste, fCentro;
// Chama o mapa da Região Norte // Chama o mapa da Região Nordeste // Chama o mapa da Região Sul // Chama o mapa da Região Sudeste // Chama o mapa da Região Centro-Oeste
procedure TF_Mapa.ChamaRegiao(Sender: TObject); // Chama os outros Formulários procedure CriaForm(aFormClass: TFormClass); begin with aFormClass.Create(Application) do try ShowModal; finally Free; end; end; begin if (Sender = ImgNorte) then CriaForm(TF_Norte) else if (Sender = ImgCentro) then CriaForm(TF_Centro) else if (Sender = ImgNordeste) then CriaForm(TF_Nordeste) else if (Sender = ImgSul) then CriaForm(TF_Sul) else if (Sender = ImgSudeste) then CriaForm(TF_Sudeste); end; end. Antes de explicar esse procedimento deixa eu comentar porque criei uma nova declaração USES (note que na terceira linha da Unit - lá em cima) já tem um comando assim, este comando serve para identificar minhas unidades externas, antes da palavra chave IMPLEMENTATION assim que o formulário é gerado tudo é compilado e salvaguardado em áreas de memória prontos para serem utilizados, ou seja, a Unit Windows (se você reparar ela está lá em cima) e jogada para uma área de memória, mas em compensação a Unit fNorte (que criaremos posteriormente) não é armazenada. Assim eu estou preservando vários blocos de memória para serem utilizados apenas quando realmente forem necessários. Prontinho agora vamos explicar essa procedure linda e maravilhosa que foi montada de propósito para você entenda algumas artimanhas da linguagem Pascal, antes de fazê-la poderiamos simplesmente em
cada objeto TImage clicarmos no evento OnClick e para cada um colocarmos o seguinte código: (por exemplo para o objeto da Região Norte) begin F_Norte := TF_Norte.Create(Application); F_Norte.ShowModal; F_Norte.Free; end; Isso funcionaria perfeitamente bem mas como são cinco objetos precisariamos repetir isso cinco vezes (imagine se fossem uns 20 ou 30), e isso já não é tão bom assim em Pascal. Outra coisa que poderiamos fazer é, criamos um procedimento particular (lá no Private) para todas os outros procedimentos então ficaria assim: private procedure CriaForm(aFormClass: TFormClass); public . . . // Depois do comando uses procedure TF_Mapa.CriaForm(aFormClass: TFormClass); begin with aFormClass.Create(Application) do try ShowModal; finally Free; end; end; e em cada objeto TImage clicarmos no evento OnClick e para cada um colocarmos o seguinte código: (por exemplo para o objeto da Região Norte) begin CriaForm(TF_Norte); end; Isso também funcionaria perfeitamente bem mas como são cinco objetos precisariamos repetir isso cinco vezes (imagine novamente se fossem uns 20 ou 30), mas agora o pior que e serão vários procedimentos que teremos que olhar caso dê algum erro e isso já não é tão bom assim em Pascal. Então resolvi fazer da maneira como eu coloquei. Criei um único procedimento ChamaRegiao que receberá uma variável do tipo TObject (lembra da apostila anterior ? É o objeto que chama o procedimento) e para este procedimento coloquei um outro procedimento interno, chamado CriaForm. Para ativar todo o conjunto aperte novamente a tecla F12 (para mostrar o formulário) e dê um clique simples sobre o objeto ImgNorte aperte a tecla F11 (para chamar a Object Inspector), vá para a página de eventos e para o evento OnClick, selecione atraves do Combo (aquela setinha apontada para baixo) o procedimento ChamaRegiao. Repita os mesmos passos com as outras imagens das outras regiões. Este formulário já está pronto, vamos agora ver o que acontece com cada região. (Obs. Não adianta tentar rodar que ele deve acusar erro que as outras unidades ainda não existem.
Primeira Região Apenas para guiá-los mostrarei como criar o mapa da Região Sul (só tem três estados e não deve me dar muito trabalho :)) você deverá criar os formulários para as outras regiões. Observe que é quase tudo igual ao primeiro formulário criado. A partir do Menu Principal clique em File | New Form e será disponibilizado um novo formulário, vamos aos passos: 12. Na Component Pallete localize uma página chamada Additional e dentro dessa página de um clique no objeto Image (acredito que seja o sexto) e dê um clique no Form. (automaticamente o Delphi criou um quadrado quadriculado que representa o objeto Image1). 13. Olhe na Object Inspector e verifique as propriedades do objeto Image1 criado, e altere as seguintes propriedades: 13.1. AutoSize: True (Fará com que o tamanho do objeto fique automaticamente do tamanho da figura selecionada) 13.2. Picture: Clique nos "..." e localize o arquivo SUL.BMP enviado (Seleciona determinada figura) 14. Vá na Object Inspector e localize o objeto Form1 (basta clicar no Combo Box para selecioná-lo), e altere as seguintes propriedades: 14.1. BorderStyle: bsDialog (Fará com que a janela fique no formato padrão de uma janela de mensagens) 14.2. Caption: Estados da Região Sul (Conteúdo da tarja do formulário) 14.3. Name: F_Sul (Nome interno do formulário) 14.4. Position: poScreenCenter (Fará com que o formulário fique sempre centralizado quando for executado) 15. Dê uma salvadinha no seu projeto, para tanto, no menu vá em File | Save All...: 15.1. Aonde aparece Unit1.pas (o Delphi está se referindo do nome do formulário) mude para fSul.PAS 16. Na Component Pallete localize uma página chamada Standard e dentro dessa página localize o objeto Label (acredito que seja o terceiro) clique no objeto e dê um clique no Form e altere as seguintes propriedades: 16.1. Font: Clique nos "..." e faça as seguintes alteções na janela de Fonts: 6.11. Cor: Castanho 6.12. Estilo: Negrito 16.2. Caption: Clique sobre o Estado a consultar (Conteúdo que será mostrado) 17. Na Component Pallete localize uma página chamada Additional e dentro dessa página localize o objeto Image (acredito que seja o sexto) pressione a tecla SHIFT e clique no objeto (deve ter ficado um quadriculado azul em volta do objeto, como se ficasse marcado) e dê cinco cliques no Form - de preferência um em cada região, e altere as propriedades Name e Hint de cada um para, respectivamente: Name ImgPR ImgSC ImgRS
- Hint - Descreve o estado do Paraná - Descreve o estado de Santa Catarina - Descreve o estado do Rio Grande do Sul
18. (Praticando o polimorfismo novamente) Clique no objeto ImgPR segure a tecla SHIFT e clique em
ImgSC e ImgRS, altere agora a propriedade ShowHint para True e Cursor para crHandPoint. 19. Quando terminar clique em qualquer região do formulário para desmarcar os objetos. 20. Para terminar nosso primeiro formulário desse projeto vá para a Component Pallete localize uma página chamada Additional e dentro dessa página localize o objeto BitBtn (acredito que seja o primeiro) clique no objeto e dê um clique no Form e altere as seguintes propriedades: 20.1. Kind: bkClose, isso fez com que três importantes propriedades se alterassem: 20.2. Caption: &Fechar (apenas para "aportuguesar"o nosso aplicativo). 21. Dê uma comparadinha no desenho para ver como ficou:
Agora cabe a você criar mais quatro formulários, são eles respectivamente: Nome Interno F_Norte F_Nordeste F_Centro F_Sudeste
Nome Externo Figura a usar fNorte NORTE.BMP fNordeste NORDESTE.BMP fCentro CENTRO.BMP fSudeste SUDESTE.BMP
☞
Importante - Chamei de Nome Interno a propriedade Name dos formulários e Nome Externo como será o nome que você deve salvar cada formulário. Note que a única diferença entre eles está num simples apostrofe "_", isso facilita muito quando queremos lembrar o nome que precisamos utilizar.
☞
Importante - Infelizmente com o Delphi não existe outro componente mais poligonal que o tImage, mas tem uma notícia boa o Delphi respeitará o objeto tImage criado por último, então você pode colocar uns sobre os outros. Comigo aqui acabei conseguindo montar com uma exatidão fora do normal, até eu me assustei. Uma Dica: Para a região Centro-Oeste crie primeiro o Objeto do estado de Goiás e dentro dele coloque o objeto do estado do Distrito Federal.
Tirando os formulários do Auto-Create
O Delphi cria automaticamente todos os formulários que utilizamos, mas isso gera um tanto de prejuízo as áreas de memória (é óbvio que um projeto com 7 ou até 10 não é um caso sério, mas um projeto com 50 ou 70 já começa a dar uns erros muito estranhos) então lembra-se do procedimento CriaForm ele vai exatamente criar os nosso formulários para utilizarmos e depois destruí-los. Mas precisamos dizer para o Delphi que não queremos que ele faça o serviço de Auto-Create, para tanto vá (a partir do menu principal) em View | Project Manager, esta janelinha é a que controla todas as unidades do seu projeto. Clique no botão Options. Selecione a página Forms lá você verá dois objetos ListBox, do lado esquerdo são os Auto-Create Forms e do lado direito estão os Available forms ou simplesmente formulários disponíveis. Então selecione os formulários: F_Norte, F_Nordeste, F_Centro, F_Sudeste e F_Sul e clique no botão com o sinal > isso fará com que eles sejam despachados para o outro lado. Não faça o procedimento com o F_Mapa, ele é o nosso Menu e ele precisa realmente ser criado automaticamente assim que o usuário iniciar o processo. Prontinho, agora execute o projeto e veja como ele está ficando.
Finalmente Existem várias maneiras de se mostrar o estado escolhido mas a que eu achei mais interessante utiliza o QuickReport (que vem com o Delphi) para fazer o serviço. Mas faremos isto apenas na próxima apostila.
3 Curso de Delphi 4.0 - Apostila 3 Autor: Fernando Antonio F. Anselmo eMail:
[email protected] Pré-Requisitos: • • • •
Windows 98 Delphi 4.0 versão Client/Server Suite BDE 5.00 MS-Access 97
Arquivos trabalhados juntos com esta apostila: •
BASICO.MDB
Prefácio Salve, na última apostila começamos a montar nosso pequeno mapa eletrônico, agora vamos concluílo. Antes de recomeçarmos precisamos entender como funciona a conexão entre o Delphi e o Banco de Dados. Isto é realizado através de um conjunto de bibliotecas que a Inprise chamou de BDE (Borland DataBase Engine) ela trabalha assim como um ODBC de ligação, mas com a grande vantagem que para determinados bancos o acesso é totalmente nativo, isso significa que a conversa entre sua Aplicação e o Banco não recebe interferencias externas a não ser do BDE (mas isso até o antigo Clipper precisava de suas ligações para seus acessos com os bancos xBase). Ilustradamente o acesso funciona da seguinte maneira:
A coisa acontece da seguinte forma, a sua aplicação através dos objetos contidos na Component Pallete (localizado na parte superior direita) e na página chamada Data Access estão todos os objetos que fazem esta primeira conexão entre o Aplicativo e o BDE e este se comunica com o Banco de Dados.
☞Importante - Note que eu não especifiquei qual o Banco de Dados, então salvaguardando algumas regras do próprio banco (tais como o nome das tabelas, formas de SQL) poderemos utilizar para nossa aplicação qualquer banco que acharmos mais fácil de manipularmos (tais como dBase, Access, Paradox...) e ao final (antes de entregar a aplicação para o usuário) fazermos um último teste com o banco de dados escolhido por ele (Oracle, SQL Server, Interbase, Sybase...) para isso não precisaremos modificar uma única linha de código do nosso aplicativo.
☞Importante - A conexão com o MS-Access funciona da seguinte forma: Entre o BDE e o Banco de Dados existe um aplicativo a mais de conexão, chamado DAO, a sigla significa Data Access Objects, é um conjunto de bibliotecas para o desenvolvimento com o banco de dados MS-Access, e pertence a Microsoft, para ter o direito de uso e distribuição do produto você deve adquirir quaisquer das ferramentas de desenvolvimento da Microsoft.
Iniciando na Prática
Bem se você ainda não fez, aconselho que você dê uma olhada no apêndice identificado por CONEXAO e faça as alterações sugeridas nele. Junto com essa apostila você está recebendo um banco de dados (formato MS-Access 97). Para padronizar vamos criar uma pasta com o nome CursoDelphi e dentro dela criaremos uma nova pasta chamada Federação coloque dentro desta tudo que você recebeu. Graficamente então temos:
Abra agora o aplicativo BDE Administrator e crie um Alias para o banco de dados enviado. Se você não sabe como fazer vou dar uma canja siga os passos abaixo: 1. A partir do BDE Administrator aberto vá em Object | New... (ou simplesmente CTRL+N) e modifique a janelinha que aparece para:
e pressione a tecla OK. 2. Mude o nome do seu novo alias para AlFedera
☞Importante - Apesar de ser permitido não coloque acentos no seu Alias e procure não ultrapassar os oito caracteres isso além de manter a compatibilidade entre o Delphi 32 Bits e o Delphi 16 Bits também evita uma série de confusões. 3. Altere a propriedade DATABASE NAME para C:\CursoDelphi\Federação\basico.mdb e confirme as alterações em Object | Apply (ou simplesmente CTRL+A, ou ainda clique no quarto botão da barra de ferramentas) 4. Teste seu novo alias clicando em Object | Open (ou simplesmente clique no primeiro botão da barra de ferramentas) seu alias deve formar um quadradinho luminoso em volta do objeto, conforme a figura a seguir: 5. Feche-o em em Object | Close (ou simplesmente clique novamente no primeiro botão da barra de ferramentas) Se você está confuso com tudo isso não fique retorne aquela figura inicial sobre a conexão, pode-se dizer que estamos exatamente criando o quadradinho do BDE. O Alias é simplesmente uma conexão que se fará entre seu Aplicativo e o Banco de Dados
Trabalhando com o TDatabase Antes de começarmos abra novamente o seu projeto, para isso a partir do Menu Principal clique em File | Open localize o arquivo Mapa.DPR. No formulário F_Mapa e coloque um objeto DataBase (que se encontra na Component Pallete na página Data Access) e altere as seguintes propriedades:
AliasName para AlFedera (aquele que foi criado na apostila anterior) DataBaseName para dnFedera (nome da base de dados) Name para nmFedera Este objeto é o que fará a segunda conexão com o nosso banco de dados, para lembrar a vocês: 1a. Conexão: Entre o Banco de Dados e o Alias 2a. Conexão: Entre o Alias e o objeto tDataBase 3a. Conexão: Entre o objeto tDataBase e os objetos DB (tTable, tQuery, tStoreProc) 4a. Conexão: Entre os objetos DB com os objetos que o usuário utilizará (todos os que estão na página DataControls e alguns outros). Se você quer simular como será essa segunda conexão, altere a propriedade Connected do objeto para true e será mostrada a seguinte janela:
Clique no botao Ok e prontinho seu banco estará conectado, mas vamos evitar que essa janelinha apareça quando o usuário for usar nosso aplicativo, antes volte a propriedade Connected do objeto para false, na página de eventos de um duplo clique no evento OnLogin e vamos as alterações: procedure TF_Mapa.nmFederaLogin(Database: TDatabase; LoginParams: TStrings); begin LoginParams.Values['USER NAME'] := ''; LoginParams.Values['PASSWORD'] := ''; end; Agora precisamos simular as alterações de Conexão para tanto, chame o objeto F_Mapa, e dê um duplo clique no evento OnShow para abrirmos esta conexão: procedure TF_Mapa.FormShow(Sender: TObject); begin nmFedera.Connected := True; end; Para fechar a conexão quando terminar nosso sistema. dê um duplo clique no evento OnClose: procedure TF_Mapa.FormClose(Sender: TObject; var Action: TCloseAction); begin nmFedera.Connected := False; end;
☞Importante - Aqui executaremos mais um termo da Orientação a Objetos (lembram-se do POLIMORFISMO), o termo é AÇÃO, isso significa que um evento qualquer é disparado quando outro
evento é acionado, ou seja é como um efeito cascata. O que acontece aqui é que quando o usuário executar o sistema esse disparará o evento OnShow do formulário e este disparará o evento OnLogin do objeto TDataBase.
Sobre o Quick Report O Quick Report é o gerador oficial do Delphi, deixa eu abrir aqui um pequeno parenteses, quando surgiu o Delphi, era uma das melhores ferramentas RAD para se trabalhar com bancos de dados, perfeito até hoje na construção e desenvolvimento de softwares, mas como todo paraíso tem seu inferno, o Delphi também tinha o seu, a geração de relatórios, na época do Delphi 1.0 a ferramenta para gerá-los era o Report Smith, mas era claro que ele não dava conta do recado por diversos motivos, entre eles destacam-se: - Era preciso carregar um Run-Time do Report Smith juntamente com o projeto - Os relatórios ficavam separados do executável principal - Relatórios muito complexos eram uma Via-Crucis fazê-los - Relatórios muito simples demoravam uma eternidade para rodá-los Então os Delphianos da época procuravam alternativas, entre elas aqui vale destacar: - Report Crystal - Report Builder - Biblioteca Printers (do próprio Delphi) Esta última deu origem a vários geradores de relatórios e o principal surgido foi o Quick Report que se tornou um mero coadjuvante do Delphi 2.0 fazendo parceria com o Report Smith e em pouco tempo tornou-se óbvio que o Quick era muito superior ao Smith tanto que a partir da versão 3.0 resolveu-se não mais distribuir o Report Smith tornando o Quick o gerador oficial do Delphi. Não pretendo dizer aqui que o Quick é o melhor gerador de relatórios que existe para o Delphi, acredito sempre que a melhor ferramenta é aquela que você domina e conhece, em listas de discussão é comum você ver coisas como: - O Quick é ruim - É difícil de construir algo nele - Relatórios complicados são impossíveis fazê-los - entre milhares de outras coisas Aí, todos colocam milhares de substitutos, mas veja bem, a própria Inprise abriu mão de um gerador dela (caso do Report Smith) para trocar por um de uma empresa de terceiro (QuSoft AS). Será que isso tudo foi porque o Quick é ruim ? Acho que muitas vezes quando não conhecemos ou tentamos aprender uma ferramenta, acabamos não fazendo o essencial que é ver primeiro como a ferramenta trabalha, o Quick é um gerador de relatórios totalmente orientado a objetos, e isso não é muito fácil de assimilarmos. Então para ajudá-los sempre tentarei utilizá-lo como uma ferramenta não só para gerar relatórios, mas também para: - Formulários de Consultas - Importações em .TXT e .HTML - Relatórios Analíticos - Fichas de Caixa, Balancetes e Outros. Vocês verão que esse terrível monstro horroroso de duzentas cabeças (que cada dia cresce uma) na verdade não passa de um horroroso monstro terrível de duzentas e uma cabeças. Bem vamos deixar de ladainha e começar a trabalhar.
Construindo o formulário para uma região genérica
Não pretendo aqui construir um formulário para cada região (teve gente que suspirou de alívio), mas sim um único que servirá para qualquer região que o nosso usuário clicar. Vamos aos passos: 1. A partir do Menu Principal clique em File | New Form e será disponibilizado um novo formulário e altere logo a propriedade name para F_Estado. 2. Dê logo uma salvadinha no seu projeto, para tanto, no menu vá em File | Save All...: 2.1. Aonde aparece Unit1.pas (o Delphi está se referindo do nome do formulário) mude para fEstado.PAS 3. Na Component Pallete ache uma página entitulada QReport nela estão todos os objetos utilizados pelo Quick, localize o objeto chamado QuickRep, clique nele e em seguida click no formulário.
☞
Importante - Foi criado nesse momento nossa área de trabalho, o Quick 1.0 (distribuído com o Delphi 2.0) não criava esta área branca que vc está vendo, ele se resumia a apenas alargar as proporções do formulário (propriedade Width e Height) para o tamanho de uma página da impressora. 4. Vamos para a Object Inspector e altere a propriedade Name para QrEstado
☞
Importante - Qualquer gerador de relatório trabalha por seções, pois nossos (e qualquer) relatórios tem essas seções, são elas: Cabeçalho, Título da Página, Rodapé da Página, Página Inicial, Última Página, Linhas Detalhes, e assim vai, vamos criar essas seções, o Quick as chama de Bandas. 5. Na Component Pallete na página QReport, localize o objeto chamado QrBand, clique nele e em seguida click dentro do objeto do QrEstado criado anteriormente. 6. Vamos para a Object Inspector e altere as seguintes propriedades: 6.1. Name para BdCabPagina 6.2. BandType para rbPageHeader - Essa é a propriedade que controla os tipos das seções no caso escolhemos uma Banda de Cabeçalho de Página, ela aparecerá em todas as páginas. Dentro do Quick devemos usar os objetos do Quick (isso parece óbvio mas muita gente esquece disso) o correspondente ao objeto Label do Delphi que mostra um texto fixo no Quick é o QrLabel. 7. Na Component Pallete na página QReport, localize o objeto chamado QrLabel, clique nele e em seguida click dentro do objeto da objeto BdCabPagina criado anteriormente . 8. Vamos para a Object Inspector e altere as seguintes propriedades: 8.1. Name para lbTitulo 8.2. Alignment para taCenter (alinhamento centralizado) 8.3. AlignToBand para True - Isso fará com o que foi definido na propriedade Alignment seja estendido para a banda (Então o QrLabel se alinhará centralizado dentro da banda)
8.4. Font: Clique nos "..." e faça as seguintes alteções na janela de Fonts: 8.41. Cor: Azul-Marinho 8.42. Estilo: Negrito 8.43. Tamanho: 16 8.44. Fonte: Times New Roman 8.5. Caption para Estado do Brasil 9. Na Component Pallete na página QReport, localize o objeto chamado QrBand, clique nele e em seguida click dentro do objeto do QrEstado (não é dentro daquela primeira banda criada). 10. Vamos para a Object Inspector e altere as seguintes propriedades: 10.1. Name para BdDetalhe 10.2. BandType para rbDetail - Essa é a propriedade que controla os tipos das seções no caso escolhemos uma Banda de Detalhe, ela será replicada a cada registro e dê uma esticadinha para baixo nela, aumentando o tamanho (ou a propriedade Height) 11. Agora eu vou precisar dentro desta banda de seis (6) objetos QrLabel (é só apertar o objeto enquanto você segura a tecla SHIFT - O objeto vai ficar com a marcação azul e dê seis click's) dentro do objeto BdDetalhe, agora altere a propriedade Caption de cada um respectivamente: Sigla: Nome: Capital: Núm.Município: Região: Descrição: 12. Agora marque todos os seis objetos (lembra-se) e aproveitando o Polimorfismo altere a propriedade Font, clique nos "..." e faça as seguintes alteções na janela de Fonts: 12.1. Cor: Castanho 12.2. Estilo: Negrito 12.3. Fonte: Times New Roman 13. Continue com os objetos marcados e a partir do menu principal vá em View | Alignment Palette será mostrada a seguinte janela:
Clique então no último botão da primeira linha. Todos eles serão organizados à direita.
☞Importante - Vamos a uma rapidinha sobre os alinhamentos, isso só serve para dois ou mais objetos marcados: Primeira Linha: à esquerda, centraliza verticalmente, tamanho vertical, espaçamento vertical e à direita. Segunda Linha: Superior, centraliza horizontalmente, tamanho horizontal, espaçamento horizontal e inferior 14. Faremos agora a 3a. Conexão. Vamos para a página Data Access e localize o objeto Query. Click nele e clique dentro do formulário e altere as seguinte propriedades: 14.1. DataBaseName para dnFedera (isto só aparecerá se o formulário F_Mapa estiver aberto) 14.2. SQL, clique nos "..." e faça escreva:
select * from Federacao
14.3. Name para QryEstado
☞
Importante - Se você não conhece SQL (Structure Query Language) aconselho que você compre um bom livro, ou veja a apostila referente aos comandos básicos. 15. Está é a 4a. Conexão. Voltemos para a página QReport e localize o objeto QrDBText, precisaremos de seis (6) objetos dentro do objeto BdDetalhe 16. Agora marque todos os seis objetos e aproveitando o Polimorfismo altere as seguintes propriedades: 16.1. Font, clique nos "..." e faça as seguintes alteções na janela de Fonts: 16.11. Cor: Azul 16.13. Fonte: Times New Roman 16.2. DataSet para QryEstado 17. Marque agora cada objeto e altere a propriedade DataField de cada um respectivamente: SIG_UF NOM_ESTADO NOM_CAPITAL NUM_MUNICIPIO NOM_REGIAO DES_REGIAO 18. Uma das principais facilidades do Quick é quanto a campos Memo (como é o caso do campo DES_REGIAO) altere as seguintes propriedades (do objeto QRDBText6 - marcado com a propriedade DataField em DES_REGIAO) 18.1. AutoSize para False (cancela o esticamento automatico horizontal) 18.2. AutoStretch para True (permite que o objeto se estique verticalmente) 18.3. WordWrap para True (só para confirmar - permite que o objeto quebre as linhas) 19. Agora estique esse objeto até o final, acredito que a propriedade Width deve ficar em torno de 625 20. Vamos conectar o objeto QrEstado (TQuickRep) com o objeto QryEstado (TQuery), para tanto localize o objeto QrEstado e altere a propriedade DataSet para QryEstado. Está pronto, compare como ficou:
☞
Importante - Uma enorme vantagem do Quick é você poder ver como fica seu relatório final mesmo sem precisar rodar o sistema, para tanto faça o seguinte: 1. No objeto QryEstado altere a propriedade Active para True. 2. Clique no objeto QrEstado e em seguida clique com o botão direito e será mostrado um menu e dentro dele clique em Preview. 3. Novamente no objeto QryEstado altere a propriedade Active para False.
Codificando a Primeira Região Apenas para guiá-los mostrarei como criar os códigos do mapa da Região Sul você deverá criar os códigos para as outras regiões. Observe que novamente é quase tudo igual. Abra o formulário F_SUL e aperte a tecla F12 até que você tenha a janela da Code Editor aberta e localize para mim as seguintes linhas: ImgSC: TImage; ImgRS: TImage; private Inclua a seguinte chamada a um procedimento antes da parte private: ImgSC: TImage; ImgRS: TImage; procedure MostraEstado(Sender: TObject); private Agora localize a linha: implementation {$R *.DFM}
end. E faça as seguintes alterações: implementation {$R *.DFM} uses fEstado;
// Mostra o Estado
procedure TF_Sul.MostraEstado(Sender: TObject); procedure Mostra(Estado: String); begin F_Estado := TF_Estado.Create(Application); with F_Estado do begin with QryEstado do begin SQL.Clear; SQL.Add('SELECT * FROM FEDERACAO WHERE (SIG_UF = ''' + Estado + ''')'); // Atenção é tudo aspas simples Open; end; QrEstado.Preview; QryEstado.Close; Free; end; end; begin if (Sender = ImgPR) then Mostra('PR') else if (Sender = ImgSC) then Mostra('SC') else if (Sender = ImgRS) then Mostra('RS'); end; end. Prontinho veja que o procedimento que eu construí aqui é igualzinho ao do F_Mapa, óbvio salvo alguns comandos. Criei um único procedimento MostraEstado que receberá uma variável do tipo TObject e para este procedimento coloquei um outro procedimento interno, chamado Mostra que realizará os seguintes passos: 1. Criação do Formulário F_Estado; 2. Organização do SQL para o estado selecionado criando a Query; 3. Mostra na tela do relatório (note que não preciso do comando SHOWMODAL do formulário, e sim PREVIEW do objeto QuickRep); 4. Fecha a Query; e 5. Eliminação do F_Estado da memória. Para ativar todo o conjunto aperte novamente a tecla F12 (para mostrar o formulário) e dê um clique simples sobre o objeto ImgPR aperte a tecla F11 (para chamar a Object Inspector), vá para a página de eventos e para o evento OnClick, selecione atraves do Combo (aquela setinha apontada para baixo) o procedimento MostraEstado. Repita os mesmos passos com as outras imagens dos outros estados.
☞Importante - No comando SQL.Add('SELECT * FROM FEDERACAO WHERE (SIG_UF = ''' +
Estado + ''')'); esses três plicks ( ''' ) é tudo simples, nenhum é aspas duplas ( " ). Pois dentro de uma string cada dois plicks simples ( '' ) conseguimos um plicks ( ' ), confuso né, mas veja só, se fizermos: VariavelString := 'Nome : Nando'; A VariavelString terá em seu conteúdo o valor Nome : Nando, agora se fizermos: VariavelString := 'Nome : ''Nando'''; A VariavelString terá em seu conteúdo o valor Nome : 'Nando'. Eu apenas acrescentei mais dois plicks simples entre a palavra Nando.
Tirando o formulário F_Estado do Auto-Create Vá (a partir do menu principal) em View | Project Manager. Clique no botão Options. Selecione a página Forms lá você verá dois objetos ListBox, do lado esquerdo são os Auto-Create Forms e do lado direito estão os Available forms ou simplesmente formulários disponíveis. Então selecione os formulários: F_Estado e clique no botão com o sinal > e despache-o para o lado aonde estão os outros isolando novamente o nosso Menu pois lembrando que ele precisa ser criado automaticamente assim que o usuário iniciar o processo. Prontinho, agora execute o projeto e bom divertimento com seu mapa eletrônico. Na próxima aprenderemos como distribuí-lo e gerar alguns macetes para otimização.
Finalmente Agora precisamos arrumar, empacotar e distribuir nosso projeto, mas isto só será feito na próxima apostila.
4 Curso de Delphi 4.0 - Apostila 4 Autor: Fernando Antonio F. Anselmo eMail:
[email protected] Pré-Requisitos: • • • •
Windows 98 Delphi 4.0 versão Client/Server Suite BDE 5.00 MS-Access 97
Arquivos trabalhados juntos com esta apostila: • • • • • •
GEOGRAPH.ICO SETUP1.BMP SETUP2.BMP SETUP3.BMP SPLASH.BMP LOGO.BMP
Prefácio Salve, na última apostila montamos nosso segundo aplicativo o Mapa Eletrônico, o interessante é com ele é que calmamente começamos a desvendar os segredos do trabalho com o Delphi associado a Bancos de Dados, repararam como a maior parte dos livros evita em falar sobre o assunto ? O máximo com um aplicativo que arranha a superfície deste fantástico mundo. O problema é que o assunto é muito mais do que se pode imaginar, pois o Delphi tem milhares de possibilidades para realizar esta tarefa. O maior problema com o Delphi (depois de entendê-lo) é como distribuir seus aplicativos gerados, quando ele é independente de tratamento de banco de dados, tudo bem é só mandar o executável (.EXE) mas o problema começa quando ele utiliza o BDE, aí a coisa complica um pouco, mas acredito que após essa parte você começará a dominar uma importante ferramenta de distribuição para seus aplicativos.
Preparando o sistema para o Empacotamento Antes de gerarmos nossos discos de instalação vamos fazer algumas alterações no projeto então abra novamente o seu projeto, para isso a partir do Menu Principal clique em File | Open localize o arquivo Mapa.DPR. Agora, a partir do Menu Principal, clique em Project | Options e vamos realizar dois serviços aqui: 1. Na página Application coloque o Título do nosso projeto (Mapa Eletrônico) e localize o ícone enviado (Geograph.ico). 2. Na página Compiler desmarque todas as opções dos grupos Debugging e Messages e clique no botão OK. Novamente a partir do Menu Principal, clique em Project | Build All para gerarmos o executável final, prontinho agora feche o Delphi confirmando as modificações realizadas no projeto.
Utilizando o Install Shield No Delphi 1.0 para distribuir o BDE era uma complicação, existia um diretório no CD do Delphi chamado REDIST, nele estava (dividido para caber em disquetes de 1.44 Mb) o BDE. Ou seja, você se deslocava até a máquina do seu Cliente (que iria instalar o sistema) criava um diretório, colocava o executável, as tabelas, e instalava o BDE, depois criava o alias, testava e pronto estava instalado. Com um certo tempo as pessoas aprenderam a gerar o Alias automático. Mas ainda assim era um tanto primitivo, principalmente quando você precisava mandar tudo para que o próprio cliente instalasse. Com o Delphi 2.0 surgiu o InstallShield que foi mais aprimorado ainda nessa versão, ele é um produto da Stirling Technologies. Que acompanha também o Delphi 3.0 e o Delphi 4.0. Um aviso, não tente utilizar o InstallShield que vem com o Delphi 2.0 para aplicações do Delphi 3.0 ou 4.0, nem vice-versa, apesar de todos serem de 32 Bits são de versões totalmente diferentes. O InstallShield não é que nem o Quick Report, você precisa instalá-lo em separado (ele vem no próprio CD do Delphi), após sua instalação e execução, você acabará com a seguinte janela:
Esta é a tela inicial para a criação do seu projeto .IWZ, informe o nome do projeto, o tipo (no caso de versões registradas) e o diretório que será criado, após isso aperte o botão Create e iremos para a janela de construção do projeto:
Esta tela foi dividida em nove grandes grupos, para explicar melhor vamos analizar grupo a grupo enquanto fazemos as alterações para a geração do nosso pacote.
1. Set the Visual Design Neste grupo estão as informações iniciais do instalador: Na primeira parte (Application Information) você deve informar o nome da aplicação (mapa), localizar o executável que deverá ser instalado (C:\...\Mapa.EXE), a versão (1.0) e o nome da sua empresa (Curso). Note que nesta parte é montado o Diretório que será instalado o sistema final (
\Curso\Mapa). Na segunda parte (Main Window) é a tela principal da instalação, aqui você escolherá o título principal (Mapa Eletrônico), o Logotipo da sua Empresa (localize o BitMap Enviado: Logo.BMP), a posição em que o logotipo ficará (Top Right - Em cima a direita) e a cor de fundo (Dithered Blue - degradê em azul). Na terceira parte (Features) preste muita atenção que este é o momento mais difícil, aqui você escolherá se o usuário pode ou não desinstalar automaticamente o projeto. Prontinho pode dar OK.
☞Importante - Assim como o Logo.BMP você notará que no decorrer dessa montagem colocaremos vários Bitmap's, você mesmo poderá gerá-los mas lembre-se que o InstallShield aceita apenas imagens com no máximo 16 cores.
2. Select InstallShield Objects for Delphi Esta é o grupo que mais confunde as pessoas, mas com um pouquinho de atenção a gente chega lá, aqui você definirá qual tipo de BDE será instalado, o tipo do SQL Links ou se deseja carregar qualquer dos pacotes de objetos do Delphi. Na primeira parte (General) são as informações principais, marque o BDE, (Observação: O SQL
Links, serve apenas para conexão com bancos do tipo MS-SQL, SyBase padrão DB-Lib, InterBase, Oracle, Informix, DB2 e SyBase padrão CT-Lib e os pacotes de objetos servem apenas para o caso de compilações parciais), clique no botão Settings... BDE Instalation Type - Aqui você define seu tipo de banco de dados, infelizmente o Install não possui permissão para a distribuição da DAO 3.5, que é a responsável pela conexão nativa com o MS-Access, ista permissão é adquirida apenas com a compra de qualquer ferramenta de desenvolvimento Microsoft, teremos então que colocar na mão todos os arquivos necessários, marque Partial BDE Installation e clique no botão Avançar. BDE Driver Types - não escolha nenhum, deixe todos desmarcados. Query Engine Types - Marque a opção SQL Engine isto fará com que o BDE reconheça e envie para o gerenciados de banco de dados os comandos de SQL e clique no botão Avançar. BDE Alias - Step 1 of 4 - Clique no botão New e informe o nome do nosso Alias (AlFedera) BDE Alias - Step 2 of 4 - Esta e a tela mais enigmática do Install, nela você deve informar se quer que seu BDE seja configurado para aplicações Win16/Win32 ou somente Win32, mas aqui ele não se refere a possibilidade de instalação para Windows 3.x ele apenas está se referindo ao .CFG salvo (que é o arquivo de configuração do BDE 32, então deixe desmarcado e sigamos em frente. BDE Alias - Step 3 of 4 - Aqui está todo o pulo do gato sobre a construção do BDE, em Alias Name ele mostrará o Nome do seu alias, em Path é o local que seu banco deverá ser instalado, agora vamos pensar um pouquinho, mas se o usuário mudar o destino ? Aqui usaremos uma variável do Install, coloque: [Program Files]\ que será o diretório em que ficará sua aplicação. No Type selecione MSAccess. E finalmente escreva na lista de parâmetros opcionais para o Alias o seguinte: DATABASE NAME=[Program Files]\Basico.mdb BDE Alias - Step 4of 4 - Aqui você precisa apenas clicar no botão Concluir para finalizar todas as inclusões no BDE. Na segunda parte (Advanced) você verá todas as bibliotecas que serão instaladas, apenas clique no botão OK e vamos em frente.
3. Specify Components and Files Neste grupo você dirá o que o Install realmente levará no pacote: Na primeira parte (Group and Files) faça as seguintes inclusões: Na pasta Program Files aperte o botão Insert Files, localize e arraste o arquivo BASICO.MDB (clicando com o mouse sobre ele, segurando e levando) para dentro desta pasta. Na pasta BDE/IDAPI Files localize e arraste o arquivo IDDA3532.DLL, pode fechar o Windows Explorer. Vamos agora criar algumas pastas necessárias para a instalação do DAO, clique no botão Add Group e coloque as seguintes informações: Group Name: DAOSystem Destination Directory: <WINSYSDIR> Com o auxílio do botão Insert Files arraste os seguintes arquivos para esta pasta:
C:\Windows\System\MSJTER35.DLL C:\Windows\System\MSVCRT40.DLL C:\Windows\System\VBAJET32.DLL C:\Windows\System\OLEAUT32.DLL C:\Windows\System\ODBCJT32.DLL C:\Windows\System\ODBCTL32.DLL C:\Windows\System\MSJINT32.DLL C:\Windows\System\MSVCRT20.DLL C:\Windows\System\MSRD2X32.DLL C:\Windows\System\MFC40.DLL C:\Windows\System\ODBCINT.DLL C:\Windows\System\MSREPL35.DLL
C:\Windows\System\MSJINT35.DLL C:\Windows\System\MSJET35.DLL C:\Windows\System\VBAR332.DLL C:\Windows\System\STDOLE2.TLB C:\Windows\System\ODBCJI32.DLL C:\Windows\System\MSJT3032.DLL C:\Windows\System\VEN2232.OLB C:\Windows\System\MSWNG300.DLL C:\Windows\System\VBDB32.DLL C:\Windows\System\ODBC32.DLL C:\Windows\System\MSRD2X35.DLL
Group Name: DAO Destination Directory: \Microsoft Shared\DAO Com o auxílio do botão Launch Explorer arraste os seguintes arquivos para esta pasta: C:\Arquivos de Programas\Arquivos comuns\Microsoft Shared\DAO\DAO350.DLL C:\Arquivos de Programas\Arquivos comuns\Microsoft Shared\DAO\DAO2535.TLB C:\Arquivos de Programas\Arquivos comuns\Microsoft Shared\DAO\DAO2532.TLB C:\Arquivos de Programas\Arquivos comuns\Microsoft Shared\DAO\DAO3032.DLL Group Name: VBFiles Destination Directory: <WINSYSDIR> Com o auxílio do botão Launch Explorer arraste os seguintes arquivos para esta pasta: C:\Windows\System\OLEPRO32.DLL C:\Windows\System\CTL3D32.DLL C:\Windows\System\VBAR2232.DLL As próximas partes (Components e Setup Types) são utilizadas quando você estiver trabalhando com uma aplicação muito grande aonde existe a divisão em várias partes, você poderá dar também a chance do seu cliente instalar apenas determinadas partes que o interesse.
4. Select User Interface Components Este grupo é o que comandará a instalação propriamente dita, gerando a interface com o nosso cliente. Vamos tratá-lo com calma e parte a parte: Welcome Bitmap - Este é um bitmap de abertura, é a primeira janela que será mostrada após iniciado o programa de instalação. Marque a opções e clique na página Settings e localize o arquivo Splash.bmp enviado. Para o nosso caso deixe a opção marcada. Welcome Message - Esta é uma janela de boas-vindas com uma mensagem para o nosso cliente sobre o sistema, infelizmente ela é totalmente em inglês, só pode ser modificada na versão registrada do produto. Para o nosso caso desmarque a opção. Software Licence Agreement - Aqui esta a famosa janela da Licença de uso, ou se você prefere das regras de uso para o nosso aplicativo, você pode modificar o conteúdo criando um arquivo texto (formato .TXT) e o localizando através da página Settings, mas não poderá modificar as instruções em Inglês (apenas na versão registrada). Para o nosso caso desmarque a opção. Readme Information - Aqui será mostrado o arquivo LeiaMe inicial, novamente você pode modificar o conteúdo criando um arquivo texto (formato .TXT) e o localizando através da página Settings, mas não poderá modificar as instruções em Inglês (Apesar de que ela se reduz a um simples Information) se você quiser crie-o ou então desmarque a opção.
User Information - Aqui são informações do nosso cliente: seu nome, nome da empresa e o número de registro do nosso software. Para o nosso caso deixe a opção desmarcada. Choose Destination Location - Aqui é aonde nosso cliente poderá escolher qual o drive e a pasta que o sistema será instalado. (para o nosso caso ela será colocada em C:\Arquivo de Programas\Curso\Mapa). Como acertamos no BDE podemos deixá-la marcada para que o nosso cliente decida. Setup Type - Em casos de sistemas muito grandes é aqui que o cliente decidirá qual o modo que ele quer que seja instalado o sistema. Tudo, Compacto ou Customizado. Para o nosso caso deixe a opção desmarcada. Custom Setup - Esta é uma subdivisão da parte anterior aonde o cliente escolherá (a partir da opção Customizado da janela anterior, qual a parte que ele quer que seja instalada. Para o nosso caso deixe a opção desmarcada. Select Program Folder - Aqui aparecerá uma janela que permitirá alterar o nome do grupo que será criado no Windows para colocar nossos ícones do projeto. Para o nosso caso deixe a opção marcada. Start Copying Files - É aqui que o cliente vê todas as opções que ele escolheu anteriormente, podendo voltar atrás e modificar algo antes da instalação propriamente dita. Para o nosso caso deixe a opção marcada. Progress Indicator - Uma barra que acompanhará o processo de instalação mostrando ao cliente o quanto falta (em percentual) para a conclusão da instalação. Para o nosso caso deixe a opção marcada. Billboards - São cartazes que fazem a propaganda do nosso software ou de outros que produzimos, aqui é possível colocar um para cada mídia instalada, basta apenas nomeá-los em SETUP1.BMP, SETUP2.BMP e assim sucessivamente dependendo do número de discos que produzimos. Vá para a página Settings e localize o diretório dos bitmaps enviados (SETUP1.BMP, SETUP2.BMP e SETUP3.BMP). Para o nosso caso deixe a opção marcada. Online Registration - Muitas empresas processam o registros dos softwares de forma automática, bastando para isso que o cliente possua um Modem, para tanto na página Settings identifique o número identificador do sistema e o número do telefone ou então desmarque a opção. Setup Complete - Este é o último passo do processo, aqui você pode escolher se o cliente deve dar um Reboot na máquina (que é aconselhável), ou mostrar um arquivo Leiame final, bastando para isso alterar na página Settings, mas de qualquer forma deixe esta opção marcada. Clique no botão OK para finalizar
5. Make Registry Changes Esta página deve ser tratada com o carinho e o respeito que ela merece, pois aqui faremos as modificações na área de register do Windows, então calma e muito sangue frio aqui. Não queremos corromper essa área de registro do nosso cliente. Como modificamos a versão do DAO em nosso BDEAdmin para 3.5 também precisamos repetir essa operação na máquina que será instalado o nosso sistema. Na página Registry - Keys abra a chave HKEY_LOCAL_MACHINE e clique no botão Add Key... crie a chave SOFTWARE, clique nesta nova chave e vá repetindo a operação criando a seguinte estrutura:
HKEY_LOCAL_MACHINE\SOFTWARE\Borland\DataBase Engine\Settings\DRIVERS\MSACCESS\INIT
Deixe marcada a última chave INIT e clique na página Registry - Values e clique no botão Add Values e proceda as seguintes alterações:
Pronto, clique no botão OK. Agora crie a seguinte Chave na página Registry - Keys: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Shared Tools\DAO Crie o seguinte Valor para esta chave na página Registry - Values: Value Type: String Value Name: Path Value Data: \Microsoft Shared\DAO\Dao3032.dll Crie a seguinte Chave na página Registry - Keys: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Shared Tools\DAO35 Crie o seguinte Valor para esta chave na página Registry - Values: Value Type: String Value Name: Path Value Data: \Microsoft Shared\DAO\DAO350.DLL
6. Specify Folders and Icons Aqui será mostrado os Ícones (dos Arquivos) que serão instalados dentro do grupo escolhido, este grupo divide-se em: General - Aonde é possível adicionar novos ícones, lembre-se que antes eles devem ter sido colocados pelo grupo Specify Components and Files, tais como: Arquivos TXT - Readme iniciais, para o registro do aplicativo, entre outros. Arquivos HLP - Contendo um arquivo de auxílio para a aplicação. Advanced Settings - Aqui podemos modificar o destino dos nossos arquivos, o ícone, criamos uma tecla de atalho rápido para sua execução ou até mesmo iniciá-lo quando o Windows for iniciado.
☞Importante - Para o aplicativo iniciar assim que o Windows iniciar na página Advanced, existe uma caixinha para marcar que está escrito: Place Icon and Start Programs Menu.
7. Run Disk Builder Pronto, tudo foi informado e agora é o grande momento a geração do nosso pacote, escolha a midia que será gerado e clique no botão Build, espere o término do processo e veja em quantas mídias foram geradas o seu pacote.
☞Importante - Não se assuste com o número de disquetes (1.44Mb) normalmente apenas o BDE ocupa 2,5 disquetes então é comum sistemas darem de 3 ou superior. Contando que o DAO normalmente ocupa 3 Disquetes ou mais, calcule que seu sistema caberá em simples 7 disquetes.
☞Importante - Se você instalar o sistema a partir da rede escolha a opção CD-Rom pois aí será uma única mídia.
8. Test the Installation Aqui você pode testar como ficou seu pacote, acompanhando eventuais erros, mas o melhor mesmo é você colocá-lo em disquetes e levá-lo para uma máquina que não tenha o Delphi instalado.
☞
Importante - Gere seu pacote em disquetes de 1.44Mb e copie para os disquetes para proceder a instalação assim você poderá acompanhar a mudança das telas a cada disquete solicitado.
☞
Importante - Não se esqueça que depois, para removê-lo, você precisa ir em Painel de Controle | Adicionar ou Remover Programas para que o Install proceda a retirada das entradas nas áreas de registro do Windows.
9. Create Distribution Media Neste último grupo você poderá copiar totalmente, ou parcialmente, o seu pacote na mídia selecionada.
Finalmente
Agora você já pode mandar todo o seu projeto para aquele cliente especial, basta apenas embalá-lo e despachar com as famosas instruções:
Como Instalar O Mapa Eletrônico só pode ser consultado depois de instalado no seu Microcomputador, sob o ambiente Windows 95 ou superior. Para realizar a instalação siga essas instruções: 1. Ligue o Microcomputador ativando o Windows 2. Introduza o disquete marcado como INICIAL na unidade de leitura 3. Clique no botão INICIAR e escolha a opção EXECUTAR 4. Digite então A:\SETUP (ou no lugar do A, a letra equivalente ao drive da sua unidade de leitura do disquete). 5. Click sobre o botão OK e execute as instruções do Instalador. Acredito que seu usuário não errará esses 5 passos. Um abraço e até a próxima.
5 Curso de Delphi 4.0 - Apostila 5 Autor: Fernando Antonio F. Anselmo eMail: [email protected] Pré-Requisitos: • • • •
Windows 98 Delphi 4.0 versão Client/Server Suite BDE 5.00 MS-Access 97
Arquivos trabalhados juntos com esta apostila: •
SQL.WRI
Prefácio O nosso projeto para essa apostila será um tanto bobinho, mas é uma imensa mão na roda para testarmos nossos aplicativos futuramente, noto que a maioria das pessoas quando começam a programar em Delphi, temem o maior de todos os pesadelos: o SQL (Structured Query Language), são apenas três letrinhas mas que confundem e complicam a vida da maioria dos programadores, um conselho dominando essa simples (porém complexa) linguagem, garanto que será a diferença entre um sistema que apresentará facilidades imensas e dará poderes extraordinários para o nosso usuário, basicamente a linguagem SQL contém 4 comandos: - SELECT - INSERT - UPDATE - DELETE Na apostila em anexo, enviada junto com esta, explica-se exatamente a função de cada comando, aqui vamos nos ater ao Delphi, então vamos começar mais um projeto
Projeto 3 - Construtor de SQL Bem, agora que estamos familiarizados com o ambiente SQL (espero que você tenha lido a apostila em anexo antes de começarmos), vamos para as nossas receitas de bolo, siga um passo atrás do outro, mas antes de começar crie uma pasta que abrigará seu projeto, por exemplo Gera SQL. 1. Na Component Pallete localize uma página chamada Standard e dentro dessa página de um clique no objeto ListBox (acredito que seja o nono) e dê um clique no Form. Olhe na Object Inspector e altere a propriedade Name para ListaAlias. 2. Pegue outro objeto ListBox e dê um clique no Form e altere a propriedade Name para ListaTabela e altere a propriedade sorted para True isto fará a ordenação alfabetica dos nomes da lista. 3. Vá na Object Inspector e localize o objeto Form1 (basta clicar no Combo Box para selecioná-lo), e altere as seguintes propriedades: 3.1. BorderStyle: bsDialog (Fará com que a janela fique no formato padrão de uma janela de mensagens)
3.2. Caption: Executa instruções SQL (Conteúdo da tarja do formulário) 3.3. Name: F_SQL (Nome interno do formulário) 3.4. Position: poScreenCenter (Fará com que o formulário fique sempre centralizado quando for executado) 4. Dê uma salvadinha no seu projeto, para tanto, no menu vá em File | Save All...: 4.1. Aonde aparece Unit1.pas (o Delphi está se referindo do nome do formulário) mude para fSQL.PAS 4.2. Aonde aparece Project1.dpr (o Delphi está se referindo do nome do projeto - que será o nome do executável final) mude para GerSQL.DPR 5. Na Component Pallete novamente na página Standard e localize agora o objeto Memo (acredito que seja o quinto) e através da Object Inspector altere as seguintes propriedades: 5.1. Lines: Clique nos ... e elimine todo o seu conteúdo 6. Precisamos agora de três objetos Label's, para tanto pressione a tecla SHIFT e clique no objeto Label (deve ter ficado um quadriculado azul em volta do objeto, como se ficasse marcado) e dê três cliques no Form, coloque-os acima dos três objetos criados anteriormente. (automaticamente o Delphi criou oito objetos chamados respectivamente Label1, Label2 e Label3) 7. Quando terminar clique dentro da Component Pallete na setinha para poder desmarcar o objeto Label. 8. Altere as seguintes propriedades para esses três objetos: 8.1. Font: Clique nos "..." e faça as seguintes alterações na janela de Fonts: 3.41. Cor: Castanho 3.42. Estilo: Negrito 8.2. Caption: Altere para cada um respectivamente: Selecione o Alias: Tabelas Disponíveis: Digite a clausula SQL 9. Na Component Pallete vá para a página Addicional e localize agora o objeto SpeedButton (acredito que seja o segundo) e traga dois para o form e através da Object Inspector altere as seguintes propriedades: 9.1. Glyph: Altere para cada um respectivamente: CHECK.BMP CLEAR.BMP 9.2. Flat: True (faz com que o botão fique liso no form) 9.3. Hint: Altere para cada um respectivamente: Executa a instrução SQL Limpa a instrução SQL 9.4. ShowHint: True 9.5. Name: Altere para cada um respectivamente: ButExecuta ButLimpa 10. Na Component Pallete vá para a página Data Access e localize agora o objeto Query (acredito que seja o terceiro) 11. Na mesma página Data Access e localize agora o objeto DataSource (acredito que seja o primeiro) e através da Object Inspector altere a propriedade: 11.1. DataSet: Query1 (faz a ligação com um objeto Query ou Table)
12. Para finalizar na Component Pallete vá para a página Data Controls e localize agora o objeto DbGrid (acredito que seja o primeiro) e através da Object Inspector altere a propriedade: 12.1. DataSource: DataSource1 (faz a ligação com um objeto DataSource) 13. Terminamos, compare como ficou:
Codificando Tudo pronto, basta apenas meter a mão no programa, mas vamos devagar, a idéia deste projeto apesar de simples pode parecer um pouco complicada, inicialmente será mostrado todos os alias que existem no BDE Administrator após a escolha de qualquer um deles, serão mostradas as tabelas disponíveis, agora basta apenas digitar as instruções SQL no objeto MEMO1 e pressionar o botão para executá-lo. 14. Localize na Object Inspector o objeto F_SQL, mude para a página de eventos (Events) e localize o evento OnShow, dê um duplo clique na área em branco. Automaticamente o Delphi criará para você a chamada ao evento e o transferirá para a Code Editor, insira o seguinte código: procedure TF_SQL.FormShow(Sender: TObject); begin Session.GetAliasNames(ListaAlias.Items); Query1.DataBaseName := ListaAlias.Items[0]; end; Este procedimento se encarregará de carregar o nosso objeto ListBox com a lista do nome de todos os Alias existentes e transferir o primeiro nome carregado para a propriedade Databasename do objeto Query1. 15. Localize na Object Inspector o objeto ListaAlias e na página de eventos (Events) localize o evento OnClick, dê um duplo clique na área em branco. Automaticamente o Delphi criará para você a chamada ao evento e o transferirá para a Code Editor, insira o seguinte código:
procedure TF_SQL.ListaAliasClick(Sender: TObject); var i : integer; begin if (ListaAlias.SelCount = 0) then begin MessageDlg('Selecione primeiro algum Alias',mtError,[mbOk],0); exit; end; // Mostra os itens da lista não resolvida Screen.Cursor := crHourGlass; for i := 0 to (ListaAlias.Items.Count - 1) do if ListaAlias.Selected[i] then begin with Query1 do if Active then Close; Query1.DataBaseName := ListaAlias.Items[i]; Session.GetTableNames(ListaAlias.Items[i],'', true, false, ListaTabela.Items); break; end; Screen.Cursor := crDefault; end; Não se preocupe em não entender nada aqui, muito desses comandos sequer foram falados, então vamos por partes, o evento é disparado assim que qualquer dos Alias da nossa lista for selecionado: 1. Verificação (de rotina) se realmente algum alias foi selecionado da lista 2. Modifica o cursor para o formato de uma ampulheta 3. Do primeiro ao último da lista (aonde o primeiro é 0 e o último é o número de elementos - 1) 3.1. Verifica se é este o alias selecionado e se for 3.1.1. Verifica se a query1 está aberta se estiver fecha ela 3.1.2. Transfere o nome do alias para a propriedade Databasename da Query1 3.1.3. Carrega a lista dos nomes das tabelas do alias selecionado 3.1.4. Interrompe o laço 4. Modifica novamente o cursor para o formato padrão
☞Importante - Existem dois comandos que cancelam laços de repetições (Comandos For, While e Repeat) são eles: Break - Interrompe o laço mandando o comando para o próximo comando após o laço. Exit - Interrompe o laço terminando o procedimento ou função. O comando Break só pode ser usado dentro de um laço de repetição enquanto que o comando Exit pode ser usado dentro de procedimentos ou funções livres de um laço de repetição. 16. Localize na Object Inspector o objeto ButExecuta e na página de eventos (Events) localize o evento OnClick, dê um duplo clique na área em branco. Automaticamente o Delphi criará para você a chamada ao evento e o transferirá para a Code Editor, insira o seguinte código: procedure TF_SQL.ButExecutaClick(Sender: TObject); begin with Query1 do begin if Active then Close; SQL.Clear; SQL := Memo1.Lines; try ExecSQL;
try Open; except end; MessageDlg('Instrução Executada...', mtInformation, [mbOk], 0); except MessageDlg('Comando SQL está inválido', mtError, [mbOk], 0); end; end; end; Aqui até que poderia ser tudo simples, mas para possibilitar que o usuário possa fazer uso dos comandos INSERT, UPDATE e DELETE tive que usar de uns macetes que acabaram se tornando interessantes, meu problema estava no seguinte, esses três comandos indicados anteriormente diferentemente do comando SELECT não geram o que chamamos em SQL de uma cadeia de códigos, ou seja, eles não me dão uma resposta em uma lista, então não posso utilizar-me do comando OPEN para eles, ao invés disso preciso usar o comando EXECSQL que apenas dispara esses comandos para o banco de dados, não gerando nenhuma espécie de retorno e para sorte o EXECSQL suporta o comando SELECT. Além desse problema o usuário poderia digitar um comando errado, algo como: Maria tinha um carneirinho... o que me daria um erro que travaria totalmente meu aplicativo (causando uma falha do programa). Para sanar ambos os problemas construí um bloco de proteção try...except...end; esses comandos protegem os códigos que estão entre o try...except e caso acontece erro em algum deles (por exemplo um comando assim: Variavel_Inteira := 10/0; ou Variavel_Inteira := 'Maria tinha um carneirinho...') transferindo automaticamente para a instrução entre o except...end; Vamos dar uma olhada então como ficou a lógica do procedimento: 1. Verifica se a query1 está aberta se estiver fecha ela 2. Limpa o parâmetro lines da Query1 3. Transfere o conteúdo das linhas do Memo1 para dentro do SQL da Query1 4. Abre um bloco de proteção 4.1. Executa o comando SQL 4.2. Ativa um novo bloco de proteção 4.2.1. Abre a Query1 4.2.2. Em caso de erro no bloco de proteção apenas segura e não faz nada 4.3. Mostra uma mensagem dizendo que está tudo bem 5. Em caso de erro no bloco de proteção coloca uma mensagem de alerta
Observação Interessante: Existe também o bloco de proteção try...finally...end; que protege os comandos, e acontecendo ou não o erro executa obrigatoriamente os comandos localizados entre o finally...end; 17. Localize na Object Inspector o objeto ButLimpa, na página de eventos (Events) localize o evento OnClick, dê um duplo clique na área em branco. Automaticamente o Delphi criará para você a chamada ao evento e o transferirá para a Code Editor, insira o seguinte código: procedure TF_SQL.ButLimpaClick(Sender: TObject); begin Memo1.Lines.Clear; end; Agora ficou fácil, a única função deste botão é limpar o conteúdo do objeto Memo1.
18. Localize na Object Inspector o objeto F_SQL, na página de eventos (Events) localize o evento OnClose, dê um duplo clique na área em branco. Automaticamente o Delphi criará para você a chamada ao evento e o transferirá para a Code Editor, insira o seguinte código: procedure TF_SQL.FormClose(Sender: TObject; var Action: TCloseAction); begin with Query1 do if Active then Close; end; Aqui também é simples, quando terminar o aplicativo verifica se o objeto Query1 ficou aberto, e em caso afirmativo fecha ele.
Finalmente Prontinho você já pode executar seu aplicativo, mas ainda aqui vale uma pequena observação, escreva um código esquisito para o objeto Memo1 (por exemplo digite: Maria tinha um carneirinho... e clique no botão para executar o SQL note que automaticamente o Delphi interrompe a execução do programa e assume o controle, basta apenas você disparar F9 para continuar, não se preocupe isso acontece apenas em modo Run-Time se você executar o aplicativo fora do Delphi você não passará mais por isso e verá que seu aplicativo consegue controlar o erro eficazmente.
☞
Importante - Você pode desativar isto, para tanto a partir do Menu Principal vá em Tools | Environment Options... e na página Preferences no bloco Debugging desative a opção Break on Exception.
6 Curso de Delphi 4.0 - Apostila 6 Autor: Fernando Antonio F. Anselmo eMail: [email protected] Pré-Requisitos: • • • •
Windows 98 Delphi 4.0 versão Client/Server Suite BDE 5.00 MS-Access 97
Prefácio Salve, antes de começarmos devo dizer que este será o projeto mais longo e completo que já fizemos no decorrer deste curso, atualmente não existe mais a figura do programador, aquele cara que sentava atrás de um teclado e ficava simplesmente desenvolvendo programas maravilhosos que o usuário acabava achando confuso e complicado de usar. Então porque fazer um curso de Delphi (ou qualquer outra ferramenta) apenas para apenas aprendermos a linguagem ? Sendo que seria muito mais fácil consultar o manual. Com base nisso ao invés de me restringir a apenas ensinar macetes e dicas quentes, vou tentar algo mais "ousado" a partir de agora, tentar dar uma visão do mundo externo para vocês com projetos reais. Vale uma pequena observação aqui: Apesar de todos os dados se aproximarem o máximo possível da realidade todas as empresas que serão abordadas e criadas aqui serão totalmente fictícias, caso numa dessas loucuras da vida a empresa exista (cada dia é criado uma nova mesmo) todos os dados foram criados exclusivamente por imaginação e não existe nenhuma relação com a realidade. Começaremos desde a fase da entrevista com os usuários responsáveis até a finalização com a instalação dos módulos, portanto dividi este projeto em diversas apostilas, a de hoje considero a mais chata, mas em compensação é a mais importante, para quem gosta de colocar a mão na massa vai se decepcionar hoje, pois a única massa que usaremos será a cerebral. Portanto feche o Delphi e o micro, pegue papel e caneta e vamos ao trabalho.
Iniciando A companhia Antes & Depois nos contratou para que criassemos um sistema que agilizaria o trabalho rotineiro, esta empresa trabalha basicamente com o conceito de SPA (vulgarmente conhecidos como Campo de Concentração para Gordinhos), mas teve um pequeno problema no caminho, Ela (a empresa) não sabe qual o tipo de sistema que quer, mas a idéia basica de que se precisa é: De um cadastro organizado e completo de cada cliente; De um controle individual da criação dos programas alimentares; e De um acompanhamento pós-programa do Cliente. Então foram realizadas três entrevistas, a primeira com o médico-diretor geral da Empresa que recebe e define o programa do cliente, a segunda com o responsável pelos cardápios da alimentação e a terceira com o médico nutricionista da empresa responsável pelo acompanhamento pós-programa. A seguir você encontrará a síntese dessas entrevistas.
Projeto 4 - Analizando o SPA Antes & Depois Cia.
1º Dia de entrevistas com o usuário: Programação alimentar para o emagrecimento Um novo hábito em vez de uma nova dieta este é o lema da nossa empresa. Primeiramente, é importante ter em mente a necessidade de se chegar a um novo hábito alimentar, que irá assegurar a manutenção do peso ideal após o final do tratamento. Já sabemos que 90% das pessoas que fazem uma dieta para emagrecer recuperam depois todo o peso perdido. Sabemos também que ficar engordando e emagrecendo é pior para a saúde do que simplesmente manter-se obeso. Devemos, portanto, buscar sempre um resultado definitivo, que permitirá a manutenção do peso dentro de uma faixa ideal. Esqueça aquela idéia antiga do emagrecimento através de dietas, que representavam um período de sacrifício, fome, fraqueza e mau humor. As pessoas deixavam inclusive de comparecer a festas e reuniões sociais que pudessem representar uma ameaça ao seu programa alimentar rigoroso. Flexibilidade. A tendência mundial tem sido de recomendar programas alimentares flexíveis, onde as quantidades planejadas de cada alimento não precisam ser rigorosamente respeitadas nem o paciente é obrigado a evitar compromissos sociais onde alimentos "proibidos" serão servidos. Algumas comidas devem ser evitadas, ou consumidas com moderação, principalmente as mais gordurosas. Alimentação sob-medida. Cada pessoa precisa de um determinado programa alimentar para emagrecer de forma saudável e equilibrada. Existem fórmulas para se calcular a quantidade de calorias a ser ingerida diariamente. Infelizmente, este método é muito falho, já que não leva em conta as grandes variações de gasto metabólico de uma pessoa para outra. Este gasto energético só pode ser medido através de aparelhos sofisticados e caros, que são utilizados apenas em trabalhos de pesquisa. Existem, no entanto, maneiras práticas de se estimar quanto uma pessoa queima em calorias. Por exemplo, se o paciente já relata na consulta que, mesmo comendo pouco, emagrece muito lentamente, provavelmente seu gasto metabólico é baixo. Sua alimentação deverá conter entre 1000 e 1200 Kcal para que o tratamento não seja muito demorado. Já uma pessoa que tenha engordado porque ingere uma quantidade exagerada de calorias e conta que emagreceu rapidamente durante um período de contenção alimentar, provavelmente tem um metabolismo que consome muita energia. Este paciente poderá emagrecer bem com uma quantidade de calorias maior, entre 1500 e 1800 Kcal. Algumas pessoas acham que não podem emagrecer porque têm um horário muito irregular, uma vida profissional muito agitada ou porque jantam fora todas as noites. Tudo isso pode ser contornado. Sempre haverá uma maneira de planejar uma alimentação adequada que se adapte ao seu estilo de vida, respeitando seus hábitos e seu paladar. Equilíbrio. Emagrecer não é fechar a boca. A alimentação deve ser voltada para o equilíbrio do metabolismo. Além de conter uma quantidade adequada de calorias, elas devem estar distribuídas em proporções apropriadas, entre carboidratos, proteínas e gorduras. Para isso, você precisará conhecer a composição dos alimentos, consultando a tabela de alimentos equivalentes ou o dicionário. Também é importante distribuir adequadamente as refeições. Os horários não precisam ser obedecidos rigorosamente, mas não se deve ficar mais de 4 horas sem comer. Um programa de alimentação ideal deveria conter 6 refeições diárias - desjejum (café da manhã), colação (refeição ligeira entre o desjejum e o almoço), almoço, lanche, jantar e ceia. Se você tem o hábito de dormir logo após o jantar, não é necessário incluir a ceia. É muito comum as pessoas saltarem refeições sempre que estão sem fome, tentando desta forma obter resultados mais rápidos, o que não é recomendável. Uma parte importante do nosso gasto energético vem da própria metabolização dos alimentos.
2º Dia de entrevistas com o usuário: Como são montados os cardápios A tabela de alimentos equivalentes é uma lista de substituições, que deve ser sempre consultada para que a alimentação não se torne monótona. Lembre-se que o objetivo principal é o desenvolvimento de um novo hábito alimentar. Comendo todo dia as mesmas coisas você não estaria evoluindo na busca de um comportamento alimentar diferente daquele que o levou a engordar. Através da tabela você poderá substituir os alimentos à vontade, sempre dentro de um mesmo grupo, onde o teor calórico e a proporção de carboidratos, proteínas e gorduras serão semelhantes (equivalentes). Conhecendo as possibilidades de substituições que a tabela oferece, você mesmo poderá elaborar seu cardápio, mantendo-o sempre atrativo e saboroso. Além disso, você estará apto a manipular sua alimentação para adaptá-la às mais diversas ocasiões, como jantares festivos, refeições rápidas, churrascos e qualquer circunstância que o obrigue a sair da rotina.
A seguir você verá os 8 grupos básicos na composição de dietas para emagrecimento. Grupo 1 VEGETAIS DE BAIXÍSSIMO TEOR CALÓRICO ABOBRINHA ALFACE BRÓCOLIS ESCAROLA NABO REPOLHO TOMATE
ACELGA ALMEIRÃO CARURU ESPINAFRE PEPINO SALSÃO
AGRIÃO AZEDINHA CHICÓRIA MAXIXE PIMENTÃO SERRALHA
AIPO BERTALHA COUVE NABIÇA RABANETE TAIOBA
Grupo 2 VEGETAIS DE BAIXO TEOR CALÓRICO (2 colheres das de sopa equivalem a 1 porção) ABÓBORA CEBOLA COUVE-FLOR VAGEM
ASPARGO CENOURA ERVILHA
BERINGELA CHUCHU PALMITO
BETERRABA COGUMELO QUIABO
Grupo 3 FRUTAS ABACAXI - 1 RODELA PEQUENA ACEROLA - 1 PEQUENA ÁGUA DE COCO - 1 COPO PEQUENO MEIXA - 2 MÉDIAS AMORA - MEIO COPO BANANA D'ÁGUA - MEIA FRUTA BANANA MAÇÃ - 1 PEQUENA BANANA OURO - 1 PEQUENA BANANA PRATA - 1 PEQUENA CAJÁ-MANGA - 1 PEQUENO CAJU - 1 MÉDIOCAQUI - 1 PEQUENO CARAMBOLA - 1 MÉDIA CEREJA - 6 FRUTAS DAMASCO - 2 MÉDIOS FIGO - 1 MÉDIO FRAMBOESA - 10 FRUTAS FRUTA-DE-CONDE - MEIA FRUTA GOIABA - 1 PEQUENA GRAPEFRUIT - MEIA FRUTA JABUTICABA - 10 FRUTAS JACA - 4 BAGOS JAMBO - 4 FRUTAS KIWI - 1 MÉDIO LARANJA - 1 PEQUENA LIMA DA PÉRSIA - 1 PEQUENA MAÇÃ - 1 MÉDIA MAMÃO - 1 FATIA PEQUENA MANGA - 1 PEQUENA MARACUJÁ - 1 PEQUENO MELANCIA - 1 FATIA MÉDIA MELÃO - 1 FATIA PEQUENA MORANGO - 10 FRUTASNECTARINA - 1 MÉDIA NÊSPERA - 3 PEQUENAS PASSA - 1 COLHER DE SOPA PERA - 1 PEQUENA PÊSSEGO - 1 MÉDIO PITANGA - MEIO COPO ROMÃ - MEIA FRUTA SALADA DE FRUTAS - 3 COLHERES TÂMARA - 2 MÉDIAS TANGERINA - 1 MÉDIA UVA - 10 FRUTAS Grupo 4 CEREAIS, PÃES, BISCOITOS E MASSAS AIPIM - 1 PEDAÇO MÉDIO AVEIA - 3 COLH. DE SOPA BATATA INGLESA - 1 MÉDIA BOLACHA ÁGUA E SAL - 2 EMPADA - 1 PEQUENA FAROFA - 1 COLH. DE SOPA
ARROZ - 2 COLH. DE SOPA BATATA DOCE - 1 PEQUENA BISCOITO CREAM CRACKER - 2 CORN FLAKES - 1 COLH. DE SOPA FARINHA - 2 COLH. DE SOPA FEIJÃO - 4 COLH. DE SOPA
GERME DE TRIGO - 3 COLH. DE SOPA LASANHA - 2 COLH. DE SOPA MACARRÃO - 2 COLH. DE SOPA MILHO VERDE - 4 COLH. DE SOPA PANQUECA - 1 PEQUENA PÃO DE FORMA - 1 FATIA PÃO INTEGRAL - 1 FATIA PASTEL - 1 MÉDIO PIRÃO - 2 COLH. SOPA TORRADA - 6 DAS PEQUENAS
GRÃO DE BICO - 2 COLH. DE SOPA LENTILHA - 2 COLH. DE SOPA MAISENA - 1 COLH. DE SOPA NHOQUE - 2 COLH. DE SOPA PÃO DE CENTEIO - 1 FATIA PÃO DE GRAHAM - 1 FATIA PÃO FRANCÊS - MEIO PEQ. PIPOCA - 1 PACOTE PEQ. PIZZA - 1 FATIA PEQUENA TREMOÇOS - 3 COLH. DE SOPA
Grupo 5 CARNES, QUEIJOS E OVOS CABRITO - 1 TERÇO DE BIFE CARNEIRO - 1 TERÇO DE BIFE CAVIAR - 1 COLHER DE SOBREMESA DOBRADINHA - 2 COLH. DE SOPA FONDUE DE QUEIJO - 25 GRAMAS LAGOSTA - 1 PEDAÇO PEQUENO LULA - 1 PORÇÃO MÉDIA MORTADELA - 2 FATIAS FINAS OVO DE CODORNA - 3 UNIDADES PAIO - 1 PEDAÇO PEQUENO PERU - 1 TERÇO DE BIFE POLVO - 1 PORÇÃO MÉDIA QUEIJO - 1 FATIA REQUEIJÃO - 1 COLHER DE SOPA SALAME - 1 FATIA PEQUENA SIRI - 3 DE TAMANHO MÉDIO
CAMARÃO - 2 MÉDIOS CARNE SECA - 1 PEDAÇO PEQUENO COELHO - MEIO BIFE FÍGADO - 1 TERÇO DE BIFE FRANGO - 1 TERÇO DE BIFE LINGUIÇA - 1 PEDAÇO PEQUENO MEXILHÃO - 1 PORÇÃO PEQUENA OSTRAS - 1 PORÇÃO PEQUENA OVO DE GALINHA - 1 UNIDADE PATO - 1 TERÇO DE BIFE PEIXE - MEIA POSTA PEQUENA PRESUNTO MAGRO - 2 FATIAS QUEIJO COTTAGE - 2 COLHERES RICOTA - 2 FATIAS FINAS SALSICHA - 1 PEQUENA VACA - 1 TERÇO DE BIFE
Grupo 6 GORDURAS AZEITE - 1 COLHER DE CHÁ BACON - 1 FATIA PEQUENA MAIONESE - 1 COLHER DE CHÁ MANTEIGA - 1 COLHER DE CHÁ ÓLEO VEGETAL - 1 COLHER DE CHÁ
AZEITONA - 4 MÉDIAS CREME DE LEITE - 1 COLH. DE SOPA MAIONESE LIGHT - 2 COLH. DE CHÁ MARGARINA - 1 COLHER DE CHÁ PATÊ - 1 COLHER DE CHÁ
Grupo 7 LEITES COALHADA - MEIO COPO IOGURTE DIET - 2 FRASCOS LEITE INTEGRAL - MEIO COPO PUDIM DIET - 1 PEQUENO
IOGURTE NATURAL - 1 COPO LEITE DESNATADO - 1 COPO LEITE INTEGRAL EM PÓ - 1 COLHER SORVETE DIET - 1 BOLA
Grupo 8 BEBIDAS, CONDIMENTOS E DIETÉTICOS DE BAIXÍSSIMO TEOR CALÓRICO ADOÇANTES CHÁ ERVA-DOCE LIMONADA REFRIG. DIETÉTICOS
ALHO CAFÉ CANELA CEBOLINHA COMINHO CRAVO GELATINA DIETÉTICA HORTELÃ LIMÃO MATE ORÉGANO PIMENTA SAL SALSA VINAGRE
A unidade básica da tabela é chamada porção, que é a quantidade de cada alimento listado em um grupo. Um exemplo: Se o seu programa alimentar tem no almoço 2 porções do grupo 4, você poderá consumir: 1 colher de arroz + 1 colher de farofa ou 2 fatias de pão de forma ou batata inglesa + 1 panqueca e assim por diante. Se no almoço você também tem 3 porções do grupo 5, pode comer além daqueles alimentos: 1 bife de tamanho médio (cada porção corresponde a um terço de bife) ou 1 posta de peixe + 1 ovo ou 2 fatias de queijo (cada porção dá para 1 fatia) + 2 fatias de presunto e assim por diante. Não devem ser trocados alimentos de grupos diferentes. A troca de um alimento do grupo 4 por um alimento do grupo 5, por exemplo, implicaria em uma redução do teor de carboidratos da refeição, podendo desregular os mecanismos cerebrais de regulação do apetite. Por outro lado, pode-se transferir um determinado alimento de uma refeição para outra, desde que seja mantida em todas as refeições pelo menos uma porção dos grupos 3 ou 4, que contêm mais carboidratos. Apenas os alimentos listados nos grupos 1 e 8 podem ser consumidos à vontade, já que seu teor calórico é considerado desprezível. Mesmo nas refeições onde estes grupos não forem mencionados, os alimentos neles contidos podem ser consumidos sem restrições. Os grupos 1 e 2 apresentam a vantagem de acrescentar fibras à alimentação, além de serem pobres em calorias. Os alimentos do grupo 3 são as frutas, constituídas basicamente de carboidratos. Não está relacionado o abacate, por possuir um elevado teor de gordura. Também os alimentos do grupo 4 são constituídos principalmente por carboidratos. Cuidado com as massas e pizzas, porque na cobertura ou no molho elas podem carregar grandes quantidades de gorduras e calorias. No grupo 5 estão listados os alimentos constituídos por proteínas e gorduras. O teor de gorduras, no entanto, é variável. Os queijos brancos, como a ricota, o cottage e o próprio queijo tipo Minas são menos gordurosos que os outros. Também as carnes brancas são menos gordurosas que as vermelhas. Cuidado com a pele dos peixes e do frango, porque é onde se armazena a gordura. Crustáceos como o camarão e a lagosta são ricos em colesterol, assim como a gema dos ovos. Sempre que possível as carnes devem ser consumidas grelhadas, assadas ou cozidas, já que a fritura as torna mais gordurosas. O grupo 6 é o das gorduras. Deve ser evitado na medida do possível. No grupo 7 estão o leite e seus derivados. Por serem menos gordurosos, deve-se dar preferência aos desnatados. No grupo 8 estão listados vários alimentos, temperos e bebidas cujo teor calórico é desprezível. Apesar de não engordarem, seu consumo excessivo pode trazer outros males à saúde. O café, por exemplo, pode causar insônia quando ingerido em demasia, enquanto os refrigerantes e temperos podem levar a problemas gástricos. As bebidas alcoólicas estão listadas na tabela abaixo, com seus respectivos teores calóricos. Elas não podem substituir nenhum alimento de outro grupo, porque seu valor nutritivo não é o mesmo. Grupo 9
BEBIDAS ALCOÓLICAS BEBIDA Cachaça Cerveja Champanhe Conhaque Gim Rum Uísque Vinho branco seco Vinho branco doce Vinho tinto Vodka
QUANTIDADE VALOR CALÓRICO 1 dose de 50 ml 120 Kcal 1 copo com 300 ml 140 Kcal 1 copo com 100 ml 110 Kcal 1 copo com 50 ml 120 Kcal 1 copo com 50 ml 130 Kcal 1 copo com 50 ml 120 Kcal 1 copo com 50 ml 120 Kcal 1 copo com 100 ml 90 Kcal 1 copo com 100 ml 140 Kcal 1 copo com 100 ml 70 Kcal 1 copo com 50 ml 120 Kcal
Grupo 10 DOCES O teor calórico dos doces é muito variável, dependendo principalmente do seu conteúdo de gorduras. Na tabela abaixo você encontra o teor calórico médio de alguns doces mais consumidos pelos brasileiros. DOCE BALA BANANA CARAMELADA BIS BOLO DE FESTA BOMBA DE CHOCOLATE BOMBOM BRIGADEIRO CHICLETE CHOCOLATE EM BARRA DOCE DE LEITE GELATINA GELÉIA GOIABADA MILK SHAKE McDonald's MOUSSE DE CHOCOLATE PÊSSEGO EM CALDA PUDIM SONHO SUNDAE (McDonald's) SUSPIRO TORTA
QUANTIDADE 1 UNIDADE 1 UNIDADE 1 UNIDADE 1 FATIA 1 UNIDADE 1 UNIDADE 1 UNIDADE 1 UNIDADE 1 PEQUENO 2 COLHERES DE SOPA 1 CAIXA 1 COLHER DE SOBREMESA 1 PEDAÇO 1 UNIDADE 1 POTE PEQUENO 1 METADE 1 FATIA 1 UNIDADE 1 UNIDADE 1 GRANDE 1 FATIA
VALOR CALÓRICO 20 kCAL 450 kCAL 40 KCAL 200 kCAL 200 KCAL 120 kCAL 50 kCAL 20 kCAL 160 kCAL 200 kCAL 70 kCAL 30 kCAL 80 KCAL 340 kCAL 200 KCAL 80 kCAL 250 kCAL 150 KCAL 260 kCAL 70 KCAL 250 kCAL
Sempre que possível, recomenda-se dar preferência aos dietéticos, que não contêm açúcar. É importante lembrar, no entanto, que muitos deles, mesmo não contendo açúcar, são altamente calóricos, como é o caso dos chocolates. Cardápio com 800 Kcal REFEIÇÃO Desjejum (café da manhã) Colação (lanche da manhã) Almoço Lanche Jantar
PORÇÕES 1 do grupo 4 + 1 do grupo 5 1 do grupo 3 1 do grupo 2 + 2 do grupo 5 + 1 do grupo 4 1 do grupo 3 1 do grupo 2 + 3 do grupo 5 + 1 do grupo 4
Ceia
1 do grupo 3
Cardápio com 1.000 Kcal REFEIÇÃO Desjejum (café da manhã) Colação (lanche da manhã) Almoço Lanche Jantar Ceia
PORÇÕES 1 do grupo 4 + 1 do grupo 5 + 1 do grupo 3 1 do grupo 3 1 do grupo 2 + 3 do grupo 5 + 1 do grupo 4 + 1 do grupo 3 1 do grupo 4 + 1 do grupo 5 1 do grupo 2 + 3 do grupo 5 + 1 do grupo 4 1 do grupo 3
Cardápio com 1.200 Kcal REFEIÇÃO Desjejum (café da manhã) Colação (lanche da manhã) Almoço Lanche Jantar Ceia
PORÇÕES 1 do grupo 7 + 1 do grupo 4 + 1 do grupo 5 + 1 do grupo 3 1 do grupo 3 1 do grupo 2 + 3 do grupo 5 + 1 do grupo 4 + 1 do grupo 3 1 do grupo 4 2 do grupo 2 + 3 do grupo 5 + 1 do grupo 4 + 1 do grupo 6 + 1 do grupo 3 1 do grupo 3
Cardápio com 1.500 Kcal REFEIÇÃO Desjejum (café da manhã) Colação (lanche da manhã) Almoço Lanche Jantar Ceia
PORÇÕES 1 do grupo 7 + 1 do grupo 4 + 1 do grupo 5 + 1 do grupo 3 1 do grupo 3 2 do grupo 2 + 3 do grupo 5 + 2 do grupo 4 + 1 do grupo 3 2 do grupo 4 + 1 do grupo 5 2 do grupo 2 + 1 do grupo 6 + 3 do grupo 5 + 2 do grupo 4 + 1 do grupo 3 1 do grupo 3
Cardápio com 1.800 Kcal REFEIÇÃO Desjejum (café da manhã) Colação (lanche da manhã) Almoço Lanche Jantar Ceia
PORÇÕES 1 do grupo 7 + 1 do grupo 4 + 1 do grupo 5 + 1 do grupo 3 1 do grupo 3 2 do grupo 2 + 4 do grupo 5 + 2 do grupo 4 + 1 do grupo 3 2 do grupo 4 + 1 do grupo 5 + 1 do grupo 3 2 do grupo 2 + 4 do grupo 5 + 2 do grupo 4 + 1 do grupo 6 + 1 do grupo 3 1 do grupo 7 + 1 do grupo 3
Obs.: Os grupos 1 e 8 podem ser utilizados à vontade, em qualquer horário e em qualquer cardápio.
3º Dia de entrevistas com o usuário: Conversa com o nutricionista O que é o peso ideal ? Peso ideal é aquele que propicia o máximo de saúde. O conceito atual de saúde, segundo a Organização Mundial de Saúde é "Estado de bem-estar físico, mental e social". Estes 3 elementos devem ser, portanto, valorizados por quem tenta definir o peso ideal de um determinado indivíduo. Métodos de cálculo do peso ideal. O cálculo do peso ideal deveria ser feito, idealmente, através da medida do percentual de gordura corporal, que pode ser obtida por métodos como a bioimpedância ou pela medida das dobras cutâneas. Como na maioria dos casos estes métodos não estão disponíveis, o índice de massa corporal tem sido largamente utilizado para determinar a faixa ideal de peso. O Índice de Massa Corporal: Este índice pode ser obtido dividindo-se o peso corporal pelo quadrado da altura em metros.
2 Por exemplo: uma pessoa que pese 67 Kg e meça 1,64m, tem um IMC de 24,9 Kg/m ,(67 divididos pelo quadrado de 1,64). ÍNDICE DE MASSA CORPORAL = PESO ( em Kg ) / ( ALTURA em metros ) 2 Apesar de não discriminar os componentes gordo e magro da massa corporal total, é o método mais prático para avaliar o grau de risco associado à obesidade. Os estudos populacionais mostram que o menor 2 risco de mortalidade corresponde à faixa de IMC que vai dos 20 aos 25 Kg/m . Entre 25 e 30 já se observa um aumento do risco. Os pacientes que aí se situam são rotulados como "sobrepesados" ou "com excesso de peso". Entre 30 e 35 considera-se "obesidade leve", entre 35 e 40 "obesidade moderada" e acima de 40 2 "obesidade mórbida". Abaixo dos 20 Kg/m também se observam maiores índices de mortalidade, principalmente por doenças pulmonares e desnutrição. Estão nesta faixa, por exemplo, os portadores de 2 anorexia nervosa. A faixa ideal, portanto, situa-se entre 20 e 25 Kg/m . O indice de massa corporal por faixas de risco
Veja aqui o gráfico que mostra o risco de morte de acordo com o índice de massa corporal. As tabelas de peso e altura Apesar de muito sujeitas a erros, as tabelas de peso e altura ainda são largamente utilizadas em todo o mundo para estimar-se o peso ideal. Elas são derivadas de dados obtidos por companhias de seguro americanas, que as desenvolveram a partir da observação de dados de mortalidade e longevidade de sua população segurada. Os pesos chamados de "ideais" são, na verdade, médias das faixas de peso ideal para cada grupo etário analisado. As tabelas abaixo mostram os pesos de referência para cada um destes grupos. Reparem que na tabela dos indivíduos mais idosos estes pesos já são bem mais altos. Pesos de referência para adultos entre 21 e 55 anos ALTURA (em metros) 1,47 1,50 1,52 1,55 1,57 1,60 1,63 1,65 1,68 1,70 1,73 1,75 1,78 1,80
PESO para homens (em Kg) 60,3 61,2 62,4 63,5 64,9 66,2 67,6 68,9 70,3 71,9
PESO para mulheres (em Kg) 51,7 52,8 53,9 55,3 56,7 58,0 59,4 60,8 62,1 63,5 64,9 66,2 67,6 69,0
1,83 1,85 1,88 1,91
73,9 75,3 76,9 78,9
-
Pesos de referência para adultos entre 55 e 74 anos ALTURA (em metros) 1,47 1,50 1,52 1,55 1,57 1,60 1,63 1,65 1,68 1,70 1,73 1,75 1,78 1,80 1,83 1,85 1,88
PESO para homens (em Kg) 68 70 71 72 74 78 78 77 80 84 81 88 95
PESO para mulheres (em Kg) 57 62 65 64 64 65 66 67 66 72 70 72 73 -
Obs. Os métodos utilizados para o cálculo do peso ideal de adultos não são adequados para indivíduos em fase de crescimento.
Observações finais Além dessas três entrevistas foi constatado que o SPA Antes & Depois ainda mantêm alguns dados importantes: Manutenção periódica da Pasta do Cliente que contém: Dados para o envio de eventual correspondência de propaganda e promoções. Dependendo do plano adotado - acompanhamento nutricional e envio de um cardápio semanal personalizado e completo, baseado no plano de calorias indicado pelo nutricionista. Histórico dos planos realizados pelo cliente no SPA. Não são aceitos clientes menores de 21anos e maiores de 74 anos de idade. Descontos para clientes com re-incidência, baseado na seguinte tabela: 5% primeira re-incidência. 10% segunda re-incidência. 15% terceira re-incidência. Aumento de 1% nas próximas re-incidências até um máximo de 20%. Os planos da empresa são: Plano A (Anti-Stress) - 3 Dias. Plano B (Reeducação) - 1 Semana com acompanhamento periódico de 3 meses. Plano C (Completo) - 1 mês. Plano D (Especial de Reeducação) - 4 Dias com acompanhamento periódico de 3 meses. A divisão do capital da empresa é realizada em cima do preço final do cliente, e dividido da seguinte maneira:
20% para o médico-presidente da empresa. 40% para o coordenador dos planos alimentares. 10% para o nutricionista (caso seja efetuado os planos B ou D ). 30% (ou 40 % - caso seja efetuado os planos A ou C) para despesas gerais. e todo final de mês é criado um relatório de fechamento financeiro com a situação da empresa e a divisão do capital do mês.
Finalmente Prontinho na próxima apostila, criaremos nosso projeto físico baseado em tudo o que foi feito aqui, o projeto físico servirá para montarmos nossa base de dados e termos uma idéia qual o caminho que seguirá nosso sistema. Então aconselho a você que releia as entrevistas com calma e começe a pensar não apenas como uma chave de fenda mas como a caixa de ferramentas completa que não só senta na máquina e começa a programar mas analisa e verifica o que o usuário realmente necessita.
7 Curso de Delphi 4.0 - Apostila 7 Autor: Fernando Antonio F. Anselmo eMail: [email protected] Pré-Requisitos: • • • •
Windows 98 Delphi 4.0 versão Client/Server Suite BDE 5.00 MS-Access 97
Arquivos trabalhados juntos com esta apostila: •
BASICO.MDB
Prefácio Salve, espero que todos vocês tenha gostado do rumo que tomou o nosso curso, também espero que assim fique mais interessante e atual o uso de uma linguagem tão complexa como é o Delphi. Vale uma pequena observação aqui (copiada da apostila anterior, para ficar bem claro): Apesar de todos os dados se aproximarem o máximo possível da realidade todas as empresas que serão abordadas e criadas aqui serão totalmente fictícias, caso numa dessas loucuras da vida a empresa exista (cada dia é criado uma nova mesmo) todos os dados foram criados exclusivamente por imaginação e não existe nenhuma relação com a realidade. Já estamos com todos os dados da nossa empresa na mão, agora vem a fase que antigamente era designada exclusivamente para a nata da informática conhecida por: Analistas de Sistemas, quantas vezes não sonhamos com esse maravilhoso e imponente título. Bem, uma coisa devemos aprender: "Atualmente quem na área de informática não chuta nas onze, não se dá muito bem e acaba vendendo cachorro-quente na porta da Igreja", então quem acha que aprendendo Delphi, ou qualquer outra ferramenta de desenvolvimento, e a única coisa que vai ter que fazer daqui para frente, são programas já prontos e detalhados logicamente sem ter que usar qualquer conhecimento de um Analista de Sistemas, pode começando a pensar seriamente a mudar de profissão. É óbvio que experiência nunca vou conseguir passar para todos, principalmente porque esta vida é um eterno aprendizado, mas vou tentar dar algumas dicas para vocês começarem a pegar o embalo.
Brain-Storm Na entrevista ouvimos algumas palavras chaves, então primeiramente, pegue um quadro-negro e juntamente com sua equipe de desenvolvimento tente fazer um resumo de tudo o que foi dito nas entrevistas iniciais: • • • • • • •
Cadastro organizado e completo de cada cliente; Criação dos programas alimentares; Acompanhamento do Cliente; Cada cliente precisa de um determinado programa; Existem fórmulas para se calcular a quantidade de calorias, este método é muito falho; O paciente relata na consulta e sempre haverá uma maneira de planejar uma alimentação adequada; Existe uma tabela de alimentos;
• • • • • • •
Existem cardápios formados através de uma regra; O Índice de Massa Corporal pode ser obtido dividindo-se o peso corporal pelo quadrado da altura em metros; Existe uma tabela para o Índice de Massa Corporal; Existe uma tabela de Descontos para clientes re-incidentes; Existem duas divisões entre 21 - 55 e 55 - 74 anos; Excluem-se menores de 21 e maiores de 74 anos; e Cálculos de receitas e despesas através de demonstrativos mensais e resumo anual.
Está técnica é melhor quando a equipe é formada por três ou mais pessoas, uma coisa se você é do tipo que detesta o trabalho em grupo, infelizmente você será um péssimo Analista, pois 98% do trabalho é feito com discussões em grupo, debates e análises com a equipe e com o usuário, validando e revalidando periodicamente todos os dados levantados, até que o sistema esteje entregue e pronto. O método que mostrei acima é conhecido por Brain-Storm (Tempestade Cerebral) a idéia é que você recolha os dados mais importantes e discuta em cima deles, existem óbvio vários métodos de análises, mas pessoalmente, considero este o melhor, adote aquele que você sinta mais a vontade.
Preparação da Modelagem dos Dados A próxima fase é conhecida como Modelagem dos Dados, aqui vamos definir nossas entidades (antigamente chamariamos de tabelas, mas prefiro adotar uma linguagem mais atual), faça um jogo com você mesmo antes de ler os atributos de cada entidade (campos) propostos por mim, tente montar seus próprios atributos: Entidade Cliente Atributos: CPF, Nome, Endereço, Bairro, CEP, Cidade, Estado, eMail, Telefones de contato, Altura, Peso medido e data de nascimento. Entidade Alimento Atributos: Número do Grupo, Nome do Alimento e Quantidade Permitida Entidade Pasta do Cliente Atributos: CPF do Cliente, Data, Plano Adotado, Quantidade de Calorias, Observações do tratamento, Data de pagamento, Valor Total e Desconto concedido Entidade Resumo Mensal Atributos: Mes e Ano, Valor do Médico, Valor Coordenador, Valor Nutricionista e Valor Despesa
☞Importante - Dicas Quentes: - Não dê o nome de uma entidade no plural, por exemplo Clientes, Alimentos pois além de gastar um byte a mais para o banco de dados, está errado pois sempre nos referimos a um único registro da entidade. - Pense na entidade como única, note que a entidade Cliente tem o atributo Cidade, o que pode futuramente virar uma outra entidade, mas sempre deixe isso para a fase de normalização. - Não invente entidades ou atributos que não fazem parte do que foi levantado com os usuários, é lógico que os clientes devem ter uma profissão, mas isso não interessa para nosso sistema, se achar que interessa discuta primeiro com o usuário. - Evite sempre códigos estranhos ao cliente para definir Chaves Únicas (aquelas que servirão de
índices primários), primeiro procure por campos únicos na própria entidade, na entidade Cliente podemos usar o CPF.
Modelo Físico Terminada a fase de Preparação da Modelagem, é iniciado todo o trabalho para a construção de um modelo físico, ou seja, como realmente vai ficar implantado nossa base de dados, neste momento valem todas as regras de Normalização e outras técnicas aprendidas em qualquer bom Curso de Análise ou Livros disponíveis no mercado, como minha função é ensinar o Delphi não vou me ater a estes detalhes então vamos dar uma olhada no Modelo Físico pronto e depois farei alguns comentários necessários:
Bem aqui valem algumas regras que aprendi ao longo do tempo:
1. Formação dos Nomes dos Atributos: O maior trabalho de uma empresa de desenvolvimento é formar o nome dos atributos, pois sabemos que eles influenciarão no nome das variáveis, assim ao longo do tempo, e após vários aperfeiçoamentos cheguei a uma regra que venho adotando: XXX_YYYYY - aonde: XXX - Três casas representativas do atributo, Ex: NOM - Nome, NUM - Número, VAL - Valor, DAT - Data, DES - Descrição, ... YYYYY - Complemento do Atributo, Ex: Nome da Própria Entidade, Nomes Significativos, ...
2. Quanto ao Tipo do Atributo: Uma dica que aprendi a muito tempo ainda vale até hoje, escolha os tipos com lógica e utilidade, quer um exemplo então responda as seguintes perguntas:
O que é mais útil e lógico um atributo CPF (NUM_CPF) ser Texto com 11 casas ou um Inteiro ? Se vamos fazer cálculos com a Altura do Cliente (ALT_CLIENTE) então definiremos o atributo como Texto ou Inteiro com casas decimais ? Se a observação do clientes (OBS_PASTA) pode variar muito o que é mais prático um campo Texto Variável ou um Texto fixo de 300 casas ? Todas as quantidades devem ser numéricas mesmo que não se façam cálculos com elas ? E como fica a Quantidade de Caloria (QTD_CALORIA)
3. Escolha das Chaves: Vou bater na mesma tecla pois acho ela importante, escolha chaves fáceis de lembrar, no último caso escolha os tipos de atributos automáticos, como foi o caso da entidade ALIMENTO que acabei optando por uma chave Auto Incremental (1,2,3,4,5...)
☞Importante - Não utilize, mesmo que o banco permita, tipos de atributos AUTO INCREMENTAL pois esses campos não permitem sua modificação ou seu controle, utilize campos INTEIROS e faça os cálculos do maior através de uma função genérica.
Módulos Funcionais A última fase da Analise de um sistema é a documentação de todas as funções ou se você preferir pode chamar de Módulos Funcionais, estes módulos normalmente são divididos em cadastros, movimentações, consultas e relatórios impressos, fazendo isso e conseguindo a validação do usuário, você evitará muitos aborrecimentos posteriores, tais como ser mal interpretado ou de causar falsas expectativas, e esta fase também ajudará na elaboração das Opções do Menu.
Cadastro Cidade: terá a função de editar e coordenar o arquivo de cidades Grupo: terá a função de editar e coordenar o arquivo de grupos Alimento: terá a função de editar e coordenar o arquivo de alimentos Cliente: terá a função de editar e coordenar o arquivo de clientes
Movimentação Entrada do Cliente: recepção para os clientes e montagem e definição dos planos nas pastas Saída do Cliente: fechamento da conta e da pasta do cliente Massa Corporal: Cálculo da Massa Corporal e pesagem atual de determinado cliente
Consulta Pasta do Cliente: Verificação de determinado cliente, com gráficos sobre peso e massa coorporal Verificação do Caixa Mensal: Cálculo da arrecadação de um determinado mês
Relatório Correspondência: envio de corrêspondencia a clientes Cardápio: montagem de determinado cardápio diário baseado no número de calorias informadas Divisão das Contas Mensal: fechamento das contas mensais e divisão dos lucros Analítico das Contas Anual: resumo anual de toda a divisão efetuada
Finalmente
Prontinho agora resta mostrar para o nosso usuário ter o carimbo de aprovação, não se esquecendo de especificar prazos para a conclusão de cada módulo funcional descrito. Na próxima apostila, começaremos a programar nosso sistema criando o menu e as telas de apoio.
8 Curso de Delphi 4.0 - Apostila 8 Autor: Fernando Antonio F. Anselmo eMail: [email protected] Pré-Requisitos: • • • •
Windows 98 Delphi 4.0 versão Client/Server Suite BDE 5.00 MS-Access 97
Arquivos trabalhados juntos com esta apostila: • •
PESO.HLP IM0.BMP até IM10.BMP
Prefácio Salve, bem hoje pretendo tratar aqui de um tema da maior importância, também que gera a maior polêmica entre qualquer grupo de mais de um programador, Menus. Não me refiro a Cardápios, e sim Menus de Sistemas, ou popurlamente chamados de Telas de Entrada, por isso mesmo que são os responsáveis pela maior polêmica. Um Menu está para um sistema, assim como a Sala está para a casa, pegue um sistema, o mais prático o possível, cheio de "nove horas", entre outras dezenas de outras vantagens, e acrescente nele um Menu horroroso que só quem o programou entende e depois de um mês nem ele mais. Esta apostila (tão aguardada) pode parecer simples a primeira vista, mas garanto-lhes que não é muito simples projetar uma casa sem começar pela sala.
Tipos de Sistema SDI ou MDI ? Vou falar rapidamente dos tipos de sistemas, existem basicamente dois tipos de sistemas: MDI (multiple document interface) - é aquele que permite a abertura de várias janelas, caracterizando-as como filhas que são exibidas dentro do contexto da janela principal, pode ser aberto inclusive diversas cópias de uma mesma janela. Existindo uma intensa movimentação entre elas. Muito usado em Editores de texto e Planilhas de cálculos. SDI (single document interface) - é aquele que permite a abertura de uma só janela de cada vez inibindo atuações nas áreas fora da mesma, não existindo nenhuma coorelação entre elas. Muito usados em sistemas de grande porte. Já deu para perceber a diferença básica entre os menus que são construídos para cada sistema, no primeiro caso o Menu deve ser máximizado para comportar as janelas filhas, no segundo caso o Menu pode ser uma simples janela que pode ser colocada no canto superior (como a barra do Office), se você se complicou com os dois sistemas imaginemos um Sistema de Estoque, aonde existe um formulário que é a Fatura podemos tratá-la da seguinte maneira: No sistema MDI - A janela da Fatura pode ser aberta diversas vezes, ou seja no meio de uma Fatura, poderemos iniciar uma nova, ou então entrar na janela de Material para cadastrar (ou descobrir o código) de
um determinado material. No sistema SDI - A janela da Fatura é aberta e nela permanece (salvo que exista um botão, ou outro meio, para chamar uma outra janela) até que a Fatura seja encerrada. Também você deve ter notado que existem diferenças bárbaras em ambos os sistemas, vamos analisar as desvantagens: No sistema MDI - O usuário pode começar a abrir diversas janelas de Faturas, ou um número excessivo de janelas, causando assim o estouro da área de memória, lembre-se que cada formulário aberto vai para a área de memória, aquela área baixa (do 640 Kb) então nem adianta aumentar a memória, vai chegar num momento que o sistema simplesmente não aguentará. No sistema SDI - Se o usuário precisar de cadastrar (ou descobrir o código de) um determinado material, ele precisará cancelar a Fatura fechar a janela, entrar na janela de Material, cadastrar ou pesquisar , fechar essa janela e voltar para a janela de Fatura e começar a digitar a Fatura tudo novamente, a menos que o Programador tenha lembrado de colocar um botão para que ele acesse a tela de material. Pessoalmente eu prefiro meus sistemas no modo SDI, apesar de achar o MDI tentador, primeiro muitos dos meus usuários são leigos, eu não teria como explicar-lhes (às cinco da manhã de sábado normalmente) que a aplicação deles caiu porque tinha vinte clientes na loja e ele resolveu abrir vinte janelas de Fatura, mas você poderá optar por qual sistema deseja adotar, pois futuramente nosso próximo projeto será um sistema totalmente MDI.
Tipos de Menus Ficou comprovado no ambiente Windows, também em outros ambientes, que o Menu que melhor funciona é aquele que abre de cima para baixo, estou me referindo dentro do Delphi ao 1o. Objeto da 1a. Palheta, ou seja o objeto MainMenu, não é a toa que ele é o primeiro, seu irmão mais novo é o PopMenu, aquele menuzinho rápido que temos todas as vezes que clicamos com o botão direito em cima de um objeto. Já vi muitos Menus interessantes, dos mais diversos tipos, um deles inclusive imita o menu do botão Iniciar do Windows 95, mas pessoalmente fico com os menus Pull-Down (é assim que são chamados) primeiro porque em qualquer aplicação do Windows (ou outro ambiente) eles estão lá, segundo porque o usuário é acostumado com eles (desde que se sigam regras) e terceiro porque são mais simples de se programarem. Desde a primeira versão do Pascal for Windows que a Borland (hoje Inprise) lançou esse tipo de menu, e sempre sua programação foi muito superior aos seus concorrentes, além de muito fácil, abro um desafio aqui, peguem uma cópia dos VB's (ou FOX, Access, CA-Clipper) ou e tentem criar um menu lá, agora peguem o velho Pascal for Windows e façam a mesma coisa, e me digam o que acharam. O Delphi, seguiu uma tradição da família, seu menu é tão fácil de programar que até mesmo me assusta, vamos lá, sigam o mestre: 1. Se você ainda não fez crie um diretório que abrigará seu sistema. (para padronizar comigo crie: C:\CursoDelphi\Peso) Antes de começarmos a criar nossos menus, deixe-me dizer-lhes um detalhe a mais, a partir do MSOffice 97, foram colocadas figurinhas no tamanho de 16x16 nos menus, e parece que com o Windows 98 isto virou um padrão oficial dos Menus, então na Component Pallete localize uma página chamada Win32 e dentro dessa página de um clique no objeto ImageList (acredito que seja o terceiro) e dê um clique no Form. (automaticamente o Delphi criou um botãozinho com o desenho dele. Para o Delphi é assim que ficam todos os objetos que são invisíveis durante o tempo de execução, ou seja tanto faz em qual posição que você o coloque, quando começar a rodar seu sistema este objeto ficará invisível). Dê um duplo clique no objeto
criado e vamos entrar na ImageList, clique no botão Add e vá adicionando as imagens enviadas na ordem: primeiro a IM0.BMP, depois a IM1.BMP e assim sucessivamente, veja a figura:
2. Abra o Delphi e na Component Pallete localize uma página chamada Standard e dentro dessa página de um clique no objeto MainMenu (acredito que seja o primeiro) e dê um clique no Form. (automaticamente o Delphi criou um botãozinho com o desenho dele, mais um objeto invisível). Dê um clique simples em cima do objeto criado e altere a seguinte propriedade: Images: ImageList1 (Define um objeto ImageList para ser utilizado como repositório de imagens). 3. Vamos agora entrar na Menu Editor, dê agora um clique duplo em cima do MainMenu1 criado, agora é só começar a construir seu Menu, este é um objeto que sou apaixonado vamos a algumas propriedades:
3.0.Antes deixe-me avisá-lo que cada quadradinho criado representa um novo objeto (pertencente a classe tMenuItem) 3.1.BitMap: A partir do MS-Office 97, foram colocadas figurinhas no tamanho de 16x16 nos menus, e parece que com o Windows 98 isto virou um padrão oficial dos Menus, então aqui você insere este tipo de figura. 3.1.Break: permite que você crie um submenu lateral (utilize a opção mbBreak para o primeiro e mbBarBreak para os filhos) 3.2.Caption: é o que o seu usário verá, a opção em si, utilize o caracter & para colocar atalhos nas opções (ex: &Arquivo) 3.3.Check: permite que você crie uma marca no item de menu, assim você pode criar opções do tipo habilitado ou não. 3.4.Default: permite que uma das opções de um dos itens do submenu fique em negrito. 3.5.GroupIndex: cria para um determinado Grupo de submenu um indice, uma marca, determinante, assim você pode dizer os itens do grupo 1 estão desabilitados, os do grupo 2 estão habilitados e assim vai. 3.6.HelpContext: desloca automaticamente ao contexto selecionado ao ser chamado um arquivo de auxílio, se o HelpContext for igual a 0 não envia para contexto nenhum. 3.7.Hint: Pequeno auxílio para o item do menu, mas essa propriedade deve ser visualizada através de um objeto do tipo StatusBar (localizado na Palheta Win32)
3.8.Name: Todos os objetos tem que ter, me recuso a escrever sobre essa propriedade, vou deixar vocês na dúvida. 3.9.RadioItem: Seleciona dentre um grupo (determinado pela propriedade GroupIndex) um único item do menu, por exemplo um submenu assim: Cor de Fundo, items: Azul, Vermelho ou Verde. 3.10.ShortCut: Cria um atalho rápido através do menu, por exemplo CRTL+C ou CTRL+V 3.11.Tag: Outra propriedade, em conjunto com a propriedade Name, que aparece em todos os objetos, independente da cor, raça ou credo, a Tag é uma variável inteira que você pode rotular para diversos usos como por exemplo transformar em Invisível todos os objetos que possuam a Tag igual a 10 ou pintar a fonte de azul-marinho todos os objetos da Tag 5. 3.12.Visible: Permite que o objeto fique visível ou não em tempo de execução. Prontinho com todas essas informações acredito que você já está pronto (e ansioso) para construir nosso menu. Vamos lá então. Na primeira janelinha, ou se você prefere no primeiro Item de Menu altere as seguintes propriedades: Caption - &Arquivo Hint - Arquivos principais do sistema.
Assim que você pressionar o Enter vai formar mais duas novas janelas uma lateral a Arquivo e uma logo abaixo dele, na janela abaixo, clique nela e altere as seguintes propriedades: Caption: &Cadastro Hint: Informações principais do sistema. ImageIndex: 0
Assim que você pressionar o Enter vai formar uma nova janela uma abaixo a Cadastro, ainda com o curso posiciona em Cadastro clique com o botão direito e no menu que aparecerá clique com o botão direito do mouse na opção Create Submenu, e será criada um item de menu lateral, clique nesse novo item e altere as seguintes propriedades, e a medida que for criando crie as demais opções: Caption: &Cidade Hint: função de editar e coordenar o arquivo de cidades Caption: &Grupo Hint: função de editar e coordenar o arquivo de grupos Caption: &Alimentos Hint: função de editar e coordenar o arquivo de alimentos
Caption: - (sinal de menos) O resultado será uma barra de separação
Caption: Cli&entes Hint: função de editar e coordenar o arquivo de clientes
Volta para aquela área abaixo do cadastro e altere a propriedade Caption: (Você não está enchergando ruim não é o traço de menos mesmo.) Isso produzirá o seguinte efeito:
E vamos a última opção deste submenu: Caption: &Sair Hint: Retorna ao Windows ShortCut: Ctrl+S ImageIndex: 10 Prontinho a subopção Arquivo ficou da seguinte maneira:
☞Importante - As imagens aparecerão apenas fora do MenuEditor. Agora crie os outros submenus segundo definimos na apostila anterior, não se lembra ? então aqui estão eles: (com os respectivos Caption's, Hint's e caso tenham ImageIndex)
&Movimentação: informações constantes do sistema &Entrada do Cliente: recepção para os clientes e montagem e definição dos planos (ImageIndex: 1) &Saída do Cliente: fechamento da conta do cliente (ImageIndex: 2) &Massa Corporal: Cálculo da Massa Corporal e pesagem atual do cliente (ImageIndex: 3)
&Consulta: visões on-line dos arquivos &Pasta do Cliente: Verificação de determinado cliente, com gráficos sobre peso e massa coorporal (ImageIndex: 4) &Verificação do Caixa Mensal: Cálculo da arrecadação de um determinado mês
&Relatório: emissões na tela e em papel de um determinado momento dos arquivos &Correspondência: envio de corrêspondencia a clientes (ImageIndex: 9) Car&dápio: montagem de determinado cardápio diário baseado no número de calorias informadas &Divisão das Contas Mensal: fechamento das contas mensais e divisão dos lucros &Analítico das Contas Anual: resumo anual de toda a divisão efetuada Configura &Impressora: Verifica qual a impressora que será utilizada para as impressões (ImageIndex: 5)
Au&xílio: chama o help on-line do sistema &Conteúdo: Conteúdo do auxílio on-line (ImageIndex: 6) &Tópicos do Auxílio: Chama os tópicos do Auxílio on-line (ImageIndex: 7) Como &Usar o Auxílio: Como ultilizar o auxílio do windows (ImageIndex: 8) &Sobre o Sistema: Informações sobre a execução do sistema
4. Dê uma salvadinha no seu projeto, para tanto, no menu vá em File | Save All...: 4.1. Aonde aparece Unit1.pas (o Delphi está se referindo do nome do formulário) mude para fMenu.PAS 4.2. Aonde aparece Project1.dpr (o Delphi está se referindo do nome do projeto - que será o nome do executável final) mude para Peso.DPR 5. Pode sair do Menu Editor e testar seu menu. Clique agora em qualquer área vázia do formulário e vamos alterar algumas propriedades: 5.1. Caption - Sistema de Controle do SPA - Antes & Depois 5.2. Name - F_Menu 5.3. WindowState - wsMaximized (fará com que o formulário se inicie no modo maximizado) 6. Na Component Pallete localize uma página chamada Win32 e dentro dessa página de um clique no objeto StatusBar (acredito que seja o décimo quarto) e dê um clique no Form, foi criado tipo um painel na parte inferior do formulário. Altere as seguinte propriedades: 6.1. Name - BarraStat 6.2. Panels - Clique nos ... e clique três vezes no primeiro botãozinho (marcado com Add New (Ins) ) para criar 3 subpainéis e altere as seguintes propriedades de cada um: 6.2.1. Para o primeiro: Text - Bem Vindo... Width - 500 6.2.2. Para o segundo: Text - 99:99:99 Width - 60 Alignment - taCenter 6.2.3. Para o terceiro: Text - Criado por: Curso de Delphi Alignment - taCenter 7. Na Component Pallete localize uma página chamada System e dentro dessa página de um clique no objeto Timer (acredito que seja o primeiro) e dê um clique no Form, foi criado tipo um quadradinho representando o objeto.
Iniciando os programas do Menu Vamos começar agora a programar nosso Menu. Primeiramente vamos programar a Barra de Status, note que nela foram criados 3 painéis, ou três divisões, a primeira servirá para capturar os Hint de cada objeto do Menu (tMenuItem), a segunda mostrará a hora atual do micro com a ajuda do objeto Timer, e a terceira será uma propaganda fixa (isso é excelente quando queremos promover nossa SoftwareHouse). Para capturar os hint dos objetos precisamos criar um procedimento particular que faça esse desvio, para tanto, aperte o botão F12 para ir para a Code Editor e localize a seguinte parte: private { Private declarations } public E coloque o seguinte código: private procedure MontaHint(Sender: TObject); public
Agora abaixo da diretiva de compilação, insira o seguinte código: implementation {$R *.DFM} procedure TF_Menu.MontaHint(Sender: TObject); begin BarraStat.Panels[0].Text := Application.Hint; end; Isto transferirá o Hint do objeto selecionado para o primeiro painel da Barra de Status, mas precisamos iniciar, aperte a tecla F11 para chamar a Object Inspector e selecione o objeto F_Menu vá para a janela de eventos e dê um duplo clique para o evento OnCreate e coloque o seguinte código: procedure TF_Menu.FormCreate(Sender: TObject); begin Application.OnHint := MontaHint; end; Prontinho, agora vamos tratar do segundo painel, selecione novamente a Object Inspector e selecione o objeto Timer1 vá para a janela de eventos e dê um duplo clique para o evento OnTimer e coloque o seguinte código: procedure TF_Menu.Timer1Timer(Sender: TObject); begin BarraStat.Panels[1].Text := FormatDateTime('HH:MM:SS',Now); end; A cada segundo a hora será atualizada, não se preocupe que isso não afetará em nada o desempenho do sistema. Bem agora vamos colocar alguns comandos básicos, inicialmente, aperte F12 para voltar a ter a visão do formulário, e clique em Arquivo e Sair, coloque o seguinte código: procedure TF_Menu.Sair1Click(Sender: TObject); begin Close; end; O comando Close fará com que o formulário seja encerrado, como é o próprio Menu do Sistema, então o Sistema será encerrado.
Codificando o Auxílio Uma coisa interessante sobre o Delphi é como ele facilmente chama e executa arquivos .HLP, enquanto que para muitos softwares isso é algo do outro mundo, no Delphi basta, simplesmente executarmos alguns comandos pré-programados, além de que diversos objetos tem a propriedade HelpContext que permite que o arquivo de ajuda seja acionado a partir da tecla F1 a partir de um tópico Pré-Definido. Futuramente veremos como criar nosso arquivo de auxílio, mas, por enquanto vamos utilizar o arquivo enviado juntamente com esta apostila. A partir do Menu Principal vá em Project | Options... na página Applications altere as seguintes propriedades:
Title: Controle do SPA HelpFile: Peso.HLP As palavras-chaves para o comando HelpCommand são: Comando
Parâmetro Passado
Utilização
HELP_CONTEXT
Inteiro longo, contendo o número do contexto.
Mostra o auxílio a partir de tópico selecionado identificado a
partir do número do contexto definido pela seção [MAP] do arquivo .HPJ HELP_CONTENTS Ignorado. Normalmente passado 0.
Mostra o conteúdo do primeiro tópico definido pela seção [MAP] do arquivo .HPJ
HELP_SETCONTENTS
Inteiro longo, contendo o número do contexto Determina a chamada do tópico determinado que foi designado como tópico de conteúdo.através do uso da tecla F1
HELP_CONTEXTPOPUP
Inteiro longo, contendo o número do contexto. Mostra uma janela Pop-Up com um tópico particular identificado pelo número do contexto definido pela seção [MAP]
do arquivo .HPJ HELP_KEY
Ponteiro longo como uma string contendo o tópico designado.
Mostra um tópico pesquisado em uma lista de palavras chaves. Esta palavra chave deve ser exatamente o
Ponteiro longo como uma string contendo o tópico designado.
Mostra um determinado tópico através de uma lista de palavras chaves. Se a palavra chave não for encontrada posiciona na palavra fonêtica mais perto.
texto procurado. HELP_PARTIALKEY
HELP_MULTIKEY Ponteiro longo para uma estrutura de Mostra o tópico indentificado pela palavra TMULTIKEYHELP. Esta estrutura específica de chave ou uma chave da tabela alternada. caracteres e palavras chaves. HELP_COMMAND Ponteiro longo, contém a macro para a execução
Executa um macro help.
HELP_SETWINPOS Ponteiro longo para uma estrutura de Mostra um help do windows com um mínimo de TMULTIKEYHELP. Esta estrutura específica memória, variando o tamanho e a posição de contém o tamanho e a posição da janela do help acordo primário ou a janela secundária para ser mostrado. com o dado passado. HELP_FORCEFILE Ignorado. Normalmente passado 0.
Executa o WinHelp mostrando o arquivo de auxílio corrijido.
HELP_HELPONHELP
Ignorado. Normalmente passado 0.
Mostra o auxílio de como usar o auxílio.
HELP_QUIT
Ignorado. Normalmente passado 0.
Solicita o fechamento do auxílio ativo.
De posse desse nosso dicionário de comandos, aperte F12 e clique em Auxílio e Conteúdo, e insira o seguinte código: procedure TF_Menu.Contedo1Click(Sender: TObject); begin Application.HelpCommand(HELP_CONTENTS, 0); end; Aperte F12 e clique em Auxílio e Tópicos do Auxílio, e coloque o seguinte código: procedure TF_Menu.TpicosdoAuxlio1Click(Sender: TObject); const EmptyString: PChar = ''; begin
Application.HelpCommand(HELP_PARTIALKEY, Longint(EmptyString)); end; E finalmente, aperte F12, clique em Auxílio e Como usar o Auxílio, e coloque o seguinte código: procedure TF_Menu.ComoUsaroAuxlio1Click(Sender: TObject); begin Application.HelpCommand(HELP_HELPONHELP, 0); end; Vamos completar o comando de sair colocando também o encerramento do arquivo de auxílio, aperte F12 e clique em Arquivo e Sair, complete com seguinte código antes do comando Close: procedure TF_Menu.Sair1Click(Sender: TObject); begin Application.HelpCommand(HELP_QUIT, 0); Close; end; Rode sua aplicação e teste os comandos do Auxílio, caso a tecla F1 não ative o auxílio On-Line, provavelmente o seu menu está com a propriedade FormStyle em modo fsMDIForm, coloque-a no modo fsNormal. Se mesmo assim ainda não funcionou, mude a propriedade HelpContext do formulário para 1.
Finalmente Uma dica interessante é que o Fórmulário está associado ao Menu através da propriedade Menu, é que ela é possível de ser alterada em modo Run-Time, então imagine que num mesmo formulário é possível ter vários Menus diferentes, cada um se adaptando a uma situação do usuário (financeiro, administrador, digitador). Na próxima apostila, vamos criar as janelas auxiliares Splash e Sobre o Sistema.
9 Curso de Delphi 4.0 - Apostila 9 Autor: Fernando Antonio F. Anselmo eMail: [email protected] Pré-Requisitos: • • • •
Windows 98 Delphi 4.0 versão Client/Server Suite BDE 5.00 MS-Access 97
Arquivos trabalhados juntos com esta apostila: • •
IMGGER.BMP IMGICO.BMP
Prefácio Salve, a apostila de hoje faz parte do chamado propaganda do sistema, o ambiente Windows conseguiu trazer consigo mais do que simplesmente um ambiente gráfico de janelas, trouxe uma coisa muito importante, alias foram duas, note que todo o sistema ditos "for Windows" carregam consigo essas duas importantes e imprescindíveis janelas. Splash Screen, não isso não é nada do outro mundo, ouvimos e vimos falar de uma janela Splash desde a primeira vez que entramos no Word, no Access e até mesmo o Delphi tem a sua janela Splash, não precisa você ficar procurando por ela, ela está logo na nossa cara assim que entramos em qualquer desses aplicativos, e a chamada janela inicial. Sobre o Sistema, para que serve ? como surgiu ? como começou ? ninguém sabe, sabe-se apenas que todo o sistema que se preza tem que ter a sua, algumas bem incrementandas contendo os famosos "Ovos de Páscoa", aquela combinação maluca de teclas que antes de iniciarmos a janela Sobre é mostrado algo mais, as vezes pode até ser um joguinho. A Splash Screen e a Sobre o Sistema são janelas que a maioria dos programadores não dá a menor importância, mas que bem feita pode ser como um Out-Door na estrada, rendendo-nos uma bela propaganda gratuita da nossa empresa. Vou tentar ensinar aqui alguns macetes como se criar ambas as janelas com um pouco de incrementação, vamos nessa então.
Splash Screen Inicialmente deixe-me dizer uma coisa, a Splash é apenas uma janela pedindo para o usuário ter um pouco de paciência enquanto todo o sistema se inicia, não a faça demorada demais pois a última coisa que o usuário precisa e de mais paciência, tem gente que coloca um timer nelas para poder demorar ou então um simples comando For i := 1 to 10000 não façam isso, inicialmente pode parecer que a janela pouco vai aparecer, mas não se preocupe com o tempo, e o sistema crescendo, essa janela vai acabar demorando o tempo suficiente para que o usuário possa ver as informações descritas nela e não se aborrecer. Para começarmos abra o sistema e a partir do Menu Principal clique em File | New Form criando um novo formulário que será a nossa área de trabalho, vamos aos passos:
1. Altere as seguintes propriedades desta janela: 1.1. BorderStyle - bsNone - A borda em volta da janela, incluindo a tarja azul desapareça. 1.2. Name - F_Splash. 1.3. Position - poScreenCenter - A janela aparecerá centralizada no vídeo. 2. Na Component Pallete localize uma página chamada Additional e dentro dessa página de um clique no objeto Image (acredito que seja o sexto) e dê um clique no Form, foi criado tipo um painel pontilhado no formulário. Altere as seguinte propriedades: 2.1. Picture - clique nos ... clique no botão Load e localize o arquivo IMGGER.BMP (enviado) 2.2. Transparent - True - Isso fará com que a cor da posição 0,0 seja a base para que a imagem fique transparente, então dentro da imagem aonde tiver cor semelhante ficará transparente. 3. Na Component Pallete localize uma página chamada Standard e dentro dessa página de um clique no objeto Label (acredito que seja o terceiro) e dê um clique no Form. Altere as seguinte propriedades: 3.1. Caption - Produzido por ... 3.2. Font - clique nos ... e altere as seguintes propriedades: Fonte: MS Sans Serif Estilo da Fonte: Negrito Tamanho: 10 3.2. Transparent - True - Isso fará com que a cor de fundo do objeto Label fique transparente.
Prontinho de uma comparada e veja como ficou, agora salve esse formulário com o nome de fSplash, já temos agora em nosso projeto a nossa Splash Screen mas ainda falta um pequeno toque, clique no formulário e selecione o evento OnCreate, dê um duplo clique neste evento e digite o seguinte comando: procedure TF_Splash.FormCreate(Sender: TObject); begin Brush.Style := bsClear; end; Este simples comando produzido no evento de criação fará com que todo o formulário fique também transparente, então na verdade dentro da nossa Splash só aparecerá a Imagem e o Label, agora precisamos chamá-la do nosso sistema.
☞Importante - Peço por favor a maior atenção para o próximo passo pois mecheremos em áreas delicadas do nosso projeto. Antes de começarmos deixe-me dizer-lhes uma curiosidade sobre o Pascal, um projeto em Pascal sempre existe apenas um ÚNICO programa, o resto é tudo UNIDADES de sistema, pensam que estou
mentindo ? Olhem na primeira linha de qualquer formulário, aparecerá escrito UNIT tal, mas aonde então está o nosso Programa ? Quando você inclui um novo formulário ao projeto, o Delphi se encarrega automaticamente de criar as chamadas a esta nova Unidade alterando por si só o nosso Programa, infelizmente ele não tem uma área para fazer isso automaticamente com uma janela Splash então teremos que colocar na mão. A partir do menu principal clique em View | Project Source e aí está o nosso único PROGRAM do sistema todo, ele recebe exatamente o nome do nosso Projeto, vamos as alterações, localize o comando BEGIN e insira os seguintes comandos: begin Application.Initialize; Application.Title := 'Controle do SPA'; Application.HelpFile := 'Peso.hlp'; F_Splash := TF_Splash.Create(Application); F_Splash.Show; F_Splash.Update; Application.CreateForm(TF_Menu, F_Menu); Application.Run; end. Ou seja com estes três comandos, nos Criaremos a janela de Splash, chamaremos ela (não passando o controle para ela) e forçaremos sua aparição.
☞Importante - Existem dois comandos para se chamar um Formulário, são eles: SHOW - Chama o formulário sem passar o controle para ele, ou seja o programa que o chamou ainda possui o controle da ação. SHOWMODAL - Chama o formulário passando o controle da ação para ele até que ele seja finalizado. Bem, feito isso, agora só falta destruirmos nossa janela quando o sistema começar a execução, você pode colocar o comando: F_Splash.Free antes do comando Application.Run mas pessoalmente eu prefiro finalizá-la apenas quando o menu efetivamente for criado, então chame o formulário do Menu e para o evento OnShow coloque o comando: procedure TF_Menu.FormShow(Sender: TObject); begin F_Splash.Free; end; Não se esqueça de logo após a diretiva de compilação acrescentar a utilização da Unidade, desta maneira: {$R *.DFM} uses fSplash;
Sobre o Sistema A partir do Menu Principal clique em File | New Form criando um novo formulário que será a nossa área de trabalho, vamos aos passos: 1. Altere as seguintes propriedades desta janela: 1.1. BorderStyle - bsDialog 1.2. Caption - Sobre o Sistema...
1.3. Name - F_Sobre. 1.4 Position - poScreenCenter - A janela aparecerá centralizada no vídeo. 2. Na Component Pallete localize uma página chamada Standard e dentro dessa página de um clique no objeto Panel (acredito que seja o último) e dê um clique no Form. Altere as seguinte propriedades: 2.1. BevelInner - bvLowered - Borda interna rebaixada 2.2. BevelOuter - bvRaised - Borda externa levantada 2.3. BevelWidth - 2 - Espessura da borda
☞Importante - Para os tópicos 3 e 4, antes de clicar nos objetos indicados clique primeiramente neste objeto Panel criado. 3. Na Component Pallete localize uma página chamada Additional e dentro dessa página de um clique no objeto Image (acredito que seja o sexto) e dê um clique no objeto Panel. Altere as seguinte propriedades: 3.1. Picture - clique em ... clique no botão Load e localize o arquivo IMGICO.BMP (enviado) 3.2. Transparent - True - Isso fará com que a cor da posição 0,0 seja a base para que a imagem fique transparente, então dentro da imagem aonde tiver cor semelhante ficará transparente. 4. Na Component Pallete localize uma página chamada Standard e dentro dessa página traga três objetos Label (acredito que seja o terceiro) para dentro do objeto Panel. Altere as seguinte propriedades: 4.1. Objeto Label1: 4.1.1. Caption - Sistema de Controle do SPA 4.1.2. Font - clique nos ... e altere as seguintes propriedades: Fonte: MS Sans Serif Estilo da Fonte: Negrito Tamanho: 10 Cor: Castanho 4.2. Objeto Label2: 4.2.1. Caption - Versão Beta 1 4.2.2. Font - clique nos ... e altere as seguintes propriedades: Fonte: MS Sans Serif Estilo da Fonte: Itálico Tamanho: 8 Cor: Castanho 4.3. Objeto Label3: 4.3.1. Caption - Copyright © Curso Delphi 1998 - Junho 4.3.2. Font - clique nos ... e altere as seguintes propriedades: Fonte: MS Sans Serif Estilo da Fonte: Normal Tamanho: 8 Cor: Castanho 5. Na Component Pallete ainda na página Standard dentro dessa página de um clique no objeto GroupBox (acredito que seja o décimo segundo) e dê um clique no Form. Altere as seguinte propriedades: 5.1. Caption - Dados Técnicos 5.2. Font - clique nos ... e altere as seguintes propriedades: Fonte: MS Sans Serif Estilo da Fonte: Negrito Tamanho: 8 Cor: Castanho
☞Importante - Para o tópico 6, antes de clicar no objeto indicado clique primeiramente neste objeto GroupBox criado. 6. Na Component Pallete ainda na página Standard e dentro dessa página traga quinze objetos Label
(acredito que seja o terceiro) para dentro do objeto Panel. Altere as seguinte propriedades: 6.1. Para os primeiros Sete labels (coloque um abaixo do outro) mudando a propriedade Font de todos para: Font - clique nos ... e altere as seguintes propriedades: Fonte: MS Sans Serif Estilo da Fonte: Normal Tamanho: 8 Cor: Castanho E a propriedade Caption para: Caption do 1: Endereço Internet: Caption do 2: EMail: Caption do 3: Versão Windows: Caption do 4: Versão do DOS: Caption do 5: CPU: Caption do 6: Memória Livre: Caption do 7: Espaço Livre: 6.2. Coloque os próximos Oito labels na frente dos primeiros Sete (deixe o último sobrando) e altere a propriedade Font de todos para: Font - clique nos ... e altere as seguintes propriedades: Fonte: MS Sans Serif Estilo da Fonte: Normal Tamanho: 8 Cor: Azul-marinho A propriedade Name para: Name do 1: EnderNet Name do 2: EMail Name do 3: WinVersion Name do 4: DOSVersion Name do 5: CPU Name do 6: FreeMemory Name do 7: FreeDisk Name do 8: FreeResources Dos dois primeiros objetos altere as seguintes propriedades: Caption para: do 1: http://www.geocities.com/SiliconValley/Vista/3144 do 2: [email protected] Complete a propriedade Font de ambos para: Efeitos: Sublinhado Cursor de ambos para: crUpArrow 7. Finalmente na Component Pallete localize uma página chamada Additional e dentro dessa página de um clique no objeto BitBtn (acredito que seja o primeiro) e dê um clique no form. Altere as seguinte propriedades: 7.1. Kind - bkOK, isto trocará também as propriedades: Caption, Glyph e ModalResult. Compare agora como ficou a janela Sobre o Sistema
Iniciando o programa da Sobre o Sistema Notou que colocaremos algumas informações bem sofisticadas tais como Versão do Windows e DOS entre outras, mas vamos com calma, inicialmente clique no objeto EnderNet e para o evento OnClick insira o seguinte código: procedure TF_Sobre.EnderNETClick(Sender: TObject); const pEnderNET = 'http://www.geocities.com/SiliconValley/Vista/3144'; begin {$ifdef win32} ShellExecute(Handle, 'open', pEnderNET, nil, nil, SW_SHOW); {$endif} end; Este código fará com que seja executado um comando via API para uma chamada ao OLE para iniciar o Browser de Internet corrente com o comando a home-page especificada, as diretivas de compilação são para assegurar que o comando só seja executado em ambiente Win32. Clique agora no objeto EMail e para o evento OnClick insira o seguinte código: procedure TF_Sobre.EMailClick(Sender: TObject); const pEMail = 'mailto:[email protected]'; begin {$ifdef win32} ShellExecute(Handle, 'open', pEMail, nil, nil, SW_SHOW); {$endif} end; Novamente é realizado um comando via API para uma chamada ao OLE desta vez para iniciar o servidor de eMail corrente criando uma nova correspondência para o endereço eMail especificado. Clique agora no objeto F_Sobre e para o evento OnShow insira o seguinte código: procedure TF_Sobre.FormShow(Sender: TObject);
var OsInfo: TOSVERSIONINFO; SysInfo: TSYSTEMINFO; MemStat: TMEMORYSTATUS; DiskNo: Integer; begin OsInfo.dwOSVersionInfoSize := sizeof(TOSVERSIONINFO); GetVersionEx(OsInfo); // Versão do Windows case OsInfo.dwPlatformId of VER_PLATFORM_WIN32s : WinVersion.Caption := 'Windows 3.1'; VER_PLATFORM_WIN32_WINDOWS : WinVersion.Caption := 'Windows 95'; VER_PLATFORM_WIN32_NT : WinVersion.Caption := 'Windows NT'; end; // Versão do DOS DosVersion.Caption := format('%d.%d Ver : %d', [OsInfo.dwMajorVersion,OsInfo.dwMinorVersion,LOWORD(OsInfo.dwBuildNumber)]); // Pega o processador GetSystemInfo(SysInfo); case SysInfo.dwProcessorType of PROCESSOR_INTEL_860 : CPU.Caption := format('%d %s',[SysInfo.dwNumberOfProcessors, 'Intel 8086']); PROCESSOR_INTEL_386 : CPU.Caption := format('%d %s',[SysInfo.dwNumberOfProcessors, 'Intel 80386']); PROCESSOR_INTEL_486 : CPU.Caption := format('%d %s',[SysInfo.dwNumberOfProcessors, 'Intel 80486']); PROCESSOR_INTEL_PENTIUM : CPU.Caption := format('%d %s',[SysInfo.dwNumberOfProcessors, 'Intel Pentium']); PROCESSOR_MIPS_R2000 : CPU.Caption := format('%d %s',[SysInfo.dwNumberOfProcessors, 'MIPS R2000']); PROCESSOR_MIPS_R3000 : CPU.Caption := format('%d %s',[SysInfo.dwNumberOfProcessors, 'MIPS R3000']); PROCESSOR_MIPS_R4000 : CPU.Caption := format('%d %s',[SysInfo.dwNumberOfProcessors, 'MIPS R4000']); PROCESSOR_ALPHA_21064 : CPU.Caption := format('%d %s',[SysInfo.dwNumberOfProcessors, 'ALPHA 21064']); PROCESSOR_PPC_601 : CPU.Caption := format('%d %s',[SysInfo.dwNumberOfProcessors, 'Power PC 601']); PROCESSOR_PPC_603 : CPU.Caption := format('%d %s',[SysInfo.dwNumberOfProcessors, 'Power PC 603']); PROCESSOR_PPC_604 : CPU.Caption := format('%d %s',[SysInfo.dwNumberOfProcessors, 'Power PC 604']); PROCESSOR_PPC_620 : CPU.Caption := format('%d %s',[SysInfo.dwNumberOfProcessors, 'Power PC 620']); end; MemStat.dwLength := sizeof(TMEMORYSTATUS); GlobalMemoryStatus(MemStat); // Memória Livre FreeMemory.Caption := format('Tot: %d KB Disp: %d KB', [Trunc(MemStat.dwAvailPhys/1024),Trunc(MemStat.dwTotalPhys/1024)]); // Recursos livres DiskNo := 3; FreeDisk.Caption := ''; FreeResources.Caption := ''; repeat if DiskNo < 7 then
FreeDisk.Caption := FreeDisk.Caption + format('%s: %d MB ', [Chr(DiskNo + Ord('A')- 1),Trunc(DiskFree(DiskNo)/1024/1024)]) else FreeResources.Caption := FreeResources.Caption + format('%s: %d MB ', [Chr(DiskNo + Ord('A')- 1),Trunc(DiskFree(DiskNo)/1024/1024)]); inc(DiskNo); until DiskFree(DiskNo)=-1; end; Basicamente são todos comandos API que fazem chamadas ao Windows solicitando as informações necessárias, apenas perderia tempo explicando comando a comando quando seria muito mais proveitoso que você consulte o Help e verifique os comandos utilizados para fazer as capturas, uma pequena observação, note que para capturar o processador me utilizei de determinadas constantes para facilitar o entendimento, elas devem então serem criadas, localize o comando VAR e entre este comando e o comando End de finalização do comando Type crie as seguintes constantes: public { Public declarations } end; const PROCESSOR_INTEL_860 = 860; PROCESSOR_INTEL_386 = 386; PROCESSOR_INTEL_486 = 486; PROCESSOR_INTEL_PENTIUM = 586; PROCESSOR_MIPS_R2000 = 2000; PROCESSOR_MIPS_R3000 = 3000; PROCESSOR_MIPS_R4000 = 4000; PROCESSOR_ALPHA_21064 = 21064; PROCESSOR_PPC_601 = 601; PROCESSOR_PPC_603 = 603; PROCESSOR_PPC_604 = 604; PROCESSOR_PPC_620 = 620; var F_Sobre: TF_Sobre; Para que todos os comandos API funcionem precisamos ainda disponibilizar a utilização da Unidade: ShellAPI, coloque então a declação dela no comando USES perto do comando INTERFACE. Pronto, agora basta chamarmos novamente nosso formulário que contém o Menu e chamarmos a janela do Sobre para tanto chame o formulário, clique em Auxílio | Sobre o Sistema e insira os seguintes códigos: procedure TF_Menu.SobreoSistema1Click(Sender: TObject); begin F_Sobre := Tf_Sobre.Create(Application); F_Sobre.ShowModal; F_Sobre.Free; end; Não se esqueça de logo após a diretiva de compilação acrescentar a utilização desta nova Unidade, desta maneira: {$R *.DFM} uses
fSplash, fSobre; Nota Importante: Note que para o formulário fMenu eu criei um novo comando USES enquanto que no formulário do fSobre eu apenas acrescentei no USES já existente, existe uma grande diferença entre ambos, no primeiro caso as unidades fSplash e fSobre não estão com os endereços fixados na área de memória no momento da criação do formulário, no segundo caso todas as unidades inclusive a ShellApi estão com os endereços de memória reservado assim que o formulário é criado.
Retirando os formulários da Área de Memória Falando em áreas de memória, os formulários só devem ser criados (a excessão óbvia do fMenu) quando o usuário necessitar deles, ou seja, se o usuário que chamar o FSobre então o sistema deve criá-lo, chamá-lo e depois removê-lo completamente da área de memória, isto é feito pois o Delphi se utiliza da área de memória baixa para manter os endereços do objetos criados, ou seja o Delphi faz uso dos 640 Kb desta memória, então não adianta ter um Pentium com 64 Megas de memória, pois o disponível para execução dos formulário é apenas aquela taxa de 640 Kb, e deve ser muito menos, pois o Windows também utiliza ela, e outros aplicativos também. Precisamos então aliviar o máximo esta área, para isso no Menu Principal clique em Project | Options... na folha Forms selecione F_Splash e F_Sobre e clique no botão > mandando ambas para a área dos Avaliable Forms isto será feito com todas as outras janelas a exceção da DModelo que será o nosso DataModule.
Finalmente Pode executar o sistema e apreciar a propaganda da Splash e da Sobre, novamente digo não se preocupe com a rapidez que a janela Splash vai aparecer, quanto mais inserirmos no sistema mais demorado esta janela ficará. Na próxima apostila, vamos discutir o assunto de como juntar todas as nossas regras de negócio num único e simples DATA MODULE.
10 Curso de Delphi 4.0 - Apostila 10 Autor: Fernando Antonio F. Anselmo eMail: [email protected] Pré-Requisitos: • • • •
Windows 98 Delphi 4.0 versão Client/Server Suite BDE 5.00 MS-Access 97
Arquivos trabalhados juntos com esta apostila: •
BASICO.MDB
Prefácio Salve, nesta apostila desvendaremos a utilização dos Data Modules. Os Data Modules não são um bicho de sete cabeças, na verdade ele tem oito e mais uma que vive escondida esperando para te dar aquela dentada. Mas, você verá é que depois de domesticado ele se torna um fiel e amável bichinho de nove cabeças, você deve é tomar cuidado para não cortar nenhuma delas pois sempre nascem mais duas no lugar.
Primeira Cabeça - Quando nasceu Os Data Modules surgiram a partir do Delphi 2.0, então não adianta você ficar procurando naquela sua antiga versão de Delphi 1.0, com a necessidade de organizar os formulários, pois ficava aquele monte de objetos invisíveis em tempo de execução tipo tTable, tDataSource e tQuery perdidos, fora que você sempre tinha que definir em dois formulários diferentes a mesma tabela, os mesmos campos, as mesmas ligações, isto gastava tempo e muito espaço do sistema.
Segunda Cabeça - Invisibilidade Os Data Modules são parentes primários dos formulários, eles são uma espécie de "Nehandertal" dos formulários, não são visíveis em tempo de execução, então não adianta tentar dar um comando do tipo Show para mostrá-los pois todos são envergonhados e detestam aparecer, eles só servem para uma única função controlar e armazenar objetos invisíveis como eles, então não tente colocar um tEdit ou um tImage dentro deles que eles não deixarão. Outra característica dos Data Modules é que eles adoram ser criados automaticamente, quando os tiramos daquela área dos Auto-Create Forms eles simplesmente somem do projeto, você pode até ficar criando os Data Modules na mão, dando aqueles comandos de criação, mas em todo o nosso projeto será apenas um único Data Module, então além do Menu deixe-o quietinho na área dos Auto-Create.
Terceira Cabeça - Relação Data Module X Formulário É possível criar um Data Module para cada formulário, mas este não é o objetivo para o qual eles foram criados, a maneira mais racional de se trabalhar com eles é criar um único Data Module abrigando todas as tabelas, montando as regras de negócio, criando e definindo os campos das tabelas além de outros
objetos invisíveis que o sistema poderá a necessitar. O Data Module é um espécie de armazém do nosso sistema, guarde nele tudo o que for globalmente usado, como por exemplo variáveis, funções ou procedimentos basta apenas definí-los em sua área Public e depois declarar o Data Module no comando Uses da nossa unidade.
Quarta Cabeça - Criando a 1a. Conexão Vamos começar nosso desenvolvimento criando o Banco de Dados que abrigará o nossas tabelas do sistema, pegue novamente a Apostila 7 e veja como ficou o nosso Banco de Dados e crie-o com o MSAccess 97 (ou então utilize o MBD enviado) o nome do nosso banco será BASICO.MDB, na Apostila 2 mostrei como se cria um Alias, precisamos criar outro para este sistema. Abra o aplicativo BDE Administrator para criar o Alias para o Banco de Dados enviado. 1. A partir do BDE Administrator aberto vá em Object | New... (ou simplesmente CTRL+N) e modifique a janelinha que aparece para o Database Driver Name para MSACCESS e pressione a tecla OK. 2. Mude o nome do seu novo alias para AlPeso. 3. Altere a propriedade DATABASE NAME para C:\CursoDelphi\Peso\basico.mdb e confirme as alterações em Object | Apply (ou simplesmente CTRL+A, ou ainda clique no quarto botão da barra de ferramentas). 4. Teste seu novo alias clicando em Object | Open seu alias deve formar um quadradinho luminoso em volta do objeto. 5. Feche-o em em Object | Close. Volte para o Delphi e reabra novamente o projeto PESO.DPR, a partir do Menu Principal clique em File | New Data Module criando a seguinte janela:
Altere a propriedade Name para D_Modelo e salve o Data Module com o nome de dModelo. Na Component Pallete localize uma página chamada DataAccess e dentro dessa página de um clique no objeto DataBase (acredito que seja o quinto) e dê um clique dentro do Data Module criado. Altere as seguinte propriedades: AliasName - AlPeso - Nome do Alias de Conexão DataBase Name - DNmPeso - Nome da Base de Dados Interna Name - PrjPeso - Nome do Objeto
Quinta Cabeça - Criando a 2a. Conexão Vamos agora criar toda a nossa regra de negócio, ou seja, vamos criar todos os objetos tDataBase, tTable, tQuery e quaiquer outro que necessitaremos e que utilizaremos ao longo de todo esse projeto e qual a
forma como as tabelas se relacionam. Na Component Pallete ainda uma página chamada DataAccess e dentro dessa página traga nove objetos Table (acredito que seja o segundo), um objeto DataSource (acredito que seja o primeiro) e um objeto Query (acredito que seja o terceiro). Altere as seguinte propriedades: Para os objetos Tables e Query altere a propriedade DataBaseName para DNmPeso Para os objetos Tables altere as propriedades TableName, Name e IndexFieldName respectivamente: TableName Alimento Cidade Cliente Grupo Pasta_Cliente Peso_Cliente Resumo_Mensal Telefone_Cliente
Name tbAlimento tbCidade tbCliente tbGrupo tbPasta_Cliente tbPeso_Cliente tbResumo_Mensal tbTelefone_Cliente
IndexFieldName COD_ALIMENTO SIG_CIDADE NUM_CPF NUM_GRUPO NUM_CPF;DAT_CORRENTE NUM_CPF;DAT_MEDIDO ANO_MES NUM_CPF;NUM_TELEFONE
Para o objeto DataSource altere as propriedades: DataSet - tbCliente Name - DsCliente Para o objeto tbTelefone_Cliente altere as propriedades: MasterSource - DsCliente MasterFields - NUM_CPF Isto fará com que esta tabela automaticamente se relacionem com a tabela de Cliente através do campo chave NUM_CPF, o mesmo será colocado automaticamente quando de uma inclusão, mantendo assim a integridade referencial com este. Altere a propriedade Name do objeto Query1 para QrySql Prontinho, deve ter ficado algo parecido com isso:
Sétima Cabeça - Criando os campos Uma coisa prática que podemos fazer é a definição dos campos de cada tabela, isto servirá para que quando mostremos esta tabela através de um objeto dbGrid o Delphi o trate pelo nome que desejamos e não como NUM_CPF por exemplo, outra parte interessante é que aqui podemos definir as máscaras para os
campos. Para criar os objetos fields, dê um duplo clique em cima de qualquer tabela e aparecerá a janela Definition Fields, clique com o botão direito nela e aparecerá o menu popup conforme a figura a seguir:
Clique em Add fields... e clique no botão OK para inserir todos os campos, vou agora descrever campo a campo de cada tabela e as propriedades que devem ser trocadas, cabe a você entrar em tabela a tabela e ir criando e alterando os campos: Tabela Currency
Campo
DisplayLabel
tbAlimento tbAlimento tbAlimento tbAlimento tbResumo_Mensal tbResumo_Mensal True tbResumo_Mensal True tbResumo_Mensal True tbResumo_Mensal True tbCliente tbCliente tbCliente tbCliente tbCliente tbCliente tbCliente tbCliente tbCliente tbGrupo tbGrupo
COD_ALIMENTO NUM_GRUPO NOM_ALIMENTO QTD_PERMITIDA ANO_MES VAL_MEDICO
Código Núm Grupo Nome Qtd Permitida Ano e Mês Valor Médico
EditMask
>a;0;_
9999\/99;0;_
VAL_COORDENADOR Valor Coordenador VAL_NUTRICIONISTA Valor Nutricionista VAL_DESPESA
Valor Despesa
NUM_CPF SIG_CIDADE NOM_CLIENTE END_CLIENTE BAI_CLIENTE CEP_CLIENTE DES_EMAIL ALT_CLIENTE DAT_NASCIMENTO NUM_GRUPO DES_GRUPO
CPF Cliente Sigla da Cidade Nome Endereço Bairro CEP eMail Altura (Cm) Data de Nascimento Número Descrição
000\.000\.000\/00;0;_ >aaa;0;_
00\.000\-000;0;_
!99/99/0000;1;_ >a;0;_
tbTelefone_Cliente tbTelefone_Cliente tbTelefone_Cliente tbPasta_Cliente tbPasta_Cliente tbPasta_Cliente tbPasta_Cliente tbPasta_Cliente tbPasta_Cliente tbPasta_Cliente True tbPasta_Cliente True tbCidade tbCidade tbCidade tbPeso_Cliente tbPeso_Cliente tbPeso_Cliente
NUM_CPF NUM_TELEFONE DES_FUNCAO NUM_CPF DAT_CORRENTE PLN_ADOTADO QTD_CALORIA OBS_PASTA DAT_PAGAMENTO VAL_TOTAL
CPF Cliente Núm Telefone Função CPF Cliente Data Corrente Plano Adotado Qtd Calorias Observações Data Pagamento Valor Total
VAL_DESCONTO
Valor Desconto
SIG_CIDADE NOM_CIDADE SIG_UF NUM_CPF DAT_MEDIDO PES_MEDIDO
Sigla Nome UF CPF Cliente Data Medição Peso Medido
000\.000\.000\/00;0;_ \(0000\) 000\-0000;0;_ 000\.000\.000\/00;0;_ !99/99/0000;1;_ >a;0;_ 0000;0;_ !99/99/0000;1;_
>aaa;0;_ >AA;0;_ 000\.000\.000\/00;0;_ !99/99/0000;1;_
Oitava Cabeça - Coficando a entrada das tabelas Um grande problema que existe quando se troca de bancos de dados em sistemas com o Delphi é quanto ao nome das tabelas, quem já tentou por exemplo mudar do Paradox para o Oracle viu que nem por mais cuidado se tome sempre acaba tropeçando nos chamados Domínios do Oracle, que são iniciais automáticas que ele coloca para definir quem é o dono das tabelas. O problema uma mudança de nome em qualquer ponto pode ser desastroso, e isso não se limita apenas ao Oracle serve para qualquer outra migração de base de dados, para evitar este pequeno problema, vamos adotar em nosso sistema oito variáveis globais, cada uma contendo e carregando consigo o nome da tabela. Outra coisa que precisamos controlar é a entrada do sistema, verificarmos se foi feito a conexão corretamente entre o objeto TDataBase e o Alias para ambas: 1. Alterne para o Code Editor e localize a seguinte porção do código: private { Private declarations } public { Public declarations } e coloque o seguinte: private { Private declarations } public nmAlimento, nmCidade, nmGrupo, nmPasta_Cliente, nmPeso_Cliente, // nmResumo_Mensal, nmTelefone_Cliente, nmCliente : String; end; 2. Selecione o objeto D_Modelo e para o evento OnCreate insira o seguinte código: procedure TD_Modelo.D_ModeloCreate(Sender: TObject); var Conexao : Boolean; begin
// Atribui os nomes externos as variáveis nmAlimento := 'ALIMENTO'; nmCidade := 'CIDADE'; nmGrupo := 'GRUPO'; nmPasta_Cliente := 'PASTA_CLIENTE'; nmPeso_Cliente := 'PESO_CLIENTE'; nmResumo_Mensal := 'RESUMO_MENSAL'; nmTelefone_Cliente := 'TELEFONE_CLIENTE'; nmCliente := 'CLIENTE'; // Atribui os nomes das variáveis aos nomes das tabelas tbAlimento.TableName := nmAlimento; tbCidade.TableName := nmCidade; tbGrupo.TableName := nmGrupo; tbPasta_Cliente.TableName := nmPasta_Cliente; tbPeso_Cliente.TableName := nmPeso_Cliente; tbResumo_Mensal.TableName := nmResumo_Mensal; tbTelefone_Cliente.TableName := nmTelefone_Cliente; tbCliente.TableName := nmCliente; // Testa a conexão try PrjPeso.Connected := True; if not PrjPeso.IsSQLBased then PrjPesoLogin(PrjPeso, nil); Conexao := True; except MessageDlg('Erro na Conexão do Banco de Dados', mtError, [MbOk], 0); Conexao := False; end; if not conexao then begin MessageDlg('Sistema cancelado...', mtError, [MbOk], 0); Application.Terminate; end; end; 3. Selecione o objeto PrjPeso e para o evento OnLogin insira o seguinte código: procedure TD_Modelo.PrjPesoLogin(Database: TDatabase; LoginParams: TStrings); begin LoginParams.Values['USER NAME'] := ''; LoginParams.Values['PASSWORD'] := ''; end; 4. Para terminar a conexão, quando o sistema for encerrado, selecione o objeto D_Modelo e para o evento OnDestroy insira o seguinte código: procedure TD_Modelo.D_ModeloDestroy(Sender: TObject); begin PrjPeso.Connected := False; end;
Nona Cabeça - Funções Particulares e as regras de negócio Todas as amarrações que normalmente são definidas por DBA do banco de dados, criando Stored Procedures e Triggers para a administração do banco podem ser reproduzidas perfeitamente aqui, vou citar alguns exemplos e você terá uma boa base para criar outras que serão necessários aos seus sistemas.
Já falei antes e vou repetir agora, não sou muito fã de campos do tipo AutoIncremento, primeiro porque não são todos os bancos que os implementam e segundo porque não sou eu quem o controla, assim já que não posso arrumá-lo ou liberá-lo quando desejar, não posso criar meu próprio passo e inúmeras outras coisas, isto em bancos complexos é realizado criando Stored Procedures, procedimentos prontos em linguagens SQL que são chamados em determinados momentos, mas estamos utilizando o MS-Access aqui, e amanhã podemos usar o Oracle no dia seguinte o InterBase imagine o tempo que ficariamos com o sistema parado nas famosas ADAPTAÇÕES. Para gerar um número automático para um campo qualquer precisamos apenas seguir os seguintes passos: 1. Crie uma chamada a uma função particular: private function Maximo(nmCampo, nmTabela: String) : integer; public 2. Crie a função: function TD_Modelo.Maximo(nmCampo, nmTabela: String) : integer; begin with QrySQL do begin if Active then Close; SQL.Clear; SQL.ADD('SELECT MAX(' + NmCampo + ') FROM'); SQL.ADD(NmTabela); Open; result := Fields[0].AsInteger + 1; Close; end; end; 3. Para o evento AfterInsert do objeto tbAlimento coloque a seguinte codificação: procedure TD_Modelo.tbAlimentoAfterInsert(DataSet: TDataSet); begin tbAlimentoCOD_ALIMENTO.AsInteger := Maximo('COD_ALIMENTO',nmAlimento); end; Resolvido as crises com os números automáticos, a função recebe como parâmetro o nome do campo inteiro e o nome da tabela, então ela simplesmente monta uma cláusula SQL para procurar o maior valor daquele campo dentro da tabela e depois simplesmente soma mais um e devolve este resultado aonde o mesmo é jogado direto para o campo. Outras funções particulares que podemos colocar são para os eventos OnPostError e OnDeleteError para controlar falhas na gravação e ao invés de recebermos aquelas amigáveis mensagens binárias hexadecimais $FFFFFFF para a alegria e desespero do nosso usuário, aparecer controladamente algo mais agradável, então siga os passos: 1. Alterne para o Code Editor e defina os seguintes procedimentos antes da cláusula Private procedure TabelaErroPost(DataSet:TDataSet; E: EDataBaseError; var Action: TDataAction); procedure TabelaErroDelete(DataSet:TDataSet; E: EDataBaseError; var Action: TDataAction); private
2. Codifique agora os procedimentos: // Controla os Erros de Gravação coloque no Evento onPostError de todas as Tabelas procedure TD_Modelo.TabelaErroPost(DataSet:TDataSet; E: EDataBaseError; var Action: TDataAction); begin if (E is EDBEngineError) then begin MessageDlg('Impossível gravação: Provavelmente Registro Duplicado', mtWarning, [mbOk], 0); Abort; end; end; // Controla os Erros de Exclusão coloque no Evento onDeleteError de todas as Tabelas procedure TD_Modelo.TabelaErroDelete(DataSet:TDataSet; E: EDataBaseError; var Action: TDataAction); begin if (E is EDBEngineError) then begin MessageDlg('Impossível excluir: Provavelmente Registros Associados', mtWarning, [mbOk], 0); Abort; end; end; 3. Selecione todas as tabelas e para o evento OnPostError selecione (através da seta, não dê duplo clique) o procedimento TabelaErroPost e para o evento OnDeleteError selecione o procedimento TabelaErroDelete. Estes procedimentos foram criados para receberem os mesmos parâmetros do procedimento original ou seja, o DataSet vinculado, o código do erro e a ação a tomar, então basta simplesmente verificarmos se o código do erro é um EDBEngineError ou seja um erro de banco, darmos a nossa mensagem controlada e abortarmos o processo de gravação ou eliminação. Para as regras de negócio contamos com o evento OnValidate que cada campo separadamente possui, vou citar aqui uma das mais importantes regras: • •
Existem duas divisões entre 21 - 55 e 55 - 74 anos; Excluem-se clientes menores de 21 e maiores de 74 anos;
Isto é uma regra que o banco deve cumprir, normalmente isto é feito através do que chamamos de Triggers de banco (Gatilhos), mas esses "Gatilhos" variam muito de banco para banco, então pessoalmente prefiro colocá-los no Delphi pois assim permito a maleabilidade dos diversos bancos, vamos então implementar esta regra: 1. Dê um duplo clique na tabela de cliente, e selecione o campo DAT_NASCIMENTO. 2. Altere a propriedade Required para True, isto fará com que o campo tenha que ser preenchido obrigatoriamente. 3. Chame o evento OnValidate e insira os seguintes procedimentos: procedure TD_Modelo.tbClienteDAT_NASCIMENTOValidate(Sender: TField); var Idade: Integer; begin Idade := StrToInt(FormatDateTime('YY',Now - tbClienteDAT_NASCIMENTO.AsDateTime)); if (Idade < 21) or (Idade > 74) then raise Exception.Create('Este Cliente está com a idade fora da faixa'); end;
Criamos uma variável inteira aonde será calculado quantos anos este cliente possui, para isso, utilizamos a função FormatDateTime que devolve uma data com base de uma máscara formatada, isso vale para: Especificação c o fracionária d dd ddd dddd uma ddddd dddddd m ou mm um h ou mmm variável mmmm uma yy yyyy h hh n nn s ss t tt am/pm am' A misturado a/p
ampm
/ : "xx"
Mostra A data que usa o formato dada pelo ShortDateFormat variável global, seguiu até que usasse formato dado pelo LongTimeFormat variável global. O tempo não é exibido se a parte do valor do DateTime é zero. O dia como um número sem um zero principal (1-31). O dia como um número com um zero principal (01-31). O dia como uma abreviação (Sun-Sat) usando a string ShortDayNames que é uma variável global. Exibe o dia como um nome cheio (Sunday-Saturday) usando a string LongDayNames que é variável global. A data usando a string ShortDateFormat que é uma variável global. A data usando a string LongDateFormat que é uma variável global. O mês como um número sem um zero principal (1-12). Se a especificação de m segue um h especificar de hh imediatamente, então será exibido o minuto em lugar do mês. O mês como um número com um zero principal (01-12). Se a especificação de mm segue especificar um hh imediatamente, o minuto em lugar do mês é exibido. O mês como uma abreviação (Jan-Dec) usando a string ShortMonthNames que é uma global. O mês como um nome cheio (January-December) usando a string LongMonthNamesque é variável global. O ano como um número de dois-dígito (00-99). O ano como um número de quatro-dígito (0000-9999). Displays a hora sem um zero principal (0-23). A hora com um zero principal (00-23). O minuto sem um zero principal (0-59). O minuto com um zero principal (00-59). O segundo sem um zero principal (0-59). O segundo com um zero principal (00-59). O tempo que usa o formato dado pela variável global ShortTimeFormat. Exibe o tempo que usa o formato dado pela variável global LongTimeFormat. Usa a notação Hora-12 do relógio para o h precedendo ou especificado de hh, e exibições ' durante qualquer hora antes de meio-dia, e ' pm' durante qualquer hora depois de meio-dia. especificação pode ser usado em minúscula (am/pm), caso contrário (AM/PM), ou (Am/Pm) o resultado será exibido de acordo. Usa a notação Hora-12 do relógio para o h precedendo ou especificado de hh, e exibições ' a' durante qualquer hora antes de meio-dia, e ' p' durante qualquer hora depois de meio-dia. A especificação pode ser usado em minúscula (a/p), caso contrário (A/P), ou misturado (A/p) o resultado será exibido de acordo. Usa a notação Hora-12 do relógio para o h precedendo ou specifier de hh, e exibições os conteúdos da variável global TimeAMString durante qualquer hora antes de meio-dia, e os conteúdos da variável global TimePMString durante qualquer hora depois de meio-dia. Exibe o carácter separador de data dado pela variável global DateSeparator. Exibe o carácter separador de tempo dado pela variável global TimeSeparator. Carácter incluídos em plicks ( ' ) ou aspas ( " ) não afetam o formato.
Coloquei esta tabela, que pode ser encontrada no tópico do auxílio da função FormatDateTime apenas para que você não se esqueça o quão útil pode ser esta função no tratamento de Datas. O cálculo para a idade é feito da seguinte maneira, pegamos a data atual e subtraimos pela data de nascimento o resultado é convertido em anos pela função, depois basta apenas questionarmos se o valor está fora da faixa especificada. Outro tipo de Regra de Negócio que podemos aplicar e quanto a entrada padrão de determinados campos, supomos que queremos que toda vez que for dada a entrada dos campos na tabela Pasta do Cliente
os campos Plano Adotado receba o Plano A, Quantidade de Calorias receba 800 KCal e Data Corrente receba a Data Atual, esta Regra também pode ser determinada por certos bancos, mas para realizá-la no Delphi fazemos: 1. Selecione o objeto tbPasta_Cliente. 2. Para o evento onAfterInsert (depois de ser dado o comando Insert) coloque os seguintes códigos: procedure TD_Modelo.tbPasta_ClienteAfterInsert(DataSet: TDataSet); begin with tbPasta_Cliente do begin FieldByName('PLN_ADOTADO').AsString := 'A'; FieldByName('QTD_CALORIA').AsString := '0800'; FieldByName('DAT_CORRENTE').AsDateTime := Now; end; end; Acredito que não precisa de muita explicação para o que fiz, apenas mandei os valores especicados para cada campo. Estas regras podem ser aplicadas na medida que você precise delas, não precisando de bancos complexos como Oracle, MS-SQL ou Interbase entre outros, para obtê-las.
Finalmente Ao longo deste projeto ainda voltaremos por aqui para incluirmos novas funcionalidades globais, mas acredito que já deu para você perceber a utilíssima ferramenta que são os Data Modules. Na próxima apostila, nosso assunto será de construir os formulários que cadastrarão as tabelas básicas do sistema, ou seja, começaremos a construir nossas telas de entradas.
11 Curso de Delphi 4.0 - Apostila 11 Autor: Fernando Antonio F. Anselmo eMail: [email protected] Pré-Requisitos: • • • •
Windows 98 Delphi 4.0 versão Client/Server Suite BDE 5.00 MS-Access 97
Arquivos trabalhados juntos com esta apostila: • •
OBJETOS.WRI POO.WRI
•
Seguintes Objetos : • DgFiltro • DgPrint • SelectT • PosEstad
•
Seguintes Imagens : • ImgAnterior.BMP • ImgAvanca.BMP • ImgGrava.BMP • ImgCancela.BMP • ImgDesFiltro.BMP • ImgDuplFicha.BMP • ImgElimina.BMP • ImgEnviaArea.BMP
ImgFiltra.BMP ImgMarca.BMP ImgFormCons.BMP ImgPrimeiro.BMP ImgTabela.BMP ImgAvancaSalto.BMP ImgImprime.BMP ImgUltimo.BMP ImgInsere.BMP ImgFicha.BMP ImgInsLote.BMP ImgVaiMarca.BMP ImgLocaliza.BMP ImgVoltaSalto.BMP
Prefácio Salve, nesta apostila desvendaremos a primeira parte de como criar os cadastros. Mas antes de começarmos deixe-me explicar porque suspendi o curso durante o mês de Agosto. Todo o curso foi reformulado, tanto o ambiente como a linguagem, e aviso que isto sempre vai acontecer, porque sempre que pensei em lançar um curso deste nível também sempre desejei que as pessoas pudessem aprender o que existe de mais moderno sem ficar preso a uma linguagem ou ambiente antigo e morto, então não quero nem vou ficar esperando concluir ou terminar um módulo para mudar. Aconselho que você sempre se mantenha sempre atualizado em relação ao Delphi, ao ambiente Windows e ao Gerenciador de Banco de Dados MS-Access.
☞
Importante - Junto com esta estou disponibilizando na parte de Objetos um manual e todos os objetos necessários que iremos utilizar a partir de agora, então antes que você começe a desenvolver nesta apostila aconselho que você baixe e dê uma lida neste manual, instale e verifique a utilidade dos objetos disponibilizados, e também estou disponibilizando o Apêndice C para que você aprenda e compreenda mais um pouco sobre a linguagem Object Pascal.
Começando e Criando o Pai de Todos Em Orientação a Objetos a palavra-chave é Reaproveitamento, e isto é conseguido facilmente através da Herança dos Objetos primeiramente se ninguém nunca disse isso a você então vou ter a honra de falar primeiro, tudo no Delphi são objetos, inclusive e principalmente os formulários, eles são tratados como qualquer outro objeto, então existe a propriedade Herança para o reaproveitamento dos formulários, para não complicar muito esta apostila será dividida em duas partes (você verá que mesmo dividindo esta apostila em dois ela é bastante extensa). Neste primeiro momento criaremos o pano de fundo para todos os nossos cadastros, não pense que vai ser simples, pois em 17 anos programando mudei várias vezes minhas telas de cadastro desde que trabalhava com linguagens do tipo Natural e Cobol, venho aprimorando minhas telas, até que finalmente, graças a uma olhada num sistema me apaixonei logo de cara na tela de cadastro, mais pela simplicidade do que pelo número de funções fiz algumas mudanças e consegui chegar a uma tela de cadastro que julgo a ideal. Sendo simples e ao mesmo tempo complexa em número de utilidade que ela disponibiliza para o usuário. Para diminuir um pouco, ou se você prefere, para não assustar muito ao usuário dividi a parte central da tela em três partes: 1a. Parte. Mostra os dados em forma de uma FICHA, é como se o usuário estivesse navegando em uma gaveta dessas de bibliotecas e vasculhando as fichas que ele deseja utilizar, servindo também para incluir ou alterar qualquer ficha. 2a. Parte. Mostra os dados em forma de uma TABELA aberta ou como a forma de uma Planilha, esta deve dar a mobilidade necessária para que o usuário possa ver os dados num bloco, de maneira rápida e eficiente. 3a. Parte. Fica a cargo das pesquisas, relações e filtragens o que o usuário quiser fazer para poder visualizar seus dados da forma como ele julgar melhor.
Criando o Geral Para começarmos abra o sistema e a partir do Menu Principal clique em File | New Form criando um novo formulário que será a nossa área de trabalho, vamos aos passos: 1. Altere as seguintes propriedades desta janela: 1.1. BorderStyle - bsDialog - Uma janela diálogo padrão. 1.2. Name - F_Ficha. 1.3. Position - poScreenCenter - A janela aparecerá centralizada no vídeo.
☞Importante - salve o formulário com o nome de fFicha, e de vez em quando vá salvando para não perder o serviço. 2. Na Component Pallete localize uma página chamada Additional e dentro dessa página de um clique no objeto BitBtn (prendendo-o com a tecla Shift) e dê cinco cliques no Form, solte o objeto clicando no cursor reprensentado na Component Pallete, foram criados cinco botões, organize-os do lado esquerdo, um abaixo do outro deixando um espaço maior entre o quarto e quinto. Altere as seguinte propriedades dos quatro primeiros:
1 2 3 4
Glyph ImgInsere ImgGrava ImgCancela ImgElimina
Name ButInsert ButPost ButCancel ButDelete
Caption &Insere &Grava &Cancela &Elimina
Hint Inclui uma nova ficha Grava as alterações realizadas na ficha Cancela as alterações realizadas na ficha Apaga a Ficha corrente
2.1. Para o quinto botão altere a propriedade Kind para bkClose, e altere a propriedade Hint para Fecha esta janela. 2.2. Altere a propriedade ShowHint de todos para True. 3. Na Component Pallete ainda na página Additional dentro dessa página de um clique no objeto SpeedButton (prendendo-o com a tecla Shift) e dê dez cliques no Form, solte o objeto, foram criados dez botões pequenos, dois coloque-os no espaço entre o ButDelete e o BitBtn5 e estique-os para ficarem do mesmo tamanho, os outros oito organize-os na parte de baixo do formulário. Altere as seguinte propriedades:
1 2 3 4 5 6 7 8 9 10
Glyph ImgInsLote ImgDuplFicha ImgPrimeiro ImgVoltaSalto ImgAnterior ImgAvanca ImgAvancaSalto ImgUltimo ImgMarca ImgVaiMarca
Name ButFixIns ButDupField ButFirst ButRW ButPrior ButNext ButFF ButLast ButMark ButGotoMark
Caption Ins. &Lote &Dupl.Ficha
Hint Insere um conjunto de fichas Duplica determinada Ficha quando Inserir Primeira Ficha Volta o Salto das Fichas Ficha Anterior Próxima Ficha Salta Fichas Última Ficha Marca uma determinada Ficha Volta para a Ficha marcada
3.1. Altere as seguintes propriedades para os objetos ButFixIns e ButDupField: propriedade AllowAllUp altere para True e propriedade GroupIndex altere do primeiro para 1 e do segundo para 2. 3.2. Altere a propriedade ShowHint de todos para True. 4. Na Component Pallete ainda na página Additional pegue um objeto chamado Bevel e envolva os objetos ButMark e ButGotoMark. 5. Se perdeu ? Ok, vamos dar uma olhada para ver como está ficando a janela:
6. Na Component Pallete, na página Data Access clique no objeto DataSource e dê um clique no Form e altere a propriedade Name para dsVisao. 7. Na Component Pallete, na página Additional clique no objeto PosEstado (Olhe o Manual dos Objetos
para qualquer referencia) e dê um clique no Form bem abaixo do BitBtn5 e altere a propriedade DataSource para dsVisao e limpe a propriedade Caption. 8. Na Component Pallete, na página Data Controls clique no objeto DBMemo e dê um clique no Form e altere a propriedade Name para DBMemClip, a propriedade Visible para False e a propriedade DataSource para dsVisao. 9. Na Component Pallete, na página Standard clique no objeto Memo e dê um clique no Form e altere a propriedade Name para memClip e a propriedade Visible para False. 10. Na Component Pallete, ainda na página Standard clique no objeto Label e dê um clique no Form colocando no espaço entre os objetos ButPrior e ButNext e altere a propriedade Caption para Valor Salto. 11. Na Component Pallete, na página Additional clique no objeto MaskEdit e dê um clique no Form colocando abaixo do objeto Label1e altere as seguintes propriedades 11.1. Name para mskSalto 11.2. EditMask para 099;0;_ 11.3. Hint para Defina um valor para o salto das Fichas 11.4. ShowHint para True Veja como ficou o trabalho até aqui:
Criando o Separador das Partes Toda essa parte de botões e apenas o acessoramento que servirá para substituir com muito mais eficiência um padrão adotado desde o Delphi 1.0, a famosa Barra de Navegação, ou seja o objeto DBNavigator, não quero aqui em momento nenhum falar mal deste objeto, o problema se deu que com o passar do tempo eu o consegui aprimorar, até torná-lo uma barra com 23 botões e sem querer acabei foi conseguindo complicar bastante a cabeça dos meus usuários, então resolvi descartá-lo e colocar toda a sua funcionalidade nesta tela.
☞
Importante - Ainda na terceira parte desta janela criaremos mais alguns botões para completar a barra que eu tinha desenvolvido, mas você pode notar a ausência do botão Edição ou Alteração, o Delphi permite entrada direta em modo de Edição, basta que para isto o usuário começe a digitar os dados e depois ou gravar
uma determinada Ficha ou simplesmente começar a navegar os dados, caso ele deseje pode também Cancelar o processo, veja bem criei esta janela para facilitar a vida do usuário, não para prendê-lo a uma regra ou a um conjunto, você notará que em momento nenhum desabilito ou habilito qualquer destes botões (a excessão do butMark e butGotoMark). Para dividir a tela em três partes utilizei um objeto PageControl associado a figuras para ficar mais familiar ao usuário, vamos construir este preparatório antes de continuarmos. 12. Na Component Pallete, na página Win32 clique no objeto ImageList e dê um clique no Form, agora dê um duplo clique em cima do objeto criado para entrarmos no editor da lista de imagens, conforme a figura abaixo:
12.1. Clique no botão Add... e localize a figura ImgFicha, e clique no botão abrir, ela será a posição 0, insira as imagens ImgTabela e ImgFormCons. Clique no botão OK e saia do editor. 13. Na Component Pallete, ainda na página Win32 clique no objeto PageControl e dê um clique no Form, acerte-o para ocupar o espaço vazio do formulário e altere a propriedade Images para ImageList1 e a propriedade Name para PgPrincipal. 14. Clique neste objeto criado com o botão Direito do mouse e escolha a opção NewPage, uma nova página será criada, altere a propriedade Caption para Ficha e propriedade Name para TabFicha. 15. Novamente clique no objeto PgPrincipal com o botão Direito do mouse e escolha a opção NewPage, mais uma nova página será criada, altere a propriedade Caption para Tabela e propriedade Name para TabTabela. 16. Finalmente clique no objeto PgPrincipal com o botão Direito do mouse e escolha a opção NewPage, mais uma nova página será criada, altere a propriedade Caption para Formas de Consulta e propriedade Name para TabConsulta. O resultado de todo este trabalho se mostra na figura a seguir:
☞Importante - Note que os objetos DBMemClip e MemClip ficaram escondidos atrás do objeto PgPrincipal, isto não tem importância pois quando em modo de execução estes objetos ficarão invisíveis.
Criando a Primeira Parte Atenção que esta é a parte mais difícil e complicada, você aqui simplesmente não vai fazer nada, deixe exatamente do jeito que está, utilizaremos esta parte apenas nos formulários que criaremos por herança.
Criando a Segunda Parte Clique na orelha Tabela dentro do objeto PgPrincipal, o problema em se mostrar os dados de uma tabela sob a forma de uma planilha é que campos tipo Imagem e campos tipo Texto não aparecem, solucionei este problema, dividindo esta parte em mais três partes, uma que mostra exclusivamente os dados simples, a outra apenas para campos tipo Imagem e a última apenas para campos do tipo Texto e vamos ao trabalho: 17. Na Component Pallete, clique na página Win32 clique no objeto PageControl e dê um clique no Form, e altere a propriedade Align para AlClient e a propriedade Name para PgTabela. 18. Clique neste objeto criado com o botão Direito do mouse e escolha a opção NewPage, uma nova página será criada, altere a propriedade Caption para Dados e propriedade Name para TabTDados. 19. Dentro desta página na Component Pallete, clique na página Data Controls clique no objeto dbGrid e dê um clique nesta página, altere as seguintes propriedades: 19.1. Align para AlClient 19.2. Options para [dgTitles,dgColumnResize,dgColLines,dgRowSelect,dgAlwaysShowSelection] 19.3. DataSource para DsVisao, compare como ficou:
20. Novamente clique no objeto PgTabela com o botão Direito do mouse e escolha a opção NewPage, mais uma nova página será criada, altere a propriedade Caption para Imagem e propriedade Name para TabTImagem. 21. Dentro desta página na Component Pallete, clique na página Data Controls clique no objeto dbImage e dê um clique nesta página, altere a propriedade Align para AlTop e a propriedade DataSource para DsVisao 22. Ainda dentro desta página na Component Pallete, clique na página Standard clique no objeto Label e dê um clique nesta página, altere a propriedade Caption para Campo e a propriedade Font para Estilo: Negrito e Cor: Castanho. 23. Ainda dentro desta página na Component Pallete, ainda na página Standard clique no objeto ComboBox e dê um clique nesta página, altere a propriedade Hint para Selecione o campo a pesquisar, a propriedade ShowHint para True e a propriedade Name para CbCampoImg. 24. Ainda dentro desta página na Component Pallete, ainda na página Standard traga outro objeto ComboBox, e altere a propriedade Visible para False e a propriedade Name para CbCampoImgReal, compare como ficou:
25. Finalmente clique novamente no objeto PgTabela com o botão Direito do mouse e escolha a opção NewPage, mais uma nova página será criada, altere a propriedade Caption para Texto e propriedade Name para TabTTexto. 26. Dentro desta página na Component Pallete, clique na página Data Controls clique no objeto dbMemo e dê um clique nesta página, altere a propriedade Align para AlTop e a propriedade DataSource para DsVisao
27. Ainda dentro desta página na Component Pallete, clique na página Standard clique no objeto Label e dê um clique nesta página, altere a propriedade Caption para Campo e a propriedade Font para Estilo: Negrito e Cor: Castanho. 28. Ainda dentro desta página na Component Pallete, ainda na página Standard clique no objeto ComboBox e dê um clique nesta página, altere a propriedade Hint para Selecione o campo a pesquisar, a propriedade ShowHint para True e a propriedade Name para CbCampoTxt. 29. Ainda dentro desta página na Component Pallete, ainda na página Standard traga outro objeto ComboBox, e altere a propriedade Visible para False e a propriedade Name para CbCampoTxtReal, compare como ficou:
Criando a Terceira Parte Clique na orelha Formas de Consulta dentro do objeto PgPrincipal e vamos ao trabalho: 30. Na Component Pallete clique na página Additional dentro dessa página de um clique no objeto SpeedButton (prendendo-o com a tecla Shift) e dê cinco cliques nesta página, solte o objeto, foram criados cinco botões pequenos, coloque-os um abaixo do outro modificando a propriedade Flat de todos para True. E altere as seguinte propriedades:
1 2 3 4 5
Glyph ImgFiltra ImgDesFiltro ImgLocaliza ImgImprime ImgEnviaArea
Name ButFilterOpen ButFilterClose ButSearch ButPrint ButCopyClip
Enabled True False True True True
31. Na Component Pallete clique na página Standard dentro dessa página de um clique no objeto Label (prendendo-o com a tecla Shift) e dê cinco cliques nesta página, solte o objeto, coloque-os ao lado de cada botão, altere a propriedade Font de todos para Cor: Azul-Marinho. E altere a propriedade Caption de cada para: Caption 1 Ativa as opções para se criar um Filtro, o Filtro permite uma seleção das fichas mostradas, limitando-as. 2 Desativa um filtro. 3 Localiza determinada Ficha. 4 Imprime todas as fichas, limitando-as caso haja filtro ativo.
5
Envia a ficha corrente para área de transferência. Compare como ficou:
Criando os Acessores na D_Modelo Antes de continuarmos, abra a unidade D_Modelo e crie os seguintes objetos: Na Component Pallete na página chamada Dialogs e dentro dessa página traga um objeto SelectDlgT, um objeto DgPrint e um objeto DgFiltro. Altere a propriedade Name para SelPesquisa, PrtPesquisa e FilPesquisa respectivamente.
Codificando A codificação deste formulário não é tão complicado quando se entende toda a utilidade desta janela, óbvio que precisei usar uma boa gama de conhecimento que tenho em linguagem Object Pascal mas adianto que não utilizei nada estranho 1. Alterne para o Code Editor e localize a seguinte porção do código: private { Private declarations } public { Public declarations } e coloque o seguinte: private FBM: TBookmark; ChDuplica, fTrava: Boolean; FiltroVisto: String; public procedure ChamaExterno(var Tab: TTable; aFormClass: TFormClass); end;
uses dModelo, fFiltro; // Gera o Filtro // Procedure Global para a chamadas a formulários terceiros procedure TF_Ficha.ChamaExterno(var Tab: TTable; aFormClass: TFormClass); begin Screen.Cursor := crHourGlass; Tab.Close; with aFormClass.Create(Application) do try ShowModal; finally Free; end; Tab.Open; Screen.Cursor := crDefault; end;
☞
Importante - Coloque na primeira declaração do USES (fica logo abaixo da Seção interface) a unidade DBTables pois o procedimento ChamaExterno faz uso do objeto TTable que faz parte desta biblioteca. Aqui foram criadas algumas variáveis para uso particular do programa ou seja só funcionarão aqui dentro, são elas: • • • •
FBM: Ponteiro para guardar a posição do arquivo quando for disparado o botão Marca Registro. ChDuplica: Booleana que diz se é ou não para Duplicar um registro marcado. fTrava: Booleana que informa se o Inserção em Lote foi ou não ativada. FiltroVisto: Caso a tabela está com o filtro ativo criado e armado pelo usuário.
Foi criada também um procedimento público para poder criar e chamar formulários secundários, este procedimento será visto com mais detalhes a frente. 2. Para o evento onShow do Formulário procedure TF_Ficha.FormShow(Sender: TObject); var i : Integer; begin with dsVisao.DataSet do begin for i := 0 to (FieldCount -1) do case Fields[i].DataType of ftMemo, ftFmtMemo : begin CbCampoTxt.Items.Add(Fields[i].DisplayLabel); CbCampoTxtReal.Items.Add(Fields[i].FieldName); end; ftBlob, ftBCD, ftTypedBinary, ftGraphic : begin CbCampoImg.Items.Add(Fields[i].DisplayLabel); CbCampoImgReal.Items.Add(Fields[i].FieldName); end; end;
end; CbCampoTxt.ItemIndex := 0; CbCampoImg.ItemIndex := 0; CbCampoImgChange(Sender); CbCampoTxtChange(Sender); PgPrincipal.ActivePage := TabFicha; PgTabela.ActivePage := TabTDados; PosEstado1.Atualiza; fTrava := False; Screen.Cursor := crDefault; end; A primeira parte coloca e divide os nomes dos campos das tabelas em três segmentos, do tipo comum, do tipo texto e do tipo imagem, isto é para ser colocado na segunda parte do formulário quando o usuário terá a visão da tabela como a forma de uma planilha de dados. A segunda parte prepara todo o ambiente para a mostragem dos dados. Posicionando os combos, ativando os procedimentos Change de ambos os combos Imagem e Texto para carregá-los, transformando a Página FICHA como inicial, na segunda página ativa a Página DADOS como principal, atualiza o objeto PosEstado1, acerta a variável fTrava e retorna o cursor para o formato de uma seta. 3. Para o evento onClick do objeto ButInsert procedure TF_Ficha.ButInsertClick(Sender: TObject); var i : Integer; begin with dsVisao.DataSet do begin Insert; if ChDuplica then for i := 0 to (FieldCount -1) do Fields[i].Value := D_Modelo.QrySQL.Fields[i].Value; end; PosEstado1.Atualiza; TabFicha.SetFocus; Keybd_event(9,0,0,0); end; Quando for pressionado o botão Insere ativa o comando Insert da tabela e verifica se está em modo de Duplicação da Ficha, se estiver transfere todos os dados da Query pública para a tabela corrente campo a campo, atualiza o objeto PosEstado1 e manda o foco para o objeto TabFicha depois simula o pressionamento da tecla TAB isto fará com que o foco vá para o primeiro campo da TabFicha. 4. Para o evento onClick do objeto ButPost procedure TF_Ficha.ButPostClick(Sender: TObject); begin with dsVisao.DataSet do Post; if fTrava then ButInsertClick(Sender) else PosEstado1.Atualiza; end; Quando for pressionado o botão Grava ativa o comando Post da tabela e verifica se está em modo de Inserção de Lote, se estiver chama o procedimento de inclusão, caso contrário atualiza o objeto
PosEstado1. 5. Para o evento onClick do objeto ButCancel procedure TF_Ficha.ButCancelClick(Sender: TObject); begin with dsVisao.DataSet do Cancel; if fTrava then ButInsertClick(Sender) else PosEstado1.Atualiza; end; Quando for pressionado o botão Cancela ativa o comando Cancel da tabela e verifica se está em modo de Inserção de Lote, se estiver chama o procedimento de inclusão, caso contrário atualiza o objeto PosEstado1. 6. Para o evento onClick do objeto ButDelete procedure TF_Ficha.ButDeleteClick(Sender: TObject); begin with dsVisao.DataSet do Delete; PosEstado1.Atualiza; end; Quando for pressionado o botão Elimina ativa o comando Delete da tabela e atualiza o objeto PosEstado1. 7. Para o evento onClick do objeto ButFixIns procedure TF_Ficha.ButFixInsClick(Sender: TObject); begin fTrava := not fTrava; ButFixIns.Down := not fTrava; ButDelete.Enabled := not fTrava; if fTrava then ButInsertClick(Sender); end; Quando for pressionado o botão Insere Lote pode acontecer dois momentos o primeiro pressionamento trava e o segundo pressionamento libera, acerta a variável de controle, coloca o botão pressionado (ou despressionado conforme o caso), desabilita (ou habilita conforme o caso) o botão de exclusão e se for para travar chama o procedimento de inclusão. 8. Para o evento onClick do objeto ButFirst procedure TF_Ficha.ButFirstClick(Sender: TObject); begin with dsVisao.DataSet do First; end; Quando for pressionado o botão Primeiro Registro ativa o comando First da tabela. 9. Para o evento onClick do objeto ButRw procedure TF_Ficha.ButRwClick(Sender: TObject);
begin with dsVisao.DataSet do moveby(-StrToInt(mskSalto.Text)); end; Quando for pressionado o botão Salto para Trás ativa o comando MoveBy enviando o salto estipulado de forma negativa. 10. Para o evento onClick do objeto ButPrior procedure TF_Ficha.ButPriorClick(Sender: TObject); begin with dsVisao.DataSet do Prior; end; Quando for pressionado o botão Registro Anterior ativa o comando Prior da tabela. 11. Para o evento onClick do objeto ButNext procedure TF_Ficha.ButNextClick(Sender: TObject); begin with dsVisao.DataSet do Next; end; Quando for pressionado o botão Próximo Registro ativa o comando Next da tabela. 12. Para o evento onClick do objeto ButFF procedure TF_Ficha.ButFFClick(Sender: TObject); begin with dsVisao.DataSet do moveby(StrToInt(mskSalto.Text)); end; Quando for pressionado o botão Salto para Frente ativa o comando MoveBy enviando o salto estipulado. 13. Para o evento onClick do objeto ButLast procedure TF_Ficha.ButLastClick(Sender: TObject); begin with dsVisao.DataSet do Last; end; Quando for pressionado o botão Último Registro ativa o comando Last da tabela. 14. Para o evento onClick do objeto ButMark procedure TF_Ficha.ButMarkClick(Sender: TObject); begin with dsVisao.DataSet do FBM := getbookmark; ButGotoMark.enabled := true; end; Quando for pressionado o botão Marca Registro acerta o ponteiro BookMark para guardar a posição do registro. 15. Para o evento onClick do objeto ButGotoMark
procedure TF_Ficha.ButGotoMarkClick(Sender: TObject); begin with dsVisao.DataSet do gotobookmark(FBM); end; Quando for pressionado o botão Vai para o Registro Marcado posiciona a tabela de acordo com o ponteiro criado com o BookMark. 16. Para o evento onClick do objeto ButFilter procedure TF_Ficha.ButFilterOpenClick(Sender: TObject); begin with D_Modelo.FilPesquisa do begin Tabela := (dsVisao.DataSet as TTable); FiltroSQL := (dsVisao.DataSet as TTable).Filter; FiltroVe := FiltroVisto; if Execute then begin FiltroVisto := FiltroVe; with dsVisao.DataSet do begin Close; Filter := FiltroSQL; Filtered := True; Open; end; ButFilterOpen.Enabled := False; ButFilterClose.Enabled := True; end; end; end; Quando for pressionado o botão Abre Filtro seta os parâmetros para o objeto FilPesquisa localizado na D_Modelo e depois executa-o, caso seja devolvida uma resposta positiva realiza a filtragem da tabela e desabilita este botão e habilita o botão Fecha Filtro. 17. Para o evento onClick do objeto ButFilterClose procedure TF_Ficha.ButFilterCloseClick(Sender: TObject); begin with dsVisao.DataSet do begin Close; Filtered := False; Open; ButFilterOpen.Enabled := True; ButFilterClose.Enabled := False; end; end; Quando for pressionado o botão Fecha Filtro limpa o filtro da tabela e desabilita este botão e habilita o botão Abre Filtro. 18. Para o evento onClick do objeto ButSearch procedure TF_Ficha.ButSearchClick(Sender: TObject); var Marca: TBookmark;
begin D_Modelo.SelPesquisa.Tabela := (dsVisao.DataSet as TTable); with dsVisao.DataSet do with D_Modelo.SelPesquisa do begin Filtro := Filter; Marca := GetBookMark; if not Execute then GotoBookMark(Marca); FreeBookMark(Marca); end; end; Quando for pressionado o botão Localiza Registro seta os parâmetros para o objeto SelPesquisa localizado na D_Modelo e depois executa-o, antes guarda em um ponteiro do tipo BookMark a posição da tabela, caso seja devolvida uma resposta negativa retorna a posição guardada anteriormente. 19. Para o evento onClick do objeto ButPrint procedure TF_Ficha.ButPrintClick(Sender: TObject); begin D_Modelo.PrtPesquisa.Tabela := (dsVisao.DataSet as TTable); with dsVisao.DataSet do with D_Modelo.PrtPesquisa do begin NomeTela := 'Impressão'; NomeRel := 'Relação de'; Filtro := Filter; Execute; end; end; Quando for pressionado o botão Imprime Dados seta os parâmetros para o objeto PrtPesquisa localizado na D_Modelo e depois executa-o. 20. Para o evento onClick do objeto ButCopyClip procedure TF_Ficha.ButCopyClipClick(Sender: TObject); var i : Integer; begin with dsVisao.DataSet do begin MemClip.Lines.Clear; for i := 0 to FieldCount - 1 do if Fields[i].Visible then begin MemClip.Lines.Add(Fields[i].DisplayLabel + ': '); DBMemClip.DataField := Fields[i].FieldName; if Fields[i].AsString > '' then begin DBMemClip.SelectAll; DBMemClip.CopyToClipboard; MemClip.PasteFromClipBoard; end; end; MemClip.SelectAll; MemClip.CopyToClipboard; end; end;
Quando for pressionado o botão Copia para Área de Transferência utiliza-se do objeto invisível MemClip, com o auxílio do objeto dbMemClip, para colocar todos os dados do registro atual para dentro deste e depois simplesmente seleciona tudo e envia para a Área de Transferência. 21. Para o evento onChange do objeto CbCampoTxt procedure TF_Ficha.CbCampoTxtChange(Sender: TObject); begin CbCampoTxtReal.ItemIndex := CbCampoTxt.ItemIndex; if CbCampoTxtReal.Items.Count > -1 then DbMemo1.DataField := CbCampoTxtReal.Text; end; Quando for modicada a posição do combo que contém os campos em formato Texto da página Tabela faz as alterações necessárias setando o objeto DBMemo1 para o novo campo. 22. Para o evento onChange do objeto CbCampoImg procedure TF_Ficha.CbCampoImgChange(Sender: TObject); begin CbCampoImgReal.ItemIndex := CbCampoImg.ItemIndex; if CbCampoImgReal.Items.Count > -1 then DbImage1.DataField := CbCampoImgReal.Text; end; Quando for modicada a posição do combo que contém os campos em formato Imagem da página Tabela faz as alterações necessárias setando o objeto DBImage1 para o novo campo. 23. Para o evento onExit do objeto TabFicha procedure TF_Ficha.TabFichaExit(Sender: TObject); begin if fTrava then begin ButPostClick(Sender); TabFicha.SetFocus; end; end; A Inserção de Registros em Lote é realizada da seguinte forma, é disparado um comando Insert para a tabela e posicionado no primeiro campo, o usuário digitará até o último campo pressionando a tecla Tab quando ele chegar no último campo ele pressionará mais um Tab isto fará com que este comando seja ativado, então confirmaremos a gravação do registro digitado, chamando o procedimento para tal, e retornaremos para o primeiro campo. 24. Para o evento onClick do objeto ButDupField procedure TF_Ficha.ButDupFieldClick(Sender: TObject); var NomeCampo: String; i : Integer; begin ChDuplica := not ChDuplica; ButDupField.Down := not ChDuplica; if ChDuplica then with D_Modelo.QrySQL do if Active then Close else
with D_Modelo.QrySQL do begin // Monta o "SQL Completo" if Active then Close; SQL.Clear; SQL.Add('select * from ' + (dsVisao.DataSet as TTable).TableName); NomeCampo := (dsVisao.DataSet as TTable).IndexFields[0].FieldName; case (dsVisao.DataSet as TTable).FieldByName(NomeCampo).DataType of ftAutoInc, ftTypedBinary, ftSmallint, ftInteger, ftWord, ftBoolean, ftFloat, ftCurrency, ftBytes, ftVarBytes: SQL.Add('where (' + NomeCampo + ' = ' + (dsVisao.DataSet as TTable).FieldByName(NomeCampo).AsString + ')'); else SQL.Add('where (' + NomeCampo + ' = ''' + (dsVisao.DataSet as TTable).FieldByName(NomeCampo).AsString + ''')'); end; for i := 1 to (dsVisao.DataSet as TTable).IndexFieldCount-1 do begin NomeCampo := (dsVisao.DataSet as TTable).IndexFields[i].FieldName; case (dsVisao.DataSet as TTable).FieldByName(NomeCampo).DataType of ftAutoInc, ftTypedBinary, ftSmallint, ftInteger, ftWord, ftBoolean, ftFloat, ftCurrency, ftBytes, ftVarBytes: SQL.Add('and (' + NomeCampo + ' = ' + (dsVisao.DataSet as TTable).FieldByName(NomeCampo).AsString + ')'); else SQL.Add('and (' + NomeCampo + ' = ''' + (dsVisao.DataSet as TTable).FieldByName(NomeCampo).AsString + ''')'); end; end; Open; end; end; Quando for pressionado o botão Duplica Registro fará com que esta trenheira (gostei do trenheira) de código seja executado, é simples, com o auxílio do objeto Query público da D_Modelo (Objeto QrySQL) geraremos um comando SQL que quando disparado conterá o registro atual, apenas ele, após isto basta com que após cada comando Insert copiemos campo a campo do objeto Query para a Tabela. 25. Para o evento onClose do Formulário procedure TF_Ficha.FormClose(Sender: TObject; var Action: TCloseAction); begin if FiltroVisto <> '' then with dsVisao.DataSet do begin if Active then Close; Filter := ''; Filtered := False; end; if ButGotoMark.enabled then with dsVisao.DataSet do FreeBookmark(FBM); with D_Modelo.QrySQL do if Active then Close; end; Antes do usuário sair, cancelaremos o filtro, caso exista algum, finalizaremos caso tenha sido criado o ponteiro de guardar registros e fecharemos, caso esteje ativa, o objeto Query Público da D_Modelo.
Finalmente
Na próxima apostila criaremos a primeira utilização deste formulário através da Herança dos Objetos.
Dúvidas das Apostilas Anteriores Como faço para criar tabelas relacionadas ? Use o gerenciador do banco de dados para isso ou você quer criá-los via programação ? se sim não faça isso pois os comandos variam muito de banco para banco. Posso relacioná-las no Access ? Claro, mas lembre-se que alguns bancos não permitem o relacionamento de Alteração e Exclusão em cascata como o Access permite, entaum se vc quer um sistema portátil não utilize essa opção mesmo sendo ela muito prática. ou uso MasterSource ? Você não relaciona tabelas com as opções MasterSource e MasterFields o que você faz é criar um indice virtual, isso apenas serve para controlar entradas e visões dos dados nada mais. Qual a melhor solução ? Ex. Produto -> Items Quando utilizava o Paradox naum utilizava relacionamentos deixava o sistema controlar toda a entrada dos dados, quando passei a usar o Access comecei a definir meus relacionamentos no próprio banco mas sempre tomando o cuidado para que o sistema naum deixe passar besteiras, acredito que vc próprio saberá o que é melhor para seu sistema pois cada caso é uma sentença. A minha duvida é com relação ao Access/Multiusuario, isto é possível? Sim ele é um banco multiusuário, ou controlado o acesso livremente ou por determinados usuários com determinadas permissões. e com relação a distribuição? Veja a apostila 4 como criar o Install Shield para isto. Com o Access isto também acontece? A forma de acesso ao Access é pelo DAO, seu cliente precisa tê-lo ou vc a permissão para instalá-lo. o DAO3032.DLL nao foi encontrado em um determinado diretorio. O bom e velho Isto ocorre porque vc precisa instalar o DAO 3.5, instale o APE Work disponível no endereço citado da home page do Bruno. Ja li sua resposta no final da apostila 7. Possuo Windows 95 e o Office ORIGINAIS !!!!! Sera que nao resolve ?!? Dependendo naum resolve pois vc terá apenas o DAO 3.0, mas se vc conseguir conexão com ele sem problemas então deixe a IDDAO32.DLL Acessei o endereco para atualizar o DBE so que a versao que la se encontra e a 5.0 ! Por acaso, exitiria algum problema em baixa-la ?
Ela foi criada para atender o Delphi 4.0 ainda naum testei com o D3 A minha base de dados que está feita no Access 97 quando é acessada sempre pede o login e a password. É somente dar um <enter> que consigo acessá-la. Já fiz todas as configurações que você fala na sua Home Page, desabilitei o botão de "login prompt" no componente DataBase do Delphi, mas ainda o problema de pedir o login para acessar a base persiste. O meu Delphi é o 3.0 e você fala que os exemplos são todos para a versão 3.02 do Delphi. Será que os meus problemas são por causa da minha versão do Delphi ??? Onde posso arrumar um uprade para atualizar a minha versão de Delphi ??? Sempre em modo de edição ele pedirá para vc a janela Status Login, apenas com o sistema rodando que ele parará de pedir pois entrará ou no LoginPrompt := False ou no evento OnLogin (conforme as apostilas 3 e 10). O problema naum é com seu Delphi mas para atualizá-lo para a versão 3.02, primeiro vc tem que pegar aonde vc comprou o Delphi a versão 3.01, depois vc vai no próprio site da Inprise e pega a atualização para 3.02, ATENÇÃO: Não baixe a 3.02 em cima da 3.0. A senha e pedida e se eu der o OK o erro ocorre. O que é óbvio porque apenas neste momento que vc está tentando o acesso ao DAO. É preferível sempre trabalhar com Querys? Quando devo usar Tables ? Isso surgiu com o Delphi 1.0 e se estendeu com o Delphi 2.0, pois os objetos Query´s eram indiscutivelmente mais rápidos e práticos que os Table´s mas se vc está utilizando o Delphi 3.0 ou Delphi 4.0 a Inprise já corrigiu e acertou os objetos Table´s, então aconselho que vc os utilize. Qual a melhor maneira de procurar um registro usado query ? Pode ser o Locate ? Usando a cláusula Where. Como devo fazer a consitencia do meu sistema para não deixar que registros duplicatos sejam cadastrados ? Faço a procura em outra Query? Crio em run_time ? Crie outra table para procura, ou uma query para procurar, mas modifique o comando SQL via programa, pois assim vc pode utilizar uma única query para seu sistema inteiro. Uso DBEdit ? ou a melhor opção são Edits ? Os DBEdit são melhores. Os indíces, ou By Order, ...Permito que o usário escolha a ordem dos dados? Neste caso coloquei no evento OnTitleClick do DBGrid o seguinte código. procedure TFClas.DBGridClasTitleClick(Column: TColumn); var Chave:String; begin Chave:=Column.FieldName; With QueryClas do begin Close; SQL.Clear; SQL.Add('Select * from Classe'); SQL.Add('Order By ' + Chave ); Open; end; end;
É a melhor opção ? Se vc está utilizando Query´s para cadastrar é, mas eu naum recomendo seu uso depois do Delphi 3.0. Em um sistema, 60% se resume em inclui, altera, exclui,consulta. Se eu estiver equivocado por favor me corrija... Não tenho como fazê-lo no meu caso as vezes é quase 90% Nao sei direito como funciona o relacionamento entre tabelas do Access. No clipper eu criava minhas tabelas (.DBF) e depois com SET RELATION... relacionava a tabela PAI com a tabela FILHO. Quando posicionava o registro na tabela PAI, seu correspondente na tabela FILHO ja era posicionado automatico. No access criei um .MDB com duas tabelas, uma PAI e outra FILHO. Na aba de relacionamento (dentro do ACCESS97) fiz o relacionamento, salvei e abri o DELPHI. Iniciei um novo projeto coloquei dois table/datasource/grid. Fiz as conexoes, porem quando movimento o registro na tabela PAI, a tabela filho nao se movimenta! Isso esta correto? Se sim, entao para que serve o relacionamento feito dentro do Access em um programa delphi? No teste que eu fiz, o relacionamento dentro do access nao funcionou no programa em delphi. Se vc quer movimentar o PAI e movimentar o FILHO use os parametros Master do objeto Table para isso. Os relacionamentos no banco de dados, em qualquer deles, serve para garantir que só existirá FILHOS se existirem PAIS, é que um PAI dependendo da regra não pode morrer ou modificar sua chave se ouverem FILHOS atrelados a eles. Para o Delphi isso serve pois vc não precisa codificar isso. O que voce acha do OPUS para acessar MDB em relacao ao BDE 4.51 ??? Qual a melhor opcao? OPUS sem sombra de dúvida, é rápido, prático e seguro, utilizo o BDE para manter a integridade e portabilidade dos sistemas para qualquer banco de dados, não sei se amanhã resolvo mudar do Access para outra coisa qualquer. Gostaria de armazenar um conjunto de imagens diretamente no banco de dados, que pode ser Access97 ou Paradox 7.0 e depois empregá-las no meu projeto. Qual seria o tipo de campo ideal para armazenar estas imagens e qual seria o procedimento para fazer a visualização dessas imagens? Se isto for possível(eu sei que é, só não sei como) quais os formatos além do Bmp e ico que o delphi aceita, poderia ser empregado? No Access e no Paradox é um campo OLE e no Delphi vc os associa a um campo DBImage, existe um exemplo nos Demos do Delphi sobre isso. O Delphi aceita qualquer formato pois para colocar uma imagem nesses campos o que vc faz é recortar a imagem e colar, vc pode desenvolver uma função que faça isso. Existe algum componente que permite a "Justificação" de texto nos relatórios criados via QuickReport? Nunca o vi, mas talvez o QR que vem com o Delphi 4 já vem com isso, vou dar uma pesquisada nele aguarde notícias. Suponha que eu tenho 5 micros ligados em rede win95 com nenhum computador servidor dedicado(apenas compatilhamento de arquivos e hardware). Seria possível a utilização do programa Mapa criado nas apostilas 2,3,4 e todo a rede, elegendo por exemplo, o micro1 como local de instalação do programa e do banco de dados? Em todos os micros temos instalados os mesmo programas (Access97, win95 e bde 4.51) É possível sem problema nenhum e vc naum precisa do Access97 instalado nos micros apenas o Win95 Sistema - BDE 4.51 - DAO, para instalar tudo siga as instruções da nova apostila 4.
12 Curso de Delphi 4.0 - Apostila 12 Autor: Fernando Antonio F. Anselmo eMail: [email protected] Pré-Requisitos: • • • •
Windows 98 Delphi 4.0 versão Client/Server Suite BDE 5.00 MS-Access 97
Arquivos trabalhados juntos com esta apostila: •
Formulário : F_Ficha (criado na Apostila 11)
•
Objetos: DBCmpList
DBDateEdit97
•
Seguintes Imagens : • ImgLamp.BMP
ImgTerc.BMP
ImgTele.BMP
Prefácio Salve, nesta apostila desvendaremos a segunda parte de como criar os cadastros dos nossos sistemas. Na apostila passada criamos a primeira parte dos cadastros que foi a construção de um formulário que servirá como base de todos os cadastros, neste mostrarei como utilizar o formulário criado, lembre-se que definimos quatro cadastros: Cidade, Grupo, Alimento e Cliente. Aqui criarei o formulário para o Cadastro de Cliente que é o mais complexo de todos, então caberá a você, após este, a criação dos formulários para os cadastros de Cidade, Grupo e Alimento.
Como utilizar a Herança A coisa que mais falei na apostila passada foi no tocante a Herança, então vamos fazer uso dela, inicialmente reabra o nosso projeto e proceda da seguinte maneira: 1. A partir do Menu Principal vá em File | New... e vá na página Peso, escolha o formulário F_Ficha e clique em Ok. Pronto, primeiramente vamos começar bem devagar, neste momento foi criado uma cópia, um espelho ou se você prefere um novo objeto formulário baseado por herança no objeto formulário F_Ficha. NÃO altere neste formulário criado qualquer posição dos botões, NÃO faça modificações na janela, NADA. Se tiver que fazer este tipo de alteração faça no formulário F_Ficha pois deste modo automaticamente todos os outros formulários que foram herdados serão alterados. Altere aqui o extritamente necessário, pois cada alteração causa um desvínculo da herança. Para este objeto altere apenas as seguintes propriedades: 1.1. Name: F_Cliente 1.2. Caption: Cadastro de Clientes...
1.3. Salve o formulário com o nome de fCliente.PAS Note que precisamos preencher o miolo da primeira parte (A página da ficha propriamente dita), para tanto: 2. A partir do Menu Principal vá em File | New... e vá na página Business, escolha o formulário "Database Form Wizard" e clique em Ok: 2.1. O tipo do formulário a ser criado. Para a opção Form Options marque Create a simple form (Um formulário simples) e para a opção DataSet Options marque Create a form using TTables objects (Usando o objeto tabela) e clique no Botão Next. 2.2. A tabela a ser usada para o formulário. Para a opção Drive or Alias name localize o Alias AlPeso e para a opção Table Name marque Cliente e clique no Botão Next. 2.3. Campos a serem inseridos clique no Botão ">>" para ser inserido todos os campos e clique no Botão Next. 2.4. Clique na opção Vertically para a formação dos campos na Vertical e clique no Botão Next 2.5. Posição dos Labels deixe marcada a opção Left (A esquerda) e clique no Botão Next 2.6. Completo. Desmarque a opção Generate a main form (Gera a tela como form principal) e na opção Form Generation marque Form e clique no Botão Finish. 3. Agora selecione todos os campos e respectivos labels e digite CTRL+C vá para o formulário F_Cliente e clique na página Ficha selecione a página e digite CTRL+V dê uma arrumada nos campos, você deve conseguir algo como isto:
Este segundo formulário criado já serviu para seu propósito pode fechá-lo cancelando qualquer procedimento para sua gravação.
☞
Importante - Existem várias maneiras de se criar este formulário que mostrei, garanto que em breve você dominará uma maneira que mais lhe agrade, particularmente prefiro deste modo.
Acertando os campos 4. Inicilmente vamos nos ocupar dos objetos Label´s, altere as seguintes propriedades de todos:
4.1. Propriedade Caption (respectivamente): CPF: Nome: Endereço: Bairro: CEP: Cidade: eMail: Altura: Dt.Nasc: 4.3. Propriedade AutoSize para True 4.4. Na frente do campo EditALT_CLIENTE crie mais um objeto Label e coloque na propriedade Caption: em Cm 4.5. Altere a propriedade Font de todos para: Font.Color = clMaroon Font.Style = [fsBold]
5. Vamos para os campos agora, aumente o espaço entre o campo CEP e eMail e elimine o objeto EditSIG_CIDADE, e na página Data Controls localize o objeto DBCmpList e coloque-o no lugar deste.
☞Importante - Abra o Data Module D_Modelo, volte para o formulário F_Cliente e alterne para a janela do programa e insira a seguinte declaração após a diretiva de compilação: {$R *.DFM} uses dModelo; 6. Marque o objeto DsVisao e altere a propriedade DataSet para D_Modelo.tbCliente. 7. Para o objeto DBCmpList criado altere as seguintes propriedades: 7.1. Desça-o para o espaço aberto entre os campos CEP e eMail 7.2. CapLocaliza: Localiza determinada Cidade 7.3. Caption: 7.4. CriticaEd: False 7.5. DataSource: DsVisao (Atenção: Não marque, caso apareça F_Ficha.DsVisao) 7.6. DataField: SIG_CIDADE 7.7. GlyphLoc: ImgLamp.BMP (Enviado) 7.8. HintButLoc: Localiza determinada Cidade 7.9. MensagemCodigo: Sigla da Cidade não localizada 7.10. MensagemDescricao: Cidade não localizada 7.11. Name: CmpCidade 7.12. PosCmpCodigoSec: 0 7.13. PosCmpDescricao: 1 7.14. TbSecundaria: D_Modelo.tbCidade 7.15. TipoSQL: Access 7.16. UsaDescricao: True 7.17. UsaLocaliza: True
8. Marque este objeto e vá na página Additional e coloque um objeto SpeedButton em cima do objeto CmpCidade ao lado do botão de localizar e altere as seguintes propriedades: 8.1. Flat: True 8.2. Glyph: ImgTerc.BMP 8.3. Hint: Chama o cadastro de Cidade 8.4. Name: ButIncCidade 8.5. ShowHint: True 9. Elimine o campo EditDAT_NASCIMENTO e coloque um DBDateEdit97 no lugar e altere as seguintes propriedades: 9.1. DataSource: DsVisao 9.2. DataField: DAT_NASCIMENTO 9.3. Name: EditDAT_NASCIMENTO 10. Altere a propriedade Font de todos os campos para Font.Color = clNavy e organize a propriedade TabOrder para colocar os campos na sequência. O trabalho final ficou desta maneira:
Criando Mais uma Orelha Note através do nosso modelo que a tabela de CLIENTE tem um relacionamento de 1 para N com a tabela de TELEFONE_CLIENTE, normalmente adoto o seguinte método para o cadastro desse tipo. 11. Dê um Duplo-Clique no objeto ImageList1, clique no botão Add... e insira a imagem ImgTele.BMP (enviada) 12. Clique no objeto PgPrincipal e depois clique com o botão direito no sub-menu que aparece clique na
opção New Page. 13. Para esta nova página criada altere as seguintes propriedades: 13.1. Caption: Telefones 13.2. Name: TabTelefone 14. Crie agora três objetos: 14.1. Label e altere as seguintes propriedades: 14.1.1. Caption: Inclua aqui os telefones de Contato do Cliente: 14.1.2. Propriedade Font para: Font.Color = clMaroon Font.Style = [fsBold] 14.2. DataSource e altere as seguintes propriedades: 14.2.1. Name: dsTelefone_Cliente 14.2.2. DataSet: D_Modelo.tbTelefone_Cliente 14.3. dbGrid e altere as seguintes propriedades: 14.3.1. DataSource: dsTelefone_Cliente 14.3.2. Options: [dgEditing,dgTitles,dgIndicator,dgColumnResize,dgColLines,dgRowLines, dgTabs,dgConfirmDelete,dgCancelOnExit] 14.3.3. Columns: clique em [...], na janela que aparece clique duas vezes em seguintes propriedades:
, altere as
para a coluna 0 FieldName: NUM_TELEFONE Font.Color: clNavy Title.Caption: Número do Telefone Title.Font.Color: clMaroon Title.Font.Style: [fsBold] Width: 200 para a coluna 1 FieldName: DES_FUNCAO Font.Color: clNavy Title.Caption: Função PickList: Voz; FAX; Voz e FAX; PABX (Um em cada linha) Title.Font.Color: clMaroon Title.Font.Style: [fsBold] Width: 104 Não vamos nos preocupar aqui com os detalhes de controlar qual telefone e de qual cliente pois esta amarração foi realizada no DataModule através do objeto tbTELEFONE_CLIENTE, veja como ficou esta nova página:
Difícil Programação Você vai se surpreender com a programação criada aqui, a maior parte do trabalho ficou com o formulário anterior, este é a apenas um espelho do passado e sua programação é quase mínima e teremos apenas três trabalhos, vamos a ela:
1° Trabalho. Abrir as tabelas. Para tanto selecione o evento OnShow do formulário: procedure TF_Cliente.FormShow(Sender: TObject; var Action: TCloseAction); begin with D_Modelo do begin with tbCIDADE do begin Tab1 := Active; if not Tab1 then Open; end; with tbCLIENTE do begin Tab2 := Active; if not Tab2 then Open; end; with tbTELEFONE_CLIENTE do begin Tab3 := Active; if not Tab3 then Open; end; end; inherited; end; e crie três variáveis na Seção Particular do Objeto: private Tab1, Tab2, Tab3 : Boolean; Uma explicação geral é a seguinte, sempre que abro um formulário de cadastro abro respectivamente as tabelas que ele utiliza na D_Modelo, mas como um formulário pode chamar outro formulário então corrijo isso através de variáveis locais que armazenam se a respectiva tabela já se encontrava ou não aberta quando o formulário foi ativado.
☞Importante - Aqui a ordem dos tratores altera o viaduto, o objeto DBCmpList exige que a tabela secundária (tbCidade) seja aberta primeiramente que a tabela que serão gravados os dados (tbCliente). Um outro comando que você pode estranhar é o comando inherited ele é o responsável por chamar os comandos que estão localizados no evento OnShow do formulário Pai.
2° Trabalho. Fechar as tabelas. Para tanto selecione o evento OnClose do formulário: procedure TF_Cliente.FormClose(Sender: TObject; var Action: TCloseAction); begin with D_Modelo do begin case CriticaEdicao(dsVISAO, 'do Cliente', 'fechar') of mrYes : tbCLIENTE.Cancel; mrNo : begin Action := caNone; Exit; end; end; // *** Screen.Cursor := crHourGlass; if not Tab3 then tbTELEFONE_CLIENTE.Close; if not Tab2 then tbCLIENTE.Close; if not Tab1 then tbCIDADE.Close; end; inherited; end; Aqui é relativamente simples, através da função CriticaEdicao que será montada na D_Modelo verifica-se se o estado da tabela Cliente está em estado de Edição ou Inserção em caso positivo, podemos cancelar a Edição ou cancelar o Fechamento da janela. Na segunda parte devolvemos o estado original das tabelas.
☞Importante - Novamente a ordem dos camarões altera o vatapá, o objeto DBCmpList exige que a tabela que serão gravados os dados (tbCliente) seja fechada primeiramente que a tabela secundária (tbCidade).
3° Trabalho. É o botão responsável por chamar o Cadastro de Cidade para tanto de um duplo-clique no objeto ButIncCidade para ativar o evento OnClick: procedure TF_Cliente.ButIncCidadeClick(Sender: TObject); begin inherited; ChamaExterno(D_Modelo.tbCIDADE, TF_CIDADE); end; Não se esqueça de declarar o formulário utilizado na USES: uses dModelo, fCidade; Esse foi moleza pois basta que chamemos a função ChamaExterno localizada no formulário F_Ficha, note que por ser uma função localizada no objeto que herdamos não precisamos nem fazer a referência para ela.
Alterando a D_Modelo Lembra-se que na apostila referente ao DataModule avisei que algumas funções seriam posteriormente incluídas ? Então vamos começar estas inclusões: Função Responsável pela Verificação do Estado de uma Tabela: 1. Abra o DataModule D_Modelo através do Code Editor e localize a seção Public, insira o seguinte cabeçalho para a declaração da função coloque-o abaixo da declaração das variáveis: public nmAlimento, nmCidade, nmGrupo, nmPasta_Cliente, nmPeso_Cliente, // nmResumo_Mensal, nmTelefone_Cliente, nmCliente : String; function CriticaEdicao(DSOrigem: TDataSource; DoQue: String; AntesDe: String) :Word; end; 2. Após a diretiva de compilação insira os seguintes comandos: {$R *.DFM} function TD_Modelo.CriticaEdicao(DSOrigem: TDataSource; DoQue: String; AntesDe: String) :Word; begin if DSOrigem.State in [dsEdit, dsInsert] then result := MessageDlg('Necessário cancelar a edição (ou Inclusão) ' + Doque + ' antes de ' + AntesDe + '. Deseja sair agora ?', mtConfirmation, [mbYes, mbNo], 0) else result := mrNone; end; Vamos a uma explicação geral, a função é relativamente simples, ela recebe três variáveis sendo uma delas um objeto inteiro, uma coisa fantástica na linguagem Object Pascal é a possibilidade de passar objetos inteiros atraves de funções ou procedimentos, são passados os seguintes: DSOrigem : DataSource que será analisado DoQue : Ajuda na montagem da mensagem, "Do que será cancelada a tarefa ? " AntesDe : Complemento da mensagem do modo de edição Então caso o DataSource passado esteja em estado de Edição ou inserção será mostrada a seguinte mensagem "Necessário cancelar a edição (ou Inclusão) Conteúdo_Doque antes de Conteúdo_AntesDe. Deseja sair agora ?" e mostrado dois botões "Sim" ou "Não" o resultado será um dos dois, caso contrário será devolvido um resultado mrNone. Função Responsável pela crítica do CPF do Cliente: 1. Localize agora a seção Private, e insira o seguinte cabeçalho para a declaração da função: private function Maximo(nmCampo, nmTabela: String) : integer; function Critica_CPF(sNumCpf: String) : Boolean; 2. Após a diretiva de compilação insira os seguintes comandos: {$R *.DFM}
function TD_Modelo.Critica_CPF(sNumCpf: String) :boolean; var I, J, nMod, nSubTotal, nTotal, nDv: Integer; sChar, sNumCpfCalc: String; begin Result := True; if sNumCpf = '' then Exit; sNumCpfCalc := Copy(sNumCpf,1,9); for I := 1 to 2 do begin nMod := 2; nTotal := 0; for J := Length(sNumCpfCalc) downto 1 do begin sChar := Copy(sNumCpfCalc, J, 1); nSubTotal := (StrToInt(sChar) * nMod); nTotal := nTotal + nSubTotal; Inc(nMod); end; nDv := (11 - (nTotal mod 11)); if nDv > 9 then nDv := 0; sNumCpfCalc := sNumCpfCalc + IntToStr(nDv); end; Result := (sNumCpfCalc = sNumCpf); end; 3. Dê um duplo clique em cima da Tabela de Clientes e marque o campo NUM_CPF para o evento OnValidade insira os seguintes códigos: procedure TD_Modelo.tbClienteNUM_CPFValidate(Sender: TField); begin if not Critica_CPF(tbClienteNUM_CPF.Value) then Raise Exception.Create('CPF não confere com o da Receita Federal'); end; A função é o cálculo do famoso MÓDULO 11, você já deve ter ouvido falar isso várias vezes, o cálculo para o primeiro dígito é feito pegando-se os nove primeiros números do CPF e multiplicando-os da seguinte maneira, o primeiro por 10, o segundo por 9 e assim sucessivamente até o nono número por 2, e este valor somado (isto é realizado no segundo comando FOR) é aplicada a seguinte equação: Digito1 = 11 - Resto( Soma / 11) A função MOD dá exatamente o resto de uma divisão. Se o valor deste primeiro dígito for maior que 9 o resultado é 0, adiciona-se este digito aos outros nove e realiza-se uma nova multiplicação com os 10 números da seguinte maneira, o primeiro por 11, o segundo por 10 e assim sucessivamente até o décimo número por 2, aplica-se a mesma fómula anterior para encontrar o resultado do segundo dígito.
☞
Importante - Neste sistema não precisaremos, mas vou colocar aqui os códigos caso você precise, da função para a crítica do CGC de Empresas. function TD_Modelo.Critica_CGC(sNumCgc: String) : boolean; var I, J, nMod, nSubTotal, nTotal, nDv: Integer; sChar, sNumCgcCalc: String; begin Result := True; if sNumCgc = '' then Exit;
sNumCgcCalc := Copy(sNumCgc,1,12); for I := 1 to 2 do begin nMod := 2; nTotal := 0; for J := Length(sNumCgcCalc) downto 1 do begin sChar := Copy(sNumCgcCalc, J, 1); nSubTotal := (StrToInt(sChar) * nMod); nTotal := nTotal + nSubTotal; inc(nMod); if nMod > 9 then nMod := 2; end; nDv := (11 - (nTotal mod 11)); if nDv > 9 then nDv := 0; sNumCgcCalc := sNumCgcCalc + IntToStr(nDv); end; Result := (sNumCgcCalc = sNumCgc); end;
Finalmente Agora basta você voltar para o formulário F_Menu para fazer a inserção dos comandos para chamar o formulário: procedure TF_Menu.Cliente1Click(Sender: TObject); begin F_Cliente := TF_Cliente.Create(Application); F_Cliente.ShowModal; F_Cliente.Free; end; Também chame a partir do menu principal Project | Options... e retire o formulário F_Cliente da área dos Auto-Create forms (retire também o F_Ficha caso você ainda não o fez)
☞Importante - Este formulário precisa do Formulário F_Cidade já criado para funcionar. Agora cabê a você a criação dos formulários F_Cidade, F_Grupo e F_Alimento. Até a próxima.
13 Curso de Delphi 4.0 - Apostila 13 Autor: Fernando Antonio F. Anselmo eMail: [email protected] Pré-Requisitos: • • • •
Windows 98 Delphi 4.0 versão Client/Server Suite BDE 5.00 MS-Access 97
Arquivos trabalhados juntos com esta apostila: •
Objeto : DBDateEdit97
•
Seguintes Imagens : • ImgLamp.BMP
ImgTerc.BMP
ImgGrava.BMP
ImgCancela.BMP
Prefácio Salve, nesta apostila começaremos as primeiras movimentações do nosso projeto. A movimentação basicamente é dividida em duas fases: dados de Entrada ou dados de Saída, nesta vamos analisar a movimentação para Dados de Entrada. Esta fase deve ser lembrada como um formulário fácil e simples para que o usuário não se confunda com o processo que ele realizará.
Entrada de Clientes Inicialmente vamos construir a parte da movimentação relativa a Entrada de Clientes, é o momento em que o Cliente entra no SPA e é cadastrado em algum plano 1. A partir do Menu Principal vá em File | New Form e para este objeto altere apenas as seguintes propriedades: 1.1. BorderStyle: bsDialog 1.2. Caption: Entrada de Clientes 1.3. Name: F_Entrada 1.4. Position: poScreenCenter 1.5. Salve o formulário com o nome de fEntrada.PAS 2. Crie um objeto do tipo TPanel e altere as seguintes propriedades: 2.1. BevelInner: bvLowered 2.2. BorderWidth: 4 2.3. Align: alTop 3. Crie dentro deste Panel seis objetos do tipo Label e altere as seguintes propriedades 3.1. Propriedade Caption (respectivamente): CPF:
[Nome do Cliente] Data: Plano: Qtd.Caloria: Observação: 3.2. Propriedade Font para: Font.Color = clMaroon Font.Style = [fsBold] 3.3. Propriedade AutoSize para True, menos para o segundo Label 3.4. Para o segundo Label altere as seguintes propriedades 3.4.1. LabNOM_CLIENTE 3.4.2. Estique-o para ficar com o tamanho do Panel
☞Importante - Abra o Data Module D_Modelo, volte para o formulário F_Entrada e alterne para a janela do programa e insira a seguinte declaração após a diretiva de compilação: {$R *.DFM} uses dModelo; 4. Crie um objeto do tipo DataSource e altere as seguintes propriedades: 4.1. DataSet: D_Modelo.tbPasta_Cliente 4.2. Name: dsPasta_Cliente 5. Crie dentro deste Panel um objeto do tipo dbEdit e altere as seguintes propriedades 5.1. DataSource: dsPasta_Cliente 5.2. DataField: NUM_CPF 5.3. Font.Color: clNavy 5.4. Name: EditNUM_CPF 6. Ao lado deste objeto criado crie mais dois objetos do tipo SpeedButton e altere as seguintes propriedades: 6.1. Para o primeiro SpeedButton: 6.1.1. Flat: True 6.1.2. Glyph: ImgLamp.BMP 6.1.3. Hint: Localiza determinado Cliente 6.1.4. Name: ButLocCliente 6.1.5. ShowHint: True 6.2. Para o segundo SpeedButton: 6.2.1. Flat: True 6.2.2. Glyph: ImgTerc.BMP 6.2.3. Hint: Chama o cadastro de Clientes 6.2.4. Name: ButIncCliente 6.2.5. ShowHint: True 7. Crie dentro do objeto Panel1 um objeto do tipo dbDateEdit97 e altere as seguintes propriedades
7.1. DataSource: dsPasta_Cliente 7.2. DataField: DAT_CORRENTE 7.3. Font.Color: clNavy 7.4. Name: EditDAT_CORRENTE 8. Crie dentro do objeto Panel1 dois objetos do tipo DBRadioGroup e altere as seguintes propriedades 8.1. Para o primeiro DBRadioGroup: 8.1.1. DataSource: dsPasta_Cliente 8.1.2. DataField: PLN_ADOTADO 8.1.3. Font.Color: clNavy 8.1.4. Items: (Um por Linha) Plano Anti-Stress Plano Reeducação Plano Completo Plano Especial de Reeducação 8.1.5. Values: (Um por Linha) A;B; C;D 8.1.6. Columns: 2 8.2. Para o segundo DBRadioGroup: 8.2.1. DataSource: dsPasta_Cliente 8.2.2. DataField: QTD_CALORIA 8.2.3. Font.Color: clNavy 8.2.4. Items: (Um por Linha) 800 KCal 1.000 KCal 1.200 KCal 1.500 KCal 1.800 KCal 8.2.5. Values: (Um por Linha) 0800 ; 1000 ; 1200 ; 1500 ; 1800 8.2.6. Columns: 2 9. Crie dentro do objeto Panel1 um objeto do tipo DBMemo e altere as seguintes propriedades 9.1. DataSource: dsPasta_Cliente 9.2. DataField: OBS_PASTA 9.3. Font.Color: clNavy 9.4. Name: MemoOBS_PASTA 10. Acerte a propriedade TabOrder para a sequência correta. 11. Abaixo do Objeto Panel1 crie três objetos do tipo BitBtn e altere as seguintes propriedades: 11.1. Para o primeiro BitBtn: 11.1.1. Caption: &Grava 11.1.2. Glyph: ImgGrava.BMP 11.1.3. Hint: Grava os dados na Pasta do Cliente 11.1.4. Name: ButGrava 11.1.5. ShowHint: True 11.2. Para o segundo BitBtn: 11.2.1. Caption: &Cancela 11.2.2. Glyph: ImgCancela.BMP 11.2.3. Hint: Cancela e limpa a entrada dos dados
11.2.4. Name: ButCancela 11.2.5. ShowHint: True 11.3. Para o terceiro BitBtn: 11.3.1. Kind: bkClose 11.3.2. Caption: &Fechar 11.3.3. Hint: Fecha esta janela retornando ao menu do sistema 11.3.4. ShowHint: True O trabalho final ficou desta maneira:
Programando a Entrada Lembre-se, a programação aqui é uma coisa rápida é direta, ela não deve ser aplicada em situações de risco, como por exemplo um cadastro. 1. Inicialmente alterne para a Code Editor e na seção Private crie a seguinte chamada para o procedimento: private procedure AcertaInsercao; public 2. Agora abaixo da diretiva de compilação crie o procedimento proposto: {$R *.DFM} uses dModelo; procedure TF_Entrada.AcertaInsercao; begin D_Modelo.tbPasta_Cliente.Insert; LabNOM_CLIENTE.Caption := '';
end; Este procedimento será chamado toda vez que for feito uma nova inclusão na tabela Pasta Cliente. 3. Selecione agora o evento OnShow do formulário: procedure TF_Entrada.FormShow(Sender: TObject); begin with D_Modelo do begin tbCliente.Open; SelPesquisa.NomeTela := 'Seleciona Determinado Cliente'; SelPesquisa.Tabela := tbCliente; tbPasta_Cliente.Open; end; AcertaInsercao; end; Toda vez que o formulário for ativado, e aberta a tabela acessória tbCliente e organizado os campos dentro do objeto SelPesquisa localizado na D_Modelo, depois aberta a tabela em que será realizada toda a movimentação a tbPasta_Cliente e chamado o procedimento particular para colocá-la em estado de inserção.
4. Selecione o evento OnClose do formulário: procedure TF_Entrada.FormClose(Sender: TObject; var Action: TCloseAction); begin with D_Modelo do begin tbCliente.Close; tbPasta_Cliente.Cancel; tbPasta_Cliente.Close; end; end; Aqui é relativamente simples, simplesmente fechamos as tabelas cancelando o estado de inserção da tabela principal. 5. Vamos começar com os botões, primeiro o botão responsável para realizar a Gravação na Pasta para tanto de um duplo-clique no objeto ButGrava para ativar o evento OnClick: procedure TF_Entrada.ButGravaClick(Sender: TObject); begin if EditNUM_CPF.Text = '' then raise exception.create('Cliente não informado'); if LabNOM_CLIENTE.Caption = '' then raise exception.create('Cliente não cadastrado'); D_Modelo.tbPasta_Cliente.Post; AcertaInsercao; end; Fazemos duas críticas simples apenas para controlar se o CPF foi preenchido e se o nome do cliente foi encontrado (o que significará que o cliente existe), então gravamos o dado e simplesmente chamamos o procedimento para reativar o estado de inserção. 6. O segundo botão é o responsável para realizar o Cancelamento dos dados para tanto de um duplo-clique no objeto ButCancela para ativar o evento OnClick: procedure TF_Entrada.ButCancelaClick(Sender: TObject);
begin D_Modelo.tbPasta_Cliente.Cancel; AcertaInsercao; end; Este aqui é simplesmente disparar um comando Cancel para a tabela e chamarmos o procedimento para reativar o estado de inserção.
Programando o Cliente A ligação entre a tabela Pasta_Cliente e Cliente deverá ser totalmente controlada aqui, poderiamos usar do objeto CmpTerc para fazer este controle (igual fizemos no cadastro) mas preferi deixar o Cliente solto, então vamos aos passos: 1. Selecione o objeto EditNUM_CPF e chame o evento OnExit: procedure TF_Entrada.EditNUM_CPFExit(Sender: TObject); begin if EditNUM_CPF.Text <> '' then with D_Modelo.tbCliente do if FindKey([EditNUM_CPF.Text]) then LabNOM_CLIENTE.Caption := FieldByName('NOM_CLIENTE').AsString else begin EditNUM_CPF.SetFocus; raise exception.create('Cliente não cadastrado'); end; end; Inicialmente verificamos se foi preenchido algo no campo, então pesquisamos na tabela Cliente com o valor informado, caso encontre coloca o nome do cliente no Label destinado para tal, caso contrário volta o cursor para o objeto EditNUM_CPF e mostra a mensagem de erro. 2. O primeiro o botão localizado depois do campo é o responsável para realizar a Consulta do Cliente para tanto de um duplo-clique no objeto ButLocCliente para ativar o evento OnClick: procedure TF_Entrada.ButLocClienteClick(Sender: TObject); begin with D_Modelo do if SelPesquisa.Execute then EditNUM_CPF.Text := tbClienteNUM_CPF.AsString; end; São comando simples, executamos o objeto SelPesquisa e caso ele traga uma resposta verdadeira apenas adicionamos o valor do campo NUM_CPF da tabela cliente ao objeto EditNUM_CPF. 3. A pior coisa de um sistema, é por exemplo o Cliente não estar cadastrado e o usuário ser obrigado a sair da tela em que se encontra e cadastrar o cliente e depois retornar, para evitar isto o segundo botão é o responsável para chamar o Cadastro de Cliente para tanto de um duplo-clique no objeto ButIncCliente para ativar o evento OnClick: procedure TF_Entrada.ButIncClienteClick(Sender: TObject); begin F_Cliente := TF_Cliente.Create(Application); F_Cliente.ShowModal; F_Cliente.Free; end;
Aqui apenas disparamos a chamada ao formulário de Cliente, exatamente como é feito no menu principal, não se esquece de adicionar o formulário fCliente a cláusula USES.
Massa Corporal Outro exemplo de movimentação de entrada é o formulário para fazer a Massa Corporal, é o momento em que o Cliente é pesado e sua massa é mostrada em um cálculo (Recorde este cálculo na apostila referente ao Levantamento dos Dados): 1. A partir do Menu Principal vá em File | New Form e para este objeto altere apenas as seguintes propriedades: 1.1. BorderStyle: bsDialog 1.2. Caption: Massa Corporal 1.3. Name: F_Massa 1.4. Position: poScreenCenter 1.5. Salve o formulário com o nome de fMassa.PAS 2. Crie um objeto do tipo TPanel e altere as seguintes propriedades: 2.1. BevelInner: bvLowered 2.2. BorderWidth: 4 2.3. Align: alTop 3. Crie dentro deste Panel seis objetos do tipo Label e altere as seguintes propriedades 3.1. Propriedade Caption (respectivamente): CPF: [Nome do Cliente] Data: Peso: em Kg Massa Corporal é: 3.2. Propriedade Font para: Font.Color = clMaroon Font.Style = [fsBold] Para destacar aumente a fonte do último objeto para 11. 3.3. Propriedade AutoSize para True, menos para o segundo Label 3.4. Para o segundo Label altere as seguintes propriedades 3.4.1. LabNOM_CLIENTE 3.4.2. Estique-o para ficar com o tamanho do Panel
☞Importante - Abra o Data Module D_Modelo, volte para o formulário F_Entrada e alterne para a janela do programa e insira a seguinte declaração após a diretiva de compilação: {$R *.DFM} uses dModelo;
4. Crie um objeto do tipo DataSource e altere as seguintes propriedades: 4.1. DataSet: D_Modelo.tbPeso_Cliente 4.2. Name: dsPeso_Cliente 5. Crie dentro deste Panel um objeto do tipo dbEdit e altere as seguintes propriedades 5.1. DataSource: dsPeso_Cliente 5.2. DataField: NUM_CPF 5.3. Font.Color: clNavy 5.4. Name: EditNUM_CPF 6. Ao lado deste objeto criado crie mais dois objetos do tipo SpeedButton e altere as seguintes propriedades: 6.1. Para o primeiro SpeedButton: 6.1.1. Flat: True 6.1.2. Glyph: ImgLamp.BMP 6.1.3. Hint: Localiza determinado Cliente 6.1.4. Name: ButLocCliente 6.1.5. ShowHint: True 6.2. Para o segundo SpeedButton: 6.2.1. Flat: True 6.2.2. Glyph: ImgTerc.BMP 6.2.3. Hint: Chama o cadastro de Clientes 6.2.4. Name: ButIncCliente 6.2.5. ShowHint: True 7. Crie dentro do objeto Panel1 um objeto do tipo dbDateEdit97 e altere as seguintes propriedades 7.1. DataSource: dsPeso_Cliente 7.2. DataField: DAT_MEDIDO 7.3. Font.Color: clNavy 7.4. Name: EditDAT_MEDIDO 8. Crie dentro deste Panel um objeto do tipo dbEdit e altere as seguintes propriedades 8.1. DataSource: dsPeso_Cliente 8.2. DataField: PES_MEDIDO 8.3. Font.Color: clNavy 8.4. Name: EditPES_MEDIDO 9. Acerte a propriedade TabOrder para a sequência correta. 10. Abaixo do Objeto Panel1 crie três objetos do tipo BitBtn e altere as seguintes propriedades: 10.1. Para o primeiro BitBtn: 10.1.1. Caption: &Grava 10.1.2. Glyph: ImgGrava.BMP 10.1.3. Hint: Grava os dados na Pasta do Cliente 10.1.4. Name: ButGrava 10.1.5. ShowHint: True 10.2. Para o segundo BitBtn: 10.2.1. Caption: &Cancela
10.2.2. Glyph: ImgCancela.BMP 10.2.3. Hint: Cancela e limpa a entrada dos dados 10.2.4. Name: ButCancela 10.2.5. ShowHint: True 10.3. Para o terceiro BitBtn: 10.3.1. Kind: bkClose 10.3.2. Caption: &Fechar 10.3.3. Hint: Fecha esta janela retornando ao menu do sistema 10.3.4. ShowHint: True O trabalho final ficou desta maneira:
Programando a Massa Novamente vou frisar que a programação aqui é uma coisa rápida é direta, ela não deve ser aplicada em situações de risco, como por exemplo um cadastro. 1. Inicialmente alterne para a Code Editor e na seção Private crie a seguinte chamada para o procedimento: private procedure AcertaInsercao; public 2. Agora abaixo da diretiva de compilação crie o procedimento proposto: {$R *.DFM} uses dModelo; procedure TF_Massa.AcertaInsercao; begin D_Modelo.tbPeso_Cliente.Insert; LabNOM_CLIENTE.Caption := ''; end; Este procedimento será chamado toda vez que for feito uma nova inclusão na tabela Peso Cliente. 3. Selecione agora o evento OnShow do formulário:
procedure TF_Massa.FormShow(Sender: TObject); begin with D_Modelo do begin tbCliente.Open; SelPesquisa.NomeTela := 'Seleciona Determinado Cliente'; SelPesquisa.Tabela := tbCliente; tbPeso_Cliente.Open; end; AcertaInsercao; end; Toda vez que o formulário for ativado, e aberta a tabela acessória tbCliente e organizado os campos dentro do objeto SelPesquisa localizado na D_Modelo, depois aberta a tabela em que será realizada toda a movimentação a tbPeso_Cliente e chamado o procedimento particular para colocá-la em estado de inserção. 4. Selecione o evento OnClose do formulário: procedure TF_Massa.FormClose(Sender: TObject; var Action: TCloseAction); begin with D_Modelo do begin tbCliente.Close; tbPeso_Cliente.Cancel; tbPeso_Cliente.Close; end; end; Aqui é relativamente simples, simplesmente fechamos as tabelas cancelando o estado de inserção da tabela principal. 5. Vamos começar com os botões, primeiro o botão responsável para realizar a Gravação do Peso para tanto de um duplo-clique no objeto ButGrava para ativar o evento OnClick: procedure TF_Massa.ButGravaClick(Sender: TObject); begin if EditNUM_CPF.Text = '' then raise exception.create('Cliente não informado'); if LabNOM_CLIENTE.Caption = '' then raise exception.create('Cliente não cadastrado'); D_Modelo.tbPeso_Cliente.Post; AcertaInsercao; end; Fazemos duas críticas simples apenas para controlar se o CPF foi preenchido e se o nome do cliente foi encontrado (o que significará que o cliente existe), então gravamos o dado e simplesmente chamamos o procedimento para reativar o estado de inserção. 6. O segundo botão é o responsável para realizar o Cancelamento dos dados para tanto de um duplo-clique no objeto ButCancela para ativar o evento OnClick: procedure TF_Massa.ButCancelaClick(Sender: TObject); begin D_Modelo.tbPeso_Cliente.Cancel; AcertaInsercao; end; Este aqui é simplesmente disparar um comando Cancel para a tabela e chamarmos o procedimento
para reativar o estado de inserção.
Últimos Passos Um passo, que até poderia copiar é o Programando o Cliente, mas ao invés de repetir todos os comandos prefiro que você volte e veja na seção anterior como isso é feito. A principal parte diferente aqui é quanto ao cálculo da massa corporal, então selecione o objeto EditPES_MEDIDO e chame o evento OnExit: procedure TF_Massa.EditPES_MEDIDOExit(Sender: TObject); var ind: Integer; begin if LabNOM_CLIENTE.Caption <> '' then begin with D_Modelo do ind := Round(tbPESO_CLIENTEPES_MEDIDO.AsInteger / ((tbClienteALT_CLIENTE.AsInteger / 100) * (tbClienteALT_CLIENTE.AsInteger / 100))); LabMAS_CLIENTE.Caption := 'Massa coorporal é: ' + IntToStr(Ind); with LabMAS_CLIENTE do if ind < 20 then Caption := Caption + ' (Abaixo do Peso)' else if ind < 26 then Caption := Caption + ' (Normal)' else if ind < 30 then Caption := Caption + ' (Excesso de Peso)' else if ind < 40 then Caption := Caption + ' (Obsidade)' else Caption := Caption + ' (Obsidade Mórbida)'; end; end; Pronto, na saída da informação do peso, é calculada a massa corporal, apensa se existir um cliente pois precisamos saber da altura do cliente para o cálculo de sua massa, novamente vou frisar que se você não lembra como é realizado isto recorra a apostila referente ao Levantamento dos Dados.
Finalmente Agora basta você voltar para o formulário F_Menu para fazer a inserção dos comandos para chamar os formulários: procedure TF_Menu.EntradadoCliente1Click(Sender: TObject); begin F_Entrada := TF_Entrada.Create(Application); F_Entrada.ShowModal; F_Entrada.Free; end; procedure TF_Menu.MassaCorporal1Click(Sender: TObject); begin F_Massa := TF_Massa.Create(Application); F_Massa.ShowModal; F_Massa.Free; end; Também chame a partir do menu principal Project | Options... e retire os formulários F_Entrada e F_Massa da área dos Auto-Create forms.
Na próxima apostila vamos criar uma movimentação um tanto mais complexa, portanto esteje preparado.
14 Curso de Delphi 4.0 - Apostila 14 Autor: Fernando Antonio F. Anselmo eMail: [email protected] Pré-Requisitos: • • • •
Windows 98 Delphi 4.0 versão Client/Server Suite BDE 5.00 MS-Access 97
Arquivos trabalhados juntos com esta apostila: •
Objeto : DBDateEdit97
•
Seguintes Imagens : • ImgCalc.BMP
ImgGrava.BMP
ImgLocaliza.BMP
Prefácio Salve, nesta apostila vamos concluir as movimentações do nosso projeto. Nesta segunda fase mostrarei como coordenar dados de Saída, não associe os dados de saída como retirada ou qualquer outra coisa parecida, na verdade são dados já colocados nas tabelas mas que faltam a informação final, aquele famoso Tchan para ficar completo.
Saída de Clientes Vamos construir a parte da movimentação relativa a Saída de Clientes, é o momento em que o Cliente está saindo do SPA e precisa efetuar o pagamento. 1. A partir do Menu Principal vá em File | New Form e para este objeto altere apenas as seguintes propriedades: 1.1. BorderStyle: bsDialog 1.2. Caption: Saída de Clientes 1.3. Name: F_Saida 1.4. Position: poScreenCenter 1.5. Salve o formulário com o nome de fSaida.PAS
☞
Importante - Abra o Data Module D_Modelo, volte para o formulário F_Saida e alterne para a janela do programa e insira a seguinte declaração após a diretiva de compilação: {$R *.DFM} uses dModelo; 2. Crie um objeto do tipo DataSource e altere as seguintes propriedades:
2.1. DataSet: D_Modelo.tbPasta_Cliente 2.2. Name: dsPasta_Cliente 3. Crie um objeto do tipo TPanel e altere as seguintes propriedades: 3.1. Caption: 3.2. Align: alTop 4. Crie dentro do objeto Panel1 um objeto do tipo dbNavigator e altere as seguintes propriedades 4.1. DataSource: dsPasta_Cliente 4.2. Hints: Primeiro Registro Próximo Registro Registro Anterior Último Registro 4.3. Name: DbNavega 4.4. ShowHint: True 4.5. VisibleButtons: [nbFirst,nbPrior,nbNext,nbLast] 5. Crie dentro do objeto Panel1 um objeto do tipo BitBtn e altere as seguintes propriedades 5.1. Caption: &Localizar 5.2. Glyph: ImgLocaliza.BMP 5.3. Hint: Localiza Determinada Pasta do Cliente 5.4. Name: ButLocaliza 5.5. ShowHint: True 6. Crie agora um segundo objeto do tipo TPanel e altere as seguintes propriedades: 6.1. BevelInner: bvLowered 6.2. BorderWidth: 4 6.3. Align: alTop 7. Crie dentro do objeto Panel2 dez objetos do tipo Label e altere as seguintes propriedades: 7.1. Propriedade Caption (respectivamente): Cliente: Dt.Chegada: Plano: Qtd.Caloria: KCal Observação: Dt.Pagamento: Valor: Desconto: Total a Pagar: 7.2. Propriedade Font para: Font.Color = clMaroon Font.Style = [fsBold]
☞Importante - Aqui vão algumas observações: a. Deixe um espaço entre o label Cliente e Dt.Chegada b. O label KCal fica na frente do Label Qtd.Caloria com um espaço para colocar um campo
c. Deixe um espaço entre o Label Qtd.Caloria e o label Observação 8. Crie dentro do objeto Panel2 um objeto do tipo Bevel e altere as seguintes propriedades 8.1. Shape: bsBottomLine
☞Importante - Este objeto foi criado apenas para separar os dados, coloque-o entre os Labels Qtd.Caloria e Observação 9. Crie dentro do objeto Panel2 três objetos do tipo dbEdit e altere as seguintes propriedades: 9.1. DataSource: dsPasta_Cliente 9.2. DataField (respectivamente): NUM_CPF, DAT_CORRENTE e QTD_CALORIA 9.3. Font.Color: clMarron 9.4. Name (respectivamente): EditNUM_CPF, EditDAT_CORRENTE e EditQTD_CALORIA 9.5. Color: clBtnFace 9.6. TabStop: False 9.7. ReadOnly: True
☞Importante - Posicione-os em frente aos labels Cliente, Dt.Chegada e Qtd.Caloria respectivamente. 10. Crie dentro do objeto Panel2 abaixo do objeto EditNUM_CPF mais um objeto do tipo dbEdit e altere as seguintes propriedades: 10.1. DataSource: dsCliente 10.2. DataField: NOM_CLIENTE 10.3. Font.Color: clMarron 10.2. Name: EditNOM_CLIENTE 10.4. Color: clBtnFace 10.4. TabStop: False 10.4. ReadOnly: True 11. Crie dentro do objeto Panel2 na frente do Label Plano um objeto do tipo Edit e altere as seguintes propriedades 11.1. Font.Color: clMarron 11.2. Name: EditNOM_PLANO 11.3. Color: clBtnFace 11.4. TabStop: False 11.5. ReadOnly: True 12. Crie dentro do objeto Panel2 na frente do Label Dt.Pagamento um objeto do tipo dbDateEdit97 e altere as seguintes propriedades 12.1. DataSource: dsPasta_Cliente 12.2. DataField: DAT_PAGAMENTO 12.3. Font.Color: clNavy 12.4. Name: EditDAT_PAGAMENTO 13. Crie dentro do objeto Panel2 na frente do Label Valor e Desconto respectivamente dois objetos do tipo dbEdit e altere as seguintes propriedades: 13.1. DataSource: dsPasta_Cliente 13.2. DataField (respectivamente): VAL_TOTAL e VAL_DESCONTO 13.3. Font.Color: clNavy
13.2. Name (respectivamente): EditVAL_TOTAL e EditVAL_DESCONTO 14. Acerte a propriedade TabOrder desses três últimos objetos para uma sequência correta a partir do zero. 15. Crie dentro do objeto Panel2 na frente do objeto EditVAL_DESCONTO um objeto do tipo SpeedButton e altere as seguintes propriedades: 15.1. Flat: True 15.2. Glyph: ImgCalc.BMP 15.3. Hint: Calcula o Desconto Padrão 15.4. Name: ButCalcDesconto 15.5. ShowHint: True 16. Crie dentro do objeto Panel2 na frente do label Total a Pagar um objeto do tipo Panel e altere as seguintes propriedades: 16.1. BevelOuter: bvNone 16.2. BorderStyle: bsSingle 16.3. Height: 21 16.4. Name: PnlTotal 16.5. Alignment: taRightJustify 16.6. Font.Color: clMaroon 17. Abaixo do Objeto Panel2 crie dois objetos do tipo BitBtn e altere as seguintes propriedades: 17.1. Para o primeiro BitBtn: 17.1.1. Caption: &Grava 17.1.2. Glyph: ImgGrava.BMP 17.1.3. Hint: Grava os dados na Pasta do Cliente 17.1.4. Name: ButGrava 17.1.5. ShowHint: True 17.2. Para o segundo BitBtn: 17.2.1. Kind: bkClose 17.2.2. Caption: &Fechar 17.2.3. Hint: Fecha esta janela retornando ao menu do sistema 17.2.4. ShowHint: True O trabalho final ficou desta maneira:
Programando a Saída A programação aqui (ainda bem que estamos tratando do Delphi) não é algo tão complicado, pode ser se você desejar colocar coisas homéricas, a idéia é que o usuário localize na tabela Pasta Cliente a entrada deste Cliente, mas lembre-se que o mesmo Cliente pode visitar várias vezes o SPA então precisamos restringir os registros, acompanhe atentamente a codificação: 1. Inicialmente alterne para a Code Editor e na seção Private crie uma variável para acumular o valor de um desconto dado. private VlDesconto: Double; public 2. Selecione agora o evento OnShow do formulário: procedure TF_Saida.FormShow(Sender: TObject); begin with D_Modelo do begin SelPesquisa.NomeTela := 'Seleciona Determinada Pasta Cliente'; SelPesquisa.Tabela := tbPasta_Cliente; with tbCliente do begin MasterSource := dsPasta_Cliente; MasterFields := 'NUM_CPF'; Open; end; with tbPasta_Cliente do begin Filter := 'VAL_TOTAL < 0'; Filtered := True;
Open; end; end; end; Toda vez que o formulário for ativado, é organizado os campos dentro do objeto SelPesquisa localizado na D_Modelo, e ativado um relacionamento entre a tabela tbCliente e tbPasta_Cliente e é aberta a tabela acessória tbCliente e depois é ativado um filtro para a tabela tbPasta_Cliente permitindo que sejam mostrados apenas os registros aonde o Valor ainda é 0 (ou menor, isso incluirá os nulos) e aberta a tabela em que será realizada toda a movimentação a tbPasta_Cliente.
☞Importante - Abra a tabela ascessória primeiramente (no caso tbCliente), pois existirá uma dependência no evento quando os dados serão mudados do objeto DsPasta_Cliente que necessitará que esta tabela esteje aberta. 3. Selecione o evento OnClose do formulário: procedure TF_Saida.FormClose(Sender: TObject; var Action: TCloseAction); begin with D_Modelo do begin with tbPasta_Cliente do begin if dsPasta_Cliente.State = dsEdit then Cancel; Close; Filter := ''; Filtered := False; end; with tbCliente do begin Close; MasterSource := Nil; MasterFields := ''; end; end; end; Neste momento fechamos inicialmente a tabela principal, aplicando um comando Cancel na tabela caso os dados estejam em momento de edição (para não acontecer uma gravação equivocada, se o usuário quer gravar então ele deve apertar o botão Grava) depois de fechada, eliminamos o filtro da tabela, o segundo passo é fechar a tabela secundária, eliminando também a dependência entre as duas tabelas. 4. Vamos começar com os botões, primeiro o botão responsável para realizar a Gravação na Pasta para tanto de um duplo-clique no objeto ButGrava para ativar o evento OnClick: procedure TF_Saida.ButGravaClick(Sender: TObject); begin if EditDAT_PAGAMENTO.Text = '' then Raise Exception.Create('Data de Pagamento não informada'); if EditVAL_TOTAL.Text = '' then Raise Exception.Create('Valor não informado'); D_Modelo.tbPasta_Cliente.Post; end; Fazemos duas críticas simples apenas para controlar se a Data e o Valor de pagamento foram preenchidos, então simplesmente gravamos o dado. Aqui não precisamos nos preocupar em colocar a tabela em momento de inserção pois o Delphi trata isto automaticamente. Também, automaticamente, o registro sumirá da tela, por causa do Filtro ativo.
5. O botão localizado ao lado da barra de navegação é o responsável para realizar a Consulta a Pasta Cliente para tanto de um duplo-clique no objeto ButLocaliza para ativar o evento OnClick: procedure TF_Saida.ButLocalizaClick(Sender: TObject); begin D_Modelo.SelPesquisa.Execute; end; É um simples comando aqui apenas executamos o objeto SelPesquisa ele se encarregará de posicionar no registro correto. 6. Selecione o objeto EditVAL_TOTAL e chame o evento OnExit: procedure TF_Saida.EditVAL_TOTALExit(Sender: TObject); begin if EditVal_Total.Text <> '' then with D_Modelo.tbPasta_Cliente do PnlTotal.Caption := Format('%10.2m', [(FieldByName('VAL_TOTAL').AsFloat - FieldByName ('VAL_DESCONTO').AsFloat)]); end; Aqui será feito para calcularmos o valor total a pagar, no momento da saída do campo Valor e do campo Desconto. 7. Selecione o objeto EditVAL_DESCONTO e localize o evento OnExit, clique na seta que aparece ao lado do campo e coloque nele a chamada EditVAL_TOTALExit. 8. O botão ao lado do EditVAL_DESCONTO é o responsável para calcular um desconto concedido para tanto de um duplo-clique no objeto ButCalcDesconto para ativar o evento OnClick: procedure TF_Saida.ButCalcDescontoClick(Sender: TObject); begin if EditVal_Total.Text <> '' then EditVAL_DESCONTO.Text := FloatToStr(D_Modelo.tbPasta_ClienteVal_Total.AsFloat * VlDesconto) else MessageDlg('Informe primeiro o Valor',mtInformation,[mbOk],0); end; Verificamos se o Valor do Pagamento já foi preenchido, então calculamos o desconto com base na variável VlDesconto. 9. Este agora é o coração de todo o formulário, é aqui que a maior parte foi projetada, selecione o objeto DsPasta_Cliente e dê um duplo-clique no evento OnDataChange: procedure TF_Saida.dsPasta_ClienteDataChange(Sender: TObject; Field: TField); procedure AcertaDesc(ValS: String; ValN: Double); begin LabDesconto.Caption := 'Desconto ' + ValS + '%:'; VlDesconto := ValN; end; begin with D_Modelo.tbPasta_Cliente do if FieldByName('PLN_ADOTADO').AsString = 'A' then
EdtNOM_PLANO.Text := 'Plano Anti-Stress' else if FieldByName('PLN_ADOTADO').AsString = 'B' then EdtNOM_PLANO.Text := 'Plano Reeducação' else if FieldByName('PLN_ADOTADO').AsString = 'C' then EdtNOM_PLANO.Text := 'Plano Completo' else if FieldByName('PLN_ADOTADO').AsString = 'D' then EdtNOM_PLANO.Text := 'Plano Especial de Reeducação' else EdtNOM_PLANO.Text := ''; if EditVal_Total.Text <> '' then with D_Modelo.tbPasta_Cliente do PnlTotal.Caption := Format('%10.2m', [(FieldByName('VAL_TOTAL').AsFloat - FieldByName ('VAL_DESCONTO').AsFloat)]) else PnlTotal.Caption := Format('%10.2m', [0.00]); with D_Modelo do with QrySQL do begin if Active then Close; SQL.Clear; SQL.Add('Select Count(NUM_CPF) from ' + NmPasta_Cliente); SQL.Add('Where (NUM_CPF = ''' + EditNUM_CPF.Text + ''')'); Open; LabObserva.Caption := 'Observação: Não existe'; LabDesconto.Caption := 'Desconto:'; VlDesconto := 0; if not EOF then begin LabObserva.Caption := 'Observação: Esta é a ' + Fields[0].AsString + 'ª visita deste cliente.'; case Fields[0].AsInteger of 2: AcertaDesc('5',0.05); 3: AcertaDesc('10',0.1); 4: AcertaDesc('15',0.15); 5: AcertaDesc('16',0.16); 6: AcertaDesc('17',0.17); 7: AcertaDesc('18',0.18); 8: AcertaDesc('19',0.19); else if Fields[0].AsInteger > 8 then AcertaDesc('20',0.2); end; end; Close; end; D_Modelo.tbCliente.Refresh; end; Olhando assim parece complicado mas não precisamos temer tanto, o brincadeira é a seguinte, inicialmente coloquei um procedimento dentro para mostrar no LabDesconto se existe algum desconto cedido, e setar a variável VlDesconto com este valor. Começando o procedimento realmente, inicialmente é verificado qual é o plano que o cliente optou, depois é calculado o valor a pagar (da mesma forma em que foi feito na saida dos campos EditVAL_TOTAL e EditVAL_DESCONTO). Agora utilizaremos a Query ascessória para pesquisarmos dentro da tabela Pasta Cliente quantas vezes este Cliente já veio ao SPA, e verificamos qual o valor do desconto que pode ser concedido para este cliente (Lembra-se da regra: 2ª Visita = 5%, 3ª Visita = 10%, verifique na parte do Levantamento dos Dados), e finalmente damos um Refresh na tabela de Cliente para que o relacionamento feito entre ela e a tabela Pasta_Cliente possa ser efetivado, mostrando o nome do cliente corretamente.
Finalmente Agora basta você voltar para o formulário F_Menu para fazer a inserção dos comandos para chamar os formulários: procedure TF_Menu.SaidadoCliente1Click(Sender: TObject); begin F_Saida := TF_Saida.Create(Application); F_Saida.ShowModal; F_Saida.Free; end; Também chame a partir do menu principal Project | Options... e retire o formulário F_Saida da área dos Auto-Create forms. Acredito que você tenha reparado os dois processos de movimentação, na anterior trabalhamos basicamente com o momento INSERT da tabela, era apenas uma entrada simples e básica, nesta aqui pegamos aqueles dados inseridos e trabalhamos um pouco mais, solicitando mais alguns dados para finalmente finalizarmos este Cadastro. Em movimentações, também é possível, e admissível, criarmos uma tabela idêntica, apenas para servir como arquivamento dos dados, ou seja, após concluirmos esta segunda fase da movimentação, passar os dados já gravados para uma segunda tabela, tipo um Fechamento. Na próxima apostila vamos começar a analisar como são feitos relatórios.
15 Curso de Delphi 4.0 - Conexão Delphi com o MS-Access Autor: Fernando Antonio F. Anselmo eMail: [email protected] Pré-Requisitos: • • • •
Windows 98 Delphi 4.0 versão Client/Server Suite BDE 5.00 MS-Access 97
Prefácio Antes de começarmos o nosso curso precisamos configurar o acesso ao banco de dados que será utilizado, MS-Access. Porque trabalhar com o Access ? Bem, poderia explicar que porque ele é o banco de dados mais fácil de se trabalhar tanto para nós (programadores) quanto para o usuário, ou então que muitos de nós o temos, ou ainda pode-se dizer que ele é um padrão mundial, mas fico com a explicação de que entre todos os bancos de dados de pequeno porte (Inclui aí, MS-Access, Paradox, dBase, entre outros) ele é o que melhor se comporta para o desenvolvimento inicial de qualquer projeto suportando as alterações feitas constantemente na base, perda e recuperação dos índices, e por aí vai. Existe algum problema em se migrar um sistema desenvolvido no Access para outro banco de dados, por exemplo ORACLE ? Não existe "quase" nenhum problema na migração de sistemas com o Delphi, normalmente não é preciso mudar uma única linha de programação para se utilizar o mesmo sistema em bancos de dados completamente diferente (desde óbvio siga-se alguns passos básico). O único problema que existe numa migração é quanto aos comandos SQL (Structure Query Language), pois infelizmente o Access possui um SQL próprio não comum aos outros bancos de dados. Mas todos os problemas são facilmente resolvidos criando-se variáveis globais para definir qual tipo de banco estamos lidando, qual o nome correto da tabela e assim sucessivamente. A ferramenta Delphi 4.0 possui uma conexão direta com o Banco de Dados MS-Access 97, para tanto faz-se necessário de: 1. 2.
BDE (Borland DataBase Engine) para a versão 5.00 Biblioteca de acesso DAO 3.5 (IDDA3532.DLL) colocada no diretório do BDE - C:\Arquivos de Programas\Borland\Common Files\BDE
A conexão do Delphi com o MS-Access funciona da seguinte maneira BDE - DAO - Banco Access, então na verdade é preciso instalar o DAO (Data Access Objects), a Microsoft para as versões MS-Access posteriores a 2.0 (que o acesso era feito com o JET) prendeu o instalador do DAO com os aplicativos de desenvolvimento dela tais como: Visual Basic, MS-J++, MS-C++ e assim vai, então para ter a "correta" licença de distribuição do DAO você precisa adquirir qualquer um desses aplicativos. O DAO se faz necessário pois precisamos levar o sistema para o nosso cliente, e do mesmo modo que você precisa instalar o sistema em Delphi, o MDB, o BDE client, você também precisará instalar o link de conexão. Você poderá acertar o Install Shield (conforme a apostila 4) para instalar todas as bibliotecas de acesso do DAO mas é necessário tê-las.
☞
Importante - o BDE 5.00 pode operar tanto com o DAO 3.0 quanto com o 3.5.Para definir qual será utilizado, voce precisa informar no BDE Administrator qual a DLL que sera' utilizada para o driver
MSACCESS. A biblioteca DAO 3.0 é a IDDAO32.DLL e a Biblioteca DAO 3.5 é IDDA3532.DLL (Que será a que utilizaremos) Mas antes de se criar qualquer alias de conexão, entre no BDE Administrator e proceda a seguinte troca na página Configuration, conforme a figura:
Prontinho basta agora sair e entrar novamente do BDE Administrator e criamos nossos Aliases de conexão.
16 Curso de Delphi 4.0 - Principais Instruções em SQL Autor: Fernando Antonio F. Anselmo eMail: [email protected] Pré-Requisitos: • • • •
Windows 98 Delphi 4.0 versão Client/Server Suite BDE 5.00 MS-Access 97
Prefácio Esta apostila foi desenvolvida com o auxílio on-Line do banco MS-ACCESS, este tipo de SQL para este banco não é totalmente compatível com o SQL Padrão ANSI, que é o oficial na maioria dos bancos de dados, então algumas cláusulas podem não funcionar em outros gerenciadores de bancos de dados.
Instrução SELECT Instrui o programa principal do banco de dados para retornar a informação como um conjunto de registros.
Sintaxe SELECT [predicado { * | tabela.* | [tabela.]campo1 [AS alias1] [, [tabela.]campo2 [AS alias2] [, ...]]} FROM expressãotabela [, ...] [IN bancodedadosexterno] [WHERE... ] [GROUP BY... ] [HAVING... ] [ORDER BY... ] [WITH OWNERACCESS OPTION] A instrução SELECT tem as partes abaixo: Parte predicado
* tabela campo1, campo2 alias1, alias2
Descrição Um dos seguintes predicados: ALL, DISTINCT, DISTINCTROW ou TOP. Você usa o predicado para restringir o número de registros que retornam. Se nenhum for especificado, o padrão será ALL. Especifica que todos os campos da tabela ou tabelas especificadas são selecionados. O nome da tabela que contém os campos dos quais os registros são selecionados. Os nomes dos campos dos quais os dados serão recuperados. Se você incluir mais de um campo, eles serão recuperados na ordem listada. Os nomes que serão usados como títulos de colunas em vez dos nomes originais das colunas na tabela.
expressãotabela bancodedadosexterno
O nome da tabela ou tabelas contendo os dados que você quer recuperar. O Nome do banco de dados que contém as tabelas em expressãotabela se não estiver no banco de dados atual.
Comentários Para executar esta operação, o programa principal de banco de dados procura a tabela ou tabelas especificadas, extrai as colunas escolhidas, seleciona as linhas que satisfazem o critério e classifica ou agrupa as linhas resultantes na ordem especificada. A instrução SELECT não muda os dados no banco de dados. SELECT é normalmente a primeira palavra em uma instrução SQL. A maior parte das instruções SQL são instruções SELECT. A sintaxe mínima da instrução SELECT é: SELECT campos FROM tabela Você pode usar um asterisco (*) para selecionar todos os campos na tabela. O exemplo abaixo seleciona todos os campos na tabela Funcionários: SELECT * FROM Funcionários; Se o nome de um campo estiver incluído em mais de uma tabela na cláusula FROM, preceda-o com o nome da tabela e o operador . (ponto). No exemplo abaixo, o campo Departamento está nas tabelas Funcionários e Supervisores. A instrução SQL seleciona Departamento da tabela Funcionários e NomeSupv da tabela Supervisores: SELECT Funcionários.Departamento, Supervisores.NomeSupv FROM Funcionários INNER JOIN Supervisores WHERE Funcionários.Departamento = Supervisores.Departamento; Ao criar um objeto Recordset, o programa principal de banco de dados do Jet usa o nome do campo da tabela como o nome do objeto Field no objeto Recordset. Se você quiser um nome de campo diferente ou um nome que não esteja implícito na expressão usada para gerar o campo, use a palavra reservada AS. O exemplo abaixo usa o título Nasc para nomear o objeto Field retornado no objeto Recordset resultante: SELECT DataNasc AS Nasc FROM Funcionários; Sempre que você usar funções aggregate ou consultas que retornem nomes de objetos Field ambíguos ou duplicados, você precisará usar a cláusula AS para fornecer um nome alternativo para o objeto Field. O exemplo abaixo usa o título Contagem para nomear o objeto Field retornado no objeto Recordset resultante: SELECT COUNT(FuncionárioID) AS Contagem FROM Funcionários; Você pode usar outras cláusulas na instrução SELECT para restringir e organizar posteriormente os seus dados retornados.
Cláusula GROUP BY GROUP BY é opcional. Valores de resumo são omitidos se não houver qualquer função aggregate SQL na instrução SELECT. Os valores Null nos campos GROUP BY são agrupados e não omitidos. No entanto, os valores Null não são avaliados em qualquer função aggregate SQL. Use a cláusula WHERE para excluir linhas que você não quer agrupadas e use a cláusula HAVING para filtrar os registros após eles terem sido agrupados.
A não ser que contenha dados Memo ou OLE Object, um campo na lista de campos GROUP BY pode fazer referência a qualquer campo em qualquer tabela listada na cláusula FROM. Mesmo que o campo não esteja incluído na instrução SELECT, fornecida a instrução SELECT, inclua pelo menos uma função SQL. O programa principal de banco de dados do Jet não pode agrupar campos Memo ou OLE Objects. Todos os campos na lista de campos SELECT devem ser incluídos na cláusula GROUP BY ou incluídos como argumentos em uma função aggregate SQL.
Cláusula HAVING HAVING é opcional. HAVING é semelhante a WHERE, que determina quais registros são selecionados. Depois que os registros são agrupados com GROUP BY, HAVING determina quais registros são exibidos: SELECT CategoriaID, Sum(UnidadesNoEstoque) FROM Produtos GROUP BY CategoriaID HAVING Sum(UnidadesNoEstoque) > 100 AND LIKE "BOS*"; Uma cláusula HAVING pode conter até 40 expressões vinculadas por operadores lógicos, como And ou Or.
Cláusula ORDER BY ORDER BY é opcional. Entretanto, se você quiser exibir seus dados na ordem classificada, você deve utilizar ORDER BY. O padrão ordem de classificação é ascendente (A a Z, 0 a 9). Os dois exemplos abaixo classificam os nomes dos funcionários pelo sobrenome. SELECT Sobrenome, Nome FROM Funcionários ORDER BY Sobrenome; SELECT Sobrenome, Nome FROM Funcionários ORDER BY Sobrenome ASC; Para classificar em ordem descendente (Z a A, 9 a 0), adicione a palavra reservada DESC ao final de cada campo que você quiser classificar em ordem descendente. O exemplo abaixo seleciona salários e os classifica em ordem descendente SELECT Sobrenome, Salário FROM Funcionários ORDER BY Salário DESC, Sobrenome; Se você especificar um campo que contém dados Memo ou OLE Objects na cláusula ORDER BY, um erro ocorrerá. O programa principal de banco de dados do Jet não classifica campos deste tipo. ORDER BY é normalmente o último item em uma instrução SQL. Você pode incluir campos adicionais na cláusula ORDER BY. Os registros são classificados primeiro pelo primeiro campo listado depois de ORDER BY. Os registros que tiverem valores iguais naquele campo são classificados pelo valor no segundo campo listado e assim por diante.
Cláusula WITH OWNERACCESS OPTION A declaração WITH OWNERACCESS OPTION é opcional. O exemplo abaixo habilita o usuário a ver as informações de salário (mesmo que não tenha outra permissão para ver a tabela Folha de Pagamentos) desde que o proprietário da consulta tenha tal permissão: SELECT Sobrenome, Nome, Salário FROM Funcionários ORDER BY Sobrenome WITH OWNERACCESS OPTION;
Se, por outro lado, um usuário for impedido de criar ou anexar a uma tabela, você poderá usar WITH OWNERACCESS OPTION para habilitá-lo a executar uma consulta construção de tabela ou consulta anexação. Se você quiser reforçar as configurações de segurança do grupo de trabalho e as permissões dos usuários, não inclua a declaração WITH OWNERACCESS OPTION. Esta opção exige que você tenha acesso ao arquivo System.mda associado ao banco de dados. É realmente útil em implementações de multiusuários seguras.
Exemplo da instrução SELECT, cláusula FROM Esse exemplo seleciona os campos "Sobrenome" e "Nome" de todos os registros da tabela "Funcionários". SELECT Sobrenome, Nome FROM Funcionários Esse exemplo seleciona todos os campos da tabela "Funcionários". SELECT Funcionários.* FROM Funcionários; Esse exemplo conta o número de registros que têm uma entrada no campo "CódigoPostal" e nomeia o campo retornado como "Tcp". SELECT Count(CódigoPostal) AS Tcp FROM Clientes; Esse exemplo mostra qual seria o salário se cada funcionário recebesse um aumento de 10 porcento. Não altera o valor original dos salários. SELECT Sobrenome, Salário AS Atual, Salário * 1.1 AS Proposto FROM Funcionários; Esse exemplo coloca o título Nome no topo da coluna "Sobrenome". O título Salário é exibido no topo da coluna "Salário". SELECT Sobrenome AS Nome, Salário FROM Funcionários; Esse exemplo mostra o número de funcionários e os salários médio e máximo. SELECT Count(*) AS [Total de Funcionários], Avg(Salário) AS [Salário Médio], Max(Salário) AS [Salário Máximo] FROM Funcionários; Para cada registro, mostra Sobrenome e Salário no primeiro e último campos. A seqüência de caracteres "tem um salário de" é retornada como o campo do meio de cada registro. SELECT Sobrenome, 'tem um salário de', Salário FROM Funcionários;
Exemplo de cláusula GROUP BY Esse exemplo cria uma lista de nomes de departamentos únicos e o número de funcionários em cada um destes departamentos. SELECT Departamento, Count([Departamento]) AS Tbc FROM Funcionários GROUP BY Departamento; Para cada título de função único, calcula o número de funcionários do departamento de Vendas que têm este título. SELECT Título, Count(Título) AS Tbc FROM Funcionários WHERE Departamento = 'Vendas' GROUP BY Título;
Esse exemplo calcula o número de itens em estoque para cada combinação de número e cor do item. SELECT Item, Sum(Unidades) AS Tbc FROM ItensEmEstoque GROUP BY Item, Cor;
Exemplo de cláusula HAVING Esse exemplo seleciona os títulos de cargos do departamento de Produção atribuídos a mais de 50 funcionários. SELECT Título, Count(Título) FROM Funcionários WHERE Departamento = 'Produção' GROUP BY Título HAVING Count(Título) > 50; Esse exemplo seleciona os departamentos que tenham mais de 100 funcionários. SELECT Departamento, Count([Departamento]) FROM Funcionários GROUP BY Departamento HAVING Count(Departamento) > 100;
Exemplo de cláusula ORDER BY As instruções SQL mostradas abaixo usam a cláusula ORDER BY para classificar os registros em ordem alfabética e depois por categoria. Esse exemplo ordena os registros pelo sobrenome, em ordem descendente (Z-A). SELECT Sobrenome, Nome FROM Funcionários ORDER BY Sobrenome DESC; Esse exemplo ordena, primeiro, por categoria ID e depois por nome do produto. SELECT CategoriaID, ProdutoNome, PreçoUnit FROM Produtos ORDER BY CategoriaID, NomeProduto;
Instrução INSERT INTO Adiciona um ou vários registros a uma tabela. Isto é referido como consulta anexação.
Sintaxe Consulta anexação de vários registros: INSERT INTO destino [IN bancodedadosexterno] [(campo1[, campo2[, ...]])] SELECT [origem.]campo1[, campo2[, ...] FROM expressãodetabela
Consulta anexação de um único registro: INSERT INTO destino [(campo1[, campo2[, ...]])] VALUES (valor1[, valor2[, ...]) A instrução INSERT INTO tem as partes abaixo: Parte destino bancodedadosexterno origem campo1, campo2
expressãodetabela
valor1, valor2
Descrição O nome da tabela ou consulta em que os registros devem ser anexados. O caminho para um banco de dados externo. Para uma descrição do caminho, consulte a cláusula IN. O nome da tabela ou consulta de onde os dados devem ser copiados. Os nomes dos campos aos quais os dados devem ser anexados, se estiverem após um argumento destino ou os nomes dos campos dos quais se deve obter os dados, se estiverem após um argumento origem. O nome da tabela ou tabelas das quais registros são inseridos. Este argumento pode ser um único nome de tabela ou uma combinação resultante de uma operação INNER JOIN, LEFT JOIN ou RIGHT JOIN ou de uma consulta gravada. Os valores para inserir em campos específicos do novo registro. Cada valor é inserido no campo que corresponde à posição do valor na lista: Valor1 é inserido no campo1 do novo registro, valor2 no campo2 e assim por diante. Você deve separar os valores com uma vírgula e colocar os campos de textos entre aspas (" ").
Comentários Você pode usar a instrução INSERT INTO para adicionar um único registro a uma tabela usando a sintaxe de consulta anexação de um único registro como mostrado acima. Neste caso, seu código especifica o nome e o valor de cada campo do registro. Você precisa especificar cada um dos campos do registro para os quais um valor deve ser designado e um valor para este campo. Quando você não especifica cada campo, o valor padrão ou Null é inserido nas colunas omitidas. Os registros são adicionados no final da tabela. Você também pode usar INSERT INTO para anexar um conjunto de registros de outra tabela ou consulta usando a cláusula SELECT ... FROM como é mostrado acima na sintaxe consulta anexação de vários registros. Neste caso, a cláusula SELECT especifica os campos para acrescentar à tabela destino especificada. A tabela de origem ou de destino pode especificar uma tabela ou uma consulta. Se uma consulta for especificada, o programa principal de banco de dados do Microsoft anexa a qualquer e a todas as tabelas especificadas pela consulta. INSERT INTO é opcional, mas quando incluída, precede a instrução SELECT. Se sua tabela de destino contém uma chave primária, você deve acrescentar valores únicos, não Null ao campo ou campos da chave primária. Caso contrário, o programa principal de banco de dados do Jet não anexará os registros. Se você anexar registros a uma tabela com um campo Counter e quiser numerar novamente os registros anexados, não inclua o campo Counter em sua consulta. Inclua o campo Counter na consulta se quiser manter os valores originais do campo. Use a cláusula IN para anexar registros a uma tabela de outro banco de dados. Para achar quais registros serão anexados, antes de você executar a consulta anexação, primeiro execute e veja os resultados de uma consulta seleção que use o mesmo critério de seleção.
Uma operação de consulta anexação copia os registros de uma ou mais tabelas em outra. As tabelas que contêm os registros que você anexa não são afetadas pela operação de consulta anexação. Em lugar de acrescentar registros existentes de outra tabela, você pode especificar o valor de cada campo em um único registro novo usando a cláusula VALUES. Se você omitir a lista de campo, a cláusula VALUES deve incluir um valor para cada campo na tabela; caso contrário, um erro ocorrerá em INSERT. Use uma instrução adicional INSERT INTO com uma cláusula VALUES para cada registro adicional que você quiser criar.
Exemplo de instrução INSERT INTO Esse exemplo seleciona todos os registros de uma tabela hipotética "Novos Clientes" e os adiciona à tabela "Clientes" (quando não são designadas colunas individuais, os nomes das colunas das tabelas SELECT devem corresponder exatamente aos da tabela INSERT INTO). INSERT INTO Clientes SELECT [Novos Clientes].* FROM [Novos Clientes]; Esse exemplo cria um novo registro na tabela "Funcionários" INSERT INTO Funcionários (Nome,Sobrenome, Título) VALUES ("André", "Pereira", "Estagiário"); Esse exemplo seleciona todos os estagiários de uma tabela hipotética "Estagiários" que foram contratados há mais de 30 dias e adiciona seus registros à tabela "Funcionários". INSERT INTO Funcionários SELECT Estagiários.* FROM Estagiários WHERE DataContrato < Now() - 30;
Declaração UPDATE Cria uma consulta atualização que altera os valores dos campos em uma tabela especificada com base em critérios específicos.
Sintaxe UPDATE tabela SET valornovo WHERE critério; A instrução UPDATE tem as partes abaixo: Parte tabela valornovo
Descrição O nome da tabela cujos os dados você quer modificar. Uma expressão que determina o valor a ser inserido em um campo específico nos
registros atualizados. Uma expressão que determina quais registros devem ser atualizados. Só os registros que satisfazem a expressão são atualizados.
critério
Comentários UPDATE é especialmente útil quando você quer alterar muitos registros ou quando os registros que você quer alterar estão em várias tabelas. Você pode alterar vários campos ao mesmo tempo. O exemplo abaixo aumenta o Valor do Pedido em 10 por cento e o valor do Frete em 3 por cento para embarques do Reino Unido: UPDATE Pedidos SET ValorPedido = ValorPedido * 1.1, Frete = Frete * 1.03 WHERE PaísEmbarque = 'RU'; UPDATE não gera um conjunto de resultados. Se você quiser saber quais resultados serão alterados, examine primeiro os resultados da consulta seleção que use os mesmos critérios e então execute a consulta atualização.
Exemplo de instrução UPDATE Esse exemplo muda os valores no campo "RelatórioPara" para 5 para todos os registros de funcionários que atualmente têm valores de RelatórioPara de 2. UPDATE Funcionários SET RelatórioPara = 5 WHERE RelatórioPara = 2; Esse exemplo aumenta o "PreçoUnit" de todos os produtos não suspensos do fornecedor 8 em 10 porcento. UPDATE Produtos SET PreçoUnit = PreçoUnit * 1.1 WHERE FornecedorID = 8 AND Suspenso = No; Esse exemplo reduz o PreçoUnit de todos os produtos não suspensos fornecidos pela Tokyo Traders em 5 porcento. As tabelas "Produtos" e "Fornecedores" têm uma relação um para vários. UPDATE Fornecedores INNER JOIN Produtos ON Fornecedores.FornecedorID = Produtos.FornecedorID SET PreçoUnit = PreçoUnit * .95 WHERE NomeEmpresa = 'Tokyo Traders' AND Suspenso = No;
Instrução DELETE Cria uma consulta exclusão que remove registros de uma ou mais tabelas listadas na cláusula FROM que satisfaz a cláusula WHERE.
Sintaxe DELETE [tabela.*] FROM tabela WHERE critério A instrução DELETE tem as partes abaixo: Parte tabela.* tabela critério
Descrição O nome opcional da tabela da qual os registros são excluídos. O nome da tabela da qual os registros são excluídos. Uma expressão que determina qual registro deve ser excluído.
Comentários DELETE é especialmente útil quando você quer excluir muitos registros. Para eliminar uma tabela inteira do banco de dados, você pode usar o método Execute com uma instrução DROP. Entretanto, se você eliminar a tabela, a estrutura é perdida. Por outro lado, quando você usa DELETE, apenas os dados são excluídos. A estrutura da tabela e todas as propriedades da tabela, como atributos de campo e índices, permanecem intactos. Você pode usar DELETE para remover registros de tabelas que estão em uma relação um por vários com outras tabelas. Operações de exclusão em cascata fazem com que os registros das tabelas que estão no lado "vários" da relação sejam excluídos quando os registros correspondentes do lado "um" da relação são excluídos na consulta. Por exemplo, nas relações entre as tabelas Clientes e Pedidos, a tabela Clientes está do lado "um" e a tabela Pedidos está no lado "vários" da relação. Excluir um registro em Clientes faz com que os registros correspondentes em Pedidos sejam excluídos se a opção de exclusão em cascata for especificada. Uma consulta de exclusão exclui registros inteiros e não apenas dados em campos específicos. Se você quiser excluir valores de um campo específico, crie uma consulta atualização que mude os valores para Null.
Importante Após remover os registros usando uma consulta exclusão, você não poderá desfazer a operação. Se quiser saber quais arquivos foram excluídos, primeiro examine os resultados de uma consulta seleção que use o mesmo critério e então, execute a consulta exclusão. Mantenha os backups de seus dados. Se você excluir os registros errados, poderá recuperá-los a partir dos seus backups.
Exemplo de instrução DELETE Esse exemplo exclui todos os registros de funcionários cujo título seja Estagiário. Quando a cláusula FROM inclui apenas uma tabela, não é necessário indicar o nome da tabela na instrução DELETE. DELETE *FROM Funcionários WHERE Título = 'Estagiário'; Esse exemplo exclui todos os registros de funcionários cujo título seja Estagiário e que também tenham um registro na tabela "FolhadePagamento". As tabelas "Funcionários" e "FolhadePagamento" têm uma relação um por um. DELETE Funcionários.* FROM Funcionários INNER JOIN FolhaDePagamento ON Funcionários.FuncionárioID = FolhadePagamento.FuncionárioID WHERE Funcionários.Título = 'Estagiário';
Subconsultas SQL Uma subconsulta é uma instrução SELECT aninhada dentro de uma instrução SELECT, INSERT, DELETE ou UPDATE ou dentro de uma outra subconsulta.
Sintaxe Você pode usar três formas de sintaxe para criar uma subconsulta: comparação [ANY | ALL | SOME] (instruçãosql) expressão [NOT] IN (instruçãosql) [NOT] EXISTS (instruçãosql) Uma subconsulta tem as partes abaixo: Parte comparação expressão instruçãosqlt
Descrição Uma expressão e um operador de comparação que compara a expressão com o resultado da subconsulta. Uma expressão para a qual o resultado definido da subconsulta é procurado. Uma instrução SELECT de acordo com as mesmas regras e formato de qualquer outra instrução SELECT. Ela deve estar entre parênteses.
Comentários Você pode usar uma subconsulta em vez de uma expressão na lista de campo de uma instrução SELECT ou em uma cláusula WHERE ou HAVING. Em uma subconsulta, você usa uma instrução SELECT para fornecer um conjunto de um ou mais valores específicos para avaliar as expressões das cláusulas WHERE ou HAVING. Use o predicado ANY ou SOME, que são sinônimos, para recuperar registros na consulta principal que satisfaçam a comparação com quaisquer registros recuperados na subconsulta. O exemplo abaixo retorna todos os produtos cujo preço unitário é maior que o preço de qualquer produto vendido com um desconto de 25 por cento ou mais: SELECT * FROM Produtos WHERE PreçoUnit > ANY (SELECT PreçoUnit FROM PedidoDetalhes WHERE Desconto >= .25); Use o predicado ALL para recuperar apenas os registros na consulta principal que satisfaçam a comparação com todos os registros recuperados na subconsulta. Se você mudou ANY para ALL no exemplo acima, a consulta retornaria apenas os produtos cujo preço unitário fosse maior que o de todos os produtos vendidos com um desconto de 25 por cento ou mais. Isto é muito mais restritivo. Use o predicado IN para recuperar apenas os registros na consulta principal para os quais alguns registros na subconsulta contêm um valor igual. O exemplo abaixo retorna todos os produtos com um desconto de 25 por cento ou mais:
SELECT * FROM Produtos WHERE ProdutoID IN (SELECT ProdutoID FROM PedidoDetalhes WHERE Desconto >= .25); De maneira contrária, você pode usar NOT IN para recuperar apenas os registros na consulta principal para os quais não existam registros com valores iguais na subconsulta. Utilize o predicado EXISTS (com a palavra reservada NOT opcionalmente) em comparações true/false para determinar se a subconsulta retorna algum registro. Você também pode usar aliases de nomes de tabelas em uma subconsulta para fazer referência a tabelas listadas em uma cláusula FROM fora da subconsulta. O exemplo abaixo retorna os nomes dos funcionários cujos salários sejam iguais ou superiores à média de salários de todos os funcionários na mesma função. Para a tabela Funcionários é dada o alias "T1": SELECT Sobrenome, Nome, Título, Salário FROM Funcionários AS T1 WHERE Salário >= (SELECT Avg(Salário) FROM Funcionários WHERE T1. T1.Título = Funcionários.Título) Order by Title; No exemplo acima, a palavra reservada AS é opcional. Algumas subconsultas são aceitas em consultas de tabela cruzada especialmente como predicados (as da cláusula WHERE). Subconsultas como saída (as da lista SELECT) não são aceitas em tabelas de referência cruzada.
Exemplos de subconsultas SQL Esse exemplo lista o nome, título e salário de todos os representantes de vendas cujos salários sejam superiores aos de todos os gerentes e diretores. SELECT Sobrenome, Nome, Título, Salário FROM Funcionários WHERE Título LIKE "*Repr Vendas*" AND Salário > ALL (SELECT Salário FROM Funcionários WHERE (Título LIKE "*Gerente*") OR (Título LIKE "*Diretor*")); Esse exemplo lista o nome e preço unitário de todos os produtos cujo preço unitário seja igual ao do Licor de Cacau. SELECT NomeProduto, PreçoUnit FROM Produtos WHERE PreçoUnit = (SELECT PreçoUnit FROM [Produtos] WHERE NomeProduto = "Licor de Cacau"); Esse exemplo lista a empresa e o contato de cada empresa de todos os clientes que fizeram pedidos no segundo trimestre de 1995. SELECT NomeContato, NomeEmpresa, ContatoTítulo, Fone FROM Clientes WHERE ClienteID IN (SELECT ClienteID FROM Pedidos WHERE DataPedido BETWEEN #1/04/95# AND #1/07/95#); Esse exemplo lista os funcionários cujo salário seja maior que a média dos salários de todos os funcionários. SELECT Sobrenome, Nome, Título, Salário FROM Funcionários T1 WHERE Salário >= (SELECT AVG(Salário) FROM Funcionários WHERE Funcionários.Título = T1.Título) ORDER BY Título; Esse exemplo seleciona o nome de todos os funcionários que tenham registrado pelo menos um pedido. Isto também poderia ser feito com INNER JOIN. SELECT Nome, Sobrenome FROM Funcionários AS E WHERE EXISTS (SELECT * FROM Pedidos AS O
WHERE O.FuncionárioID = E.FuncionárioID); Altera o campo Efetuado do arquivo de serviços para 2 caso o mesmo tenha parecer técnico da entidade encaminhanhamento diferente de nulo. UPDATE servico SET efetuado = 2 WHERE numero_servico = ANY (SELECT servico.numero_servico FROM servico INNER JOIN encaminhamento ON (servico.numero_servico = encaminhamento. numero_servico) AND (servico. ano_servico = encaminhamento.ano_servico) WHERE (((servico.efetuado) Is Null) AND ((encaminhamento.parecer_tecnico) Is Not Null)) GROUP BY servico.numero_servico ORDER BY servico.numero_servico);
17 Curso de Delphi 4.0 - Programação Orientada a Objetos Autor: Fernando Antonio F. Anselmo eMail: [email protected] Pré-Requisitos: • • • •
Windows 98 Delphi 4.0 versão Client/Server Suite BDE 5.00 MS-Access 97
Prefácio Para você poder compreender melhor o ambiente de desenvolvimento Delphi, é necessário que seja apresentado alguns conceitos da POO (Programação Orientada a Objetos). Não os confunda com POE (Programação Orientada a Eventos), muito difundido com a linguagem encontrada com o MS-Access, o Access-Basic (um ambiente baseado em Objetos). Vou tentar expor aqui as sensíveis diferenças que existem entre esses dois conceitos. A POO e a POE são facilmente confundidas, mas lembre-se, a POO contém a POE, mas a POE não contém a POO; um objeto pode existir mesmo que para ele não exista nenhum evento associado, mas é impossível existir um evento se não houver um objeto associado. Outra característica que pode causar confusão, são ambientes Orientados a Objetos e ambientes Baseados em Objetos. Em ambiente Orientado a Objetos existe a possibilidade da criação e manipulação de objetos, enquanto que o Baseado em Objetos esta possibilidade é totalmente inexistente o que existe é a simples manipulação ou no máximo uma derivação (criação de um a partir de outro já existente) dos objetos. A POO é um conceito desenvolvido para facilitar o uso de códigos de desenvolvimento em interfaces gráficas. Sendo a Inprise, uma das primeiras a entrar neste novo conceito, possui suas principais linguagens de programação (tais como Object Pascal e Object C), totalmente voltadas para este tipo de programação. A POO atraiu muitos adeptos principalmente pelo pouco uso de código que o Projeto (diferente de Sistema) carrega no programa fonte, ao contrário de linguagens mais antigas como o Clipper’87 muito utilizado no final da década de 80 e início da década de 90. O resultado desta “limpeza” resulta que uma manutenção no projeto é muito mais simples. Para entender o sistema POO, vamos tentar pensar simples, imagine que você acabou de adquirir uma caixa de bloquinhos de Lego, você pode criar várias coisas com eles, mas você possui um número limitado de peças, você pode aumentar sua coleção, aumentando também a possibilidade do número de coisas que você poderá criar, formando verdadeiras cidades de Lego. Depois do comercial, a POO é basicamente isto, adquirindo o Delphi você está adquirindo um ambiente totalmente flexível para a criação de um número de determinados sistemas, você pode aumentar sua produtividade simplesmente aumentando o número de objetos. Os conceitos que vou apresentar a seguir existem desde que foi sonhada a Orientação a Objetos, provavelmente você deve conhecer uma boa parte, se não, então é a hora de você se familiarizar com este ambiente.
Conceitos da Orientação a Objeto Antes de começarmos a falar realmente de linguagem orientada a objetos e necessário que você possua os conceitos básicos da orientação a objetos, são eles:
Objeto - é qualquer estrutura modular que faz parte de um produto. Uma janela por exemplo, é um objeto de uma casa, de um carro ou de um software com interface gráfica para o usuário. Atributos - São as características do objeto, como cor e tamanho, a janela, por exemplo, tem atributos como o modelo, tamanho, abertura simples ou dupla, entre outros. Encapsulação - é um mecanismo interno do objeto “escondido” do usuário. Uma pessoa pode abrir uma janela girando a tranca sem precisar saber o que há dentro dela. Ação - é a operação efetuada pelo objeto. Todas as janelas, por exemplo, controlam a iluminação e temperatura ambiente, dependendo do seu design. Herança - um objeto novo nem sempre é criado do zero. Ele pode “herdar” atributos e ações de outros já existentes. Um basculante herda atributos das janelas e das persianas. Polimorfismo - é a capacidade de objetos diferentes reagirem segundo a sua função a uma ordem padrão. O comando “abre”, por exemplo, faz um objeto entrar em ação, seja ele uma janela, uma porta ou uma tampa de garrafa. Ligação - é quando um objeto conecta a sua ação a outro. Um sensor de claridade, por exemplo, ativa o acendimento automático da iluminação de rua. Embutimento - Permite a um objeto incorporar funções de outros, como um liqüidificador que mói carne com a mudança do tipo da lâmina.
Linguagem Object Pascal Object Pascal é uma linguagem Orientada a Objetos não é pura, mas, híbrida, por possuir características de programação não só visual mas também escrita, para os programadores que já conhecem técnicas de estruturas de programação, tais como C, Basic, Pascal ou xBASE entre outras linguagens a Object Pascal providência uma migração de forma natural oferecendo um produto de maior complexibilidade. Object Pascal força a executar passos lógicos. Isto torna mais fácil o desenvolvimento em ambiente gráficos (tais como o Windows), de aplicações livres, ou que utilizam banco de dados do tipo Cliente/Servidor. A linguagem trabalha com o uso de ponteiros para a alocação de memória e todo o poder de um código totalmente compilável. Além disso, possibilita a criação e reutilização (vantagem de re-uso tão sonhado com a Orientação a Objetos) de objetos e bibliotecas dinâmicas (Dynamic Link Libraries - DLL). Object Pascal contém todo o conceito da Orientação a Objetos, incluindo a herança, o encapsulamento e o polimorfismo. Algumas extensões foram incluídas para facilitar o uso tais como conceitos de propriedades, particulares e públicas, e tipos de informações em modo run-time, manuseamento de exceções, e referências de classes. O resultado de toda esta junção faz com que Object Pascal consiga suportar as facilidades de um baixo nível de programação, tais como: •
Controle e acesso das subclasses do Windows (API);
•
Passar por cima das mensagens de loop do Windows;
•
Mensagens semelhantes as do Windows;
•
Código puro da linguagem Assembler.
Como deu para perceber a base de toda a programação Delphi é a linguagem Object Pascal nunca diga então que você programa em Delphi e sim que você programa em Object Pascal, assim como você nunca programou em Clipper mas em xBase, vamos aprender alguns conceitos básicos dentro deste tipo de programação.
Símbolos Especiais A Object Pascal aceita os seguintes caracteres ASCII: • Letras - do Alfabeto Inglês: A até Z e a até z. • Dígitos - Decimal: 0 até 9 e HexaDecimal: 0 até 9 e A até F (ou a até f) • Brancos - Espaço (ASCII 32) e todos os caracteres de controle ASCII (ASCII 0 até ASCII 31), incluindo final de linha e Enter (ASCII 13). • Especiais - Caracteres: + - * / = < > [ ] . , ( ) : ; ^ @ { } $ # • Símbolos - Caracteres: <= >= := .. (* *) (. .) //
☞
Importante - O colchetes esquerdo “[” e equivalente ao “(.” e o colchetes direito “]” e equivalente a “.)”.
☞
Importante - Os comentários são formados por chave esquerda “{” e equivalente ao “(*” e fechados com a chave direita “}” e equivalente a “*)”. O comentário de uma linha é o “//” (não é aceito pelo Delphi 1.0). for i := 1 to 10 do // Este é o exemplo de um comentário apenas desta linha
for i := 1 to 10 do for i := 1 to 10 do
{ Este é o exemplo de um comentário que pode ser em várias linhas } (*Este é o exemplo de um comentário que pode ser em várias linhas *)
Palavras Reservadas Object Pascal se utiliza das seguintes palavras reservadas, não podendo as mesmas serem utilizadas ou definidas: And Array As Asm Begin Case Class Const Constructor Destructor Div Do Downto Else End Except
Exports File Finnaly For Function Goto If Implementation In Inherited Initialization Inline Interface Is Label
Library Mod Nil Not Object Of On Or Packed Procedure Program Property Raise Record Repeat
Set Shl Shr String Then To Try Type Unit Until Uses Var While With Xor
Uma outra lista a seguir, apresenta as diretivas que são utilizadas em contextos de identificação de objetos: Absolute Abstract Assembler At Cdecl Default Dynamic
Export External Far Forward Index Interrupt Message
Name Near Nodefault Override Private Protected Public
Published Read Resident Stored Virtual Write
Números É possível definir variáveis ou constantes com tipos Inteiros ou Numéricos de ponto flutuante, a diferença entre os diversos tipos permitidos se deve a capacidade de armazenamento e o espaço ocupado, veja a comparação nas tabelas abaixo: Para os tipos Inteiros Tipo Integer Shortint Smallint Longint Int64 Cardinal Byte Word Longword
Range -2147483648..2147483647 -128..127 -32768..32767 -2147483648..2147483647 -2^63..2^63-1 0..4294967295 0..255 0..65535 0..4294967295
Para os tipos Ponto Flutuante
Formato 32-bit + sinal 8-bit + sinal 16-bit + sinal 32-bit + sinal 64-bit + sinal 32-bit 8-bit 16-bit 32-bit
Tipo Real48 Real Single Double Extended Comp Currency
Range 2.9 x 10^-39 .. 1.7 x 10^38 5.0 x 10^-324 .. 1.7 x 10^308 1.5 x 10^-45 .. 3.4 x 10^38 5.0 x 10^-324 .. 1.7 x 10^308 3.6 x 10^-4951 .. 1.1 x 10^4932 -2^63+1 .. 2^63 -1 -922337203685477.5808.. 922337203685477.5807
Dígitos Significantes 11-12 15-16 7-8 15-16 19-20 19-20 19-20
Tamanho em Bytes 6 8 4 8 10 8 8
var i : double; // Aqui crio uma variável i sendo Float z : integer; // Aqui crio uma variável z sendo Inteira t : real; // Aqui crio uma variável t sendo Real begin i := StrToFloat('10.23'); z := Round(i); t := i; end;
Constantes Uma constante é um identificador com valor(es) fixo(s). Um bloco de declarações constante possui a seguinte expressão: [Declaração Constante] [Identificador] (=) [constante] (;) A lista abaixo apresenta um conjunto de funções que podem ser utilizadas para a declaração das constantes: Ab Chr Hi High
Length Lo Low Odd
Ord Pred Ptr Round
Alguns exemplos para a definição de Constantes: const Min = 0; Max = 100; Centro = (Max - Min) div 2; Beta = Chr(225); NumLetras = Ord('Z') - Ord('A') + 1; MensOla = 'Instrução inválida'; MensErro = ' Erro: ' + MensOla + '. '; PosErr = 80 - Length(MensErro) div 2; Ln10 = 2.302585092994045684; Ln10R = 1 / Ln10; DigNumericos = ['0'..'9']; LetrasAlpha = ['A'..'Z', 'a'..'z']; AlphaNum = LetrasAlpha + DigNumericos;
SizeOf Succ Swap Trunc
Expressões As expressões em Object Pascal (como em qualquer linguagem) são formadas por operadores e operandos; os operadores são divididos em quatro categorias básicas: Únicos Multiplicativos Adicionais Relacionais
@, Not >, /, div, mod, and, shl, shr, as +, -, or, xor =, < >, <, >, < =, > =, in, is
As expressões obedecem as regras básicas de lógica para a precedência da execução das operações.
Identificadores Identificadores podem ser constantes, tipos, variáveis, procedures, funções, unidades, programas e campos de registros. Não existe limite de caracteres para o nome de um identificador mas apenas os 63 primeiros caracteres são significantes (não podendo ser idêntico ao nome das palavras reservadas). O nome de um identificador deve ser iniciado por Letras ou o caracter underscore ( _ ). O resto é formado por Letras, Dígitos, caracter underscore (ASCII $5F). Não é permitido a utilização de espaços para a formação do nome.
☞
Importante - Exemplo de identificadores válidos: Form1, SysUtils.StrLen, Label1.Caption
with... do...; Delimita um determinado bloco de declarações para um identificador específico evitando a declaração deste identificador. A sintaxe do comando é: WITH {nome do identificador} DO {comandos};. Ex.: begin { ... comandos iniciais ... } with form1 do begin Caption := ‘Teste’; BorderStyle := bsSizable; end; end;
// Equivalente a Form1.Caption // Equivalente a Form1.BorderStyle
array [ ... ] of ...; Define um conjunto de variáveis ou constantes de um mesmo tipo. A sintaxe do comando é: array [{quantidade de ocorrências}] of {Tipo};. Os arrays são controlados por três funções: Função Low High SizeOf
Ex.:
Valor de Retorno Primeiro elemento Aponta para o último elemento Tamanho do array
const t: array [1..50] of Char { Declara 50 elementos para o tipo Char } var s : array[1..100] of Real { Declara 100 elementos para o tipo real } ind: Integer; begin for Ind := Low(s) to High(s) do s[Ind] := 0; { Zera os elementos do array S } if SizeOf(t) = ‘C’ then exit; { Se o último elemento do array T for ‘C’ sai do bloco } { ... outros comandos... } end;
Declarações Declarações descrevem ações de um algorítmo a serem executadas.
begin... end; Prende um conjunto de declarações em um bloco de comandos determinado. A sintaxe do comando é: BEGIN {comandos} END;. Ex.: begin { ... comandos iniciais ... } begin { ... bloco 1 ... } end; begin { ... bloco 2 ... } end; { ... comandos finais ... } end;
if... then... else...; Esta expressão escolhe entre o resultado de uma condição booleana o caminho verdadeiro (then) ou falso (else). A sintaxe do comando é: IF {condição} THEN {bloco de comandos} ELSE {bloco de comandos};. Ex.: begin { ... comandos iniciais ... } if x > 2 then { ... Bloco verdadeiro ... } else { ... Bloco falso ... }; end;
goto... ; Transfere a execução de um programa para o ponto determinado pelo Label. A sintaxe do comando é: GOTO {Label};. Ex.: label primeiro;
begin { ... comandos iniciais ... } if x = 2 then goto primeiro; { ... outros comandos ... } Primeiro: { ... comandos do Primeiro ... } end;
case... of... else... end; Consiste de uma lista de declarações que satisfaz a condição de um seletor de expressões, se nenhuma parte da lista satisfizer ao seletor executa os comandos do sub-comando else. Para o seletor serão válidos os tipos definidos, tipo Inteiros ou LongInt. A sintaxe do comando é: CASE {seletor} OF {Expressão 1}: {comando da expressão 1}; {Expressão 2}: {comando da expressão 2}; {Expressão n}: {comando da expressão n} ELSE {comando}; end;. Ex.: begin { ... comandos iniciais ... } case x of 1: { ... Bloco para x = 1 ... } 2, 3: { ... Bloco para x = 2 ou X = 3... } 4..6: { ... Bloco para 4 <= x <= 6 ... } else { ... Bloco para x < 1 ou x > 6 ... }; end; end;
repeat... until; Repete um determinado bloco de declarações até a condição booleana do subcomando until ser satisfeita. A sintaxe do comando é: REPEAT {comandos}; until {condição};. Ex.: begin { ... comandos iniciais ... } x := 0; repeat x := x + 1 until (x = 2); end;
for... to (downto)... do...; Incrementa em 1 uma determinada variável inteira, repetindo um bloco de comandos, até que esta atinja o valor final do intervalo, o subcomando downto realiza o incremento reverso. A sintaxe do comando é: FOR {variável} := {valor inicial} to (downto) {valor final} do {bloco de comandos};. Ex.: begin { ... comandos iniciais ... } for i := 1 to 10 do { ... Comandos A ... } for s := 10 downto 1 do
// Executa o [comandos A] para i = 1,2,3,4,5,6,7,8,9 e 10 // Executa o [comandos B] para i = 10,9,8,7,6,5,4,3,2 e 1
{ ... Comandos B... } end;
while... do...; Repete um bloco de comandos enquanto que determinada condição booleana seja satisfeita. A sintaxe do comando é: WHILE {condição} DO {bloco de comandos};. Ex.: begin { ... comandos iniciais ... } while i := 1 do { ... Bloco de comandos ... } end;
// Repete o [Bloco de comandos] enquanto i = 1
break; ou continue...; O comando break interrompe um bloco de repetição for, while ou repeat saindo do bloco. A sintaxe do comando é: BREAK; enquanto que o comando continue retorna a primeira instrução do bloco de repetição for, while ou repeat. A sintaxe do comando é: CONTINUE;. Ex.: begin { ... comandos iniciais ... } for i := 1 to 10 do begin if i = 8 then break; {... comandos A...} if i = 5 then continue; {... comandos B ...} end; {... comandos C ...} end;
// Salta para os [comandos C]
// Retorna para o comando for pulando os [comandos B]
Blocos de Procedimentos ou Funções As procedures ou funções são declaradas na seção de tipos de declarações (abaixo do comando type) pertencendo ao objeto ou serem do tipo public (públicas - executadas por outras unidades) ou private (particulares - restritas a unidade local).
Procedure procedure {cabeçalho}; var {declaração das variáveis}; {bloco de comandos};
O cabeçalho da procedure é composto pelo nome do procedimento e variáveis que serão recebidas (ou modificadas através da declaração var, ex.: “procedure teste(var x:string);”). procedure soma(a,b: integer); var c: integer; begin c := a + b;
// Início enviando as variáveis A e B do tipo inteiro. // Declaração de variáveis locais a procedure // Corpo do procedimento.
end;
Function function {cabeçalho} : {resultado}; var {declaração das variáveis}; {bloco de comandos};
As funções se diferem dos procedimentos pela obrigatoriedade do retorno de um resultado, podendo este resultado ser retornado pela declaração: {nome da função} := valor ou result := valor. function soma(a,b: integer) : integer; begin soma := a + b; end;
// Início enviando as variáveis A e B do tipo inteiro. // Corpo do procedimento. // ou result := a + b;
☞
Importante - Junto com o Delphi vem o manual Object Pascal Reference em formato .HLP, caso a linguagem seja novidade para você aconselho que você dê uma boa olhada (o Delphi 1.0 traz o mesmo manual, mas em formato .PDF), mas não se preocupe com o que foi explicado acima já está mais do que suficiente para um bom entendimento com o Object Pascal. Tudo o que vimos acima é o que normalmente temos em outras linguagens comuns, mas o caracteriza realmente a linguagem Orientada em Objetos é o trabalho e a manipulação com os mesmos.