Vous êtes sur la page 1sur 178

ipsgyn .

Curso Delphi 4.0 com MS-Access

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 1/178

Curriculum Vitae
I- Identificao
Nome: Fernando Antonio Fernandes Anselmo Data Nascimento: 17 de Agosto de 1966 Contato: fernandoanselmo@yahoo.com.br Site:http://orbita.starmedia.com/~anselmo32//programa/default.html

II- Resumo
Coordenao e desenvolvimento de atividades de anlise, definio de projetos, experincia na definio e criao de algoritmos lgicos, codificao, compilao e teste de programas. Treinamento e iniciao de usurios em diversos ambientes, entre estes destacam-se Delphi, Java e ASP. Seus cursos so oferecidos pela MCI Informtica e pela FINATEC. Possui larga experincia quanto ao levantamento de Informaes, acompanhamento e anlise do processamento dos programas desenvolvidos. Grande experincia em programao para ambientes Cliente/Servidor.

III- Formao
Desenvolvimento WEB e JavaScript Promotor: Politec Ambientao em SQL Server, Internet, Interdev e IIS 4.0 Promotor: EFATEC ORACLE 7.0 - Para DBA Promotor: ORACLE do Brasil SCO UNIX SYSTEM V Promotor : CT&S Modelagem e Desenvolvimento de Sistemas Aplicativos Promotor : UsP - Universidade de So Paulo Programao em Computadores Promotor : ETUC - Faculdade Catlica de Tecnologia Lngua Inglesa Promotor : Fluency Idiomas Formao bsica no Segundo Grau com Habilitao em Qumica Colgio Santa Rosa de Lima

IV- Categoria Profissional

Cargo Atual: Analista de Sistemas Snior (Lder de Projetos) Tempo de experincia: 11 anos

V- Experincia Profissional
a) Atividades Principais:

Experincia no Desenvolvimento e Manuteno de Sistemas para Internet utilizando ASP, JAVA e HTML. Domnio em SGBDR de 4a. gerao, tais como ORACLE, MS-SQL Server, INTERBASE entre outros. Ministra cursos destinados a profissionais Desenvolvedores da rea de informtica SENAC e MCI Informtica Escrevi os livros: "Delphi - O caminho das Pedras" e "Delphi & Access - O melhor de

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 2/178

dois mundos" Grande experincia com sistemas em Delphi em especial para aplicaes Intranet utilizando Delphi e objetos ActiveX.

b) Ambiente Operacional:

Domnio dos ambientes operacionais Windows e Linux. Conhecimentos do ambiente operacional Netware. Noes em Ambientes de Grande Porte ADABAS, ROSCOE, NATURAL, COMPLETE, JCL, VM/CMS e CICS.

c) Histrico das ltimas Atividades Exercidas


1999/Atual - Politec Ltda Cargo: Analista de Sistemas Snior - Contratado para auxiliar ao desenvolvimento do Sistema Justia do Superior Tribunal de Justia - STJ. - Ministrando aulas de Delphi, HTML, ASP e Java. 1994/1999 - FIA/USP Cargo: Lder de Projetos Ano 99 - Iniciei o desenvolvimento de Sistema Piloto em OutLook 98 para controlar os atendimentos ao usurio - Treinei em INTERNET sobre o modelo adotado pela Microsoft IIS 4.0, MTS e Interdev - Desenvolvi sistema em Delphi para controle de Biblioteca utilizando o banco de dados textual MicroIsis Ano 98 - Planejei e desenvolvi os sistemas em Delphi 4.0: Cadastro de Processos de Licitao, Controle de Help Desk para o atendimento ao usurio e Criao de diversos objetos para suporte as aplicaes - Iniciei o desenvolvimento do Sistema de Cadastro Dinmico para o Fechamento do Censo Escolar de 97 com o prazo de entrega previsto para 31/12/1997 Ano 97 - Treinei usurios do FNDE em Power Designer 6.0 - Ferramenta CASE e Delphi 3.0 Client / Server - Iniciei a criao de diversas "Templates" para a automao da ferramenta Power Designer na gerao de sistemas na plataforma DELPHI 3.0. Ano 96 - Fui transferido para o contrato FIA/MEC - Fui responsvel pelo desenvolvimento tcnico com a criao de vrios objetos em DELPHI para servir de apoio ao desenvolvimento dos sistemas. Ano 95 - Ministrei vrios cursos de DELPHI desde o bsico ao avanado. - Estudei mudanas para substituio da plataforma ACCESS / ORACLE e adoo a ferramenta de desenvolvimento de 4a. Gerao Borland Delphi. Ano 94 - Fui contratado pela FIA/USP - Sendo lotado para trabalhar no IBAMA - Instituto Brasileiro do Meio-Ambiente e Recursos Naturais Renovveis. Para liderar a equipe de desenvolvimento.

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 3/178

1993/1994 - Politec Ltda Cargo: Analista de Sistemas - Desenvolvimento do Sistemas na plataforma Visual Basic e Natural for Windows. - Fui contratado pela POLITEC, para a manuteno e desenvolvimento do projeto JUSTIA, lotado no Superior Tribunal de Justia. Inicia os trabalhos de manuteno e reajustes no sistema de controle e distribuio de processos jurdicos - desenvolvimento em ambiente NATURAL II / ADABAS. 1992/1993 - RCM Informtica Cargo: Analista de Sistemas - A RCM, nesta poca, era a representante na Amrica do Sul pela comercializao do SGBD4 ZIM. Fui contratado para iniciar os trabalhos no sistema de Tele-Suporte para o Sistema de Arrecadao Comercial para o DNRC. 1990/1992 - FIA/USP Cargo: Programador a Analista de Sistemas Fui lotado para trabalhar na NOVACAP - Companhia Urbanizadora da Nova Capital do Brasil. Neste perodo desenvolvi diversos sistemas na plataforma Clipper e bancos padro xBase e na nova plataforma Unix com banco ZIM. 1990 - Racional Informtica Cargo: Programador Durante um perodo de treinamento de 1 ms, no cheguei a ser contratado em carteira, pois foi imediatamente contratado pela FIA/USP. Nesta empresa realizei os trabalhos de programao do Sistema Controle de Estoque e Mercadorias - Desenvolvido em ambiente DOS / dBASE III Plus. 1989/1990 - FTI - Fundao de Tecnologia Industrial Cargo: Programador Fui lotado para trabalhar no Ministrio do Desenvolvimento da Indstria e do Comrcio, desenvolvi em sistemas nas seguintes linguagens: Natural, COBOL, PL1, EASYTRIEVE Plus, JCL e Clipper. Outros Dados: 1988 - Primeiro emprego em Carteira na KRION Vdeo Clube na rea de programao em Computadores em Ambiente dBASE III plus e planilha para contabilidade em Ltus 123. 1987 - Conclui com nota "A" o Estgio de Programao de Computadores no PRODASEN - Processamento de Dados do Senado Federal. 1986 - Contratado como "Free-lancer" pela ETUC - para ministrar cursos de COBOL e PL1. 1985 - Primeiro trabalho remunerado como substituto de um Digitador em frias no Banco do Nordeste do Brasil em mquinas PC.

VI- Local, data e assinatura

Assumo total responsabilidade que todas as informaes prestadas so verdadeiras at a presente data. Fernando Antonio Fernandes Anselmo Braslia, sexta-feira 20 de setembro de 2002

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 4/178

Programo Orientada a Objetos


Pr-Requisitos: Windows 98 Delphi 4.0 verso Client/Server Suite BDE 5.00 MS-Access 97

Autor: Fernando Antonio Fernandes Anselmo E-Mail: fernandoanselmo@yahoo.com.br

Prefcio
Para voc poder compreender melhor o ambiente de desenvolvimento Delphi, necessrio que seja apresentado alguns conceitos da POO (Programao Orientada a Objetos). No os confunda com POE (Programao 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 sensveis diferenas que existem entre esses dois conceitos. A POO e a POE so facilmente confundidas, mas lembre-se, a POO contm a POE, mas a POE no contm a POO; um objeto pode existir mesmo que para ele no exista nenhum evento associado, mas impossvel existir um evento se no houver um objeto associado. Outra caracterstica que pode causar confuso, so ambientes Orientados a Objetos e ambientes Baseados em Objetos. Em ambiente Orientado a Objetos existe a possibilidade da criao e manipulao de objetos, enquanto que o Baseado em Objetos esta possibilidade totalmente inexistente o que existe a simples manipulao ou no mximo uma derivao (criao de um a partir de outro j existente) dos objetos. A POO um conceito desenvolvido para facilitar o uso de cdigos de desenvolvimento em interfaces grficas. Sendo a Inprise, uma das primeiras a entrar neste novo conceito, possui suas principais linguagens de programao (tais como Object Pascal e Object C), totalmente voltadas para este tipo de programao. A POO atraiu muitos adeptos principalmente pelo pouco uso de cdigo que o Projeto (diferente de Sistema) carrega no programa fonte, ao contrrio de linguagens mais antigas como o Clipper87 muito utilizado no final da dcada de 80 e incio da dcada de 90. O resultado desta limpeza resulta que uma manuteno 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 vrias coisas com eles, mas voc possui um nmero limitado de peas, voc pode aumentar sua coleo, aumentando tambm a possibilidade do nmero 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 flexvel para a criao de um nmero de determinados sistemas, voc pode aumentar sua produtividade simplesmente aumentando o nmero de objetos. Os conceitos que vou apresentar a seguir existem desde que foi sonhada a Orientao a Objetos, provavelmente voc deve conhecer uma boa parte, se no, ento a hora de voc se familiarizar com este ambiente.

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 5/178

Conceitos da Orientao a Objeto


Antes de comearmos a falar realmente de linguagem orientada a objetos e necessrio que voc possua os conceitos bsicos da orientao a objetos, so 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 grfica para o usurio. Atributos - So as caractersticas do objeto, como cor e tamanho, a janela, por exemplo, tem atributos como o modelo, tamanho, abertura simples ou dupla, entre outros. Encapsulao - um mecanismo interno do objeto escondido do usurio. Uma pessoa pode abrir uma janela girando a tranca sem precisar saber o que h dentro dela. Ao - a operao efetuada pelo objeto. Todas as janelas, por exemplo, controlam a iluminao e temperatura ambiente, dependendo do seu design. Herana - um objeto novo nem sempre criado do zero. Ele pode herdar atributos e aes de outros j existentes. Um basculante herda atributos das janelas e das persianas. Polimorfismo - a capacidade de objetos diferentes reagirem segundo a sua funo a uma ordem padro. O comando abre, por exemplo, faz um objeto entrar em ao, seja ele uma janela, uma porta ou uma tampa de garrafa. Ligao - quando um objeto conecta a sua ao a outro. Um sensor de claridade, por exemplo, ativa o acendimento automtico da iluminao de rua. Embutimento - Permite a um objeto incorporar funes de outros, como um liquidificador que mi carne com a mudana do tipo da lmina.

Linguagem Object Pascal


Object Pascal uma linguagem Orientada a Objetos no pura, mas, hbrida, por possuir caractersticas de programao no s visual mas tambm escrita, para os programadores que j conhecem tcnicas de estruturas de programao, tais como C, Basic, Pascal ou xBASE entre outras linguagens a Object Pascal providncia uma migrao de forma natural oferecendo um produto de maior complexibilidade. Object Pascal fora a executar passos lgicos. Isto torna mais fcil o desenvolvimento em ambiente grficos (tais como o Windows), de aplicaes livres, ou que utilizam banco de dados do tipo Cliente/Servidor. A linguagem trabalha com o uso de ponteiros para a alocao de memria e todo o poder de um cdigo totalmente compilvel. Alm disso, possibilita a criao e reutilizao (vantagem de re-uso to sonhado com a Orientao a Objetos) de objetos e bibliotecas dinmicas (Dynamic Link Libraries - DLL). Object Pascal contm todo o conceito da Orientao a Objetos, incluindo a herana, o encapsulamento e o polimorfismo. Algumas extenses foram includas para facilitar o uso tais como conceitos de propriedades, particulares e pblicas, e tipos de informaes em modo run-time, manuseamento de excees, e referncias de classes. O resultado de toda esta juno faz com que Object Pascal consiga suportar as facilidades de um baixo nvel de programao, tais como: Controle e acesso das sub classes do Windows (API);

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 6/178

Passar por cima das mensagens de loop do Windows; Mensagens semelhantes as do Windows; Cdigo puro da linguagem Assembler. Como deu para perceber a base de toda a programao Delphi a linguagem Object Pascal nunca diga ento 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 bsicos dentro deste tipo de programao.

Smbolos Especiais
A Object Pascal aceita os seguintes caracteres ASCII:
Letras - do Alfabeto Ingls: A at Z e a at z. Dgitos - Decimal: 0 at 9 e HexaDecimal: 0 at 9 e A at F (ou a at f) Brancos - Espao (ASCII 32) e todos os caracteres de controle ASCII (ASCII 0 at ASCII 31), incluindo final de linha e Enter (ASCII 13). Especiais - Caracteres: + - * / = < > [ ] . , ( ) : ; ^ @ { } $ # Smbolos - Caracteres: <= >= := .. (* *) (. .) //

Importante - O colchetes esquerdo [ e equivalente ao (. e o colchetes direito ] e equivalente a .). Importante - Os comentrios so formados por chave esquerda { e equivalente ao (* e fechados com a chave direita } e equivalente a *). O comentrio de uma linha o // (no aceito pelo Delphi 1.0).
for i := 1 to 10 do for i := 1 to 10 do for i := 1 to 10 do // Este o exemplo de um comentrio apenas desta linha { Este o exemplo de um comentrio que pode ser em vrias linhas } (*Este o exemplo de um comentrio que pode ser em vrias linhas *)

Palavras Reservadas
Object Pascal se utiliza das seguintes palavras reservadas, no 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 so utilizadas em contextos de identificao de objetos:
Absolute Abstract Assembler At Cdecl Export External Far Forward Index Name Near Nodefault Override Private Published Read Resident Stored Virtual

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 7/178

Default Dynamic

Interrupt Message

Protected Public

Write

Nmeros
possvel definir variveis ou constantes com tipos Inteiros ou Numricos de ponto flutuante, a diferena entre os diversos tipos permitidos se deve a capacidade de armazenamento e o espao ocupado, veja a comparao 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 Formato 32-bit + sinal 8-bit + sinal 16-bit + sinal 32-bit + sinal 64-bit + sinal 32-bit 8-bit 16-bit 32-bit

Para os tipos Ponto Flutuante


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 Dgitos 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 varivel i sendo Float z : integer; // Aqui crio uma varivel z sendo Inteira t : real; // Aqui crio uma varivel 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 declaraes constante possui a seguinte expresso: [Declarao Constante] [Identificador] (=) [constante] (;) A lista abaixo apresenta um conjunto de funes que podem ser utilizadas para a declarao das constantes:
Ab Chr Hi High Length Lo Low Odd Ord Pred Ptr Round SizeOf Succ Swap Trunc

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 8/178

Alguns exemplos para a definio de Constantes:


const Min = 0; Max = 100; Centro = (Max - Min) div 2; Beta = Chr(225); NumLetras = Ord('Z') - Ord('A') + 1; MensOla = 'Instruo invlida'; 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;

Expresses
As expresses em Object Pascal (como em qualquer linguagem) so formadas por operadores e operandos; os operadores so divididos em quatro categorias bsicas:
nicos Multiplicativos Adicionais Relacionais @, Not >, /, div, mod, and, shl, shr, as +, -, or, xor =, < >, <, >, < =, > =, in, is

As expresses obedecem as regras bsicas de lgica para a precedncia da execuo das operaes.

Identificadores
Identificadores podem ser constantes, tipos, variveis, procedures, funes, unidades, programas e campos de registros. No existe limite de caracteres para o nome de um identificador mas apenas os 63 primeiros caracteres so significantes (no podendo ser idntico ao nome das palavras reservadas). O nome de um identificador deve ser iniciado por Letras ou o caracter underscore ( _ ). O resto formado por Letras, Dgitos, caracter underscore (ASCII $5F). No permitido a utilizao de espaos para a formao do nome.

Importante - Exemplo de identificadores vlidos: Form1, SysUtils.StrLen, Label1.Caption


with... do...;
Delimita um determinado bloco de declaraes para um identificador especfico evitando a declarao 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 variveis ou constantes de um mesmo tipo. A sintaxe do comando : array [{quantidade de ocorrncias}] of {Tipo};. Os arrays so controlados por trs funes:

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 9/178

Funo Low High SizeOf

Valor de Retorno Primeiro elemento Aponta para o ltimo elemento Tamanho do array

Ex.:
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;

Declaraes
Declaraes descrevem aes de um algortmo a serem executadas.

begin... end;
Prende um conjunto de declaraes 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 expresso escolhe entre o resultado de uma condio booleana o caminho verdadeiro (then) ou falso (else). A sintaxe do comando : IF {condio} 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 execuo de um programa para o ponto determinado pelo Label. A sintaxe do comando : GOTO {Label};. Ex.:
label primeiro;

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 10/178

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 declaraes que satisfaz a condio de um seletor de expresses, se nenhuma parte da lista satisfizer ao seletor executa os comandos do sub-comando else. Para o seletor sero vlidos os tipos definidos, tipo Inteiros ou LongInt. A sintaxe do comando : CASE {seletor} OF {Expresso 1}: {comando da expresso 1}; {Expresso 2}: {comando da expresso 2}; {Expresso n}: {comando da expresso 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 declaraes at a condio booleana do subcomando until ser satisfeita. A sintaxe do comando : REPEAT {comandos}; until {condio};. Ex.:
begin { ... comandos iniciais ... } x := 0; repeat x := x + 1 until (x = 2); end;

for... to (downto)... do...;


Incrementa em 1 uma determinada varivel 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 {varivel} := {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 { ... Comandos B... } end;

// 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

while... do...;
Repete um bloco de comandos enquanto que determinada condio booleana seja satisfeita. A sintaxe do

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 11/178

comando : WHILE {condio} 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 repetio for, while ou repeat saindo do bloco. A sintaxe do comando : BREAK; enquanto que o comando continue retorna a primeira instruo do bloco de repetio 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 Funes


As procedures ou funes so declaradas na seo de tipos de declaraes (abaixo do comando type) pertencendo ao objeto ou serem do tipo public (pblicas - executadas por outras unidades) ou private (particulares - restritas a unidade local).

Procedure
procedure {cabealho}; var {declarao das variveis}; {bloco de comandos};

O cabealho da procedure composto pelo nome do procedimento e variveis que sero recebidas (ou modificadas atravs da declarao var, ex.: procedure teste(var x:string);).
procedure soma(a,b: integer); var c: integer; begin c := a + b; end; // Incio enviando as variveis A e B do tipo inteiro. // Declarao de variveis locais a procedure // Corpo do procedimento.

Function
function {cabealho} : {resultado}; var {declarao das variveis}; {bloco de comandos};

As funes se diferem dos procedimentos pela obrigatoriedade do retorno de um resultado, podendo este resultado ser retornado pela declarao: {nome da funo} := valor ou result := valor.
function soma(a,b: integer) : integer; begin soma := a + b; end; // Incio enviando as variveis 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
PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 12/178

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 no 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 manipulao com os mesmos.

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 13/178

Manual dos Objetos


Autor: Fernando Antonio Fernandes Anselmo E-Mail: fernandoanselmo@yahoo.com.br
Pr-Requisitos: Windows 98 Delphi 4.0 verso Client/Server Suite BDE 5.00 MS-Access 97 Arquivos trabalhados juntos com esta apostila: AlignEdit.ZIP Card.ZIP ChessBrd.ZIP Date97.ZIP DbCmpList.ZIP DgFiltro.ZIP DgPrint.ZIP EditN.ZIP Moon.ZIP myLabel3D.ZIP PGridStr.ZIP PosEstado.ZIP PrtGrid.ZIP SelectDlgT.ZIP Semelha.ZIP sGridSQL.ZIP Tips.ZIP

Prefcio
Desde o comeo do meu tempo de Delphiano, tenho feito duas coisas, criar objetos e colecionar objetos (FREEWARE) de terceiros, melhorando-os e adaptando-os as minhas necessidades, uma boa coleo de objetos importante em qualquer construo de um projeto em uma linguagem Orientada a Objetos, aqui estou disponibilizando mais do que objetos, estou tambm disponibilizando este manual que ensina como utiliz-los corretamente e us-los para o desenvolvimento eficaz de qualquer projeto ou aplicativo.

Para Instal-los no Delphi 4.0


Aconselho que voc crie um outro diretrio (alm do LIB tradicional do Delphi) para conter seus "outros" objetos, no fique alterando o diretrio padro do Delphi, por uma simples razo, quando voc quiser criar um backup com seus objetos basta voc copiar este novo diretrio ento crie por exemplo c:\arquivos de programas\borland\delphi4\lib1 para guardar seus objetos e descompacte nele todos os arquivos mencionados no incio da apostila. Todos os objetos que so instalados no Delphi 4.0 Client/Server precisam estar embutidos em um Package, isto facilita na hora de transportar os objetos de um Delphi instalado em uma mquina qualquer para outro em outra mquina, fora o controle dos mesmos, aqui colocarei por ordem na Componnent Pallete que os objetos sero instalados, antes de instalar qualquer objeto d uma olhada se ele depende da instalao de outro primeiro, para iniciar vamos instalar o primeiro objeto, v em Component | Install Component... e na pgina Into new Package e ser mostrada a seguinte janela:

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 14/178

Unit file name - Corresponde ao nome do fonte que contm o objeto (localize o arquivo Posestad.PAS) Search path - Caminhos disponveis dos diversos objetos Package file name - Nome do Pacote que ser instalado seu objeto (localize o diretrio Lib1 e coloque o nome Colecao.DPK) Package description - Uma descrio do pacote (Coleo com meus objetos por exemplo) Aps preenchido os dados necessrios e pressionado o boto de OK uma janela se abrir questionando se voc deseja compilar e instalar o novo objeto, responda negativamente para siguirmos em frente instalando os outros objetos, voc acabar com esta janela:

Agora para incorporarmos um novo Objeto ao Package basta apenas clicarmos no boto Add e adicionarmos os fontes mencionados. Ao final de todo o processo de instalao compilaremos todos os objetos instalados atravs do boto Compile. Vamos comear ento:

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 15/178

Objetos Instalados na Component Pallete em Additional


PosEstado Objetivo: Objeto derivado do TPanel que verifica e mostra o estado e o nmero de registros de um objeto do tipo BDE ligado a um DataSource Propriedades: DataSource: Nome do DataSource que est ligado o BDE Funes ou procedimentos necessrios para execuo: Procedimento Atualiza - faz a verificao do estado e do numero de registros do objeto ligado ao DataSource. Fonte que deve ser instalado no pacote Posestad.pas Objeto ao qual depende que seja instalado primeiramente Nenhum

PGridStr Objetivo: Enviar para a impressora o contedo de um objeto StringGrid. Propriedades: LeftMargin: margem a esquerda TopMargin: margem entre o incio da pgina e o comeo da impresso RightMargin: margem a direita BottomMargin: margem a ser deixada no final da pgina ColHeaderFont: Fonte do cabealho ColScale: Escala de impresso (Ex: 100 % a 0 %) TitleFont: Fonte do Ttulo LinesFont: Fonte das linhas detalhe StringGrid: Objeto StringGrid a imprimir PrintMgrTitle: Ttulo Title: Cabealho TitleAlignment: Alinhamento do Cabealho Orientation: Tipo de orientao do papel PrintToFile: Se ao invs de imprimir gera um arquivo FullPage: Pgina toda PrintFileName: Nome do arquivo a gerar PrintFileDir: Diretrio do arquivo a gerar FromPage: Inicia na pgina EndPage: At a pgina Border: Deve imprimir linhas em volta ColLines: Deve imprimir linhas entre as colunas RowLines: Deve imprimir linhas entre as linhas detalhe HorizontalGap: Distncia horizontal entre as linhas detalhes VerticalGapPct: Distncia vertical entre as linhas detalhes PageNumberPos: Posio do nmero da pgina PageNumberLabel: Label para o nmero da pgina (Ex: Pg:) DatePos: Posio da data atual DateLabel: Label para a data atual (Ex: Data:) Funes ou procedimentos necessrios para execuo: Procedimento Print - Inicia o processo de impresso

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 16/178

Procedimento PrintDialog - Mostra uma janela de configurao da impresso Procedimento SaveToFile - Gera direto para um arquivo determinado Fonte que deve ser instalado no pacote PGridStr.pas Objeto ao qual depende que seja instalado primeiramente Nenhum

AlignEdit -

(Original de Jos Mara Ferri - jmferri@hotmail.com)

Objetivo: Objeto derivado do TEdit que o melhora proporciando um alinhamento do texto a Direita, a Esquerda ou Centralizado e modificao das cores do objeto caso esteje ou no em foco Propriedades: Alignment: Tipo do Alinhamento ColorOnFocus: Cor do objeto quando tiver o foco ColorOnNoFocus: Cor do objeto quando no tiver o foco TextOnFocus: Cor do texto quando o objeto tiver o foco TextOnNoFocus: Cor do texto quando o objeto no tiver o foco ExitOnReturn: Se deve sair do objeto com o pressionamento da tecla Enter Funes ou procedimentos necessrios para execuo: Nenhuma Fonte que deve ser instalados no pacote AlignEdit.pas Objeto ao qual depende que seja instalado primeiramente Nenhum

myLabel3D Objetivo: Descendente do objeto TLabel que o adiciona a capacidade de ficar em 3D, ganhando sombras ou em degrad Propriedades: AStyle3D : Estilo do objeto AShadeRightBottom: TColor read FShadowColor write SetShadowColor default clGray; AShadeLeftTop : Cor do degrad em viso 3D AHShadeOffSet : Distncia horizontal da sombra AVShadeOffSet : Distncia vertical da sombra AShadeLTSet : se o degrad deve ficar Branco ou assumir a cor da propriedade AShadeLeftTop Funes ou procedimentos necessrios para execuo: Nenhuma Fonte que deve ser instalados no pacote MyLabel.pas Objeto ao qual depende que seja instalado primeiramente Nenhum

EditN -

(Original de Jos.M Gas - sigecom@bbvnet.es)

Objetivo: Descendente do objeto TLabel que o adiciona a capacidade de ficar em 3D, ganhando sombras ou em degrad

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 17/178

Propriedades: ColorOnFocus: Cor de fundo quando o Edit tem o Foco ColorOnNotFocus: Cor de fundo quando o Edit no tem o Foco EditType: etString, etInteger, etFloat. Considerando os dados que conter o Edit EditAlign: etAlignRight, etAlignLeft, etAlignCenter, etAlignNone. EditLengthAlign: Tamanho que deve alinhar dentro do objeto ValueInteger: Valor Inteiro do Edit, quando EditType = etInteger ValueFloat: Valor Float do Edit, quando EditType = etFloat EditPrecision: Permite definir a quantidade de casas decimais. Si o valor maior de 0, formatar o valor, completando com zeros. KeyByTab: Tecla que a ser trocada pela tecla TAB (#9) o Enter #13 FirstCharUpper: Converte em maiusculas o primeiro caracter de uma cadeia se EditType = etString WidthOnFocus: Permite definir uma altura do Edit diferente quando tem o Foco. Funes ou procedimentos necessrios para execuo: Procedimento SetInteger - Pode ser colocado um valor para o objeto diretamente quando a propriedade EditType for etInteger. Por Exemplo: EditN10.SetInteger(63565); Procedimento SetFloat - Pode ser colocado um valor para o objeto diretamente quando a propriedade EditType for etFloat. Por Exemplo: EditN9.SetFloat(-63,56); Fonte que deve ser instalados no pacote EditNew.pas Objeto ao qual depende que seja instalado primeiramente Nenhum

Objetos Instalados na Component Pallete em Dialogs


Semelha Objetivo: Objeto derivado do TComponent que pesquisa registro atravs de um determinado valor inicial de um campo dentro de um objeto do tipo tTable, mostrando em uma janela se caso o valor no exista na tabela se existe valores semelhantes aquele informado, ao final retorna uma varivel do tipo boolean informando se encontrou ou no o registro procurado. Propriedades: aVersao: Contm o nmero da verso do objeto Tabela: em qual objeto ser pesquisada CmpDig: Filtro: Caso a tabela esteja com o filtro ativo PosCampo: Posio (propriedade Index do TField) do campo a pesquisar dentro na tabela TipoSQL: Se ser pesquisado em uma base Access ou Paradox (padro Ansi-SQL) Funes ou procedimentos necessrios para execuo: Funo Execute - inicia a procura e devolve True caso seja encontrado o registro ou False. Fontes que devem ser instalados no pacote Semelha.pas Fsemelh.pas Objeto ao qual depende que seja instalado primeiramente Nenhum

SelectDlgT Objetivo: Objeto derivado do TComponent que verifica atravs de um complexo conjunto de pesquisa determinado registro dentro de um objeto do tipo tTable, ao final retorna uma varivel do tipo boolean informando se encontrou ou no o registro procurado.

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 18/178

Propriedades: aVersao: Contm o nmero da verso do objeto Tabela: em qual objeto ser pesquisada NomeTela: o valor do Caption da janela de pesquisa, se nada for informado por default ser: Procure pelo registro desejado... Filtro: Caso a tabela esteja com algum filtro TipoSQL: Tipo do SQL a utilizar se ser utilizado em uma base Access ou Paradox (padro Ansi-SQL) Funes ou procedimentos necessrios para execuo: Funo Execute - inicia a janela e devolve True caso seja encontrado o registro ou False. Fontes que devem ser instalados no pacote SelecaoT.pas fSelectT.pas Objetos ao qual depende que sejam instalados primeiramente PosEstad Semelha

Tips Objetivo: Mostrar uma janela do tipo Dicas do Windows Propriedades mais importantes: AppName: nome da aplicao SaveShowAtStart: Se deve salvar para mostrar ou no SaveKey : String read FSaveKey write FSaveKey; Language: Linguagem do objeto (Portugus, Ingls ou Alemo) TipBackground: Cor de Fundo Header: Cabealho Title: Ttulo TipHelp: Ttulo da Dica ShowAtStart: Se deve mostrar ou no na prxima vez Tips: Dicas a serem mostradas, uma dica por linha, ser escolhida por processo randmico TipsCount: Total de dicas Funes ou procedimentos necessrios para execuo: Procedimento Execute: Mostra a dica Fonte que deve ser instalados no pacote Tips.pas FormTips.pas Objeto ao qual depende que seja instalado primeiramente Nenhum

dgPrint Objetivo: Auxilia o trato com o objeto PrtGrid mostrando uma janela prvia para a escolha das opes Propriedades: aVersao: Contm o nmero da verso do objeto Tabela: em qual objeto ser pesquisada NomeTela: o valor do Caption da janela de pesquisa, se nada for informado por default ser: Procure pelo

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 19/178

registro desejado... NomeRel: Ttulo do relatrio Filtro: Caso a tabela esteja com algum filtro Funes ou procedimentos necessrios para execuo: Procedimento Print - Inicia o processo de impresso Procedimento PrintDialog - Mostra uma janela de configurao da impresso Procedimento SaveToFile - Gera direto para um arquivo determinado Fontes que devem ser instalado no pacote fPrtGrid.pas dgPrint.pas Objeto ao qual depende que seja instalado primeiramente PosEstad PrintGrid

dgFiltro Objetivo: Permite que o usurio defina e configure a opo Filter do objeto tTable, pode ainda ser utilizado para criar clusulas Where de comandos SQL. Propriedades: aVersao: Contm o nmero da verso do objeto Tabela: em qual objeto ser pesquisada NomeTela: o valor do Caption da janela de pesquisa, se nada for informado por default ser: Define um filtro para os Dados FiltroVe: Filtro na linguagem que o usurio entenda FiltroSQL: Filtro pronto para ser colocado na propriedade Filter TipoSQL: Tipo do SQL a utilizar se ser utilizado em uma base Access ou Paradox (padro Ansi-SQL) Funes ou procedimentos necessrios para execuo: Procedimento Execute - Inicia a janela e devolve True caso seja concludo o filtro ou False. Fontes que devem ser instalado no pacote fFiltro.pas dgFiltro.pas Objeto ao qual depende que seja instalado primeiramente Nenhum

Objetos Instalados na Component Pallete em Data Controls


GridSQL Objetivo: Ajuntar um objeto DBGrid a um objeto tQuery para mostrar o resultado de um SQL Propriedades: aVersao: Contm o nmero da verso do objeto CodSQL: SQL para o tQuery DatabaseName: Nome do DataBaseName LabPesq: Caption do Label que aparece acima do DBGrid servindo de rtulo LigaDes: Ativa e desativa a tQuery OpcaoGrid: Opes do DBGrid OpcaoGridCol: Opes das colunas do DBGrid

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 20/178

Funes ou procedimentos necessrios para execuo: Nenhum Fonte que deve ser instalado no pacote sGridSQL.pas Objeto ao qual depende que seja instalado primeiramente Nenhum

PrtGrid -

(Original de Paul Rice)

Objetivo: Enviar para a impressora o contedo de um objeto DbGrid. Propriedades: LeftMargin: margem a esquerda LeftMargin: margem a esquerda TopMargin: margem entre o incio da pgina e o comeo da impresso RightMargin: margem a direita BottomMargin: margem a ser deixada no final da pgina ColHeaderFont: Fonte do cabealho ColScale: Escala de impresso (Ex: 100 % a 0 %) TitleFont: Fonte do Ttulo LinesFont: Fonte das linhas detalhe DBGrid: Objeto StringGrid a imprimir PrintMgrTitle: Ttulo Title: Cabealho TitleAlignment: Alinhamento do Cabealho Orientation: Tipo de orientao do papel PrintToFile: Se ao invs de imprimir gera um arquivo FullPage: Pgina toda PrintFileName: Nome do arquivo a gerar PrintFileDir: Diretrio do arquivo a gerar FromPage: Inicia na pgina EndPage: At a pgina Border: Deve imprimir linhas em volta ColLines: Deve imprimir linhas entre as colunas RowLines: Deve imprimir linhas entre as linhas detalhe HorizontalGap: Distncia horizontal entre as linhas detalhes VerticalGapPct: Distncia vertical entre as linhas detalhes PageNumberPos: Posio do nmero da pgina PageNumberLabel: Label para o nmero da pgina (Ex: Pg:) DatePos: Posio da data atual DateLabel: Label para a data atual (Ex: Data:) Funes ou procedimentos necessrios para execuo: Procedimento Print - Inicia o processo de impresso Procedimento PrintDialog - Mostra uma janela de configurao da impresso Procedimento SaveToFile - Gera direto para um arquivo determinado Fonte que deve ser instalado no pacote PrtGrid.pas Objeto ao qual depende que seja instalado primeiramente Nenhum

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 21/178

DBCmpList Objetivo: Substituir o DBLookupCombo quando em pesquisa em tabelas secundrias, por exemplo, em funcionrio se cadastra o rgo ao qual o funcionrio trabalha, este rgo ser cadastrado utilizando este objeto, veja nas propriedades o exemplo detalhado, conforme a seguinte estrutura: tbFuncionario (Tab. Primria) COD_FUNCIONARIO COD_CARGO { Outros Campos } tbCargo (Tab. Secundria) COD_CARGO SIG_CARGO DES_CARGO

Propriedades: aVersao: Contm o nmero da verso do objeto CapLocaliza: Caption a ser usado no boto de localiza DataField: Nome do campo a inserir (No exemplo: CD_CARGO) DataSource: Nome do DataSource dono do DataField (No exemplo: dsFuncionrio) TbSecundaria: Nome da Tabela Secundria a pesquisar (No exemplo: tbCargo) CriticaEd: Se deve ou no criticar o modo de Edio para a utilizao do boto Localiza GlyphLoc: Glyph para o boto de localiza (No exemplo: Localize o BMP que mais lhe agradar) MensagemCodigo: Uma mensagem caso no encontre o campo cdigo (No exemplo: Cdigo do Cargo no cadastrado) MensagemSigla: Uma mensagem caso no encontre o campo sigla (No exemplo: Sigla do Cargo no cadastrada) MensagemDescricao: Uma mensagem caso no encontre o campo descrio (No exemplo: Cargo no cadastrado) NumGlyphsLoc: Nmero de Glyphs da imagem do boto de localiza PosCmpCodigoSec: Posio em FIELD.INDEX do campo Cdigo (No exemplo: 0) PosCmpDescricao: Posio em FIELD.INDEX do campo Descrio (No exemplo: 2) PosCmpSigla: Posio em FIELD.INDEX do campo Sigla (No exemplo: 1) TamEdtCodigo: Tamanho do Edit do campo Cdigo TamEdtDescricao: Tamanho do Edit do campo Descrio TamEdtSigla: Tamanho do Edit do campo Sigla PosEdtCodigo: Posio a esquerda do campo Cdigo PosEdtDescricao: Posio a esquerda do campo Descrio PosEdtSigla: Posio a esquerda do campo Sigla TopEdtCodigo: Posio do topo do campo Cdigo TopEdtDescricao: Posio do topo do campo Descrio TopEdtSigla: Posio do topo do campo Sigla HintButLoc: Hint para o boto de Localiza (No exemplo: Localiza determinado Cargo) UsaLocaliza: Se vai ou no usar o boto de Localiza UsaDescricao: Se vai ou no usar o campo Descrio UsaSigla: Se vai ou no usar o campo Sigla Filtro: Caso a tabela esteja com algum filtro TipoSQL: Tipo do SQL a utilizar se ser utilizado em uma base Access ou Paradox (padro Ansi-SQL) Evento OnMudaFiltro: Se ocorrer alguma mudana no Filtro Funes ou procedimentos necessrios para execuo: ATENO - Em programa as tabelas Secundrias devem ser abertas primeiras que a tabela Principal e para fechar proceda de forma contrria. Ou Seja: tbCargo.Open; tbFuncionario.Open; { ... } tbFuncionario.Close; tbCargo.Close; Fonte que deve ser instalado no pacote CmpTerc.pas

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 22/178

Objeto ao qual depende que seja instalado primeiramente SelecaoT Semelha

Objetos Instalados na Component Pallete em Jogos


Card (Original de T. J. Sobotka - elvis@sway.com)

Objetivo: Objeto para produo de jogos de cartas Propriedades: Card: Utilizado para selecionar uma determinada carta SelectedCard: Determina se a carta vai ter aparncia de selecionada ou no ShowCard: Determina o lado da carta Suit: Determina qual o Nipe da carta Funes ou procedimentos necessrios para execuo: Nenhuma Fonte que deve ser instalado no pacote Cards.pas Objeto ao qual depende que seja instalado primeiramente Nenhum

Moon -

(Original de Andreas Hrstemeier)

Objetivo: Objeto derivado do TImage que atravs de um algortmo astronmico calcula vrios dados sobre a lua e o sol, ideal para sistemas exotricos e agendas Propriedades: Date: Data e Hora para o clculo MoonSize: Tamanho do Display Funes ou procedimentos necessrios para execuo: Funo Julian_date: recebe uma Data e Hora e devolve a Data Juliana Funo Sun_distance: recebe uma Data e Hora e devolve a distncia da Terra ao Sol Funo Moon_distance: recebe uma Data e Hora e devolve a distncia da Terra Lua Funo Age_of_moon: recebe uma Data e Hora e devolve a idade da Lua Funo function last_phase: recebe uma Data, Hora e a Fase da Lua de devolve a data da ltima fase Funo next_phase: recebe uma Data, Hora e a Fase da Lua de devolve a data da prxima fase Funo current_phase: recebe uma Data, Hora e devolve a Fase da Lua Funo lunation: recebe uma Data e Hora e devolve a lunao da lua Funo sun_diameter: recebe uma Data e Hora e devolve o dimetro do Sol Funo moon_diameter: recebe uma Data e Hora e devolve o dimetro da Lua Funo QLua: recebe uma Data e Hora e devolve a fase da lua em String Fonte que deve ser instalado no pacote Moon.pas Objeto ao qual depende que seja instalado primeiramente Nenhum

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 23/178

ChessBrd -

(Original de Daniel Terhell)

Objetivo: Jogar uma partida de Xadrez em um dos objetos mais incrveis que j vi, ideal para ser colocado no sobre do sistema como opo para o usurio. Propriedades mais importantes: AnimateMoves: Movimentos devem ser animados AnimateDelay: Se deve haver um tempo para a animao BoardLines: Linhas entre as casas e as bordas BoardBitmap: Imagem para da Borda BoardColor: Cor da Borda ComputerPlaysBack: Computador joga com as pretas ComputerPlaysWhite: Computador joga com as brancas Position: Posio de todas as peas no tabuleiro Funes ou procedimentos necessrios para execuo: Procedimento NewGame: Inicializa um novo jogo Procedimento UpdateChessBoard: Recebe a posio do tabuleiro Variveis FirstMove - Primeiro Movimento e LastMove - ltimo movimento ambas do tipo inteiras Fonte que deve ser instalado no pacote ChessBrd.pas Objeto ao qual depende que seja instalado primeiramente Nenhum

Objetos Instalados na Component Pallete em Freeware


Coleo Date97- Todos estes objetos so originais de BOURMAD Mehdi - bourmad@mygale.org e contm os seguintes objetos:
Calendar97 , DbCalendar97 , DateEdit97 , DbDateEdit97 , DateFromTo97 Objetivo: Funo principal de todos controlar variveis e campos do tipo TDateTime, facilitando o manuseamento das mesmas Fonte que deve ser instalado no pacote dtCabDb97.pas dtCal97.pas dtEdDB97.pas dtEdFt97.pas dtEdit97.pas dtFunc97.pas dtMisc97.pas dtPop97.pas dtProp97.pas dtReg97.pas UBitMap.pas Objeto ao qual depende que seja instalado primeiramente Nenhum

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 24/178

Principais Instrues em SQL


Autor: Fernando Antonio Fernandes Anselmo E-Mail: fernandoanselmo@yahoo.com.br
Pr-Requisitos: Windows 98 Delphi 4.0 verso Client/Server Suite BDE 5.00 MS-Access 97

Prefcio
Esta apostila foi desenvolvida com o auxlio on-Line do banco MS-ACCESS, este tipo de SQL para este banco no totalmente compatvel com o SQL Padro ANSI, que o oficial na maioria dos bancos de dados, ento algumas clusulas podem no funcionar em outros gerenciadores de bancos de dados.

Instruo SELECT
Instrui o programa principal do banco de dados para retornar a informao como um conjunto de registros.

Sintaxe
SELECT [predicado { * | tabela.* | [tabela.]campo1 [AS alias1] [, [tabela.]campo2 [AS alias2] [, ...]]} FROM expressotabela [, ...] [IN bancodedadosexterno] [WHERE... ] [GROUP BY... ] [HAVING... ] [ORDER BY... ] [WITH OWNERACCESS OPTION] A instruo SELECT tem as partes abaixo: Parte predicado * tabela campo1, campo2 incluir alias1, alias2 expressotabela bancodedadosexterno Descrio Um dos seguintes predicados: ALL, DISTINCT, DISTINCTROW ou TOP. Voc usa o predicado para restringir o nmero de registros que retornam. Se nenhum for especificado, o padro ser ALL. Especifica que todos os campos da tabela ou tabelas especificadas so selecionados. O nome da tabela que contm os campos dos quais os registros so selecionados. Os nomes dos campos dos quais os dados sero recuperados. Se voc mais de um campo, eles sero recuperados na ordem listada. Os nomes que sero usados como ttulos de colunas em vez dos nomes originais das colunas na tabela. O nome da tabela ou tabelas contendo os dados que voc quer recuperar. O Nome do banco de dados que contm as tabelas em expressotabela se no

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 25/178

estiver no banco de dados atual.

Comentrios
Para executar esta operao, o programa principal de banco de dados procura a tabela ou tabelas especificadas, extrai as colunas escolhidas, seleciona as linhas que satisfazem o critrio e classifica ou agrupa as linhas resultantes na ordem especificada. A instruo SELECT no muda os dados no banco de dados. SELECT normalmente a primeira palavra em uma instruo SQL. A maior parte das instrues SQL so instrues SELECT. A sintaxe mnima da instruo 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 Funcionrios: SELECT * FROM Funcionrios; Se o nome de um campo estiver includo em mais de uma tabela na clusula FROM, preceda-o com o nome da tabela e o operador . (ponto). No exemplo abaixo, o campo Departamento est nas tabelas Funcionrios e Supervisores. A instruo SQL seleciona Departamento da tabela Funcionrios e NomeSupv da tabela Supervisores: SELECT Funcionrios.Departamento, Supervisores.NomeSupv FROM Funcionrios INNER JOIN Supervisores WHERE Funcionrios.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 no esteja implcito na expresso usada para gerar o campo, use a palavra reservada AS. O exemplo abaixo usa o ttulo Nasc para nomear o objeto Field retornado no objeto Recordset resultante: SELECT DataNasc AS Nasc FROM Funcionrios; Sempre que voc usar funes aggregate ou consultas que retornem nomes de objetos Field ambguos ou duplicados, voc precisar usar a clusula AS para fornecer um nome alternativo para o objeto Field. O exemplo abaixo usa o ttulo Contagem para nomear o objeto Field retornado no objeto Recordset resultante: SELECT COUNT(FuncionrioID) AS Contagem FROM Funcionrios; Voc pode usar outras clusulas na instruo SELECT para restringir e organizar posteriormente os seus dados retornados.

Clusula GROUP BY
GROUP BY opcional. Valores de resumo so omitidos se no houver qualquer funo aggregate SQL na instruo SELECT. Os valores Null nos campos GROUP BY so agrupados e no omitidos. No entanto, os valores Null no so avaliados em qualquer funo aggregate SQL. Use a clusula WHERE para excluir linhas que voc no quer agrupadas e use a clusula HAVING para filtrar os registros aps eles terem sido agrupados. A no ser que contenha dados Memo ou OLE Object, um campo na lista de campos GROUP BY pode fazer referncia a qualquer campo em qualquer tabela listada na clusula FROM. Mesmo que o campo no esteja includo na instruo SELECT, fornecida a instruo SELECT, inclua pelo menos uma funo SQL. O programa principal de banco de dados do Jet no pode agrupar campos Memo ou OLE Objects. Todos os campos na lista de campos SELECT devem ser includos na clusula GROUP BY ou includos como argumentos em uma funo aggregate SQL.

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 26/178

Clusula HAVING
HAVING opcional. HAVING semelhante a WHERE, que determina quais registros so selecionados. Depois que os registros so agrupados com GROUP BY, HAVING determina quais registros so exibidos: SELECT CategoriaID, Sum(UnidadesNoEstoque) FROM Produtos GROUP BY CategoriaID HAVING Sum(UnidadesNoEstoque) > 100 AND LIKE "BOS*"; Uma clusula HAVING pode conter at 40 expresses vinculadas por operadores lgicos, como And ou Or.

Clusula ORDER BY
ORDER BY opcional. Entretanto, se voc quiser exibir seus dados na ordem classificada, voc deve utilizar ORDER BY. O padro ordem de classificao ascendente (A a Z, 0 a 9). Os dois exemplos abaixo classificam os nomes dos funcionrios pelo sobrenome. SELECT Sobrenome, Nome FROM Funcionrios ORDER BY Sobrenome; SELECT Sobrenome, Nome FROM Funcionrios 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 salrios e os classifica em ordem descendente SELECT Sobrenome, Salrio FROM Funcionrios ORDER BY Salrio DESC, Sobrenome; Se voc especificar um campo que contm dados Memo ou OLE Objects na clusula ORDER BY, um erro ocorrer. O programa principal de banco de dados do Jet no classifica campos deste tipo. ORDER BY normalmente o ltimo item em uma instruo SQL. Voc pode incluir campos adicionais na clusula ORDER BY. Os registros so classificados primeiro pelo primeiro campo listado depois de ORDER BY. Os registros que tiverem valores iguais naquele campo so classificados pelo valor no segundo campo listado e assim por diante.

Clusula WITH OWNERACCESS OPTION


A declarao WITH OWNERACCESS OPTION opcional. O exemplo abaixo habilita o usurio a ver as informaes de salrio (mesmo que no tenha outra permisso para ver a tabela Folha de Pagamentos) desde que o proprietrio da consulta tenha tal permisso: SELECT Sobrenome, Nome, Salrio FROM Funcionrios ORDER BY Sobrenome WITH OWNERACCESS OPTION; Se, por outro lado, um usurio for impedido de criar ou anexar a uma tabela, voc poder usar WITH OWNERACCESS OPTION para habilit-lo a executar uma consulta construo de tabela ou consulta anexao. Se voc quiser reforar as configuraes de segurana do grupo de trabalho e as permisses dos usurios, no inclua a declarao WITH OWNERACCESS OPTION. Esta opo exige que voc tenha acesso ao arquivo System.mda associado ao banco de dados. realmente til em implementaes de multiusurios seguras.

Exemplo da instruo SELECT, clusula FROM


Esse exemplo seleciona os campos "Sobrenome" e "Nome" de todos os registros da tabela "Funcionrios". SELECT Sobrenome, Nome FROM Funcionrios Esse exemplo seleciona todos os campos da tabela "Funcionrios".

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 27/178

SELECT Funcionrios.* FROM Funcionrios; Esse exemplo conta o nmero de registros que tm uma entrada no campo "CdigoPostal" e nomeia o campo retornado como "Tcp". SELECT Count(CdigoPostal) AS Tcp FROM Clientes; Esse exemplo mostra qual seria o salrio se cada funcionrio recebesse um aumento de 10 porcento. No altera o valor original dos salrios. SELECT Sobrenome, Salrio AS Atual, Salrio * 1.1 AS Proposto FROM Funcionrios; Esse exemplo coloca o ttulo Nome no topo da coluna "Sobrenome". O ttulo Salrio exibido no topo da coluna "Salrio". SELECT Sobrenome AS Nome, Salrio FROM Funcionrios; Esse exemplo mostra o nmero de funcionrios e os salrios mdio e mximo. SELECT Count(*) AS [Total de Funcionrios], Avg(Salrio) AS [Salrio Mdio], Max(Salrio) AS [Salrio Mximo] FROM Funcionrios; Para cada registro, mostra Sobrenome e Salrio no primeiro e ltimo campos. A seqncia de caracteres "tem um salrio de" retornada como o campo do meio de cada registro. SELECT Sobrenome, 'tem um salrio de', Salrio FROM Funcionrios;

Exemplo de clusula GROUP BY


Esse exemplo cria uma lista de nomes de departamentos nicos e o nmero de funcionrios em cada um destes departamentos. SELECT Departamento, Count([Departamento]) AS Tbc FROM Funcionrios GROUP BY Departamento; Para cada ttulo de funo nico, calcula o nmero de funcionrios do departamento de Vendas que tm este ttulo. SELECT Ttulo, Count(Ttulo) AS Tbc FROM Funcionrios WHERE Departamento = 'Vendas' GROUP BY Ttulo; Esse exemplo calcula o nmero de itens em estoque para cada combinao de nmero e cor do item. SELECT Item, Sum(Unidades) AS Tbc FROM ItensEmEstoque GROUP BY Item, Cor;

Exemplo de clusula HAVING


Esse exemplo seleciona os ttulos de cargos do departamento de Produo atribudos a mais de 50 funcionrios. SELECT Ttulo, Count(Ttulo) FROM Funcionrios WHERE Departamento = 'Produo' GROUP BY Ttulo HAVING Count(Ttulo) > 50; Esse exemplo seleciona os departamentos que tenham mais de 100 funcionrios. SELECT Departamento, Count([Departamento]) FROM Funcionrios GROUP BY Departamento HAVING Count(Departamento) > 100;

Exemplo de clusula ORDER BY

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 28/178

As instrues SQL mostradas abaixo usam a clusula ORDER BY para classificar os registros em ordem alfabtica e depois por categoria. Esse exemplo ordena os registros pelo sobrenome, em ordem descendente (Z-A). SELECT Sobrenome, Nome FROM Funcionrios ORDER BY Sobrenome DESC; Esse exemplo ordena, primeiro, por categoria ID e depois por nome do produto.

SELECT CategoriaID, ProdutoNome, PreoUnit FROM Produtos ORDER BY CategoriaID, NomeProduto;

Instruo INSERT INTO


Adiciona um ou vrios registros a uma tabela. Isto referido como consulta anexao.

Sintaxe
Consulta anexao de vrios registros: INSERT INTO destino [IN bancodedadosexterno] [(campo1[, campo2[, ...]])] SELECT [origem.]campo1[, campo2[, ...] FROM expressodetabela Consulta anexao de um nico registro: INSERT INTO destino [(campo1[, campo2[, ...]])] VALUES (valor1[, valor2[, ...]) A instruo INSERT INTO tem as partes abaixo: Parte destino bancodedadosexterno origem campo1, campo2 expressodetabela Descrio O nome da tabela ou consulta em que os registros devem ser anexados. O caminho para um banco de dados externo. Para uma descrio do caminho, consulte a clusula 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 aps um argumento destino ou os nomes dos campos dos quais se deve obter os dados, se estiverem aps um argumento origem. O nome da tabela ou tabelas das quais registros so inseridos. Este argumento pode ser um nico nome de tabela ou uma combinao resultante de uma operao INNER JOIN, LEFT JOIN ou RIGHT JOIN ou de uma consulta gravada. Os valores para inserir em campos especficos do novo registro. Cada valor inserido no campo que corresponde posio 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 vrgula e colocar os campos de textos entre aspas (" ").

valor1, valor2

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 29/178

Comentrios
Voc pode usar a instruo INSERT INTO para adicionar um nico registro a uma tabela usando a sintaxe de consulta anexao de um nico registro como mostrado acima. Neste caso, seu cdigo 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 no especifica cada campo, o valor padro ou Null inserido nas colunas omitidas. Os registros so adicionados no final da tabela. Voc tambm pode usar INSERT INTO para anexar um conjunto de registros de outra tabela ou consulta usando a clusula SELECT ... FROM como mostrado acima na sintaxe consulta anexao de vrios registros. Neste caso, a clusula 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 includa, precede a instruo SELECT. Se sua tabela de destino contm uma chave primria, voc deve acrescentar valores nicos, no Null ao campo ou campos da chave primria. Caso contrrio, o programa principal de banco de dados do Jet no anexar os registros. Se voc anexar registros a uma tabela com um campo Counter e quiser numerar novamente os registros anexados, no inclua o campo Counter em sua consulta. Inclua o campo Counter na consulta se quiser manter os valores originais do campo. Use a clusula IN para anexar registros a uma tabela de outro banco de dados. Para achar quais registros sero anexados, antes de voc executar a consulta anexao, primeiro execute e veja os resultados de uma consulta seleo que use o mesmo critrio de seleo. Uma operao de consulta anexao copia os registros de uma ou mais tabelas em outra. As tabelas que contm os registros que voc anexa no so afetadas pela operao de consulta anexao. Em lugar de acrescentar registros existentes de outra tabela, voc pode especificar o valor de cada campo em um nico registro novo usando a clusula VALUES. Se voc omitir a lista de campo, a clusula VALUES deve incluir um valor para cada campo na tabela; caso contrrio, um erro ocorrer em INSERT. Use uma instruo adicional INSERT INTO com uma clusula VALUES para cada registro adicional que voc quiser criar.

Exemplo de instruo INSERT INTO


Esse exemplo seleciona todos os registros de uma tabela hipottica "Novos Clientes" e os adiciona tabela "Clientes" (quando no so 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 "Funcionrios" INSERT INTO Funcionrios (Nome,Sobrenome, Ttulo) VALUES ("Andr", "Pereira", "Estagirio"); Esse exemplo seleciona todos os estagirios de uma tabela hipottica "Estagirios" que foram contratados h mais de 30 dias e adiciona seus registros tabela "Funcionrios". INSERT INTO Funcionrios SELECT Estagirios.* FROM Estagirios WHERE DataContrato < Now() - 30;

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 30/178

Declarao UPDATE
Cria uma consulta atualizao que altera os valores dos campos em uma tabela especificada com base em critrios especficos.

Sintaxe
UPDATE tabela SET valornovo WHERE critrio; A instruo UPDATE tem as partes abaixo: Parte tabela valornovo critrio Descrio O nome da tabela cujos os dados voc quer modificar. Uma expresso que determina o valor a ser inserido em um campo especfico nos registros atualizados. Uma expresso que determina quais registros devem ser atualizados. S os registros que satisfazem a expresso so atualizados.

Comentrios
UPDATE especialmente til quando voc quer alterar muitos registros ou quando os registros que voc quer alterar esto em vrias tabelas. Voc pode alterar vrios 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 PasEmbarque = 'RU'; UPDATE no gera um conjunto de resultados. Se voc quiser saber quais resultados sero alterados, examine primeiro os resultados da consulta seleo que use os mesmos critrios e ento execute a consulta atualizao.

Exemplo de instruo UPDATE


Esse exemplo muda os valores no campo "RelatrioPara" para 5 para todos os registros de funcionrios que atualmente tm valores de RelatrioPara de 2. UPDATE Funcionrios SET RelatrioPara = 5 WHERE RelatrioPara = 2; Esse exemplo aumenta o "PreoUnit" de todos os produtos no suspensos do fornecedor 8 em 10 porcento. UPDATE Produtos SET PreoUnit = PreoUnit * 1.1 WHERE FornecedorID = 8 AND Suspenso = No; Esse exemplo reduz o PreoUnit de todos os produtos no suspensos fornecidos pela Tokyo Traders em 5 porcento. As tabelas "Produtos" e "Fornecedores" tm uma relao um para vrios. UPDATE Fornecedores INNER JOIN Produtos ON Fornecedores.FornecedorID = Produtos.FornecedorID SET PreoUnit = PreoUnit * .95 WHERE NomeEmpresa = 'Tokyo Traders' AND Suspenso = No;

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 31/178

Instruo DELETE
Cria uma consulta excluso que remove registros de uma ou mais tabelas listadas na clusula FROM que satisfaz a clusula WHERE.

Sintaxe
DELETE [tabela.*] FROM tabela WHERE critrio A instruo DELETE tem as partes abaixo: Parte tabela.* tabela critrio Comentrios DELETE especialmente til quando voc quer excluir muitos registros. Para eliminar uma tabela inteira do banco de dados, voc pode usar o mtodo Execute com uma instruo DROP. Entretanto, se voc eliminar a tabela, a estrutura perdida. Por outro lado, quando voc usa DELETE, apenas os dados so excludos. 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 esto em uma relao um por vrios com outras tabelas. Operaes de excluso em cascata fazem com que os registros das tabelas que esto no lado "vrios" da relao sejam excludos quando os registros correspondentes do lado "um" da relao so excludos na consulta. Por exemplo, nas relaes entre as tabelas Clientes e Pedidos, a tabela Clientes est do lado "um" e a tabela Pedidos est no lado "vrios" da relao. Excluir um registro em Clientes faz com que os registros correspondentes em Pedidos sejam excludos se a opo de excluso em cascata for especificada. Uma consulta de excluso exclui registros inteiros e no apenas dados em campos especficos. Se voc quiser excluir valores de um campo especfico, crie uma consulta atualizao que mude os valores para Null. Descrio O nome opcional da tabela da qual os registros so excludos. O nome da tabela da qual os registros so excludos. Uma expresso que determina qual registro deve ser excludo.

Importante
Aps remover os registros usando uma consulta excluso, voc no poder desfazer a operao. Se quiser saber quais arquivos foram excludos, primeiro examine os resultados de uma consulta seleo que use o mesmo critrio e ento, execute a consulta excluso. Mantenha os backups de seus dados. Se voc excluir os registros errados, poder recuper-los a partir dos seus backups.

Exemplo de instruo DELETE


Esse exemplo exclui todos os registros de funcionrios cujo ttulo seja Estagirio. Quando a clusula FROM inclui apenas uma tabela, no necessrio indicar o nome da tabela na instruo DELETE. DELETE *FROM Funcionrios WHERE Ttulo = 'Estagirio'; Esse exemplo exclui todos os registros de funcionrios cujo ttulo seja Estagirio e que tambm tenham um registro na tabela "FolhadePagamento". As tabelas "Funcionrios" e "FolhadePagamento" tm uma relao um por um.

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 32/178

DELETE Funcionrios.* FROM Funcionrios INNER JOIN FolhaDePagamento ON Funcionrios.FuncionrioID = FolhadePagamento.FuncionrioID WHERE Funcionrios.Ttulo = 'Estagirio';

Subconsultas SQL
Uma subconsulta uma instruo SELECT aninhada dentro de uma instruo SELECT, INSERT, DELETE ou UPDATE ou dentro de uma outra subconsulta.

Sintaxe
Voc pode usar trs formas de sintaxe para criar uma subconsulta: comparao [ANY | ALL | SOME] (instruosql) expresso [NOT] IN (instruosql) [NOT] EXISTS (instruosql) Uma subconsulta tem as partes abaixo: Parte comparao expresso instruosqlt Descrio Uma expresso e um operador de comparao que compara a expresso com o resultado da subconsulta. Uma expresso para a qual o resultado definido da subconsulta procurado. Uma instruo SELECT de acordo com as mesmas regras e formato de qualquer outra instruo SELECT. Ela deve estar entre parnteses.

Comentrios
Voc pode usar uma subconsulta em vez de uma expresso na lista de campo de uma instruo SELECT ou em uma clusula WHERE ou HAVING. Em uma subconsulta, voc usa uma instruo SELECT para fornecer um conjunto de um ou mais valores especficos para avaliar as expresses das clusulas WHERE ou HAVING. Use o predicado ANY ou SOME, que so sinnimos, para recuperar registros na consulta principal que satisfaam a comparao com quaisquer registros recuperados na subconsulta. O exemplo abaixo retorna todos os produtos cujo preo unitrio maior que o preo de qualquer produto vendido com um desconto de 25 por cento ou mais: SELECT * FROM Produtos WHERE PreoUnit > ANY (SELECT PreoUnit FROM PedidoDetalhes WHERE Desconto >= .25); Use o predicado ALL para recuperar apenas os registros na consulta principal que satisfaam a comparao com todos os registros recuperados na subconsulta. Se voc mudou ANY para ALL no exemplo acima, a consulta retornaria apenas os produtos cujo preo unitrio 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 contm 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);

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 33/178

De maneira contrria, voc pode usar NOT IN para recuperar apenas os registros na consulta principal para os quais no existam registros com valores iguais na subconsulta. Utilize o predicado EXISTS (com a palavra reservada NOT opcionalmente) em comparaes true/false para determinar se a subconsulta retorna algum registro. Voc tambm pode usar aliases de nomes de tabelas em uma subconsulta para fazer referncia a tabelas listadas em uma clusula FROM fora da subconsulta. O exemplo abaixo retorna os nomes dos funcionrios cujos salrios sejam iguais ou superiores mdia de salrios de todos os funcionrios na mesma funo. Para a tabela Funcionrios dada o alias "T1": SELECT Sobrenome, Nome, Ttulo, Salrio FROM Funcionrios AS T1 WHERE Salrio >= (SELECT Avg(Salrio) FROM Funcionrios WHERE T1. T1.Ttulo = Funcionrios.Ttulo) Order by Title; No exemplo acima, a palavra reservada AS opcional. Algumas subconsultas so aceitas em consultas de tabela cruzada especialmente como predicados (as da clusula WHERE). Subconsultas como sada (as da lista SELECT) no so aceitas em tabelas de referncia cruzada.

Exemplos de subconsultas SQL


Esse exemplo lista o nome, ttulo e salrio de todos os representantes de vendas cujos salrios sejam superiores aos de todos os gerentes e diretores. SELECT Sobrenome, Nome, Ttulo, Salrio FROM Funcionrios WHERE Ttulo LIKE "*Repr Vendas*" AND Salrio > ALL (SELECT Salrio FROM Funcionrios WHERE (Ttulo LIKE "*Gerente*") OR (Ttulo LIKE "*Diretor*")); Esse exemplo lista o nome e preo unitrio de todos os produtos cujo preo unitrio seja igual ao do Licor de Cacau. SELECT NomeProduto, PreoUnit FROM Produtos WHERE PreoUnit = (SELECT PreoUnit 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, ContatoTtulo, Fone FROM Clientes WHERE ClienteID IN (SELECT ClienteID FROM Pedidos WHERE DataPedido BETWEEN #1/04/95# AND #1/07/95#); Esse exemplo lista os funcionrios cujo salrio seja maior que a mdia dos salrios de todos os funcionrios. SELECT Sobrenome, Nome, Ttulo, Salrio FROM Funcionrios T1 WHERE Salrio >= (SELECT AVG(Salrio) FROM Funcionrios WHERE Funcionrios.Ttulo = T1.Ttulo) ORDER BY Ttulo; Esse exemplo seleciona o nome de todos os funcionrios que tenham registrado pelo menos um pedido. Isto tambm poderia ser feito com INNER JOIN. SELECT Nome, Sobrenome FROM Funcionrios AS E WHERE EXISTS (SELECT * FROM Pedidos AS O WHERE O.FuncionrioID = E.FuncionrioID); Altera o campo Efetuado do arquivo de servios para 2 caso o mesmo tenha parecer tcnico 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);

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 34/178

Coneco Delphi com o MS-Access


Autor: Fernando Antonio Fernandes Anselmo E-Mail: fernandoanselmo@yahoo.com.br
Pr-Requisitos: Windows 98 Delphi 4.0 verso Client/Server Suite BDE 5.00 MS-Access 97

Prefcio
Antes de comearmos 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 fcil de se trabalhar tanto para ns (programadores) quanto para o usurio, ou ento que muitos de ns o temos, ou ainda pode-se dizer que ele um padro mundial, mas fico com a explicao 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 alteraes feitas constantemente na base, perda e recuperao 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 ? No existe "quase" nenhum problema na migrao de sistemas com o Delphi, normalmente no preciso mudar uma nica linha de programao para se utilizar o mesmo sistema em bancos de dados completamente diferente (desde bvio siga-se alguns passos bsico). O nico problema que existe numa migrao quanto aos comandos SQL (Structure Query Language), pois infelizmente o Access possui um SQL prprio no comum aos outros bancos de dados. Mas todos os problemas so facilmente resolvidos criando-se variveis 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 conexo direta com o Banco de Dados MS-Access 97, para tanto faz-se necessrio de: 1. 2. BDE (Borland DataBase Engine) para a verso 5.00 Biblioteca de acesso DAO 3.5 (IDDA3532.DLL) colocada no diretrio do BDE - C:\Arquivos de Programas\Borland\Common Files\BDE

A conexo do Delphi com o MS-Access funciona da seguinte maneira BDE - DAO - Banco Access, ento na verdade preciso instalar o DAO (Data Access Objects), a Microsoft para as verses 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, ento para ter a "correta" licena de distribuio do DAO voc precisa adquirir qualquer um desses aplicativos. O DAO se faz necessrio 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 tambm precisar instalar o link de conexo. Voc poder acertar o Install Shield (conforme a apostila 4) para instalar todas as bibliotecas de acesso do DAO mas necessrio 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 conexo, entre no BDE Administrator e proceda a seguinte troca na pgina Configuration, conforme a figura:

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 35/178

Prontinho basta agora sair e entrar novamente do BDE Administrator e criamos nossos Aliases de conexo.

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 36/178

Curso de Delphi 4.0 - Apostila 01


Autor: Fernando Antonio Fernandes Anselmo E-Mail: fernandoanselmo@yahoo.com.br
Pr-Requisitos: Windows 98 Delphi 4.0 verso Client/Server Suite BDE 5.00 MS-Access 97 Arquivos trabalhados juntos com esta apostila: PASCOA2G.BMP

Prefcio
Salve, para voc que est comeando e participando deste curso, primeiramente gostaria de avisar que o curso totalmente prtico, com exerccios e truques que lhe ajudaro a seno dominar pelo menos a desvendar os mistrios 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 conhea tambm 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 construdo errado. Existe uma frase para o Delphi que sempre utilizo quando comeo meus cursos assim: Tudo o que parece difcil na verdade fcil Tudo o que parece fcil na verdade muito mais fcil. Isso sempre funcionou com o Delphi. Um abrao e bom trabalho. Solicito que quando voc encontrar a seguinte simbologia Importante pare e leia com a maior ateno, pois ali voc encontrar uma dica valiosa que poder lhe ajudar a esclarecer vrias dvidas. O Delphi um ambiente de Desenvolvimento totalmente Baseado na Orientao a Objetos, no puro (discutiremos isso no apndice referente a Orientao a Objetos) mas por enquanto voc precisa apenas saber que ele uma ferramenta com um incrvel poder na construo tanto de softwares complexos, quanto de sistemas de manipulao a bancos de dados. Para o nosso primeiro contato com a ferramenta, selecionei algo prtico, fcil, til e at mesmo bonitinho, um carto eletrnico, voc poder mandar para seus amigos um simples executvel com uma mensagem, vou criar aqui um para a Pscoa mas possvel aproveitar a idia para outros eventos tambm tais como Natal, Aniversrios, nascimentos e assim vai. Vamos comear ento:

Conhecendo o Ambiente
Abra o Delphi, bem a est seu ambiente de trabalho, vamos a uma rpida explicao, o Delphi composto por quatro ambientes de trabalho:

1. Parte superior composta pelo Menu, Component Pallete e Botes de Acesso Rpido (Speed Button): exatamente o conjunto que est suspenso na rea aberta, o Menu (localizado no topo) d acesso as
opes, a Component Pallete (localizado na parte superior direita) contm todos os objetos (divididos em classes) que voc utilizar para realizar seus projetos, e os Botes de Acesso Rpido (localizado na parte superior esquerda) que so uma abreviao dos comandos do menu.

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 37/178

Uma novidade do Delphi 4.0 que todos eles esto colocados em janelas auto-arrastveis, ento possvel modificar as possies 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 contm 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 comunicao entre o sistema e os nossos usurios.

4. Code Editor: a rea localizada atrs do "Form", ela foi dividida em dois ambientes, uma parte que funcionar
como ndice, nos mostrandos os objetos existentes, as bibliotecas utilizadas e as variveis ou constantes disponveis, elm dos procedimentos e funes criadas e uma outra que conter nossas o cdigo propriamente dito (em linguagem Object Pascal), diferentemente das outras linguagens visuais, no Delphi voc tem a capacidade de visualizar todo o cdigo do seu formulrio e no apenas uma determinada parte.

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 38/178

Projeto 1 - Carto Eletrnico


Bem, agora que estamos familiarizados com o ambiente, vamos comear como uma receita de bolo, siga um passo atrs do outro, mas antes de comear, 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 Carto, e coloque nela o .BMP enviado: 1. Na Component Pallete localize uma pgina chamada Additional e dentro dessa pgina 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 padro de uma janela de mensagens) 3.2. Caption: Feliz Pscoa (Contedo da tarja do formulrio) 3.3. Color: clBlack (Cor do formulrio para preto) 3.4. Font: Clique nos "..." e faa as seguintes altees na janela de Fonts: 3.41. Cor: Branco 3.42. Tamanho: 10 3.4. Name: F_Cartao (Nome interno do formulrio) 3.5. Position: poScreenCenter (Far com que o formulrio fique sempre centralizado quando for executado)

Importante - Aps alterarmos a Cor (propriedade Color) e a Fonte (propriedade Font) todos os outros objetos criados em cima deste Form, automaticamente herdaro essas alteraes.
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 formulrio) mude para fCartao.PAS 4.2.Aonde aparece Project1.dpr (o Delphi est se referindo do nome do projeto - que ser o nome do executvel final) mude para Cartao.DPR 5. Na Component Pallete localize uma pgina chamada Standard e dentro dessa pgina 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:

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 39/178

Bom, todos os objetos que sero visveis j esto a, agora vamos criar dois objetos que serviro apenas como meros auxiliares: 7. Na Component Pallete na mesma pgina 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 faa as seguintes altees 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 sacrifcio em incenso, que sobe clamando por justia 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 estratosfrico, seus deputados escondidos, seus senadores omissos, sua igreja distrada, seus militares fantoches, sua polcia ausente, perdoa ns todos, Senhor, perdoa a mim e a meu irmo que nada fizemos, que no agimos, e que no vimos a imagem de seu filho Cristo na Cruz. Ou digite um outro texto que mais lhe agradar, mas anote o nmero de linhas (neste aqui temos 25 linhas) 8.3. Visible: False (No mostrar o objeto em tempo de execuo)

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 40/178

9. Na Component Pallete na pgina System clique no objeto Timer (acredito que seja o primeiro) e d um clique no Form (automaticamente o Delphi criou um quadradinho com um relgio, que por sinal uma cpia do desenho do objeto). A propriedade Interval controla a velocidade do objeto.

Codificando
Tudo pronto, agora s meter a mo no programa, mas vamos devagar, a idia do carto, se voc ainda no 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 (atravs da propriedade Interval, medida em milsimos de segundo) que simular o movimento entre os labels. Ento vamos comear 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 varivel particular (Private) do tipo inteira (Integer) que servir apenas a este formulrio, sendo criada e destruda junto com ele. 11. Localize na Object Inspector o objeto F_Cartao, mude para a pgina 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 cdigo: 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 formulrio se inicia, limparemos os oito Labels para isso simplesmente utilizaremos uma string vazia, use aspas simples (nunca duplas) e sem espaos entre elas, para chamar os oito labels utilizaremos a varivel ComponentCount para contar quantos componentes tem o formulrio, verificamos quais deles so label's e estes limparemos e iniciarmos a nossa varivel NumLinha com 0.

Importante -

Muitos dos procedimentos que o Delphi cria automaticamente (atravs 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 ao de um mouse ou de um clique num boto, e assim vai.

Aqui foi preciso rastrear todos os componentes do formulrio atravs do comando Components[n], aonde n o nmero de cada componente. Isto iniciado do 0 (assim como todo Array no Delphi comea do 0, ex: Lines, Items...), ento preciso criar um FOR que vai do 0 at o (nmero total de componente-1) porque o primeiro o 0 isto explicasse imaginando uma lista de 10 nmeros comeados pelo 0, vc ter 0,1,2,3,4,5,6,7,8,9 ento o ltimo nmero ser o nmero total da sua lista - 1.

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 41/178

Importante - Claro que ao invs 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 alm 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 ?? Alm do que isso pode-se dizer que o primeiro passo para um recurso de MacroSubstituio, como foi utilizado com o TLabel, pode tambm ser utilizado para o TEdit, TEditMask , TDBText ou qualquer outro que voc deseje. 12. Localize na Object Inspector o objeto Timer1, mude para a pgina 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 funo interna Monta que nos retornar o contedo de uma determinada linha do objeto Memo1, note que trabalhamos com 8 label's, ento:

Importante - Note que existe uma varivel chamada Result ela uma varivel definida pela prpria funo (no
caso tipo String), poderamos aqui usar dois nomes ou Monta ou a palavra chave Result, ambos os nomes apontam para a mesma varivel que tem como funo fazer a devoluo da String definida pela funo (para maiores referncias veja a apostila Programao Orientada a Objetos) no primeiro segundo que passar: Label1 at Label7 = Branco e o Label8 com o contedo da primeira linha do objeto Memo1.

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 42/178

No prximo segundo que passar: Label1 at Label6 = Branco, Label7 com o contedo da primeira linha do objeto Memo1 e o Label8 com o contedo da segunda linha do objeto Memo1. No prximo segundo que passar: Label1 at Label5 = Branco, Label6 com o contedo da primeira linha do objeto Memo1 e o Label7 com o contedo da segunda linha do objeto Memo1 e Label8 com o contedo da terceira linha do objeto Memo1 E assim vai aumentando segundo aps segundo, at um total de 30 segundos, note aqui que so 25 linhas, aumentei mais 5 para ter um intervalo entre a ltima linha e o comeo de uma nova montagem quando a varivel monta linha novamente reiniciada a zero. Note que para adicionar 1 a varivel NumLinha utilizo a funo interna INC, esta funo tambm pode ser: Inc(varivel, [quanto]) aonde "quanto" representa o nmero que voc quer adicionar a varivel, se no for enviado ser por default 1. Isto seria o correspondente: varivel := varivel + quanto; e s de curiosidade o contrrio da funo INC a funo DEC.

Importante - os brancos so conseguidos pesquisando valores negativos dentro da propriedade Lines do objeto
Memo1. Note que eu fao [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 no adianta tentar usar o recurso da ComponentCount pois pode avacalhar na hora da
montagem, ento prefervel fazer o lote da montagem dos oito label's na mo mesmo.

Enviando o projeto para um Amigo


Prontinho agora basta apenas voc compilar o projeto, v ao menu nas opes Project | Compile... (ou pressione CTRL+F9 e prontinho s mandar o executvel gerado para sua(seu) namorada(o), parente, colega ou amigo(a), acredito que deva caber num nico disquete (Ateno: No precisa mandar o .BMP o Delphi j se encarrega de guard-lo no executvel).

Realizando uma pequena otimizao


Anote antes desses passos qual foi o tamanho em Bytes que ficou o seu executvel. 1. Uma coisa que voc pode (e deve fazer) ir em Project | Options... na pgina Application atribua um ttulo (Title) e um novo cone (Icon) ao seu projeto, depois v na pgina Compiler e desmarque todas as opes do Grupo Debugging (elas s servem para quando voc estiver testando o aplicativo). 2. No incio do programa do seu formulrio deixe apenas as seguintes bibliotecas: unit fCartao; interface uses Windows, Classes, Controls, ExtCtrls, StdCtrls, Forms; 3. D uma compilada final escolhendo as opes Project | Build All Compare agora o tamanho do seu executvel final. Mas no se preocupe esses macetes voc aprender ao longo do nosso curso. (Ateno: tambm no precisa mandar o cone que voc escolheu para seu projeto o Delphi tambm se encarrega de coloc-lo no executvel).

Finalmente
Na prxima apostila comearemos a desvendar os segredos dos bancos de dados.

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 43/178

Curso de Delphi 4.0 - Apostila 02


Autor: Fernando Antonio Fernandes Anselmo E-Mail: fernandoanselmo@yahoo.com.br
Pr-Requisitos: Windows 98 Delphi 4.0 verso 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

Prefcio
Salve, aps a construo de um Carto voc pode estar pensando o que vir a seguir ? Acertou se pensou no acesso a Banco de Dados, afinal o maior mistrio 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 conexo de forma rpida e prtica. 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 comear a desenvolver. Vamos a uma rpida explicao o que este projeto. Inicialmente ser mostrado o mapa do Brasil para que o usurio possa escolher determinada regio, aps a escolha de uma regio o usurio poder dentro desta escolher qual o estado ele deseja ter uma pequena descrio, eu vou alargar um pouco e dar tambm a possibilidade de impresso da regio escolhida.

Projeto 2 - Mapa Eletrnico (1a. Parte)


Bem, agora vamos comear nosso projeto (note que eu sempre falo a palavra Projeto ao invs de Sistema, em Orientao a Objetos no existem Sistemas e sim Projetos ento 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 concluso do resto do projeto, Ok ? Ento vamos meter a mo na massa: 1. Abra o Delphi, como se isso j no fosse bvio. 2. Na Component Pallete localize uma pgina chamada Additional e dentro dessa pgina 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)

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 44/178

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 padro de uma janela de mensagens) 4.2. Caption: Mapa Eletrnico (Contedo da tarja do formulrio) 4.3. Name: F_Mapa (Nome interno do formulrio) 4.4. Position: poScreenCenter (Far com que o formulrio 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 formulrio) mude para fMapa.PAS 5.2. Aonde aparece Project1.dpr (o Delphi est se referindo do nome do projeto - que ser o nome do executvel final) mude para Mapa.DPR 6. Na Component Pallete localize uma pgina chamada Standard e dentro dessa pgina 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 faa as seguintes altees na janela de Fonts: 6.11. Cor: Castanho 6.12. Estilo: Negrito 6.2. Caption: Clique sobre a Regio a consultar (Contedo que ser mostrado) 7. Na Component Pallete localize uma pgina chamada Additional e dentro dessa pgina 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 preferncia um em cada regio, e altere as propriedades Name e Hint de cada um para, respectivamente: Name ImgNorte ImgNordeste ImgCentro ImgSudeste ImgSul - Hint - Mostra os estados da Regio Norte - Mostra os estados da Regio Nordeste - Mostra os estados da Regio Centro-Oeste - Mostra os estados da Regio Sudeste - Mostra os estados da Regio Sul

Importante - A prxima modificao tem a ver com Orientao a Objetos o termo POLIMORFISMO, isso significa que vrios objetos (mesmo diferentes) possuem propriedades idnticas entre si, por exemplo a propriedade Caption de um objeto Form possui (basicamente) a mesma funo 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 no 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 mozinha apontando).

Importante - Isso pode ser usado para alterar diversas propriedades de objetos diferentes, praticaremos isso
posteriormente. 9. Quando terminar clique em qualquer regio do formulrio para desmarcar os objetos. 10. Para terminar nosso primeiro formulrio desse projeto v para a Component Pallete localize uma pgina chamada Additional e dentro dessa pgina 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 trs importantes propriedades se alterassem: 10.11. Caption: assumiu o valor &Close. 10.12. Glyph: ganhou uma imagem padro de uma portinha de sada 10.13. Modal Result: apesar de no ter sofrido alterao internamente foi disparado uma Flag que far com que quando este boto seja clicado o formulrio se encerre automaticamente. 10.2.Caption: &Fechar (apenas para "aportuguesar"o nosso aplicativo). 11. D uma comparadinha no desenho para ver como ficou:

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 45/178

Bom, este ser o nosso primeiro formulrio, de uma srie de sete, sua funo simples, ele mostrar o mapa do Brasil e ao ser clicar em qualquer parte de uma determinada regio ele disparar o mapa respectivo desta.

Codificando o mapa
A codificao um tanto simples, mas pretendo aqui ensinar tambm 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 faa as seguintes alteraes implementation {$R *.DFM} uses fNorte, fNordeste, fSul,

// Chama o mapa da Regio Norte // Chama o mapa da Regio Nordeste // Chama o mapa da Regio Sul

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 46/178

fSudeste, fCentro;

// Chama o mapa da Regio Sudeste // Chama o mapa da Regio Centro-Oeste

procedure TF_Mapa.ChamaRegiao(Sender: TObject); // Chama os outros Formulrios 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 declarao 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 formulrio gerado tudo compilado e salvaguardado em reas de memria prontos para serem utilizados, ou seja, a Unit Windows (se voc reparar ela est l em cima) e jogada para uma rea de memria, mas em compensao a Unit fNorte (que criaremos posteriormente) no armazenada. Assim eu estou preservando vrios blocos de memria para serem utilizados apenas quando realmente forem necessrios. Prontinho agora vamos explicar essa procedure linda e maravilhosa que foi montada de propsito 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 cdigo: (por exemplo para o objeto da Regio Norte) begin F_Norte := TF_Norte.Create(Application); F_Norte.ShowModal; F_Norte.Free; end; Isso funcionaria perfeitamente bem mas como so cinco objetos precisariamos repetir isso cinco vezes (imagine se fossem uns 20 ou 30), e isso j no to bom assim em Pascal. Outra coisa que poderiamos fazer , criamos um procedimento particular (l no Private) para todas os outros procedimentos ento 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

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 47/178

ShowModal; finally Free; end; end; e em cada objeto TImage clicarmos no evento OnClick e para cada um colocarmos o seguinte cdigo: (por exemplo para o objeto da Regio Norte) begin CriaForm(TF_Norte); end; Isso tambm funcionaria perfeitamente bem mas como so cinco objetos precisariamos repetir isso cinco vezes (imagine novamente se fossem uns 20 ou 30), mas agora o pior que e sero vrios procedimentos que teremos que olhar caso d algum erro e isso j no to bom assim em Pascal. Ento resolvi fazer da maneira como eu coloquei. Criei um nico procedimento ChamaRegiao que receber uma varivel 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 formulrio) e d um clique simples sobre o objeto ImgNorte aperte a tecla F11 (para chamar a Object Inspector), v para a pgina 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 regies. Este formulrio j est pronto, vamos agora ver o que acontece com cada regio. (Obs. No adianta tentar rodar que ele deve acusar erro que as outras unidades ainda no existem.

Primeira Regio
Apenas para gui-los mostrarei como criar o mapa da Regio Sul (s tem trs estados e no deve me dar muito trabalho :)) voc dever criar os formulrios para as outras regies. Observe que quase tudo igual ao primeiro formulrio criado. A partir do Menu Principal clique em File | New Form e ser disponibilizado um novo formulrio, vamos aos passos: 12. Na Component Pallete localize uma pgina chamada Additional e dentro dessa pgina 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 padro de uma janela de mensagens) 14.2. Caption: Estados da Regio Sul (Contedo da tarja do formulrio) 14.3. Name: F_Sul (Nome interno do formulrio) 14.4. Position: poScreenCenter (Far com que o formulrio 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 formulrio) mude para fSul.PAS

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 48/178

16. Na Component Pallete localize uma pgina chamada Standard e dentro dessa pgina 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 faa as seguintes altees na janela de Fonts: 6.11. Cor: Castanho 6.12. Estilo: Negrito 16.2. Caption: Clique sobre o Estado a consultar (Contedo que ser mostrado) 17. Na Component Pallete localize uma pgina chamada Additional e dentro dessa pgina 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 preferncia um em cada regio, 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 regio do formulrio para desmarcar os objetos. 20. Para terminar nosso primeiro formulrio desse projeto v para a Component Pallete localize uma pgina chamada Additional e dentro dessa pgina 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 trs 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 formulrios, so eles respectivamente: Nome Interno Nome Externo F_Norte fNorte F_Nordeste fNordeste F_Centro fCentro F_Sudeste fSudeste Figura a usar NORTE.BMP NORDESTE.BMP CENTRO.BMP SUDESTE.BMP

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 49/178

Importante - Chamei de Nome Interno a propriedade Name dos formulrios e Nome Externo como ser o nome
que voc deve salvar cada formulrio. Note que a nica diferena entre eles est num simples apostrofe "_", isso facilita muito quando queremos lembrar o nome que precisamos utilizar.

Importante - Infelizmente com o Delphi no existe outro componente mais poligonal que o tImage, mas tem uma notcia boa o Delphi respeitar o objeto tImage criado por ltimo, ento voc pode colocar uns sobre os outros. Comigo aqui acabei conseguindo montar com uma exatido fora do normal, at eu me assustei. Uma Dica: Para a regio Centro-Oeste crie primeiro o Objeto do estado de Gois e dentro dele coloque o objeto do estado do Distrito Federal.

Tirando os formulrios do Auto-Create


O Delphi cria automaticamente todos os formulrios que utilizamos, mas isso gera um tanto de prejuzo as reas de memria ( bvio que um projeto com 7 ou at 10 no um caso srio, mas um projeto com 50 ou 70 j comea a dar uns erros muito estranhos) ento lembra-se do procedimento CriaForm ele vai exatamente criar os nosso formulrios para utilizarmos e depois destru-los. Mas precisamos dizer para o Delphi que no queremos que ele faa o servio 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 boto Options. Selecione a pgina Forms l voc ver dois objetos ListBox, do lado esquerdo so os AutoCreate Forms e do lado direito esto os Available forms ou simplesmente formulrios disponveis. Ento selecione os formulrios: F_Norte, F_Nordeste, F_Centro, F_Sudeste e F_Sul e clique no boto com o sinal > isso far com que eles sejam despachados para o outro lado. No faa o procedimento com o F_Mapa, ele o nosso Menu e ele precisa realmente ser criado automaticamente assim que o usurio iniciar o processo. Prontinho, agora execute o projeto e veja como ele est ficando.

Finalmente
Existem vrias 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 servio. Mas faremos isto apenas na prxima apostila.

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 50/178

Curso de Delphi 4.0 - Apostila 03


Autor: Fernando Antonio Fernandes Anselmo E-Mail: fernandoanselmo@yahoo.com.br
Pr-Requisitos: Windows 98 Delphi 4.0 verso Client/Server Suite BDE 5.00 MS-Access 97 Arquivos trabalhados juntos com esta apostila: BASICO.MDB

Prefcio
Salve, na ltima apostila comeamos a montar nosso pequeno mapa eletrnico, agora vamos conclu-lo. Antes de recomearmos precisamos entender como funciona a conexo entre o Delphi e o Banco de Dados. Isto realizado atravs de um conjunto de bibliotecas que a Inprise chamou de BDE (Borland DataBase Engine) ela trabalha assim como um ODBC de ligao, mas com a grande vantagem que para determinados bancos o acesso totalmente nativo, isso significa que a conversa entre sua Aplicao e o Banco no recebe interferencias externas a no ser do BDE (mas isso at o antigo Clipper precisava de suas ligaes para seus acessos com os bancos xBase). Ilustradamente o acesso funciona da seguinte maneira:

A coisa acontece da seguinte forma, a sua aplicao atravs dos objetos contidos na Component Pallete (localizado na parte superior direita) e na pgina chamada Data Access esto todos os objetos que fazem esta primeira conexo entre o Aplicativo e o BDE e este se comunica com o Banco de Dados.

Importante - Note que eu no especifiquei qual o Banco de Dados, ento salvaguardando algumas regras do
prprio banco (tais como o nome das tabelas, formas de SQL) poderemos utilizar para nossa aplicao qualquer banco que acharmos mais fcil de manipularmos (tais como dBase, Access, Paradox...) e ao final (antes de entregar a aplicao para o usurio) fazermos um ltimo teste com o banco de dados escolhido por ele (Oracle, SQL Server, Interbase, Sybase...) para isso no precisaremos modificar uma nica linha de cdigo do nosso aplicativo.

Importante - A conexo com o MS-Access funciona da seguinte forma: Entre o BDE e o Banco de Dados existe um aplicativo a mais de conexo, 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 distribuio do produto voc deve adquirir quaisquer das ferramentas de desenvolvimento da Microsoft.

Iniciando na Prtica
Bem se voc ainda no fez, aconselho que voc d uma olhada no apndice identificado por CONEXAO e faa as alteraes 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 Federao coloque

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 51/178

dentro desta tudo que voc recebeu. Graficamente ento temos:

Abra agora o aplicativo BDE Administrator e crie um Alias para o banco de dados enviado. Se voc no 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 no coloque acentos no seu Alias e procure no ultrapassar os oito caracteres isso alm de manter a compatibilidade entre o Delphi 32 Bits e o Delphi 16 Bits tambm evita uma srie de confuses.
3. Altere a propriedade DATABASE NAME para C:\CursoDelphi\Federao\basico.mdb e confirme as alteraes em Object | Apply (ou simplesmente CTRL+A, ou ainda clique no quarto boto da barra de ferramentas) 4. Teste seu novo alias clicando em Object | Open (ou simplesmente clique no primeiro boto 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 boto da barra de ferramentas) Se voc est confuso com tudo isso no fique retorne aquela figura inicial sobre a conexo, pode-se dizer que estamos exatamente criando o quadradinho do BDE. O Alias simplesmente uma conexo que se far entre seu Aplicativo e o Banco de Dados

Trabalhando com o TDatabase


Antes de comearmos abra novamente o seu projeto, para isso a partir do Menu Principal clique em File | Open localize o arquivo Mapa.DPR. No formulrio F_Mapa e coloque um objeto DataBase (que se encontra na Component Pallete na pgina 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 conexo com o nosso banco de dados, para lembrar a vocs: 1a. Conexo: Entre o Banco de Dados e o Alias 2a. Conexo: Entre o Alias e o objeto tDataBase 3a. Conexo: Entre o objeto tDataBase e os objetos DB (tTable, tQuery, tStoreProc) 4a. Conexo: Entre os objetos DB com os objetos que o usurio utilizar (todos os que esto na pgina DataControls e alguns outros).

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 52/178

Se voc quer simular como ser essa segunda conexo, 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 aparea quando o usurio for usar nosso aplicativo, antes volte a propriedade Connected do objeto para false, na pgina de eventos de um duplo clique no evento OnLogin e vamos as alteraes: procedure TF_Mapa.nmFederaLogin(Database: TDatabase; LoginParams: TStrings); begin LoginParams.Values['USER NAME'] := ''; LoginParams.Values['PASSWORD'] := ''; end; Agora precisamos simular as alteraes de Conexo para tanto, chame o objeto F_Mapa, e d um duplo clique no evento OnShow para abrirmos esta conexo: procedure TF_Mapa.FormShow(Sender: TObject); begin nmFedera.Connected := True; end; Para fechar a conexo 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 Orientao a Objetos (lembram-se do POLIMORFISMO),


o termo AO, isso significa que um evento qualquer disparado quando outro evento acionado, ou seja como um efeito cascata. O que acontece aqui que quando o usurio executar o sistema esse disparar o evento OnShow do formulrio 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 construo e desenvolvimento de softwares, mas como todo paraso tem seu inferno, o Delphi tambm tinha o seu, a gerao de relatrios, na poca do Delphi 1.0 a ferramenta para ger-los era o Report Smith, mas era claro que ele no 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 relatrios ficavam separados do executvel principal - Relatrios muito complexos eram uma Via-Crucis faz-los - Relatrios muito simples demoravam uma eternidade para rod-los

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 53/178

Ento os Delphianos da poca procuravam alternativas, entre elas aqui vale destacar: - Report Crystal - Report Builder - Biblioteca Printers (do prprio Delphi) Esta ltima deu origem a vrios geradores de relatrios 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 verso 3.0 resolveu-se no mais distribuir o Report Smith tornando o Quick o gerador oficial do Delphi. No pretendo dizer aqui que o Quick o melhor gerador de relatrios que existe para o Delphi, acredito sempre que a melhor ferramenta aquela que voc domina e conhece, em listas de discusso comum voc ver coisas como: - O Quick ruim - difcil de construir algo nele - Relatrios complicados so impossveis faz-los - entre milhares de outras coisas A, todos colocam milhares de substitutos, mas veja bem, a prpria Inprise abriu mo 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 no conhecemos ou tentamos aprender uma ferramenta, acabamos no fazendo o essencial que ver primeiro como a ferramenta trabalha, o Quick um gerador de relatrios totalmente orientado a objetos, e isso no muito fcil de assimilarmos. Ento para ajud-los sempre tentarei utiliz-lo como uma ferramenta no s para gerar relatrios, mas tambm para: - Formulrios de Consultas - Importaes em .TXT e .HTML - Relatrios Analticos - Fichas de Caixa, Balancetes e Outros. Vocs vero que esse terrvel monstro horroroso de duzentas cabeas (que cada dia cresce uma) na verdade no passa de um horroroso monstro terrvel de duzentas e uma cabeas. Bem vamos deixar de ladainha e comear a trabalhar.

Construindo o formulrio para uma regio genrica


No pretendo aqui construir um formulrio para cada regio (teve gente que suspirou de alvio), mas sim um nico que servir para qualquer regio que o nosso usurio clicar. Vamos aos passos: 1. A partir do Menu Principal clique em File | New Form e ser disponibilizado um novo formulrio 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 formulrio) mude para fEstado.PAS 3. Na Component Pallete ache uma pgina entitulada QReport nela esto todos os objetos utilizados pelo Quick, localize o objeto chamado QuickRep, clique nele e em seguida click no formulrio.

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 54/178

Importante - Foi criado nesse momento nossa rea de trabalho, o Quick 1.0 (distribudo com o Delphi 2.0) no
criava esta rea branca que vc est vendo, ele se resumia a apenas alargar as propores do formulrio (propriedade Width e Height) para o tamanho de uma pgina da impressora. 4. Vamos para a Object Inspector e altere a propriedade Name para QrEstado

Importante - Qualquer gerador de relatrio trabalha por sees, pois nossos (e qualquer) relatrios tem essas
sees, so elas: Cabealho, Ttulo da Pgina, Rodap da Pgina, Pgina Inicial, ltima Pgina, Linhas Detalhes, e assim vai, vamos criar essas sees, o Quick as chama de Bandas. 5. Na Component Pallete na pgina 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 sees no caso escolhemos uma Banda de Cabealho de Pgina, ela aparecer em todas as pginas. 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 pgina 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 (Ento o QrLabel se alinhar centralizado dentro da banda) 8.4. Font: Clique nos "..." e faa as seguintes altees 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 pgina QReport, localize o objeto chamado QrBand, clique nele e em seguida click dentro do objeto do QrEstado (no 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 sees 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 marcao azul e d seis click's) dentro do objeto BdDetalhe, agora altere a propriedade Caption de cada um respectivamente: Sigla: Nome: Capital: Nm.Municpio: Regio: Descrio:

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 55/178

12. Agora marque todos os seis objetos (lembra-se) e aproveitando o Polimorfismo altere a propriedade Font, clique nos "..." e faa as seguintes altees 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 ento no ltimo boto da primeira linha. Todos eles sero 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, espaamento vertical e direita. Segunda Linha: Superior, centraliza horizontalmente, tamanho horizontal, espaamento horizontal e inferior 14. Faremos agora a 3a. Conexo. Vamos para a pgina Data Access e localize o objeto Query. Click nele e clique dentro do formulrio e altere as seguinte propriedades: 14.1. DataBaseName para dnFedera (isto s aparecer se o formulrio F_Mapa estiver aberto) 14.2. SQL, clique nos "..." e faa escreva:
select * from Federacao

14.3. Name para QryEstado

Importante - Se voc no conhece SQL (Structure Query Language) aconselho que voc compre um bom livro,
ou veja a apostila referente aos comandos bsicos. 15. Est a 4a. Conexo. Voltemos para a pgina 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 faa as seguintes altees 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

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 56/178

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 relatrio final mesmo sem precisar
rodar o sistema, para tanto faa o seguinte: 1. No objeto QryEstado altere a propriedade Active para True. 2. Clique no objeto QrEstado e em seguida clique com o boto 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 Regio


Apenas para gui-los mostrarei como criar os cdigos do mapa da Regio Sul voc dever criar os cdigos para as outras regies. Observe que novamente quase tudo igual. Abra o formulrio 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}

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 57/178

end. E faa as seguintes alteraes: 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 + ''')'); // Ateno 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 varivel do tipo TObject e para este procedimento coloquei um outro procedimento interno, chamado Mostra que realizar os seguintes passos: 1. Criao do Formulrio F_Estado; 2. Organizao do SQL para o estado selecionado criando a Query; 3. Mostra na tela do relatrio (note que no preciso do comando SHOWMODAL do formulrio, e sim PREVIEW do objeto QuickRep); 4. Fecha a Query; e 5. Eliminao do F_Estado da memria. Para ativar todo o conjunto aperte novamente a tecla F12 (para mostrar o formulrio) e d um clique simples sobre o objeto ImgPR aperte a tecla F11 (para chamar a Object Inspector), v para a pgina 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 trs 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';

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 58/178

A VariavelString ter em seu contedo o valor Nome : Nando, agora se fizermos: VariavelString := 'Nome : ''Nando'''; A VariavelString ter em seu contedo o valor Nome : 'Nando'. Eu apenas acrescentei mais dois plicks simples entre a palavra Nando.

Tirando o formulrio F_Estado do Auto-Create


V (a partir do menu principal) em View | Project Manager. Clique no boto Options. Selecione a pgina Forms l voc ver dois objetos ListBox, do lado esquerdo so os Auto-Create Forms e do lado direito esto os Available forms ou simplesmente formulrios disponveis. Ento selecione os formulrios: F_Estado e clique no boto com o sinal > e despache-o para o lado aonde esto os outros isolando novamente o nosso Menu pois lembrando que ele precisa ser criado automaticamente assim que o usurio iniciar o processo. Prontinho, agora execute o projeto e bom divertimento com seu mapa eletrnico. Na prxima aprenderemos como distribu-lo e gerar alguns macetes para otimizao.

Finalmente
Agora precisamos arrumar, empacotar e distribuir nosso projeto, mas isto s ser feito na prxima apostila.

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 59/178

Curso de Delphi 4.0 - Apostila 04


Autor: Fernando Antonio Fernandes Anselmo E-Mail: fernandoanselmo@yahoo.com.br
Pr-Requisitos: Windows 98 Delphi 4.0 verso 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 e LOGO.BMP

Prefcio
Salve, na ltima apostila montamos nosso segundo aplicativo o Mapa Eletrnico, o interessante com ele que calmamente comeamos 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 mximo com um aplicativo que arranha a superfcie deste fantstico 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 executvel (.EXE) mas o problema comea quando ele utiliza o BDE, a a coisa complica um pouco, mas acredito que aps essa parte voc comear a dominar uma importante ferramenta de distribuio para seus aplicativos.

Preparando o sistema para o Empacotamento


Antes de gerarmos nossos discos de instalao vamos fazer algumas alteraes no projeto ento 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 servios aqui: 1. Na pgina Application coloque o Ttulo do nosso projeto (Mapa Eletrnico) e localize o cone enviado (Geograph.ico). 2. Na pgina Compiler desmarque todas as opes dos grupos Debugging e Messages e clique no boto OK. Novamente a partir do Menu Principal, clique em Project | Build All para gerarmos o executvel final, prontinho agora feche o Delphi confirmando as modificaes realizadas no projeto.

Utilizando o Install Shield


No Delphi 1.0 para distribuir o BDE era uma complicao, existia um diretrio 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 mquina do seu Cliente (que iria instalar o sistema) criava um diretrio, colocava o executvel, 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 automtico. Mas ainda assim era um tanto primitivo, principalmente quando voc precisava mandar tudo para que o prprio cliente instalasse.

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 60/178

Com o Delphi 2.0 surgiu o InstallShield que foi mais aprimorado ainda nessa verso, ele um produto da Stirling Technologies. Que acompanha tambm o Delphi 3.0 e o Delphi 4.0. Um aviso, no tente utilizar o InstallShield que vem com o Delphi 2.0 para aplicaes do Delphi 3.0 ou 4.0, nem vice-versa, apesar de todos serem de 32 Bits so de verses totalmente diferentes. O InstallShield no que nem o Quick Report, voc precisa instal-lo em separado (ele vem no prprio CD do Delphi), aps sua instalao e execuo, voc acabar com a seguinte janela:

Esta a tela inicial para a criao do seu projeto .IWZ, informe o nome do projeto, o tipo (no caso de verses registradas) e o diretrio que ser criado, aps isso aperte o boto Create e iremos para a janela de construo do projeto:

Esta tela foi dividida em nove grandes grupos, para explicar melhor vamos analizar grupo a grupo enquanto fazemos as alteraes para a gerao do nosso pacote.

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 61/178

1. Set the Visual Design


Neste grupo esto as informaes iniciais do instalador: Na primeira parte (Application Information) voc deve informar o nome da aplicao (mapa), localizar o executvel que dever ser instalado (C:\...\Mapa.EXE), a verso (1.0) e o nome da sua empresa (Curso). Note que nesta parte montado o Diretrio que ser instalado o sistema final (<ProgramFilesDir>\Curso\Mapa). Na segunda parte (Main Window) a tela principal da instalao, aqui voc escolher o ttulo principal (Mapa Eletrnico), o Logotipo da sua Empresa (localize o BitMap Enviado: Logo.BMP), a posio 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 ateno que este o momento mais difcil, aqui voc escolher se o usurio pode ou no desinstalar automaticamente o projeto. Prontinho pode dar OK.

Importante - Assim como o Logo.BMP voc notar que no decorrer dessa montagem colocaremos vrios
Bitmap's, voc mesmo poder ger-los mas lembre-se que o InstallShield aceita apenas imagens com no mximo 16 cores.

2. Select InstallShield Objects for Delphi


Esta o grupo que mais confunde as pessoas, mas com um pouquinho de ateno 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) so as informaes principais, marque o BDE, (Observao: O SQL Links, serve apenas para conexo com bancos do tipo MS-SQL, SyBase padro DB-Lib, InterBase, Oracle, Informix, DB2 e SyBase padro CT-Lib e os pacotes de objetos servem apenas para o caso de compilaes parciais), clique no boto Settings... BDE Instalation Type - Aqui voc define seu tipo de banco de dados, infelizmente o Install no possui permisso para a distribuio da DAO 3.5, que a responsvel pela conexo nativa com o MS-Access, ista permisso adquirida apenas com a compra de qualquer ferramenta de desenvolvimento Microsoft, teremos ento que colocar na mo todos os arquivos necessrios, marque Partial BDE Installation e clique no boto Avanar. BDE Driver Types - no escolha nenhum, deixe todos desmarcados. Query Engine Types - Marque a opo SQL Engine isto far com que o BDE reconhea e envie para o gerenciados de banco de dados os comandos de SQL e clique no boto Avanar. BDE Alias - Step 1 of 4 - Clique no boto New e informe o nome do nosso Alias (AlFedera) BDE Alias - Step 2 of 4 - Esta e a tela mais enigmtica do Install, nela voc deve informar se quer que seu BDE seja configurado para aplicaes Win16/Win32 ou somente Win32, mas aqui ele no se refere a possibilidade de instalao para Windows 3.x ele apenas est se referindo ao .CFG salvo (que o arquivo de configurao do BDE 32, ento deixe desmarcado e sigamos em frente. BDE Alias - Step 3 of 4 - Aqui est todo o pulo do gato sobre a construo 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 usurio mudar o destino ? Aqui usaremos uma varivel do Install, coloque: [Program Files]\ que ser o diretrio em que ficar sua aplicao. No Type selecione MSAccess. E finalmente escreva na lista de parmetros opcionais para o Alias o seguinte: DATABASE NAME=[Program Files]\Basico.mdb BDE Alias - Step 4of 4 - Aqui voc precisa apenas clicar no boto Concluir para finalizar todas as incluses no BDE. Na segunda parte (Advanced) voc ver todas as bibliotecas que sero instaladas, apenas clique no boto OK

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 62/178

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) faa as seguintes incluses: Na pasta Program Files aperte o boto 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 necessrias para a instalao do DAO, clique no boto Add Group e coloque as seguintes informaes: Group Name: DAOSystem Destination Directory: <WINSYSDIR> Com o auxlio do boto Insert Files arraste os seguintes arquivos para esta pasta: C:\Windows\System\MSJTER35.DLL C:\Windows\System\MSJINT35.DLL C:\Windows\System\MSVCRT40.DLL C:\Windows\System\MSJET35.DLL C:\Windows\System\VBAJET32.DLL C:\Windows\System\VBAR332.DLL C:\Windows\System\OLEAUT32.DLL C:\Windows\System\STDOLE2.TLB C:\Windows\System\ODBCJT32.DLL C:\Windows\System\ODBCJI32.DLL C:\Windows\System\ODBCTL32.DLL C:\Windows\System\MSJT3032.DLL C:\Windows\System\MSJINT32.DLL C:\Windows\System\VEN2232.OLB C:\Windows\System\MSVCRT20.DLL C:\Windows\System\MSWNG300.DLL C:\Windows\System\MSRD2X32.DLL C:\Windows\System\VBDB32.DLL C:\Windows\System\MFC40.DLL C:\Windows\System\ODBC32.DLL C:\Windows\System\ODBCINT.DLL C:\Windows\System\MSRD2X35.DLL C:\Windows\System\MSREPL35.DLL Group Name: DAO Destination Directory: <CommonFilesDir>\Microsoft Shared\DAO Com o auxlio do boto 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 auxlio do boto 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 prximas partes (Components e Setup Types) so utilizadas quando voc estiver trabalhando com uma aplicao muito grande aonde existe a diviso em vrias partes, voc poder dar tambm a chance do seu cliente instalar apenas determinadas partes que o interesse.

4. Select User Interface Components


Este grupo o que comandar a instalao 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 aps iniciado o programa de instalao. Marque a opes e clique na pgina Settings e localize o arquivo Splash.bmp enviado. Para o nosso caso deixe a opo marcada.

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 63/178

Welcome Message - Esta uma janela de boas-vindas com uma mensagem para o nosso cliente sobre o sistema, infelizmente ela totalmente em ingls, s pode ser modificada na verso registrada do produto. Para o nosso caso desmarque a opo. Software Licence Agreement - Aqui esta a famosa janela da Licena de uso, ou se voc prefere das regras de uso para o nosso aplicativo, voc pode modificar o contedo criando um arquivo texto (formato .TXT) e o localizando atravs da pgina Settings, mas no poder modificar as instrues em Ingls (apenas na verso registrada). Para o nosso caso desmarque a opo. Readme Information - Aqui ser mostrado o arquivo LeiaMe inicial, novamente voc pode modificar o contedo criando um arquivo texto (formato .TXT) e o localizando atravs da pgina Settings, mas no poder modificar as instrues em Ingls (Apesar de que ela se reduz a um simples Information) se voc quiser crie-o ou ento desmarque a opo. User Information - Aqui so informaes do nosso cliente: seu nome, nome da empresa e o nmero de registro do nosso software. Para o nosso caso deixe a opo 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 opo desmarcada. Custom Setup - Esta uma subdiviso da parte anterior aonde o cliente escolher (a partir da opo Customizado da janela anterior, qual a parte que ele quer que seja instalada. Para o nosso caso deixe a opo 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 opo marcada. Start Copying Files - aqui que o cliente v todas as opes que ele escolheu anteriormente, podendo voltar atrs e modificar algo antes da instalao propriamente dita. Para o nosso caso deixe a opo marcada. Progress Indicator - Uma barra que acompanhar o processo de instalao mostrando ao cliente o quanto falta (em percentual) para a concluso da instalao. Para o nosso caso deixe a opo marcada. Billboards - So cartazes que fazem a propaganda do nosso software ou de outros que produzimos, aqui possvel colocar um para cada mdia instalada, basta apenas nome-los em SETUP1.BMP, SETUP2.BMP e assim sucessivamente dependendo do nmero de discos que produzimos. V para a pgina Settings e localize o diretrio dos bitmaps enviados (SETUP1.BMP, SETUP2.BMP e SETUP3.BMP). Para o nosso caso deixe a opo marcada. Online Registration - Muitas empresas processam o registros dos softwares de forma automtica, bastando para isso que o cliente possua um Modem, para tanto na pgina Settings identifique o nmero identificador do sistema e o nmero do telefone ou ento desmarque a opo. Setup Complete - Este o ltimo passo do processo, aqui voc pode escolher se o cliente deve dar um Reboot na mquina (que aconselhvel), ou mostrar um arquivo Leiame final, bastando para isso alterar na pgina Settings, mas de qualquer forma deixe esta opo marcada. Clique no boto OK para finalizar

5. Make Registry Changes


Esta pgina deve ser tratada com o carinho e o respeito que ela merece, pois aqui faremos as modificaes na rea de register do Windows, ento calma e muito sangue frio aqui. No queremos corromper essa rea de registro do nosso cliente.

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 64/178

Como modificamos a verso do DAO em nosso BDEAdmin para 3.5 tambm precisamos repetir essa operao na mquina que ser instalado o nosso sistema. Na pgina Registry - Keys abra a chave HKEY_LOCAL_MACHINE e clique no boto Add Key... crie a chave SOFTWARE, clique nesta nova chave e v repetindo a operao criando a seguinte estrutura: HKEY_LOCAL_MACHINE\SOFTWARE\Borland\DataBase Engine\Settings\DRIVERS\MSACCESS\INIT

Deixe marcada a ltima chave INIT e clique na pgina Registry - Values e clique no boto Add Values e proceda as seguintes alteraes:

Pronto, clique no boto OK. Agora crie a seguinte Chave na pgina Registry - Keys: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Shared Tools\DAO Crie o seguinte Valor para esta chave na pgina Registry - Values: Value Type: String Value Name: Path Value Data: <CommonFilesDir>\Microsoft Shared\DAO\Dao3032.dll Crie a seguinte Chave na pgina Registry - Keys: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Shared Tools\DAO35 Crie o seguinte Valor para esta chave na pgina Registry - Values: Value Type: String Value Name: Path Value Data: <CommonFilesDir>\Microsoft Shared\DAO\DAO350.DLL

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 65/178

6. Specify Folders and Icons


Aqui ser mostrado os cones (dos Arquivos) que sero instalados dentro do grupo escolhido, este grupo divide-se em: General - Aonde possvel 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 auxlio para a aplicao. Advanced Settings - Aqui podemos modificar o destino dos nossos arquivos, o cone, criamos uma tecla de atalho rpido para sua execuo ou at mesmo inici-lo quando o Windows for iniciado.

Importante - Para o aplicativo iniciar assim que o Windows iniciar na pgina 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 gerao do nosso pacote, escolha a midia que ser gerado e clique no boto Build, espere o trmino do processo e veja em quantas mdias foram geradas o seu pacote.

Importante - No se assuste com o nmero de disquetes (1.44Mb) normalmente apenas o BDE ocupa 2,5
disquetes ento 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 opo CD-Rom pois a ser uma nica mdia.
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 mquina que no tenha o Delphi instalado.

Importante - Gere seu pacote em disquetes de 1.44Mb e copie para os disquetes para proceder a instalao assim
voc poder acompanhar a mudana das telas a cada disquete solicitado.

Importante - No se esquea 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 mdia selecionada.

Finalmente
Agora voc j pode mandar todo o seu projeto para aquele cliente especial, basta apenas embal-lo e despachar com as famosas instrues:

Como Instalar
O Mapa Eletrnico s pode ser consultado depois de instalado no seu Microcomputador, sob o ambiente Windows 95 ou superior. Para realizar a instalao siga essas instrues:

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 66/178

1. Ligue o Microcomputador ativando o Windows 2. Introduza o disquete marcado como INICIAL na unidade de leitura 3. Clique no boto INICIAR e escolha a opo EXECUTAR 4. Digite ento A:\SETUP (ou no lugar do A, a letra equivalente ao drive da sua unidade de leitura do disquete). 5. Click sobre o boto OK e execute as instrues do Instalador. Acredito que seu usurio no errar esses 5 passos. Um abrao e at a prxima.

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 67/178

Curso de Delphi 4.0 - Apostila 05


Autor: Fernando Antonio Fernandes Anselmo E-Mail: fernandoanselmo@yahoo.com.br
Pr-Requisitos: Windows 98 Delphi 4.0 verso Client/Server Suite BDE 5.00 MS-Access 97 Arquivos trabalhados juntos com esta apostila: SQL.WRI

Prefcio
O nosso projeto para essa apostila ser um tanto bobinho, mas uma imensa mo na roda para testarmos nossos aplicativos futuramente, noto que a maioria das pessoas quando comeam a programar em Delphi, temem o maior de todos os pesadelos: o SQL (Structured Query Language), so apenas trs letrinhas mas que confundem e complicam a vida da maioria dos programadores, um conselho dominando essa simples (porm complexa) linguagem, garanto que ser a diferena entre um sistema que apresentar facilidades imensas e dar poderes extraordinrios para o nosso usurio, basicamente a linguagem SQL contm 4 comandos: - SELECT - INSERT - UPDATE - DELETE Na apostila em anexo, enviada junto com esta, explica-se exatamente a funo de cada comando, aqui vamos nos ater ao Delphi, ento vamos comear 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 comearmos), vamos para as nossas receitas de bolo, siga um passo atrs do outro, mas antes de comear crie uma pasta que abrigar seu projeto, por exemplo Gera SQL. 1. Na Component Pallete localize uma pgina chamada Standard e dentro dessa pgina 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 ordenao 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 padro de uma janela de mensagens) 3.2. Caption: Executa instrues SQL (Contedo da tarja do formulrio) 3.3. Name: F_SQL (Nome interno do formulrio) 3.4. Position: poScreenCenter (Far com que o formulrio fique sempre centralizado quando for executado) 4. D uma salvadinha no seu projeto, para tanto, no menu v em File | Save All...:

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 68/178

4.1. Aonde aparece Unit1.pas (o Delphi est se referindo do nome do formulrio) mude para fSQL.PAS 4.2. Aonde aparece Project1.dpr (o Delphi est se referindo do nome do projeto - que ser o nome do executvel final) mude para GerSQL.DPR 5. Na Component Pallete novamente na pgina Standard e localize agora o objeto Memo (acredito que seja o quinto) e atravs da Object Inspector altere as seguintes propriedades: 5.1. Lines: Clique nos ... e elimine todo o seu contedo 6. Precisamos agora de trs 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 trs cliques no Form, coloque-os acima dos trs 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 trs objetos: 8.1. Font: Clique nos "..." e faa as seguintes alteraes na janela de Fonts: 3.41. Cor: Castanho 3.42. Estilo: Negrito 8.2. Caption: Altere para cada um respectivamente: Selecione o Alias: Tabelas Disponveis: Digite a clausula SQL 9. Na Component Pallete v para a pgina Addicional e localize agora o objeto SpeedButton (acredito que seja o segundo) e traga dois para o form e atravs 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 boto fique liso no form) 9.3. Hint: Altere para cada um respectivamente: Executa a instruo SQL Limpa a instruo SQL 9.4. ShowHint: True 9.5. Name: Altere para cada um respectivamente: ButExecuta ButLimpa 10. Na Component Pallete v para a pgina Data Access e localize agora o objeto Query (acredito que seja o terceiro) 11. Na mesma pgina Data Access e localize agora o objeto DataSource (acredito que seja o primeiro) e atravs da Object Inspector altere a propriedade: 11.1. DataSet: Query1 (faz a ligao com um objeto Query ou Table) 12. Para finalizar na Component Pallete v para a pgina Data Controls e localize agora o objeto DbGrid (acredito que seja o primeiro) e atravs da Object Inspector altere a propriedade: 12.1. DataSource: DataSource1 (faz a ligao com um objeto DataSource) 13. Terminamos, compare como ficou:

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 69/178

Codificando
Tudo pronto, basta apenas meter a mo no programa, mas vamos devagar, a idia deste projeto apesar de simples pode parecer um pouco complicada, inicialmente ser mostrado todos os alias que existem no BDE Administrator aps a escolha de qualquer um deles, sero mostradas as tabelas disponveis, agora basta apenas digitar as instrues SQL no objeto MEMO1 e pressionar o boto para execut-lo. 14. Localize na Object Inspector o objeto F_SQL, mude para a pgina 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 cdigo: 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 pgina 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 cdigo: 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 no resolvida Screen.Cursor := crHourGlass; for i := 0 to (ListaAlias.Items.Count - 1) do if ListaAlias.Selected[i] then begin

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 70/178

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; No se preocupe em no entender nada aqui, muito desses comandos sequer foram falados, ento vamos por partes, o evento disparado assim que qualquer dos Alias da nossa lista for selecionado: 1. Verificao (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 nmero 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 lao 4. Modifica novamente o cursor para o formato padro

Importante - Existem dois comandos que cancelam laos de repeties (Comandos For, While e Repeat) so
eles: Break - Interrompe o lao mandando o comando para o prximo comando aps o lao. Exit - Interrompe o lao terminando o procedimento ou funo. O comando Break s pode ser usado dentro de um lao de repetio enquanto que o comando Exit pode ser usado dentro de procedimentos ou funes livres de um lao de repetio. 16. Localize na Object Inspector o objeto ButExecuta e na pgina 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 cdigo: 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('Instruo Executada...', mtInformation, [mbOk], 0); except MessageDlg('Comando SQL est invlido', mtError, [mbOk], 0); end; end; end; Aqui at que poderia ser tudo simples, mas para possibilitar que o usurio 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 trs comandos indicados anteriormente diferentemente do comando SELECT no geram o que chamamos em SQL de uma cadeia de cdigos, ou seja, eles no me do uma resposta em uma lista, ento no posso utilizar-me do comando OPEN para eles, ao invs disso preciso usar o comando EXECSQL que apenas dispara esses comandos para o banco de dados, no gerando nenhuma espcie de retorno e para sorte o EXECSQL suporta o comando SELECT.

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 71/178

Alm desse problema o usurio 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 proteo try...except...end; esses comandos protegem os cdigos que esto 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 instruo entre o except...end; Vamos dar uma olhada ento como ficou a lgica do procedimento: 1. Verifica se a query1 est aberta se estiver fecha ela 2. Limpa o parmetro lines da Query1 3. Transfere o contedo das linhas do Memo1 para dentro do SQL da Query1 4. Abre um bloco de proteo 4.1. Executa o comando SQL 4.2. Ativa um novo bloco de proteo 4.2.1. Abre a Query1 4.2.2. Em caso de erro no bloco de proteo apenas segura e no faz nada 4.3. Mostra uma mensagem dizendo que est tudo bem 5. Em caso de erro no bloco de proteo coloca uma mensagem de alerta Observao Interessante: Existe tambm o bloco de proteo try...finally...end; que protege os comandos, e acontecendo ou no o erro executa obrigatoriamente os comandos localizados entre o finally...end; 17. Localize na Object Inspector o objeto ButLimpa, na pgina 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 cdigo: procedure TF_SQL.ButLimpaClick(Sender: TObject); begin Memo1.Lines.Clear; end; Agora ficou fcil, a nica funo deste boto limpar o contedo do objeto Memo1. 18. Localize na Object Inspector o objeto F_SQL, na pgina 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 cdigo: procedure TF_SQL.FormClose(Sender: TObject; var Action: TCloseAction); begin with Query1 do if Active then Close; end; Aqui tambm 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 observao, escreva um cdigo esquisito para o objeto Memo1 (por exemplo digite: Maria tinha um carneirinho... e clique no boto para executar o SQL note que automaticamente o Delphi interrompe a execuo do programa e assume o controle, basta apenas voc disparar F9 para continuar, no se preocupe isso acontece apenas em modo Run-Time se voc executar o aplicativo fora do Delphi voc no 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 pgina Preferences no bloco Debugging desative a opo Break on Exception.

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 72/178

Curso de Delphi 4.0 - Apostila 06


Autor: Fernando Antonio Fernandes Anselmo E-Mail: fernandoanselmo@yahoo.com.br
Pr-Requisitos: Windows 98 Delphi 4.0 verso Client/Server Suite BDE 5.00 MS-Access 97

Prefcio
Salve, antes de comearmos devo dizer que este ser o projeto mais longo e completo que j fizemos no decorrer deste curso, atualmente no existe mais a figura do programador, aquele cara que sentava atrs de um teclado e ficava simplesmente desenvolvendo programas maravilhosos que o usurio acabava achando confuso e complicado de usar. Ento porque fazer um curso de Delphi (ou qualquer outra ferramenta) apenas para apenas aprendermos a linguagem ? Sendo que seria muito mais fcil consultar o manual. Com base nisso ao invs de me restringir a apenas ensinar macetes e dicas quentes, vou tentar algo mais "ousado" a partir de agora, tentar dar uma viso do mundo externo para vocs com projetos reais. Vale uma pequena observao aqui: Apesar de todos os dados se aproximarem o mximo possvel da realidade todas as empresas que sero abordadas e criadas aqui sero totalmente fictcias, caso numa dessas loucuras da vida a empresa exista (cada dia criado uma nova mesmo) todos os dados foram criados exclusivamente por imaginao e no existe nenhuma relao com a realidade. Comearemos desde a fase da entrevista com os usurios responsveis at a finalizao com a instalao dos mdulos, portanto dividi este projeto em diversas apostilas, a de hoje considero a mais chata, mas em compensao a mais importante, para quem gosta de colocar a mo 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 Concentrao para Gordinhos), mas teve um pequeno problema no caminho, Ela (a empresa) no sabe qual o tipo de sistema que quer, mas a idia basica de que se precisa : De um cadastro organizado e completo de cada cliente; De um controle individual da criao dos programas alimentares; e De um acompanhamento ps-programa do Cliente. Ento foram realizadas trs entrevistas, a primeira com o mdico-diretor geral da Empresa que recebe e define o programa do cliente, a segunda com o responsvel pelos cardpios da alimentao e a terceira com o mdico nutricionista da empresa responsvel pelo acompanhamento ps-programa. A seguir voc encontrar a sntese dessas entrevistas.

Projeto 4 - Analizando o SPA Antes & Depois Cia.


1 Dia de entrevistas com o usurio: Programao alimentar para o emagrecimento
Um novo hbito 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 hbito alimentar, que ir assegurar a manuteno do peso ideal aps o final do tratamento. J sabemos que 90% das pessoas que fazem uma dieta para emagrecer recuperam

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 73/178

depois todo o peso perdido. Sabemos tambm que ficar engordando e emagrecendo pior para a sade do que simplesmente manter-se obeso. Devemos, portanto, buscar sempre um resultado definitivo, que permitir a manuteno do peso dentro de uma faixa ideal. Esquea aquela idia antiga do emagrecimento atravs de dietas, que representavam um perodo de sacrifcio, fome, fraqueza e mau humor. As pessoas deixavam inclusive de comparecer a festas e reunies sociais que pudessem representar uma ameaa ao seu programa alimentar rigoroso. Flexibilidade. A tendncia mundial tem sido de recomendar programas alimentares flexveis, onde as quantidades planejadas de cada alimento no precisam ser rigorosamente respeitadas nem o paciente obrigado a evitar compromissos sociais onde alimentos "proibidos" sero servidos. Algumas comidas devem ser evitadas, ou consumidas com moderao, principalmente as mais gordurosas. Alimentao sob-medida. Cada pessoa precisa de um determinado programa alimentar para emagrecer de forma saudvel e equilibrada. Existem frmulas para se calcular a quantidade de calorias a ser ingerida diariamente. Infelizmente, este mtodo muito falho, j que no leva em conta as grandes variaes de gasto metablico de uma pessoa para outra. Este gasto energtico s pode ser medido atravs de aparelhos sofisticados e caros, que so utilizados apenas em trabalhos de pesquisa. Existem, no entanto, maneiras prticas 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 metablico baixo. Sua alimentao dever conter entre 1000 e 1200 Kcal para que o tratamento no seja muito demorado. J uma pessoa que tenha engordado porque ingere uma quantidade exagerada de calorias e conta que emagreceu rapidamente durante um perodo de conteno 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 no podem emagrecer porque tm um horrio 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 alimentao adequada que se adapte ao seu estilo de vida, respeitando seus hbitos e seu paladar. Equilbrio. Emagrecer no fechar a boca. A alimentao deve ser voltada para o equilbrio do metabolismo. Alm de conter uma quantidade adequada de calorias, elas devem estar distribudas em propores apropriadas, entre carboidratos, protenas e gorduras. Para isso, voc precisar conhecer a composio dos alimentos, consultando a tabela de alimentos equivalentes ou o dicionrio. Tambm importante distribuir adequadamente as refeies. Os horrios no precisam ser obedecidos rigorosamente, mas no se deve ficar mais de 4 horas sem comer. Um programa de alimentao ideal deveria conter 6 refeies dirias - desjejum (caf da manh), colao (refeio ligeira entre o desjejum e o almoo), almoo, lanche, jantar e ceia. Se voc tem o hbito de dormir logo aps o jantar, no necessrio incluir a ceia. muito comum as pessoas saltarem refeies sempre que esto sem fome, tentando desta forma obter resultados mais rpidos, o que no recomendvel. Uma parte importante do nosso gasto energtico vem da prpria metabolizao dos alimentos.

2 Dia de entrevistas com o usurio: Como so montados os cardpios


A tabela de alimentos equivalentes uma lista de substituies, que deve ser sempre consultada para que a alimentao no se torne montona. Lembre-se que o objetivo principal o desenvolvimento de um novo hbito alimentar. Comendo todo dia as mesmas coisas voc no estaria evoluindo na busca de um comportamento alimentar diferente daquele que o levou a engordar. Atravs da tabela voc poder substituir os alimentos vontade, sempre dentro de um mesmo grupo, onde o teor calrico e a proporo de carboidratos, protenas e gorduras sero semelhantes (equivalentes). Conhecendo as possibilidades de substituies que a tabela oferece, voc mesmo poder elaborar seu cardpio, mantendo-o sempre atrativo e saboroso. Alm disso, voc estar apto a manipular sua alimentao para adapt-la s mais diversas ocasies, como jantares festivos, refeies rpidas, churrascos e qualquer circunstncia que o obrigue a sair da rotina. A seguir voc ver os 8 grupos bsicos na composio de dietas para emagrecimento. Grupo 1 VEGETAIS DE BAIXSSIMO TEOR CALRICO ABOBRINHA ALFACE BRCOLIS ESCAROLA NABO REPOLHO TOMATE ACELGA ALMEIRO CARURU ESPINAFRE PEPINO SALSO AGRIO AZEDINHA CHICRIA MAXIXE PIMENTO SERRALHA AIPO BERTALHA COUVE NABIA RABANETE TAIOBA

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 74/178

Grupo 2 VEGETAIS DE BAIXO TEOR CALRICO (2 colheres das de sopa equivalem a 1 poro) ABBORA CEBOLA COUVE-FLOR VAGEM Grupo 3 FRUTAS ABACAXI - 1 RODELA PEQUENA GUA DE COCO - 1 COPO PEQUENO AMORA - MEIO COPO BANANA MA - 1 PEQUENA BANANA PRATA - 1 PEQUENA CAJU - 1 MDIOCAQUI - 1 PEQUENO CEREJA - 6 FRUTAS FIGO - 1 MDIO FRUTA-DE-CONDE - MEIA FRUTA GRAPEFRUIT - MEIA FRUTA JACA - 4 BAGOS JAMBO - 4 FRUTAS LARANJA - 1 PEQUENA MA - 1 MDIA MANGA - 1 PEQUENA MELANCIA - 1 FATIA MDIA MORANGO - 10 FRUTASNECTARINA - 1 MDIA PASSA - 1 COLHER DE SOPA PSSEGO - 1 MDIO ROM - MEIA FRUTA TMARA - 2 MDIAS UVA - 10 FRUTAS Grupo 4 CEREAIS, PES, BISCOITOS E MASSAS AIPIM - 1 PEDAO MDIO AVEIA - 3 COLH. DE SOPA BATATA INGLESA - 1 MDIA BOLACHA GUA E SAL - 2 EMPADA - 1 PEQUENA FAROFA - 1 COLH. DE SOPA GERME DE TRIGO - 3 COLH. DE SOPA LASANHA - 2 COLH. DE SOPA MACARRO - 2 COLH. DE SOPA MILHO VERDE - 4 COLH. DE SOPA PANQUECA - 1 PEQUENA PO DE FORMA - 1 FATIA PO INTEGRAL - 1 FATIA PASTEL - 1 MDIO PIRO - 2 COLH. SOPA TORRADA - 6 DAS PEQUENAS Grupo 5 CARNES, QUEIJOS E OVOS CABRITO - 1 TERO DE BIFE CARNEIRO - 1 TERO DE BIFE CAVIAR - 1 COLHER DE SOBREMESA DOBRADINHA - 2 COLH. DE SOPA FONDUE DE QUEIJO - 25 GRAMAS CAMARO - 2 MDIOS CARNE SECA - 1 PEDAO PEQUENO COELHO - MEIO BIFE FGADO - 1 TERO DE BIFE FRANGO - 1 TERO DE BIFE ARROZ - 2 COLH. DE SOPA BATATA DOCE - 1 PEQUENA BISCOITO CREAM CRACKER - 2 CORN FLAKES - 1 COLH. DE SOPA FARINHA - 2 COLH. DE SOPA FEIJO - 4 COLH. DE SOPA GRO DE BICO - 2 COLH. DE SOPA LENTILHA - 2 COLH. DE SOPA MAISENA - 1 COLH. DE SOPA NHOQUE - 2 COLH. DE SOPA PO DE CENTEIO - 1 FATIA PO DE GRAHAM - 1 FATIA PO FRANCS - MEIO PEQ. PIPOCA - 1 PACOTE PEQ. PIZZA - 1 FATIA PEQUENA TREMOOS - 3 COLH. DE SOPA ACEROLA - 1 PEQUENA MEIXA - 2 MDIAS BANANA D'GUA - MEIA FRUTA BANANA OURO - 1 PEQUENA CAJ-MANGA - 1 PEQUENO CARAMBOLA - 1 MDIA DAMASCO - 2 MDIOS FRAMBOESA - 10 FRUTAS GOIABA - 1 PEQUENA JABUTICABA - 10 FRUTAS KIWI - 1 MDIO LIMA DA PRSIA - 1 PEQUENA MAMO - 1 FATIA PEQUENA MARACUJ - 1 PEQUENO MELO - 1 FATIA PEQUENA NSPERA - 3 PEQUENAS PERA - 1 PEQUENA PITANGA - MEIO COPO SALADA DE FRUTAS - 3 COLHERES TANGERINA - 1 MDIA ASPARGO CENOURA ERVILHA BERINGELA CHUCHU PALMITO BETERRABA COGUMELO QUIABO

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 75/178

LAGOSTA - 1 PEDAO PEQUENO LULA - 1 PORO MDIA MORTADELA - 2 FATIAS FINAS OVO DE CODORNA - 3 UNIDADES PAIO - 1 PEDAO PEQUENO PERU - 1 TERO DE BIFE POLVO - 1 PORO MDIA QUEIJO - 1 FATIA REQUEIJO - 1 COLHER DE SOPA SALAME - 1 FATIA PEQUENA SIRI - 3 DE TAMANHO MDIO 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 Grupo 7 LEITES COALHADA - MEIO COPO IOGURTE DIET - 2 FRASCOS LEITE INTEGRAL - MEIO COPO PUDIM DIET - 1 PEQUENO

LINGUIA - 1 PEDAO PEQUENO MEXILHO - 1 PORO PEQUENA OSTRAS - 1 PORO PEQUENA OVO DE GALINHA - 1 UNIDADE PATO - 1 TERO DE BIFE PEIXE - MEIA POSTA PEQUENA PRESUNTO MAGRO - 2 FATIAS QUEIJO COTTAGE - 2 COLHERES RICOTA - 2 FATIAS FINAS SALSICHA - 1 PEQUENA VACA - 1 TERO DE BIFE

AZEITONA - 4 MDIAS CREME DE LEITE - 1 COLH. DE SOPA MAIONESE LIGHT - 2 COLH. DE CH MARGARINA - 1 COLHER DE CH PAT - 1 COLHER DE CH

IOGURTE NATURAL - 1 COPO LEITE DESNATADO - 1 COPO LEITE INTEGRAL EM P - 1 COLHER SORVETE DIET - 1 BOLA

Grupo 8 BEBIDAS, CONDIMENTOS E DIETTICOS DE BAIXSSIMO TEOR CALRICO ADOANTES CH ERVA-DOCE LIMONADA REFRIG. DIETTICOS ALHO CEBOLINHA GELATINA DIETTICA MATE SAL CAF COMINHO HORTEL ORGANO SALSA CANELA CRAVO LIMO PIMENTA VINAGRE

A unidade bsica da tabela chamada poro, que a quantidade de cada alimento listado em um grupo. Um exemplo: Se o seu programa alimentar tem no almoo 2 pores do grupo 4, voc poder consumir: 1 colher de arroz + 1 colher de farofa ou 2 fatias de po de forma ou batata inglesa + 1 panqueca e assim por diante. Se no almoo voc tambm tem 3 pores do grupo 5, pode comer alm daqueles alimentos: 1 bife de tamanho mdio (cada poro corresponde a um tero de bife) ou 1 posta de peixe + 1 ovo ou 2 fatias de queijo (cada poro d para 1 fatia) + 2 fatias de presunto e assim por diante. No 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 reduo do teor de carboidratos da refeio, podendo desregular os mecanismos cerebrais de regulao do apetite. Por outro lado, pode-se transferir um determinado alimento de uma refeio para outra, desde que seja mantida em todas as refeies pelo menos uma poro dos grupos 3 ou 4, que contm mais carboidratos. Apenas os alimentos listados nos grupos 1 e 8 podem ser consumidos vontade, j que seu teor calrico considerado desprezvel. Mesmo nas refeies onde estes grupos no forem mencionados, os alimentos neles contidos podem ser consumidos sem restries.

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 76/178

Os grupos 1 e 2 apresentam a vantagem de acrescentar fibras alimentao, alm de serem pobres em calorias. Os alimentos do grupo 3 so as frutas, constitudas basicamente de carboidratos. No est relacionado o abacate, por possuir um elevado teor de gordura. Tambm os alimentos do grupo 4 so constitudos 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 esto listados os alimentos constitudos por protenas e gorduras. O teor de gorduras, no entanto, varivel. Os queijos brancos, como a ricota, o cottage e o prprio queijo tipo Minas so menos gordurosos que os outros. Tambm as carnes brancas so menos gordurosas que as vermelhas. Cuidado com a pele dos peixes e do frango, porque onde se armazena a gordura. Crustceos como o camaro e a lagosta so ricos em colesterol, assim como a gema dos ovos. Sempre que possvel 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 possvel. No grupo 7 esto o leite e seus derivados. Por serem menos gordurosos, deve-se dar preferncia aos desnatados. No grupo 8 esto listados vrios alimentos, temperos e bebidas cujo teor calrico desprezvel. Apesar de no engordarem, seu consumo excessivo pode trazer outros males sade. O caf, por exemplo, pode causar insnia quando ingerido em demasia, enquanto os refrigerantes e temperos podem levar a problemas gstricos. As bebidas alcolicas esto listadas na tabela abaixo, com seus respectivos teores calricos. Elas no podem substituir nenhum alimento de outro grupo, porque seu valor nutritivo no o mesmo. Grupo 9 BEBIDAS ALCOLICAS BEBIDA Cachaa Cerveja Champanhe Conhaque Gim Rum Usque Vinho branco seco Vinho branco doce Vinho tinto Vodka Grupo 10 DOCES O teor calrico dos doces muito varivel, dependendo principalmente do seu contedo de gorduras. Na tabela abaixo voc encontra o teor calrico mdio 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 QUANTIDADE 1 UNIDADE 1 UNIDADE 1 UNIDADE 1 FATIA 1 UNIDADE 1 UNIDADE 1 UNIDADE 1 UNIDADE 1 PEQUENO 2 COLHERES DE SOPA VALOR CALRICO 20 kCAL 450 kCAL 40 KCAL 200 kCAL 200 KCAL 120 kCAL 50 kCAL 20 kCAL 160 kCAL 200 kCAL QUANTIDADE 1 dose de 50 ml 1 copo com 300 ml 1 copo com 100 ml 1 copo com 50 ml 1 copo com 50 ml 1 copo com 50 ml 1 copo com 50 ml 1 copo com 100 ml 1 copo com 100 ml 1 copo com 100 ml 1 copo com 50 ml VALOR CALRICO 120 Kcal 140 Kcal 110 Kcal 120 Kcal 130 Kcal 120 Kcal 120 Kcal 90 Kcal 140 Kcal 70 Kcal 120 Kcal

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 77/178

GELATINA GELIA GOIABADA MILK SHAKE McDonald's MOUSSE DE CHOCOLATE PSSEGO EM CALDA PUDIM SONHO SUNDAE (McDonald's) SUSPIRO TORTA

1 CAIXA 70 kCAL 1 COLHER DE SOBREMESA 30 kCAL 1 PEDAO 80 KCAL 1 UNIDADE 340 kCAL 1 POTE PEQUENO 200 KCAL 1 METADE 80 kCAL 1 FATIA 250 kCAL 1 UNIDADE 150 KCAL 1 UNIDADE 260 kCAL 1 GRANDE 70 KCAL 1 FATIA 250 kCAL

Sempre que possvel, recomenda-se dar preferncia aos dietticos, que no contm acar. importante lembrar, no entanto, que muitos deles, mesmo no contendo acar, so altamente calricos, como o caso dos chocolates. Cardpio com 800 Kcal REFEIO Desjejum (caf da manh) Colao (lanche da manh) Almoo Lanche Jantar Ceia Cardpio com 1.000 Kcal REFEIO Desjejum (caf da manh) Colao (lanche da manh) Almoo Lanche Jantar Ceia Cardpio com 1.200 Kcal REFEIO Desjejum (caf da manh) Colao (lanche da manh) Almoo Lanche Jantar Ceia Cardpio com 1.500 Kcal REFEIO Desjejum (caf da manh) Colao (lanche da manh) Almoo Lanche Jantar Ceia Cardpio com 1.800 Kcal REFEIO Desjejum (caf da manh) Colao (lanche da manh) Almoo Lanche Jantar Ceia PORES 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 PORES 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 grup 3 1 do grupo 3 PORES 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 grup 3 1 do grupo 3 PORES 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 grup 3 1 do grupo 7 + 1 do grupo 3 PORES 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 1 do grupo 3

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 78/178

Obs.: Os grupos 1 e 8 podem ser utilizados vontade, em qualquer horrio e em qualquer cardpio.

3 Dia de entrevistas com o usurio: Conversa com o nutricionista


O que o peso ideal ? Peso ideal aquele que propicia o mximo de sade. O conceito atual de sade, segundo a Organizao Mundial de Sade "Estado de bem-estar fsico, mental e social". Estes 3 elementos devem ser, portanto, valorizados por quem tenta definir o peso ideal de um determinado indivduo. Mtodos de clculo do peso ideal. O clculo do peso ideal deveria ser feito, idealmente, atravs da medida do percentual de gordura corporal, que pode ser obtida por mtodos como a bioimpedncia ou pela medida das dobras cutneas. Como na maioria dos casos estes mtodos no esto disponveis, 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.

Por exemplo: uma pessoa que pese 67 Kg e mea 1,64m, tem um IMC de 24,9 Kg/m2,(67 divididos pelo quadrado de 1,64). NDICE DE MASSA CORPORAL = PESO ( em Kg ) / ( ALTURA em metros ) 2 Apesar de no discriminar os componentes gordo e magro da massa corporal total, o mtodo mais prtico para avaliar o grau de risco associado obesidade. Os estudos populacionais mostram que o menor risco de mortalidade corresponde faixa de IMC que vai dos 20 aos 25 Kg/m2. Entre 25 e 30 j se observa um aumento do risco. Os pacientes que a se situam so 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 "obesidade mrbida". Abaixo dos 20 Kg/m2 tambm se observam maiores ndices de mortalidade, principalmente por doenas pulmonares e desnutrio. Esto nesta faixa, por exemplo, os portadores de anorexia nervosa. A faixa ideal, portanto, situa-se entre 20 e 25 Kg/m2. O indice de massa corporal por faixas de risco

Veja aqui o grfico 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 so largamente utilizadas em todo o mundo para estimar-se o peso ideal. Elas so derivadas de dados obtidos por companhias de seguro americanas, que as desenvolveram a partir da observao de dados de mortalidade e longevidade de sua populao segurada. Os pesos chamados de "ideais" so, na verdade, mdias das faixas de peso ideal para cada grupo etrio analisado. As tabelas abaixo mostram os pesos de referncia para cada um destes grupos. Reparem que na tabela dos indivduos mais idosos estes pesos j so bem mais altos.

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 79/178

Pesos de referncia 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 1,83 1,85 1,88 1,91 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 73,9 75,3 76,9 78,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 -

Pesos de referncia 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 mtodos utilizados para o clculo do peso ideal de adultos no so adequados para indivduos em fase de crescimento. Observaes finais Alm dessas trs entrevistas foi constatado que o SPA Antes & Depois ainda mantm

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 80/178

alguns dados importantes: Manuteno peridica da Pasta do Cliente que contm: Dados para o envio de eventual correspondncia de propaganda e promoes. Dependendo do plano adotado - acompanhamento nutricional e envio de um cardpio semanal personalizado e completo, baseado no plano de calorias indicado pelo nutricionista. Histrico dos planos realizados pelo cliente no SPA. No so aceitos clientes menores de 21anos e maiores de 74 anos de idade. Descontos para clientes com re-incidncia, baseado na seguinte tabela: 5% primeira re-incidncia. 10% segunda re-incidncia. 15% terceira re-incidncia. Aumento de 1% nas prximas re-incidncias at um mximo de 20%.

Os planos da empresa so: Plano A (Anti-Stress) - 3 Dias. Plano B (Reeducao) - 1 Semana com acompanhamento peridico de 3 meses. Plano C (Completo) - 1 ms. Plano D (Especial de Reeducao) - 4 Dias com acompanhamento peridico de 3 meses. A diviso do capital da empresa realizada em cima do preo final do cliente, e dividido da seguinte maneira: 20% para o mdico-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 ms criado um relatrio de fechamento financeiro com a situao da empresa e a diviso do capital do ms. Finalmente Prontinho na prxima apostila, criaremos nosso projeto fsico baseado em tudo o que foi feito aqui, o projeto fsico servir para montarmos nossa base de dados e termos uma idia qual o caminho que seguir nosso sistema. Ento aconselho a voc que releia as entrevistas com calma e comee a pensar no apenas como uma chave de fenda mas como a caixa de ferramentas completa que no s senta na mquina e comea a programar mas analisa e verifica o que o usurio realmente necessita.

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 81/178

Curso de Delphi 4.0 - Apostila 07


Autor: Fernando Antonio Fernandes Anselmo E-Mail: fernandoanselmo@yahoo.com.br
Pr-Requisitos: Windows 98 Delphi 4.0 verso Client/Server Suite BDE 5.00 MS-Access 97 Arquivos trabalhados juntos com esta apostila: BASICO.MDB

Prefcio
Salve, espero que todos vocs tenha gostado do rumo que tomou o nosso curso, tambm espero que assim fique mais interessante e atual o uso de uma linguagem to complexa como o Delphi. Vale uma pequena observao aqui (copiada da apostila anterior, para ficar bem claro): Apesar de todos os dados se aproximarem o mximo possvel da realidade todas as empresas que sero abordadas e criadas aqui sero totalmente fictcias, caso numa dessas loucuras da vida a empresa exista (cada dia criado uma nova mesmo) todos os dados foram criados exclusivamente por imaginao e no existe nenhuma relao com a realidade. J estamos com todos os dados da nossa empresa na mo, agora vem a fase que antigamente era designada exclusivamente para a nata da informtica conhecida por: Analistas de Sistemas, quantas vezes no sonhamos com esse maravilhoso e imponente ttulo. Bem, uma coisa devemos aprender: "Atualmente quem na rea de informtica no chuta nas onze, no se d muito bem e acaba vendendo cachorro-quente na porta da Igreja", ento quem acha que aprendendo Delphi, ou qualquer outra ferramenta de desenvolvimento, e a nica coisa que vai ter que fazer daqui para frente, so programas j prontos e detalhados logicamente sem ter que usar qualquer conhecimento de um Analista de Sistemas, pode comeando a pensar seriamente a mudar de profisso. bvio que experincia nunca vou conseguir passar para todos, principalmente porque esta vida um eterno aprendizado, mas vou tentar dar algumas dicas para vocs comearem a pegar o embalo.

Brain-Storm
Na entrevista ouvimos algumas palavras chaves, ento 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; Criao dos programas alimentares; Acompanhamento do Cliente; Cada cliente precisa de um determinado programa; Existem frmulas para se calcular a quantidade de calorias, este mtodo muito falho; O paciente relata na consulta e sempre haver uma maneira de planejar uma alimentao adequada; Existe uma tabela de alimentos; Existem cardpios formados atravs 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 divises entre 21 - 55 e 55 - 74 anos; Excluem-se menores de 21 e maiores de 74 anos; e Clculos de receitas e despesas atravs de demonstrativos mensais e resumo anual.

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 82/178

Est tcnica melhor quando a equipe formada por trs ou mais pessoas, uma coisa se voc do tipo que detesta o trabalho em grupo, infelizmente voc ser um pssimo Analista, pois 98% do trabalho feito com discusses em grupo, debates e anlises com a equipe e com o usurio, validando e revalidando periodicamente todos os dados levantados, at que o sistema esteje entregue e pronto. O mtodo que mostrei acima conhecido por Brain-Storm (Tempestade Cerebral) a idia que voc recolha os dados mais importantes e discuta em cima deles, existem bvio vrios mtodos de anlises, mas pessoalmente, considero este o melhor, adote aquele que voc sinta mais a vontade.

Preparao da Modelagem dos Dados


A prxima fase conhecida como Modelagem dos Dados, aqui vamos definir nossas entidades (antigamente chamariamos de tabelas, mas prefiro adotar uma linguagem mais atual), faa um jogo com voc mesmo antes de ler os atributos de cada entidade (campos) propostos por mim, tente montar seus prprios atributos: Entidade Cliente Atributos: CPF, Nome, Endereo, Bairro, CEP, Cidade, Estado, eMail, Telefones de contato, Altura, Peso medido e data de nascimento. Entidade Alimento Atributos: Nmero do Grupo, Nome do Alimento e Quantidade Permitida Entidade Pasta do Cliente Atributos: CPF do Cliente, Data, Plano Adotado, Quantidade de Calorias, Observaes do tratamento, Data de pagamento, Valor Total e Desconto concedido Entidade Resumo Mensal Atributos: Mes e Ano, Valor do Mdico, Valor Coordenador, Valor Nutricionista e Valor Despesa

Importante - Dicas Quentes:


- No d o nome de uma entidade no plural, por exemplo Clientes, Alimentos pois alm 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 normalizao. - No invente entidades ou atributos que no fazem parte do que foi levantado com os usurios, lgico que os clientes devem ter uma profisso, mas isso no interessa para nosso sistema, se achar que interessa discuta primeiro com o usurio. - Evite sempre cdigos estranhos ao cliente para definir Chaves nicas (aquelas que serviro de ndices primrios), primeiro procure por campos nicos na prpria entidade, na entidade Cliente podemos usar o CPF.

Modelo Fsico
Terminada a fase de Preparao da Modelagem, iniciado todo o trabalho para a construo de um modelo fsico, ou seja, como realmente vai ficar implantado nossa base de dados, neste momento valem todas as regras de Normalizao e outras tcnicas aprendidas em qualquer bom Curso de Anlise ou Livros disponveis no mercado, como minha funo ensinar o Delphi no vou me ater a estes detalhes ento vamos dar uma olhada no Modelo Fsico pronto e depois farei alguns comentrios necessrios:

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 83/178

Bem aqui valem algumas regras que aprendi ao longo do tempo:

1. Formao dos Nomes dos Atributos:


O maior trabalho de uma empresa de desenvolvimento formar o nome dos atributos, pois sabemos que eles influenciaro no nome das variveis, assim ao longo do tempo, e aps vrios aperfeioamentos cheguei a uma regra que venho adotando: XXX_YYYYY - aonde: XXX - Trs casas representativas do atributo, Ex: NOM - Nome, NUM - Nmero, VAL - Valor, DAT - Data, DES Descrio, ... YYYYY - Complemento do Atributo, Ex: Nome da Prpria Entidade, Nomes Significativos, ...

2. Quanto ao Tipo do Atributo:


Uma dica que aprendi a muito tempo ainda vale at hoje, escolha os tipos com lgica e utilidade, quer um exemplo ento responda as seguintes perguntas: O que mais til e lgico um atributo CPF (NUM_CPF) ser Texto com 11 casas ou um Inteiro ? Se vamos fazer clculos com a Altura do Cliente (ALT_CLIENTE) ento definiremos o atributo como Texto ou Inteiro com casas decimais ? Se a observao do clientes (OBS_PASTA) pode variar muito o que mais prtico um campo Texto Varivel ou um Texto fixo de 300 casas ? Todas as quantidades devem ser numricas mesmo que no se faam clculos 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 fceis de lembrar, no ltimo caso escolha os tipos de atributos automticos, como foi o caso da entidade ALIMENTO que acabei optando por uma chave Auto Incremental (1,2,3,4,5...)

Importante - No utilize, mesmo que o banco permita, tipos de atributos AUTO INCREMENTAL pois esses
PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 84/178

campos no permitem sua modificao ou seu controle, utilize campos INTEIROS e faa os clculos do maior atravs de uma funo genrica.

Mdulos Funcionais
A ltima fase da Analise de um sistema a documentao de todas as funes ou se voc preferir pode chamar de Mdulos Funcionais, estes mdulos normalmente so divididos em cadastros, movimentaes, consultas e relatrios impressos, fazendo isso e conseguindo a validao do usurio, voc evitar muitos aborrecimentos posteriores, tais como ser mal interpretado ou de causar falsas expectativas, e esta fase tambm ajudar na elaborao das Opes do Menu.

Cadastro
Cidade: ter a funo de editar e coordenar o arquivo de cidades Grupo: ter a funo de editar e coordenar o arquivo de grupos Alimento: ter a funo de editar e coordenar o arquivo de alimentos Cliente: ter a funo de editar e coordenar o arquivo de clientes

Movimentao
Entrada do Cliente: recepo para os clientes e montagem e definio dos planos nas pastas Sada do Cliente: fechamento da conta e da pasta do cliente Massa Corporal: Clculo da Massa Corporal e pesagem atual de determinado cliente

Consulta
Pasta do Cliente: Verificao de determinado cliente, com grficos sobre peso e massa coorporal Verificao do Caixa Mensal: Clculo da arrecadao de um determinado ms

Relatrio
Correspondncia: envio de corrspondencia a clientes Cardpio: montagem de determinado cardpio dirio baseado no nmero de calorias informadas Diviso das Contas Mensal: fechamento das contas mensais e diviso dos lucros Analtico das Contas Anual: resumo anual de toda a diviso efetuada

Finalmente
Prontinho agora resta mostrar para o nosso usurio ter o carimbo de aprovao, no se esquecendo de especificar prazos para a concluso de cada mdulo funcional descrito. Na prxima apostila, comearemos a programar nosso sistema criando o menu e as telas de apoio.

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 85/178

Curso de Delphi 4.0 - Apostila 08


Autor: Fernando Antonio Fernandes Anselmo E-Mail: fernandoanselmo@yahoo.com.br
Pr-Requisitos: Windows 98 Delphi 4.0 verso Client/Server Suite BDE 5.00 MS-Access 97 Arquivos trabalhados juntos com esta apostila: PESO.HLP IM0.BMP at IM10.BMP

Prefcio
Salve, bem hoje pretendo tratar aqui de um tema da maior importncia, tambm que gera a maior polmica entre qualquer grupo de mais de um programador, Menus. No me refiro a Cardpios, e sim Menus de Sistemas, ou popurlamente chamados de Telas de Entrada, por isso mesmo que so os responsveis pela maior polmica. Um Menu est para um sistema, assim como a Sala est para a casa, pegue um sistema, o mais prtico o possvel, 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 ms nem ele mais. Esta apostila (to aguardada) pode parecer simples a primeira vista, mas garanto-lhes que no muito simples projetar uma casa sem comear 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 vrias janelas, caracterizando-as como filhas que so exibidas dentro do contexto da janela principal, pode ser aberto inclusive diversas cpias de uma mesma janela. Existindo uma intensa movimentao entre elas. Muito usado em Editores de texto e Planilhas de clculos. SDI (single document interface) - aquele que permite a abertura de uma s janela de cada vez inibindo atuaes nas reas fora da mesma, no existindo nenhuma coorelao entre elas. Muito usados em sistemas de grande porte. J deu para perceber a diferena bsica entre os menus que so construdos para cada sistema, no primeiro caso o Menu deve ser mximizado 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 formulrio 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 ento entrar na janela de Material para cadastrar (ou descobrir o cdigo) de um determinado material. No sistema SDI - A janela da Fatura aberta e nela permanece (salvo que exista um boto, ou outro meio, para chamar uma outra janela) at que a Fatura seja encerrada. Tambm voc deve ter notado que existem diferenas brbaras em ambos os sistemas, vamos analisar as desvantagens:

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 86/178

No sistema MDI - O usurio pode comear a abrir diversas janelas de Faturas, ou um nmero excessivo de janelas, causando assim o estouro da rea de memria, lembre-se que cada formulrio aberto vai para a rea de memria, aquela rea baixa (do 640 Kb) ento nem adianta aumentar a memria, vai chegar num momento que o sistema simplesmente no aguentar e seu usurio ganhar uma linda tela azul. No sistema SDI - Se o usurio precisar de cadastrar (ou descobrir o cdigo 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 comear a digitar a Fatura tudo novamente, a menos que o Programador tenha lembrado de colocar um boto 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 usurios so leigos, eu no teria como explicar-lhes (s cinco da manh de sbado normalmente) que a aplicao 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 prximo projeto ser um sistema totalmente MDI.

Tipos de Menus
Ficou comprovado no ambiente Windows, tambm 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, no a toa que ele o primeiro, seu irmo mais novo o PopMenu, aquele menuzinho rpido que temos todas as vezes que clicamos com o boto direito em cima de um objeto. J vi muitos Menus interessantes, dos mais diversos tipos, um deles inclusive imita o menu do boto Iniciar do Windows 95, mas pessoalmente fico com os menus Pull-Down ( assim que so chamados) primeiro porque em qualquer aplicao do Windows (ou outro ambiente) eles esto l, segundo porque o usurio acostumado com eles (desde que se sigam regras) e terceiro porque so mais simples de se programarem. Desde a primeira verso do Pascal for Windows que a Borland (hoje Inprise) lanou esse tipo de menu, e sempre sua programao foi muito superior aos seus concorrentes, alm de muito fcil, abro um desafio aqui, peguem uma cpia dos VB's (ou FOX, Access, CA-Clipper) ou e tentem criar um menu l, agora peguem o velho Pascal for Windows e faam a mesma coisa, e me digam o que acharam. O Delphi, seguiu uma tradio da famlia, seu menu to fcil de programar que at mesmo me assusta, vamos l, sigam o mestre: 1. Se voc ainda no fez crie um diretrio que abrigar seu sistema. (para padronizar comigo crie: C:\CursoDelphi\Peso) Antes de comearmos a criar nossos menus, deixe-me dizer-lhes um detalhe a mais, 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 padro oficial dos Menus, ento na Component Pallete localize uma pgina chamada Win32 e dentro dessa pgina de um clique no objeto ImageList (acredito que seja o terceiro) e d um clique no Form. (automaticamente o Delphi criou um botozinho com o desenho dele. Para o Delphi assim que ficam todos os objetos que so invisveis durante o tempo de execuo, ou seja tanto faz em qual posio que voc o coloque, quando comear a rodar seu sistema este objeto ficar invisvel). D um duplo clique no objeto criado e vamos entrar na ImageList, clique no boto Add e v adicionando as imagens enviadas na ordem: primeiro a IM0.BMP, depois a IM1.BMP e assim sucessivamente, veja a figura:

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 87/178

2. Abra o Delphi e na Component Pallete localize uma pgina chamada Standard e dentro dessa pgina de um clique no objeto MainMenu (acredito que seja o primeiro) e d um clique no Form. (automaticamente o Delphi criou um botozinho com o desenho dele, mais um objeto invisvel). D um clique simples em cima do objeto criado e altere a seguinte propriedade: Images: ImageList1 (Define um objeto ImageList para ser utilizado como repositrio de imagens). 3. Vamos agora entrar na Menu Editor, d agora um clique duplo em cima do MainMenu1 criado, agora s comear 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 padro oficial dos Menus, ento aqui voc insere este tipo de figura. 3.1.Break: permite que voc crie um submenu lateral (utilize a opo mbBreak para o primeiro e mbBarBreak para os filhos) 3.2.Caption: o que o seu usrio ver, a opo em si, utilize o caracter & para colocar atalhos nas opes (ex: &Arquivo) 3.3.Check: permite que voc crie uma marca no item de menu, assim voc pode criar opes do tipo habilitado ou no. 3.4.Default: permite que uma das opes 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 esto desabilitados, os do grupo 2 esto habilitados e assim vai. 3.6.HelpContext: desloca automaticamente ao contexto selecionado ao ser chamado um arquivo de auxlio, se o HelpContext for igual a 0 no envia para contexto nenhum. 3.7.Hint: Pequeno auxlio para o item do menu, mas essa propriedade deve ser visualizada atravs 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 vocs na dvida. 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 rpido atravs 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, raa ou credo, a Tag uma varivel inteira que voc pode rotular para diversos usos como por exemplo transformar em Invisvel todos os objetos que possuam a Tag igual a 10 ou pintar a fonte de azul-marinho

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 88/178

todos os objetos da Tag 5. 3.12.Visible: Permite que o objeto fique visvel ou no em tempo de execuo. Prontinho com todas essas informaes acredito que voc j est pronto (e ansioso) para construir nosso menu. Vamos l ento. 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: Informaes 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 boto direito e no menu que aparecer clique com o boto direito do mouse na opo 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 opes: Caption: &Cidade Hint: funo de editar e coordenar o arquivo de cidades Caption: &Grupo Hint: funo de editar e coordenar o arquivo de grupos Caption: &Alimentos Hint: funo de editar e coordenar o arquivo de alimentos

Caption: - (sinal de menos) O resultado ser uma barra de separao

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 89/178

Caption: Cli&entes Hint: funo de editar e coordenar o arquivo de clientes

Volta para aquela rea abaixo do cadastro e altere a propriedade Caption: (Voc no est enchergando ruim no o trao de menos mesmo.) Isso produzir o seguinte efeito:

E vamos a ltima opo deste submenu: Caption: &Sair Hint: Retorna ao Windows ShortCut: Ctrl+S ImageIndex: 10 Prontinho a subopo Arquivo ficou da seguinte maneira:

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 90/178

Importante - As imagens aparecero apenas fora do MenuEditor.


Agora crie os outros submenus segundo definimos na apostila anterior, no se lembra ? ento aqui esto eles: (com os respectivos Caption's, Hint's e caso tenham ImageIndex)

&Movimentao: informaes constantes do sistema


&Entrada do Cliente: recepo para os clientes e montagem e definio dos planos (ImageIndex: 1) &Sada do Cliente: fechamento da conta do cliente (ImageIndex: 2) &Massa Corporal: Clculo da Massa Corporal e pesagem atual do cliente (ImageIndex: 3)

&Consulta: vises on-line dos arquivos


&Pasta do Cliente: Verificao de determinado cliente, com grficos sobre peso e massa coorporal (ImageIndex: 4) &Verificao do Caixa Mensal: Clculo da arrecadao de um determinado ms

&Relatrio: emisses na tela e em papel de um determinado momento dos arquivos


&Correspondncia: envio de corrspondencia a clientes (ImageIndex: 9) Car&dpio: montagem de determinado cardpio dirio baseado no nmero de calorias informadas &Diviso das Contas Mensal: fechamento das contas mensais e diviso dos lucros &Analtico das Contas Anual: resumo anual de toda a diviso efetuada Configura &Impressora: Verifica qual a impressora que ser utilizada para as impresses (ImageIndex: 5)

Au&xlio: chama o help on-line do sistema


&Contedo: Contedo do auxlio on-line (ImageIndex: 6) &Tpicos do Auxlio: Chama os tpicos do Auxlio on-line (ImageIndex: 7) Como &Usar o Auxlio: Como ultilizar o auxlio do windows (ImageIndex: 8) &Sobre o Sistema: Informaes sobre a execuo 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 formulrio) mude para fMenu.PAS 4.2. Aonde aparece Project1.dpr (o Delphi est se referindo do nome do projeto - que ser o nome do executvel final) mude para Peso.DPR 5. Pode sair do Menu Editor e testar seu menu. Clique agora em qualquer rea vzia do formulrio 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 formulrio se inicie no modo maximizado) 6. Na Component Pallete localize uma pgina chamada Win32 e dentro dessa pgina de um clique no objeto StatusBar (acredito que seja o dcimo quarto) e d um clique no Form, foi criado tipo um painel na parte inferior do formulrio. Altere as seguinte propriedades:

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 91/178

6.1. Name - BarraStat 6.2. Panels - Clique nos ... e clique trs vezes no primeiro botozinho (marcado com Add New (Ins) ) para criar 3 subpainis 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 pgina chamada System e dentro dessa pgina 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. 8. Na Component Pallete localize uma pgina chamada Dialogs e dentro dessa pgina de um clique no objeto PrinterSetupDialog (acredito que seja o oitavo) e d um clique no Form, foi criado tipo um quadradinho representando o objeto.

Iniciando os programas do Menu


Vamos comear agora a programar nosso Menu. Primeiramente vamos programar a Barra de Status, note que nela foram criados 3 painis, ou trs divises, 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 faa esse desvio, para tanto, aperte o boto F12 para ir para a Code Editor e localize a seguinte parte:
private { Private declarations } public

E coloque o seguinte cdigo:


private procedure MontaHint(Sender: TObject); public

Agora abaixo da diretiva de compilao, insira o seguinte cdigo: 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 cdigo:
procedure TF_Menu.FormCreate(Sender: TObject); begin Application.OnHint := MontaHint; end;

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 92/178

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 cdigo:
procedure TF_Menu.Timer1Timer(Sender: TObject); begin BarraStat.Panels[1].Text := FormatDateTime('HH:MM:SS',Now); end;

A cada segundo a hora ser atualizada, no se preocupe que isso no afetar em nada o desempenho do sistema. Bem agora vamos colocar alguns comandos bsicos, inicialmente, aperte F12 para voltar a ter a viso do formulrio, e clique em Arquivo e Sair, coloque o seguinte cdigo:
procedure TF_Menu.Sair1Click(Sender: TObject); begin Close; end;

O comando Close far com que o formulrio seja encerrado, como o prprio Menu do Sistema, ento o Sistema ser encerrado. O comando para chamar a Configurao da Impressora simples, auxiliado pelo objeto PrinterSetupDialog, Clique em Arquivo e Configura Impressora e insira o seguinte cdigo:
procedure TF_Menu.ConfiguraImpressora1Click(Sender: TObject); begin PrinterSetupDialog1.Execute; end;

Como todos os objetos da Pallete Dialogs basta apenas chamar o mtodo Execute do objeto que todo o servio est feito.

Codificando o Auxlio
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 prprogramados, alm 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 tpico Pr-Definido. Futuramente veremos como criar nosso arquivo de auxlio, mas, por enquanto vamos utilizar o arquivo enviado juntamente com esta apostila. A partir do Menu Principal v em Project | Options... na pgina Applications altere as seguintes propriedades: Title: Controle do SPA HelpFile: Peso.HLP As palavras-chaves para o comando HelpCommand so: Comando
HELP_CONTEXT

Parmetro Passado
Inteiro longo, contendo o nmero do contexto.

Utilizao
Mostra o auxlio a partir de tpico selecionado identificado a partir do nmero do contexto definido pela seo [MAP] do arquivo .HPJ Mostra o contedo do primeiro tpico definido pela seo [MAP] do arquivo .HPJ Determina a chamada do tpico determinado atravs do uso da tecla F1 Mostra uma janela Pop-Up com um tpico definido pela seo [MAP] do arquivo .HPJ

HELP_CONTENTS HELP_SETCONTENTS HELP_CONTEXTPOPUP

Ignorado. Normalmente passado 0. Inteiro longo, contendo o nmero do contexto que foi designado como tpico de contedo. Inteiro longo, contendo o nmero do contexto. particular identificado pelo nmero do contexto

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 93/178

HELP_KEY

Ponteiro longo como uma string contendo o tpico designado. Ponteiro longo como uma string contendo o tpico designado.

Mostra um tpico pesquisado em uma lista de palavras chaves. Esta palavra chave deve ser exatamente o texto procurado. Mostra um determinado tpico atravs de uma lista de palavras chaves. Se a palavra chave no for encontrada posiciona na palavra fontica mais perto. Mostra o tpico indentificado pela palavra chave ou uma chave da tabela alternada. Executa um macro help. Mostra um help do windows com um mnimo de memria, variando o tamanho e a posio de acordo primrio ou a janela secundria para ser mostrado. Com o dado passado. Executa o WinHelp mostrando o arquivo de auxlio corrijido. Mostra o auxlio de como usar o auxlio. Solicita o fechamento do auxlio ativo.

HELP_PARTIALKEY

HELP_MULTIKEY

Ponteiro longo para uma estrutura de TMULTIKEYHELP. Esta estrutura especfica de caracteres e palavras chaves. Ponteiro longo, contm a macro para a execuo Ponteiro longo para uma estrutura de TMULTIKEYHELP. Esta estrutura especfica contm o tamanho e a posio da janela do help Ignorado. Normalmente passado 0. Ignorado. Normalmente passado 0. Ignorado. Normalmente passado 0.

HELP_COMMAND HELP_SETWINPOS

HELP_FORCEFILE HELP_HELPONHELP HELP_QUIT

De posse desse nosso dicionrio de comandos, aperte F12 e clique em Auxlio e Contedo, e insira o seguinte cdigo:
procedure TF_Menu.Contedo1Click(Sender: TObject); begin Application.HelpCommand(HELP_CONTENTS, 0); end;

Aperte F12 e clique em Auxlio e Tpicos do Auxlio, e coloque o seguinte cdigo:


procedure TF_Menu.TpicosdoAuxlio1Click(Sender: TObject); const EmptyString: PChar = ''; begin Application.HelpCommand(HELP_PARTIALKEY, Longint(EmptyString)); end;

E finalmente, aperte F12, clique em Auxlio e Como usar o Auxlio, e coloque o seguinte cdigo:
procedure TF_Menu.ComoUsaroAuxlio1Click(Sender: TObject); begin Application.HelpCommand(HELP_HELPONHELP, 0); end;

Vamos completar o comando de sair colocando tambm o encerramento do arquivo de auxlio, aperte F12 e clique em Arquivo e Sair, complete com seguinte cdigo antes do comando Close:
procedure TF_Menu.Sair1Click(Sender: TObject); begin Application.HelpCommand(HELP_QUIT, 0); Close; end;

Rode sua aplicao e teste os comandos do Auxlio, caso a tecla F1 no ative o auxlio On-Line, provavelmente o seu menu est com a propriedade FormStyle em modo fsMDIForm, coloque-a no modo fsNormal. Se mesmo assim ainda no funcionou, mude a propriedade HelpContext do formulrio para 1.

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 94/178

Finalmente
Uma dica interessante que o Frmulrio est associado ao Menu atravs da propriedade Menu, que ela possvel de ser alterada em modo Run-Time, ento imagine que num mesmo formulrio possvel ter vrios Menus diferentes, cada um se adaptando a uma situao do usurio (financeiro, administrador, digitador). Na prxima apostila, vamos criar as janelas auxiliares Splash e Sobre o Sistema.

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 95/178

Curso de Delphi 4.0 - Apostila 09


Autor: Fernando Antonio Fernandes Anselmo E-Mail: fernandoanselmo@yahoo.com.br
Pr-Requisitos: Windows 98 Delphi 4.0 verso Client/Server Suite BDE 5.00 MS-Access 97 Arquivos trabalhados juntos com esta apostila: IMGGER.BMP IMGICO.BMP

Prefcio
Salve, a apostila de hoje faz parte do chamado propaganda do sistema, o ambiente Windows conseguiu trazer consigo mais do que simplesmente um ambiente grfico de janelas, trouxe uma coisa muito importante, alias foram duas, note que todo o sistema ditos "for Windows" carregam consigo essas duas importantes e imprescindveis janelas. Splash Screen, no isso no 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, no 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 comeou ? ningum sabe, sabe-se apenas que todo o sistema que se preza tem que ter a sua, algumas bem incrementandas contendo os famosos "Ovos de Pscoa", aquela combinao 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 so janelas que a maioria dos programadores no d a menor importncia, 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 incrementao, vamos nessa ento.

Splash Screen
Inicialmente deixe-me dizer uma coisa, a Splash apenas uma janela pedindo para o usurio ter um pouco de pacincia enquanto todo o sistema se inicia, no a faa demorada demais pois a ltima coisa que o usurio precisa e de mais pacincia, tem gente que coloca um timer nelas para poder demorar ou ento um simples comando For i := 1 to 10000 no faam isso, inicialmente pode parecer que a janela pouco vai aparecer, mas no se preocupe com o tempo, e o sistema crescendo, essa janela vai acabar demorando o tempo suficiente para que o usurio possa ver as informaes descritas nela e no se aborrecer. Para comearmos abra o sistema e a partir do Menu Principal clique em File | New Form criando um novo formulrio 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 desaparea. 1.2. Name - F_Splash. 1.3. Position - poScreenCenter - A janela aparecer centralizada no vdeo. 2. Na Component Pallete localize uma pgina chamada Additional e dentro dessa pgina de um clique no objeto

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 96/178

Image (acredito que seja o sexto) e d um clique no Form, foi criado tipo um painel pontilhado no formulrio. Altere as seguinte propriedades: 2.1. Picture - clique nos ... clique no boto Load e localize o arquivo IMGGER.BMP (enviado) 2.2. Transparent - True - Isso far com que a cor da posio 0,0 seja a base para que a imagem fique transparente, ento dentro da imagem aonde tiver cor semelhante ficar transparente. 3. Na Component Pallete localize uma pgina chamada Standard e dentro dessa pgina 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 formulrio com o nome de fSplash, j temos agora em nosso projeto a nossa Splash Screen mas ainda falta um pequeno toque, clique no formulrio 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 criao far com que todo o formulrio fique tambm transparente, ento na verdade dentro da nossa Splash s aparecer a Imagem e o Label, agora precisamos cham-la do nosso sistema.

Importante - Peo por favor a maior ateno para o prximo passo pois mecheremos em reas delicadas do nosso
projeto. Antes de comearmos 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 formulrio, aparecer escrito UNIT tal, mas aonde ento est o nosso Programa ? Quando voc inclui um novo formulrio ao projeto, o Delphi se encarrega automaticamente de criar as chamadas a esta nova Unidade alterando por si s o nosso Programa, infelizmente ele no tem uma rea para fazer isso automaticamente com uma janela Splash ento teremos que colocar na mo. 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 alteraes, localize o comando BEGIN e insira os seguintes comandos: begin

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 97/178

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 trs comandos, nos Criaremos a janela de Splash, chamaremos ela (no passando o controle para ela) e foraremos sua apario.

Importante - Existem dois comandos para se chamar um Formulrio, so eles:


SHOW - Chama o formulrio sem passar o controle para ele, ou seja o programa que o chamou ainda possui o controle da ao. SHOWMODAL - Chama o formulrio passando o controle da ao para ele at que ele seja finalizado. Bem, feito isso, agora s falta destruirmos nossa janela quando o sistema comear a execuo, 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, ento chame o formulrio do Menu e para o evento OnShow coloque o comando: procedure TF_Menu.FormShow(Sender: TObject); begin F_Splash.Free; end; No se esquea de logo aps a diretiva de compilao acrescentar a utilizao da Unidade, desta maneira: {$R *.DFM} uses fSplash;

Sobre o Sistema
A partir do Menu Principal clique em File | New Form criando um novo formulrio 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 vdeo. 2. Na Component Pallete localize uma pgina chamada Standard e dentro dessa pgina 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 tpicos 3 e 4, antes de clicar nos objetos indicados clique primeiramente neste objeto Panel
criado. 3. Na Component Pallete localize uma pgina chamada Additional e dentro dessa pgina 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 boto Load e localize o arquivo IMGICO.BMP (enviado) 3.2. Transparent - True - Isso far com que a cor da posio 0,0 seja a base para que a imagem fique transparente, ento dentro da imagem aonde tiver cor semelhante ficar transparente.

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 98/178

4. Na Component Pallete localize uma pgina chamada Standard e dentro dessa pgina traga trs 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 - Verso Beta 1 4.2.2. Font - clique nos ... e altere as seguintes propriedades: Fonte: MS Sans Serif Estilo da Fonte: Itlico 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 pgina Standard dentro dessa pgina de um clique no objeto GroupBox (acredito que seja o dcimo segundo) e d um clique no Form. Altere as seguinte propriedades: 5.1. Caption - Dados Tcnicos 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 tpico 6, antes de clicar no objeto indicado clique primeiramente neste objeto GroupBox
criado. 6. Na Component Pallete ainda na pgina Standard e dentro dessa pgina 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: Endereo Internet: Caption do 2: EMail: Caption do 3: Verso Windows: Caption do 4: Verso do DOS: Caption do 5: CPU: Caption do 6: Memria Livre: Caption do 7: Espao Livre: 6.2. Coloque os prximos 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

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 99/178

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: fernandoans@geocities.com Complete a propriedade Font de ambos para: Efeitos: Sublinhado Cursor de ambos para: crUpArrow 7. Finalmente na Component Pallete localize uma pgina chamada Additional e dentro dessa pgina 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 tambm 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 informaes bem sofisticadas tais como Verso do Windows e DOS entre outras, mas vamos com calma, inicialmente clique no objeto EnderNet e para o evento OnClick insira o seguinte cdigo: 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;

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 100/178

Este cdigo 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 compilao so para assegurar que o comando s seja executado em ambiente Win32. Clique agora no objeto EMail e para o evento OnClick insira o seguinte cdigo: procedure TF_Sobre.EMailClick(Sender: TObject); const pEMail = 'mailto:fernandoans@geocities.com'; 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 correspondncia para o endereo eMail especificado. Clique agora no objeto F_Sobre e para o evento OnShow insira o seguinte cdigo: procedure TF_Sobre.FormShow(Sender: TObject); var OsInfo: TOSVERSIONINFO; SysInfo: TSYSTEMINFO; MemStat: TMEMORYSTATUS; DiskNo: Integer; begin OsInfo.dwOSVersionInfoSize := sizeof(TOSVERSIONINFO); GetVersionEx(OsInfo); // Verso 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; // Verso 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); // Memria 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 := '';

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 101/178

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 so todos comandos API que fazem chamadas ao Windows solicitando as informaes necessrias, 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 observao, note que para capturar o processador me utilizei de determinadas constantes para facilitar o entendimento, elas devem ento serem criadas, localize o comando VAR e entre este comando e o comando End de finalizao 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 utilizao da Unidade: ShellAPI, coloque ento a declao dela no comando USES perto do comando INTERFACE. Pronto, agora basta chamarmos novamente nosso formulrio que contm o Menu e chamarmos a janela do Sobre para tanto chame o formulrio, clique em Auxlio | Sobre o Sistema e insira os seguintes cdigos: procedure TF_Menu.SobreoSistema1Click(Sender: TObject); begin F_Sobre := Tf_Sobre.Create(Application); F_Sobre.ShowModal; F_Sobre.Free; end; No se esquea de logo aps a diretiva de compilao acrescentar a utilizao desta nova Unidade, desta maneira: {$R *.DFM} uses fSplash, fSobre; Nota Importante: Note que para o formulrio fMenu eu criei um novo comando USES enquanto que no formulrio do fSobre eu apenas acrescentei no USES j existente, existe uma grande diferena entre ambos, no primeiro caso as

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 102/178

unidades fSplash e fSobre no esto com os endereos fixados na rea de memria no momento da criao do formulrio, no segundo caso todas as unidades inclusive a ShellApi esto com os endereos de memria reservado assim que o formulrio criado.

Retirando os formulrios da rea de Memria


Falando em reas de memria, os formulrios s devem ser criados (a excesso bvia do fMenu) quando o usurio necessitar deles, ou seja, se o usurio que chamar o FSobre ento o sistema deve cri-lo, cham-lo e depois remov-lo completamente da rea de memria, isto feito pois o Delphi se utiliza da rea de memria baixa para manter os endereos do objetos criados, ou seja o Delphi faz uso dos 640 Kb desta memria, ento no adianta ter um Pentium com 64 Megas de memria, pois o disponvel para execuo dos formulrio apenas aquela taxa de 640 Kb, e deve ser muito menos, pois o Windows tambm utiliza ela, e outros aplicativos tambm. Precisamos ento aliviar o mximo esta rea, para isso no Menu Principal clique em Project | Options... na folha Forms selecione F_Splash e F_Sobre e clique no boto > mandando ambas para a rea dos Avaliable Forms isto ser feito com todas as outras janelas a exceo da DModelo que ser o nosso DataModule.

Finalmente
Pode executar o sistema e apreciar a propaganda da Splash e da Sobre, novamente digo no se preocupe com a rapidez que a janela Splash vai aparecer, quanto mais inserirmos no sistema mais demorado esta janela ficar. Na prxima apostila, vamos discutir o assunto de como juntar todas as nossas regras de negcio num nico e simples DATA MODULE.

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 103/178

Curso de Delphi 4.0 - Apostila 10


Autor: Fernando Antonio Fernandes Anselmo E-Mail: fernandoanselmo@yahoo.com.br
Pr-Requisitos: Windows 98 Delphi 4.0 verso Client/Server Suite BDE 5.00 MS-Access 97 Arquivos trabalhados juntos com esta apostila: BASICO.MDB

Prefcio
Salve, nesta apostila desvendaremos a utilizao dos Data Modules. Os Data Modules no so um bicho de sete cabeas, 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 amvel bichinho de nove cabeas, voc deve tomar cuidado para no cortar nenhuma delas pois sempre nascem mais duas no lugar.

Primeira Cabea - Quando nasceu


Os Data Modules surgiram a partir do Delphi 2.0, ento no adianta voc ficar procurando naquela sua antiga verso de Delphi 1.0, com a necessidade de organizar os formulrios, pois ficava aquele monte de objetos invisveis em tempo de execuo tipo tTable, tDataSource e tQuery perdidos, fora que voc sempre tinha que definir em dois formulrios diferentes a mesma tabela, os mesmos campos, as mesmas ligaes, isto gastava tempo e muito espao do sistema.

Segunda Cabea - Invisibilidade


Os Data Modules so parentes primrios dos formulrios, eles so uma espcie de "Nehandertal" dos formulrios, no so visveis em tempo de execuo, ento no adianta tentar dar um comando do tipo Show para mostr-los pois todos so envergonhados e detestam aparecer, eles s servem para uma nica funo controlar e armazenar objetos invisveis como eles, ento no tente colocar um tEdit ou um tImage dentro deles que eles no deixaro. Outra caracterstica 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 mo, dando aqueles comandos de criao, mas em todo o nosso projeto ser apenas um nico Data Module, ento alm do Menu deixe-o quietinho na rea dos Auto-Create.

Terceira Cabea - Relao Data Module X Formulrio


possvel criar um Data Module para cada formulrio, mas este no 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 negcio, criando e definindo os campos das tabelas alm de outros objetos invisveis que o sistema poder a necessitar. O Data Module um espcie de armazm do nosso sistema, guarde nele tudo o que for globalmente usado, como por exemplo variveis, funes ou procedimentos basta apenas defin-los em sua rea Public e depois declarar o Data Module no comando Uses da nossa unidade.

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 104/178

Quarta Cabea - Criando a 1a. Conexo


Vamos comear 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 MS-Access 97 (ou ento 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 alteraes em Object | Apply (ou simplesmente CTRL+A, ou ainda clique no quarto boto 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 pgina chamada DataAccess e dentro dessa pgina 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 Conexo DataBase Name - DNmPeso - Nome da Base de Dados Interna Name - PrjPeso - Nome do Objeto

Quinta Cabea - Criando a 2a. Conexo


Vamos agora criar toda a nossa regra de negcio, 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 pgina chamada DataAccess e dentro dessa pgina 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:

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 105/178

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 atravs do campo chave NUM_CPF, o mesmo ser colocado automaticamente quando de uma incluso, mantendo assim a integridade referencial com este. Altere a propriedade Name do objeto Query1 para QrySql Prontinho, deve ter ficado algo parecido com isso:

Stima Cabea - Criando os campos


Uma coisa prtica que podemos fazer a definio dos campos de cada tabela, isto servir para que quando mostremos esta tabela atravs de um objeto dbGrid o Delphi o trate pelo nome que desejamos e no como NUM_CPF por exemplo, outra parte interessante que aqui podemos definir as mscaras 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 boto direito nela e aparecer o menu popup conforme a figura a seguir:

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 106/178

Clique em Add fields... e clique no boto 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 tbAlimento tbAlimento tbAlimento tbAlimento tbResumo_Mensal tbResumo_Mensal tbResumo_Mensal tbResumo_Mensal tbResumo_Mensal tbCliente tbCliente tbCliente tbCliente tbCliente tbCliente tbCliente tbCliente tbCliente tbGrupo tbGrupo tbTelefone_Cliente tbTelefone_Cliente tbTelefone_Cliente tbPasta_Cliente tbPasta_Cliente tbPasta_Cliente tbPasta_Cliente tbPasta_Cliente tbPasta_Cliente tbPasta_Cliente tbPasta_Cliente tbCidade tbCidade tbCidade tbPeso_Cliente tbPeso_Cliente tbPeso_Cliente Campo COD_ALIMENTO NUM_GRUPO NOM_ALIMENTO QTD_PERMITIDA ANO_MES VAL_MEDICO VAL_COORDENADOR VAL_NUTRICIONISTA VAL_DESPESA NUM_CPF SIG_CIDADE NOM_CLIENTE END_CLIENTE BAI_CLIENTE CEP_CLIENTE DES_EMAIL ALT_CLIENTE DAT_NASCIMENTO NUM_GRUPO DES_GRUPO NUM_CPF NUM_TELEFONE DES_FUNCAO NUM_CPF DAT_CORRENTE PLN_ADOTADO QTD_CALORIA OBS_PASTA DAT_PAGAMENTO VAL_TOTAL VAL_DESCONTO SIG_CIDADE NOM_CIDADE SIG_UF NUM_CPF DAT_MEDIDO PES_MEDIDO DisplayLabel Cdigo Nm Grupo Nome Qtd Permitida Ano e Ms Valor Mdico Valor Coordenador Valor Nutricionista Valor Despesa CPF Cliente Sigla da Cidade Nome Endereo Bairro CEP eMail Altura (Cm) Data de Nascimento Nmero Descrio CPF Cliente Nm Telefone Funo CPF Cliente Data Corrente Plano Adotado Qtd Calorias Observaes Data Pagamento Valor Total Valor Desconto Sigla Nome UF CPF Cliente Data Medio Peso Medido EditMask >a;0;_ 9999\/99;0;_ True True True True 000\.000\.000\/00;0;_ >aaa;0;_ Currency

00\.000\-000;0;_ !99/99/0000;1;_ >a;0;_ 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;_ True True >aaa;0;_ >AA;0;_ 000\.000\.000\/00;0;_ !99/99/0000;1;_

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 107/178

Oitava Cabea - 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 tropeando nos chamados Domnios do Oracle, que so iniciais automticas que ele coloca para definir quem o dono das tabelas. O problema uma mudana de nome em qualquer ponto pode ser desastroso, e isso no se limita apenas ao Oracle serve para qualquer outra migrao de base de dados, para evitar este pequeno problema, vamos adotar em nosso sistema oito variveis 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 conexo corretamente entre o objeto TDataBase e o Alias para ambas: 1. Alterne para o Code Editor e localize a seguinte poro do cdigo: 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 cdigo: procedure TD_Modelo.D_ModeloCreate(Sender: TObject); var Conexao : Boolean; begin // Atribui os nomes externos as variveis 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 variveis 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 conexo try PrjPeso.Connected := True; if not PrjPeso.IsSQLBased then PrjPesoLogin(PrjPeso, nil); Conexao := True; except MessageDlg('Erro na Conexo do Banco de Dados', mtError, [MbOk], 0);

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 108/178

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 cdigo: procedure TD_Modelo.PrjPesoLogin(Database: TDatabase; LoginParams: TStrings); begin LoginParams.Values['USER NAME'] := ''; LoginParams.Values['PASSWORD'] := ''; end; 4. Para terminar a conexo, quando o sistema for encerrado, selecione o objeto D_Modelo e para o evento OnDestroy insira o seguinte cdigo: procedure TD_Modelo.D_ModeloDestroy(Sender: TObject); begin PrjPeso.Connected := False; end;

Nona Cabea - Funes Particulares e as regras de negcio


Todas as amarraes que normalmente so definidas por DBA do banco de dados, criando Stored Procedures e Triggers para a administrao do banco podem ser reproduzidas perfeitamente aqui, vou citar alguns exemplos e voc ter uma boa base para criar outras que sero necessrios aos seus sistemas. J falei antes e vou repetir agora, no sou muito f de campos do tipo AutoIncremento, primeiro porque no so todos os bancos que os implementam e segundo porque no sou eu quem o controla, assim j que no posso arrum-lo ou liber-lo quando desejar, no posso criar meu prprio passo e inmeras outras coisas, isto em bancos complexos realizado criando Stored Procedures, procedimentos prontos em linguagens SQL que so 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 ADAPTAES. Para gerar um nmero automtico para um campo qualquer precisamos apenas seguir os seguintes passos: 1. Crie uma chamada a uma funo particular: private function Maximo(nmCampo, nmTabela: String) : integer; public 2. Crie a funo: 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;

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 109/178

3. Para o evento AfterInsert do objeto tbAlimento coloque a seguinte codificao: procedure TD_Modelo.tbAlimentoAfterInsert(DataSet: TDataSet); begin tbAlimentoCOD_ALIMENTO.AsInteger := Maximo('COD_ALIMENTO',nmAlimento); end; Resolvido as crises com os nmeros automticos, a funo recebe como parmetro o nome do campo inteiro e o nome da tabela, ento ela simplesmente monta uma clusula 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 funes particulares que podemos colocar so para os eventos OnPostError e OnDeleteError para controlar falhas na gravao e ao invs de recebermos aquelas amigveis mensagens binrias hexadecimais $FFFFFFF para a alegria e desespero do nosso usurio, aparecer controladamente algo mais agradvel, ento siga os passos: 1. Alterne para o Code Editor e defina os seguintes procedimentos antes da clusula 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 Gravao 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('Impossvel gravao: Provavelmente Registro Duplicado', mtWarning, [mbOk], 0); Abort; end; end; // Controla os Erros de Excluso 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('Impossvel excluir: Provavelmente Registros Associados', mtWarning, [mbOk], 0); Abort; end; end; 3. Selecione todas as tabelas e para o evento OnPostError selecione (atravs da seta, no d duplo clique) o procedimento TabelaErroPost e para o evento OnDeleteError selecione o procedimento TabelaErroDelete. Estes procedimentos foram criados para receberem os mesmos parmetros do procedimento original ou seja, o DataSet vinculado, o cdigo do erro e a ao a tomar, ento basta simplesmente verificarmos se o cdigo do erro um EDBEngineError ou seja um erro de banco, darmos a nossa mensagem controlada e abortarmos o processo de gravao ou eliminao. Para as regras de negcio contamos com o evento OnValidate que cada campo separadamente possui, vou citar aqui uma das mais importantes regras: Existem duas divises 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 atravs do que chamamos de Triggers de banco (Gatilhos), mas esses "Gatilhos" variam muito de banco para banco, ento pessoalmente prefiro coloc-los no Delphi pois assim permito a maleabilidade dos diversos bancos, vamos ento 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.

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 110/178

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 varivel inteira aonde ser calculado quantos anos este cliente possui, para isso, utilizamos a funo FormatDateTime que devolve uma data com base de uma mscara formatada, isso vale para: Especificao Mostra c A data que usa o formato dada pelo ShortDateFormat varivel global, seguiu at que usasse o formato dado pelo LongTimeFormat varivel global. O tempo no exibido se a parte fracionria do valor do DateTime zero. d O dia como um nmero sem um zero principal (1-31). dd O dia como um nmero com um zero principal (01-31). ddd O dia como uma abreviao (Sun-Sat) usando a string ShortDayNames que uma varivel global. dddd Exibe o dia como um nome cheio (Sunday-Saturday) usando a string LongDayNames que uma varivel global. ddddd A data usando a string ShortDateFormat que uma varivel global. dddddd A data usando a string LongDateFormat que uma varivel global. m O ms como um nmero sem um zero principal (1-12). Se a especificao de m segue um h ou especificar de hh imediatamente, ento ser exibido o minuto em lugar do ms. mm O ms como um nmero com um zero principal (01-12). Se a especificao de mm segue um h ou especificar um hh imediatamente, o minuto em lugar do ms exibido. mmm O ms como uma abreviao (Jan-Dec) usando a string ShortMonthNames que uma varivel global. mmmm O ms como um nome cheio (January-December) usando a string LongMonthNamesque uma varivel global. yy O ano como um nmero de dois-dgito (00-99). yyyy O ano como um nmero de quatro-dgito (0000-9999). h Displays a hora sem um zero principal (0-23). hh A hora com um zero principal (00-23). n O minuto sem um zero principal (0-59). nn O minuto com um zero principal (00-59). s O segundo sem um zero principal (0-59). ss O segundo com um zero principal (00-59). t O tempo que usa o formato dado pela varivel global ShortTimeFormat. tt Exibe o tempo que usa o formato dado pela varivel global LongTimeFormat. am/pm Usa a notao Hora-12 do relgio para o h precedendo ou especificado de hh, e exibies ' am' durante qualquer hora antes de meio-dia, e ' pm' durante qualquer hora depois de meio-dia. A especificao pode ser usado em minscula (am/pm), caso contrrio (AM/PM), ou misturado (Am/Pm) o resultado ser exibido de acordo. a/p Usa a notao Hora-12 do relgio para o h precedendo ou especificado de hh, e exibies ' a' durante qualquer hora antes de meio-dia, e ' p' durante qualquer hora depois de meio-dia. A especificao pode ser usado em minscula (a/p), caso contrrio (A/P), ou misturado (A/p) o resultado ser exibido de acordo. ampm Usa a notao Hora-12 do relgio para o h precedendo ou specifier de hh, e exibies os contedos da varivel global TimeAMString durante qualquer hora antes de meio-dia, e os contedos da varivel global TimePMString durante qualquer hora depois de meio-dia. / Exibe o carcter separador de data dado pela varivel global DateSeparator. : Exibe o carcter separador de tempo dado pela varivel global TimeSeparator. "xx" Carcter includos em plicks ( ' ) ou aspas ( " ) no afetam o formato. Coloquei esta tabela, que pode ser encontrada no tpico do auxlio da funo FormatDateTime apenas para que voc no se esquea o quo til pode ser esta funo no tratamento de Datas. O clculo para a idade feito da

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 111/178

seguinte maneira, pegamos a data atual e subtraimos pela data de nascimento o resultado convertido em anos pela funo, depois basta apenas questionarmos se o valor est fora da faixa especificada. Outro tipo de Regra de Negcio que podemos aplicar e quanto a entrada padro 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 tambm 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 cdigos: 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 no precisa de muita explicao para o que fiz, apenas mandei os valores especicados para cada campo. Estas regras podem ser aplicadas na medida que voc precise delas, no 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 utilssima ferramenta que so os Data Modules. Na prxima apostila, nosso assunto ser de construir os formulrios que cadastraro as tabelas bsicas do sistema, ou seja, comearemos a construir nossas telas de entradas.

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 112/178

Curso de Delphi 4.0 - Apostila 11


Autor: Fernando Antonio Fernandes Anselmo E-Mail: fernandoanselmo@yahoo.com.br
Pr-Requisitos: Windows 98 Delphi 4.0 verso 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 ImgFormCons.BMP ImgTabela.BMP ImgImprime.BMP ImgInsere.BMP ImgInsLote.BMP ImgLocaliza.BMP ImgMarca.BMP ImgPrimeiro.BMP ImgAvancaSalto.BMP ImgUltimo.BMP ImgFicha.BMP ImgVaiMarca.BMP ImgVoltaSalto.BMP

Prefcio
Salve, nesta apostila desvendaremos a primeira parte de como criar os cadastros. Mas antes de comearmos deixe-me explicar porque suspendi o curso durante o ms 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 lanar um curso deste nvel tambm sempre desejei que as pessoas pudessem aprender o que existe de mais moderno sem ficar preso a uma linguagem ou ambiente antigo e morto, ento no quero nem vou ficar esperando concluir ou terminar um mdulo para mudar. Aconselho que voc sempre se mantenha sempre atualizado em relao 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 necessrios que iremos utilizar a partir de agora, ento antes que voc comee a desenvolver nesta apostila aconselho que voc baixe e d uma lida neste manual, instale e verifique a utilidade dos objetos disponibilizados, e tambm estou disponibilizando o Apndice C para que voc aprenda e compreenda mais um pouco sobre a linguagem Object Pascal.

Comeando e Criando o Pai de Todos


Em Orientao a Objetos a palavra-chave Reaproveitamento, e isto conseguido facilmente atravs da Herana dos Objetos primeiramente se ningum nunca disse isso a voc ento vou ter a honra de falar primeiro, tudo no Delphi so objetos, inclusive e principalmente os formulrios, eles so tratados como qualquer outro objeto, ento existe a propriedade Herana para o reaproveitamento dos formulrios, para no complicar muito esta apostila ser dividida em duas partes (voc ver que mesmo dividindo esta apostila em dois ela bastante extensa).

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 113/178

Neste primeiro momento criaremos o pano de fundo para todos os nossos cadastros, no pense que vai ser simples, pois em 17 anos programando mudei vrias vezes minhas telas de cadastro desde que trabalhava com linguagens do tipo Natural e Cobol, venho aprimorando minhas telas, at que finalmente, graas a uma olhada num sistema me apaixonei logo de cara na tela de cadastro, mais pela simplicidade do que pelo nmero de funes fiz algumas mudanas e consegui chegar a uma tela de cadastro que julgo a ideal. Sendo simples e ao mesmo tempo complexa em nmero de utilidade que ela disponibiliza para o usurio. Para diminuir um pouco, ou se voc prefere, para no assustar muito ao usurio dividi a parte central da tela em trs partes: 1a. Parte. Mostra os dados em forma de uma FICHA, como se o usurio estivesse navegando em uma gaveta dessas de bibliotecas e vasculhando as fichas que ele deseja utilizar, servindo tambm 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 necessria para que o usurio possa ver os dados num bloco, de maneira rpida e eficiente. 3a. Parte. Fica a cargo das pesquisas, relaes e filtragens o que o usurio quiser fazer para poder visualizar seus dados da forma como ele julgar melhor.

Criando o Geral
Para comearmos abra o sistema e a partir do Menu Principal clique em File | New Form criando um novo formulrio que ser a nossa rea de trabalho, vamos aos passos: 1. Altere as seguintes propriedades desta janela: 1.1. BorderStyle - bsDialog - Uma janela dilogo padro. 1.2. Name - F_Ficha. 1.3. Position - poScreenCenter - A janela aparecer centralizada no vdeo.

Importante - salve o formulrio com o nome de fFicha, e de vez em quando v salvando para no perder o
servio. 2. Na Component Pallete localize uma pgina chamada Additional e dentro dessa pgina 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 botes, organize-os do lado esquerdo, um abaixo do outro deixando um espao maior entre o quarto e quinto. Altere as seguinte propriedades dos quatro primeiros: 1 2 3 4 janela. 2.2. Altere a propriedade ShowHint de todos para True. 3. Na Component Pallete ainda na pgina Additional dentro dessa pgina de um clique no objeto SpeedButton (prendendo-o com a tecla Shift) e d dez cliques no Form, solte o objeto, foram criados dez botes pequenos, dois coloque-os no espao entre o ButDelete e o BitBtn5 e estique-os para ficarem do mesmo tamanho, os outros oito organize-os na parte de baixo do formulrio. Altere as seguinte propriedades: 1 2 3 4 5 6 Glyph ImgInsLote ImgDuplFicha ImgPrimeiro ImgVoltaSalto ImgAnterior ImgAvanca Name ButFixIns ButDupField ButFirst ButRW ButPrior ButNext Caption Hint Ins. &Lote Insere um conjunto de fichas &Dupl.Ficha Duplica determinada Ficha quando Inserir Primeira Ficha Volta o Salto das Fichas Ficha Anterior Prxima Ficha Glyph ImgInsere ImgGrava ImgCancela ImgElimina Name ButInsert ButPost ButCancel ButDelete Caption &Insere &Grava &Cancela &Elimina Hint Inclui uma nova ficha Grava as alteraes realizadas na ficha Cancela as alteraes realizadas na ficha Apaga a Ficha corrente

2.1. Para o quinto boto altere a propriedade Kind para bkClose, e altere a propriedade Hint para Fecha esta

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 114/178

7 8 9 10

ImgAvancaSalto ImgUltimo ImgMarca ImgVaiMarca

ButFF ButLast ButMark ButGotoMark

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 pgina 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 pgina Data Access clique no objeto DataSource e d um clique no Form e altere a propriedade Name para dsVisao. 7. Na Component Pallete, na pgina 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 pgina 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 pgina 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 pgina Standard clique no objeto Label e d um clique no Form colocando no espao entre os objetos ButPrior e ButNext e altere a propriedade Caption para Valor Salto. 11. Na Component Pallete, na pgina 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:

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 115/178

Criando o Separador das Partes


Toda essa parte de botes e apenas o acessoramento que servir para substituir com muito mais eficincia um padro adotado desde o Delphi 1.0, a famosa Barra de Navegao, ou seja o objeto DBNavigator, no 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 botes e sem querer acabei foi conseguindo complicar bastante a cabea dos meus usurios, ento resolvi descart-lo e colocar toda a sua funcionalidade nesta tela.

Importante - Ainda na terceira parte desta janela criaremos mais alguns botes para completar a barra que eu tinha
desenvolvido, mas voc pode notar a ausncia do boto Edio ou Alterao, o Delphi permite entrada direta em modo de Edio, basta que para isto o usurio comee a digitar os dados e depois ou gravar uma determinada Ficha ou simplesmente comear a navegar os dados, caso ele deseje pode tambm Cancelar o processo, veja bem criei esta janela para facilitar a vida do usurio, no para prend-lo a uma regra ou a um conjunto, voc notar que em momento nenhum desabilito ou habilito qualquer destes botes (a excesso do butMark e butGotoMark). Para dividir a tela em trs partes utilizei um objeto PageControl associado a figuras para ficar mais familiar ao usurio, vamos construir este preparatrio antes de continuarmos. 12. Na Component Pallete, na pgina 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:

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 116/178

12.1. Clique no boto Add... e localize a figura ImgFicha, e clique no boto abrir, ela ser a posio 0, insira as imagens ImgTabela e ImgFormCons. Clique no boto OK e saia do editor. 13. Na Component Pallete, ainda na pgina Win32 clique no objeto PageControl e d um clique no Form, acerte-o para ocupar o espao vazio do formulrio e altere a propriedade Images para ImageList1 e a propriedade Name para PgPrincipal. 14. Clique neste objeto criado com o boto Direito do mouse e escolha a opo NewPage, uma nova pgina ser criada, altere a propriedade Caption para Ficha e propriedade Name para TabFicha. 15. Novamente clique no objeto PgPrincipal com o boto Direito do mouse e escolha a opo NewPage, mais uma nova pgina ser criada, altere a propriedade Caption para Tabela e propriedade Name para TabTabela. 16. Finalmente clique no objeto PgPrincipal com o boto Direito do mouse e escolha a opo NewPage, mais uma nova pgina 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 atrs do objeto PgPrincipal, isto
no tem importncia pois quando em modo de execuo estes objetos ficaro invisveis.

Criando a Primeira Parte


Ateno que esta a parte mais difcil e complicada, voc aqui simplesmente no vai fazer nada, deixe exatamente do jeito que est, utilizaremos esta parte apenas nos formulrios que criaremos por herana.

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 no aparecem, solucionei este problema, dividindo esta parte em mais trs 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 pgina Win32 clique no objeto PageControl e d um clique no Form, e altere a propriedade Align para AlClient e a propriedade Name para PgTabela.

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 117/178

18. Clique neste objeto criado com o boto Direito do mouse e escolha a opo NewPage, uma nova pgina ser criada, altere a propriedade Caption para Dados e propriedade Name para TabTDados. 19. Dentro desta pgina na Component Pallete, clique na pgina Data Controls clique no objeto dbGrid e d um clique nesta pgina, 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 boto Direito do mouse e escolha a opo NewPage, mais uma nova pgina ser criada, altere a propriedade Caption para Imagem e propriedade Name para TabTImagem. 21. Dentro desta pgina na Component Pallete, clique na pgina Data Controls clique no objeto dbImage e d um clique nesta pgina, altere a propriedade Align para AlTop e a propriedade DataSource para DsVisao 22. Ainda dentro desta pgina na Component Pallete, clique na pgina Standard clique no objeto Label e d um clique nesta pgina, altere a propriedade Caption para Campo e a propriedade Font para Estilo: Negrito e Cor: Castanho. 23. Ainda dentro desta pgina na Component Pallete, ainda na pgina Standard clique no objeto ComboBox e d um clique nesta pgina, 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 pgina na Component Pallete, ainda na pgina 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 boto Direito do mouse e escolha a opo NewPage, mais uma nova pgina ser criada, altere a propriedade Caption para Texto e propriedade Name para TabTTexto.

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 118/178

26. Dentro desta pgina na Component Pallete, clique na pgina Data Controls clique no objeto dbMemo e d um clique nesta pgina, altere a propriedade Align para AlTop e a propriedade DataSource para DsVisao 27. Ainda dentro desta pgina na Component Pallete, clique na pgina Standard clique no objeto Label e d um clique nesta pgina, altere a propriedade Caption para Campo e a propriedade Font para Estilo: Negrito e Cor: Castanho. 28. Ainda dentro desta pgina na Component Pallete, ainda na pgina Standard clique no objeto ComboBox e d um clique nesta pgina, 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 pgina na Component Pallete, ainda na pgina 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 pgina Additional dentro dessa pgina de um clique no objeto SpeedButton (prendendo-o com a tecla Shift) e d cinco cliques nesta pgina, solte o objeto, foram criados cinco botes 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 pgina Standard dentro dessa pgina de um clique no objeto Label (prendendoo com a tecla Shift) e d cinco cliques nesta pgina, solte o objeto, coloque-os ao lado de cada boto, altere a propriedade Font de todos para Cor: Azul-Marinho. E altere a propriedade Caption de cada para: 1 2 3 4 5 Caption Ativa as opes para se criar um Filtro, o Filtro permite uma seleo das fichas mostradas, limitando-as. Desativa um filtro. Localiza determinada Ficha. Imprime todas as fichas, limitando-as caso haja filtro ativo. Envia a ficha corrente para rea de transferncia. Compare como ficou:

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 119/178

Criando os Acessores na D_Modelo


Antes de continuarmos, abra a unidade D_Modelo e crie os seguintes objetos: Na Component Pallete na pgina chamada Dialogs e dentro dessa pgina traga um objeto SelectDlgT, um objeto DgPrint e um objeto DgFiltro. Altere a propriedade Name para SelPesquisa, PrtPesquisa e FilPesquisa respectivamente.

Codificando
A codificao deste formulrio no to 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 no utilizei nada estranho 1. Alterne para o Code Editor e localize a seguinte poro do cdigo: 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 formulrios terceiros procedure TF_Ficha.ChamaExterno(var Tab: TTable; aFormClass: TFormClass); begin Screen.Cursor := crHourGlass;

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 120/178

Tab.Close; with aFormClass.Create(Application) do try ShowModal; finally Free; end; Tab.Open; Screen.Cursor := crDefault; end;

Importante
elas:

- Coloque na primeira declarao do USES (fica logo abaixo da Seo interface) a unidade DBTables pois o procedimento ChamaExterno faz uso do objeto TTable que faz parte desta biblioteca.
Aqui foram criadas algumas variveis para uso particular do programa ou seja s funcionaro aqui dentro, so FBM: Ponteiro para guardar a posio do arquivo quando for disparado o boto Marca Registro. ChDuplica: Booleana que diz se ou no para Duplicar um registro marcado. fTrava: Booleana que informa se o Insero em Lote foi ou no ativada. FiltroVisto: Caso a tabela est com o filtro ativo criado e armado pelo usurio. Foi criada tambm um procedimento pblico para poder criar e chamar formulrios secundrios, este procedimento ser visto com mais detalhes a frente. 2. Para o evento onShow do Formulrio 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 trs segmentos, do tipo comum, do tipo texto e do tipo imagem, isto para ser colocado na segunda parte do formulrio quando o usurio ter a viso da tabela

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 121/178

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 Pgina FICHA como inicial, na segunda pgina ativa a Pgina DADOS como principal, atualiza o objeto PosEstado1, acerta a varivel 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 boto Insere ativa o comando Insert da tabela e verifica se est em modo de Duplicao da Ficha, se estiver transfere todos os dados da Query pblica 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 boto Grava ativa o comando Post da tabela e verifica se est em modo de Insero de Lote, se estiver chama o procedimento de incluso, caso contrrio 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 boto Cancela ativa o comando Cancel da tabela e verifica se est em modo de Insero de Lote, se estiver chama o procedimento de incluso, caso contrrio atualiza o objeto PosEstado1. 6. Para o evento onClick do objeto ButDelete procedure TF_Ficha.ButDeleteClick(Sender: TObject); begin

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 122/178

with dsVisao.DataSet do Delete; PosEstado1.Atualiza; end; Quando for pressionado o boto 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 boto Insere Lote pode acontecer dois momentos o primeiro pressionamento trava e o segundo pressionamento libera, acerta a varivel de controle, coloca o boto pressionado (ou despressionado conforme o caso), desabilita (ou habilita conforme o caso) o boto de excluso e se for para travar chama o procedimento de incluso. 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 boto 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 boto Salto para Trs 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 boto 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 boto Prximo Registro ativa o comando Next da tabela. 12. Para o evento onClick do objeto ButFF

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 123/178

procedure TF_Ficha.ButFFClick(Sender: TObject); begin with dsVisao.DataSet do moveby(StrToInt(mskSalto.Text)); end; Quando for pressionado o boto 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 boto 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 boto Marca Registro acerta o ponteiro BookMark para guardar a posio 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 boto 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 boto Abre Filtro seta os parmetros 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

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 124/178

boto e habilita o boto 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 boto Fecha Filtro limpa o filtro da tabela e desabilita este boto e habilita o boto 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 boto Localiza Registro seta os parmetros para o objeto SelPesquisa localizado na D_Modelo e depois executa-o, antes guarda em um ponteiro do tipo BookMark a posio da tabela, caso seja devolvida uma resposta negativa retorna a posio 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 := 'Impresso'; NomeRel := 'Relao de'; Filtro := Filter; Execute; end; end; Quando for pressionado o boto Imprime Dados seta os parmetros 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;

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 125/178

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 boto Copia para rea de Transferncia utiliza-se do objeto invisvel MemClip, com o auxlio 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 Transferncia. 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 posio do combo que contm os campos em formato Texto da pgina Tabela faz as alteraes necessrias 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 posio do combo que contm os campos em formato Imagem da pgina Tabela faz as alteraes necessrias 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 Insero de Registros em Lote realizada da seguinte forma, disparado um comando Insert para a tabela e posicionado no primeiro campo, o usurio 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, ento confirmaremos a gravao do registro digitado, chamando o procedimento para tal, e retornaremos para o primeiro campo.

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 126/178

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 boto Duplica Registro far com que esta trenheira (gostei do trenheira) de cdigo seja executado, simples, com o auxlio do objeto Query pblico da D_Modelo (Objeto QrySQL) geraremos um comando SQL que quando disparado conter o registro atual, apenas ele, aps isto basta com que aps cada comando Insert copiemos campo a campo do objeto Query para a Tabela. 25. Para o evento onClose do Formulrio 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;

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 127/178

Antes do usurio 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 Pblico da D_Modelo.

Finalmente
Na prxima apostila criaremos a primeira utilizao deste formulrio atravs da Herana dos Objetos.

Dvidas das Apostilas Anteriores


Como fao para criar tabelas relacionadas ? Use o gerenciador do banco de dados para isso ou voc quer cri-los via programao ? se sim no faa isso pois os comandos variam muito de banco para banco. Posso relacion-las no Access ? Claro, mas lembre-se que alguns bancos no permitem o relacionamento de Alterao e Excluso em cascata como o Access permite, entaum se vc quer um sistema porttil no utilize essa opo mesmo sendo ela muito prtica. ou uso MasterSource ? Voc no relaciona tabelas com as opes MasterSource e MasterFields o que voc faz criar um indice virtual, isso apenas serve para controlar entradas e vises dos dados nada mais. Qual a melhor soluo ? 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 prprio banco mas sempre tomando o cuidado para que o sistema naum deixe passar besteiras, acredito que vc prprio saber o que melhor para seu sistema pois cada caso uma sentena. A minha duvida com relao ao Access/Multiusuario, isto possvel? Sim ele um banco multiusurio, ou controlado o acesso livremente ou por determinados usurios com determinadas permisses. e com relao a distribuio? Veja a apostila 4 como criar o Install Shield para isto. Com o Access isto tambm acontece? A forma de acesso ao Access pelo DAO, seu cliente precisa t-lo ou vc a permisso 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 disponvel no endereo 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 conexo com ele sem problemas ento deixe a IDDAO32.DLL

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 128/178

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 configuraes que voc fala na sua Home Page, desabilitei o boto 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 so todos para a verso 3.02 do Delphi. Ser que os meus problemas so por causa da minha verso do Delphi ??? Onde posso arrumar um uprade para atualizar a minha verso de Delphi ??? Sempre em modo de edio 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 verso 3.02, primeiro vc tem que pegar aonde vc comprou o Delphi a verso 3.01, depois vc vai no prprio site da Inprise e pega a atualizao para 3.02, ATENO: No 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. prefervel 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 Querys eram indiscutivelmente mais rpidos e prticos que os Tables mas se vc est utilizando o Delphi 3.0 ou Delphi 4.0 a Inprise j corrigiu e acertou os objetos Tables, ento aconselho que vc os utilize. Qual a melhor maneira de procurar um registro usado query ? Pode ser o Locate ? Usando a clusula Where. Como devo fazer a consitencia do meu sistema para no deixar que registros duplicatos sejam cadastrados ? Fao 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 opo so Edits ? Os DBEdit so melhores. Os indces, ou By Order, ...Permito que o usrio escolha a ordem dos dados? Neste caso coloquei no evento OnTitleClick do DBGrid o seguinte cdigo. 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 opo ? Se vc est utilizando Querys para cadastrar , mas eu naum recomendo seu uso depois do Delphi 3.0.

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 129/178

Em um sistema, 60% se resume em inclui, altera, exclui,consulta. Se eu estiver equivocado por favor me corrija... No 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 no pode morrer ou modificar sua chave se ouverem FILHOS atrelados a eles. Para o Delphi isso serve pois vc no 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 dvida, rpido, prtico e seguro, utilizo o BDE para manter a integridade e portabilidade dos sistemas para qualquer banco de dados, no 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 visualizao dessas imagens? Se isto for possvel(eu sei que , s no sei como) quais os formatos alm 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 funo que faa isso. Existe algum componente que permite a "Justificao" de texto nos relatrios 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 notcias. Suponha que eu tenho 5 micros ligados em rede win95 com nenhum computador servidor dedicado(apenas compatilhamento de arquivos e hardware). Seria possvel a utilizao do programa Mapa criado nas apostilas 2,3,4 e todo a rede, elegendo por exemplo, o micro1 como local de instalao do programa e do banco de dados? Em todos os micros temos instalados os mesmo programas (Access97, win95 e bde 4.51) possvel 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 instrues da nova apostila 4.

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 130/178

Curso de Delphi 4.0 - Apostila 12


Autor: Fernando Antonio Fernandes Anselmo E-Mail: fernandoanselmo@yahoo.com.br
Pr-Requisitos: Windows 98 Delphi 4.0 verso Client/Server Suite BDE 5.00 MS-Access 97 Arquivos trabalhados juntos com esta apostila: Formulrio : F_Ficha (criado na Apostila 11) Objetos: DBCmpList DBDateEdit97 Seguintes Imagens : ImgLamp.BMP ImgTerc.BMP ImgTele.BMP

Prefcio
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 construo de um formulrio que servir como base de todos os cadastros, neste mostrarei como utilizar o formulrio criado, lembre-se que definimos quatro cadastros: Cidade, Grupo, Alimento e Cliente. Aqui criarei o formulrio para o Cadastro de Cliente que o mais complexo de todos, ento caber a voc, aps este, a criao dos formulrios para os cadastros de Cidade, Grupo e Alimento.

Como utilizar a Herana


A coisa que mais falei na apostila passada foi no tocante a Herana, ento 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 pgina Peso, escolha o formulrio F_Ficha e clique em Ok. Pronto, primeiramente vamos comear bem devagar, neste momento foi criado uma cpia, um espelho ou se voc prefere um novo objeto formulrio baseado por herana no objeto formulrio F_Ficha. NO altere neste formulrio criado qualquer posio dos botes, NO faa modificaes na janela, NADA. Se tiver que fazer este tipo de alterao faa no formulrio F_Ficha pois deste modo automaticamente todos os outros formulrios que foram herdados sero alterados. Altere aqui o extritamente necessrio, pois cada alterao causa um desvnculo da herana. Para este objeto altere apenas as seguintes propriedades: 1.1. Name: F_Cliente 1.2. Caption: Cadastro de Clientes... 1.3. Salve o formulrio com o nome de fCliente.PAS Note que precisamos preencher o miolo da primeira parte (A pgina da ficha propriamente dita), para tanto:

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 131/178

2. A partir do Menu Principal v em File | New... e v na pgina Business, escolha o formulrio "Database Form Wizard" e clique em Ok: 2.1. O tipo do formulrio a ser criado. Para a opo Form Options marque Create a simple form (Um formulrio simples) e para a opo DataSet Options marque Create a form using TTables objects (Usando o objeto tabela) e clique no Boto Next. 2.2. A tabela a ser usada para o formulrio. Para a opo Drive or Alias name localize o Alias AlPeso e para a opo Table Name marque Cliente e clique no Boto Next. 2.3. Campos a serem inseridos clique no Boto ">>" para ser inserido todos os campos e clique no Boto Next. 2.4. Clique na opo Vertically para a formao dos campos na Vertical e clique no Boto Next 2.5. Posio dos Labels deixe marcada a opo Left (A esquerda) e clique no Boto Next 2.6. Completo. Desmarque a opo Generate a main form (Gera a tela como form principal) e na opo Form Generation marque Form e clique no Boto Finish. 3. Agora selecione todos os campos e respectivos labels e digite CTRL+C v para o formulrio F_Cliente e clique na pgina Ficha selecione a pgina e digite CTRL+V d uma arrumada nos campos, voc deve conseguir algo como isto:

Este segundo formulrio criado j serviu para seu propsito pode fech-lo cancelando qualquer procedimento para sua gravao.

Importante - Existem vrias maneiras de se criar este formulrio 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 Labels, altere as seguintes propriedades de todos: 4.1. Propriedade Caption (respectivamente): CPF: Nome: Endereo: Bairro: CEP: Cidade: eMail: Altura:

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 132/178

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 espao entre o campo CEP e eMail e elimine o objeto EditSIG_CIDADE, e na pgina Data Controls localize o objeto DBCmpList e coloque-o no lugar deste.

Importante - Abra o Data Module D_Modelo, volte para o formulrio F_Cliente e alterne para a janela do
programa e insira a seguinte declarao aps a diretiva de compilao: {$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. Desa-o para o espao aberto entre os campos CEP e eMail 7.2. CapLocaliza: Localiza determinada Cidade 7.3. Caption: 7.4. CriticaEd: False 7.5. DataSource: DsVisao (Ateno: No marque, caso aparea 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 no localizada 7.10. MensagemDescricao: Cidade no 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 pgina Additional e coloque um objeto SpeedButton em cima do objeto CmpCidade ao lado do boto 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

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 133/178

10. Altere a propriedade Font de todos os campos para Font.Color = clNavy e organize a propriedade TabOrder para colocar os campos na sequncia. O trabalho final ficou desta maneira:

Criando Mais uma Orelha


Note atravs 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 mtodo para o cadastro desse tipo. 11. D um Duplo-Clique no objeto ImageList1, clique no boto Add... e insira a imagem ImgTele.BMP (enviada) 12. Clique no objeto PgPrincipal e depois clique com o boto direito no sub-menu que aparece clique na opo New Page. 13. Para esta nova pgina criada altere as seguintes propriedades: 13.1. Caption: Telefones 13.2. Name: TabTelefone 14. Crie agora trs 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:

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 134/178

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 propriedades: para a coluna 0 FieldName: NUM_TELEFONE Font.Color: clNavy Title.Caption: Nmero do Telefone Title.Font.Color: clMaroon Title.Font.Style: [fsBold] Width: 200 para a coluna 1 FieldName: DES_FUNCAO Font.Color: clNavy Title.Caption: Funo PickList: Voz; FAX; Voz e FAX; PABX (Um em cada linha) Title.Font.Color: clMaroon Title.Font.Style: [fsBold] Width: 104 No vamos nos preocupar aqui com os detalhes de controlar qual telefone e de qual cliente pois esta amarrao foi realizada no DataModule atravs do objeto tbTELEFONE_CLIENTE, veja como ficou esta nova pgina: , altere as seguintes

Difcil Programao
Voc vai se surpreender com a programao criada aqui, a maior parte do trabalho ficou com o formulrio anterior, este a apenas um espelho do passado e sua programao quase mnima e teremos apenas trs trabalhos, vamos a ela:

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 135/178

1 Trabalho. Abrir as tabelas. Para tanto selecione o evento OnShow do formulrio:


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 trs variveis na Seo Particular do Objeto: private Tab1, Tab2, Tab3 : Boolean; Uma explicao geral a seguinte, sempre que abro um formulrio de cadastro abro respectivamente as tabelas que ele utiliza na D_Modelo, mas como um formulrio pode chamar outro formulrio ento corrijo isso atravs de variveis locais que armazenam se a respectiva tabela j se encontrava ou no aberta quando o formulrio foi ativado.

Importante - Aqui a ordem dos tratores altera o viaduto, o objeto DBCmpList exige que a tabela secundria
(tbCidade) seja aberta primeiramente que a tabela que sero gravados os dados (tbCliente). Um outro comando que voc pode estranhar o comando inherited ele o responsvel por chamar os comandos que esto localizados no evento OnShow do formulrio Pai.

2 Trabalho. Fechar as tabelas. Para tanto selecione o evento OnClose do formulrio:


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;

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 136/178

Aqui relativamente simples, atravs da funo CriticaEdicao que ser montada na D_Modelo verifica-se se o estado da tabela Cliente est em estado de Edio ou Insero em caso positivo, podemos cancelar a Edio ou cancelar o Fechamento da janela. Na segunda parte devolvemos o estado original das tabelas.

Importante - Novamente a ordem dos camares altera o vatap, o objeto DBCmpList exige que a tabela que sero
gravados os dados (tbCliente) seja fechada primeiramente que a tabela secundria (tbCidade).

3 Trabalho. o boto responsvel 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; No se esquea de declarar o formulrio utilizado na USES: uses dModelo, fCidade; Esse foi moleza pois basta que chamemos a funo ChamaExterno localizada no formulrio F_Ficha, note que por ser uma funo localizada no objeto que herdamos no precisamos nem fazer a referncia para ela.

Alterando a D_Modelo
Lembra-se que na apostila referente ao DataModule avisei que algumas funes seriam posteriormente includas ? Ento vamos comear estas incluses: Funo Responsvel pela Verificao do Estado de uma Tabela: 1. Abra o DataModule D_Modelo atravs do Code Editor e localize a seo Public, insira o seguinte cabealho para a declarao da funo coloque-o abaixo da declarao das variveis: 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. Aps a diretiva de compilao 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('Necessrio cancelar a edio (ou Incluso) ' + Doque + ' antes de ' + AntesDe + '. Deseja sair agora ?', mtConfirmation, [mbYes, mbNo], 0) else result := mrNone; end; Vamos a uma explicao geral, a funo relativamente simples, ela recebe trs variveis sendo uma delas um objeto inteiro, uma coisa fantstica na linguagem Object Pascal a possibilidade de passar objetos inteiros atraves de funes ou procedimentos, so passados os seguintes:

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 137/178

DSOrigem : DataSource que ser analisado DoQue : Ajuda na montagem da mensagem, "Do que ser cancelada a tarefa ? " AntesDe : Complemento da mensagem do modo de edio Ento caso o DataSource passado esteja em estado de Edio ou insero ser mostrada a seguinte mensagem "Necessrio cancelar a edio (ou Incluso) Contedo_Doque antes de Contedo_AntesDe. Deseja sair agora ?" e mostrado dois botes "Sim" ou "No" o resultado ser um dos dois, caso contrrio ser devolvido um resultado mrNone. Funo Responsvel pela crtica do CPF do Cliente: 1. Localize agora a seo Private, e insira o seguinte cabealho para a declarao da funo: private function Maximo(nmCampo, nmTabela: String) : integer; function Critica_CPF(sNumCpf: String) : Boolean; 2. Aps a diretiva de compilao 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 cdigos: procedure TD_Modelo.tbClienteNUM_CPFValidate(Sender: TField); begin if not Critica_CPF(tbClienteNUM_CPF.Value) then Raise Exception.Create('CPF no confere com o da Receita Federal'); end; A funo o clculo do famoso MDULO 11, voc j deve ter ouvido falar isso vrias vezes, o clculo para o primeiro dgito feito pegando-se os nove primeiros nmeros do CPF e multiplicando-os da seguinte maneira, o primeiro por 10, o segundo por 9 e assim sucessivamente at o nono nmero por 2, e este valor somado (isto realizado no segundo comando FOR) aplicada a seguinte equao: Digito1 = 11 - Resto( Soma / 11)

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 138/178

A funo MOD d exatamente o resto de uma diviso. Se o valor deste primeiro dgito for maior que 9 o resultado 0, adiciona-se este digito aos outros nove e realiza-se uma nova multiplicao com os 10 nmeros da seguinte maneira, o primeiro por 11, o segundo por 10 e assim sucessivamente at o dcimo nmero por 2, aplica-se a mesma fmula anterior para encontrar o resultado do segundo dgito.

Importante - Neste sistema no precisaremos, mas vou colocar aqui os cdigos caso voc precise, da funo para
a crtica 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 formulrio F_Menu para fazer a insero dos comandos para chamar o formulrio: procedure TF_Menu.Cliente1Click(Sender: TObject); begin F_Cliente := TF_Cliente.Create(Application); F_Cliente.ShowModal; F_Cliente.Free; end; Tambm chame a partir do menu principal Project | Options... e retire o formulrio F_Cliente da rea dos Auto-Create forms (retire tambm o F_Ficha caso voc ainda no o fez)

Importante - Este formulrio precisa do Formulrio F_Cidade j criado para funcionar.


Agora cab a voc a criao dos formulrios F_Cidade, F_Grupo e F_Alimento. At a prxima.

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 139/178

Curso de Delphi 4.0 - Apostila 13


Autor: Fernando Antonio Fernandes Anselmo E-Mail: fernandoanselmo@yahoo.com.br
Pr-Requisitos: Windows 98 Delphi 4.0 verso 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

Prefcio
Salve, nesta apostila comearemos as primeiras movimentaes do nosso projeto. A movimentao basicamente dividida em duas fases: dados de Entrada ou dados de Sada, nesta vamos analisar a movimentao para Dados de Entrada. Esta fase deve ser lembrada como um formulrio fcil e simples para que o usurio no se confunda com o processo que ele realizar.

Entrada de Clientes
Inicialmente vamos construir a parte da movimentao 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 formulrio 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:

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 140/178

Observao: 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 formulrio F_Entrada e alterne para a janela do programa e insira a seguinte declarao aps a diretiva de compilao:
{$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

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 141/178

8.1.2. DataField: PLN_ADOTADO 8.1.3. Font.Color: clNavy 8.1.4. Items: (Um por Linha) Plano Anti-Stress Plano Reeducao Plano Completo Plano Especial de Reeducao 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 sequncia correta. 11. Abaixo do Objeto Panel1 crie trs 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:

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 142/178

Programando a Entrada
Lembre-se, a programao aqui uma coisa rpida direta, ela no deve ser aplicada em situaes de risco, como por exemplo um cadastro. 1. Inicialmente alterne para a Code Editor e na seo Private crie a seguinte chamada para o procedimento: private procedure AcertaInsercao; public 2. Agora abaixo da diretiva de compilao 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 incluso na tabela Pasta Cliente. 3. Selecione agora o evento OnShow do formulrio: 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;

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 143/178

Toda vez que o formulrio for ativado, e aberta a tabela acessria tbCliente e organizado os campos dentro do objeto SelPesquisa localizado na D_Modelo, depois aberta a tabela em que ser realizada toda a movimentao a tbPasta_Cliente e chamado o procedimento particular para coloc-la em estado de insero. 4. Selecione o evento OnClose do formulrio: 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 insero da tabela principal. 5. Vamos comear com os botes, primeiro o boto responsvel para realizar a Gravao 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 no informado'); if LabNOM_CLIENTE.Caption = '' then raise exception.create('Cliente no cadastrado'); D_Modelo.tbPasta_Cliente.Post; AcertaInsercao; end; Fazemos duas crticas simples apenas para controlar se o CPF foi preenchido e se o nome do cliente foi encontrado (o que significar que o cliente existe), ento gravamos o dado e simplesmente chamamos o procedimento para reativar o estado de insero. 6. O segundo boto o responsvel 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 insero.

Programando o Cliente
A ligao 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, ento 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

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 144/178

if FindKey([EditNUM_CPF.Text]) then LabNOM_CLIENTE.Caption := FieldByName('NOM_CLIENTE').AsString else begin EditNUM_CPF.SetFocus; raise exception.create('Cliente no cadastrado'); end; end; Inicialmente verificamos se foi preenchido algo no campo, ento pesquisamos na tabela Cliente com o valor informado, caso encontre coloca o nome do cliente no Label destinado para tal, caso contrrio volta o cursor para o objeto EditNUM_CPF e mostra a mensagem de erro. 2. O primeiro o boto localizado depois do campo o responsvel 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; So 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 no estar cadastrado e o usurio ser obrigado a sair da tela em que se encontra e cadastrar o cliente e depois retornar, para evitar isto o segundo boto o responsvel 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 formulrio de Cliente, exatamente como feito no menu principal, no se esquece de adicionar o formulrio fCliente a clusula USES.

Massa Corporal
Outro exemplo de movimentao de entrada o formulrio para fazer a Massa Corporal, o momento em que o Cliente pesado e sua massa mostrada em um clculo (Recorde este clculo 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 formulrio 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

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 145/178

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 formulrio F_Entrada e alterne para a janela do programa e insira a seguinte declarao aps a diretiva de compilao:
{$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

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 146/178

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 sequncia correta. 10. Abaixo do Objeto Panel1 crie trs 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 programao aqui uma coisa rpida direta, ela no deve ser aplicada em situaes de risco, como por exemplo um cadastro. 1. Inicialmente alterne para a Code Editor e na seo Private crie a seguinte chamada para o procedimento:

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 147/178

private procedure AcertaInsercao; public 2. Agora abaixo da diretiva de compilao 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 incluso na tabela Peso Cliente. 3. Selecione agora o evento OnShow do formulrio: 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 formulrio for ativado, e aberta a tabela acessria tbCliente e organizado os campos dentro do objeto SelPesquisa localizado na D_Modelo, depois aberta a tabela em que ser realizada toda a movimentao a tbPeso_Cliente e chamado o procedimento particular para coloc-la em estado de insero. 4. Selecione o evento OnClose do formulrio: 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 insero da tabela principal. 5. Vamos comear com os botes, primeiro o boto responsvel para realizar a Gravao 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 no informado'); if LabNOM_CLIENTE.Caption = '' then raise exception.create('Cliente no cadastrado'); D_Modelo.tbPeso_Cliente.Post; AcertaInsercao; end;

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 148/178

Fazemos duas crticas simples apenas para controlar se o CPF foi preenchido e se o nome do cliente foi encontrado (o que significar que o cliente existe), ento gravamos o dado e simplesmente chamamos o procedimento para reativar o estado de insero. 6. O segundo boto o responsvel 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 insero.

ltimos Passos
Um passo, que at poderia copiar o Programando o Cliente, mas ao invs de repetir todos os comandos prefiro que voc volte e veja na seo anterior como isso feito. A principal parte diferente aqui quanto ao clculo da massa corporal, ento 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 Mrbida)'; end; end; Pronto, na sada da informao do peso, calculada a massa corporal, apensa se existir um cliente pois precisamos saber da altura do cliente para o clculo de sua massa, novamente vou frisar que se voc no lembra como realizado isto recorra a apostila referente ao Levantamento dos Dados.

Finalmente
Agora basta voc voltar para o formulrio F_Menu para fazer a insero dos comandos para chamar os formulrios: procedure TF_Menu.EntradadoCliente1Click(Sender: TObject); begin F_Entrada := TF_Entrada.Create(Application); F_Entrada.ShowModal; F_Entrada.Free; end;

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 149/178

procedure TF_Menu.MassaCorporal1Click(Sender: TObject); begin F_Massa := TF_Massa.Create(Application); F_Massa.ShowModal; F_Massa.Free; end; Tambm chame a partir do menu principal Project | Options... e retire os formulrios F_Entrada e F_Massa da rea dos Auto-Create forms. Na prxima apostila vamos criar uma movimentao um tanto mais complexa, portanto esteje preparado.

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 150/178

Curso de Delphi 4.0 - Apostila 14


Autor: Fernando Antonio Fernandes Anselmo E-Mail: fernandoanselmo@yahoo.com.br
Pr-Requisitos: Windows 98 Delphi 4.0 verso 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

Prefcio
Salve, nesta apostila vamos concluir as movimentaes do nosso projeto. Nesta segunda fase mostrarei como coordenar dados de Sada, no associe os dados de sada como retirada ou qualquer outra coisa parecida, na verdade so dados j colocados nas tabelas mas que faltam a informao final, aquele famoso Tchan para ficar completo.

Sada de Clientes
Vamos construir a parte da movimentao relativa a Sada 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: Sada de Clientes 1.3. Name: F_Saida 1.4. Position: poScreenCenter 1.5. Salve o formulrio com o nome de fSaida.PAS

Importante - Abra o Data Module D_Modelo, volte para o formulrio F_Saida e alterne para a janela do
programa e insira a seguinte declarao aps a diretiva de compilao: {$R *.DFM} uses dModelo; 2. Crie um objeto do tipo DataSource e altere as seguintes propriedades: 2.1. DataSet: D_Modelo.tbPasta_Cliente

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 151/178

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 Prximo 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 Observao: Dt.Pagamento: Valor: Desconto: Total a Pagar: 7.2. Propriedade Font para: Font.Color = clMaroon Font.Style = [fsBold]

Importante - Aqui vo algumas observaes:


a. Deixe um espao entre o label Cliente e Dt.Chegada b. O label KCal fica na frente do Label Qtd.Caloria com um espao para colocar um campo c. Deixe um espao entre o Label Qtd.Caloria e o label Observao 8. Crie dentro do objeto Panel2 um objeto do tipo Bevel e altere as seguintes propriedades 8.1. Shape: bsBottomLine

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 152/178

Importante - Este objeto foi criado apenas para separar os dados, coloque-o entre os Labels Qtd.Caloria e
Observao 9. Crie dentro do objeto Panel2 trs 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 trs ltimos objetos para uma sequncia 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 Padro 15.4. Name: ButCalcDesconto

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 153/178

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 Sada
A programao aqui (ainda bem que estamos tratando do Delphi) no algo to complicado, pode ser se voc desejar colocar coisas homricas, a idia que o usurio localize na tabela Pasta Cliente a entrada deste Cliente, mas lembre-se que o mesmo Cliente pode visitar vrias vezes o SPA ento precisamos restringir os registros, acompanhe

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 154/178

atentamente a codificao: 1. Inicialmente alterne para a Code Editor e na seo Private crie uma varivel para acumular o valor de um desconto dado. private VlDesconto: Double; public 2. Selecione agora o evento OnShow do formulrio: 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 formulrio 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 acessria 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 movimentao a tbPasta_Cliente.

Importante - Abra a tabela ascessria primeiramente (no caso tbCliente), pois existir uma dependncia no evento quando os dados sero mudados do objeto DsPasta_Cliente que necessitar que esta tabela esteje aberta.
3. Selecione o evento OnClose do formulrio: 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 edio (para no acontecer uma gravao equivocada, se o usurio quer gravar ento ele deve apertar o boto Grava) depois de fechada, eliminamos o filtro da tabela, o segundo passo fechar a tabela

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 155/178

secundria, eliminando tambm a dependncia entre as duas tabelas. 4. Vamos comear com os botes, primeiro o boto responsvel para realizar a Gravao 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 no informada'); if EditVAL_TOTAL.Text = '' then Raise Exception.Create('Valor no informado'); D_Modelo.tbPasta_Cliente.Post; end; Fazemos duas crticas simples apenas para controlar se a Data e o Valor de pagamento foram preenchidos, ento simplesmente gravamos o dado. Aqui no precisamos nos preocupar em colocar a tabela em momento de insero pois o Delphi trata isto automaticamente. Tambm, automaticamente, o registro sumir da tela, por causa do Filtro ativo. 5. O boto localizado ao lado da barra de navegao o responsvel 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 sada 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 boto ao lado do EditVAL_DESCONTO o responsvel 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, ento calculamos o desconto com base na varivel VlDesconto. 9. Este agora o corao de todo o formulrio, aqui que a maior parte foi projetada, selecione o objeto

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 156/178

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 Reeducao' 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 Reeducao' 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 := 'Observao: No existe'; LabDesconto.Caption := 'Desconto:'; VlDesconto := 0; if not EOF then begin LabObserva.Caption := 'Observao: 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 no precisamos temer tanto, o brincadeira a seguinte, inicialmente coloquei um procedimento dentro para mostrar no LabDesconto se existe algum desconto cedido, e setar a varivel VlDesconto com este valor.

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 157/178

Comeando 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 ascessria 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 formulrio F_Menu para fazer a insero dos comandos para chamar os formulrios: procedure TF_Menu.SaidadoCliente1Click(Sender: TObject); begin F_Saida := TF_Saida.Create(Application); F_Saida.ShowModal; F_Saida.Free; end; Tambm chame a partir do menu principal Project | Options... e retire o formulrio F_Saida da rea dos Auto-Create forms. Acredito que voc tenha reparado os dois processos de movimentao, na anterior trabalhamos basicamente com o momento INSERT da tabela, era apenas uma entrada simples e bsica, nesta aqui pegamos aqueles dados inseridos e trabalhamos um pouco mais, solicitando mais alguns dados para finalmente finalizarmos este Cadastro. Em movimentaes, tambm possvel, e admissvel, criarmos uma tabela idntica, apenas para servir como arquivamento dos dados, ou seja, aps concluirmos esta segunda fase da movimentao, passar os dados j gravados para uma segunda tabela, tipo um Fechamento. Na prxima apostila vamos comear a analisar como so feitos relatrios.

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 158/178

Curso de Delphi 4.0 - Apostila 15


Autor: Fernando Antonio Fernandes Anselmo E-Mail: fernandoanselmo@yahoo.com.br
Pr-Requisitos: Windows 98 Delphi 4.03 verso Client/Server Suite BDE 5.01 MS-Access 97 Arquivos trabalhados juntos com esta apostila: Objeto : DgOrdena DgFiltro Seguintes Imagens : ImgFiltra.BMP, ImgOrdena.BMP, ImgSalva.BMP, ImgTeste.BMP, ImgImprime.BMP

Prefcio
Salve, vamos agora comear a melhor parte de todo o nosso projeto, Relatrios. Pessoalmente no tenho nada contra eles, s vezes nem eles tem contra mim, mas acredito que com um pouco de cuidado tudo se acerta. Bem para essa primeira parte dos relatrios (sero trs neste projeto) vamos criar o relatrio de Etiquetas de Endereamento, isso mesmo vamos imprimir etiquetas, acho isso uma coisa estremamente divertida principalmente quando o papel engargala (isso existe ?), mas que exige alm de um certo cuidado e tambm uma boa dose de pacincia. Inicialmente j vou avisando aos fs do Quick Report que no irei utiliz-lo para tal servio, o motivo simples Etiquetas no so uma coisa que rimam muito bem com o Windows, a menos que voc utilize o Word ou um software especfico para produz-las descobrir que com o Quick Report, Crystal Report, Report Builder entre outros no so muito amigveis para produzir este tipo de arquivo. Ento vou utilizar aqui os bons e velhos comandos do arquivo Text do Pascal e simplesmente redirecionar para a sada da impressora.

Etiquetas e o Windows
Desde que me entendo trabalhando nesta rea de informtica tenho feito impresso com etiquetas, o pior que existem milhares de modos de faz-las, principalmente porque existem milhares de diferentes etiquetas, ento para esse servio, infelizmente isso varia de cliente para cliente, o do SPA Antes & Depois pediu para que utilizassemos as etiquetas da marca PIMACO referncia 10236MC com 1 Carreira o tamanho da Etiqueta de 102 x 36,1 mm e so 8 etiquetas por folha (anote essas medidas pois elas so muito importantes). Uma coisa importante neste jogo saber em qual impressora vamos imprimir, uma jato de tinta tem o comportamento diferente de uma matricial, bem como as etiquetas so em formulrio contnuo, o cliente resolveu utilizar uma impressora matricial padro Epson FX-100 para fazer este servio. A primeira coisa a fazermos instalar a impressora no Windows, aps instalada coloque como papel padro o Definido pelo Usurio e acerte as medidas em mm para:
Largura: 1200 Comprimento: 410 E coloque 0 na rea no imprimvel (isto so as margens)

Voc pode estar se perguntando como cheguei a to fabulosas medidas ? Simples vrios testes, gastei quase meia caixa de etiquetas testando, isso uma coisa (infelizmente) muito comum a quem se aventurar a fazer este tipo de impresso, voc pode estar se perguntando tambm, mas porque defini o tamanho da pgina no tamanho de uma etiqueta e no das oito ? Simples tambm, o Windows adora ao final de cada impresso mandar um caracter especial de final de pgina que ordena a impressora para se posicionar no comeo da prxima pgina, ento como no gosto de

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 159/178

perder etiquetas, e tambm para no ter que ficar controlando o tamanho das minhas linhas dentro da etiqueta. O que pretendo fazer aqui um trabalho simples, vou criar uma consulta com o que precisa ser impresso e cada linha da minha consulta vou descarregar como um arquivo na sada da minha impressora, isso mesmo se tiver 100 etiquetas para imprimir existir 100 arquivos na sada da minha impressora. Esse o jeito mais fcil ? Isso uma excelente pergunta, talvez voc conhea milhares de outras maneiras de imprimir etiquetas com o Windows, mas considero a maneira como a que vou fazer aqui a mais fcil, simples e eficaz.

Criando o Formulrio
Vamos neste momento criar um pequeno formulrio que servir de auxlio, e tambm para dizer ao nosso usurio o que estamos fazendo: 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: Relatrio de Etiquetas de Endereamento 1.3. Name: G_EtiqEnd 1.4. Position: poScreenCenter 1.5. Salve o formulrio com o nome de gEtiqEnd.PAS

Importante - Abra o Data Module D_Modelo, volte para o formulrio F_Saida e alterne para a janela do
programa e insira a seguinte declarao aps a diretiva de compilao: {$R *.DFM} uses dModelo;

Observao - Note que mudei a primeira letra do formulrio de F para G, adoto a seguinte nomenclatura em meus
forms: F - Cadastro, Tabelas e Movimentaes G - Gerao de alguma coisa especfica R - Relatrios do Quick D - Dados 2. Crie um objeto do tipo TQuery e altere as seguintes propriedades: 2.1. DataBase: DNmPeso 2.2. Name: QryEtq 3. Crie um objeto do tipo TLabel e altere as seguintes propriedades: 3.1. Caption: Selecione sua Opo: 3.2. Propriedade Font para: Font.Color = clMaroon Font.Style = [fsBold] 4. Crie um objeto do tipo TBevel e d uma esticada nele, para que dentro caiba os prximos objetos. 5. Crie cinco objetos do tipo TBitBtn e altere as seguintes propriedades respectivamente: 5.1. Glyph: ImgFiltra ImgOrdena ImgSalva ImgTeste ImgImprime

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 160/178

5.2. Name: ButFiltra ButOrdena ButSalva ButTeste ButImprime 5.3. Caption: Fil&tra &Ordena &Salva &Teste &Imprime 6. Crie mais um objeto do tipo TBitBtn, colocando-o para fora do objeto TBevel e altere as seguintes propriedades: 6.1. Kind: bkClose 6.2. Name: butFechar 6.3. Caption: &Fechar 7. Crie cinco objetos do tipo TLabel (em frente de cada objeto TBitBtn) respectivamente: e altere as seguintes propriedades

7.1. Propriedade Font para: Font.Color = clNavy 7.2. Caption: Ativa as opes para se criar um Filtro, o Filtro permite que a seleo dos Registro mostrados sejam limitados. Permite ordenar o relatrio por determinados campos. Salva o Relatrio em formato Texto Testa a posio das Etiquetas Imprime as Etiquetas Retorna a Janela Anterior 8. Crie um objeto do tipo TDgOrdena e altere as seguintes propriedades 8.1. DataSet: D_Modelo.tbCliente 8.2. Name: DgOrdenaEtq 8.3. NomeTela: Ordenao dos Registros 9. Crie um objeto do tipo TDgFiltro e altere as seguintes propriedades 9.1. DataSet: D_Modelo.tbCliente 9.2. Name: DgFiltroEtq 9.3. NomeTela: Determinando um filtro 9.4. TipoSQL: Access 10. Finalmente crie um objeto do tipo TSaveDialog e altere as seguintes propriedades 10.1. DefaultExt: TXT 10.2. Filter: Arquivos TXT|*.TXT|Todos os Arquivos|*.* 10.3. Name: SalvarArq

O trabalho final ficou desta maneira:

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 161/178

Programando a Sada
Agora comeamos com a parte mais divertida do trabalho, e por sinal minha favorita, mas por favor acompanhe atentamente esta codificao que apesar de ser simples existem alguns macetes que devem ser observados: 1. Inicialmente alterne para a Code Editor e na seo Private crie algumas coisinhas.
private pArqImpre: TextFile; pTotEtq: Integer; pDesLinha: String; function AcertaSQL: boolean; procedure EnviaEtq(Tipo: Integer); procedure ProduzEtq(Tipo: Integer); public

Quanto as variveis: pArqImpre ser o nosso arquivo texto gerado, pTotEtq acumular o total de etiquetas impressas e pDesLinha corresponde a uma linha do arquivo texto. 1.1. Para a Funo AcertaSQL
function TG_EtiqEnd.AcertaSQL: boolean; begin with QryEtq do begin if Active then Close; SQL.Clear; SQL.Add('Select cli.NOM_CLIENTE, cli.END_CLIENTE, cli.BAI_CLIENTE, '); SQL.Add('cli.CEP_CLIENTE, cid.NOM_CIDADE, cid.SIG_UF'); with D_Modelo do SQL.Add('From ' + nmCLIENTE + ' As CLI Left Join ' + nmCIDADE + ' As CID'); SQL.Add('On CLI.SIG_CIDADE = CID.SIG_CIDADE'); // Filtro if DgFiltroEtq.FiltroSQL > '' then SQL.Add('Where ' + DgFiltroEtq.FiltroSQL); // Ordenao if DgOrdenaEtq.Ordem > '' then SQL.Add('Order By ' + DgOrdenaEtq.Ordem); Open; if EOF then begin Result := False; MessageDlg('No Existem Registros para Gerar as Etiquetas', mtInformation, [mbOk], 0); end

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 162/178

else Result := True; end; end;

Est funo a responsvel pela montagem do SQL no objeto QryEtq, aqui montamos uma query simples associando a tabela de Cliente com a Tabela de Cidade (atravs do comando Left Join) as clusulas Where e Order By so definidas pelos objetos DgFiltroEtq e DgOrdenaEtq respectivamente, ao final basta apenas verificar se existe ou no registros retornando uma varivel lgica de resposta. 1.2. Para o Procedimento EnviaETQ
procedure TG_EtiqEnd.EnviaEtq(Tipo: Integer); procedure AcertaFont; var FColFont : TFont; begin fColFont := TFont.Create; fColFont.Name := 'Times New Roman'; fColFont.Size := 9; Printer.Canvas.Font.Assign(fColFont); fColFont.Free; end; begin try if AcertaSQL then begin AcertaFont; pTotEtq := 0; if tipo = 2 then begin if SalvarArq.Execute then AssignFile(pArqImpre,SalvarArq.FileName) else raise Exception.Create('Falha na gerao'); Rewrite(pArqImpre); end; ProduzEtq(Tipo); if Tipo = 2 then CloseFile(pArqImpre); if Tipo = 2 then MessageDlg('Arquivo Gerado sem problemas. Total de ' + IntToStr(pTotEtq) + ' etiqueta(s)', mtInformation, [mbOk], 0) else MessageDlg('Arquivo Impresso sem problemas. Total de ' + IntToStr(pTotEtq) + ' etiqueta(s)', mtInformation, [mbOk], 0); end; finally QryETQ.Close; end; end;

Este procedimento o responsvel pelo controle da gerao, inicialmente ele chama a funo AcertaSQL se existir registros, ele corrige a fonte da impressora, gera o arquivo de sada (caso a sada seja atravs de um arquivo fsico), manda produzir as etiquetas e finaliza tudo, ao final encerra a QryEtq 1.3. Para o Procedimento ProduzETQ
procedure TG_EtiqEnd.ProduzEtq(Tipo: Integer); begin with QryEtq do repeat if Tipo = 1 then begin AssignPrn(pArqImpre); Rewrite(pArqImpre); end; Inc(pTotEtq);

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 163/178

pDesLinha := pDesLinha + FieldByName('NOM_CLIENTE').AsString; writeln(pArqImpre, pDesLinha); // 1 pDesLinha := FieldByName('END_CLIENTE').AsString; writeln(pArqImpre, pDesLinha); // 2 pDesLinha := FieldByName('BAI_CLIENTE').AsString; writeln(pArqImpre, pDesLinha); // 3 pDesLinha := FieldByName('NOM_CIDADE').AsString; writeln(pArqImpre, pDesLinha); // 4 pDesLinha := FieldByName('SIG_UF').AsString; pDesLinha := pDesLinha+' '+Copy(FieldByName('NUM_CEP').AsString,1,5)+ // '-' + Copy(FieldByName('NUM_CEP').AsString,6,3); writeln(pArqImpre, pDesLinha); // 5 if Tipo <> 1 then begin writeln(pArqImpre, ' '); // 6 writeln(pArqImpre, ' '); // 7 writeln(pArqImpre, ' '); // 8 writeln(pArqImpre, ' '); // 9 end; if Tipo = 1 then CloseFile(pArqImpre); Next; until EOF; end;

O procedimento final que faz tudo, aqui inicialmente verificamos se a sada para impressora se for desviamos o arquivo para l, agora basta apenas gravarmos linha a linha utilizando a varivel pDesLinha como auxlio, ao final (se for para impressora) fechamos o arquivo. 2. Selecione o evento OnClose do formulrio:
procedure TG_EtiqEnd.FormClose(Sender: TObject; var Action: TCloseAction); begin with QryEtq do if Active then Close; end;

Apenas para garantir que antes de sairmos do formulrio a Query estar encerrada. 3. Vamos comear com os botes, primeiro o boto responsvel para realizar a Filtragem para tanto de um duploclique no objeto ButFiltro para ativar o evento OnClick:
procedure TG_EtiqEnd.ButFiltroClick(Sender: TObject); begin DgFiltroEtq.Execute; end;

Aqui simples, basta apenas executarmos a funo Execute do Objeto DgFiltroEtq que este objeto far o resto para ns, o filtro utilizado ser armazenado nas variveis FiltroSQL (filtro em linguagem SQL) e FiltroVe (filtro em linguagem que o usurio entende) 4. O prximo o boto que far a Ordenao dos campos para tanto de um duplo-clique no objeto ButOrdena para ativar o evento OnClick:
procedure TG_EtiqEnd.ButOrdenaClick(Sender: TObject); begin DgOrdenaEtq.Execute; end;

Aqui simples, basta apenas executarmos a funo Execute do Objeto DgOrdenaEtq que este objeto far o resto para ns. 5. O prximo o boto que far o salvamento em arquivo para tanto de um duplo-clique no objeto ButSalva para ativar o evento OnClick:
procedure TG_EtiqEnd.ButSalvaClick(Sender: TObject); begin EnviaEtq(2);

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 164/178

end;

Coisa simples basta dispararmos o procedimento EnviaEtq enviando o tipo em 2 6. O prximo o boto que far a impresso do arquivo para tanto de um duplo-clique no objeto ButImprime para ativar o evento OnClick:
procedure TG_EtiqEnd.ButImprimeClick(Sender: TObject); begin EnviaEtq(1); end;

Coisa simples basta dispararmos o procedimento EnviaEtq enviando o tipo em 1 7. O ltimo o boto que far o teste para o posicionamento da papel na impressora para tanto de um duplo-clique no objeto ButTeste para ativar o evento OnClick:
procedure TG_EtiqEnd.ButImprimeClick(Sender: TObject); var i : Integer; begin While (MessageDlg('Imprime teste ?', mtConfirmation, [mbYes, mbNo], 0) = mrYes) do begin AssignPrn(pArqImpre); Rewrite(pArqImpre); pDesLinha := '**************************************'; for i := 1 to 8 do writeln(pArqImpre, pDesLinha); writeln(pArqImpre, ' '); CloseFile(pArqImpre); end; end;

Aqui tambm fcil, criamos o arquivo na sada da impressora e questionamos se o usurio deseja o teste, se sim manda oito linhas com "*" e mais uma linha em branco para separar as etiquetas.

Finalmente
Agora basta voc voltar para o formulrio F_Menu para fazer a insero dos comandos para chamar o formulrio:
procedure TF_Menu.Correspondncia1Click(Sender: TObject); begin G_EtiqEnd := TG_EtiqEnd.Create(Application); G_EtiqEnd.ShowModal; G_EtiqEnd.Free; end;

Tambm chame a partir do menu principal Project | Options... e retire o formulrio G_EtiqEnd da rea dos Auto-Create forms.

Observao - O ideal que a impressora esteje plugada na porta LPT1 do Micro, pois imagine no meio da
impresso das etiquetas d um erro, ou algumas etiquetas cismam de enganchar. Na prxima apostila vamos continuar analisando os diferentes tipos de relatrios.

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 165/178

Curso de Delphi 4.0 - Apostila 16


Autor: Fernando Antonio Fernandes Anselmo E-Mail: fernandoanselmo@yahoo.com.br

Pr-Requisitos: Windows 98 Delphi 4.03 verso Client/Server Suite BDE 5.01 MS-Access 97 Arquivos trabalhados juntos com esta apostila: Seguintes Imagens : LogRel.JPG, ImgImprime.BMP

Prefcio
Salve, vamos comear a segunda parte dos Relatrios. Na verdade esta segunda parte ser a primeira, pois resolvi dividir este projeto (e para sua melhor compreenso) em dois tipos de relatrios do Quick Report, para este primeiro tipo criaremos relatrios Espelho. Mas o que so relatrios do tipo Espelho ? Me adiantei antes que voc perguntasse, o negcio o seguinte (no pegar um relatrio e imprimir todas as letras de trs para frente para ler diante de um espelho, isto aprenderemos no curso de espionagem e no de Delphi) este um tipo de relatrio que todos os campos dentro de um formulrio ficam sempre na mesma posio, eles j so pr-configurados para estarem ali. Pegue um bloco de Notas Fiscais se voc tivesse que imprimir o seu contedo, voc teria que pr preparar a impresso com todos os campos em pr determinadas posies. Este relatrio que lidaremos aqui est no Menu se chama: Cardpio. O entendimento simples, o usurio informa o nmero de calorias de 800 Kcal a 1.800 Kcal, e montaremos um cardpio ao acaso utilizando a tabela de alimentos.

Definindo o Relatrio
Bem, de uma colada na Apostila 6 e voc ver que o nosso usurio pr estabeleceu vrias configuraes para os cardpios, Batendo todos as refeies chegamos ao seguinte total mximo entre elas: Cardpio Padro
Refeio Desjejum (caf da manh) Colao (lanche da manh) Almoo Lanche Jantar Ceia Nmero de Refeies Variando de 2 at 4 Fixa em 1 Variando de 3 at 8 Variando de 1 at 4 Variando de 3 at 10 Variando entre 1 e 2

O que pretendo fazer aqui um trabalho simples, vou formatar uma pgina do quick com 6 campos do tipo tQrMemo para que este receba os alimentos (um em cada linha), este objeto vai crescendo a medida em que recebe os dados.

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 166/178

Importante - Para testar a sada do formulrio bom que as bases de Grupos e Alimentos estejam carregadas,
ento se voc ainda no fez aconselho que voc se encarregue disto.

Criando o Relatrio
Vamos direto a criao do relatrio no Quick: 1. A partir do Menu Principal v em File | New Form e para este objeto altere apenas as seguintes propriedades: 1.1. Name: R_Cardapio 1.2. Salve o formulrio com o nome de rCardapio.PAS

Importante - Abra o Data Module D_Modelo, volte para o formulrio R_Cardapio e alterne para a janela do
programa e insira a seguinte declarao aps a diretiva de compilao:
{$R *.DFM} uses dModelo;

2. Crie um objeto do tipo TQuery e altere as seguintes propriedades: 2.1. DataBase: DNmPeso 2.2. Name: QryRelato 3. Na Component Pallete na pgina QReport, localize o objeto chamado QuickRep, clique nele e em seguida click no formulrio e altere as seguintes propriedades: 3.1. Name: QrCardapio 3.2. PrintIfEmpty: True

Importante - Normalmente a maioria dos relatrio do tipo espelho no precisam estar amarrados a um objeto do tipo tDataSet, o caso deste nosso aqui, pois os dados seram jogados para ele.
4. Na Component Pallete ainda na pgina QReport, localize o objeto chamado QrBand, clique nele e em seguida click dentro do objeto do QrCardapio criado anteriormente e altere as seguintes propriedades: 4.1. Name para BdCabPagina 4.2. BandType para rbPageHeader - Essa a propriedade que controla os tipos das sees no caso escolhemos uma Banda de Cabealho de Pgina, ela aparecer em todas as pginas. 5. Na Component Pallete ainda na pgina QReport, localize o objeto chamado QrLabel, clique nele e em seguida click dentro do objeto do BdCabPagina e altere as seguintes propriedades: 5.1. Caption: Cardpio Planejado em xxx Cal 5.2. Font: Arial - Negrito - 18 - Azul-Marinho 5.3. AlignToBand: True - isto far com que seja alinhado de acordo com a banda. 5.4. Alignment: taCenter - isto far o alinhamento ficar centralizado. 5.5. Name: LabTitulo 6. Na Component Pallete ainda na pgina QReport, localize o objeto chamado QrImage, clique nele e em seguida click dentro do objeto do BdCabPagina e altere a propriedade Picture colocando a imagem LogRel.JPG, coloque-o no canto superior esquerdo da banda. 7. Na Component Pallete ainda na pgina QReport, crie dois objetos do tipo QrSysData colocando um abaixo do outro e altere as seguintes propriedades: 7.1. Data: qrsDate e qrsPageNumber (respectivamente)

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 167/178

7.2. Text: Data: e Pg: (respectivamente) 7.3. Font: Arial - Normal - 9 - Azul-Marinho 7.4. AlignToBand: True 7.5. Alignment: : taRightJustify 8. Crie mais um objeto do tipo QrBand, clique nele e em seguida click dentro do objeto do QrCardapio criado anteriormente e altere as seguintes propriedades: 8.1. Name para BdDetalhe 8.2. BandType para rbDetail - Neste caso escolhemos uma Banda de Detalhe de Pgina, ela aparecer a cada novo registro, como o componente Quick no est associado a nenhum DataSet ento ela aparecer apenas uma nica vez. 8.3. HasChild: True - isto criar automaticamente uma nova banda do tipo tChildBand 9. Na Component Pallete ainda na pgina QReport, localize o objeto chamado QrLabel, clique nele e em seguida click dentro do objeto do BdDetalhe e altere a propriedade Caption para Desjejum (caf da manh). 10. Na Component Pallete ainda na pgina QReport, localize o objeto chamado QrMemo, clique nele e em seguida click dentro do objeto do BdDetalhe e altere as seguintes propriedades: 10.1. AutoSize: False 10.2. AutoStretch: True 10.3. Font: Courier New - Normal - 9 10.4. Estique-o para ocupar uma linha inteira desta banda, coloque o objeto QrLabel1 em cima deste. 11. Na banda ChildBand1 criada (na alterao da propriedade HasChild para true) altere a propriedade HasChild para True - isto criar automaticamente uma nova banda do tipo tChildBand, agora que voc pegou a idia, v na nova banda criada e repita esta operao por mais quatro vezes, criando assim um total de cinco objetos ChildBand. 12. Na Component Pallete ainda na pgina QReport, localize o objeto chamado QrLabel, clique nele (segurando a tecla Shift) e em seguida click dentro de cada objeto do ChildBand, solte-o clicando na Component Pallete no desenho da seta, agora altere a propriedade Caption de todos para respectivamente Colao (lanche da manh) Almoo Lanche Jantar Ceia 13. Na Component Pallete ainda na pgina QReport, localize o objeto chamado QrLabel, clique nele (segurando a tecla Shift) e em seguida click dentro de cada objeto do ChildBand, solte-o clicando na Component Pallete no desenho da seta, agora altere as seguintes propriedades de todos: 13.1. AutoSize: False 13.2. AutoStretch: True 13.3. Font: Courier New - Normal - 9 13.4. Estique-o para ocupar uma linha inteira desta banda, coloque o objeto QrLabel em cima deste. O trabalho final ficou desta maneira:

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 168/178

Programando a Sada
Agora comeamos com a parte mais divertida do trabalho, e por sinal minha favorita, mas por favor acompanhe atentamente esta codificao que apesar de ser simples existem alguns macetes que devem ser observados: 1. Inicialmente alterne para a Code Editor e na seo Public crie uma chamada a um procedimento e na seo Private uma vrivel que receber o total de calorias:
private procedure CarrMemo(NmCampo, NmTabela : String; UsaAnd, UsaData:Boolean; var MemUtil: TQRMemo); public public NumCal : Integer; end;

Coloque a descrio do procedimento abaixo da diretiva de compilao:


{$R *.DFM} uses dModelo; procedure TR_Cardapio.CarrMemo(Grupo : String; var MemUtil: TQRMemo; Qtd: Integer); var vConta : Integer; begin with D_Modelo.QrySQL do begin if Active then Close; SQL.Clear; with D_Modelo do SQL.Add('Select NOM_ALIMENTO from ' + NmAlimento);

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 169/178

SQL.Add('Where NUM_GRUPO = ' + Grupo); Open; if EOF then MemUtil.Lines.Add('No existe alimento para compor este cardpio') else for vConta := 1 to Qtd do begin First; MoveBy(Random(RecordCount)); MemUtil.Lines.Add(Fields[0].AsString); end; Close; end; end;

Este procedimento o responsvel pela montagem de todo o cardpio, ele o corao de todo o relatrio, primeiramente ele recebe o Grupo, uma varivel contendo o QrMemo que queremos encher e a Quantidade de vezes que para o alimento deste grupo aparecer. Criamos uma SQL que pesquisa apenas os alimentos de um determinado grupo, verificamos se contm registros, e ento vamos ao primeiro registro (First) e depois saltamos (MoveBy) registros indicados atravs da funo Random que permite geramos um nmero aleatrio at o total de registros, depois basta apenas colocar o registro posicionado dentro da varivel.

Observao - possvel conforme j visto anteriormente passar qualquer tipo de varivel atravs de uma funo
ou procedimento, quando passado com o auxlio de um comando Var qualquer alterao se refletir na varivel originalmente passada. Por Exemplo:
procedure Teste(A : String); begin A := 'Dois';

end;
begin Var := 'Um'; Teste(Var);

end; O valor final de Var 'Um', diferente de:


procedure Teste(var A : String); begin A := 'Dois';

end;
begin Var := 'Um'; Teste(Var);

end; O valor final de Var 'Dois'. 1.2. Selecione agora o evento BeforePrint do objeto QrCardapio e insira os Procedimentos a seguir: procedure TR_Cardapio.QrCardapioBeforePrint(Sender: TCustomQuickRep; var PrintReport: Boolean); begin MemDesejum.Lines.Clear; MemColacao.Lines.Clear; MemAlmoco.Lines.Clear; MemLanche.Lines.Clear; MemJantar.Lines.Clear; MemCeia.Lines.Clear; LabTitulo.Caption := 'Cardpio Planejado em ' + IntToStr(NumCal) + ' Cal'; case NumCal of 800 : begin CarrMemo('4', MemDesejum, 1); CarrMemo('5', MemDesejum, 1); CarrMemo('3', MemColacao, 1); CarrMemo('2', MemAlmoco, 1); CarrMemo('5', MemAlmoco, 2); CarrMemo('4', MemAlmoco, 1); CarrMemo('3', MemLanche, 1); CarrMemo('2', MemJantar, 1);

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 170/178

CarrMemo('5', MemJantar, 3); CarrMemo('4', MemJantar, 1); CarrMemo('3', MemCeia, 1); end; 1000 : begin CarrMemo('4', MemDesejum, 1); CarrMemo('5', MemDesejum, 1); CarrMemo('3', MemDesejum, 1); CarrMemo('3', MemColacao, 1); CarrMemo('2', MemAlmoco, 1); CarrMemo('5', MemAlmoco, 3); CarrMemo('4', MemAlmoco, 1); CarrMemo('3', MemAlmoco, 1); CarrMemo('4', MemLanche, 1); CarrMemo('5', MemLanche, 1); CarrMemo('2', MemJantar, 1); CarrMemo('5', MemJantar, 3); CarrMemo('4', MemJantar, 1); CarrMemo('3', MemCeia, 3); end; 1200 : begin CarrMemo('7', MemDesejum, 1); CarrMemo('4', MemDesejum, 1); CarrMemo('5', MemDesejum, 1); CarrMemo('3', MemDesejum, 1); CarrMemo('3', MemColacao, 1); CarrMemo('2', MemAlmoco, 2); CarrMemo('5', MemAlmoco, 3); CarrMemo('4', MemAlmoco, 1); CarrMemo('3', MemAlmoco, 1); CarrMemo('4', MemLanche, 1); CarrMemo('2', MemJantar, 2); CarrMemo('5', MemJantar, 3); CarrMemo('4', MemJantar, 1); CarrMemo('6', MemJantar, 1); CarrMemo('3', MemJantar, 1); CarrMemo('3', MemCeia, 3); end; 1500 : begin CarrMemo('7', MemDesejum, 1); CarrMemo('4', MemDesejum, 1); CarrMemo('5', MemDesejum, 1); CarrMemo('3', MemDesejum, 1); CarrMemo('3', MemColacao, 1); CarrMemo('2', MemAlmoco, 2); CarrMemo('5', MemAlmoco, 3); CarrMemo('4', MemAlmoco, 2); CarrMemo('3', MemAlmoco, 1); CarrMemo('4', MemLanche, 2); CarrMemo('5', MemLanche, 1); CarrMemo('2', MemJantar, 2); CarrMemo('6', MemJantar, 1); CarrMemo('5', MemJantar, 3); CarrMemo('4', MemJantar, 2); CarrMemo('3', MemJantar, 1); CarrMemo('3', MemCeia, 1); end; 1800 : begin CarrMemo('7', MemDesejum, 1); CarrMemo('4', MemDesejum, 1); CarrMemo('5', MemDesejum, 1); CarrMemo('3', MemDesejum, 1); CarrMemo('3', MemColacao, 1); CarrMemo('2', MemAlmoco, 2); CarrMemo('5', MemAlmoco, 4); CarrMemo('4', MemAlmoco, 2); CarrMemo('3', MemAlmoco, 1); CarrMemo('4', MemLanche, 2); CarrMemo('5', MemLanche, 1); CarrMemo('3', MemLanche, 1); CarrMemo('2', MemJantar, 2); CarrMemo('5', MemJantar, 4); CarrMemo('4', MemJantar, 2); CarrMemo('6', MemJantar, 1); CarrMemo('3', MemJantar, 1); CarrMemo('7', MemCeia, 1); CarrMemo('3', MemCeia, 1); end; end; end; Este evento ser chamado preparando a montagem do relatrio, inicialmente limpamos todos os objetos QrMemo, depois simplesmente montamos conforme a verificao da varivel.

Importante - Apesar de parecer, isso apenas um Denorex, os eventos BeforePrint e AfterPrint no so como o
nome diz, antes de imprimir e depois de imprimir, na verdade so eventos relacionados ao relatrio em si, o BeforePrint acontece antes do Quick mostrar o relatrio (seja em tela ou na impressora) e o AfterPrint acontece quando se d a sada do relatrio e volta do controle ao formulrio que o chamou.

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 171/178

Finalmente
Crie a seguinte janela com o auxlio dos objetos RadioGroup e BitBtn:

Importante - Defina as seguintes propriedades para os objetos:


Formulrio - Name - F_RCardapio (salvar com o nome de: fRCardapio) RadioGroup - Name - RdgQtdCal Boto de Imprimir - Name - ButImprimir (para imagem utilize a ImgImprime.BMP) Boto de Fechar - Kind - bkClose Para o boto de Imprimir coloque o seguinte cdigo:
procedure TF_RCardapio.ButImprimirClick(Sender: TObject); begin R_Cardapio := TR_Cardapio.Create(Application); case RdgQtdCal.ItemIndex of 0 : R_Cardapio.NumCal := 800; 1 : R_Cardapio.NumCal := 1000; 2 : R_Cardapio.NumCal := 1200; 3 : R_Cardapio.NumCal := 1500; 4 : R_Cardapio.NumCal := 1800; end; R_Cardapio.QrCardapio.Preview; R_Cardapio.Free; end;

Chame a partir do menu principal Project | Options... e retire os formulrios: R_Cardapio e F_RCardapio da rea dos Auto-Create forms.

Observao - Faa a chamada do menu ao formulrio F_RCardapio

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 172/178

Curso de Delphi 4.0 - Apostila 17


Autor: Fernando Antonio Fernandes Anselmo E-Mail: fernandoanselmo@yahoo.com.br
Pr-Requisitos: Windows 98 Delphi 4.03 verso Client/Server Suite BDE 5.01 MS-Access 97 Arquivos trabalhados juntos com esta apostila: Seguintes Imagens : LogRel.JPG ImgImprime.BMP

Prefcio
Salve, vamos comear a terceira e ltima parte dos Relatrios. O segundo tipo de relatrio do Quick Report o relatrio tipo Folha de Dados. Relatrios tipo Folha de Dados so mais fceis que parecem, vou dizer aqui um grande Macete para a criao destes, uso de comandos SELECT do SQL, muitas pessoas queimam a cabea tentando construir o relatrio apenas com Table mas o grande lance aqui criar o relatrio baseado num comando SELECT primrio e sem muita complicao, associada a ele sim, objetos Table. Este relatrio que lidaremos aqui est no Menu se chama: Diviso das Contas Mensais. Mais simples que o primeiro, aqui o usurio informa o Ms e o Ano e simplesmente disparamos o relatrio totalmente baseado na tabela de PastaCliente, que tem os valores pagos pelos clientes em determinado perodo.

Definindo o Relatrio
Bem, voltando a dar uma colada na Apostila 6 voc ver que o nosso usurio pr estabeleceu vrias configuraes para a diviso dos lucros da empresa: 20% para o mdico-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. O que pretendo fazer aqui um trabalho simples, como j disse vamos simplesmente imprimir a tabela PastaCliente dentro de um determinado ms e ano e ao final deste, numa banda de ltima pgina (ou se voc prefere num sumrio de pgina) com base em variveis contendo o valor total vamos calcular a proporo de cada um. O nico problema que teremos (e este desde a definio eu fiz de propsito) quanto ao valor para o nutricionista que tem uma regra especial.

Importante - Para testar a sada do formulrio bom que a base de PastaCliente esteja carregada, ento se voc
ainda no fez aconselho que voc se encarregue disto.

Criando o Relatrio
Vamos direto criar o relatrio do Quick: 1. A partir do Menu Principal v em File | New Form e para este objeto altere apenas as seguintes propriedades:

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 173/178

1.1. Name: R_Mensal 1.2. Salve o formulrio com o nome de rMensal.PAS

Importante - Abra o Data Module D_Modelo, volte para o formulrio R_Mensal e alterne para a janela do
programa e insira a seguinte declarao aps a diretiva de compilao: {$R *.DFM} uses dModelo; 2. Crie um objeto do tipo TQuery e altere as seguintes propriedades: 2.1. DataBase: DNmPeso 2.2. Name: QryRelato 3. Na Component Pallete na pgina QReport, localize o objeto chamado QuickRep, clique nele e em seguida click no formulrio e altere as seguintes propriedades: 3.1. Name: QrMensal 3.2. PrintIfEmpty: True 3.3. DataSet: QryRelato

Importante - Diferentemente dos relatrio do tipo espelho estes aqui precisam estar amarrados a um objeto do tipo
tDataSet. 4. Na Component Pallete ainda na pgina QReport, localize o objeto chamado QrBand, clique nele e em seguida click dentro do objeto do QrMensal criado anteriormente e altere as seguintes propriedades: 4.1. Name para BdCabPagina 4.2. BandType para rbPageHeader - Essa a propriedade que controla os tipos das sees no caso escolhemos uma Banda de Cabealho de Pgina, ela aparecer em todas as pginas. 5. Na Component Pallete ainda na pgina QReport, localize o objeto chamado QrLabel, clique nele e em seguida click dentro do objeto do BdCabPagina e altere as seguintes propriedades: 5.1. Caption: Diviso das Contas Mensais 5.2. Font: Arial - Negrito - 18 - Azul-Marinho 5.3. AlignToBand: True - isto far com que seja alinhado de acordo com a banda. 5.4. Alignment: taCenter - isto far o alinhamento ficar centralizado. 5.5. Name: LabTitulo 6. Na Component Pallete ainda na pgina QReport, localize o objeto chamado QrImage, clique nele e em seguida click dentro do objeto do BdCabPagina e altere a propriedade Picture colocando a imagem LogRel.JPG, coloque-o no canto superior esquerdo da banda. 7. Na Component Pallete ainda na pgina QReport, crie dois objetos do tipo QrSysData colocando um abaixo do outro e altere as seguintes propriedades: 7.1. Data: qrsDate e qrsPageNumber (respectivamente) 7.2. Text: Data: e Pg: (respectivamente) 7.3. Font: Arial - Normal - 9 - Azul-Marinho 7.4. AlignToBand: True 7.5. Alignment: : taRightJustify 8. Crie mais um objeto do tipo QrBand, clique nele e em seguida click dentro do objeto do QrMensal criado anteriormente e altere as seguintes propriedades:

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 174/178

8.1. Name para BdCabecalho 8.2. BandType para rbColumnHeader - Neste caso escolhemos uma Banda de Cabealho de Pgina, ela aparecer a cada nova pgina. 8.3. Frame: DrawBottom e DrawTop para True, isto far com que se crie linhas inferior e superior a esta banda. 9. Crie dentro deste objeto criado, cinco objetos do tipo QrLabel e altere as seguintes propriedades: 9.1. Caption para Data, Cliente, Valor Cobrado, Desconto e Valor Pago respectivamente 9.2. Font: Courier New - Negrito - 9 - Preto 10. Crie mais um objeto do tipo QrBand, clique nele e em seguida click dentro do objeto do QrMensal criado anteriormente e altere as seguintes propriedades: 10.1. Name para BdDetalhe 10.2. BandType para rbDetail - Neste caso escolhemos uma Banda de Detalhe de Pgina, ela aparecer a cada novo registro. 11. Crie dentro deste objeto criado, cinco objetos do tipo QrDbText e altere as seguintes propriedades: 11.1. Caption para Dat_Pagamento, Nom_Cliente, Val_Total, Val_Desconto e Valor respectivamente 11.2. Font: Courier New - Normal - 9 - Preto 12. Crie mais um objeto do tipo QrBand, clique nele e em seguida click dentro do objeto do QrMensal criado anteriormente e altere as seguintes propriedades: 12.1. Name para BdSumario 12.2. BandType para rbSummary - Neste caso escolhemos uma Banda de Final de Relatrio, ela aparecer apenas quando o relatrio terminar. 13. Crie dentro deste objeto criado, cinco objetos do tipo QrLabel e altere as seguintes propriedades: 13.1. Caption para Resumo Final - Mdico-Presidente, Coordenador, Nutricionista, Despesas Gerais e Valor Total respectivamente 13.2. Font: Courier New - Negrito - 9 - Preto 14. Crie na frente destes cinco objetos criados, mais cinco objetos do tipo QrLabel e altere as seguintes propriedades: 14.1. Name para ValPresidente, ValCoordenador, ValNutricionista, ValDespesa respectivamente 14.2. Font: Courier New - Normal - 9 - Preto 14.3. Caption: 0 (Zero) para todos O trabalho final ficou desta maneira: e ValTotal

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 175/178

Programando a Sada
Vamos a quase finalizao deste projeto, o complemento com a programao: 1. Inicialmente alterne para a Code Editor e na seo Private crie cinco vriveis para receber a quantidade de valor de cada plano e na seo Public crie um varivel para receber o ms proposto:

private TotPlanoA, TotPlanoB, TotPlanoC, TotPlanoD : Float; procedure CarrMemo(Grupo : String; var MemUtil: TQRMemo; Qtd: Integer); public MesInt : Integer; AnoStr : String; end;

2.

Selecione agora o evento BeforePrint do objeto QrMensal e insira os Procedimentos a seguir:

procedure TR_Mensal.QrMensalBeforePrint(Sender: TCustomQuickRep; var PrintReport: Boolean);

var MesStr, DataIni, DataFin : String; AnoInt : Integer; begin MesStr := Copy('0',1,2 - Length(IntToStr(MesInt))) + IntToStr(MesInt); DataIni := '01/'+ MesStr + '/' + AnoStr; case MesInt of 1, 3, 5, 7, 8, 10, 12: DataFin := '31/'+ MesStr + '/' + AnoStr; 4, 6, 9, 11: DataFin := '30/'+ MesStr + '/' + AnoStr; else AnoInt := StrToInt(AnoStr); if ((AnoInt/4) = Round(AnoInt/4)) then DataFin := '29/'+ MesStr + '/' + AnoStr else DataFin := '28/'+ MesStr + '/' + AnoStr; end; // *** with QryRelato do begin

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 176/178

SQL.Add('FROM Cliente Cl, Pasta_Cliente Pc'); SQL.Add('WHERE (Pc.NUM_CPF = Cl.NUM_CPF)'); SQL.Add('AND (Pc.DAT_PAGAMENTO >= #' + DataIni + '# AND Pc.DAT_PAGAMENTO <= #' + DataFin + '#)'); Open; end; TotPlanoA := 0; TotPlanoB := 0; TotPlanoC := 0; TotPlanoD := 0; end;

SQL.Add('SELECT Pc.DAT_PAGAMENTO, Cl.NOM_CLIENTE, Pc.VAL_TOTAL, ' + 'Pc.VAL_DESCONTO, Pc.PLN_ADOTADO, (Pc.VAL_TOTAL - Pc.VAL_DESCONTO) As Valor');

if Active then Close; SQL.Clear;

No incio do relatrio montamos primeiro o intervalo do ms e ano informado (de 01/mm/aa at [ltimo dia]/mm/aa) para a pesquisa, inclusive com os clculos de ano bissexto, montamos a pesquisa selecionando apenas os registros daquele intervalo e iniciamos as variveis globais. 3. Selecione agora o evento BeforePrint do objeto BdDetalhe e insira os Procedimentos a seguir:

procedure TR_Mensal.BdDetalheBeforePrint(Sender: TQRCustomBand; var PrintBand: Boolean);

begin with QryRelato do begin if FieldByName('PLN_ADOTADO').AsString = 'A' then TotPlanoA := TotPlanoA + FieldByName('Valor').AsFloat else if FieldByName('PLN_ADOTADO').AsString = 'B' then TotPlanoB := TotPlanoB + FieldByName('Valor').AsFloat else if FieldByName('PLN_ADOTADO').AsString = 'C' then TotPlanoC := TotPlanoC + FieldByName('Valor').AsFloat else if FieldByName('PLN_ADOTADO').AsString = 'D' then TotPlanoD := TotPlanoD + FieldByName('Valor').AsFloat; end; end;

Verificamos qual o tipo de plano o registro est tratando e somamos na respectiva varivel. 4. Selecione agora o evento BeforePrint do objeto BdDetalhe e insira os Procedimentos a seguir:

procedure TR_Mensal.BdSumarioBeforePrint(Sender: TQRCustomBand; var PrintBand: Boolean);

var Total, TotPart : Double; begin Total := TotPlanoA + TotPlanoB + TotPlanoC + TotPlanoD; ValTotal.Caption := Format('%m',[Total]); ValPresidente.Caption := Format('%m',[((Total * 20) / 100)]); ValCoordenador.Caption := Format('%m',[((Total * 40) / 100)]); Total := TotPlanoB + TotPlanoD; ValNutricionista.Caption := Format('%m',[((Total * 10) / 100)]); Total := TotPlanoA + TotPlanoC; TotPart := (Total * 40) / 100; Total := TotPlanoB + TotPlanoD; ValDespesa.Caption := Format('%m',[(((Total * 30) / 100) + TotPart)]); end;

Este ltimo evento, apenas calcula os valores transferindo-os para os respectivos campos, com o auxlio da funo Format transformamos os campos String em forma de Valores Monetrios. Crie a seguinte janela com o auxlio dos objetos ComboBox, MaskEdit e BitBtn:

PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 177/178

Importante - Defina as seguintes propriedades para os objetos:


Formulrio - Name - F_RMensal (salvar com o nome de: fRMensal) ComboBox - Name - cbMes - Items - Nome dos meses (um em cada linha) MaskEdit - Name - MskAno - EditMask - 0000;0;_ Boto de Imprimir - Name - ButImprimir Boto de Fechar - Kind - bkClose Para o evento OnShow do formulrio coloque o seguinte cdigo:
procedure TF_RMensal.FormShow(Sender: TObject); begin CbMes.ItemIndex := StrToInt(FormatDateTime('MM',Now)) - 1; MskAno.Text := FormatDateTime('YYYY',Now); end; Para o boto de Imprimir coloque o seguinte cdigo: procedure TF_RMensal.ButImprimirClick(Sender: TObject); begin R_Mensal := TR_Mensal.Create(Application); R_Mensal.MesInt := CbMes.ItemIndex + 1; R_Mensal.AnoStr := MskAno.Text; R_Mensal.QrMensal.Preview; R_Mensal.Free; end;

Chame a partir do menu principal Project | Options... e retire os formulrios: R_Mensal e F_RMensal da rea dos Auto-Create forms.

Observao - Faa a chamada do menu ao formulrio F_RMensal


Grandes []s
Ao final deste projeto terminamos o nosso curso de Delphi, espero sinceramente que voc tenha aproveitado cada momento assim como eu tambm aproveitei e que este no seja apenas o final de mais um curso e sim o comeo para uma excelente jornada.

FIM
PDF criado por: Idelson Pessoa da Silva idelson@bol.com.br - Pgina Nr. 178/178

Vous aimerez peut-être aussi