Você está na página 1de 178

ipsgyn .

Curso Delphi 4.0 com MS-Access

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página Nr. 1/178
Curriculum Vitae
I- Identificação
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
Coordenação e desenvolvimento de atividades de análise, definição de projetos, experiência na
definição e criação de algoritmos lógicos, codificação, compilação e teste de programas.
Treinamento e iniciação de usuários em diversos ambientes, entre estes destacam-se Delphi, Java e
ASP. Seus cursos são oferecidos pela MCI Informática e pela FINATEC.
Possui larga experiência quanto ao levantamento de Informações, acompanhamento e análise do
processamento dos programas desenvolvidos. Grande experiência em programação para ambientes
Cliente/Servidor.
III- Formação
• Desenvolvimento WEB e JavaScript
Promotor: Politec
• Ambientação 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 São Paulo
• Programação em Computadores
Promotor : ETUC - Faculdade Católica de Tecnologia
• Língua Inglesa
Promotor : Fluency Idiomas
• Formação básica no Segundo Grau com Habilitação em Química
Colégio Santa Rosa de Lima
IV- Categoria Profissional
Cargo Atual: Analista de Sistemas Sênior (Líder de Projetos)
Tempo de experiência: 11 anos
V- Experiência Profissional
a) Atividades Principais:
• Experiência no Desenvolvimento e Manutenção de Sistemas para Internet utilizando
ASP, JAVA e HTML.
• Domínio em SGBDR de 4a. geração, tais como ORACLE, MS-SQL Server,
INTERBASE entre outros.
• Ministra cursos destinados a profissionais Desenvolvedores da área de informática -
SENAC e MCI Informática
• 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 - Página Nr. 2/178
dois mundos"
• Grande experiência com sistemas em Delphi em especial para aplicações Intranet
utilizando Delphi e objetos ActiveX.
b) Ambiente Operacional:
• Domínio dos ambientes operacionais Windows e Linux.
• Conhecimentos do ambiente operacional Netware.
• Noções em Ambientes de Grande Porte ADABAS, ROSCOE, NATURAL,
COMPLETE, JCL, VM/CMS e CICS.
c) Histórico das Últimas Atividades Exercidas
1999/Atual - Politec Ltda
Cargo: Analista de Sistemas Sênior
- Contratado para auxiliar ao desenvolvimento do Sistema
Justiça do Superior Tribunal de Justiça - STJ.
- Ministrando aulas de Delphi, HTML, ASP e Java.
1994/1999 - FIA/USP
Cargo: Líder de Projetos
Ano 99
- Iniciei o desenvolvimento de Sistema Piloto em OutLook 98
para controlar os atendimentos ao usuário
- 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 Licitação, Controle de Help Desk para o
atendimento ao usuário e Criação de diversos objetos para
suporte as aplicações
- Iniciei o desenvolvimento do Sistema de Cadastro Dinâmico
para o Fechamento do Censo Escolar de 97 com o prazo de
entrega previsto para 31/12/1997
Ano 97
- Treinei usuários do FNDE em Power Designer 6.0 - Ferramenta
CASE e Delphi 3.0 Client / Server
- Iniciei a criação de diversas "Templates" para a automação
da ferramenta Power Designer na geração de sistemas na
plataforma DELPHI 3.0.
Ano 96
- Fui transferido para o contrato FIA/MEC
- Fui responsável pelo desenvolvimento técnico com a criação
de vários objetos em DELPHI para servir de apoio ao
desenvolvimento dos sistemas.
Ano 95
- Ministrei vários cursos de DELPHI desde o básico ao avançado.
- Estudei mudanças para substituição da plataforma ACCESS /
ORACLE e adoção a ferramenta de desenvolvimento de 4a.
Geração Borland Delphi.
Ano 94
- Fui contratado pela FIA/USP - Sendo lotado para trabalhar no
IBAMA - Instituto Brasileiro do Meio-Ambiente e Recursos
Naturais Renováveis. Para liderar a equipe de
desenvolvimento.

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página 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 manutenção e
desenvolvimento do projeto JUSTIÇA, lotado no Superior
Tribunal de Justiça. Inicia os trabalhos de manutenção e
reajustes no sistema de controle e distribuição de processos
jurídicos - desenvolvimento em ambiente NATURAL II / ADABAS.
1992/1993 - RCM Informática
Cargo: Analista de Sistemas
- A RCM, nesta época, era a representante na América do Sul
pela comercialização do SGBD4 ZIM. Fui contratado para
iniciar os trabalhos no sistema de Tele-Suporte para o
Sistema de Arrecadação 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 período desenvolvi diversos
sistemas na plataforma Clipper e bancos padrão xBase e na nova
plataforma Unix com banco ZIM.
1990 - Racional Informática
Cargo: Programador
Durante um período de treinamento de 1 mês, não cheguei a ser
contratado em carteira, pois foi imediatamente contratado pela
FIA/USP. Nesta empresa realizei os trabalhos de programação do
Sistema Controle de Estoque e Mercadorias - Desenvolvido em
ambiente DOS / dBASE III Plus.
1989/1990 - FTI - Fundação de Tecnologia Industrial
Cargo: Programador
Fui lotado para trabalhar no Ministério do
Desenvolvimento da Indústria e do Comércio, desenvolvi em
sistemas nas seguintes linguagens: Natural, COBOL, PL1,
EASYTRIEVE Plus, JCL e Clipper.

Outros Dados:
1988 - Primeiro emprego em Carteira na KRION Vídeo Clube na
área de programação em Computadores em Ambiente dBASE III
plus e planilha para contabilidade em Lótus 123.
1987 - Conclui com nota "A" o Estágio de Programação 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 férias no Banco do Nordeste do Brasil em
máquinas PC.
VI- Local, data e assinatura
Assumo total responsabilidade que todas as informações prestadas são verdadeiras até a presente
data.
Fernando Antonio Fernandes Anselmo
Brasília, sexta-feira 20 de setembro de 2002

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página Nr. 4/178
Programção Orientada a Objetos
Autor: Fernando Antonio Fernandes Anselmo
E-Mail: fernandoanselmo@yahoo.com.br
Pré-Requisitos:

Windows 98
Delphi 4.0 versão Client/Server Suite
BDE 5.00
MS-Access 97

Prefácio
Para você poder compreender melhor o ambiente de desenvolvimento Delphi, é necessário que
seja apresentado alguns conceitos da POO (Programação Orientada a Objetos). Não os confunda com POE
(Programação Orientada a Eventos), muito difundido com a linguagem encontrada com o MS-Access, o
Access-Basic (um ambiente baseado em Objetos). Vou tentar expor aqui as sensíveis diferenças que existem
entre esses dois conceitos.
A POO e a POE são facilmente confundidas, mas lembre-se, a POO contém a POE, mas a POE não
contém a POO; um objeto pode existir mesmo que para ele não exista nenhum evento associado, mas é
impossível existir um evento se não houver um objeto associado. Outra característica que pode causar
confusão, são ambientes Orientados a Objetos e ambientes Baseados em Objetos. Em ambiente Orientado
a Objetos existe a possibilidade da criação e manipulação de objetos, enquanto que o Baseado em Objetos
esta possibilidade é totalmente inexistente o que existe é a simples manipulação ou no máximo uma
derivação (criação de um a partir de outro já existente) dos objetos.
A POO é um conceito desenvolvido para facilitar o uso de códigos de desenvolvimento em
interfaces gráficas. Sendo a Inprise, uma das primeiras a entrar neste novo conceito, possui suas principais
linguagens de programação (tais como Object Pascal e Object C), totalmente voltadas para este tipo de
programação. A POO atraiu muitos adeptos principalmente pelo pouco uso de código que o Projeto
(diferente de Sistema) carrega no programa fonte, ao contrário de linguagens mais antigas como o
Clipper’87 muito utilizado no final da década de 80 e início da década de 90. O resultado desta “limpeza”
resulta que uma manutenção no projeto é muito mais simples.
Para entender o sistema POO, vamos tentar pensar simples, imagine que você acabou de adquirir
uma caixa de bloquinhos de Lego, você pode criar várias coisas com eles, mas você possui um número
limitado de peças, você pode aumentar sua coleção, aumentando também a possibilidade do número de
coisas que você poderá criar, formando verdadeiras cidades de Lego. Depois do comercial, a POO é
basicamente isto, adquirindo o Delphi você está adquirindo um ambiente totalmente flexível para a criação
de um número de determinados sistemas, você pode aumentar sua produtividade simplesmente aumentando o
número de objetos. Os conceitos que vou apresentar a seguir existem desde que foi sonhada a Orientação a
Objetos, provavelmente você deve conhecer uma boa parte, se não, então é a hora de você se familiarizar
com este ambiente.

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página Nr. 5/178
Conceitos da Orientação a Objeto
Antes de começarmos a falar realmente de linguagem orientada a objetos e necessário que você
possua os conceitos básicos da orientação a objetos, são eles:

Objeto - é qualquer estrutura modular que faz parte de um produto. Uma janela por exemplo, é um
objeto de uma casa, de um carro ou de um software com interface gráfica para o usuário.
Atributos - São as características do objeto, como cor e tamanho, a janela, por exemplo, tem atributos
como o modelo, tamanho, abertura simples ou dupla, entre outros.
Encapsulação - é um mecanismo interno do objeto “escondido” do usuário. Uma pessoa pode abrir uma
janela girando a tranca sem precisar saber o que há dentro dela.
Ação - é a operação efetuada pelo objeto. Todas as janelas, por exemplo, controlam a iluminação e
temperatura ambiente, dependendo do seu design.
Herança - um objeto novo nem sempre é criado do zero. Ele pode “herdar” atributos e ações de outros já
existentes. Um basculante herda atributos das janelas e das persianas.
Polimorfismo - é a capacidade de objetos diferentes reagirem segundo a sua função a uma ordem
padrão. O comando “abre”, por exemplo, faz um objeto entrar em ação, seja ele uma janela, uma
porta ou uma tampa de garrafa.
Ligação - é quando um objeto conecta a sua ação a outro. Um sensor de claridade, por exemplo, ativa o
acendimento automático da iluminação de rua.
Embutimento - Permite a um objeto incorporar funções de outros, como um liquidificador que mói
carne com a mudança do tipo da lâmina.

Linguagem Object Pascal


Object Pascal é uma linguagem Orientada a Objetos não é pura, mas, híbrida, por possuir
características de programação não só visual mas também escrita, para os programadores que já conhecem
técnicas de estruturas de programação, tais como C, Basic, Pascal ou xBASE entre outras linguagens a
Object Pascal providência uma migração de forma natural oferecendo um produto de maior
complexibilidade. Object Pascal força a executar passos lógicos. Isto torna mais fácil o desenvolvimento em
ambiente gráficos (tais como o Windows), de aplicações livres, ou que utilizam banco de dados do tipo
Cliente/Servidor. A linguagem trabalha com o uso de ponteiros para a alocação de memória e todo o poder
de um código totalmente compilável. Além disso, possibilita a criação e reutilização (vantagem de re-uso tão
sonhado com a Orientação a Objetos) de objetos e bibliotecas dinâmicas (Dynamic Link Libraries - DLL).
Object Pascal contém todo o conceito da Orientação a Objetos, incluindo a herança, o
encapsulamento e o polimorfismo. Algumas extensões foram incluídas para facilitar o uso tais como
conceitos de propriedades, particulares e públicas, e tipos de informações em modo run-time, manuseamento
de exceções, e referências de classes. O resultado de toda esta junção faz com que Object Pascal consiga
suportar as facilidades de um baixo nível de programação, tais como:
Controle e acesso das sub classes do Windows (API);

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página Nr. 6/178
Passar por cima das mensagens de loop do Windows;
Mensagens semelhantes as do Windows;
Código puro da linguagem Assembler.
Como deu para perceber a base de toda a programação Delphi é a linguagem Object Pascal nunca
diga então que você programa em Delphi e sim que você programa em Object Pascal, assim como você
nunca programou em Clipper mas em xBase, vamos aprender alguns conceitos básicos dentro deste tipo de
programação.

Símbolos Especiais
A Object Pascal aceita os seguintes caracteres ASCII:
Letras - do Alfabeto Inglês: A até Z e a até z.
Dígitos - Decimal: 0 até 9 e HexaDecimal: 0 até 9 e A até F (ou a até f)
Brancos - Espaço (ASCII 32) e todos os caracteres de controle ASCII (ASCII 0 até ASCII 31),
incluindo final de linha e Enter (ASCII 13).
Especiais - Caracteres: + - * / = < > [ ] . , ( ) : ; ^ @ { } $ #
Símbolos - Caracteres: <= >= := .. (* *) (. .) //


Importante - O colchetes esquerdo “[” e equivalente ao “(.” e o colchetes direito “]” e
equivalente a “.)”.


Importante - Os comentários são formados por chave esquerda “{” e equivalente ao “(*” e
fechados com a chave direita “}” e equivalente a “*)”. O comentário de uma linha é o “//” (não é aceito pelo
Delphi 1.0).
for i := 1 to 10 do // Este é o exemplo de um comentário apenas desta linha
for i := 1 to 10 do { Este é o exemplo de um comentário que pode ser em várias linhas }
for i := 1 to 10 do (*Este é o exemplo de um comentário que pode ser em várias linhas *)

Palavras Reservadas
Object Pascal se utiliza das seguintes palavras reservadas, não podendo as mesmas serem utilizadas
ou definidas:
And Exports Library Set
Array File Mod Shl
As Finnaly Nil Shr
Asm For Not String
Begin Function Object Then
Case Goto Of To
Class If On Try
Const Implementation Or Type
Constructor In Packed Unit
Destructor Inherited Procedure Until
Div Initialization Program Uses
Do Inline Property Var
Downto Interface Raise While
Else Is Record With
End Label Repeat Xor
Except

Uma outra lista a seguir, apresenta as diretivas que são utilizadas em contextos de identificação de
objetos:
Absolute Export Name Published
Abstract External Near Read
Assembler Far Nodefault Resident
At Forward Override Stored
Cdecl Index Private Virtual

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página Nr. 7/178
Default Interrupt Protected Write
Dynamic Message Public

Números
É possível definir variáveis ou constantes com tipos Inteiros ou Numéricos de ponto flutuante, a
diferença entre os diversos tipos permitidos se deve a capacidade de armazenamento e o espaço ocupado,
veja a comparação nas tabelas abaixo:

Para os tipos Inteiros

Tipo Range Formato


Integer -2147483648..2147483647 32-bit + sinal
Shortint -128..127 8-bit + sinal
Smallint -32768..32767 16-bit + sinal
Longint -2147483648..2147483647 32-bit + sinal
Int64 -2^63..2^63-1 64-bit + sinal
Cardinal 0..4294967295 32-bit
Byte 0..255 8-bit
Word 0..65535 16-bit
Longword 0..4294967295 32-bit

Para os tipos Ponto Flutuante

Tipo Range Dígitos Significantes Tamanho em Bytes


Real48 2.9 x 10^-39 .. 1.7 x 10^38 11-12 6
Real 5.0 x 10^-324 .. 1.7 x 10^308 15-16 8
Single 1.5 x 10^-45 .. 3.4 x 10^38 7-8 4
Double 5.0 x 10^-324 .. 1.7 x 10^308 15-16 8
Extended 3.6 x 10^-4951 .. 1.1 x 10^4932 19-20 10
Comp -2^63+1 .. 2^63 -1 19-20 8
Currency -922337203685477.5808.. 19-20 8
922337203685477.5807

var
i : double; // Aqui crio uma variável i sendo Float
z : integer; // Aqui crio uma variável z sendo Inteira
t : real; // Aqui crio uma variável t sendo Real
begin
i := StrToFloat('10.23');
z := Round(i);
t := i;
end;

Constantes
Uma constante é um identificador com valor(es) fixo(s). Um bloco de declarações constante possui a
seguinte expressão:
[Declaração Constante] [Identificador] (=) [constante] (;)
A lista abaixo apresenta um conjunto de funções que podem ser utilizadas para a declaração das
constantes:
Ab Length Ord SizeOf
Chr Lo Pred Succ
Hi Low Ptr Swap
High Odd Round Trunc

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página Nr. 8/178
Alguns exemplos para a definição de Constantes:
const
Min = 0;
Max = 100;
Centro = (Max - Min) div 2;
Beta = Chr(225);
NumLetras = Ord('Z') - Ord('A') + 1;
MensOla = 'Instrução inválida';
MensErro = ' Erro: ' + MensOla + '. ';
PosErr = 80 - Length(MensErro) div 2;
Ln10 = 2.302585092994045684;
Ln10R = 1 / Ln10;
DigNumericos = ['0'..'9'];
LetrasAlpha = ['A'..'Z', 'a'..'z'];
AlphaNum = LetrasAlpha + DigNumericos;

Expressões
As expressões em Object Pascal (como em qualquer linguagem) são formadas por operadores e
operandos; os operadores são divididos em quatro categorias básicas:
Únicos @, Not
Multiplicativos >, /, div, mod, and, shl, shr, as
Adicionais +, -, or, xor
Relacionais =, < >, <, >, < =, > =, in, is

As expressões obedecem as regras básicas de lógica para a precedência da execução das operações.

Identificadores
Identificadores podem ser constantes, tipos, variáveis, procedures, funções, unidades, programas e
campos de registros.
Não existe limite de caracteres para o nome de um identificador mas apenas os 63 primeiros
caracteres são significantes (não podendo ser idêntico ao nome das palavras reservadas). O nome de um
identificador deve ser iniciado por Letras ou o caracter underscore ( _ ). O resto é formado por Letras,
Dígitos, caracter underscore (ASCII $5F). Não é permitido a utilização de espaços para a formação do nome.

☞Importante - Exemplo de identificadores válidos: Form1, SysUtils.StrLen, Label1.Caption


with... do...;
Delimita um determinado bloco de declarações para um identificador específico evitando a declaração
deste identificador. A sintaxe do comando é: WITH {nome do identificador} DO {comandos};. Ex.:

begin
{ ... comandos iniciais ... }
with form1 do
begin
Caption := ‘Teste’; // Equivalente a Form1.Caption
BorderStyle := bsSizable; // Equivalente a Form1.BorderStyle
end;
end;

array [ ... ] of ...;


Define um conjunto de variáveis ou constantes de um mesmo tipo. A sintaxe do comando é: array
[{quantidade de ocorrências}] of {Tipo};. Os arrays são controlados por três funções:

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página Nr. 9/178
Função Valor de Retorno
Low Primeiro elemento
High Aponta para o último elemento
SizeOf 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;

Declarações
Declarações descrevem ações de um algorítmo a serem executadas.
begin... end;
Prende um conjunto de declarações em um bloco de comandos determinado. A sintaxe do comando é:
BEGIN {comandos} END;. Ex.:

begin
{ ... comandos iniciais ... }
begin
{ ... bloco 1 ... }
end;
begin
{ ... bloco 2 ... }
end;
{ ... comandos finais ... }
end;

if... then... else...;


Esta expressão escolhe entre o resultado de uma condição booleana o caminho verdadeiro (then) ou falso
(else). A sintaxe do comando é: IF {condição} THEN {bloco de comandos} ELSE {bloco de comandos};.
Ex.:

begin
{ ... comandos iniciais ... }
if x > 2 then
{ ... Bloco verdadeiro ... }
else
{ ... Bloco falso ... };
end;

goto... ;
Transfere a execução de um programa para o ponto determinado pelo Label. A sintaxe do comando é:
GOTO {Label};. Ex.:

label
primeiro;

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página 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 declarações que satisfaz a condição de um seletor de expressões, se nenhuma
parte da lista satisfizer ao seletor executa os comandos do sub-comando else. Para o seletor serão válidos os
tipos definidos, tipo Inteiros ou LongInt. A sintaxe do comando é: CASE {seletor} OF {Expressão 1}:
{comando da expressão 1}; {Expressão 2}: {comando da expressão 2}; {Expressão n}: {comando da
expressão n} ELSE {comando}; end;. Ex.:

begin
{ ... comandos iniciais ... }
case x of
1: { ... Bloco para x = 1 ... }
2, 3: { ... Bloco para x = 2 ou X = 3... }
4..6: { ... Bloco para 4 <= x <= 6 ... }
else
{ ... Bloco para x < 1 ou x > 6 ... };
end;
end;

repeat... until;
Repete um determinado bloco de declarações até a condição booleana do subcomando until ser
satisfeita. A sintaxe do comando é: REPEAT {comandos}; until {condição};. Ex.:

begin
{ ... comandos iniciais ... }
x := 0;
repeat
x := x + 1
until (x = 2);
end;

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


Incrementa em 1 uma determinada variável inteira, repetindo um bloco de comandos, até que esta atinja
o valor final do intervalo, o subcomando downto realiza o incremento reverso. A sintaxe do comando é:
FOR {variável} := {valor inicial} to (downto) {valor final} do {bloco de comandos};. Ex.:

begin
{ ... comandos iniciais ... }
for i := 1 to 10 do // Executa o [comandos A] para i = 1,2,3,4,5,6,7,8,9 e 10
{ ... Comandos A ... }
for s := 10 downto 1 do // Executa o [comandos B] para i = 10,9,8,7,6,5,4,3,2 e 1
{ ... Comandos B... }
end;

while... do...;
Repete um bloco de comandos enquanto que determinada condição booleana seja satisfeita. A sintaxe do

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página Nr. 11/178
comando é: WHILE {condição} DO {bloco de comandos};. Ex.:
begin
{ ... comandos iniciais ... }
while i := 1 do // Repete o [Bloco de comandos] enquanto i = 1
{ ... Bloco de comandos ... }
end;
break; ou continue...;
O comando break interrompe um bloco de repetição for, while ou repeat saindo do bloco. A sintaxe do
comando é: BREAK; enquanto que o comando continue retorna a primeira instrução do bloco de repetição
for, while ou repeat. A sintaxe do comando é: CONTINUE;. Ex.:

begin
{ ... comandos iniciais ... }
for i := 1 to 10 do
begin
if i = 8 then
break; // Salta para os [comandos C]
{... comandos A...}
if i = 5 then
continue; // Retorna para o comando for pulando os [comandos B]
{... comandos B ...}
end;
{... comandos C ...}
end;

Blocos de Procedimentos ou Funções


As procedures ou funções são declaradas na seção de tipos de declarações (abaixo do comando type)
pertencendo ao objeto ou serem do tipo public (públicas - executadas por outras unidades) ou private
(particulares - restritas a unidade local).
Procedure
procedure {cabeçalho}; var {declaração das variáveis}; {bloco de comandos};
O cabeçalho da procedure é composto pelo nome do procedimento e variáveis que serão recebidas
(ou modificadas através da declaração var, ex.: “procedure teste(var x:string);”).

procedure soma(a,b: integer); // Início enviando as variáveis A e B do tipo inteiro.


var // Declaração de variáveis locais a procedure
c: integer;
begin // Corpo do procedimento.
c := a + b;
end;

Function
function {cabeçalho} : {resultado}; var {declaração das variáveis}; {bloco de comandos};
As funções se diferem dos procedimentos pela obrigatoriedade do retorno de um resultado, podendo
este resultado ser retornado pela declaração: {nome da função} := valor ou result := valor.

function soma(a,b: integer) : integer; // Início enviando as variáveis A e B do tipo inteiro.


begin // Corpo do procedimento.
soma := a + b; // ou result := a + b;
end;

☞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 - Página 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 não se preocupe com o que foi explicado acima já está mais do que
suficiente para um bom entendimento com o Object Pascal.
Tudo o que vimos acima é o que normalmente temos em outras linguagens comuns, mas o
caracteriza realmente a linguagem Orientada em Objetos é o trabalho e a manipulação com os mesmos.

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página Nr. 13/178
Manual dos Objetos
Autor: Fernando Antonio Fernandes Anselmo
E-Mail: fernandoanselmo@yahoo.com.br
Pré-Requisitos:

Windows 98
Delphi 4.0 versão 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

Prefácio
Desde o começo 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 coleção de objetos é
importante em qualquer construção de um projeto em uma linguagem Orientada a Objetos, aqui estou disponibilizando
mais do que objetos, estou também 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 diretório (além do LIB tradicional do Delphi) para conter seus
"outros" objetos, não fique alterando o diretório padrão do Delphi, por uma simples razão, quando você quiser criar um
backup com seus objetos basta você copiar este novo diretório então crie por exemplo c:\arquivos de
programas\borland\delphi4\lib1 para guardar seus objetos e descompacte nele todos os arquivos mencionados no
início da apostila.

Todos os objetos que são 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 máquina qualquer para outro em
outra máquina, fora o controle dos mesmos, aqui colocarei por ordem na Componnent Pallete que os objetos serão
instalados, antes de instalar qualquer objeto dê uma olhada se ele depende da instalação de outro primeiro, para iniciar
vamos instalar o primeiro objeto, vá em Component | Install Component... e na página Into new Package e será
mostrada a seguinte janela:

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página Nr. 14/178
Unit file name - Corresponde ao nome do fonte que contém o objeto (localize o arquivo Posestad.PAS)
Search path - Caminhos disponíveis dos diversos objetos
Package file name - Nome do Pacote que será instalado seu objeto (localize o diretório Lib1 e coloque o nome
Colecao.DPK)
Package description - Uma descrição do pacote (Coleção com meus objetos por exemplo)

Após preenchido os dados necessários e pressionado o botão 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 botão Add e
adicionarmos os fontes mencionados. Ao final de todo o processo de instalação compilaremos todos os objetos
instalados através do botão Compile. Vamos começar então:

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página Nr. 15/178
Objetos Instalados na Component Pallete em Additional
PosEstado -
Objetivo:
Objeto derivado do TPanel que verifica e mostra o estado e o número de registros de um objeto do tipo BDE
ligado a um DataSource

Propriedades:
DataSource: Nome do DataSource que está ligado o BDE

Funções ou procedimentos necessários para execução:


Procedimento Atualiza - faz a verificação 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 conteúdo de um objeto StringGrid.

Propriedades:
LeftMargin: margem a esquerda
TopMargin: margem entre o início da página e o começo da impressão
RightMargin: margem a direita
BottomMargin: margem a ser deixada no final da página
ColHeaderFont: Fonte do cabeçalho
ColScale: Escala de impressão (Ex: 100 % a 0 %)
TitleFont: Fonte do Título
LinesFont: Fonte das linhas detalhe
StringGrid: Objeto StringGrid a imprimir
PrintMgrTitle: Título
Title: Cabeçalho
TitleAlignment: Alinhamento do Cabeçalho
Orientation: Tipo de orientação do papel
PrintToFile: Se ao invés de imprimir gera um arquivo
FullPage: Página toda
PrintFileName: Nome do arquivo a gerar
PrintFileDir: Diretório do arquivo a gerar
FromPage: Inicia na página
EndPage: Até a página
Border: Deve imprimir linhas em volta
ColLines: Deve imprimir linhas entre as colunas
RowLines: Deve imprimir linhas entre as linhas detalhe
HorizontalGap: Distância horizontal entre as linhas detalhes
VerticalGapPct: Distância vertical entre as linhas detalhes
PageNumberPos: Posição do número da página
PageNumberLabel: Label para o número da página (Ex: Pág:)
DatePos: Posição da data atual
DateLabel: Label para a data atual (Ex: Data:)

Funções ou procedimentos necessários para execução:


Procedimento Print - Inicia o processo de impressão

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página Nr. 16/178
Procedimento PrintDialog - Mostra uma janela de configuração da impressão
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é María Ferri - jmferri@hotmail.com)

Objetivo:
Objeto derivado do TEdit que o melhora proporciando um alinhamento do texto a Direita, a Esquerda ou
Centralizado e modificação das cores do objeto caso esteje ou não em foco

Propriedades:
Alignment: Tipo do Alinhamento
ColorOnFocus: Cor do objeto quando tiver o foco
ColorOnNoFocus: Cor do objeto quando não tiver o foco
TextOnFocus: Cor do texto quando o objeto tiver o foco
TextOnNoFocus: Cor do texto quando o objeto não tiver o foco
ExitOnReturn: Se deve sair do objeto com o pressionamento da tecla Enter

Funções ou procedimentos necessários para execução:


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 visão 3D
AHShadeOffSet : Distância horizontal da sombra
AVShadeOffSet : Distância vertical da sombra
AShadeLTSet : se o degradê deve ficar Branco ou assumir a cor da propriedade AShadeLeftTop

Funções ou procedimentos necessários para execução:


Nenhuma

Fonte que deve ser instalados no pacote


MyLabel.pas

Objeto ao qual depende que seja instalado primeiramente


Nenhum

EditN - (Original de José.Mª Gías - 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 - Página Nr. 17/178
Propriedades:
ColorOnFocus: Cor de fundo quando o Edit tem o Foco
ColorOnNotFocus: Cor de fundo quando o Edit não 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.

Funções ou procedimentos necessários para execução:


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 através de um determinado valor inicial de um campo
dentro de um objeto do tipo tTable, mostrando em uma janela se caso o valor não exista na tabela se existe
valores semelhantes aquele informado, ao final retorna uma variável do tipo boolean informando se
encontrou ou não o registro procurado.

Propriedades:
aVersao: Contém o número da versão do objeto
Tabela: em qual objeto será pesquisada
CmpDig:
Filtro: Caso a tabela esteja com o filtro ativo
PosCampo: Posição (propriedade Index do TField) do campo a pesquisar dentro na tabela
TipoSQL: Se será pesquisado em uma base Access ou Paradox (padrão Ansi-SQL)

Funções ou procedimentos necessários para execução:


Função 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 através de um complexo conjunto de pesquisa determinado
registro dentro de um objeto do tipo tTable, ao final retorna uma variável do tipo boolean informando se
encontrou ou não o registro procurado.

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página Nr. 18/178
Propriedades:
aVersao: Contém o número da versão 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 (padrão Ansi-SQL)

Funções ou procedimentos necessários para execução:


Função 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 aplicação
SaveShowAtStart: Se deve salvar para mostrar ou não
SaveKey : String read FSaveKey write FSaveKey;
Language: Linguagem do objeto (Português, Inglês ou Alemão)
TipBackground: Cor de Fundo
Header: Cabeçalho
Title: Título
TipHelp: Título da Dica
ShowAtStart: Se deve mostrar ou não na próxima vez
Tips: Dicas a serem mostradas, uma dica por linha, será escolhida por processo randômico
TipsCount: Total de dicas

Funções ou procedimentos necessários para execução:


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 prévia para a escolha das opções

Propriedades:
aVersao: Contém o número da versão 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 - Página Nr. 19/178
registro desejado...
NomeRel: Título do relatório
Filtro: Caso a tabela esteja com algum filtro

Funções ou procedimentos necessários para execução:


Procedimento Print - Inicia o processo de impressão
Procedimento PrintDialog - Mostra uma janela de configuração da impressão
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 usuário defina e configure a opção Filter do objeto tTable, pode ainda ser utilizado para criar
cláusulas Where de comandos SQL.

Propriedades:
aVersao: Contém o número da versão 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 usuário 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 (padrão Ansi-SQL)

Funções ou procedimentos necessários para execução:


Procedimento Execute - Inicia a janela e devolve True caso seja concluído 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: Contém o número da versão do objeto
CodSQL: SQL para o tQuery
DatabaseName: Nome do DataBaseName
LabPesq: Caption do Label que aparece acima do DBGrid servindo de rótulo
LigaDes: Ativa e desativa a tQuery
OpcaoGrid: Opções do DBGrid
OpcaoGridCol: Opções das colunas do DBGrid

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página Nr. 20/178
Funções ou procedimentos necessários para execução:
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 conteúdo de um objeto DbGrid.

Propriedades:
LeftMargin: margem a esquerda
LeftMargin: margem a esquerda
TopMargin: margem entre o início da página e o começo da impressão
RightMargin: margem a direita
BottomMargin: margem a ser deixada no final da página
ColHeaderFont: Fonte do cabeçalho
ColScale: Escala de impressão (Ex: 100 % a 0 %)
TitleFont: Fonte do Título
LinesFont: Fonte das linhas detalhe
DBGrid: Objeto StringGrid a imprimir
PrintMgrTitle: Título
Title: Cabeçalho
TitleAlignment: Alinhamento do Cabeçalho
Orientation: Tipo de orientação do papel
PrintToFile: Se ao invés de imprimir gera um arquivo
FullPage: Página toda
PrintFileName: Nome do arquivo a gerar
PrintFileDir: Diretório do arquivo a gerar
FromPage: Inicia na página
EndPage: Até a página
Border: Deve imprimir linhas em volta
ColLines: Deve imprimir linhas entre as colunas
RowLines: Deve imprimir linhas entre as linhas detalhe
HorizontalGap: Distância horizontal entre as linhas detalhes
VerticalGapPct: Distância vertical entre as linhas detalhes
PageNumberPos: Posição do número da página
PageNumberLabel: Label para o número da página (Ex: Pág:)
DatePos: Posição da data atual
DateLabel: Label para a data atual (Ex: Data:)

Funções ou procedimentos necessários para execução:


Procedimento Print - Inicia o processo de impressão
Procedimento PrintDialog - Mostra uma janela de configuração da impressão
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 - Página Nr. 21/178
DBCmpList -
Objetivo:
Substituir o DBLookupCombo quando em pesquisa em tabelas secundárias, por exemplo, em funcionário se
cadastra o órgão ao qual o funcionário trabalha, este órgão será cadastrado utilizando este objeto, veja nas
propriedades o exemplo detalhado, conforme a seguinte estrutura:

tbFuncionario (Tab. Primária) tbCargo (Tab. Secundária)


COD_FUNCIONARIO COD_CARGO
COD_CARGO SIG_CARGO
{ Outros Campos } DES_CARGO

Propriedades:
aVersao: Contém o número da versão do objeto
CapLocaliza: Caption a ser usado no botão de localiza
DataField: Nome do campo a inserir (No exemplo: CD_CARGO)
DataSource: Nome do DataSource dono do DataField (No exemplo: dsFuncionário)
TbSecundaria: Nome da Tabela Secundária a pesquisar (No exemplo: tbCargo)
CriticaEd: Se deve ou não criticar o modo de Edição para a utilização do botão Localiza
GlyphLoc: Glyph para o botão de localiza (No exemplo: Localize o BMP que mais lhe agradar)
MensagemCodigo: Uma mensagem caso não encontre o campo código (No exemplo: Código do Cargo não
cadastrado)
MensagemSigla: Uma mensagem caso não encontre o campo sigla (No exemplo: Sigla do Cargo não
cadastrada)
MensagemDescricao: Uma mensagem caso não encontre o campo descrição (No exemplo: Cargo não
cadastrado)
NumGlyphsLoc: Número de Glyphs da imagem do botão de localiza
PosCmpCodigoSec: Posição em FIELD.INDEX do campo Código (No exemplo: 0)
PosCmpDescricao: Posição em FIELD.INDEX do campo Descrição (No exemplo: 2)
PosCmpSigla: Posição em FIELD.INDEX do campo Sigla (No exemplo: 1)
TamEdtCodigo: Tamanho do Edit do campo Código
TamEdtDescricao: Tamanho do Edit do campo Descrição
TamEdtSigla: Tamanho do Edit do campo Sigla
PosEdtCodigo: Posição a esquerda do campo Código
PosEdtDescricao: Posição a esquerda do campo Descrição
PosEdtSigla: Posição a esquerda do campo Sigla
TopEdtCodigo: Posição do topo do campo Código
TopEdtDescricao: Posição do topo do campo Descrição
TopEdtSigla: Posição do topo do campo Sigla
HintButLoc: Hint para o botão de Localiza (No exemplo: Localiza determinado Cargo)
UsaLocaliza: Se vai ou não usar o botão de Localiza
UsaDescricao: Se vai ou não usar o campo Descrição
UsaSigla: Se vai ou não 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 (padrão Ansi-SQL)
Evento OnMudaFiltro: Se ocorrer alguma mudança no Filtro

Funções ou procedimentos necessários para execução:


ATENÇÃO - Em programa as tabelas Secundárias devem ser abertas primeiras que a tabela Principal e para
fechar proceda de forma contrária. 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 - Página 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 produção de jogos de cartas

Propriedades:
Card: Utilizado para selecionar uma determinada carta
SelectedCard: Determina se a carta vai ter aparência de selecionada ou não
ShowCard: Determina o lado da carta
Suit: Determina qual o Nipe da carta

Funções ou procedimentos necessários para execução:


Nenhuma

Fonte que deve ser instalado no pacote


Cards.pas

Objeto ao qual depende que seja instalado primeiramente


Nenhum

Moon - (Original de Andreas Hörstemeier)

Objetivo:
Objeto derivado do TImage que através de um algorítmo astronômico calcula vários dados sobre a lua e o sol,
ideal para sistemas exotéricos e agendas

Propriedades:
Date: Data e Hora para o cálculo
MoonSize: Tamanho do Display

Funções ou procedimentos necessários para execução:


Função Julian_date: recebe uma Data e Hora e devolve a Data Juliana
Função Sun_distance: recebe uma Data e Hora e devolve a distância da Terra ao Sol
Função Moon_distance: recebe uma Data e Hora e devolve a distância da Terra à Lua
Função Age_of_moon: recebe uma Data e Hora e devolve a idade da Lua
Função function last_phase: recebe uma Data, Hora e a Fase da Lua de devolve a data da última fase
Função next_phase: recebe uma Data, Hora e a Fase da Lua de devolve a data da próxima fase
Função current_phase: recebe uma Data, Hora e devolve a Fase da Lua
Função lunation: recebe uma Data e Hora e devolve a lunação da lua
Função sun_diameter: recebe uma Data e Hora e devolve o diâmetro do Sol
Função moon_diameter: recebe uma Data e Hora e devolve o diâmetro da Lua
Função 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 - Página Nr. 23/178
ChessBrd - (Original de Daniel Terhell)

Objetivo:
Jogar uma partida de Xadrez em um dos objetos mais incríveis que já vi, ideal para ser colocado no sobre do
sistema como opção para o usuário.

Propriedades mais importantes:


AnimateMoves: Movimentos devem ser animados
AnimateDelay: Se deve haver um tempo para a animação
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: Posição de todas as peças no tabuleiro

Funções ou procedimentos necessários para execução:


Procedimento NewGame: Inicializa um novo jogo
Procedimento UpdateChessBoard: Recebe a posição do tabuleiro
Variáveis 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

Coleção Date97- Todos estes objetos são originais de BOURMAD Mehdi - bourmad@mygale.org
e contém os seguintes objetos:

Calendar97 , DbCalendar97 , DateEdit97 , DbDateEdit97 , DateFromTo97

Objetivo:
Função principal de todos é controlar variáveis 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 - Página Nr. 24/178
Principais Instruções em SQL
Autor: Fernando Antonio Fernandes Anselmo
E-Mail: fernandoanselmo@yahoo.com.br

Pré-Requisitos:

Windows 98
Delphi 4.0 versão Client/Server Suite

BDE 5.00
MS-Access 97

Prefácio
Esta apostila foi desenvolvida com o auxílio on-Line do banco MS-ACCESS, este tipo de SQL para
este banco não é totalmente compatível com o SQL Padrão ANSI, que é o oficial na maioria dos bancos de dados,
então algumas cláusulas podem não funcionar em outros gerenciadores de bancos de dados.

Instrução SELECT
Instrui o programa principal do banco de dados para retornar a informação como um conjunto de registros.

Sintaxe
SELECT [predicado { * | tabela.* | [tabela.]campo1 [AS alias1] [, [tabela.]campo2 [AS alias2] [, ...]]}
FROM expressãotabela [, ...] [IN bancodedadosexterno]
[WHERE... ]
[GROUP BY... ]
[HAVING... ]
[ORDER BY... ]
[WITH OWNERACCESS OPTION]

A instrução SELECT tem as partes abaixo:

Parte Descrição
predicado Um dos seguintes predicados: ALL, DISTINCT, DISTINCTROW ou TOP.
Você usa o predicado para restringir o número de registros que retornam. Se
nenhum for especificado, o padrão será ALL.
* Especifica que todos os campos da tabela ou tabelas especificadas são
selecionados.
tabela O nome da tabela que contém os campos dos quais os registros são
selecionados.
campo1, campo2 Os nomes dos campos dos quais os dados serão recuperados. Se você
incluir
mais de um campo, eles serão recuperados na ordem listada.
alias1, alias2 Os nomes que serão usados como títulos de colunas em vez dos nomes
originais das colunas na tabela.
expressãotabela O nome da tabela ou tabelas contendo os dados que você quer recuperar.
bancodedadosexterno O Nome do banco de dados que contém as tabelas em expressãotabela se não

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página Nr. 25/178
estiver no banco de dados atual.

Comentários
Para executar esta operação, o programa principal de banco de dados procura a tabela ou tabelas
especificadas, extrai as colunas escolhidas, seleciona as linhas que satisfazem o critério e classifica ou agrupa as linhas
resultantes na ordem especificada.

A instrução SELECT não muda os dados no banco de dados.

SELECT é normalmente a primeira palavra em uma instrução SQL. A maior parte das instruções SQL
são instruções SELECT.

A sintaxe mínima da instrução SELECT é:


SELECT campos FROM tabela

Você pode usar um asterisco (*) para selecionar todos os campos na tabela. O exemplo abaixo seleciona
todos os campos na tabela Funcionários:
SELECT * FROM Funcionários;

Se o nome de um campo estiver incluído em mais de uma tabela na cláusula FROM, preceda-o com o
nome da tabela e o operador . (ponto). No exemplo abaixo, o campo Departamento está nas tabelas Funcionários e
Supervisores. A instrução SQL seleciona Departamento da tabela Funcionários e NomeSupv da tabela Supervisores:

SELECT Funcionários.Departamento, Supervisores.NomeSupv


FROM Funcionários INNER JOIN Supervisores
WHERE Funcionários.Departamento = Supervisores.Departamento;

Ao criar um objeto Recordset, o programa principal de banco de dados do Jet usa o nome do campo da
tabela como o nome do objeto Field no objeto Recordset. Se você quiser um nome de campo diferente ou um nome que
não esteja implícito na expressão usada para gerar o campo, use a palavra reservada AS. O exemplo abaixo usa o título
Nasc para nomear o objeto Field retornado no objeto Recordset resultante:

SELECT DataNasc AS Nasc FROM Funcionários;

Sempre que você usar funções aggregate ou consultas que retornem nomes de objetos Field ambíguos
ou duplicados, você precisará usar a cláusula AS para fornecer um nome alternativo para o objeto Field. O exemplo
abaixo usa o título Contagem para nomear o objeto Field retornado no objeto Recordset resultante:

SELECT COUNT(FuncionárioID) AS Contagem FROM Funcionários;

Você pode usar outras cláusulas na instrução SELECT para restringir e organizar posteriormente os
seus dados retornados.

Cláusula GROUP BY
GROUP BY é opcional. Valores de resumo são omitidos se não houver qualquer função aggregate SQL
na instrução SELECT. Os valores Null nos campos GROUP BY são agrupados e não omitidos. No entanto, os valores
Null não são avaliados em qualquer função aggregate SQL. Use a cláusula WHERE para excluir linhas que você não
quer agrupadas e use a cláusula HAVING para filtrar os registros após eles terem sido agrupados.

A não ser que contenha dados Memo ou OLE Object, um campo na lista de campos GROUP BY pode
fazer referência a qualquer campo em qualquer tabela listada na cláusula FROM. Mesmo que o campo não esteja
incluído na instrução SELECT, fornecida a instrução SELECT, inclua pelo menos uma função SQL. O programa
principal de banco de dados do Jet não pode agrupar campos Memo ou OLE Objects.

Todos os campos na lista de campos SELECT devem ser incluídos na cláusula GROUP BY ou
incluídos como argumentos em uma função aggregate SQL.

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página Nr. 26/178
Cláusula HAVING
HAVING é opcional. HAVING é semelhante a WHERE, que determina quais registros são
selecionados. Depois que os registros são agrupados com GROUP BY, HAVING determina quais registros são
exibidos:

SELECT CategoriaID, Sum(UnidadesNoEstoque) FROM Produtos


GROUP BY CategoriaID
HAVING Sum(UnidadesNoEstoque) > 100 AND LIKE "BOS*";

Uma cláusula HAVING pode conter até 40 expressões vinculadas por operadores lógicos, como And ou Or.

Cláusula ORDER BY
ORDER BY é opcional. Entretanto, se você quiser exibir seus dados na ordem classificada, você deve
utilizar ORDER BY. O padrão ordem de classificação é ascendente (A a Z, 0 a 9). Os dois exemplos abaixo classificam
os nomes dos funcionários pelo sobrenome.

SELECT Sobrenome, Nome FROM Funcionários ORDER BY Sobrenome;

SELECT Sobrenome, Nome FROM Funcionários ORDER BY Sobrenome ASC;

Para classificar em ordem descendente (Z a A, 9 a 0), adicione a palavra reservada DESC ao final de
cada campo que você quiser classificar em ordem descendente. O exemplo abaixo seleciona salários e os classifica em
ordem descendente

SELECT Sobrenome, Salário FROM Funcionários ORDER BY Salário DESC, Sobrenome;

Se você especificar um campo que contém dados Memo ou OLE Objects na cláusula ORDER BY, um
erro ocorrerá. O programa principal de banco de dados do Jet não classifica campos deste tipo. ORDER BY é
normalmente o último item em uma instrução SQL.

Você pode incluir campos adicionais na cláusula ORDER BY. Os registros são classificados primeiro
pelo primeiro campo listado depois de ORDER BY. Os registros que tiverem valores iguais naquele campo são
classificados pelo valor no segundo campo listado e assim por diante.

Cláusula WITH OWNERACCESS OPTION


A declaração WITH OWNERACCESS OPTION é opcional. O exemplo abaixo habilita o usuário a ver
as informações de salário (mesmo que não tenha outra permissão para ver a tabela Folha de Pagamentos) desde que o
proprietário da consulta tenha tal permissão:

SELECT Sobrenome, Nome, Salário FROM Funcionários ORDER BY Sobrenome


WITH OWNERACCESS OPTION;

Se, por outro lado, um usuário for impedido de criar ou anexar a uma tabela, você poderá usar WITH
OWNERACCESS OPTION para habilitá-lo a executar uma consulta construção de tabela ou consulta anexação. Se
você quiser reforçar as configurações de segurança do grupo de trabalho e as permissões dos usuários, não inclua a
declaração WITH OWNERACCESS OPTION. Esta opção exige que você tenha acesso ao arquivo System.mda
associado ao banco de dados. É realmente útil em implementações de multiusuários seguras.

Exemplo da instrução SELECT, cláusula FROM


Esse exemplo seleciona os campos "Sobrenome" e "Nome" de todos os registros da tabela
"Funcionários".

SELECT Sobrenome, Nome FROM Funcionários

Esse exemplo seleciona todos os campos da tabela "Funcionários".

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página Nr. 27/178
SELECT Funcionários.* FROM Funcionários;

Esse exemplo conta o número de registros que têm uma entrada no campo "CódigoPostal" e nomeia o
campo retornado como "Tcp".

SELECT Count(CódigoPostal) AS Tcp FROM Clientes;

Esse exemplo mostra qual seria o salário se cada funcionário recebesse um aumento de 10 porcento.
Não altera o valor original dos salários.

SELECT Sobrenome, Salário AS Atual, Salário * 1.1 AS Proposto FROM Funcionários;

Esse exemplo coloca o título Nome no topo da coluna "Sobrenome". O título Salário é exibido no topo
da coluna "Salário".

SELECT Sobrenome AS Nome, Salário FROM Funcionários;

Esse exemplo mostra o número de funcionários e os salários médio e máximo.

SELECT Count(*) AS [Total de Funcionários], Avg(Salário) AS [Salário Médio], Max(Salário) AS [Salário Máximo]
FROM Funcionários;

Para cada registro, mostra Sobrenome e Salário no primeiro e último campos. A seqüência de caracteres
"tem um salário de" é retornada como o campo do meio de cada registro.

SELECT Sobrenome, 'tem um salário de', Salário FROM Funcionários;

Exemplo de cláusula GROUP BY


Esse exemplo cria uma lista de nomes de departamentos únicos e o número de funcionários em cada um
destes departamentos.

SELECT Departamento, Count([Departamento]) AS Tbc FROM Funcionários


GROUP BY Departamento;

Para cada título de função único, calcula o número de funcionários do departamento de Vendas que têm
este título.

SELECT Título, Count(Título) AS Tbc FROM Funcionários


WHERE Departamento = 'Vendas' GROUP BY Título;

Esse exemplo calcula o número de itens em estoque para cada combinação de número e cor do item.

SELECT Item, Sum(Unidades) AS Tbc FROM ItensEmEstoque


GROUP BY Item, Cor;

Exemplo de cláusula HAVING


Esse exemplo seleciona os títulos de cargos do departamento de Produção atribuídos a mais de 50
funcionários.

SELECT Título, Count(Título) FROM Funcionários WHERE Departamento = 'Produção'


GROUP BY Título HAVING Count(Título) > 50;

Esse exemplo seleciona os departamentos que tenham mais de 100 funcionários.

SELECT Departamento, Count([Departamento]) FROM Funcionários


GROUP BY Departamento HAVING Count(Departamento) > 100;

Exemplo de cláusula ORDER BY

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página Nr. 28/178
As instruções SQL mostradas abaixo usam a cláusula ORDER BY para classificar os registros em
ordem alfabética e depois por categoria.

Esse exemplo ordena os registros pelo sobrenome, em ordem descendente (Z-A).

SELECT Sobrenome, Nome FROM Funcionários ORDER BY Sobrenome DESC;

Esse exemplo ordena, primeiro, por categoria ID e depois por nome do produto.

SELECT CategoriaID, ProdutoNome, PreçoUnit FROM Produtos


ORDER BY CategoriaID, NomeProduto;

Instrução INSERT INTO


Adiciona um ou vários registros a uma tabela. Isto é referido como consulta anexação.

Sintaxe
Consulta anexação de vários registros:

INSERT INTO destino [IN bancodedadosexterno] [(campo1[, campo2[, ...]])]


SELECT [origem.]campo1[, campo2[, ...]
FROM expressãodetabela

Consulta anexação de um único registro:

INSERT INTO destino [(campo1[, campo2[, ...]])]


VALUES (valor1[, valor2[, ...])

A instrução INSERT INTO tem as partes abaixo:

Parte Descrição
destino O nome da tabela ou consulta em que os registros devem ser anexados.
bancodedadosexterno O caminho para um banco de dados externo. Para uma descrição do
caminho, consulte a cláusula IN.
origem O nome da tabela ou consulta de onde os dados devem ser copiados.
campo1, campo2 Os nomes dos campos aos quais os dados devem ser anexados, se
estiverem após um argumento destino ou os nomes dos campos dos quais
se deve obter os dados, se estiverem após um argumento origem.
expressãodetabela O nome da tabela ou tabelas das quais registros são inseridos. Este
argumento pode ser um único nome de tabela ou uma combinação
resultante de uma operação INNER JOIN, LEFT JOIN ou RIGHT JOIN
ou de uma consulta gravada.
valor1, valor2 Os valores para inserir em campos específicos do novo registro. Cada valor
é inserido no campo que corresponde à posição do valor na lista: Valor1 é
inserido no campo1 do novo registro, valor2 no campo2 e assim por
diante. Você deve separar os valores com uma vírgula e colocar os
campos de textos entre aspas (" ").

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página Nr. 29/178
Comentários
Você pode usar a instrução INSERT INTO para adicionar um único registro a uma tabela usando a
sintaxe de consulta anexação de um único registro como mostrado acima. Neste caso, seu código especifica o nome e o
valor de cada campo do registro. Você precisa especificar cada um dos campos do registro para os quais um valor deve
ser designado e um valor para este campo. Quando você não especifica cada campo, o valor padrão ou Null é inserido
nas colunas omitidas. Os registros são adicionados no final da tabela.

Você também pode usar INSERT INTO para anexar um conjunto de registros de outra tabela ou
consulta usando a cláusula SELECT ... FROM como é mostrado acima na sintaxe consulta anexação de vários
registros. Neste caso, a cláusula SELECT especifica os campos para acrescentar à tabela destino especificada.

A tabela de origem ou de destino pode especificar uma tabela ou uma consulta. Se uma consulta for
especificada, o programa principal de banco de dados do Microsoft anexa a qualquer e a todas as tabelas especificadas
pela consulta.

INSERT INTO é opcional, mas quando incluída, precede a instrução SELECT.

Se sua tabela de destino contém uma chave primária, você deve acrescentar valores únicos, não Null ao
campo ou campos da chave primária. Caso contrário, o programa principal de banco de dados do Jet não anexará os
registros.

Se você anexar registros a uma tabela com um campo Counter e quiser numerar novamente os registros
anexados, não inclua o campo Counter em sua consulta. Inclua o campo Counter na consulta se quiser manter os
valores originais do campo.

Use a cláusula IN para anexar registros a uma tabela de outro banco de dados. Para achar quais registros
serão anexados, antes de você executar a consulta anexação, primeiro execute e veja os resultados de uma consulta
seleção que use o mesmo critério de seleção.

Uma operação de consulta anexação copia os registros de uma ou mais tabelas em outra. As tabelas que
contêm os registros que você anexa não são afetadas pela operação de consulta anexação.

Em lugar de acrescentar registros existentes de outra tabela, você pode especificar o valor de cada
campo em um único registro novo usando a cláusula VALUES. Se você omitir a lista de campo, a cláusula VALUES
deve incluir um valor para cada campo na tabela; caso contrário, um erro ocorrerá em INSERT. Use uma instrução
adicional INSERT INTO com uma cláusula VALUES para cada registro adicional que você quiser criar.

Exemplo de instrução INSERT INTO


Esse exemplo seleciona todos os registros de uma tabela hipotética "Novos Clientes" e os adiciona à
tabela "Clientes" (quando não são designadas colunas individuais, os nomes das colunas das tabelas SELECT devem
corresponder exatamente aos da tabela INSERT INTO).

INSERT INTO Clientes SELECT [Novos Clientes].*


FROM [Novos Clientes];

Esse exemplo cria um novo registro na tabela "Funcionários"

INSERT INTO Funcionários (Nome,Sobrenome, Título)


VALUES ("André", "Pereira", "Estagiário");

Esse exemplo seleciona todos os estagiários de uma tabela hipotética "Estagiários" que foram
contratados há mais de 30 dias e adiciona seus registros à tabela "Funcionários".

INSERT INTO Funcionários SELECT Estagiários.*


FROM Estagiários WHERE DataContrato < Now() - 30;

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página Nr. 30/178
Declaração UPDATE
Cria uma consulta atualização que altera os valores dos campos em uma tabela especificada com base em critérios
específicos.

Sintaxe
UPDATE tabela
SET valornovo
WHERE critério;

A instrução UPDATE tem as partes abaixo:

Parte Descrição
tabela O nome da tabela cujos os dados você quer modificar.
valornovo Uma expressão que determina o valor a ser inserido em um campo específico nos
registros atualizados.
critério Uma expressão que determina quais registros devem ser atualizados. Só os registros
que satisfazem a expressão são atualizados.

Comentários
UPDATE é especialmente útil quando você quer alterar muitos registros ou quando os registros que
você quer alterar estão em várias tabelas. Você pode alterar vários campos ao mesmo tempo. O exemplo abaixo
aumenta o Valor do Pedido em 10 por cento e o valor do Frete em 3 por cento para embarques do Reino Unido:

UPDATE Pedidos SET ValorPedido = ValorPedido * 1.1, Frete = Frete * 1.03


WHERE PaísEmbarque = 'RU';

UPDATE não gera um conjunto de resultados. Se você quiser saber quais resultados serão alterados,
examine primeiro os resultados da consulta seleção que use os mesmos critérios e então execute a consulta atualização.

Exemplo de instrução UPDATE


Esse exemplo muda os valores no campo "RelatórioPara" para 5 para todos os registros de funcionários
que atualmente têm valores de RelatórioPara de 2.

UPDATE Funcionários SET RelatórioPara = 5 WHERE RelatórioPara = 2;

Esse exemplo aumenta o "PreçoUnit" de todos os produtos não suspensos do fornecedor 8 em 10


porcento.

UPDATE Produtos SET PreçoUnit = PreçoUnit * 1.1


WHERE FornecedorID = 8 AND Suspenso = No;

Esse exemplo reduz o PreçoUnit de todos os produtos não suspensos fornecidos pela Tokyo Traders em
5 porcento. As tabelas "Produtos" e "Fornecedores" têm uma relação um para vários.

UPDATE Fornecedores INNER JOIN Produtos

ON Fornecedores.FornecedorID = Produtos.FornecedorID SET PreçoUnit = PreçoUnit * .95


WHERE NomeEmpresa = 'Tokyo Traders' AND Suspenso = No;

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página Nr. 31/178
Instrução DELETE
Cria uma consulta exclusão que remove registros de uma ou mais tabelas listadas na cláusula FROM que satisfaz a
cláusula WHERE.

Sintaxe
DELETE [tabela.*]
FROM tabela
WHERE critério

A instrução DELETE tem as partes abaixo:

Parte Descrição
tabela.* O nome opcional da tabela da qual os registros são excluídos.
tabela O nome da tabela da qual os registros são excluídos.
critério Uma expressão que determina qual registro deve ser excluído.

Comentários

DELETE é especialmente útil quando você quer excluir muitos registros. Para eliminar uma tabela
inteira do banco de dados, você pode usar o método Execute com uma instrução DROP.

Entretanto, se você eliminar a tabela, a estrutura é perdida. Por outro lado, quando você usa DELETE,
apenas os dados são excluídos. A estrutura da tabela e todas as propriedades da tabela, como atributos de campo e
índices, permanecem intactos.

Você pode usar DELETE para remover registros de tabelas que estão em uma relação um por vários
com outras tabelas. Operações de exclusão em cascata fazem com que os registros das tabelas que estão no lado
"vários" da relação sejam excluídos quando os registros correspondentes do lado "um" da relação são excluídos na
consulta. Por exemplo, nas relações entre as tabelas Clientes e Pedidos, a tabela Clientes está do lado "um" e a tabela
Pedidos está no lado "vários" da relação. Excluir um registro em Clientes faz com que os registros correspondentes em
Pedidos sejam excluídos se a opção de exclusão em cascata for especificada.

Uma consulta de exclusão exclui registros inteiros e não apenas dados em campos específicos. Se você
quiser excluir valores de um campo específico, crie uma consulta atualização que mude os valores para Null.

Importante
Após remover os registros usando uma consulta exclusão, você não poderá desfazer a operação. Se
quiser saber quais arquivos foram excluídos, primeiro examine os resultados de uma consulta seleção que use o mesmo
critério e então, execute a consulta exclusão. Mantenha os backups de seus dados. Se você excluir os registros errados,
poderá recuperá-los a partir dos seus backups.

Exemplo de instrução DELETE


Esse exemplo exclui todos os registros de funcionários cujo título seja Estagiário. Quando a cláusula
FROM inclui apenas uma tabela, não é necessário indicar o nome da tabela na instrução DELETE.

DELETE *FROM Funcionários WHERE Título = 'Estagiário';

Esse exemplo exclui todos os registros de funcionários cujo título seja Estagiário e que também tenham
um registro na tabela "FolhadePagamento". As tabelas "Funcionários" e "FolhadePagamento" têm uma relação um por
um.

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página Nr. 32/178
DELETE Funcionários.* FROM Funcionários INNER JOIN FolhaDePagamento
ON Funcionários.FuncionárioID = FolhadePagamento.FuncionárioID
WHERE Funcionários.Título = 'Estagiário';

Subconsultas SQL
Uma subconsulta é uma instrução SELECT aninhada dentro de uma instrução SELECT, INSERT, DELETE ou
UPDATE ou dentro de uma outra subconsulta.

Sintaxe
Você pode usar três formas de sintaxe para criar uma subconsulta:

comparação [ANY | ALL | SOME] (instruçãosql)


expressão [NOT] IN (instruçãosql)
[NOT] EXISTS (instruçãosql)

Uma subconsulta tem as partes abaixo:

Parte Descrição
comparação Uma expressão e um operador de comparação que compara a expressão com o resultado
da subconsulta.
expressão Uma expressão para a qual o resultado definido da subconsulta é procurado.
instruçãosqlt Uma instrução SELECT de acordo com as mesmas regras e formato de qualquer outra
instrução SELECT. Ela deve estar entre parênteses.

Comentários
Você pode usar uma subconsulta em vez de uma expressão na lista de campo de uma instrução
SELECT ou em uma cláusula WHERE ou HAVING. Em uma subconsulta, você usa uma instrução SELECT para
fornecer um conjunto de um ou mais valores específicos para avaliar as expressões das cláusulas WHERE ou
HAVING.

Use o predicado ANY ou SOME, que são sinônimos, para recuperar registros na consulta principal que
satisfaçam a comparação com quaisquer registros recuperados na subconsulta. O exemplo abaixo retorna todos os
produtos cujo preço unitário é maior que o preço de qualquer produto vendido com um desconto de 25 por cento ou
mais:

SELECT * FROM Produtos WHERE PreçoUnit > ANY


(SELECT PreçoUnit FROM PedidoDetalhes WHERE Desconto >= .25);

Use o predicado ALL para recuperar apenas os registros na consulta principal que satisfaçam a
comparação com todos os registros recuperados na subconsulta. Se você mudou ANY para ALL no exemplo acima, a
consulta retornaria apenas os produtos cujo preço unitário fosse maior que o de todos os produtos vendidos com um
desconto de 25 por cento ou mais. Isto é muito mais restritivo.

Use o predicado IN para recuperar apenas os registros na consulta principal para os quais alguns
registros na subconsulta contêm um valor igual. O exemplo abaixo retorna todos os produtos com um desconto de 25
por cento ou mais:

SELECT * FROM Produtos WHERE ProdutoID IN


(SELECT ProdutoID FROM PedidoDetalhes WHERE Desconto >= .25);

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página Nr. 33/178
De maneira contrária, você pode usar NOT IN para recuperar apenas os registros na consulta principal
para os quais não existam registros com valores iguais na subconsulta. Utilize o predicado EXISTS (com a palavra
reservada NOT opcionalmente) em comparações true/false para determinar se a subconsulta retorna algum registro.

Você também pode usar aliases de nomes de tabelas em uma subconsulta para fazer referência a tabelas
listadas em uma cláusula FROM fora da subconsulta. O exemplo abaixo retorna os nomes dos funcionários cujos
salários sejam iguais ou superiores à média de salários de todos os funcionários na mesma função. Para a tabela
Funcionários é dada o alias "T1":

SELECT Sobrenome, Nome, Título, Salário FROM Funcionários AS T1


WHERE Salário >= (SELECT Avg(Salário)
FROM Funcionários WHERE T1. T1.Título = Funcionários.Título) Order by Title;

No exemplo acima, a palavra reservada AS é opcional. Algumas subconsultas são aceitas em consultas
de tabela cruzada especialmente como predicados (as da cláusula WHERE). Subconsultas como saída (as da lista
SELECT) não são aceitas em tabelas de referência cruzada.

Exemplos de subconsultas SQL


Esse exemplo lista o nome, título e salário de todos os representantes de vendas cujos salários sejam
superiores aos de todos os gerentes e diretores.
SELECT Sobrenome, Nome, Título, Salário FROM Funcionários
WHERE Título LIKE "*Repr Vendas*" AND Salário > ALL
(SELECT Salário FROM Funcionários WHERE (Título LIKE "*Gerente*")
OR (Título LIKE "*Diretor*"));

Esse exemplo lista o nome e preço unitário de todos os produtos cujo preço unitário seja igual ao do
Licor de Cacau.

SELECT NomeProduto, PreçoUnit FROM Produtos


WHERE PreçoUnit = (SELECT PreçoUnit FROM [Produtos]
WHERE NomeProduto = "Licor de Cacau");

Esse exemplo lista a empresa e o contato de cada empresa de todos os clientes que fizeram pedidos no
segundo trimestre de 1995.

SELECT NomeContato, NomeEmpresa, ContatoTítulo, Fone FROM Clientes


WHERE ClienteID IN (SELECT ClienteID FROM Pedidos
WHERE DataPedido BETWEEN #1/04/95# AND #1/07/95#);

Esse exemplo lista os funcionários cujo salário seja maior que a média dos salários de todos os
funcionários.

SELECT Sobrenome, Nome, Título, Salário FROM Funcionários T1


WHERE Salário >= (SELECT AVG(Salário) FROM Funcionários
WHERE Funcionários.Título = T1.Título) ORDER BY Título;

Esse exemplo seleciona o nome de todos os funcionários que tenham registrado pelo menos um pedido.
Isto também poderia ser feito com INNER JOIN.
SELECT Nome, Sobrenome FROM Funcionários AS E
WHERE EXISTS (SELECT * FROM Pedidos AS O
WHERE O.FuncionárioID = E.FuncionárioID);

Altera o campo Efetuado do arquivo de serviços para 2 caso o mesmo tenha parecer técnico da entidade
encaminhanhamento diferente de nulo.
UPDATE servico SET efetuado = 2
WHERE numero_servico = ANY (SELECT servico.numero_servico
FROM servico INNER JOIN encaminhamento
ON (servico.numero_servico = encaminhamento. numero_servico)
AND (servico. ano_servico = encaminhamento.ano_servico)
WHERE (((servico.efetuado) Is Null) AND ((encaminhamento.parecer_tecnico) Is Not Null))
GROUP BY servico.numero_servico ORDER BY servico.numero_servico);

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página Nr. 34/178
Conecção Delphi com o MS-Access
Autor: Fernando Antonio Fernandes Anselmo
E-Mail: fernandoanselmo@yahoo.com.br

Pré-Requisitos:

Windows 98
Delphi 4.0 versão Client/Server Suite
BDE 5.00
MS-Access 97

Prefácio
Antes de começarmos o nosso curso precisamos configurar o acesso ao banco de dados que será utilizado,
MS-Access.

Porque trabalhar com o Access ? Bem, poderia explicar que porque ele é o banco de dados mais fácil de se
trabalhar tanto para nós (programadores) quanto para o usuário, ou então que muitos de nós o temos, ou ainda pode-se
dizer que ele é um padrão mundial, mas fico com a explicação de que entre todos os bancos de dados de pequeno porte
(Inclui aí, MS-Access, Paradox, dBase, entre outros) ele é o que melhor se comporta para o desenvolvimento inicial de
qualquer projeto suportando as alterações feitas constantemente na base, perda e recuperação dos índices, e por aí vai.

Existe algum problema em se migrar um sistema desenvolvido no Access para outro banco de dados, por
exemplo ORACLE ? Não existe "quase" nenhum problema na migração de sistemas com o Delphi, normalmente não é
preciso mudar uma única linha de programação para se utilizar o mesmo sistema em bancos de dados completamente
diferente (desde óbvio siga-se alguns passos básico). O único problema que existe numa migração é quanto aos
comandos SQL (Structure Query Language), pois infelizmente o Access possui um SQL próprio não comum aos outros
bancos de dados. Mas todos os problemas são facilmente resolvidos criando-se variáveis globais para definir qual tipo
de banco estamos lidando, qual o nome correto da tabela e assim sucessivamente.

A ferramenta Delphi 4.0 possui uma conexão direta com o Banco de Dados MS-Access 97, para tanto faz-se
necessário de:

1. BDE (Borland DataBase Engine) para a versão 5.00


2. Biblioteca de acesso DAO 3.5 (IDDA3532.DLL) colocada no diretório do BDE - C:\Arquivos de
Programas\Borland\Common Files\BDE

A conexão do Delphi com o MS-Access funciona da seguinte maneira BDE - DAO - Banco Access, então na
verdade é preciso instalar o DAO (Data Access Objects), a Microsoft para as versões MS-Access posteriores a 2.0
(que o acesso era feito com o JET) prendeu o instalador do DAO com os aplicativos de desenvolvimento dela tais
como: Visual Basic, MS-J++, MS-C++ e assim vai, então para ter a "correta" licença de distribuição do DAO você
precisa adquirir qualquer um desses aplicativos.

O DAO se faz necessário pois precisamos levar o sistema para o nosso cliente, e do mesmo modo que você
precisa instalar o sistema em Delphi, o MDB, o BDE client, você também precisará instalar o link de conexão. Você
poderá acertar o Install Shield (conforme a apostila 4) para instalar todas as bibliotecas de acesso do DAO mas é
necessário tê-las.

☞Importante - o BDE 5.00 pode operar tanto com o DAO 3.0 quanto com o 3.5.Para definir qual será utilizado,
voce precisa informar no BDE Administrator qual a DLL que sera' utilizada para o driver MSACCESS. A biblioteca
DAO 3.0 é a IDDAO32.DLL e a Biblioteca DAO 3.5 é IDDA3532.DLL (Que será a que utilizaremos)

Mas antes de se criar qualquer alias de conexão, entre no BDE Administrator e proceda a seguinte troca na
página Configuration, conforme a figura:

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página Nr. 35/178
Prontinho basta agora sair e entrar novamente do BDE Administrator e criamos nossos Aliases de conexão.

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página 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 versão Client/Server Suite
BDE 5.00
MS-Access 97

Arquivos trabalhados juntos com esta apostila:

PASCOA2G.BMP

Prefácio
Salve, para você que está começando e participando deste curso, primeiramente gostaria de avisar que o curso
é totalmente prático, com exercícios e truques que lhe ajudarão a senão dominar pelo menos a desvendar os mistérios
desse maravilhoso ambiente. Deixa eu dar um conselho que eu aprendi a duras penas, tente sempre que acontecer
algum erro, mostrá-lo para um colega que conheça também Delphi. Uma vez fiquei quase dois dias com um erro me
incomodando, imprimi, revi linha a linha até que finalmente pedi para que um amigo do lado olhasse meu programa em
menos de 1 segundo ele descobriu o erro, era um simples comando IF que tinha construído errado. Existe uma frase
para o Delphi que sempre utilizo quando começo meus cursos é assim:

Tudo o que parece difícil na verdade é fácil


Tudo o que parece fácil na verdade é muito mais fácil.

Isso sempre funcionou com o Delphi. Um abraço e bom trabalho.

Solicito que quando você encontrar a seguinte simbologia ☞ Importante pare e leia com a maior atenção,
pois ali você encontrará uma dica valiosa que poderá lhe ajudar a esclarecer várias dúvidas.

O Delphi é um ambiente de Desenvolvimento totalmente Baseado na Orientação a Objetos, não é puro


(discutiremos isso no apêndice referente a Orientação a Objetos) mas por enquanto você precisa apenas saber que ele
é uma ferramenta com um incrível poder na construção tanto de softwares complexos, quanto de sistemas de
manipulação a bancos de dados.

Para o nosso primeiro contato com a ferramenta, selecionei algo prático, fácil, útil e até mesmo bonitinho, um
cartão eletrônico, você poderá mandar para seus amigos um simples executável com uma mensagem, vou criar aqui um
para a Páscoa mas é possível aproveitar a idéia para outros eventos também tais como Natal, Aniversários, nascimentos
e assim vai. Vamos começar então:

Conhecendo o Ambiente
Abra o Delphi, bem aí está seu ambiente de trabalho, vamos a uma rápida explicação, o Delphi é composto por
quatro ambientes de trabalho:

1. Parte superior composta pelo Menu, Component Pallete e Botões de Acesso Rápido (Speed
Button): é exatamente o conjunto que está suspenso na área aberta, o Menu (localizado no topo) dá acesso as
opções, a Component Pallete (localizado na parte superior direita) contém todos os objetos (divididos em classes)
que você utilizará para realizar seus projetos, e os Botões de Acesso Rápido (localizado na parte superior esquerda)
que são uma abreviação dos comandos do menu.

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página Nr. 37/178
Uma novidade do Delphi 4.0 é que todos eles estão colocados em janelas auto-arrastáveis, então é possível
modificar as possições entre eles ou criar janelas suspensas basta para isso que você clique no canto (dessas partes
duplas) segure e arraste.

2. Object Inspector: é uma janelinha lateral (chamada como a tecla F11) que contém as propriedades e os eventos
dos objetos selecionados.

3. Form: este objeto será sua prancheta de trabalho é nessa janela em branco (seria melhor dizer em cinza) que
criaremos nossa comunicação entre o sistema e os nossos usuários.

4. Code Editor: é a área localizada atrás do "Form", ela foi dividida em dois ambientes, uma parte que funcionará
como índice, nos mostrandos os objetos existentes, as bibliotecas utilizadas e as variáveis ou constantes disponíveis,
elém dos procedimentos e funções criadas e uma outra que conterá nossas o código propriamente dito (em linguagem
Object Pascal), diferentemente das outras linguagens visuais, no Delphi você tem a capacidade de visualizar todo o
código do seu formulário e não apenas uma determinada parte.

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página Nr. 38/178
Projeto 1 - Cartão Eletrônico
Bem, agora que estamos familiarizados com o ambiente, vamos começar como uma receita de bolo, siga um
passo atrás do outro, mas antes de começar, crie uma pasta que abrigará seu projeto, para padronizar vamos criar uma
pasta com o nome CursoDelphi e dentro dela criaremos uma nova pasta chamada Cartão, e coloque nela o .BMP
enviado:

1. Na Component Pallete localize uma página chamada Additional e dentro dessa página de um clique no objeto
Image (acredito que seja o sexto) e dê um clique no Form. (automaticamente o Delphi criou um quadrado quadriculado
que representa o objeto Image1).

2. Olhe na Object Inspector e verifique as propriedades do objeto Image1 criado, e altere as seguintes propriedades:

2.1. AutoSize: True (Fará com que o tamanho do objeto fique automaticamente do tamanho da figura
selecionada)
2.2. Picture: Clique nos "..." (ou dê um duplo clique em cima do objeto criado) e localize o arquivo .BMP
enviado (Seleciona determinada figura)

3. Vá na Object Inspector e localize o objeto Form1 (basta clicar no Combo Box para seleciona-lo), e altere as
seguintes propriedades:

3.1. BorderStyle: bsDialog (Fará com que a janela fique no formato padrão de uma janela de mensagens)
3.2. Caption: Feliz Páscoa (Conteúdo da tarja do formulário)
3.3. Color: clBlack (Cor do formulário para preto)
3.4. Font: Clique nos "..." e faça as seguintes alteções na janela de Fonts:
3.41. Cor: Branco
3.42. Tamanho: 10
3.4. Name: F_Cartao (Nome interno do formulário)
3.5. Position: poScreenCenter (Fará com que o formulário fique sempre centralizado quando for executado)

☞ Importante - Após alterarmos a Cor (propriedade Color) e a Fonte (propriedade Font) todos os outros objetos
criados em cima deste Form, automaticamente herdarão essas alterações.

4. Dê uma salvadinha no seu projeto, para tanto, no menu vá em File | Save All...:

4.1. Aonde aparece Unit1.pas (o Delphi está se referindo do nome do formulário) mude para fCartao.PAS
4.2.Aonde aparece Project1.dpr (o Delphi está se referindo do nome do projeto - que será o nome do
executável final) mude para Cartao.DPR

5. Na Component Pallete localize uma página chamada Standard e dentro dessa página localize o objeto Label
(acredito que seja o terceiro) pressione a tecla SHIFT e clique no objeto (deve ter ficado um quadriculado azul em
volta do objeto, como se ficasse marcado) e dê oito cliques no Form - um abaixo do outro e na área preta.
(automaticamente o Delphi criou oito objetos chamados respectivamente Label1, Label2, Label3, Label4, Label5,
Label6, Label7 e Label8)

6. Quando terminar clique dentro da Component Pallete na setinha para poder desmarcar o objeto Label.

7. Dê uma comparadinha no desenho para ver como está ficando:

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página Nr. 39/178
Bom, todos os objetos que serão visíveis já estão aí, agora vamos criar dois objetos que servirão apenas como
meros auxiliares:

7. Na Component Pallete na mesma página Standard clique no objeto Memo (acredito que seja o quinto) e dê um
clique no Form (automaticamente o Delphi criou um quadrado que representa o objeto Memo1).

8. Olhe na Object Inspector e verifique as propriedades do objeto Memo1 criado, e altere as seguintes propriedades:

8.1. Font: Clique nos "..." e faça as seguintes alteções na janela de Fonts:
8.11. Cor: Preto
8.12. Tamanho: 8
8.2. Lines: Clique nos "..." e copie o seguinte texto:

Recebe, Oh Senhor,
em sua gloria eterna
e envolve com paz e amor
este sacrifício em incenso,
que sobe clamando por justiça
por todos os meninos assassinados
pelos pobres que morrem de fome
pelas mulheres violentadas
pelo povo roubado e explorado.

E perdoa, Oh Senhor,
perdoa o Brasil,
seu presidente estratosférico,
seus deputados escondidos,
seus senadores omissos,
sua igreja distraída,
seus militares fantoches,
sua polícia ausente,
perdoa nós todos, Senhor,
perdoa a mim e a meu irmão
que nada fizemos,
que não agimos,
e que não vimos
a imagem de seu filho
Cristo na Cruz.

Ou digite um outro texto que mais lhe agradar, mas anote o número de linhas (neste aqui temos 25 linhas)

8.3. Visible: False (Não mostrará o objeto em tempo de execução)

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página Nr. 40/178
9. Na Component Pallete na página System clique no objeto Timer (acredito que seja o primeiro) e dê um clique no
Form (automaticamente o Delphi criou um quadradinho com um relógio, que por sinal é uma cópia do desenho do
objeto). A propriedade Interval controla a velocidade do objeto.

Codificando
Tudo pronto, agora é só meter a mão no programa, mas vamos devagar, a idéia do cartão, se você ainda não
entendeu, é que ao ser executado a mensagem que está guardada dentro do objeto Memo1 rolará entre os oito labels
(como se tivesse subindo) para isso foi criado um Temporizador (Objeto Timer1), que é ativado a cada segundo
(através da propriedade Interval, medida em milésimos de segundo) que simulará o movimento entre os labels. Então
vamos começar a brincadeira:

10. Pressione a tecla F12, até você ter acesso a Code Editor, sugiro que você maximize a área para trabalhar melhor,
localize as seguintes linhas:

private
{ Private declarations }
public
{ Public declarations }
end;

e altere para o seguinte:

private
NumLinha: Integer;
public
{ Public declarations }
end;
Você acaba de criar uma variável particular (Private) do tipo inteira (Integer) que servirá apenas a este
formulário, sendo criada e destruída junto com ele.

11. Localize na Object Inspector o objeto F_Cartao, mude para a página de eventos (Events) e localize o evento
OnShow, dê um duplo clique na área em branco. Automaticamente o Delphi criará para você a chamada ao evento e o
transferirá para a Code Editor, insira o seguinte código:

procedure TF_Cartao.FormShow(Sender: TObject);


var
i : Integer;
begin
for i := ComponentCount - 1 downto 0 do
if (Components[I] is TLabel) then
(Components[I] as TLabel).Caption := '';
NumLinha := 0;
end;
Neste evento que é disparado assim que o formulário se inicia, limparemos os oito Labels para isso
simplesmente utilizaremos uma string vazia, use aspas simples (nunca duplas) e sem espaços entre elas, para chamar os
oito labels utilizaremos a variável ComponentCount para contar quantos componentes tem o formulário, verificamos
quais deles são label's e estes limparemos e iniciarmos a nossa variável NumLinha com 0.

☞Importante - Muitos dos procedimentos que o Delphi cria automaticamente (através dos eventos) requisitam a
passagem de um objeto do tipo TObject (Sender: TObject), isso faz você saber quem foi que ativou tal evento, se foi
por ação de um mouse ou de um clique num botão, e assim vai.

Aqui foi preciso rastrear todos os componentes do formulário através do comando Components[n], aonde n é
o número de cada componente. Isto é iniciado do 0 (assim como todo Array no Delphi começa do 0, ex: Lines,
Items...), então é preciso criar um FOR que vai do 0 até o (número total de componente-1) porque o primeiro é o 0 isto
explicasse imaginando uma lista de 10 números começados pelo 0, vc terá 0,1,2,3,4,5,6,7,8,9 então o último número
será o número total da sua lista - 1.

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página Nr. 41/178
☞Importante - Claro que ao invés de usarmos:
for i := ComponentCount - 1 downto 0 do
if (Components[I] is TLabel) then
(Components[I] as TLabel).Caption := '';

poderiamos muito bem utilizar:

Label1.Caption := '';
Label2.Caption := '';
Label3.Caption := '';
Label4.Caption := '';
Label5.Caption := '';
Label6.Caption := '';
Label7.Caption := '';
Label8.Caption := '';

Mas isso além de ficar um tantinho mais inchado, fica muito deselegante, é verdade que estamos tratando
apenas com 8 objetos label's mas e se amanhã utilizamos 20 ou 30 ?? Além do que isso pode-se dizer que é o primeiro
passo para um recurso de MacroSubstituição, como foi utilizado com o TLabel, pode também ser utilizado para o
TEdit, TEditMask , TDBText ou qualquer outro que você deseje.

12. Localize na Object Inspector o objeto Timer1, mude para a página de eventos (Events) e localize o evento
OnTimer, dê um duplo clique na área em branco. Automaticamente o Delphi criará para você a chamada ao evento e o
transferirá para a Code Editor, entre os intervalos begin e end escreva:

procedure TF_Cartao.Timer1Timer(Sender: TObject);

function Monta : String;


begin
result := Memo1.Lines[NumLinha];
inc(NumLinha);
if NumLinha > 30 then NumLinha := 0;
end;

begin
NumLinha := NumLinha - 7;
Label1.Caption := Monta;
Label2.Caption := Monta;
Label3.Caption := Monta;
Label4.Caption := Monta;
Label5.Caption := Monta;
Label6.Caption := Monta;
Label7.Caption := Monta;
Label8.Caption := Monta;
end;

Neste evento é que está toda a jogada do programa, note que dentro da procedure colocamos uma função
interna Monta que nos retornará o conteúdo de uma determinada linha do objeto Memo1, note que trabalhamos com 8
label's, então:

☞Importante - Note que existe uma variável chamada Result ela é uma variável definida pela própria função (no
caso tipo String), poderíamos aqui usar dois nomes ou Monta ou a palavra chave Result, ambos os nomes apontam
para a mesma variável que tem como função fazer a devolução da String definida pela função (para maiores referências
veja a apostila Programação Orientada a Objetos)

no primeiro segundo que passar:


Label1 até Label7 = Branco e o Label8 com o conteúdo da primeira linha do objeto Memo1.

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página Nr. 42/178
No próximo segundo que passar:
Label1 até Label6 = Branco, Label7 com o conteúdo da primeira linha do objeto Memo1 e o Label8 com o conteúdo da
segunda linha do objeto Memo1.

No próximo segundo que passar:


Label1 até Label5 = Branco, Label6 com o conteúdo da primeira linha do objeto Memo1 e o Label7 com o conteúdo da
segunda linha do objeto Memo1 e Label8 com o conteúdo da terceira linha do objeto Memo1

E assim vai aumentando segundo após segundo, até um total de 30 segundos, note aqui que são 25 linhas,
aumentei mais 5 para ter um intervalo entre a última linha e o começo de uma nova montagem quando a variável monta
linha é novamente reiniciada a zero.

Note que para adicionar 1 a variável NumLinha utilizo a função interna INC, esta função também pode ser:
Inc(variável, [quanto]) aonde "quanto" representa o número que você quer adicionar a variável, se não for enviado será
por default 1. Isto seria o correspondente: variável := variável + quanto; e só de curiosidade o contrário da função INC
é a função DEC.

☞Importante - os brancos são conseguidos pesquisando valores negativos dentro da propriedade Lines do objeto
Memo1. Note que eu faço [NumLin := NumLin - 7] como resultado disto teremos primeiramente o valor -7, depois -6,
e assim vai até chegar a 0 no primeiro segundo.

☞Importante - aqui não adianta tentar usar o recurso da ComponentCount pois pode avacalhar na hora da
montagem, então é preferível fazer o lote da montagem dos oito label's na mão mesmo.

Enviando o projeto para um Amigo


Prontinho agora basta apenas você compilar o projeto, vá ao menu nas opções Project | Compile... (ou
pressione CTRL+F9 e prontinho é só mandar o executável gerado para sua(seu) namorada(o), parente, colega ou
amigo(a), acredito que deva caber num único disquete (Atenção: Não precisa mandar o .BMP o Delphi já se encarrega
de guardá-lo no executável).

Realizando uma pequena otimização


Anote antes desses passos qual foi o tamanho em Bytes que ficou o seu executável.

1. Uma coisa que você pode (e deve fazer) é ir em Project | Options... na página Application atribua um título (Title)
e um novo ícone (Icon) ao seu projeto, depois vá na página Compiler e desmarque todas as opções do Grupo
Debugging (elas só servem para quando você estiver testando o aplicativo).

2. No início do programa do seu formulário deixe apenas as seguintes bibliotecas:

unit fCartao;

interface

uses
Windows, Classes, Controls, ExtCtrls, StdCtrls, Forms;

3. Dê uma compilada final escolhendo as opções Project | Build All

Compare agora o tamanho do seu executável final. Mas não se preocupe esses macetes você aprenderá ao
longo do nosso curso. (Atenção: também não precisa mandar o Ícone que você escolheu para seu projeto o Delphi
também se encarrega de colocá-lo no executável).

Finalmente
Na próxima apostila começaremos a desvendar os segredos dos bancos de dados.

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página 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 versão Client/Server Suite
BDE 5.00
MS-Access 97

Arquivos trabalhados juntos com esta apostila:

BRASIL.BMP
NORTE.BMP
NORDESTE.BMP
SUL.BMP
SULDESTE.BMP
CENTRO.BMP

Prefácio
Salve, após a construção de um Cartão você pode estar pensando o que virá a seguir ? Acertou se pensou no
acesso a Banco de Dados, afinal o maior mistério com o Delphi é como ele trata Bancos de Dados. Uma das grandes
vantagens do Delphi é o seu relacionamento com os diversos bancos de dados atualmente existentes, e o Delphi é um
dos poucos ambientes que consegue fazer essa conexão de forma rápida e prática.

Mas antes de nos enveredarmos no conceito de Banco de Dados vamos criar a nossa capa do aplicativo,
garanto que você achará bastante interessante o que estamos prestes a começar a desenvolver.

Vamos a uma rápida explicação o que é este projeto. Inicialmente será mostrado o mapa do Brasil para que o
usuário possa escolher determinada região, após a escolha de uma região o usuário poderá dentro desta escolher qual o
estado ele deseja ter uma pequena descrição, eu vou alargar um pouco e dar também a possibilidade de impressão da
região escolhida.

Projeto 2 - Mapa Eletrônico (1a. Parte)


Bem, agora vamos começar nosso projeto (note que eu sempre falo a palavra Projeto ao invés de Sistema, em
Orientação a Objetos não existem Sistemas e sim Projetos então acostume-se com isso) agora que já ficamos
familiarizados com o Delphi este projeto será um pouco diferente criarei apenas uma parte dele caberá a você a
conclusão do resto do projeto, Ok ? Então vamos meter a mão na massa:

1. Abra o Delphi, como se isso já não fosse óbvio.

2. Na Component Pallete localize uma página chamada Additional e dentro dessa página de um clique no objeto
Image (acredito que seja o sexto) e dê um clique no Form. (automaticamente o Delphi criou um quadrado quadriculado
que representa o objeto Image1).

3. Olhe na Object Inspector e verifique as propriedades do objeto Image1 criado, e altere as seguintes propriedades:

3.1. AutoSize: True (Fará com que o tamanho do objeto fique automaticamente do tamanho da figura
selecionada)
3.2. Picture: Clique nos "..." e localize o arquivo BRASIL.BMP enviado (Seleciona determinada figura)

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página 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 padrão de uma janela de mensagens)
4.2. Caption: Mapa Eletrônico (Conteúdo da tarja do formulário)
4.3. Name: F_Mapa (Nome interno do formulário)
4.4. Position: poScreenCenter (Fará com que o formulário fique sempre centralizado quando for executado)

5. Dê uma salvadinha no seu projeto, para tanto, no menu vá em File | Save All...:

5.1. Aonde aparece Unit1.pas (o Delphi está se referindo do nome do formulário) mude para fMapa.PAS
5.2. Aonde aparece Project1.dpr (o Delphi está se referindo do nome do projeto - que será o nome do
executável final) mude para Mapa.DPR

6. Na Component Pallete localize uma página chamada Standard e dentro dessa página localize o objeto Label
(acredito que seja o terceiro) clique no objeto e dê um clique no Form e altere as seguintes propriedades:
6.1. Font: Clique nos "..." e faça as seguintes alteções na janela de Fonts:
6.11. Cor: Castanho
6.12. Estilo: Negrito
6.2. Caption: Clique sobre a Região a consultar (Conteúdo que será mostrado)

7. Na Component Pallete localize uma página chamada Additional e dentro dessa página localize o objeto Image
(acredito que seja o sexto) pressione a tecla SHIFT e clique no objeto (deve ter ficado um quadriculado azul em volta
do objeto, como se ficasse marcado) e dê cinco cliques no Form - de preferência um em cada região, e altere as
propriedades Name e Hint de cada um para, respectivamente:

Name - Hint
ImgNorte - Mostra os estados da Região Norte
ImgNordeste - Mostra os estados da Região Nordeste
ImgCentro - Mostra os estados da Região Centro-Oeste
ImgSudeste - Mostra os estados da Região Sudeste
ImgSul - Mostra os estados da Região Sul

☞ Importante - A próxima modificação tem a ver com Orientação a Objetos o termo é POLIMORFISMO, isso
significa que vários objetos (mesmo diferentes) possuem propriedades idênticas entre si, por exemplo a propriedade
Caption de um objeto Form possui (basicamente) a mesma função da propriedade Caption de um objeto Label.

8. Clique no objeto ImgNorte segure a tecla SHIFT e clique em ImgNordeste, ImgCentro, ImgSudeste e ImgSul (o
que eu queria era que todos os cinco objetos ficassem marcados simultaneamente), altere agora a propriedade
ShowHint para True. (Note que na Object Inspector não aparece o nome do objeto) e a propriedade Cursor para
crHandPoint (isso fará com que o cursor em cima da figura seja alterado para uma mãozinha apontando).

☞Importante - Isso pode ser usado para alterar diversas propriedades de objetos diferentes, praticaremos isso
posteriormente.

9. Quando terminar clique em qualquer região do formulário para desmarcar os objetos.

10. Para terminar nosso primeiro formulário desse projeto vá para a Component Pallete localize uma página chamada
Additional e dentro dessa página localize o objeto BitBtn (acredito que seja o primeiro) clique no objeto e dê um
clique no Form e altere as seguintes propriedades:
10.1. Kind: bkClose, isso fez com que três importantes propriedades se alterassem:
10.11. Caption: assumiu o valor &Close.
10.12. Glyph: ganhou uma imagem padrão de uma portinha de saída
10.13. Modal Result: apesar de não ter sofrido alteração internamente foi disparado uma Flag que fará
com que quando este botão seja clicado o formulário se encerre automaticamente.
10.2.Caption: &Fechar (apenas para "aportuguesar"o nosso aplicativo).

11. Dê uma comparadinha no desenho para ver como ficou:

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página Nr. 45/178
Bom, este será o nosso primeiro formulário, de uma série de sete, sua função é simples, ele mostrará o mapa
do Brasil e ao ser clicar em qualquer parte de uma determinada região ele disparará o mapa respectivo desta.

Codificando o mapa
A codificação é um tanto simples, mas pretendo aqui ensinar também alguns macetes interessantes, aperte a
tecla F12 até que você tenha a janela da Code Editor aberta e localize para mim as seguintes linhas:

ImgSul: TImage;
ImgSudeste: TImage;
private

Inclua a seguinte chamada a um procedimento antes da parte private:

ImgSul: TImage;
ImgSudeste: TImage;
procedure ChamaRegiao(Sender: TObject);
private

Agora localize a linha:

implementation

{$R *.DFM}

end.

E faça as seguintes alterações

implementation

{$R *.DFM}
uses
fNorte, // Chama o mapa da Região Norte
fNordeste, // Chama o mapa da Região Nordeste
fSul, // Chama o mapa da Região Sul

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página Nr. 46/178
fSudeste, // Chama o mapa da Região Sudeste
fCentro; // Chama o mapa da Região Centro-Oeste

procedure TF_Mapa.ChamaRegiao(Sender: TObject);

// Chama os outros Formulários


procedure CriaForm(aFormClass: TFormClass);
begin
with aFormClass.Create(Application) do
try
ShowModal;
finally
Free;
end;
end;

begin
if (Sender = ImgNorte) then CriaForm(TF_Norte) else
if (Sender = ImgCentro) then CriaForm(TF_Centro) else
if (Sender = ImgNordeste) then CriaForm(TF_Nordeste) else
if (Sender = ImgSul) then CriaForm(TF_Sul) else
if (Sender = ImgSudeste) then CriaForm(TF_Sudeste);
end;

end.

Antes de explicar esse procedimento deixa eu comentar porque criei uma nova declaração USES (note que na
terceira linha da Unit - lá em cima) já tem um comando assim, este comando serve para identificar minhas unidades
externas, antes da palavra chave IMPLEMENTATION assim que o formulário é gerado tudo é compilado e
salvaguardado em áreas de memória prontos para serem utilizados, ou seja, a Unit Windows (se você reparar ela está lá
em cima) e jogada para uma área de memória, mas em compensação a Unit fNorte (que criaremos posteriormente) não
é armazenada. Assim eu estou preservando vários blocos de memória para serem utilizados apenas quando realmente
forem necessários.

Prontinho agora vamos explicar essa procedure linda e maravilhosa que foi montada de propósito para você
entenda algumas artimanhas da linguagem Pascal, antes de fazê-la poderiamos simplesmente em cada objeto TImage
clicarmos no evento OnClick e para cada um colocarmos o seguinte código: (por exemplo para o objeto da Região
Norte)

begin
F_Norte := TF_Norte.Create(Application);
F_Norte.ShowModal;
F_Norte.Free;
end;

Isso funcionaria perfeitamente bem mas como são cinco objetos precisariamos repetir isso cinco vezes
(imagine se fossem uns 20 ou 30), e isso já não é tão bom assim em Pascal. Outra coisa que poderiamos fazer é,
criamos um procedimento particular (lá no Private) para todas os outros procedimentos então ficaria assim:

private
procedure CriaForm(aFormClass: TFormClass);
public
.
.
.
// Depois do comando uses

procedure TF_Mapa.CriaForm(aFormClass: TFormClass);


begin
with aFormClass.Create(Application) do
try

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página Nr. 47/178
ShowModal;
finally
Free;
end;
end;

e em cada objeto TImage clicarmos no evento OnClick e para cada um colocarmos o seguinte código: (por exemplo
para o objeto da Região Norte)

begin
CriaForm(TF_Norte);
end;

Isso também funcionaria perfeitamente bem mas como são cinco objetos precisariamos repetir isso cinco vezes
(imagine novamente se fossem uns 20 ou 30), mas agora o pior que e serão vários procedimentos que teremos que olhar
caso dê algum erro e isso já não é tão bom assim em Pascal. Então resolvi fazer da maneira como eu coloquei.

Criei um único procedimento ChamaRegiao que receberá uma variável do tipo TObject (lembra da apostila
anterior ? É o objeto que chama o procedimento) e para este procedimento coloquei um outro procedimento interno,
chamado CriaForm.

Para ativar todo o conjunto aperte novamente a tecla F12 (para mostrar o formulário) e dê um clique simples
sobre o objeto ImgNorte aperte a tecla F11 (para chamar a Object Inspector), vá para a página de eventos e para o
evento OnClick, selecione atraves do Combo (aquela setinha apontada para baixo) o procedimento ChamaRegiao.
Repita os mesmos passos com as outras imagens das outras regiões.

Este formulário já está pronto, vamos agora ver o que acontece com cada região. (Obs. Não adianta tentar
rodar que ele deve acusar erro que as outras unidades ainda não existem.

Primeira Região
Apenas para guiá-los mostrarei como criar o mapa da Região Sul (só tem três estados e não deve me dar muito
trabalho :)) você deverá criar os formulários para as outras regiões. Observe que é quase tudo igual ao primeiro
formulário criado.

A partir do Menu Principal clique em File | New Form e será disponibilizado um novo formulário, vamos aos
passos:

12. Na Component Pallete localize uma página chamada Additional e dentro dessa página de um clique no objeto
Image (acredito que seja o sexto) e dê um clique no Form. (automaticamente o Delphi criou um quadrado quadriculado
que representa o objeto Image1).

13. Olhe na Object Inspector e verifique as propriedades do objeto Image1 criado, e altere as seguintes propriedades:

13.1. AutoSize: True (Fará com que o tamanho do objeto fique automaticamente do tamanho da figura
selecionada)
13.2. Picture: Clique nos "..." e localize o arquivo SUL.BMP enviado (Seleciona determinada figura)

14. Vá na Object Inspector e localize o objeto Form1 (basta clicar no Combo Box para selecioná-lo), e altere as
seguintes propriedades:

14.1. BorderStyle: bsDialog (Fará com que a janela fique no formato padrão de uma janela de mensagens)
14.2. Caption: Estados da Região Sul (Conteúdo da tarja do formulário)
14.3. Name: F_Sul (Nome interno do formulário)
14.4. Position: poScreenCenter (Fará com que o formulário fique sempre centralizado quando for executado)

15. Dê uma salvadinha no seu projeto, para tanto, no menu vá em File | Save All...:

15.1. Aonde aparece Unit1.pas (o Delphi está se referindo do nome do formulário) mude para fSul.PAS

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página Nr. 48/178
16. Na Component Pallete localize uma página chamada Standard e dentro dessa página localize o objeto Label
(acredito que seja o terceiro) clique no objeto e dê um clique no Form e altere as seguintes propriedades:
16.1. Font: Clique nos "..." e faça as seguintes alteções na janela de Fonts:
6.11. Cor: Castanho
6.12. Estilo: Negrito
16.2. Caption: Clique sobre o Estado a consultar (Conteúdo que será mostrado)

17. Na Component Pallete localize uma página chamada Additional e dentro dessa página localize o objeto Image
(acredito que seja o sexto) pressione a tecla SHIFT e clique no objeto (deve ter ficado um quadriculado azul em volta
do objeto, como se ficasse marcado) e dê cinco cliques no Form - de preferência um em cada região, e altere as
propriedades Name e Hint de cada um para, respectivamente:

Name - Hint
ImgPR - Descreve o estado do Paraná
ImgSC - Descreve o estado de Santa Catarina
ImgRS - Descreve o estado do Rio Grande do Sul

18. (Praticando o polimorfismo novamente) Clique no objeto ImgPR segure a tecla SHIFT e clique em ImgSC e
ImgRS, altere agora a propriedade ShowHint para True e Cursor para crHandPoint.

19. Quando terminar clique em qualquer região do formulário para desmarcar os objetos.

20. Para terminar nosso primeiro formulário desse projeto vá para a Component Pallete localize uma página chamada
Additional e dentro dessa página localize o objeto BitBtn (acredito que seja o primeiro) clique no objeto e dê um
clique no Form e altere as seguintes propriedades:
20.1. Kind: bkClose, isso fez com que três importantes propriedades se alterassem:
20.2. Caption: &Fechar (apenas para "aportuguesar"o nosso aplicativo).

21. Dê uma comparadinha no desenho para ver como ficou:

Agora cabe a você criar mais quatro formulários, são eles respectivamente:

Nome Interno Nome Externo Figura a usar


F_Norte fNorte NORTE.BMP
F_Nordeste fNordeste NORDESTE.BMP
F_Centro fCentro CENTRO.BMP
F_Sudeste fSudeste SUDESTE.BMP

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página Nr. 49/178
☞Importante - Chamei de Nome Interno a propriedade Name dos formulários e Nome Externo como será o nome
que você deve salvar cada formulário. Note que a única diferença entre eles está num simples apostrofe "_", isso facilita
muito quando queremos lembrar o nome que precisamos utilizar.

☞ Importante - Infelizmente com o Delphi não existe outro componente mais poligonal que o tImage, mas tem uma
notícia boa o Delphi respeitará o objeto tImage criado por último, então você pode colocar uns sobre os outros.
Comigo aqui acabei conseguindo montar com uma exatidão fora do normal, até eu me assustei. Uma Dica: Para a
região Centro-Oeste crie primeiro o Objeto do estado de Goiás e dentro dele coloque o objeto do estado do Distrito
Federal.

Tirando os formulários do Auto-Create


O Delphi cria automaticamente todos os formulários que utilizamos, mas isso gera um tanto de prejuízo as
áreas de memória (é óbvio que um projeto com 7 ou até 10 não é um caso sério, mas um projeto com 50 ou 70 já
começa a dar uns erros muito estranhos) então lembra-se do procedimento CriaForm ele vai exatamente criar os nosso
formulários para utilizarmos e depois destruí-los.

Mas precisamos dizer para o Delphi que não queremos que ele faça o serviço de Auto-Create, para tanto vá (a
partir do menu principal) em View | Project Manager, esta janelinha é a que controla todas as unidades do seu projeto.
Clique no botão Options. Selecione a página Forms lá você verá dois objetos ListBox, do lado esquerdo são os Auto-
Create Forms e do lado direito estão os Available forms ou simplesmente formulários disponíveis.

Então selecione os formulários: F_Norte, F_Nordeste, F_Centro, F_Sudeste e F_Sul e clique no botão com o
sinal > isso fará com que eles sejam despachados para o outro lado. Não faça o procedimento com o F_Mapa, ele é o
nosso Menu e ele precisa realmente ser criado automaticamente assim que o usuário iniciar o processo.

Prontinho, agora execute o projeto e veja como ele está ficando.

Finalmente
Existem várias maneiras de se mostrar o estado escolhido mas a que eu achei mais interessante utiliza o
QuickReport (que vem com o Delphi) para fazer o serviço. Mas faremos isto apenas na próxima apostila.

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página 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 versão Client/Server Suite
BDE 5.00
MS-Access 97

Arquivos trabalhados juntos com esta apostila:

BASICO.MDB

Prefácio
Salve, na última apostila começamos a montar nosso pequeno mapa eletrônico, agora vamos concluí-lo.

Antes de recomeçarmos precisamos entender como funciona a conexão entre o Delphi e o Banco de Dados.
Isto é realizado através de um conjunto de bibliotecas que a Inprise chamou de BDE (Borland DataBase Engine) ela
trabalha assim como um ODBC de ligação, mas com a grande vantagem que para determinados bancos o acesso é
totalmente nativo, isso significa que a conversa entre sua Aplicação e o Banco não recebe interferencias externas a não
ser do BDE (mas isso até o antigo Clipper precisava de suas ligações para seus acessos com os bancos xBase).

Ilustradamente o acesso funciona da seguinte maneira:

A coisa acontece da seguinte forma, a sua aplicação através dos objetos contidos na Component Pallete
(localizado na parte superior direita) e na página chamada Data Access estão todos os objetos que fazem esta primeira
conexão entre o Aplicativo e o BDE e este se comunica com o Banco de Dados.

☞Importante - Note que eu não especifiquei qual o Banco de Dados, então salvaguardando algumas regras do
próprio banco (tais como o nome das tabelas, formas de SQL) poderemos utilizar para nossa aplicação qualquer banco
que acharmos mais fácil de manipularmos (tais como dBase, Access, Paradox...) e ao final (antes de entregar a
aplicação para o usuário) fazermos um último teste com o banco de dados escolhido por ele (Oracle, SQL Server,
Interbase, Sybase...) para isso não precisaremos modificar uma única linha de código do nosso aplicativo.

☞ Importante - A conexão com o MS-Access funciona da seguinte forma: Entre o BDE e o Banco de Dados existe
um aplicativo a mais de conexão, chamado DAO, a sigla significa Data Access Objects, é um conjunto de bibliotecas
para o desenvolvimento com o banco de dados MS-Access, e pertence a Microsoft, para ter o direito de uso e
distribuição do produto você deve adquirir quaisquer das ferramentas de desenvolvimento da Microsoft.

Iniciando na Prática
Bem se você ainda não fez, aconselho que você dê uma olhada no apêndice identificado por CONEXAO e
faça as alterações sugeridas nele.

Junto com essa apostila você está recebendo um banco de dados (formato MS-Access 97). Para padronizar
vamos criar uma pasta com o nome CursoDelphi e dentro dela criaremos uma nova pasta chamada Federação coloque

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página Nr. 51/178
dentro desta tudo que você recebeu. Graficamente então temos:

Abra agora o aplicativo BDE Administrator e crie um Alias para o banco de dados enviado. Se você não sabe
como fazer vou dar uma canja siga os passos abaixo:

1. A partir do BDE Administrator aberto vá em Object | New... (ou simplesmente CTRL+N) e modifique a janelinha
que aparece para:

e pressione a tecla OK.

2. Mude o nome do seu novo alias para AlFedera

☞ Importante - Apesar de ser permitido não coloque acentos no seu Alias e procure não ultrapassar os oito
caracteres isso além de manter a compatibilidade entre o Delphi 32 Bits e o Delphi 16 Bits também evita uma série de
confusões.

3. Altere a propriedade DATABASE NAME para C:\CursoDelphi\Federação\basico.mdb e confirme as alterações


em Object | Apply (ou simplesmente CTRL+A, ou ainda clique no quarto botão da barra de ferramentas)

4. Teste seu novo alias clicando em Object | Open (ou simplesmente clique no primeiro botão da barra de ferramentas)
seu alias deve formar um quadradinho luminoso em volta do objeto, conforme a figura a seguir:

5. Feche-o em em Object | Close (ou simplesmente clique novamente no primeiro botão da barra de ferramentas)

Se você está confuso com tudo isso não fique retorne aquela figura inicial sobre a conexão, pode-se dizer que
estamos exatamente criando o quadradinho do BDE. O Alias é simplesmente uma conexão que se fará entre seu
Aplicativo e o Banco de Dados

Trabalhando com o TDatabase


Antes de começarmos abra novamente o seu projeto, para isso a partir do Menu Principal clique em File |
Open localize o arquivo Mapa.DPR.

No formulário F_Mapa e coloque um objeto DataBase (que se encontra na Component Pallete na página
Data Access) e altere as seguintes propriedades:

AliasName para AlFedera (aquele que foi criado na apostila anterior)


DataBaseName para dnFedera (nome da base de dados)
Name para nmFedera

Este objeto é o que fará a segunda conexão com o nosso banco de dados, para lembrar a vocês:

1a. Conexão: Entre o Banco de Dados e o Alias


2a. Conexão: Entre o Alias e o objeto tDataBase
3a. Conexão: Entre o objeto tDataBase e os objetos DB (tTable, tQuery, tStoreProc)
4a. Conexão: Entre os objetos DB com os objetos que o usuário utilizará (todos os que estão na página DataControls e
alguns outros).

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página Nr. 52/178
Se você quer simular como será essa segunda conexão, altere a propriedade Connected do objeto para true e
será mostrada a seguinte janela:

Clique no botao Ok e prontinho seu banco estará conectado, mas vamos evitar que essa janelinha apareça
quando o usuário for usar nosso aplicativo, antes volte a propriedade Connected do objeto para false, na página de
eventos de um duplo clique no evento OnLogin e vamos as alterações:

procedure TF_Mapa.nmFederaLogin(Database: TDatabase; LoginParams: TStrings);


begin
LoginParams.Values['USER NAME'] := '';
LoginParams.Values['PASSWORD'] := '';
end;

Agora precisamos simular as alterações de Conexão para tanto, chame o objeto F_Mapa, e dê um duplo clique
no evento OnShow para abrirmos esta conexão:

procedure TF_Mapa.FormShow(Sender: TObject);


begin
nmFedera.Connected := True;
end;

Para fechar a conexão quando terminar nosso sistema. dê um duplo clique no evento OnClose:

procedure TF_Mapa.FormClose(Sender: TObject; var Action: TCloseAction);


begin
nmFedera.Connected := False;
end;

☞Importante - Aqui executaremos mais um termo da Orientação a Objetos (lembram-se do POLIMORFISMO),


o termo é AÇÃO, isso significa que um evento qualquer é disparado quando outro evento é acionado, ou seja é como
um efeito cascata. O que acontece aqui é que quando o usuário executar o sistema esse disparará o evento OnShow do
formulário e este disparará o evento OnLogin do objeto TDataBase.

Sobre o Quick Report


O Quick Report é o gerador oficial do Delphi, deixa eu abrir aqui um pequeno parenteses, quando surgiu o
Delphi, era uma das melhores ferramentas RAD para se trabalhar com bancos de dados, perfeito até hoje na construção
e desenvolvimento de softwares, mas como todo paraíso tem seu inferno, o Delphi também tinha o seu, a geração de
relatórios, na época do Delphi 1.0 a ferramenta para gerá-los era o Report Smith, mas era claro que ele não dava conta
do recado por diversos motivos, entre eles destacam-se:

- Era preciso carregar um Run-Time do Report Smith juntamente com o projeto


- Os relatórios ficavam separados do executável principal
- Relatórios muito complexos eram uma Via-Crucis fazê-los
- Relatórios muito simples demoravam uma eternidade para rodá-los

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página Nr. 53/178
Então os Delphianos da época procuravam alternativas, entre elas aqui vale destacar:

- Report Crystal
- Report Builder
- Biblioteca Printers (do próprio Delphi)

Esta última deu origem a vários geradores de relatórios e o principal surgido foi o Quick Report que se tornou
um mero coadjuvante do Delphi 2.0 fazendo parceria com o Report Smith e em pouco tempo tornou-se óbvio que o
Quick era muito superior ao Smith tanto que a partir da versão 3.0 resolveu-se não mais distribuir o Report Smith
tornando o Quick o gerador oficial do Delphi.

Não pretendo dizer aqui que o Quick é o melhor gerador de relatórios que existe para o Delphi, acredito
sempre que a melhor ferramenta é aquela que você domina e conhece, em listas de discussão é comum você ver coisas
como:

- O Quick é ruim
- É difícil de construir algo nele
- Relatórios complicados são impossíveis fazê-los
- entre milhares de outras coisas

Aí, todos colocam milhares de substitutos, mas veja bem, a própria Inprise abriu mão de um gerador dela
(caso do Report Smith) para trocar por um de uma empresa de terceiro (QuSoft AS). Será que isso tudo foi porque o
Quick é ruim ? Acho que muitas vezes quando não conhecemos ou tentamos aprender uma ferramenta, acabamos não
fazendo o essencial que é ver primeiro como a ferramenta trabalha, o Quick é um gerador de relatórios totalmente
orientado a objetos, e isso não é muito fácil de assimilarmos. Então para ajudá-los sempre tentarei utilizá-lo como uma
ferramenta não só para gerar relatórios, mas também para:

- Formulários de Consultas
- Importações em .TXT e .HTML
- Relatórios Analíticos
- Fichas de Caixa, Balancetes e Outros.

Vocês verão que esse terrível monstro horroroso de duzentas cabeças (que cada dia cresce uma) na verdade
não passa de um horroroso monstro terrível de duzentas e uma cabeças. Bem vamos deixar de ladainha e começar a
trabalhar.

Construindo o formulário para uma região genérica


Não pretendo aqui construir um formulário para cada região (teve gente que suspirou de alívio), mas sim um
único que servirá para qualquer região que o nosso usuário clicar. Vamos aos passos:

1. A partir do Menu Principal clique em File | New Form e será disponibilizado um novo formulário e altere logo a
propriedade name para F_Estado.

2. Dê logo uma salvadinha no seu projeto, para tanto, no menu vá em File | Save All...:

2.1. Aonde aparece Unit1.pas (o Delphi está se referindo do nome do formulário) mude para fEstado.PAS

3. Na Component Pallete ache uma página entitulada QReport nela estão todos os objetos utilizados pelo Quick,
localize o objeto chamado QuickRep, clique nele e em seguida click no formulário.

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página Nr. 54/178
☞Importante - Foi criado nesse momento nossa área de trabalho, o Quick 1.0 (distribuído com o Delphi 2.0) não
criava esta área branca que vc está vendo, ele se resumia a apenas alargar as proporções do formulário (propriedade
Width e Height) para o tamanho de uma página da impressora.

4. Vamos para a Object Inspector e altere a propriedade Name para QrEstado

☞Importante - Qualquer gerador de relatório trabalha por seções, pois nossos (e qualquer) relatórios tem essas
seções, são elas: Cabeçalho, Título da Página, Rodapé da Página, Página Inicial, Última Página, Linhas Detalhes, e
assim vai, vamos criar essas seções, o Quick as chama de Bandas.

5. Na Component Pallete na página QReport, localize o objeto chamado QrBand, clique nele e em seguida click
dentro do objeto do QrEstado criado anteriormente.

6. Vamos para a Object Inspector e altere as seguintes propriedades:

6.1. Name para BdCabPagina


6.2. BandType para rbPageHeader - Essa é a propriedade que controla os tipos das seções no caso
escolhemos uma Banda de Cabeçalho de Página, ela aparecerá em todas as páginas.

Dentro do Quick devemos usar os objetos do Quick (isso parece óbvio mas muita gente esquece disso) o
correspondente ao objeto Label do Delphi que mostra um texto fixo no Quick é o QrLabel.

7. Na Component Pallete na página QReport, localize o objeto chamado QrLabel, clique nele e em seguida click
dentro do objeto da objeto BdCabPagina criado anteriormente .

8. Vamos para a Object Inspector e altere as seguintes propriedades:

8.1. Name para lbTitulo


8.2. Alignment para taCenter (alinhamento centralizado)
8.3. AlignToBand para True - Isso fará com o que foi definido na propriedade Alignment seja estendido para
a banda (Então o QrLabel se alinhará centralizado dentro da banda)
8.4. Font: Clique nos "..." e faça as seguintes alteções na janela de Fonts:
8.41. Cor: Azul-Marinho
8.42. Estilo: Negrito
8.43. Tamanho: 16
8.44. Fonte: Times New Roman
8.5. Caption para Estado do Brasil

9. Na Component Pallete na página QReport, localize o objeto chamado QrBand, clique nele e em seguida click
dentro do objeto do QrEstado (não é dentro daquela primeira banda criada).

10. Vamos para a Object Inspector e altere as seguintes propriedades:

10.1. Name para BdDetalhe


10.2. BandType para rbDetail - Essa é a propriedade que controla os tipos das seções no caso escolhemos
uma Banda de Detalhe, ela será replicada a cada registro e dê uma esticadinha para baixo nela, aumentando o tamanho
(ou a propriedade Height)

11. Agora eu vou precisar dentro desta banda de seis (6) objetos QrLabel (é só apertar o objeto enquanto você segura a
tecla SHIFT - O objeto vai ficar com a marcação azul e dê seis click's) dentro do objeto BdDetalhe, agora altere a
propriedade Caption de cada um respectivamente:

Sigla:
Nome:
Capital:
Núm.Município:
Região:
Descrição:

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página Nr. 55/178
12. Agora marque todos os seis objetos (lembra-se) e aproveitando o Polimorfismo altere a propriedade Font, clique
nos "..." e faça as seguintes alteções na janela de Fonts:
12.1. Cor: Castanho
12.2. Estilo: Negrito
12.3. Fonte: Times New Roman

13. Continue com os objetos marcados e a partir do menu principal vá em View | Alignment Palette será mostrada a
seguinte janela:

Clique então no último botão da primeira linha. Todos eles serão organizados à direita.

☞Importante - Vamos a uma rapidinha sobre os alinhamentos, isso só serve para dois ou mais objetos marcados:
Primeira Linha: à esquerda, centraliza verticalmente, tamanho vertical, espaçamento vertical e à direita.
Segunda Linha: Superior, centraliza horizontalmente, tamanho horizontal, espaçamento horizontal e inferior

14. Faremos agora a 3a. Conexão. Vamos para a página Data Access e localize o objeto Query. Click nele e clique
dentro do formulário e altere as seguinte propriedades:
14.1. DataBaseName para dnFedera (isto só aparecerá se o formulário F_Mapa estiver aberto)
14.2. SQL, clique nos "..." e faça escreva:
select * from Federacao
14.3. Name para QryEstado

☞Importante - Se você não conhece SQL (Structure Query Language) aconselho que você compre um bom livro,
ou veja a apostila referente aos comandos básicos.

15. Está é a 4a. Conexão. Voltemos para a página QReport e localize o objeto QrDBText, precisaremos de seis (6)
objetos dentro do objeto BdDetalhe

16. Agora marque todos os seis objetos e aproveitando o Polimorfismo altere as seguintes propriedades:

16.1. Font, clique nos "..." e faça as seguintes alteções na janela de Fonts:
16.11. Cor: Azul
16.13. Fonte: Times New Roman
16.2. DataSet para QryEstado

17. Marque agora cada objeto e altere a propriedade DataField de cada um respectivamente:

SIG_UF
NOM_ESTADO
NOM_CAPITAL
NUM_MUNICIPIO
NOM_REGIAO
DES_REGIAO

18. Uma das principais facilidades do Quick é quanto a campos Memo (como é o caso do campo DES_REGIAO)
altere as seguintes propriedades (do objeto QRDBText6 - marcado com a propriedade DataField em DES_REGIAO)
18.1. AutoSize para False (cancela o esticamento automatico horizontal)
18.2. AutoStretch para True (permite que o objeto se estique verticalmente)
18.3. WordWrap para True (só para confirmar - permite que o objeto quebre as linhas)

19. Agora estique esse objeto até o final, acredito que a propriedade Width deve ficar em torno de 625

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página 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 relatório final mesmo sem precisar
rodar o sistema, para tanto faça o seguinte:

1. No objeto QryEstado altere a propriedade Active para True.


2. Clique no objeto QrEstado e em seguida clique com o botão direito e será mostrado um menu e dentro dele clique
em Preview.
3. Novamente no objeto QryEstado altere a propriedade Active para False.

Codificando a Primeira Região


Apenas para guiá-los mostrarei como criar os códigos do mapa da Região Sul você deverá criar os códigos
para as outras regiões. Observe que novamente é quase tudo igual.

Abra o formulário F_SUL e aperte a tecla F12 até que você tenha a janela da Code Editor aberta e localize
para mim as seguintes linhas:

ImgSC: TImage;
ImgRS: TImage;
private

Inclua a seguinte chamada a um procedimento antes da parte private:

ImgSC: TImage;
ImgRS: TImage;
procedure MostraEstado(Sender: TObject);
private

Agora localize a linha:

implementation

{$R *.DFM}

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página Nr. 57/178
end.

E faça as seguintes alterações:

implementation

{$R *.DFM}
uses
fEstado; // Mostra o Estado

procedure TF_Sul.MostraEstado(Sender: TObject);

procedure Mostra(Estado: String);


begin
F_Estado := TF_Estado.Create(Application);
with F_Estado do begin
with QryEstado do begin
SQL.Clear;
SQL.Add('SELECT * FROM FEDERACAO WHERE (SIG_UF = ''' + Estado + ''')'); // Atenção é tudo aspas
simples
Open;
end;
QrEstado.Preview;
QryEstado.Close;
Free;
end;
end;

begin
if (Sender = ImgPR) then Mostra('PR') else
if (Sender = ImgSC) then Mostra('SC') else
if (Sender = ImgRS) then Mostra('RS');
end;

end.

Prontinho veja que o procedimento que eu construí aqui é igualzinho ao do F_Mapa, óbvio salvo alguns
comandos.

Criei um único procedimento MostraEstado que receberá uma variável do tipo TObject e para este
procedimento coloquei um outro procedimento interno, chamado Mostra que realizará os seguintes passos:

1. Criação do Formulário F_Estado;


2. Organização do SQL para o estado selecionado criando a Query;
3. Mostra na tela do relatório (note que não preciso do comando SHOWMODAL do formulário, e sim PREVIEW do
objeto QuickRep);
4. Fecha a Query; e
5. Eliminação do F_Estado da memória.

Para ativar todo o conjunto aperte novamente a tecla F12 (para mostrar o formulário) e dê um clique simples
sobre o objeto ImgPR aperte a tecla F11 (para chamar a Object Inspector), vá para a página de eventos e para o evento
OnClick, selecione atraves do Combo (aquela setinha apontada para baixo) o procedimento MostraEstado. Repita os
mesmos passos com as outras imagens dos outros estados.

☞Importante - No comando SQL.Add('SELECT * FROM FEDERACAO WHERE (SIG_UF = ''' + Estado +


''')'); esses três plicks ( ''' ) é tudo simples, nenhum é aspas duplas ( " ). Pois dentro de uma string cada dois plicks
simples ( '' ) conseguimos um plicks ( ' ), confuso né, mas veja só, se fizermos:

VariavelString := 'Nome : Nando';

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página Nr. 58/178
A VariavelString terá em seu conteúdo o valor Nome : Nando, agora se fizermos:

VariavelString := 'Nome : ''Nando''';

A VariavelString terá em seu conteúdo o valor Nome : 'Nando'. Eu apenas acrescentei mais dois plicks
simples entre a palavra Nando.

Tirando o formulário F_Estado do Auto-Create


Vá (a partir do menu principal) em View | Project Manager. Clique no botão Options. Selecione a página
Forms lá você verá dois objetos ListBox, do lado esquerdo são os Auto-Create Forms e do lado direito estão os
Available forms ou simplesmente formulários disponíveis.

Então selecione os formulários: F_Estado e clique no botão com o sinal > e despache-o para o lado aonde
estão os outros isolando novamente o nosso Menu pois lembrando que ele precisa ser criado automaticamente assim
que o usuário iniciar o processo.

Prontinho, agora execute o projeto e bom divertimento com seu mapa eletrônico. Na próxima aprenderemos
como distribuí-lo e gerar alguns macetes para otimização.

Finalmente
Agora precisamos arrumar, empacotar e distribuir nosso projeto, mas isto só será feito na próxima apostila.

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página 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 versão Client/Server Suite
BDE 5.00
MS-Access 97

Arquivos trabalhados juntos com esta apostila:

GEOGRAPH.ICO, SETUP1.BMP, SETUP2.BMP, SETUP3.BMP, SPLASH.BMP e LOGO.BMP

Prefácio
Salve, na última apostila montamos nosso segundo aplicativo o Mapa Eletrônico, o interessante é com ele é
que calmamente começamos a desvendar os segredos do trabalho com o Delphi associado a Bancos de Dados,
repararam como a maior parte dos livros evita em falar sobre o assunto ? O máximo com um aplicativo que arranha a
superfície deste fantástico mundo. O problema é que o assunto é muito mais do que se pode imaginar, pois o Delphi
tem milhares de possibilidades para realizar esta tarefa.

O maior problema com o Delphi (depois de entendê-lo) é como distribuir seus aplicativos gerados, quando ele
é independente de tratamento de banco de dados, tudo bem é só mandar o executável (.EXE) mas o problema começa
quando ele utiliza o BDE, aí a coisa complica um pouco, mas acredito que após essa parte você começará a dominar
uma importante ferramenta de distribuição para seus aplicativos.

Preparando o sistema para o Empacotamento


Antes de gerarmos nossos discos de instalação vamos fazer algumas alterações no projeto então abra
novamente o seu projeto, para isso a partir do Menu Principal clique em File | Open localize o arquivo Mapa.DPR.

Agora, a partir do Menu Principal, clique em Project | Options e vamos realizar dois serviços aqui:

1. Na página Application coloque o Título do nosso projeto (Mapa Eletrônico) e localize o ícone
enviado (Geograph.ico).

2. Na página Compiler desmarque todas as opções dos grupos Debugging e Messages e clique no
botão OK.

Novamente a partir do Menu Principal, clique em Project | Build All para gerarmos o executável final,
prontinho agora feche o Delphi confirmando as modificações realizadas no projeto.

Utilizando o Install Shield


No Delphi 1.0 para distribuir o BDE era uma complicação, existia um diretório no CD do Delphi chamado
REDIST, nele estava (dividido para caber em disquetes de 1.44 Mb) o BDE. Ou seja, você se deslocava até a máquina
do seu Cliente (que iria instalar o sistema) criava um diretório, colocava o executável, as tabelas, e instalava o BDE,
depois criava o alias, testava e pronto estava instalado. Com um certo tempo as pessoas aprenderam a gerar o Alias
automático. Mas ainda assim era um tanto primitivo, principalmente quando você precisava mandar tudo para que o
próprio cliente instalasse.

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página Nr. 60/178
Com o Delphi 2.0 surgiu o InstallShield que foi mais aprimorado ainda nessa versão, ele é um produto da
Stirling Technologies. Que acompanha também o Delphi 3.0 e o Delphi 4.0. Um aviso, não tente utilizar o
InstallShield que vem com o Delphi 2.0 para aplicações do Delphi 3.0 ou 4.0, nem vice-versa, apesar de todos serem
de 32 Bits são de versões totalmente diferentes.

O InstallShield não é que nem o Quick Report, você precisa instalá-lo em separado (ele vem no próprio CD
do Delphi), após sua instalação e execução, você acabará com a seguinte janela:

Esta é a tela inicial para a criação do seu projeto .IWZ, informe o nome do projeto, o tipo (no caso de versões
registradas) e o diretório que será criado, após isso aperte o botão Create e iremos para a janela de construção do
projeto:

Esta tela foi dividida em nove grandes grupos, para explicar melhor vamos analizar grupo a grupo enquanto
fazemos as alterações para a geração do nosso pacote.

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página Nr. 61/178
1. Set the Visual Design
Neste grupo estão as informações iniciais do instalador:

Na primeira parte (Application Information) você deve informar o nome da aplicação (mapa), localizar o
executável que deverá ser instalado (C:\...\Mapa.EXE), a versão (1.0) e o nome da sua empresa (Curso). Note que
nesta parte é montado o Diretório que será instalado o sistema final (<ProgramFilesDir>\Curso\Mapa).

Na segunda parte (Main Window) é a tela principal da instalação, aqui você escolherá o título principal
(Mapa Eletrônico), o Logotipo da sua Empresa (localize o BitMap Enviado: Logo.BMP), a posição em que o logotipo
ficará (Top Right - Em cima a direita) e a cor de fundo (Dithered Blue - degradê em azul).

Na terceira parte (Features) preste muita atenção que este é o momento mais difícil, aqui você escolherá se o
usuário pode ou não desinstalar automaticamente o projeto. Prontinho pode dar OK.

☞Importante - Assim como o Logo.BMP você notará que no decorrer dessa montagem colocaremos vários
Bitmap's, você mesmo poderá gerá-los mas lembre-se que o InstallShield aceita apenas imagens com no máximo 16
cores.

2. Select InstallShield Objects for Delphi


Esta é o grupo que mais confunde as pessoas, mas com um pouquinho de atenção a gente chega lá, aqui você
definirá qual tipo de BDE será instalado, o tipo do SQL Links ou se deseja carregar qualquer dos pacotes de objetos do
Delphi.

Na primeira parte (General) são as informações principais, marque o BDE, (Observação: O SQL Links, serve
apenas para conexão com bancos do tipo MS-SQL, SyBase padrão DB-Lib, InterBase, Oracle, Informix, DB2 e
SyBase padrão CT-Lib e os pacotes de objetos servem apenas para o caso de compilações parciais), clique no botão
Settings...

BDE Instalation Type - Aqui você define seu tipo de banco de dados, infelizmente o Install não possui
permissão para a distribuição da DAO 3.5, que é a responsável pela conexão nativa com o MS-Access, ista permissão é
adquirida apenas com a compra de qualquer ferramenta de desenvolvimento Microsoft, teremos então que colocar na
mão todos os arquivos necessários, marque Partial BDE Installation e clique no botão Avançar.

BDE Driver Types - não escolha nenhum, deixe todos desmarcados.

Query Engine Types - Marque a opção SQL Engine isto fará com que o BDE reconheça e envie para
o gerenciados de banco de dados os comandos de SQL e clique no botão Avançar.

BDE Alias - Step 1 of 4 - Clique no botão New e informe o nome do nosso Alias (AlFedera)

BDE Alias - Step 2 of 4 - Esta e a tela mais enigmática do Install, nela você deve informar se quer que
seu BDE seja configurado para aplicações Win16/Win32 ou somente Win32, mas aqui ele não se refere a
possibilidade de instalação para Windows 3.x ele apenas está se referindo ao .CFG salvo (que é o arquivo de
configuração do BDE 32, então deixe desmarcado e sigamos em frente.

BDE Alias - Step 3 of 4 - Aqui está todo o pulo do gato sobre a construção do BDE, em Alias Name
ele mostrará o Nome do seu alias, em Path é o local que seu banco deverá ser instalado, agora vamos pensar um
pouquinho, mas se o usuário mudar o destino ? Aqui usaremos uma variável do Install, coloque: [Program Files]\ que
será o diretório em que ficará sua aplicação. No Type selecione MSAccess. E finalmente escreva na lista de parâmetros
opcionais para o Alias o seguinte:

DATABASE NAME=[Program Files]\Basico.mdb

BDE Alias - Step 4of 4 - Aqui você precisa apenas clicar no botão Concluir para finalizar todas as
inclusões no BDE.
Na segunda parte (Advanced) você verá todas as bibliotecas que serão instaladas, apenas clique no botão OK

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página 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) faça as seguintes inclusões:

Na pasta Program Files aperte o botão Insert Files, localize e arraste o arquivo BASICO.MDB
(clicando com o mouse sobre ele, segurando e levando) para dentro desta pasta.

Na pasta BDE/IDAPI Files localize e arraste o arquivo IDDA3532.DLL, pode fechar o Windows
Explorer.

Vamos agora criar algumas pastas necessárias para a instalação do DAO, clique no botão Add Group e
coloque as seguintes informações:

Group Name: DAOSystem


Destination Directory: <WINSYSDIR>
Com o auxílio do botão Insert Files arraste os seguintes arquivos para esta pasta:
C:\Windows\System\MSJTER35.DLL C:\Windows\System\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 auxílio do botão Launch Explorer arraste os seguintes arquivos para esta pasta:
C:\Arquivos de Programas\Arquivos comuns\Microsoft Shared\DAO\DAO350.DLL
C:\Arquivos de Programas\Arquivos comuns\Microsoft Shared\DAO\DAO2535.TLB
C:\Arquivos de Programas\Arquivos comuns\Microsoft Shared\DAO\DAO2532.TLB
C:\Arquivos de Programas\Arquivos comuns\Microsoft Shared\DAO\DAO3032.DLL

Group Name: VBFiles


Destination Directory: <WINSYSDIR>
Com o auxílio do botão Launch Explorer arraste os seguintes arquivos para esta pasta:
C:\Windows\System\OLEPRO32.DLL
C:\Windows\System\CTL3D32.DLL
C:\Windows\System\VBAR2232.DLL

As próximas partes (Components e Setup Types) são utilizadas quando você estiver trabalhando com uma
aplicação muito grande aonde existe a divisão em várias partes, você poderá dar também a chance do seu cliente
instalar apenas determinadas partes que o interesse.

4. Select User Interface Components


Este grupo é o que comandará a instalação propriamente dita, gerando a interface com o nosso cliente. Vamos
tratá-lo com calma e parte a parte:

Welcome Bitmap - Este é um bitmap de abertura, é a primeira janela que será mostrada após iniciado o
programa de instalação. Marque a opções e clique na página Settings e localize o arquivo Splash.bmp enviado. Para o
nosso caso deixe a opção marcada.

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página 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 inglês, só pode ser modificada na versão registrada do produto. Para o nosso
caso desmarque a opção.

Software Licence Agreement - Aqui esta a famosa janela da Licença de uso, ou se você prefere das
regras de uso para o nosso aplicativo, você pode modificar o conteúdo criando um arquivo texto (formato .TXT) e o
localizando através da página Settings, mas não poderá modificar as instruções em Inglês (apenas na versão registrada).
Para o nosso caso desmarque a opção.

Readme Information - Aqui será mostrado o arquivo LeiaMe inicial, novamente você pode modificar
o conteúdo criando um arquivo texto (formato .TXT) e o localizando através da página Settings, mas não poderá
modificar as instruções em Inglês (Apesar de que ela se reduz a um simples Information) se você quiser crie-o ou
então desmarque a opção.

User Information - Aqui são informações do nosso cliente: seu nome, nome da empresa e o número de
registro do nosso software. Para o nosso caso deixe a opção desmarcada.

Choose Destination Location - Aqui é aonde nosso cliente poderá escolher qual o drive e a pasta que o
sistema será instalado. (para o nosso caso ela será colocada em C:\Arquivo de Programas\Curso\Mapa). Como
acertamos no BDE podemos deixá-la marcada para que o nosso cliente decida.

Setup Type - Em casos de sistemas muito grandes é aqui que o cliente decidirá qual o modo que ele
quer que seja instalado o sistema. Tudo, Compacto ou Customizado. Para o nosso caso deixe a opção desmarcada.

Custom Setup - Esta é uma subdivisão da parte anterior aonde o cliente escolherá (a partir da opção
Customizado da janela anterior, qual a parte que ele quer que seja instalada. Para o nosso caso deixe a opção
desmarcada.

Select Program Folder - Aqui aparecerá uma janela que permitirá alterar o nome do grupo que será
criado no Windows para colocar nossos ícones do projeto. Para o nosso caso deixe a opção marcada.

Start Copying Files - É aqui que o cliente vê todas as opções que ele escolheu anteriormente, podendo
voltar atrás e modificar algo antes da instalação propriamente dita. Para o nosso caso deixe a opção marcada.

Progress Indicator - Uma barra que acompanhará o processo de instalação mostrando ao cliente o
quanto falta (em percentual) para a conclusão da instalação. Para o nosso caso deixe a opção marcada.

Billboards - São cartazes que fazem a propaganda do nosso software ou de outros que produzimos,
aqui é possível colocar um para cada mídia instalada, basta apenas nomeá-los em SETUP1.BMP, SETUP2.BMP e
assim sucessivamente dependendo do número de discos que produzimos. Vá para a página Settings e localize o
diretório dos bitmaps enviados (SETUP1.BMP, SETUP2.BMP e SETUP3.BMP). Para o nosso caso deixe a opção
marcada.

Online Registration - Muitas empresas processam o registros dos softwares de forma automática,
bastando para isso que o cliente possua um Modem, para tanto na página Settings identifique o número identificador
do sistema e o número do telefone ou então desmarque a opção.

Setup Complete - Este é o último passo do processo, aqui você pode escolher se o cliente deve dar um
Reboot na máquina (que é aconselhável), ou mostrar um arquivo Leiame final, bastando para isso alterar na página
Settings, mas de qualquer forma deixe esta opção marcada.

Clique no botão OK para finalizar

5. Make Registry Changes


Esta página deve ser tratada com o carinho e o respeito que ela merece, pois aqui faremos as modificações na
área de register do Windows, então calma e muito sangue frio aqui. Não queremos corromper essa área de registro do
nosso cliente.

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página Nr. 64/178
Como modificamos a versão do DAO em nosso BDEAdmin para 3.5 também precisamos repetir essa
operação na máquina que será instalado o nosso sistema.

Na página Registry - Keys abra a chave HKEY_LOCAL_MACHINE e clique no botão Add Key... crie a
chave SOFTWARE, clique nesta nova chave e vá repetindo a operação criando a seguinte estrutura:

HKEY_LOCAL_MACHINE\SOFTWARE\Borland\DataBase Engine\Settings\DRIVERS\MSACCESS\INIT

Deixe marcada a última chave INIT e clique na página Registry - Values e clique no botão Add Values e
proceda as seguintes alterações:

Pronto, clique no botão OK.

Agora crie a seguinte Chave na página Registry - Keys:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Shared Tools\DAO

Crie o seguinte Valor para esta chave na página Registry - Values:

Value Type: String


Value Name: Path
Value Data: <CommonFilesDir>\Microsoft Shared\DAO\Dao3032.dll

Crie a seguinte Chave na página Registry - Keys:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Shared Tools\DAO35

Crie o seguinte Valor para esta chave na página Registry - Values:

Value Type: String


Value Name: Path
Value Data: <CommonFilesDir>\Microsoft Shared\DAO\DAO350.DLL

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página Nr. 65/178
6. Specify Folders and Icons
Aqui será mostrado os Ícones (dos Arquivos) que serão instalados dentro do grupo escolhido, este grupo
divide-se em:

General - Aonde é possível adicionar novos ícones, lembre-se que antes eles devem ter sido colocados pelo
grupo Specify Components and Files, tais como:

Arquivos TXT - Readme iniciais, para o registro do aplicativo, entre outros.


Arquivos HLP - Contendo um arquivo de auxílio para a aplicação.

Advanced Settings - Aqui podemos modificar o destino dos nossos arquivos, o ícone, criamos uma tecla de
atalho rápido para sua execução ou até mesmo iniciá-lo quando o Windows for iniciado.

☞ Importante - Para o aplicativo iniciar assim que o Windows iniciar na página Advanced, existe uma caixinha
para marcar que está escrito: Place Icon and Start Programs Menu.

7. Run Disk Builder


Pronto, tudo foi informado e agora é o grande momento a geração do nosso pacote, escolha a midia que será
gerado e clique no botão Build, espere o término do processo e veja em quantas mídias foram geradas o seu pacote.

☞Importante - Não se assuste com o número de disquetes (1.44Mb) normalmente apenas o BDE ocupa 2,5
disquetes então é comum sistemas darem de 3 ou superior. Contando que o DAO normalmente ocupa 3 Disquetes ou
mais, calcule que seu sistema caberá em simples 7 disquetes.

☞Importante - Se você instalar o sistema a partir da rede escolha a opção CD-Rom pois aí será uma única mídia.
8. Test the Installation
Aqui você pode testar como ficou seu pacote, acompanhando eventuais erros, mas o melhor mesmo é você
colocá-lo em disquetes e levá-lo para uma máquina que não tenha o Delphi instalado.

☞Importante - Gere seu pacote em disquetes de 1.44Mb e copie para os disquetes para proceder a instalação assim
você poderá acompanhar a mudança das telas a cada disquete solicitado.

☞Importante - Não se esqueça que depois, para removê-lo, você precisa ir em Painel de Controle | Adicionar ou
Remover Programas para que o Install proceda a retirada das entradas nas áreas de registro do Windows.

9. Create Distribution Media


Neste último grupo você poderá copiar totalmente, ou parcialmente, o seu pacote na mídia selecionada.

Finalmente
Agora você já pode mandar todo o seu projeto para aquele cliente especial, basta apenas embalá-lo e despachar
com as famosas instruções:

Como Instalar
O Mapa Eletrônico só pode ser consultado depois de instalado no seu Microcomputador, sob o ambiente Windows 95
ou superior. Para realizar a instalação siga essas instruções:

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página Nr. 66/178
1. Ligue o Microcomputador ativando o Windows
2. Introduza o disquete marcado como INICIAL na unidade de leitura
3. Clique no botão INICIAR e escolha a opção EXECUTAR
4. Digite então A:\SETUP (ou no lugar do A, a letra equivalente ao drive da sua unidade de leitura do disquete).
5. Click sobre o botão OK e execute as instruções do Instalador.

Acredito que seu usuário não errará esses 5 passos. Um abraço e até a próxima.

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página 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 versão Client/Server Suite
BDE 5.00
MS-Access 97

Arquivos trabalhados juntos com esta apostila:

SQL.WRI

Prefácio
O nosso projeto para essa apostila será um tanto bobinho, mas é uma imensa mão na roda para testarmos
nossos aplicativos futuramente, noto que a maioria das pessoas quando começam a programar em Delphi, temem o
maior de todos os pesadelos: o SQL (Structured Query Language), são apenas três letrinhas mas que confundem e
complicam a vida da maioria dos programadores, um conselho dominando essa simples (porém complexa) linguagem,
garanto que será a diferença entre um sistema que apresentará facilidades imensas e dará poderes extraordinários para o
nosso usuário, basicamente a linguagem SQL contém 4 comandos:

- SELECT
- INSERT
- UPDATE
- DELETE

Na apostila em anexo, enviada junto com esta, explica-se exatamente a função de cada comando, aqui vamos
nos ater ao Delphi, então vamos começar mais um projeto

Projeto 3 - Construtor de SQL


Bem, agora que estamos familiarizados com o ambiente SQL (espero que você tenha lido a apostila em anexo
antes de começarmos), vamos para as nossas receitas de bolo, siga um passo atrás do outro, mas antes de começar crie
uma pasta que abrigará seu projeto, por exemplo Gera SQL.

1. Na Component Pallete localize uma página chamada Standard e dentro dessa página de um clique no objeto
ListBox (acredito que seja o nono) e dê um clique no Form. Olhe na Object Inspector e altere a propriedade Name
para ListaAlias.

2. Pegue outro objeto ListBox e dê um clique no Form e altere a propriedade Name para ListaTabela e altere a
propriedade sorted para True isto fará a ordenação alfabetica dos nomes da lista.

3. Vá na Object Inspector e localize o objeto Form1 (basta clicar no Combo Box para selecioná-lo), e altere as
seguintes propriedades:

3.1. BorderStyle: bsDialog (Fará com que a janela fique no formato padrão de uma janela de mensagens)
3.2. Caption: Executa instruções SQL (Conteúdo da tarja do formulário)
3.3. Name: F_SQL (Nome interno do formulário)
3.4. Position: poScreenCenter (Fará com que o formulário fique sempre centralizado quando for executado)

4. Dê uma salvadinha no seu projeto, para tanto, no menu vá em File | Save All...:

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página Nr. 68/178
4.1. Aonde aparece Unit1.pas (o Delphi está se referindo do nome do formulário) mude para fSQL.PAS
4.2. Aonde aparece Project1.dpr (o Delphi está se referindo do nome do projeto - que será o nome do
executável final) mude para GerSQL.DPR

5. Na Component Pallete novamente na página Standard e localize agora o objeto Memo (acredito que seja o quinto)
e através da Object Inspector altere as seguintes propriedades:

5.1. Lines: Clique nos ... e elimine todo o seu conteúdo

6. Precisamos agora de três objetos Label's, para tanto pressione a tecla SHIFT e clique no objeto Label (deve ter
ficado um quadriculado azul em volta do objeto, como se ficasse marcado) e dê três cliques no Form, coloque-os acima
dos três objetos criados anteriormente. (automaticamente o Delphi criou oito objetos chamados respectivamente
Label1, Label2 e Label3)

7. Quando terminar clique dentro da Component Pallete na setinha para poder desmarcar o objeto Label.

8. Altere as seguintes propriedades para esses três objetos:

8.1. Font: Clique nos "..." e faça as seguintes alterações na janela de Fonts:
3.41. Cor: Castanho
3.42. Estilo: Negrito
8.2. Caption: Altere para cada um respectivamente:
Selecione o Alias:
Tabelas Disponíveis:
Digite a clausula SQL

9. Na Component Pallete vá para a página Addicional e localize agora o objeto SpeedButton (acredito que seja o
segundo) e traga dois para o form e através da Object Inspector altere as seguintes propriedades:

9.1. Glyph: Altere para cada um respectivamente:


CHECK.BMP
CLEAR.BMP
9.2. Flat: True (faz com que o botão fique liso no form)
9.3. Hint: Altere para cada um respectivamente:
Executa a instrução SQL
Limpa a instrução SQL
9.4. ShowHint: True
9.5. Name: Altere para cada um respectivamente:
ButExecuta
ButLimpa

10. Na Component Pallete vá para a página Data Access e localize agora o objeto Query (acredito que seja o terceiro)

11. Na mesma página Data Access e localize agora o objeto DataSource (acredito que seja o primeiro) e através da
Object Inspector altere a propriedade:

11.1. DataSet: Query1 (faz a ligação com um objeto Query ou Table)

12. Para finalizar na Component Pallete vá para a página Data Controls e localize agora o objeto DbGrid (acredito
que seja o primeiro) e através da Object Inspector altere a propriedade:

12.1. DataSource: DataSource1 (faz a ligação com um objeto DataSource)

13. Terminamos, compare como ficou:

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página Nr. 69/178
Codificando
Tudo pronto, basta apenas meter a mão no programa, mas vamos devagar, a idéia deste projeto apesar de
simples pode parecer um pouco complicada, inicialmente será mostrado todos os alias que existem no BDE
Administrator após a escolha de qualquer um deles, serão mostradas as tabelas disponíveis, agora basta apenas digitar
as instruções SQL no objeto MEMO1 e pressionar o botão para executá-lo.

14. Localize na Object Inspector o objeto F_SQL, mude para a página de eventos (Events) e localize o evento
OnShow, dê um duplo clique na área em branco. Automaticamente o Delphi criará para você a chamada ao evento e o
transferirá para a Code Editor, insira o seguinte código:

procedure TF_SQL.FormShow(Sender: TObject);


begin
Session.GetAliasNames(ListaAlias.Items);
Query1.DataBaseName := ListaAlias.Items[0];
end;

Este procedimento se encarregará de carregar o nosso objeto ListBox com a lista do nome de todos os Alias
existentes e transferir o primeiro nome carregado para a propriedade Databasename do objeto Query1.

15. Localize na Object Inspector o objeto ListaAlias e na página de eventos (Events) localize o evento OnClick, dê
um duplo clique na área em branco. Automaticamente o Delphi criará para você a chamada ao evento e o transferirá
para a Code Editor, insira o seguinte código:

procedure TF_SQL.ListaAliasClick(Sender: TObject);


var
i : integer;
begin
if (ListaAlias.SelCount = 0) then begin
MessageDlg('Selecione primeiro algum Alias',mtError,[mbOk],0);
exit;
end;
// Mostra os itens da lista não resolvida
Screen.Cursor := crHourGlass;
for i := 0 to (ListaAlias.Items.Count - 1) do
if ListaAlias.Selected[i] then begin

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página 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;

Não se preocupe em não entender nada aqui, muito desses comandos sequer foram falados, então vamos por
partes, o evento é disparado assim que qualquer dos Alias da nossa lista for selecionado:

1. Verificação (de rotina) se realmente algum alias foi selecionado da lista


2. Modifica o cursor para o formato de uma ampulheta
3. Do primeiro ao último da lista (aonde o primeiro é 0 e o último é o número de elementos - 1)
3.1. Verifica se é este o alias selecionado e se for
3.1.1. Verifica se a query1 está aberta se estiver fecha ela
3.1.2. Transfere o nome do alias para a propriedade Databasename da Query1
3.1.3. Carrega a lista dos nomes das tabelas do alias selecionado
3.1.4. Interrompe o laço
4. Modifica novamente o cursor para o formato padrão

☞Importante - Existem dois comandos que cancelam laços de repetições (Comandos For, While e Repeat) são
eles:

Break - Interrompe o laço mandando o comando para o próximo comando após o laço.
Exit - Interrompe o laço terminando o procedimento ou função.

O comando Break só pode ser usado dentro de um laço de repetição enquanto que o comando Exit pode ser
usado dentro de procedimentos ou funções livres de um laço de repetição.

16. Localize na Object Inspector o objeto ButExecuta e na página de eventos (Events) localize o evento OnClick, dê
um duplo clique na área em branco. Automaticamente o Delphi criará para você a chamada ao evento e o transferirá
para a Code Editor, insira o seguinte código:

procedure TF_SQL.ButExecutaClick(Sender: TObject);


begin
with Query1 do begin
if Active then Close;
SQL.Clear;
SQL := Memo1.Lines;
try
ExecSQL;
try
Open;
except
end;
MessageDlg('Instrução Executada...', mtInformation, [mbOk], 0);
except
MessageDlg('Comando SQL está inválido', mtError, [mbOk], 0);
end;
end;
end;

Aqui até que poderia ser tudo simples, mas para possibilitar que o usuário possa fazer uso dos comandos
INSERT, UPDATE e DELETE tive que usar de uns macetes que acabaram se tornando interessantes, meu problema
estava no seguinte, esses três comandos indicados anteriormente diferentemente do comando SELECT não geram o
que chamamos em SQL de uma cadeia de códigos, ou seja, eles não me dão uma resposta em uma lista, então não
posso utilizar-me do comando OPEN para eles, ao invés disso preciso usar o comando EXECSQL que apenas dispara
esses comandos para o banco de dados, não gerando nenhuma espécie de retorno e para sorte o EXECSQL suporta o
comando SELECT.

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página Nr. 71/178
Além desse problema o usuário poderia digitar um comando errado, algo como: Maria tinha um
carneirinho... o que me daria um erro que travaria totalmente meu aplicativo (causando uma falha do programa).

Para sanar ambos os problemas construí um bloco de proteção try...except...end; esses comandos protegem os
códigos que estão entre o try...except e caso acontece erro em algum deles (por exemplo um comando assim:
Variavel_Inteira := 10/0; ou Variavel_Inteira := 'Maria tinha um carneirinho...') transferindo automaticamente
para a instrução entre o except...end;

Vamos dar uma olhada então como ficou a lógica do procedimento:

1. Verifica se a query1 está aberta se estiver fecha ela


2. Limpa o parâmetro lines da Query1
3. Transfere o conteúdo das linhas do Memo1 para dentro do SQL da Query1
4. Abre um bloco de proteção
4.1. Executa o comando SQL
4.2. Ativa um novo bloco de proteção
4.2.1. Abre a Query1
4.2.2. Em caso de erro no bloco de proteção apenas segura e não faz nada
4.3. Mostra uma mensagem dizendo que está tudo bem
5. Em caso de erro no bloco de proteção coloca uma mensagem de alerta

Observação Interessante: Existe também o bloco de proteção try...finally...end; que protege os comandos, e
acontecendo ou não o erro executa obrigatoriamente os comandos localizados entre o finally...end;

17. Localize na Object Inspector o objeto ButLimpa, na página de eventos (Events) localize o evento OnClick, dê
um duplo clique na área em branco. Automaticamente o Delphi criará para você a chamada ao evento e o transferirá
para a Code Editor, insira o seguinte código:

procedure TF_SQL.ButLimpaClick(Sender: TObject);


begin
Memo1.Lines.Clear;
end;

Agora ficou fácil, a única função deste botão é limpar o conteúdo do objeto Memo1.

18. Localize na Object Inspector o objeto F_SQL, na página de eventos (Events) localize o evento OnClose, dê um
duplo clique na área em branco. Automaticamente o Delphi criará para você a chamada ao evento e o transferirá para a
Code Editor, insira o seguinte código:

procedure TF_SQL.FormClose(Sender: TObject; var Action: TCloseAction);


begin
with Query1 do if Active then Close;
end;

Aqui também é simples, quando terminar o aplicativo verifica se o objeto Query1 ficou aberto, e em caso
afirmativo fecha ele.

Finalmente
Prontinho você já pode executar seu aplicativo, mas ainda aqui vale uma pequena observação, escreva um
código esquisito para o objeto Memo1 (por exemplo digite: Maria tinha um carneirinho... e clique no botão para
executar o SQL note que automaticamente o Delphi interrompe a execução do programa e assume o controle, basta
apenas você disparar F9 para continuar, não se preocupe isso acontece apenas em modo Run-Time se você executar o
aplicativo fora do Delphi você não passará mais por isso e verá que seu aplicativo consegue controlar o erro
eficazmente.

☞ Importante - Você pode desativar isto, para tanto a partir do Menu Principal vá em Tools | Environment
Options... e na página Preferences no bloco Debugging desative a opção Break on Exception.

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página 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 versão Client/Server Suite
BDE 5.00
MS-Access 97

Prefácio
Salve, antes de começarmos devo dizer que este será o projeto mais longo e completo que já fizemos no
decorrer deste curso, atualmente não existe mais a figura do programador, aquele cara que sentava atrás de um teclado e
ficava simplesmente desenvolvendo programas maravilhosos que o usuário acabava achando confuso e complicado de
usar. Então porque fazer um curso de Delphi (ou qualquer outra ferramenta) apenas para apenas aprendermos a
linguagem ? Sendo que seria muito mais fácil consultar o manual. Com base nisso ao invés de me restringir a apenas
ensinar macetes e dicas quentes, vou tentar algo mais "ousado" a partir de agora, tentar dar uma visão do mundo
externo para vocês com projetos reais.

Vale uma pequena observação aqui: Apesar de todos os dados se aproximarem o máximo possível da
realidade todas as empresas que serão abordadas e criadas aqui serão totalmente fictícias, caso numa dessas loucuras da
vida a empresa exista (cada dia é criado uma nova mesmo) todos os dados foram criados exclusivamente por
imaginação e não existe nenhuma relação com a realidade.

Começaremos desde a fase da entrevista com os usuários responsáveis até a finalização com a instalação
dos módulos, portanto dividi este projeto em diversas apostilas, a de hoje considero a mais chata, mas em
compensação é a mais importante, para quem gosta de colocar a mão na massa vai se decepcionar hoje, pois a única
massa que usaremos será a cerebral. Portanto feche o Delphi e o micro, pegue papel e caneta e vamos ao trabalho.

Iniciando
A companhia Antes & Depois nos contratou para que criassemos um sistema que agilizaria o trabalho
rotineiro, esta empresa trabalha basicamente com o conceito de SPA (vulgarmente conhecidos como Campo de
Concentração para Gordinhos), mas teve um pequeno problema no caminho, Ela (a empresa) não sabe qual o tipo de
sistema que quer, mas a idéia basica de que se precisa é:

De um cadastro organizado e completo de cada cliente;


De um controle individual da criação dos programas alimentares; e
De um acompanhamento pós-programa do Cliente.

Então foram realizadas três entrevistas, a primeira com o médico-diretor geral da Empresa que recebe e
define o programa do cliente, a segunda com o responsável pelos cardápios da alimentação e a terceira com o médico
nutricionista da empresa responsável pelo acompanhamento pós-programa. A seguir você encontrará a síntese dessas
entrevistas.

Projeto 4 - Analizando o SPA Antes & Depois Cia.


1º Dia de entrevistas com o usuário: Programação alimentar para o emagrecimento
Um novo hábito em vez de uma nova dieta este é o lema da nossa empresa. Primeiramente, é
importante ter em mente a necessidade de se chegar a um novo hábito alimentar, que irá assegurar a manutenção do
peso ideal após o final do tratamento. Já sabemos que 90% das pessoas que fazem uma dieta para emagrecer recuperam

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página Nr. 73/178
depois todo o peso perdido. Sabemos também que ficar engordando e emagrecendo é pior para a saúde do que
simplesmente manter-se obeso. Devemos, portanto, buscar sempre um resultado definitivo, que permitirá a manutenção
do peso dentro de uma faixa ideal. Esqueça aquela idéia antiga do emagrecimento através de dietas, que representavam
um período de sacrifício, fome, fraqueza e mau humor. As pessoas deixavam inclusive de comparecer a festas e
reuniões sociais que pudessem representar uma ameaça ao seu programa alimentar rigoroso.

Flexibilidade. A tendência mundial tem sido de recomendar programas alimentares flexíveis, onde as
quantidades planejadas de cada alimento não precisam ser rigorosamente respeitadas nem o paciente é obrigado a evitar
compromissos sociais onde alimentos "proibidos" serão servidos. Algumas comidas devem ser evitadas, ou consumidas
com moderação, principalmente as mais gordurosas.

Alimentação sob-medida. Cada pessoa precisa de um determinado programa alimentar para


emagrecer de forma saudável e equilibrada. Existem fórmulas para se calcular a quantidade de calorias a ser
ingerida diariamente. Infelizmente, este método é muito falho, já que não leva em conta as grandes variações de gasto
metabólico de uma pessoa para outra. Este gasto energético só pode ser medido através de aparelhos sofisticados e
caros, que são utilizados apenas em trabalhos de pesquisa. Existem, no entanto, maneiras práticas de se estimar quanto
uma pessoa queima em calorias. Por exemplo, se o paciente já relata na consulta que, mesmo comendo pouco,
emagrece muito lentamente, provavelmente seu gasto metabólico é baixo. Sua alimentação deverá conter entre 1000 e
1200 Kcal para que o tratamento não seja muito demorado. Já uma pessoa que tenha engordado porque ingere uma
quantidade exagerada de calorias e conta que emagreceu rapidamente durante um período de contenção alimentar,
provavelmente tem um metabolismo que consome muita energia. Este paciente poderá emagrecer bem com uma
quantidade de calorias maior, entre 1500 e 1800 Kcal. Algumas pessoas acham que não podem emagrecer porque têm
um horário muito irregular, uma vida profissional muito agitada ou porque jantam fora todas as noites. Tudo isso pode
ser contornado. Sempre haverá uma maneira de planejar uma alimentação adequada que se adapte ao seu estilo de vida,
respeitando seus hábitos e seu paladar.

Equilíbrio. Emagrecer não é fechar a boca. A alimentação deve ser voltada para o equilíbrio do
metabolismo. Além de conter uma quantidade adequada de calorias, elas devem estar distribuídas em proporções
apropriadas, entre carboidratos, proteínas e gorduras. Para isso, você precisará conhecer a composição dos alimentos,
consultando a tabela de alimentos equivalentes ou o dicionário. Também é importante distribuir adequadamente as
refeições. Os horários não precisam ser obedecidos rigorosamente, mas não se deve ficar mais de 4 horas sem comer.
Um programa de alimentação ideal deveria conter 6 refeições diárias - desjejum (café da manhã), colação (refeição
ligeira entre o desjejum e o almoço), almoço, lanche, jantar e ceia. Se você tem o hábito de dormir logo após o jantar,
não é necessário incluir a ceia. É muito comum as pessoas saltarem refeições sempre que estão sem fome, tentando
desta forma obter resultados mais rápidos, o que não é recomendável. Uma parte importante do nosso gasto energético
vem da própria metabolização dos alimentos.

2º Dia de entrevistas com o usuário: Como são montados os cardápios


A tabela de alimentos equivalentes é uma lista de substituições, que deve ser sempre consultada para
que a alimentação não se torne monótona. Lembre-se que o objetivo principal é o desenvolvimento de um novo hábito
alimentar. Comendo todo dia as mesmas coisas você não estaria evoluindo na busca de um comportamento alimentar
diferente daquele que o levou a engordar. Através da tabela você poderá substituir os alimentos à vontade, sempre
dentro de um mesmo grupo, onde o teor calórico e a proporção de carboidratos, proteínas e gorduras serão semelhantes
(equivalentes). Conhecendo as possibilidades de substituições que a tabela oferece, você mesmo poderá elaborar seu
cardápio, mantendo-o sempre atrativo e saboroso. Além disso, você estará apto a manipular sua alimentação para
adaptá-la às mais diversas ocasiões, como jantares festivos, refeições rápidas, churrascos e qualquer circunstância que o
obrigue a sair da rotina.

A seguir você verá os 8 grupos básicos na composição de dietas para emagrecimento.


Grupo 1
VEGETAIS DE BAIXÍSSIMO TEOR CALÓRICO

ABOBRINHA ACELGA AGRIÃO AIPO


ALFACE ALMEIRÃO AZEDINHA BERTALHA
BRÓCOLIS CARURU CHICÓRIA COUVE
ESCAROLA ESPINAFRE MAXIXE NABIÇA
NABO PEPINO PIMENTÃO RABANETE
REPOLHO SALSÃO SERRALHA TAIOBA
TOMATE

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página Nr. 74/178
Grupo 2
VEGETAIS DE BAIXO TEOR CALÓRICO (2 colheres das de sopa equivalem a 1 porção)

ABÓBORA ASPARGO BERINGELA BETERRABA


CEBOLA CENOURA CHUCHU COGUMELO
COUVE-FLOR ERVILHA PALMITO QUIABO
VAGEM

Grupo 3
FRUTAS

ABACAXI - 1 RODELA PEQUENA ACEROLA - 1 PEQUENA


ÁGUA DE COCO - 1 COPO PEQUENO MEIXA - 2 MÉDIAS
AMORA - MEIO COPO BANANA D'ÁGUA - MEIA FRUTA
BANANA MAÇÃ - 1 PEQUENA BANANA OURO - 1 PEQUENA
BANANA PRATA - 1 PEQUENA CAJÁ-MANGA - 1 PEQUENO
CAJU - 1 MÉDIOCAQUI - 1 PEQUENO CARAMBOLA - 1 MÉDIA
CEREJA - 6 FRUTAS DAMASCO - 2 MÉDIOS
FIGO - 1 MÉDIO FRAMBOESA - 10 FRUTAS
FRUTA-DE-CONDE - MEIA FRUTA GOIABA - 1 PEQUENA
GRAPEFRUIT - MEIA FRUTA JABUTICABA - 10 FRUTAS
JACA - 4 BAGOS JAMBO - 4 FRUTAS KIWI - 1 MÉDIO
LARANJA - 1 PEQUENA LIMA DA PÉRSIA - 1 PEQUENA
MAÇÃ - 1 MÉDIA MAMÃO - 1 FATIA PEQUENA
MANGA - 1 PEQUENA MARACUJÁ - 1 PEQUENO
MELANCIA - 1 FATIA MÉDIA MELÃO - 1 FATIA PEQUENA
MORANGO - 10 FRUTASNECTARINA - 1 MÉDIA NÊSPERA - 3 PEQUENAS
PASSA - 1 COLHER DE SOPA PERA - 1 PEQUENA
PÊSSEGO - 1 MÉDIO PITANGA - MEIO COPO
ROMÃ - MEIA FRUTA SALADA DE FRUTAS - 3 COLHERES
TÂMARA - 2 MÉDIAS TANGERINA - 1 MÉDIA
UVA - 10 FRUTAS

Grupo 4
CEREAIS, PÃES, BISCOITOS E MASSAS

AIPIM - 1 PEDAÇO MÉDIO ARROZ - 2 COLH. DE SOPA


AVEIA - 3 COLH. DE SOPA BATATA DOCE - 1 PEQUENA
BATATA INGLESA - 1 MÉDIA BISCOITO CREAM CRACKER - 2
BOLACHA ÁGUA E SAL - 2 CORN FLAKES - 1 COLH. DE SOPA
EMPADA - 1 PEQUENA FARINHA - 2 COLH. DE SOPA
FAROFA - 1 COLH. DE SOPA FEIJÃO - 4 COLH. DE SOPA
GERME DE TRIGO - 3 COLH. DE SOPA GRÃO DE BICO - 2 COLH. DE SOPA
LASANHA - 2 COLH. DE SOPA LENTILHA - 2 COLH. DE SOPA
MACARRÃO - 2 COLH. DE SOPA MAISENA - 1 COLH. DE SOPA
MILHO VERDE - 4 COLH. DE SOPA NHOQUE - 2 COLH. DE SOPA
PANQUECA - 1 PEQUENA PÃO DE CENTEIO - 1 FATIA
PÃO DE FORMA - 1 FATIA PÃO DE GRAHAM - 1 FATIA
PÃO INTEGRAL - 1 FATIA PÃO FRANCÊS - MEIO PEQ.
PASTEL - 1 MÉDIO PIPOCA - 1 PACOTE PEQ.
PIRÃO - 2 COLH. SOPA PIZZA - 1 FATIA PEQUENA
TORRADA - 6 DAS PEQUENAS TREMOÇOS - 3 COLH. DE SOPA

Grupo 5
CARNES, QUEIJOS E OVOS

CABRITO - 1 TERÇO DE BIFE CAMARÃO - 2 MÉDIOS


CARNEIRO - 1 TERÇO DE BIFE CARNE SECA - 1 PEDAÇO PEQUENO
CAVIAR - 1 COLHER DE SOBREMESA COELHO - MEIO BIFE
DOBRADINHA - 2 COLH. DE SOPA FÍGADO - 1 TERÇO DE BIFE
FONDUE DE QUEIJO - 25 GRAMAS FRANGO - 1 TERÇO DE BIFE

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página Nr. 75/178
LAGOSTA - 1 PEDAÇO PEQUENO LINGUIÇA - 1 PEDAÇO PEQUENO
LULA - 1 PORÇÃO MÉDIA MEXILHÃO - 1 PORÇÃO PEQUENA
MORTADELA - 2 FATIAS FINAS OSTRAS - 1 PORÇÃO PEQUENA
OVO DE CODORNA - 3 UNIDADES OVO DE GALINHA - 1 UNIDADE
PAIO - 1 PEDAÇO PEQUENO PATO - 1 TERÇO DE BIFE
PERU - 1 TERÇO DE BIFE PEIXE - MEIA POSTA PEQUENA
POLVO - 1 PORÇÃO MÉDIA PRESUNTO MAGRO - 2 FATIAS
QUEIJO - 1 FATIA QUEIJO COTTAGE - 2 COLHERES
REQUEIJÃO - 1 COLHER DE SOPA RICOTA - 2 FATIAS FINAS
SALAME - 1 FATIA PEQUENA SALSICHA - 1 PEQUENA
SIRI - 3 DE TAMANHO MÉDIO VACA - 1 TERÇO DE BIFE

Grupo 6
GORDURAS

AZEITE - 1 COLHER DE CHÁ AZEITONA - 4 MÉDIAS


BACON - 1 FATIA PEQUENA CREME DE LEITE - 1 COLH. DE SOPA
MAIONESE - 1 COLHER DE CHÁ MAIONESE LIGHT - 2 COLH. DE CHÁ
MANTEIGA - 1 COLHER DE CHÁ MARGARINA - 1 COLHER DE CHÁ
ÓLEO VEGETAL - 1 COLHER DE CHÁ PATÊ - 1 COLHER DE CHÁ

Grupo 7
LEITES

COALHADA - MEIO COPO IOGURTE NATURAL - 1 COPO


IOGURTE DIET - 2 FRASCOS LEITE DESNATADO - 1 COPO
LEITE INTEGRAL - MEIO COPO LEITE INTEGRAL EM PÓ - 1 COLHER
PUDIM DIET - 1 PEQUENO SORVETE DIET - 1 BOLA

Grupo 8
BEBIDAS, CONDIMENTOS E DIETÉTICOS DE BAIXÍSSIMO TEOR CALÓRICO

ADOÇANTES ALHO CAFÉ CANELA


CHÁ CEBOLINHA COMINHO CRAVO
ERVA-DOCE GELATINA DIETÉTICA HORTELÃ LIMÃO
LIMONADA MATE ORÉGANO PIMENTA
REFRIG. DIETÉTICOS SAL SALSA VINAGRE

A unidade básica da tabela é chamada porção, que é a quantidade de cada alimento listado em um
grupo. Um exemplo: Se o seu programa alimentar tem no almoço 2 porções do grupo 4, você poderá consumir:

1 colher de arroz + 1 colher de farofa ou


2 fatias de pão de forma ou
batata inglesa + 1 panqueca e assim por diante.

Se no almoço você também tem 3 porções do grupo 5, pode comer além daqueles alimentos:

1 bife de tamanho médio (cada porção corresponde a um terço de bife) ou


1 posta de peixe + 1 ovo ou
2 fatias de queijo (cada porção dá para 1 fatia) + 2 fatias de presunto e assim por diante.

Não devem ser trocados alimentos de grupos diferentes. A troca de um alimento do grupo 4 por um
alimento do grupo 5, por exemplo, implicaria em uma redução do teor de carboidratos da refeição, podendo desregular
os mecanismos cerebrais de regulação do apetite. Por outro lado, pode-se transferir um determinado alimento de uma
refeição para outra, desde que seja mantida em todas as refeições pelo menos uma porção dos grupos 3 ou 4, que
contêm mais carboidratos.

Apenas os alimentos listados nos grupos 1 e 8 podem ser consumidos à vontade, já que seu teor calórico
é considerado desprezível. Mesmo nas refeições onde estes grupos não forem mencionados, os alimentos neles contidos
podem ser consumidos sem restrições.

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página Nr. 76/178
Os grupos 1 e 2 apresentam a vantagem de acrescentar fibras à alimentação, além de serem pobres em
calorias.

Os alimentos do grupo 3 são as frutas, constituídas basicamente de carboidratos. Não está relacionado o
abacate, por possuir um elevado teor de gordura.

Também os alimentos do grupo 4 são constituídos principalmente por carboidratos. Cuidado com as
massas e pizzas, porque na cobertura ou no molho elas podem carregar grandes quantidades de gorduras e calorias.

No grupo 5 estão listados os alimentos constituídos por proteínas e gorduras. O teor de gorduras, no
entanto, é variável. Os queijos brancos, como a ricota, o cottage e o próprio queijo tipo Minas são menos gordurosos
que os outros. Também as carnes brancas são menos gordurosas que as vermelhas. Cuidado com a pele dos peixes e do
frango, porque é onde se armazena a gordura. Crustáceos como o camarão e a lagosta são ricos em colesterol, assim
como a gema dos ovos. Sempre que possível as carnes devem ser consumidas grelhadas, assadas ou cozidas, já que a
fritura as torna mais gordurosas.

O grupo 6 é o das gorduras. Deve ser evitado na medida do possível.

No grupo 7 estão o leite e seus derivados. Por serem menos gordurosos, deve-se dar preferência aos
desnatados.

No grupo 8 estão listados vários alimentos, temperos e bebidas cujo teor calórico é desprezível. Apesar
de não engordarem, seu consumo excessivo pode trazer outros males à saúde. O café, por exemplo, pode causar insônia
quando ingerido em demasia, enquanto os refrigerantes e temperos podem levar a problemas gástricos.

As bebidas alcoólicas estão listadas na tabela abaixo, com seus respectivos teores calóricos. Elas não
podem substituir nenhum alimento de outro grupo, porque seu valor nutritivo não é o mesmo.

Grupo 9
BEBIDAS ALCOÓLICAS

BEBIDA QUANTIDADE VALOR CALÓRICO


Cachaça 1 dose de 50 ml 120 Kcal
Cerveja 1 copo com 300 ml 140 Kcal
Champanhe 1 copo com 100 ml 110 Kcal
Conhaque 1 copo com 50 ml 120 Kcal
Gim 1 copo com 50 ml 130 Kcal
Rum 1 copo com 50 ml 120 Kcal
Uísque 1 copo com 50 ml 120 Kcal
Vinho branco seco 1 copo com 100 ml 90 Kcal
Vinho branco doce 1 copo com 100 ml 140 Kcal
Vinho tinto 1 copo com 100 ml 70 Kcal
Vodka 1 copo com 50 ml 120 Kcal

Grupo 10
DOCES

O teor calórico dos doces é muito variável, dependendo principalmente do seu conteúdo de gorduras.
Na tabela abaixo você encontra o teor calórico médio de alguns doces mais consumidos pelos brasileiros.

DOCE QUANTIDADE VALOR CALÓRICO


BALA 1 UNIDADE 20 kCAL
BANANA CARAMELADA 1 UNIDADE 450 kCAL
BIS 1 UNIDADE 40 KCAL
BOLO DE FESTA 1 FATIA 200 kCAL
BOMBA DE CHOCOLATE 1 UNIDADE 200 KCAL
BOMBOM 1 UNIDADE 120 kCAL
BRIGADEIRO 1 UNIDADE 50 kCAL
CHICLETE 1 UNIDADE 20 kCAL
CHOCOLATE EM BARRA 1 PEQUENO 160 kCAL
DOCE DE LEITE 2 COLHERES DE SOPA 200 kCAL

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página Nr. 77/178
GELATINA 1 CAIXA 70 kCAL
GELÉIA 1 COLHER DE SOBREMESA 30 kCAL
GOIABADA 1 PEDAÇO 80 KCAL
MILK SHAKE McDonald's 1 UNIDADE 340 kCAL
MOUSSE DE CHOCOLATE 1 POTE PEQUENO 200 KCAL
PÊSSEGO EM CALDA 1 METADE 80 kCAL
PUDIM 1 FATIA 250 kCAL
SONHO 1 UNIDADE 150 KCAL
SUNDAE (McDonald's) 1 UNIDADE 260 kCAL
SUSPIRO 1 GRANDE 70 KCAL
TORTA 1 FATIA 250 kCAL

Sempre que possível, recomenda-se dar preferência aos dietéticos, que não contêm açúcar. É importante
lembrar, no entanto, que muitos deles, mesmo não contendo açúcar, são altamente calóricos, como é o caso dos
chocolates.

Cardápio com 800 Kcal

REFEIÇÃO PORÇÕES
Desjejum (café da manhã) 1 do grupo 4 + 1 do grupo 5
Colação (lanche da manhã) 1 do grupo 3
Almoço 1 do grupo 2 + 2 do grupo 5 + 1 do grupo 4
Lanche 1 do grupo 3
Jantar 1 do grupo 2 + 3 do grupo 5 + 1 do grupo 4
Ceia 1 do grupo 3

Cardápio com 1.000 Kcal

REFEIÇÃO PORÇÕES
Desjejum (café da manhã) 1 do grupo 4 + 1 do grupo 5 + 1 do grupo 3
Colação (lanche da manhã) 1 do grupo 3
Almoço 1 do grupo 2 + 3 do grupo 5 + 1 do grupo 4 + 1 do grupo 3
Lanche 1 do grupo 4 + 1 do grupo 5
Jantar 1 do grupo 2 + 3 do grupo 5 + 1 do grupo 4
Ceia 1 do grupo 3

Cardápio com 1.200 Kcal


REFEIÇÃO PORÇÕES
Desjejum (café da manhã) 1 do grupo 7 + 1 do grupo 4 + 1 do grupo 5 + 1 do grupo 3
Colação (lanche da manhã) 1 do grupo 3
Almoço 1 do grupo 2 + 3 do grupo 5 + 1 do grupo 4 + 1 do grupo 3
Lanche 1 do grupo 4
Jantar 2 do grupo 2 + 3 do grupo 5 + 1 do grupo 4 + 1 do grupo 6 + 1 do grup 3
Ceia 1 do grupo 3
Cardápio com 1.500 Kcal
REFEIÇÃO PORÇÕES
Desjejum (café da manhã) 1 do grupo 7 + 1 do grupo 4 + 1 do grupo 5 + 1 do grupo 3
Colação (lanche da manhã) 1 do grupo 3
Almoço 2 do grupo 2 + 3 do grupo 5 + 2 do grupo 4 + 1 do grupo 3
Lanche 2 do grupo 4 + 1 do grupo 5
Jantar 2 do grupo 2 + 1 do grupo 6 + 3 do grupo 5 + 2 do grupo 4 + 1 do grup 3
Ceia 1 do grupo 3
Cardápio com 1.800 Kcal
REFEIÇÃO PORÇÕES
Desjejum (café da manhã) 1 do grupo 7 + 1 do grupo 4 + 1 do grupo 5 + 1 do grupo 3
Colação (lanche da manhã) 1 do grupo 3
Almoço 2 do grupo 2 + 4 do grupo 5 + 2 do grupo 4 + 1 do grupo 3
Lanche 2 do grupo 4 + 1 do grupo 5 + 1 do grupo 3
Jantar 2 do grupo 2 + 4 do grupo 5 + 2 do grupo 4 + 1 do grupo 6 + 1 do grup 3
Ceia 1 do grupo 7 + 1 do grupo 3

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página Nr. 78/178
Obs.: Os grupos 1 e 8 podem ser utilizados à vontade, em qualquer horário e em qualquer cardápio.

3º Dia de entrevistas com o usuário: Conversa com o nutricionista


O que é o peso ideal ? Peso ideal é aquele que propicia o máximo de saúde. O conceito atual de saúde,
segundo a Organização Mundial de Saúde é "Estado de bem-estar físico, mental e social". Estes 3 elementos devem ser,
portanto, valorizados por quem tenta definir o peso ideal de um determinado indivíduo. Métodos de cálculo do peso
ideal. O cálculo do peso ideal deveria ser feito, idealmente, através da medida do percentual de gordura corporal, que
pode ser obtida por métodos como a bioimpedância ou pela medida das dobras cutâneas. Como na maioria dos casos
estes métodos não estão disponíveis, o índice de massa corporal tem sido largamente utilizado para determinar a faixa
ideal de peso. O Índice de Massa Corporal: Este índice pode ser obtido dividindo-se o peso corporal pelo quadrado da
altura em metros.

Por exemplo: uma pessoa que pese 67 Kg e meça 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 não discriminar os componentes gordo e magro da massa corporal total, é o


método mais prático para avaliar o grau de risco associado à obesidade. Os estudos populacionais
mostram que o menor 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 são
rotulados como "sobrepesados" ou "com excesso de peso". Entre 30 e 35 considera-se "obesidade
leve", entre 35 e 40 "obesidade moderada" e acima de 40 "obesidade mórbida". Abaixo dos 20
Kg/m2 também se observam maiores índices de mortalidade, principalmente por doenças
pulmonares e desnutrição. Estão nesta faixa, por exemplo, os portadores de 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 gráfico que mostra o risco de morte de acordo com o índice de massa corporal.

As tabelas de peso e altura

Apesar de muito sujeitas a erros, as tabelas de peso e altura ainda são largamente
utilizadas em todo o mundo para estimar-se o peso ideal. Elas são derivadas de dados obtidos por
companhias de seguro americanas, que as desenvolveram a partir da observação de dados de
mortalidade e longevidade de sua população segurada. Os pesos chamados de "ideais" são, na
verdade, médias das faixas de peso ideal para cada grupo etário analisado. As tabelas abaixo
mostram os pesos de referência para cada um destes grupos. Reparem que na tabela dos indivíduos
mais idosos estes pesos já são bem mais altos.

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página Nr. 79/178
Pesos de referência para adultos entre 21 e 55 anos

ALTURA (em metros) PESO para homens (em Kg) PESO para mulheres (em Kg)
1,47 - 51,7
1,50 - 52,8
1,52 - 53,9
1,55 - 55,3
1,57 60,3 56,7
1,60 61,2 58,0
1,63 62,4 59,4
1,65 63,5 60,8
1,68 64,9 62,1
1,70 66,2 63,5
1,73 67,6 64,9
1,75 68,9 66,2
1,78 70,3 67,6
1,80 71,9 69,0
1,83 73,9 -
1,85 75,3 -
1,88 76,9 -
1,91 78,9 -

Pesos de referência para adultos entre 55 e 74 anos

ALTURA (em metros) PESO para homens (em Kg) PESO para mulheres (em Kg)
1,47 - 57
1,50 - 62
1,52 - 65
1,55 - 64
1,57 68 64
1,60 70 65
1,63 71 66
1,65 72 67
1,68 74 66
1,70 78 72
1,73 78 70
1,75 77 72
1,78 80 73
1,80 84 -
1,83 81 -
1,85 88 -
1,88 95 -

Obs. Os métodos utilizados para o cálculo do peso ideal de adultos não são adequados para
indivíduos em fase de crescimento.

Observações finais

Além dessas três entrevistas foi constatado que o SPA Antes & Depois ainda mantêm

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página Nr. 80/178
alguns dados importantes:

Manutenção periódica da Pasta do Cliente que contém:


Dados para o envio de eventual correspondência de propaganda e promoções.
Dependendo do plano adotado - acompanhamento nutricional e envio de um cardápio
semanal personalizado e completo, baseado no plano de calorias indicado pelo nutricionista.
Histórico dos planos realizados pelo cliente no SPA.

Não são aceitos clientes menores de 21anos e maiores de 74 anos de idade.

Descontos para clientes com re-incidência, baseado na seguinte tabela:


5% primeira re-incidência.
10% segunda re-incidência.
15% terceira re-incidência.
Aumento de 1% nas próximas re-incidências até um máximo de 20%.

Os planos da empresa são:


Plano A (Anti-Stress) - 3 Dias.
Plano B (Reeducação) - 1 Semana com acompanhamento periódico de 3 meses.
Plano C (Completo) - 1 mês.
Plano D (Especial de Reeducação) - 4 Dias com acompanhamento periódico de 3
meses.

A divisão do capital da empresa é realizada em cima do preço final do cliente, e dividido da


seguinte maneira:
20% para o médico-presidente da empresa.
40% para o coordenador dos planos alimentares.
10% para o nutricionista (caso seja efetuado os planos B ou D ).
30% (ou 40 % - caso seja efetuado os planos A ou C) para despesas gerais.
e todo final de mês é criado um relatório de fechamento financeiro com a situação da empresa e a
divisão do capital do mês.

Finalmente

Prontinho na próxima apostila, criaremos nosso projeto físico baseado em tudo o que
foi feito aqui, o projeto físico servirá para montarmos nossa base de dados e termos uma idéia qual
o caminho que seguirá nosso sistema.

Então aconselho a você que releia as entrevistas com calma e começe a pensar não
apenas como uma chave de fenda mas como a caixa de ferramentas completa que não só senta na
máquina e começa a programar mas analisa e verifica o que o usuário realmente necessita.

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página 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 versão Client/Server Suite
BDE 5.00
MS-Access 97

Arquivos trabalhados juntos com esta apostila:

BASICO.MDB

Prefácio
Salve, espero que todos vocês tenha gostado do rumo que tomou o nosso curso, também espero que assim
fique mais interessante e atual o uso de uma linguagem tão complexa como é o Delphi.

Vale uma pequena observação aqui (copiada da apostila anterior, para ficar bem claro): Apesar de todos os
dados se aproximarem o máximo possível da realidade todas as empresas que serão abordadas e criadas aqui serão
totalmente fictícias, caso numa dessas loucuras da vida a empresa exista (cada dia é criado uma nova mesmo) todos os
dados foram criados exclusivamente por imaginação e não existe nenhuma relação com a realidade.

Já estamos com todos os dados da nossa empresa na mão, agora vem a fase que antigamente era designada
exclusivamente para a nata da informática conhecida por: Analistas de Sistemas, quantas vezes não sonhamos com
esse maravilhoso e imponente título. Bem, uma coisa devemos aprender: "Atualmente quem na área de informática não
chuta nas onze, não se dá muito bem e acaba vendendo cachorro-quente na porta da Igreja", então quem acha que
aprendendo Delphi, ou qualquer outra ferramenta de desenvolvimento, e a única coisa que vai ter que fazer daqui para
frente, são programas já prontos e detalhados logicamente sem ter que usar qualquer conhecimento de um Analista de
Sistemas, pode começando a pensar seriamente a mudar de profissão.

É óbvio que experiência nunca vou conseguir passar para todos, principalmente porque esta vida é um eterno
aprendizado, mas vou tentar dar algumas dicas para vocês começarem a pegar o embalo.

Brain-Storm
Na entrevista ouvimos algumas palavras chaves, então primeiramente, pegue um quadro-negro e juntamente
com sua equipe de desenvolvimento tente fazer um resumo de tudo o que foi dito nas entrevistas iniciais:

Cadastro organizado e completo de cada cliente;


Criação dos programas alimentares;
Acompanhamento do Cliente;
Cada cliente precisa de um determinado programa;
Existem fórmulas para se calcular a quantidade de calorias, este método é muito falho;
O paciente relata na consulta e sempre haverá uma maneira de planejar uma alimentação adequada;
Existe uma tabela de alimentos;
Existem cardápios formados através de uma regra;
O Índice de Massa Corporal pode ser obtido dividindo-se o peso corporal pelo quadrado da altura em metros;
Existe uma tabela para o Índice de Massa Corporal;
Existe uma tabela de Descontos para clientes re-incidentes;
Existem duas divisões entre 21 - 55 e 55 - 74 anos;
Excluem-se menores de 21 e maiores de 74 anos; e
Cálculos de receitas e despesas através de demonstrativos mensais e resumo anual.

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página Nr. 82/178
Está técnica é melhor quando a equipe é formada por três ou mais pessoas, uma coisa se você é do tipo que
detesta o trabalho em grupo, infelizmente você será um péssimo Analista, pois 98% do trabalho é feito com discussões
em grupo, debates e análises com a equipe e com o usuário, validando e revalidando periodicamente todos os dados
levantados, até que o sistema esteje entregue e pronto.

O método que mostrei acima é conhecido por Brain-Storm (Tempestade Cerebral) a idéia é que você recolha
os dados mais importantes e discuta em cima deles, existem óbvio vários métodos de análises, mas pessoalmente,
considero este o melhor, adote aquele que você sinta mais a vontade.

Preparação da Modelagem dos Dados


A próxima fase é conhecida como Modelagem dos Dados, aqui vamos definir nossas entidades (antigamente
chamariamos de tabelas, mas prefiro adotar uma linguagem mais atual), faça um jogo com você mesmo antes de ler os
atributos de cada entidade (campos) propostos por mim, tente montar seus próprios atributos:

Entidade Cliente

Atributos: CPF, Nome, Endereço, Bairro, CEP, Cidade, Estado, eMail, Telefones de contato, Altura, Peso
medido e data de nascimento.

Entidade Alimento

Atributos: Número do Grupo, Nome do Alimento e Quantidade Permitida

Entidade Pasta do Cliente

Atributos: CPF do Cliente, Data, Plano Adotado, Quantidade de Calorias, Observações do tratamento, Data de
pagamento, Valor Total e Desconto concedido

Entidade Resumo Mensal

Atributos: Mes e Ano, Valor do Médico, Valor Coordenador, Valor Nutricionista e Valor Despesa

☞Importante - Dicas Quentes:


- Não dê o nome de uma entidade no plural, por exemplo Clientes, Alimentos pois além de gastar um byte a
mais para o banco de dados, está errado pois sempre nos referimos a um único registro da entidade.
- Pense na entidade como única, note que a entidade Cliente tem o atributo Cidade, o que pode futuramente
virar uma outra entidade, mas sempre deixe isso para a fase de normalização.
- Não invente entidades ou atributos que não fazem parte do que foi levantado com os usuários, é lógico que
os clientes devem ter uma profissão, mas isso não interessa para nosso sistema, se achar que interessa discuta primeiro
com o usuário.
- Evite sempre códigos estranhos ao cliente para definir Chaves Únicas (aquelas que servirão de índices
primários), primeiro procure por campos únicos na própria entidade, na entidade Cliente podemos usar o CPF.

Modelo Físico
Terminada a fase de Preparação da Modelagem, é iniciado todo o trabalho para a construção de um modelo
físico, ou seja, como realmente vai ficar implantado nossa base de dados, neste momento valem todas as regras de
Normalização e outras técnicas aprendidas em qualquer bom Curso de Análise ou Livros disponíveis no mercado,
como minha função é ensinar o Delphi não vou me ater a estes detalhes então vamos dar uma olhada no Modelo Físico
pronto e depois farei alguns comentários necessários:

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página Nr. 83/178
Bem aqui valem algumas regras que aprendi ao longo do tempo:

1. Formação dos Nomes dos Atributos:


O maior trabalho de uma empresa de desenvolvimento é formar o nome dos atributos, pois sabemos que eles
influenciarão no nome das variáveis, assim ao longo do tempo, e após vários aperfeiçoamentos cheguei a uma regra que
venho adotando:

XXX_YYYYY - aonde:

XXX - Três casas representativas do atributo, Ex: NOM - Nome, NUM - Número, VAL - Valor, DAT - Data, DES -
Descrição, ...
YYYYY - Complemento do Atributo, Ex: Nome da Própria Entidade, Nomes Significativos, ...

2. Quanto ao Tipo do Atributo:


Uma dica que aprendi a muito tempo ainda vale até hoje, escolha os tipos com lógica e utilidade, quer um
exemplo então responda as seguintes perguntas:

O que é mais útil e lógico um atributo CPF (NUM_CPF) ser Texto com 11 casas ou um Inteiro ?
Se vamos fazer cálculos com a Altura do Cliente (ALT_CLIENTE) então definiremos o atributo como Texto ou
Inteiro com casas decimais ?
Se a observação do clientes (OBS_PASTA) pode variar muito o que é mais prático um campo Texto Variável ou um
Texto fixo de 300 casas ?
Todas as quantidades devem ser numéricas mesmo que não se façam cálculos com elas ? E como fica a Quantidade de
Caloria (QTD_CALORIA)

3. Escolha das Chaves:


Vou bater na mesma tecla pois acho ela importante, escolha chaves fáceis de lembrar, no último caso escolha
os tipos de atributos automáticos, como foi o caso da entidade ALIMENTO que acabei optando por uma chave Auto
Incremental (1,2,3,4,5...)

☞Importante - Não utilize, mesmo que o banco permita, tipos de atributos AUTO INCREMENTAL pois esses

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página Nr. 84/178
campos não permitem sua modificação ou seu controle, utilize campos INTEIROS e faça os cálculos do maior através
de uma função genérica.

Módulos Funcionais
A última fase da Analise de um sistema é a documentação de todas as funções ou se você preferir pode chamar
de Módulos Funcionais, estes módulos normalmente são divididos em cadastros, movimentações, consultas e
relatórios impressos, fazendo isso e conseguindo a validação do usuário, você evitará muitos aborrecimentos
posteriores, tais como ser mal interpretado ou de causar falsas expectativas, e esta fase também ajudará na elaboração
das Opções do Menu.

Cadastro

Cidade: terá a função de editar e coordenar o arquivo de cidades


Grupo: terá a função de editar e coordenar o arquivo de grupos
Alimento: terá a função de editar e coordenar o arquivo de alimentos
Cliente: terá a função de editar e coordenar o arquivo de clientes

Movimentação

Entrada do Cliente: recepção para os clientes e montagem e definição dos planos nas pastas
Saída do Cliente: fechamento da conta e da pasta do cliente
Massa Corporal: Cálculo da Massa Corporal e pesagem atual de determinado cliente

Consulta

Pasta do Cliente: Verificação de determinado cliente, com gráficos sobre peso e massa coorporal
Verificação do Caixa Mensal: Cálculo da arrecadação de um determinado mês

Relatório

Correspondência: envio de corrêspondencia a clientes


Cardápio: montagem de determinado cardápio diário baseado no número de calorias informadas
Divisão das Contas Mensal: fechamento das contas mensais e divisão dos lucros
Analítico das Contas Anual: resumo anual de toda a divisão efetuada

Finalmente
Prontinho agora resta mostrar para o nosso usuário ter o carimbo de aprovação, não se esquecendo de
especificar prazos para a conclusão de cada módulo funcional descrito.

Na próxima apostila, começaremos a programar nosso sistema criando o menu e as telas de apoio.

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página 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 versão Client/Server Suite
BDE 5.00
MS-Access 97

Arquivos trabalhados juntos com esta apostila:

PESO.HLP
IM0.BMP até IM10.BMP

Prefácio
Salve, bem hoje pretendo tratar aqui de um tema da maior importância, também que gera a maior polêmica
entre qualquer grupo de mais de um programador, Menus. Não me refiro a Cardápios, e sim Menus de Sistemas, ou
popurlamente chamados de Telas de Entrada, por isso mesmo que são os responsáveis pela maior polêmica.

Um Menu está para um sistema, assim como a Sala está para a casa, pegue um sistema, o mais prático o
possível, cheio de "nove horas", entre outras dezenas de outras vantagens, e acrescente nele um Menu horroroso que só
quem o programou entende e depois de um mês nem ele mais.

Esta apostila (tão aguardada) pode parecer simples a primeira vista, mas garanto-lhes que não é muito simples
projetar uma casa sem começar pela sala.

Tipos de Sistema SDI ou MDI ?


Vou falar rapidamente dos tipos de sistemas, existem basicamente dois tipos de sistemas:

MDI (multiple document interface) - é aquele que permite a abertura de várias janelas, caracterizando-as como filhas
que são exibidas dentro do contexto da janela principal, pode ser aberto inclusive diversas cópias de uma mesma janela.
Existindo uma intensa movimentação entre elas. Muito usado em Editores de texto e Planilhas de cálculos.

SDI (single document interface) - é aquele que permite a abertura de uma só janela de cada vez inibindo atuações nas
áreas fora da mesma, não existindo nenhuma coorelação entre elas. Muito usados em sistemas de grande porte.

Já deu para perceber a diferença básica entre os menus que são construídos para cada sistema, no primeiro
caso o Menu deve ser máximizado para comportar as janelas filhas, no segundo caso o Menu pode ser uma simples
janela que pode ser colocada no canto superior (como a barra do Office), se você se complicou com os dois sistemas
imaginemos um Sistema de Estoque, aonde existe um formulário que é a Fatura podemos tratá-la da seguinte maneira:

No sistema MDI - A janela da Fatura pode ser aberta diversas vezes, ou seja no meio de uma Fatura, poderemos
iniciar uma nova, ou então entrar na janela de Material para cadastrar (ou descobrir o código) de um determinado
material.

No sistema SDI - A janela da Fatura é aberta e nela permanece (salvo que exista um botão, ou outro meio, para
chamar uma outra janela) até que a Fatura seja encerrada.

Também você deve ter notado que existem diferenças bárbaras em ambos os sistemas, vamos analisar as
desvantagens:

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página Nr. 86/178
No sistema MDI - O usuário pode começar a abrir diversas janelas de Faturas, ou um número excessivo de janelas,
causando assim o estouro da área de memória, lembre-se que cada formulário aberto vai para a área de memória, aquela
área baixa (do 640 Kb) então nem adianta aumentar a memória, vai chegar num momento que o sistema simplesmente
não aguentará e seu usuário ganhará uma linda tela azul.

No sistema SDI - Se o usuário precisar de cadastrar (ou descobrir o código de) um determinado material, ele precisará
cancelar a Fatura fechar a janela, entrar na janela de Material, cadastrar ou pesquisar , fechar essa janela e voltar para a
janela de Fatura e começar a digitar a Fatura tudo novamente, a menos que o Programador tenha lembrado de
colocar um botão para que ele acesse a tela de material.

Pessoalmente eu prefiro meus sistemas no modo SDI, apesar de achar o MDI tentador, primeiro muitos dos
meus usuários são leigos, eu não teria como explicar-lhes (às cinco da manhã de sábado normalmente) que a aplicação
deles caiu porque tinha vinte clientes na loja e ele resolveu abrir vinte janelas de Fatura, mas você poderá optar por
qual sistema deseja adotar, pois futuramente nosso próximo projeto será um sistema totalmente MDI.

Tipos de Menus
Ficou comprovado no ambiente Windows, também em outros ambientes, que o Menu que melhor funciona é
aquele que abre de cima para baixo, estou me referindo dentro do Delphi ao 1o. Objeto da 1a. Palheta, ou seja o objeto
MainMenu, não é a toa que ele é o primeiro, seu irmão mais novo é o PopMenu, aquele menuzinho rápido que temos
todas as vezes que clicamos com o botão direito em cima de um objeto.

Já vi muitos Menus interessantes, dos mais diversos tipos, um deles inclusive imita o menu do botão Iniciar
do Windows 95, mas pessoalmente fico com os menus Pull-Down (é assim que são chamados) primeiro porque em
qualquer aplicação do Windows (ou outro ambiente) eles estão lá, segundo porque o usuário é acostumado com eles
(desde que se sigam regras) e terceiro porque são mais simples de se programarem.

Desde a primeira versão do Pascal for Windows que a Borland (hoje Inprise) lançou esse tipo de menu, e
sempre sua programação foi muito superior aos seus concorrentes, além de muito fácil, abro um desafio aqui, peguem
uma cópia dos VB's (ou FOX, Access, CA-Clipper) ou e tentem criar um menu lá, agora peguem o velho Pascal for
Windows e façam a mesma coisa, e me digam o que acharam.

O Delphi, seguiu uma tradição da família, seu menu é tão fácil de programar que até mesmo me assusta,
vamos lá, sigam o mestre:

1. Se você ainda não fez crie um diretório que abrigará seu sistema. (para padronizar comigo crie:
C:\CursoDelphi\Peso)

Antes de começarmos a criar nossos menus, deixe-me dizer-lhes um detalhe a mais, a partir do MS-Office 97,
foram colocadas figurinhas no tamanho de 16x16 nos menus, e parece que com o Windows 98 isto virou um padrão
oficial dos Menus, então na Component Pallete localize uma página chamada Win32 e dentro dessa página de um
clique no objeto ImageList (acredito que seja o terceiro) e dê um clique no Form. (automaticamente o Delphi criou um
botãozinho com o desenho dele. Para o Delphi é assim que ficam todos os objetos que são invisíveis durante o tempo
de execução, ou seja tanto faz em qual posição que você o coloque, quando começar a rodar seu sistema este objeto
ficará invisível). Dê um duplo clique no objeto criado e vamos entrar na ImageList, clique no botão Add e vá
adicionando as imagens enviadas na ordem: primeiro a IM0.BMP, depois a IM1.BMP e assim sucessivamente, veja a
figura:

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página Nr. 87/178
2. Abra o Delphi e na Component Pallete localize uma página chamada Standard e dentro dessa página de um clique
no objeto MainMenu (acredito que seja o primeiro) e dê um clique no Form. (automaticamente o Delphi criou um
botãozinho com o desenho dele, mais um objeto invisível). Dê um clique simples em cima do objeto criado e altere a
seguinte propriedade:

Images: ImageList1 (Define um objeto ImageList para ser utilizado como repositório de imagens).

3. Vamos agora entrar na Menu Editor, dê agora um clique duplo em cima do MainMenu1 criado, agora é só começar
a construir seu Menu, este é um objeto que sou apaixonado vamos a algumas propriedades:

3.0.Antes deixe-me avisá-lo que cada quadradinho criado representa um novo objeto (pertencente a classe
tMenuItem)
3.1.BitMap: A partir do MS-Office 97, foram colocadas figurinhas no tamanho de 16x16 nos menus, e parece
que com o Windows 98 isto virou um padrão oficial dos Menus, então aqui você insere este tipo de figura.
3.1.Break: permite que você crie um submenu lateral (utilize a opção mbBreak para o primeiro e
mbBarBreak para os filhos)
3.2.Caption: é o que o seu usário verá, a opção em si, utilize o caracter & para colocar atalhos nas opções (ex:
&Arquivo)
3.3.Check: permite que você crie uma marca no item de menu, assim você pode criar opções do tipo
habilitado ou não.
3.4.Default: permite que uma das opções de um dos itens do submenu fique em negrito.
3.5.GroupIndex: cria para um determinado Grupo de submenu um indice, uma marca, determinante, assim
você pode dizer os itens do grupo 1 estão desabilitados, os do grupo 2 estão habilitados e assim vai.
3.6.HelpContext: desloca automaticamente ao contexto selecionado ao ser chamado um arquivo de auxílio, se
o HelpContext for igual a 0 não envia para contexto nenhum.
3.7.Hint: Pequeno auxílio para o item do menu, mas essa propriedade deve ser visualizada através de um
objeto do tipo StatusBar (localizado na Palheta Win32)
3.8.Name: Todos os objetos tem que ter, me recuso a escrever sobre essa propriedade, vou deixar vocês na
dúvida.
3.9.RadioItem: Seleciona dentre um grupo (determinado pela propriedade GroupIndex) um único item do
menu, por exemplo um submenu assim: Cor de Fundo, items: Azul, Vermelho ou Verde.
3.10.ShortCut: Cria um atalho rápido através do menu, por exemplo CRTL+C ou CTRL+V
3.11.Tag: Outra propriedade, em conjunto com a propriedade Name, que aparece em todos os objetos,
independente da cor, raça ou credo, a Tag é uma variável inteira que você pode rotular para diversos usos como por
exemplo transformar em Invisível todos os objetos que possuam a Tag igual a 10 ou pintar a fonte de azul-marinho

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página Nr. 88/178
todos os objetos da Tag 5.
3.12.Visible: Permite que o objeto fique visível ou não em tempo de execução.

Prontinho com todas essas informações acredito que você já está pronto (e ansioso) para construir nosso menu. Vamos
lá então. Na primeira janelinha, ou se você prefere no primeiro Item de Menu altere as seguintes propriedades:

Caption - &Arquivo
Hint - Arquivos principais do sistema.

Assim que você pressionar o Enter vai formar mais duas novas janelas uma lateral a Arquivo e uma logo abaixo dele,
na janela abaixo, clique nela e altere as seguintes propriedades:

Caption: &Cadastro
Hint: Informações principais do sistema.
ImageIndex: 0

Assim que você pressionar o Enter vai formar uma nova janela uma abaixo a Cadastro, ainda com o curso posiciona
em Cadastro clique com o botão direito e no menu que aparecerá clique com o botão direito do mouse na opção
Create Submenu, e será criada um item de menu lateral, clique nesse novo item e altere as seguintes propriedades, e a
medida que for criando crie as demais opções:

Caption: &Cidade
Hint: função de editar e coordenar o arquivo de cidades

Caption: &Grupo
Hint: função de editar e coordenar o arquivo de grupos

Caption: &Alimentos
Hint: função de editar e coordenar o arquivo de alimentos

Caption: - (sinal de menos)

O resultado será uma barra de separação

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página Nr. 89/178
Caption: Cli&entes
Hint: função de editar e coordenar o arquivo de clientes

Volta para aquela área abaixo do cadastro e altere a propriedade

Caption: -

(Você não está enchergando ruim não é o traço de menos mesmo.) Isso produzirá o seguinte efeito:

E vamos a última opção deste submenu:

Caption: &Sair
Hint: Retorna ao Windows
ShortCut: Ctrl+S
ImageIndex: 10

Prontinho a subopção Arquivo ficou da seguinte maneira:

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página Nr. 90/178
☞Importante - As imagens aparecerão apenas fora do MenuEditor.
Agora crie os outros submenus segundo definimos na apostila anterior, não se lembra ? então aqui estão eles: (com os
respectivos Caption's, Hint's e caso tenham ImageIndex)

&Movimentação: informações constantes do sistema


&Entrada do Cliente: recepção para os clientes e montagem e definição dos planos (ImageIndex: 1)
&Saída do Cliente: fechamento da conta do cliente (ImageIndex: 2)
&Massa Corporal: Cálculo da Massa Corporal e pesagem atual do cliente (ImageIndex: 3)

&Consulta: visões on-line dos arquivos


&Pasta do Cliente: Verificação de determinado cliente, com gráficos sobre peso e massa coorporal
(ImageIndex: 4)
&Verificação do Caixa Mensal: Cálculo da arrecadação de um determinado mês

&Relatório: emissões na tela e em papel de um determinado momento dos arquivos


&Correspondência: envio de corrêspondencia a clientes (ImageIndex: 9)
Car&dápio: montagem de determinado cardápio diário baseado no número de calorias informadas
&Divisão das Contas Mensal: fechamento das contas mensais e divisão dos lucros
&Analítico das Contas Anual: resumo anual de toda a divisão efetuada
-
Configura &Impressora: Verifica qual a impressora que será utilizada para as impressões (ImageIndex: 5)

Au&xílio: chama o help on-line do sistema


&Conteúdo: Conteúdo do auxílio on-line (ImageIndex: 6)
&Tópicos do Auxílio: Chama os tópicos do Auxílio on-line (ImageIndex: 7)
Como &Usar o Auxílio: Como ultilizar o auxílio do windows (ImageIndex: 8)
-
&Sobre o Sistema: Informações sobre a execução do sistema

4. Dê uma salvadinha no seu projeto, para tanto, no menu vá em File | Save All...:

4.1. Aonde aparece Unit1.pas (o Delphi está se referindo do nome do formulário) mude para fMenu.PAS
4.2. Aonde aparece Project1.dpr (o Delphi está se referindo do nome do projeto - que será o nome do
executável final) mude para Peso.DPR

5. Pode sair do Menu Editor e testar seu menu. Clique agora em qualquer área vázia do formulário e vamos alterar
algumas propriedades:

5.1. Caption - Sistema de Controle do SPA - Antes & Depois


5.2. Name - F_Menu
5.3. WindowState - wsMaximized (fará com que o formulário se inicie no modo maximizado)

6. Na Component Pallete localize uma página chamada Win32 e dentro dessa página de um clique no objeto
StatusBar (acredito que seja o décimo quarto) e dê um clique no Form, foi criado tipo um painel na parte inferior do
formulário. Altere as seguinte propriedades:

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página Nr. 91/178
6.1. Name - BarraStat
6.2. Panels - Clique nos ... e clique três vezes no primeiro botãozinho (marcado com Add New (Ins) ) para
criar 3 subpainéis e altere as seguintes propriedades de cada um:

6.2.1. Para o primeiro:


Text - Bem Vindo...
Width - 500
6.2.2. Para o segundo:
Text - 99:99:99
Width - 60
Alignment - taCenter
6.2.3. Para o terceiro:
Text - Criado por: Curso de Delphi
Alignment - taCenter

7. Na Component Pallete localize uma página chamada System e dentro dessa página de um clique no objeto Timer
(acredito que seja o primeiro) e dê um clique no Form, foi criado tipo um quadradinho representando o objeto.

8. Na Component Pallete localize uma página chamada Dialogs e dentro dessa página 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 começar agora a programar nosso Menu. Primeiramente vamos programar a Barra de Status, note que
nela foram criados 3 painéis, ou três divisões, a primeira servirá para capturar os Hint de cada objeto do Menu
(tMenuItem), a segunda mostrará a hora atual do micro com a ajuda do objeto Timer, e a terceira será uma
propaganda fixa (isso é excelente quando queremos promover nossa SoftwareHouse). Para capturar os hint dos
objetos precisamos criar um procedimento particular que faça esse desvio, para tanto, aperte o botão F12 para ir para a
Code Editor e localize a seguinte parte:

private
{ Private declarations }
public

E coloque o seguinte código:

private
procedure MontaHint(Sender: TObject);
public

Agora abaixo da diretiva de compilação, insira o seguinte código:

implementation

{$R *.DFM}

procedure TF_Menu.MontaHint(Sender: TObject);


begin
BarraStat.Panels[0].Text := Application.Hint;
end;

Isto transferirá o Hint do objeto selecionado para o primeiro painel da Barra de Status, mas precisamos iniciar,
aperte a tecla F11 para chamar a Object Inspector e selecione o objeto F_Menu vá para a janela de eventos e dê um
duplo clique para o evento OnCreate e coloque o seguinte código:

procedure TF_Menu.FormCreate(Sender: TObject);


begin
Application.OnHint := MontaHint;
end;

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página 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 código:

procedure TF_Menu.Timer1Timer(Sender: TObject);


begin
BarraStat.Panels[1].Text := FormatDateTime('HH:MM:SS',Now);
end;

A cada segundo a hora será atualizada, não se preocupe que isso não afetará em nada o desempenho do
sistema. Bem agora vamos colocar alguns comandos básicos, inicialmente, aperte F12 para voltar a ter a visão do
formulário, e clique em Arquivo e Sair, coloque o seguinte código:

procedure TF_Menu.Sair1Click(Sender: TObject);


begin
Close;
end;

O comando Close fará com que o formulário seja encerrado, como é o próprio Menu do Sistema, então o
Sistema será encerrado. O comando para chamar a Configuração da Impressora é simples, auxiliado pelo objeto
PrinterSetupDialog, Clique em Arquivo e Configura Impressora e insira o seguinte código:

procedure TF_Menu.ConfiguraImpressora1Click(Sender: TObject);


begin
PrinterSetupDialog1.Execute;
end;

Como todos os objetos da Pallete Dialogs basta apenas chamar o método Execute do objeto que todo o
serviço está feito.

Codificando o Auxílio
Uma coisa interessante sobre o Delphi é como ele facilmente chama e executa arquivos .HLP, enquanto que
para muitos softwares isso é algo do outro mundo, no Delphi basta, simplesmente executarmos alguns comandos pré-
programados, além de que diversos objetos tem a propriedade HelpContext que permite que o arquivo de ajuda seja
acionado a partir da tecla F1 a partir de um tópico Pré-Definido.

Futuramente veremos como criar nosso arquivo de auxílio, mas, por enquanto vamos utilizar o arquivo
enviado juntamente com esta apostila.

A partir do Menu Principal vá em Project | Options... na página Applications altere as seguintes


propriedades:

Title: Controle do SPA


HelpFile: Peso.HLP

As palavras-chaves para o comando HelpCommand são:

Comando Parâmetro Passado Utilização


HELP_CONTEXT Inteiro longo, contendo o número do contexto. Mostra o auxílio a partir de tópico selecionado
identificado a partir do número do contexto
definido pela seção [MAP] do arquivo .HPJ

HELP_CONTENTS Ignorado. Normalmente passado 0. Mostra o conteúdo do primeiro tópico definido


pela seção [MAP] do arquivo .HPJ

HELP_SETCONTENTS Inteiro longo, contendo o número do contexto Determina a chamada do tópico determinado
que foi designado como tópico de conteúdo. através do uso da tecla F1

HELP_CONTEXTPOPUP Inteiro longo, contendo o número do contexto. Mostra uma janela Pop-Up com um tópico
particular identificado pelo número do contexto definido pela seção [MAP] do arquivo .HPJ

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página Nr. 93/178
HELP_KEY Ponteiro longo como uma string contendo o Mostra um tópico pesquisado em uma lista
tópico designado. de palavras chaves. Esta palavra chave deve ser
exatamente o texto procurado.

HELP_PARTIALKEY Ponteiro longo como uma string contendo o Mostra um determinado tópico através de uma
tópico designado. lista de palavras chaves. Se a palavra chave não
for encontrada posiciona na palavra fonêtica
mais perto.

HELP_MULTIKEY Ponteiro longo para uma estrutura de Mostra o tópico indentificado pela palavra
TMULTIKEYHELP. Esta estrutura específica de chave ou uma chave da tabela alternada.
caracteres e palavras chaves.

HELP_COMMAND Ponteiro longo, contém a macro para a execução Executa um macro help.

HELP_SETWINPOS Ponteiro longo para uma estrutura de Mostra um help do windows com um mínimo de
TMULTIKEYHELP. Esta estrutura específica memória, variando o tamanho e a posição de
contém o tamanho e a posição da janela do help acordo primário ou a janela secundária para ser
mostrado. Com o dado passado.

HELP_FORCEFILE Ignorado. Normalmente passado 0. Executa o WinHelp mostrando o arquivo de


auxílio corrijido.

HELP_HELPONHELP Ignorado. Normalmente passado 0. Mostra o auxílio de como usar o auxílio.

HELP_QUIT Ignorado. Normalmente passado 0. Solicita o fechamento do auxílio ativo.

De posse desse nosso dicionário de comandos, aperte F12 e clique em Auxílio e Conteúdo, e insira o seguinte
código:

procedure TF_Menu.Contedo1Click(Sender: TObject);


begin
Application.HelpCommand(HELP_CONTENTS, 0);
end;

Aperte F12 e clique em Auxílio e Tópicos do Auxílio, e coloque o seguinte código:

procedure TF_Menu.TpicosdoAuxlio1Click(Sender: TObject);


const
EmptyString: PChar = '';
begin
Application.HelpCommand(HELP_PARTIALKEY, Longint(EmptyString));
end;

E finalmente, aperte F12, clique em Auxílio e Como usar o Auxílio, e coloque o seguinte código:

procedure TF_Menu.ComoUsaroAuxlio1Click(Sender: TObject);


begin
Application.HelpCommand(HELP_HELPONHELP, 0);
end;

Vamos completar o comando de sair colocando também o encerramento do arquivo de auxílio, aperte F12 e
clique em Arquivo e Sair, complete com seguinte código antes do comando Close:

procedure TF_Menu.Sair1Click(Sender: TObject);


begin
Application.HelpCommand(HELP_QUIT, 0);
Close;
end;

Rode sua aplicação e teste os comandos do Auxílio, caso a tecla F1 não ative o auxílio On-Line,
provavelmente o seu menu está com a propriedade FormStyle em modo fsMDIForm, coloque-a no modo fsNormal. Se
mesmo assim ainda não funcionou, mude a propriedade HelpContext do formulário para 1.

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página Nr. 94/178
Finalmente
Uma dica interessante é que o Fórmulário está associado ao Menu através da propriedade Menu, é que ela é
possível de ser alterada em modo Run-Time, então imagine que num mesmo formulário é possível ter vários Menus
diferentes, cada um se adaptando a uma situação do usuário (financeiro, administrador, digitador).

Na próxima apostila, vamos criar as janelas auxiliares Splash e Sobre o Sistema.

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página 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 versão Client/Server Suite
BDE 5.00
MS-Access 97

Arquivos trabalhados juntos com esta apostila:

IMGGER.BMP
IMGICO.BMP

Prefácio
Salve, a apostila de hoje faz parte do chamado propaganda do sistema, o ambiente Windows conseguiu trazer
consigo mais do que simplesmente um ambiente gráfico de janelas, trouxe uma coisa muito importante, alias foram
duas, note que todo o sistema ditos "for Windows" carregam consigo essas duas importantes e imprescindíveis janelas.

Splash Screen, não isso não é nada do outro mundo, ouvimos e vimos falar de uma janela Splash desde a
primeira vez que entramos no Word, no Access e até mesmo o Delphi tem a sua janela Splash, não precisa você ficar
procurando por ela, ela está logo na nossa cara assim que entramos em qualquer desses aplicativos, e a chamada janela
inicial.

Sobre o Sistema, para que serve ? como surgiu ? como começou ? ninguém sabe, sabe-se apenas que todo o
sistema que se preza tem que ter a sua, algumas bem incrementandas contendo os famosos "Ovos de Páscoa", aquela
combinação maluca de teclas que antes de iniciarmos a janela Sobre é mostrado algo mais, as vezes pode até ser um
joguinho.

A Splash Screen e a Sobre o Sistema são janelas que a maioria dos programadores não dá a menor
importância, mas que bem feita pode ser como um Out-Door na estrada, rendendo-nos uma bela propaganda gratuita
da nossa empresa. Vou tentar ensinar aqui alguns macetes como se criar ambas as janelas com um pouco de
incrementação, vamos nessa então.

Splash Screen
Inicialmente deixe-me dizer uma coisa, a Splash é apenas uma janela pedindo para o usuário ter um pouco de
paciência enquanto todo o sistema se inicia, não a faça demorada demais pois a última coisa que o usuário precisa e de
mais paciência, tem gente que coloca um timer nelas para poder demorar ou então um simples comando For i := 1 to
10000 não façam isso, inicialmente pode parecer que a janela pouco vai aparecer, mas não se preocupe com o tempo, e
o sistema crescendo, essa janela vai acabar demorando o tempo suficiente para que o usuário possa ver as informações
descritas nela e não se aborrecer.

Para começarmos abra o sistema e a partir do Menu Principal clique em File | New Form criando um novo
formulário que será a nossa área de trabalho, vamos aos passos:

1. Altere as seguintes propriedades desta janela:


1.1. BorderStyle - bsNone - A borda em volta da janela, incluindo a tarja azul desapareça.
1.2. Name - F_Splash.
1.3. Position - poScreenCenter - A janela aparecerá centralizada no vídeo.

2. Na Component Pallete localize uma página chamada Additional e dentro dessa página de um clique no objeto

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página Nr. 96/178
Image (acredito que seja o sexto) e dê um clique no Form, foi criado tipo um painel pontilhado no formulário. Altere as
seguinte propriedades:
2.1. Picture - clique nos ... clique no botão Load e localize o arquivo IMGGER.BMP (enviado)
2.2. Transparent - True - Isso fará com que a cor da posição 0,0 seja a base para que a imagem fique
transparente, então dentro da imagem aonde tiver cor semelhante ficará transparente.

3. Na Component Pallete localize uma página chamada Standard e dentro dessa página de um clique no objeto Label
(acredito que seja o terceiro) e dê um clique no Form. Altere as seguinte propriedades:
3.1. Caption - Produzido por ...
3.2. Font - clique nos ... e altere as seguintes propriedades:
Fonte: MS Sans Serif
Estilo da Fonte: Negrito
Tamanho: 10
3.2. Transparent - True - Isso fará com que a cor de fundo do objeto Label fique transparente.

Prontinho de uma comparada e veja como ficou, agora salve esse formulário com o nome de fSplash, já temos
agora em nosso projeto a nossa Splash Screen mas ainda falta um pequeno toque, clique no formulário e selecione o
evento OnCreate, dê um duplo clique neste evento e digite o seguinte comando:

procedure TF_Splash.FormCreate(Sender: TObject);


begin
Brush.Style := bsClear;
end;

Este simples comando produzido no evento de criação fará com que todo o formulário fique também
transparente, então na verdade dentro da nossa Splash só aparecerá a Imagem e o Label, agora precisamos chamá-la
do nosso sistema.

☞Importante - Peço por favor a maior atenção para o próximo passo pois mecheremos em áreas delicadas do nosso
projeto.

Antes de começarmos deixe-me dizer-lhes uma curiosidade sobre o Pascal, um projeto em Pascal sempre
existe apenas um ÚNICO programa, o resto é tudo UNIDADES de sistema, pensam que estou mentindo ? Olhem na
primeira linha de qualquer formulário, aparecerá escrito UNIT tal, mas aonde então está o nosso Programa ? Quando
você inclui um novo formulário ao projeto, o Delphi se encarrega automaticamente de criar as chamadas a esta nova
Unidade alterando por si só o nosso Programa, infelizmente ele não tem uma área para fazer isso automaticamente
com uma janela Splash então teremos que colocar na mão.

A partir do menu principal clique em View | Project Source e aí está o nosso único PROGRAM do sistema
todo, ele recebe exatamente o nome do nosso Projeto, vamos as alterações, localize o comando BEGIN e insira os
seguintes comandos:

begin

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página 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 três comandos, nos Criaremos a janela de Splash, chamaremos ela (não passando o
controle para ela) e forçaremos sua aparição.

☞Importante - Existem dois comandos para se chamar um Formulário, são eles:


SHOW - Chama o formulário sem passar o controle para ele, ou seja o programa que o chamou ainda possui o
controle da ação.
SHOWMODAL - Chama o formulário passando o controle da ação para ele até que ele seja finalizado.

Bem, feito isso, agora só falta destruirmos nossa janela quando o sistema começar a execução, você pode
colocar o comando: F_Splash.Free antes do comando Application.Run mas pessoalmente eu prefiro finalizá-la apenas
quando o menu efetivamente for criado, então chame o formulário do Menu e para o evento OnShow coloque o
comando:

procedure TF_Menu.FormShow(Sender: TObject);


begin
F_Splash.Free;
end;

Não se esqueça de logo após a diretiva de compilação acrescentar a utilização da Unidade, desta maneira:

{$R *.DFM}
uses
fSplash;

Sobre o Sistema
A partir do Menu Principal clique em File | New Form criando um novo formulário que será a nossa área de
trabalho, vamos aos passos:

1. Altere as seguintes propriedades desta janela:


1.1. BorderStyle - bsDialog
1.2. Caption - Sobre o Sistema...
1.3. Name - F_Sobre.
1.4 Position - poScreenCenter - A janela aparecerá centralizada no vídeo.

2. Na Component Pallete localize uma página chamada Standard e dentro dessa página de um clique no objeto Panel
(acredito que seja o último) e dê um clique no Form. Altere as seguinte propriedades:
2.1. BevelInner - bvLowered - Borda interna rebaixada
2.2. BevelOuter - bvRaised - Borda externa levantada
2.3. BevelWidth - 2 - Espessura da borda

☞Importante - Para os tópicos 3 e 4, antes de clicar nos objetos indicados clique primeiramente neste objeto Panel
criado.

3. Na Component Pallete localize uma página chamada Additional e dentro dessa página de um clique no objeto
Image (acredito que seja o sexto) e dê um clique no objeto Panel. Altere as seguinte propriedades:
3.1. Picture - clique em ... clique no botão Load e localize o arquivo IMGICO.BMP (enviado)
3.2. Transparent - True - Isso fará com que a cor da posição 0,0 seja a base para que a imagem fique
transparente, então dentro da imagem aonde tiver cor semelhante ficará transparente.

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página Nr. 98/178
4. Na Component Pallete localize uma página chamada Standard e dentro dessa página traga três objetos Label
(acredito que seja o terceiro) para dentro do objeto Panel. Altere as seguinte propriedades:
4.1. Objeto Label1:
4.1.1. Caption - Sistema de Controle do SPA
4.1.2. Font - clique nos ... e altere as seguintes propriedades:
Fonte: MS Sans Serif
Estilo da Fonte: Negrito
Tamanho: 10
Cor: Castanho
4.2. Objeto Label2:
4.2.1. Caption - Versão Beta 1
4.2.2. Font - clique nos ... e altere as seguintes propriedades:
Fonte: MS Sans Serif
Estilo da Fonte: Itálico
Tamanho: 8
Cor: Castanho
4.3. Objeto Label3:
4.3.1. Caption - Copyright © Curso Delphi 1998 - Junho
4.3.2. Font - clique nos ... e altere as seguintes propriedades:
Fonte: MS Sans Serif
Estilo da Fonte: Normal
Tamanho: 8
Cor: Castanho

5. Na Component Pallete ainda na página Standard dentro dessa página de um clique no objeto GroupBox (acredito
que seja o décimo segundo) e dê um clique no Form. Altere as seguinte propriedades:
5.1. Caption - Dados Técnicos
5.2. Font - clique nos ... e altere as seguintes propriedades:
Fonte: MS Sans Serif
Estilo da Fonte: Negrito
Tamanho: 8
Cor: Castanho

☞Importante - Para o tópico 6, antes de clicar no objeto indicado clique primeiramente neste objeto GroupBox
criado.

6. Na Component Pallete ainda na página Standard e dentro dessa página traga quinze objetos Label (acredito que
seja o terceiro) para dentro do objeto Panel. Altere as seguinte propriedades:

6.1. Para os primeiros Sete labels (coloque um abaixo do outro) mudando a propriedade Font de todos para:
Font - clique nos ... e altere as seguintes propriedades:
Fonte: MS Sans Serif
Estilo da Fonte: Normal
Tamanho: 8
Cor: Castanho
E a propriedade Caption para:
Caption do 1: Endereço Internet:
Caption do 2: EMail:
Caption do 3: Versão Windows:
Caption do 4: Versão do DOS:
Caption do 5: CPU:
Caption do 6: Memória Livre:
Caption do 7: Espaço Livre:

6.2. Coloque os próximos Oito labels na frente dos primeiros Sete (deixe o último sobrando) e altere a
propriedade Font de todos para:
Font - clique nos ... e altere as seguintes propriedades:
Fonte: MS Sans Serif
Estilo da Fonte: Normal

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página 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 página chamada Additional e dentro dessa página de um clique no
objeto BitBtn (acredito que seja o primeiro) e dê um clique no form. Altere as seguinte propriedades:
7.1. Kind - bkOK, isto trocará também as propriedades: Caption, Glyph e ModalResult.

Compare agora como ficou a janela Sobre o Sistema

Iniciando o programa da Sobre o Sistema


Notou que colocaremos algumas informações bem sofisticadas tais como Versão do Windows e DOS entre
outras, mas vamos com calma, inicialmente clique no objeto EnderNet e para o evento OnClick insira o seguinte
código:

procedure TF_Sobre.EnderNETClick(Sender: TObject);


const
pEnderNET = 'http://www.geocities.com/SiliconValley/Vista/3144';
begin
{$ifdef win32}
ShellExecute(Handle, 'open', pEnderNET, nil, nil, SW_SHOW);
{$endif}
end;

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página Nr. 100/178
Este código fará com que seja executado um comando via API para uma chamada ao OLE para iniciar o
Browser de Internet corrente com o comando a home-page especificada, as diretivas de compilação são para assegurar
que o comando só seja executado em ambiente Win32. Clique agora no objeto EMail e para o evento OnClick insira o
seguinte código:

procedure TF_Sobre.EMailClick(Sender: TObject);


const
pEMail = 'mailto: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 correspondência para o endereço eMail especificado. Clique agora no objeto F_Sobre
e para o evento OnShow insira o seguinte código:

procedure TF_Sobre.FormShow(Sender: TObject);


var
OsInfo: TOSVERSIONINFO;
SysInfo: TSYSTEMINFO;
MemStat: TMEMORYSTATUS;
DiskNo: Integer;
begin
OsInfo.dwOSVersionInfoSize := sizeof(TOSVERSIONINFO);
GetVersionEx(OsInfo);
// Versão do Windows
case OsInfo.dwPlatformId of
VER_PLATFORM_WIN32s : WinVersion.Caption := 'Windows 3.1';
VER_PLATFORM_WIN32_WINDOWS : WinVersion.Caption := 'Windows 95';
VER_PLATFORM_WIN32_NT : WinVersion.Caption := 'Windows NT';
end;
// Versão do DOS
DosVersion.Caption := format('%d.%d Ver : %d',
[OsInfo.dwMajorVersion,OsInfo.dwMinorVersion,LOWORD(OsInfo.dwBuildNumber)]);
// Pega o processador
GetSystemInfo(SysInfo);
case SysInfo.dwProcessorType of
PROCESSOR_INTEL_860 : CPU.Caption := format('%d %s',[SysInfo.dwNumberOfProcessors, 'Intel 8086']);
PROCESSOR_INTEL_386 : CPU.Caption := format('%d %s',[SysInfo.dwNumberOfProcessors, 'Intel 80386']);
PROCESSOR_INTEL_486 : CPU.Caption := format('%d %s',[SysInfo.dwNumberOfProcessors, 'Intel 80486']);
PROCESSOR_INTEL_PENTIUM : CPU.Caption := format('%d %s',[SysInfo.dwNumberOfProcessors, 'Intel Pentium']);
PROCESSOR_MIPS_R2000 : CPU.Caption := format('%d %s',[SysInfo.dwNumberOfProcessors, 'MIPS R2000']);
PROCESSOR_MIPS_R3000 : CPU.Caption := format('%d %s',[SysInfo.dwNumberOfProcessors, 'MIPS R3000']);
PROCESSOR_MIPS_R4000 : CPU.Caption := format('%d %s',[SysInfo.dwNumberOfProcessors, 'MIPS R4000']);
PROCESSOR_ALPHA_21064 : CPU.Caption := format('%d %s',[SysInfo.dwNumberOfProcessors, 'ALPHA 21064']);
PROCESSOR_PPC_601 : CPU.Caption := format('%d %s',[SysInfo.dwNumberOfProcessors, 'Power PC 601']);
PROCESSOR_PPC_603 : CPU.Caption := format('%d %s',[SysInfo.dwNumberOfProcessors, 'Power PC 603']);
PROCESSOR_PPC_604 : CPU.Caption := format('%d %s',[SysInfo.dwNumberOfProcessors, 'Power PC 604']);
PROCESSOR_PPC_620 : CPU.Caption := format('%d %s',[SysInfo.dwNumberOfProcessors, 'Power PC 620']);
end;
MemStat.dwLength := sizeof(TMEMORYSTATUS);
GlobalMemoryStatus(MemStat);
// Memória Livre
FreeMemory.Caption := format('Tot: %d KB Disp: %d KB',
[Trunc(MemStat.dwAvailPhys/1024),Trunc(MemStat.dwTotalPhys/1024)]);
// Recursos livres
DiskNo := 3;
FreeDisk.Caption := '';
FreeResources.Caption := '';

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página 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 são todos comandos API que fazem chamadas ao Windows solicitando as informações
necessárias, apenas perderia tempo explicando comando a comando quando seria muito mais proveitoso que você
consulte o Help e verifique os comandos utilizados para fazer as capturas, uma pequena observação, note que para
capturar o processador me utilizei de determinadas constantes para facilitar o entendimento, elas devem então serem
criadas, localize o comando VAR e entre este comando e o comando End de finalização do comando Type crie as
seguintes constantes:

public
{ Public declarations }
end;

const
PROCESSOR_INTEL_860 = 860;
PROCESSOR_INTEL_386 = 386;
PROCESSOR_INTEL_486 = 486;
PROCESSOR_INTEL_PENTIUM = 586;
PROCESSOR_MIPS_R2000 = 2000;
PROCESSOR_MIPS_R3000 = 3000;
PROCESSOR_MIPS_R4000 = 4000;
PROCESSOR_ALPHA_21064 = 21064;
PROCESSOR_PPC_601 = 601;
PROCESSOR_PPC_603 = 603;
PROCESSOR_PPC_604 = 604;
PROCESSOR_PPC_620 = 620;

var
F_Sobre: TF_Sobre;

Para que todos os comandos API funcionem precisamos ainda disponibilizar a utilização da Unidade:
ShellAPI, coloque então a declação dela no comando USES perto do comando INTERFACE.

Pronto, agora basta chamarmos novamente nosso formulário que contém o Menu e chamarmos a janela do
Sobre para tanto chame o formulário, clique em Auxílio | Sobre o Sistema e insira os seguintes códigos:

procedure TF_Menu.SobreoSistema1Click(Sender: TObject);


begin
F_Sobre := Tf_Sobre.Create(Application);
F_Sobre.ShowModal;
F_Sobre.Free;
end;

Não se esqueça de logo após a diretiva de compilação acrescentar a utilização desta nova Unidade, desta
maneira:

{$R *.DFM}
uses
fSplash, fSobre;

Nota Importante: Note que para o formulário fMenu eu criei um novo comando USES enquanto que no formulário
do fSobre eu apenas acrescentei no USES já existente, existe uma grande diferença entre ambos, no primeiro caso as

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página Nr. 102/178
unidades fSplash e fSobre não estão com os endereços fixados na área de memória no momento da criação do
formulário, no segundo caso todas as unidades inclusive a ShellApi estão com os endereços de memória reservado
assim que o formulário é criado.

Retirando os formulários da Área de Memória


Falando em áreas de memória, os formulários só devem ser criados (a excessão óbvia do fMenu) quando o
usuário necessitar deles, ou seja, se o usuário que chamar o FSobre então o sistema deve criá-lo, chamá-lo e depois
removê-lo completamente da área de memória, isto é feito pois o Delphi se utiliza da área de memória baixa para
manter os endereços do objetos criados, ou seja o Delphi faz uso dos 640 Kb desta memória, então não adianta ter um
Pentium com 64 Megas de memória, pois o disponível para execução dos formulário é apenas aquela taxa de 640 Kb, e
deve ser muito menos, pois o Windows também utiliza ela, e outros aplicativos também.

Precisamos então aliviar o máximo esta área, para isso no Menu Principal clique em Project | Options... na
folha Forms selecione F_Splash e F_Sobre e clique no botão > mandando ambas para a área dos Avaliable Forms
isto será feito com todas as outras janelas a exceção da DModelo que será o nosso DataModule.

Finalmente
Pode executar o sistema e apreciar a propaganda da Splash e da Sobre, novamente digo não se preocupe com
a rapidez que a janela Splash vai aparecer, quanto mais inserirmos no sistema mais demorado esta janela ficará.

Na próxima apostila, vamos discutir o assunto de como juntar todas as nossas regras de negócio num único e
simples DATA MODULE.

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página 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 versão Client/Server Suite
BDE 5.00
MS-Access 97

Arquivos trabalhados juntos com esta apostila:

BASICO.MDB

Prefácio
Salve, nesta apostila desvendaremos a utilização dos Data Modules.

Os Data Modules não são um bicho de sete cabeças, na verdade ele tem oito e mais uma que vive escondida
esperando para te dar aquela dentada. Mas, você verá é que depois de domesticado ele se torna um fiel e amável
bichinho de nove cabeças, você deve é tomar cuidado para não cortar nenhuma delas pois sempre nascem mais duas no
lugar.

Primeira Cabeça - Quando nasceu


Os Data Modules surgiram a partir do Delphi 2.0, então não adianta você ficar procurando naquela sua antiga
versão de Delphi 1.0, com a necessidade de organizar os formulários, pois ficava aquele monte de objetos invisíveis em
tempo de execução tipo tTable, tDataSource e tQuery perdidos, fora que você sempre tinha que definir em dois
formulários diferentes a mesma tabela, os mesmos campos, as mesmas ligações, isto gastava tempo e muito espaço do
sistema.

Segunda Cabeça - Invisibilidade


Os Data Modules são parentes primários dos formulários, eles são uma espécie de "Nehandertal" dos
formulários, não são visíveis em tempo de execução, então não adianta tentar dar um comando do tipo Show para
mostrá-los pois todos são envergonhados e detestam aparecer, eles só servem para uma única função controlar e
armazenar objetos invisíveis como eles, então não tente colocar um tEdit ou um tImage dentro deles que eles não
deixarão.

Outra característica dos Data Modules é que eles adoram ser criados automaticamente, quando os tiramos
daquela área dos Auto-Create Forms eles simplesmente somem do projeto, você pode até ficar criando os Data
Modules na mão, dando aqueles comandos de criação, mas em todo o nosso projeto será apenas um único Data
Module, então além do Menu deixe-o quietinho na área dos Auto-Create.

Terceira Cabeça - Relação Data Module X Formulário


É possível criar um Data Module para cada formulário, mas este não é o objetivo para o qual eles foram
criados, a maneira mais racional de se trabalhar com eles é criar um único Data Module abrigando todas as tabelas,
montando as regras de negócio, criando e definindo os campos das tabelas além de outros objetos invisíveis que o
sistema poderá a necessitar.

O Data Module é um espécie de armazém do nosso sistema, guarde nele tudo o que for globalmente usado,
como por exemplo variáveis, funções ou procedimentos basta apenas definí-los em sua área Public e depois declarar o
Data Module no comando Uses da nossa unidade.

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página Nr. 104/178
Quarta Cabeça - Criando a 1a. Conexão
Vamos começar nosso desenvolvimento criando o Banco de Dados que abrigará o nossas tabelas do sistema,
pegue novamente a Apostila 7 e veja como ficou o nosso Banco de Dados e crie-o com o MS-Access 97 (ou então
utilize o MBD enviado) o nome do nosso banco será BASICO.MDB, na Apostila 2 mostrei como se cria um Alias,
precisamos criar outro para este sistema. Abra o aplicativo BDE Administrator para criar o Alias para o Banco de
Dados enviado.

1. A partir do BDE Administrator aberto vá em Object | New... (ou simplesmente CTRL+N) e modifique a janelinha
que aparece para o Database Driver Name para MSACCESS e pressione a tecla OK.

2. Mude o nome do seu novo alias para AlPeso.

3. Altere a propriedade DATABASE NAME para C:\CursoDelphi\Peso\basico.mdb e confirme as alterações em


Object | Apply (ou simplesmente CTRL+A, ou ainda clique no quarto botão da barra de ferramentas).

4. Teste seu novo alias clicando em Object | Open seu alias deve formar um quadradinho luminoso em volta do objeto.

5. Feche-o em em Object | Close.

Volte para o Delphi e reabra novamente o projeto PESO.DPR, a partir do Menu Principal clique em File |
New Data Module criando a seguinte janela:

Altere a propriedade Name para D_Modelo e salve o Data Module com o nome de dModelo.

Na Component Pallete localize uma página chamada DataAccess e dentro dessa página de um clique no
objeto DataBase (acredito que seja o quinto) e dê um clique dentro do Data Module criado. Altere as seguinte
propriedades:
AliasName - AlPeso - Nome do Alias de Conexão
DataBase Name - DNmPeso - Nome da Base de Dados Interna
Name - PrjPeso - Nome do Objeto

Quinta Cabeça - Criando a 2a. Conexão


Vamos agora criar toda a nossa regra de negócio, ou seja, vamos criar todos os objetos tDataBase, tTable,
tQuery e quaiquer outro que necessitaremos e que utilizaremos ao longo de todo esse projeto e qual a forma como as
tabelas se relacionam.

Na Component Pallete ainda uma página chamada DataAccess e dentro dessa página traga nove objetos
Table (acredito que seja o segundo), um objeto DataSource (acredito que seja o primeiro) e um objeto Query
(acredito que seja o terceiro). Altere as seguinte propriedades:

Para os objetos Tables e Query altere a propriedade DataBaseName para DNmPeso

Para os objetos Tables altere as propriedades TableName, Name e IndexFieldName respectivamente:

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página Nr. 105/178
TableName Name IndexFieldName
Alimento tbAlimento COD_ALIMENTO
Cidade tbCidade SIG_CIDADE
Cliente tbCliente NUM_CPF
Grupo tbGrupo NUM_GRUPO
Pasta_Cliente tbPasta_Cliente NUM_CPF;DAT_CORRENTE
Peso_Cliente tbPeso_Cliente NUM_CPF;DAT_MEDIDO
Resumo_Mensal tbResumo_Mensal ANO_MES
Telefone_Cliente tbTelefone_Cliente NUM_CPF;NUM_TELEFONE

Para o objeto DataSource altere as propriedades:


DataSet - tbCliente
Name - DsCliente

Para o objeto tbTelefone_Cliente altere as propriedades:


MasterSource - DsCliente
MasterFields - NUM_CPF
Isto fará com que esta tabela automaticamente se relacionem com a tabela de Cliente através do campo
chave NUM_CPF, o mesmo será colocado automaticamente quando de uma inclusão, mantendo assim a integridade
referencial com este.

Altere a propriedade Name do objeto Query1 para QrySql

Prontinho, deve ter ficado algo parecido com isso:

Sétima Cabeça - Criando os campos


Uma coisa prática que podemos fazer é a definição dos campos de cada tabela, isto servirá para que quando
mostremos esta tabela através de um objeto dbGrid o Delphi o trate pelo nome que desejamos e não como NUM_CPF
por exemplo, outra parte interessante é que aqui podemos definir as máscaras para os campos.

Para criar os objetos fields, dê um duplo clique em cima de qualquer tabela e aparecerá a janela Definition
Fields, clique com o botão direito nela e aparecerá o menu popup conforme a figura a seguir:

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página Nr. 106/178
Clique em Add fields... e clique no botão OK para inserir todos os campos, vou agora descrever campo a
campo de cada tabela e as propriedades que devem ser trocadas, cabe a você entrar em tabela a tabela e ir criando e
alterando os campos:

Tabela Campo DisplayLabel EditMask Currency


tbAlimento COD_ALIMENTO Código
tbAlimento NUM_GRUPO Núm Grupo >a;0;_
tbAlimento NOM_ALIMENTO Nome
tbAlimento QTD_PERMITIDA Qtd Permitida
tbResumo_Mensal ANO_MES Ano e Mês 9999\/99;0;_
tbResumo_Mensal VAL_MEDICO Valor Médico True
tbResumo_Mensal VAL_COORDENADOR Valor Coordenador True
tbResumo_Mensal VAL_NUTRICIONISTA Valor Nutricionista True
tbResumo_Mensal VAL_DESPESA Valor Despesa True
tbCliente NUM_CPF CPF Cliente 000\.000\.000\/00;0;_
tbCliente SIG_CIDADE Sigla da Cidade >aaa;0;_
tbCliente NOM_CLIENTE Nome
tbCliente END_CLIENTE Endereço
tbCliente BAI_CLIENTE Bairro
tbCliente CEP_CLIENTE CEP 00\.000\-000;0;_
tbCliente DES_EMAIL eMail
tbCliente ALT_CLIENTE Altura (Cm)
tbCliente DAT_NASCIMENTO Data de Nascimento !99/99/0000;1;_
tbGrupo NUM_GRUPO Número >a;0;_
tbGrupo DES_GRUPO Descrição
tbTelefone_Cliente NUM_CPF CPF Cliente 000\.000\.000\/00;0;_
tbTelefone_Cliente NUM_TELEFONE Núm Telefone \(0000\) 000\-0000;0;_
tbTelefone_Cliente DES_FUNCAO Função
tbPasta_Cliente NUM_CPF CPF Cliente 000\.000\.000\/00;0;_
tbPasta_Cliente DAT_CORRENTE Data Corrente !99/99/0000;1;_
tbPasta_Cliente PLN_ADOTADO Plano Adotado >a;0;_
tbPasta_Cliente QTD_CALORIA Qtd Calorias 0000;0;_
tbPasta_Cliente OBS_PASTA Observações
tbPasta_Cliente DAT_PAGAMENTO Data Pagamento !99/99/0000;1;_
tbPasta_Cliente VAL_TOTAL Valor Total True
tbPasta_Cliente VAL_DESCONTO Valor Desconto True
tbCidade SIG_CIDADE Sigla >aaa;0;_
tbCidade NOM_CIDADE Nome
tbCidade SIG_UF UF >AA;0;_
tbPeso_Cliente NUM_CPF CPF Cliente 000\.000\.000\/00;0;_
tbPeso_Cliente DAT_MEDIDO Data Medição !99/99/0000;1;_
tbPeso_Cliente PES_MEDIDO Peso Medido

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página Nr. 107/178
Oitava Cabeça - Coficando a entrada das tabelas
Um grande problema que existe quando se troca de bancos de dados em sistemas com o Delphi é quanto ao
nome das tabelas, quem já tentou por exemplo mudar do Paradox para o Oracle viu que nem por mais cuidado se tome
sempre acaba tropeçando nos chamados Domínios do Oracle, que são iniciais automáticas que ele coloca para definir
quem é o dono das tabelas. O problema uma mudança de nome em qualquer ponto pode ser desastroso, e isso não se
limita apenas ao Oracle serve para qualquer outra migração de base de dados, para evitar este pequeno problema,
vamos adotar em nosso sistema oito variáveis globais, cada uma contendo e carregando consigo o nome da tabela.

Outra coisa que precisamos controlar é a entrada do sistema, verificarmos se foi feito a conexão corretamente
entre o objeto TDataBase e o Alias para ambas:

1. Alterne para o Code Editor e localize a seguinte porção do código:

private
{ Private declarations }
public
{ Public declarations }

e coloque o seguinte:

private
{ Private declarations }
public
nmAlimento, nmCidade, nmGrupo, nmPasta_Cliente, nmPeso_Cliente, //
nmResumo_Mensal, nmTelefone_Cliente, nmCliente : String;
end;

2. Selecione o objeto D_Modelo e para o evento OnCreate insira o seguinte código:

procedure TD_Modelo.D_ModeloCreate(Sender: TObject);


var
Conexao : Boolean;
begin
// Atribui os nomes externos as variáveis
nmAlimento := 'ALIMENTO';
nmCidade := 'CIDADE';
nmGrupo := 'GRUPO';
nmPasta_Cliente := 'PASTA_CLIENTE';
nmPeso_Cliente := 'PESO_CLIENTE';
nmResumo_Mensal := 'RESUMO_MENSAL';
nmTelefone_Cliente := 'TELEFONE_CLIENTE';
nmCliente := 'CLIENTE';
// Atribui os nomes das variáveis aos nomes das tabelas
tbAlimento.TableName := nmAlimento;
tbCidade.TableName := nmCidade;
tbGrupo.TableName := nmGrupo;
tbPasta_Cliente.TableName := nmPasta_Cliente;
tbPeso_Cliente.TableName := nmPeso_Cliente;
tbResumo_Mensal.TableName := nmResumo_Mensal;
tbTelefone_Cliente.TableName:= nmTelefone_Cliente;
tbCliente.TableName := nmCliente;
// Testa a conexão
try
PrjPeso.Connected := True;
if not PrjPeso.IsSQLBased then
PrjPesoLogin(PrjPeso, nil);
Conexao := True;
except
MessageDlg('Erro na Conexão do Banco de Dados', mtError, [MbOk], 0);

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página 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 código:

procedure TD_Modelo.PrjPesoLogin(Database: TDatabase; LoginParams: TStrings);


begin
LoginParams.Values['USER NAME'] := '';
LoginParams.Values['PASSWORD'] := '';
end;

4. Para terminar a conexão, quando o sistema for encerrado, selecione o objeto D_Modelo e para o evento OnDestroy
insira o seguinte código:

procedure TD_Modelo.D_ModeloDestroy(Sender: TObject);


begin
PrjPeso.Connected := False;
end;

Nona Cabeça - Funções Particulares e as regras de negócio


Todas as amarrações que normalmente são definidas por DBA do banco de dados, criando Stored Procedures
e Triggers para a administração do banco podem ser reproduzidas perfeitamente aqui, vou citar alguns exemplos e
você terá uma boa base para criar outras que serão necessários aos seus sistemas.

Já falei antes e vou repetir agora, não sou muito fã de campos do tipo AutoIncremento, primeiro porque não
são todos os bancos que os implementam e segundo porque não sou eu quem o controla, assim já que não posso
arrumá-lo ou liberá-lo quando desejar, não posso criar meu próprio passo e inúmeras outras coisas, isto em bancos
complexos é realizado criando Stored Procedures, procedimentos prontos em linguagens SQL que são chamados em
determinados momentos, mas estamos utilizando o MS-Access aqui, e amanhã podemos usar o Oracle no dia seguinte
o InterBase imagine o tempo que ficariamos com o sistema parado nas famosas ADAPTAÇÕES.

Para gerar um número automático para um campo qualquer precisamos apenas seguir os seguintes passos:

1. Crie uma chamada a uma função particular:

private
function Maximo(nmCampo, nmTabela: String) : integer;
public

2. Crie a função:

function TD_Modelo.Maximo(nmCampo, nmTabela: String) : integer;


begin
with QrySQL do begin
if Active then Close;
SQL.Clear;
SQL.ADD('SELECT MAX(' + NmCampo + ') FROM');
SQL.ADD(NmTabela);
Open;
result := Fields[0].AsInteger + 1;
Close;
end;
end;

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página Nr. 109/178
3. Para o evento AfterInsert do objeto tbAlimento coloque a seguinte codificação:
procedure TD_Modelo.tbAlimentoAfterInsert(DataSet: TDataSet);
begin
tbAlimentoCOD_ALIMENTO.AsInteger := Maximo('COD_ALIMENTO',nmAlimento);
end;

Resolvido as crises com os números automáticos, a função recebe como parâmetro o nome do campo inteiro e
o nome da tabela, então ela simplesmente monta uma cláusula SQL para procurar o maior valor daquele campo dentro
da tabela e depois simplesmente soma mais um e devolve este resultado aonde o mesmo é jogado direto para o campo.

Outras funções particulares que podemos colocar são para os eventos OnPostError e OnDeleteError para
controlar falhas na gravação e ao invés de recebermos aquelas amigáveis mensagens binárias hexadecimais $FFFFFFF
para a alegria e desespero do nosso usuário, aparecer controladamente algo mais agradável, então siga os passos:

1. Alterne para o Code Editor e defina os seguintes procedimentos antes da cláusula Private

procedure TabelaErroPost(DataSet:TDataSet; E: EDataBaseError; var Action: TDataAction);


procedure TabelaErroDelete(DataSet:TDataSet; E: EDataBaseError; var Action: TDataAction);
private

2. Codifique agora os procedimentos:

// Controla os Erros de Gravação coloque no Evento onPostError de todas as Tabelas


procedure TD_Modelo.TabelaErroPost(DataSet:TDataSet; E: EDataBaseError; var Action: TDataAction);
begin
if (E is EDBEngineError) then begin
MessageDlg('Impossível gravação: Provavelmente Registro Duplicado', mtWarning, [mbOk], 0);
Abort;
end;
end;

// Controla os Erros de Exclusão coloque no Evento onDeleteError de todas as Tabelas


procedure TD_Modelo.TabelaErroDelete(DataSet:TDataSet; E: EDataBaseError; var Action: TDataAction);
begin
if (E is EDBEngineError) then begin
MessageDlg('Impossível excluir: Provavelmente Registros Associados', mtWarning, [mbOk], 0);
Abort;
end;
end;

3. Selecione todas as tabelas e para o evento OnPostError selecione (através da seta, não dê duplo clique) o
procedimento TabelaErroPost e para o evento OnDeleteError selecione o procedimento TabelaErroDelete.

Estes procedimentos foram criados para receberem os mesmos parâmetros do procedimento original ou seja, o
DataSet vinculado, o código do erro e a ação a tomar, então basta simplesmente verificarmos se o código do erro é um
EDBEngineError ou seja um erro de banco, darmos a nossa mensagem controlada e abortarmos o processo de
gravação ou eliminação.

Para as regras de negócio contamos com o evento OnValidate que cada campo separadamente possui, vou
citar aqui uma das mais importantes regras:

Existem duas divisões entre 21 - 55 e 55 - 74 anos;


Excluem-se clientes menores de 21 e maiores de 74 anos;

Isto é uma regra que o banco deve cumprir, normalmente isto é feito através do que chamamos de Triggers de
banco (Gatilhos), mas esses "Gatilhos" variam muito de banco para banco, então pessoalmente prefiro colocá-los no
Delphi pois assim permito a maleabilidade dos diversos bancos, vamos então implementar esta regra:

1. Dê um duplo clique na tabela de cliente, e selecione o campo DAT_NASCIMENTO.

2. Altere a propriedade Required para True, isto fará com que o campo tenha que ser preenchido obrigatoriamente.

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página 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 variável inteira aonde será calculado quantos anos este cliente possui, para isso, utilizamos a
função FormatDateTime que devolve uma data com base de uma máscara formatada, isso vale para:

Especificação Mostra
c A data que usa o formato dada pelo ShortDateFormat variável global, seguiu até que usasse o
formato dado pelo LongTimeFormat variável global. O tempo não é exibido se a parte fracionária
do valor do DateTime é zero.
d O dia como um número sem um zero principal (1-31).
dd O dia como um número com um zero principal (01-31).
ddd O dia como uma abreviação (Sun-Sat) usando a string ShortDayNames que é uma variável global.
dddd Exibe o dia como um nome cheio (Sunday-Saturday) usando a string LongDayNames que é uma
variável global.
ddddd A data usando a string ShortDateFormat que é uma variável global.
dddddd A data usando a string LongDateFormat que é uma variável global.
m O mês como um número sem um zero principal (1-12). Se a especificação de m segue um h ou
especificar de hh imediatamente, então será exibido o minuto em lugar do mês.
mm O mês como um número com um zero principal (01-12). Se a especificação de mm segue um h ou
especificar um hh imediatamente, o minuto em lugar do mês é exibido.
mmm O mês como uma abreviação (Jan-Dec) usando a string ShortMonthNames que é uma variável
global.
mmmm O mês como um nome cheio (January-December) usando a string LongMonthNamesque é uma
variável global.
yy O ano como um número de dois-dígito (00-99).
yyyy O ano como um número de quatro-dígito (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 variável global ShortTimeFormat.
tt Exibe o tempo que usa o formato dado pela variável global LongTimeFormat.
am/pm Usa a notação Hora-12 do relógio para o h precedendo ou especificado de hh, e exibições ' am'
durante qualquer hora antes de meio-dia, e ' pm' durante qualquer hora depois de meio-dia. A
especificação pode ser usado em minúscula (am/pm), caso contrário (AM/PM), ou misturado
(Am/Pm) o resultado será exibido de acordo.
a/p Usa a notação Hora-12 do relógio para o h precedendo ou especificado de hh, e exibições ' a'
durante qualquer hora antes de meio-dia, e ' p' durante qualquer hora depois de meio-dia. A
especificação pode ser usado em minúscula (a/p), caso contrário (A/P), ou misturado (A/p) o
resultado será exibido de acordo.
ampm Usa a notação Hora-12 do relógio para o h precedendo ou specifier de hh, e exibições os
conteúdos da variável global TimeAMString durante qualquer hora antes de meio-dia, e os
conteúdos da variável global TimePMString durante qualquer hora depois de meio-dia.
/ Exibe o carácter separador de data dado pela variável global DateSeparator.
: Exibe o carácter separador de tempo dado pela variável global TimeSeparator.
"xx" Carácter incluídos em plicks ( ' ) ou aspas ( " ) não afetam o formato.

Coloquei esta tabela, que pode ser encontrada no tópico do auxílio da função FormatDateTime apenas para
que você não se esqueça o quão útil pode ser esta função no tratamento de Datas. O cálculo para a idade é feito da

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página Nr. 111/178
seguinte maneira, pegamos a data atual e subtraimos pela data de nascimento o resultado é convertido em anos pela
função, depois basta apenas questionarmos se o valor está fora da faixa especificada.

Outro tipo de Regra de Negócio que podemos aplicar e quanto a entrada padrão de determinados campos,
supomos que queremos que toda vez que for dada a entrada dos campos na tabela Pasta do Cliente os campos Plano
Adotado receba o Plano A, Quantidade de Calorias receba 800 KCal e Data Corrente receba a Data Atual, esta
Regra também pode ser determinada por certos bancos, mas para realizá-la no Delphi fazemos:

1. Selecione o objeto tbPasta_Cliente.


2. Para o evento onAfterInsert (depois de ser dado o comando Insert) coloque os seguintes códigos:

procedure TD_Modelo.tbPasta_ClienteAfterInsert(DataSet: TDataSet);


begin
with tbPasta_Cliente do begin
FieldByName('PLN_ADOTADO').AsString := 'A';
FieldByName('QTD_CALORIA').AsString := '0800';
FieldByName('DAT_CORRENTE').AsDateTime := Now;
end;
end;
Acredito que não precisa de muita explicação para o que fiz, apenas mandei os valores especicados para cada
campo. Estas regras podem ser aplicadas na medida que você precise delas, não precisando de bancos complexos como
Oracle, MS-SQL ou Interbase entre outros, para obtê-las.

Finalmente
Ao longo deste projeto ainda voltaremos por aqui para incluirmos novas funcionalidades globais, mas acredito
que já deu para você perceber a utilíssima ferramenta que são os Data Modules. Na próxima apostila, nosso assunto
será de construir os formulários que cadastrarão as tabelas básicas do sistema, ou seja, começaremos a construir nossas
telas de entradas.

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página 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 versão Client/Server Suite
BDE 5.00
MS-Access 97

Arquivos trabalhados juntos com esta apostila:

OBJETOS.WRI
POO.WRI

Seguintes Objetos :
DgFiltro
DgPrint
SelectT
PosEstad

Seguintes Imagens :
ImgAnterior.BMP ImgFiltra.BMP ImgMarca.BMP
ImgAvanca.BMP ImgFormCons.BMP ImgPrimeiro.BMP
ImgGrava.BMP ImgTabela.BMP ImgAvancaSalto.BMP
ImgCancela.BMP ImgImprime.BMP ImgUltimo.BMP
ImgDesFiltro.BMP ImgInsere.BMP ImgFicha.BMP
ImgDuplFicha.BMP ImgInsLote.BMP ImgVaiMarca.BMP
ImgElimina.BMP ImgLocaliza.BMP ImgVoltaSalto.BMP
ImgEnviaArea.BMP

Prefácio
Salve, nesta apostila desvendaremos a primeira parte de como criar os cadastros. Mas antes de começarmos
deixe-me explicar porque suspendi o curso durante o mês de Agosto.

Todo o curso foi reformulado, tanto o ambiente como a linguagem, e aviso que isto sempre vai acontecer,
porque sempre que pensei em lançar um curso deste nível também sempre desejei que as pessoas pudessem aprender o
que existe de mais moderno sem ficar preso a uma linguagem ou ambiente antigo e morto, então não quero nem vou
ficar esperando concluir ou terminar um módulo para mudar. Aconselho que você sempre se mantenha sempre
atualizado em relação ao Delphi, ao ambiente Windows e ao Gerenciador de Banco de Dados MS-Access.

☞ Importante - Junto com esta estou disponibilizando na parte de Objetos um manual e todos os objetos necessários
que iremos utilizar a partir de agora, então antes que você começe a desenvolver nesta apostila aconselho que você
baixe e dê uma lida neste manual, instale e verifique a utilidade dos objetos disponibilizados, e também estou
disponibilizando o Apêndice C para que você aprenda e compreenda mais um pouco sobre a linguagem Object Pascal.

Começando e Criando o Pai de Todos


Em Orientação a Objetos a palavra-chave é Reaproveitamento, e isto é conseguido facilmente através da
Herança dos Objetos primeiramente se ninguém nunca disse isso a você então vou ter a honra de falar primeiro, tudo
no Delphi são objetos, inclusive e principalmente os formulários, eles são tratados como qualquer outro objeto, então
existe a propriedade Herança para o reaproveitamento dos formulários, para não complicar muito esta apostila será
dividida em duas partes (você verá que mesmo dividindo esta apostila em dois ela é bastante extensa).

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página Nr. 113/178
Neste primeiro momento criaremos o pano de fundo para todos os nossos cadastros, não pense que vai ser
simples, pois em 17 anos programando mudei várias vezes minhas telas de cadastro desde que trabalhava com
linguagens do tipo Natural e Cobol, venho aprimorando minhas telas, até que finalmente, graças a uma olhada num
sistema me apaixonei logo de cara na tela de cadastro, mais pela simplicidade do que pelo número de funções fiz
algumas mudanças e consegui chegar a uma tela de cadastro que julgo a ideal. Sendo simples e ao mesmo tempo
complexa em número de utilidade que ela disponibiliza para o usuário.

Para diminuir um pouco, ou se você prefere, para não assustar muito ao usuário dividi a parte central da tela
em três partes:

1a. Parte. Mostra os dados em forma de uma FICHA, é como se o usuário estivesse navegando em uma gaveta dessas
de bibliotecas e vasculhando as fichas que ele deseja utilizar, servindo também para incluir ou alterar qualquer ficha.

2a. Parte. Mostra os dados em forma de uma TABELA aberta ou como a forma de uma Planilha, esta deve dar a
mobilidade necessária para que o usuário possa ver os dados num bloco, de maneira rápida e eficiente.

3a. Parte. Fica a cargo das pesquisas, relações e filtragens o que o usuário quiser fazer para poder visualizar seus dados
da forma como ele julgar melhor.

Criando o Geral
Para começarmos abra o sistema e a partir do Menu Principal clique em File | New Form criando um novo
formulário que será a nossa área de trabalho, vamos aos passos:

1. Altere as seguintes propriedades desta janela:


1.1. BorderStyle - bsDialog - Uma janela diálogo padrão.
1.2. Name - F_Ficha.
1.3. Position - poScreenCenter - A janela aparecerá centralizada no vídeo.

☞Importante - salve o formulário com o nome de fFicha, e de vez em quando vá salvando para não perder o
serviço.

2. Na Component Pallete localize uma página chamada Additional e dentro dessa página de um clique no objeto
BitBtn (prendendo-o com a tecla Shift) e dê cinco cliques no Form, solte o objeto clicando no cursor reprensentado na
Component Pallete, foram criados cinco botões, organize-os do lado esquerdo, um abaixo do outro deixando um
espaço maior entre o quarto e quinto. Altere as seguinte propriedades dos quatro primeiros:

Glyph Name Caption Hint


1 ImgInsere ButInsert &Insere Inclui uma nova ficha
2 ImgGrava ButPost &Grava Grava as alterações realizadas na ficha
3 ImgCancela ButCancel &Cancela Cancela as alterações realizadas na ficha
4 ImgElimina ButDelete &Elimina Apaga a Ficha corrente

2.1. Para o quinto botão altere a propriedade Kind para bkClose, e altere a propriedade Hint para Fecha esta
janela.
2.2. Altere a propriedade ShowHint de todos para True.

3. Na Component Pallete ainda na página Additional dentro dessa página de um clique no objeto SpeedButton
(prendendo-o com a tecla Shift) e dê dez cliques no Form, solte o objeto, foram criados dez botões pequenos, dois
coloque-os no espaço entre o ButDelete e o BitBtn5 e estique-os para ficarem do mesmo tamanho, os outros oito
organize-os na parte de baixo do formulário. Altere as seguinte propriedades:

Glyph Name Caption Hint


1 ImgInsLote ButFixIns Ins. &Lote Insere um conjunto de fichas
2 ImgDuplFicha ButDupField &Dupl.Ficha Duplica determinada Ficha quando Inserir
3 ImgPrimeiro ButFirst Primeira Ficha
4 ImgVoltaSalto ButRW Volta o Salto das Fichas
5 ImgAnterior ButPrior Ficha Anterior
6 ImgAvanca ButNext Próxima Ficha

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página Nr. 114/178
7 ImgAvancaSalto ButFF Salta Fichas
8 ImgUltimo ButLast Última Ficha
9 ImgMarca ButMark Marca uma determinada Ficha
10 ImgVaiMarca ButGotoMark Volta para a Ficha marcada

3.1. Altere as seguintes propriedades para os objetos ButFixIns e ButDupField: propriedade AllowAllUp
altere para True e propriedade GroupIndex altere do primeiro para 1 e do segundo para 2.
3.2. Altere a propriedade ShowHint de todos para True.

4. Na Component Pallete ainda na página Additional pegue um objeto chamado Bevel e envolva os objetos ButMark
e ButGotoMark.

5. Se perdeu ? Ok, vamos dar uma olhada para ver como está ficando a janela:

6. Na Component Pallete, na página Data Access clique no objeto DataSource e dê um clique no Form e altere a
propriedade Name para dsVisao.

7. Na Component Pallete, na página Additional clique no objeto PosEstado (Olhe o Manual dos Objetos para
qualquer referencia) e dê um clique no Form bem abaixo do BitBtn5 e altere a propriedade DataSource para dsVisao e
limpe a propriedade Caption.

8. Na Component Pallete, na página Data Controls clique no objeto DBMemo e dê um clique no Form e altere a
propriedade Name para DBMemClip, a propriedade Visible para False e a propriedade DataSource para dsVisao.

9. Na Component Pallete, na página Standard clique no objeto Memo e dê um clique no Form e altere a propriedade
Name para memClip e a propriedade Visible para False.

10. Na Component Pallete, ainda na página Standard clique no objeto Label e dê um clique no Form colocando no
espaço entre os objetos ButPrior e ButNext e altere a propriedade Caption para Valor Salto.

11. Na Component Pallete, na página Additional clique no objeto MaskEdit e dê um clique no Form colocando
abaixo do objeto Label1e altere as seguintes propriedades
11.1. Name para mskSalto
11.2. EditMask para 099;0;_
11.3. Hint para Defina um valor para o salto das Fichas
11.4. ShowHint para True

Veja como ficou o trabalho até aqui:

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página Nr. 115/178
Criando o Separador das Partes
Toda essa parte de botões e apenas o acessoramento que servirá para substituir com muito mais eficiência um
padrão adotado desde o Delphi 1.0, a famosa Barra de Navegação, ou seja o objeto DBNavigator, não quero aqui em
momento nenhum falar mal deste objeto, o problema se deu que com o passar do tempo eu o consegui aprimorar, até
torná-lo uma barra com 23 botões e sem querer acabei foi conseguindo complicar bastante a cabeça dos meus usuários,
então resolvi descartá-lo e colocar toda a sua funcionalidade nesta tela.

☞Importante - Ainda na terceira parte desta janela criaremos mais alguns botões para completar a barra que eu tinha
desenvolvido, mas você pode notar a ausência do botão Edição ou Alteração, o Delphi permite entrada direta em
modo de Edição, basta que para isto o usuário começe a digitar os dados e depois ou gravar uma determinada Ficha ou
simplesmente começar a navegar os dados, caso ele deseje pode também Cancelar o processo, veja bem criei esta janela
para facilitar a vida do usuário, não para prendê-lo a uma regra ou a um conjunto, você notará que em momento
nenhum desabilito ou habilito qualquer destes botões (a excessão do butMark e butGotoMark).
Para dividir a tela em três partes utilizei um objeto PageControl associado a figuras para ficar mais familiar ao
usuário, vamos construir este preparatório antes de continuarmos.

12. Na Component Pallete, na página Win32 clique no objeto ImageList e dê um clique no Form, agora dê um duplo
clique em cima do objeto criado para entrarmos no editor da lista de imagens, conforme a figura abaixo:

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página Nr. 116/178
12.1. Clique no botão Add... e localize a figura ImgFicha, e clique no botão abrir, ela será a posição 0, insira
as imagens ImgTabela e ImgFormCons. Clique no botão OK e saia do editor.

13. Na Component Pallete, ainda na página Win32 clique no objeto PageControl e dê um clique no Form, acerte-o
para ocupar o espaço vazio do formulário e altere a propriedade Images para ImageList1 e a propriedade Name para
PgPrincipal.

14. Clique neste objeto criado com o botão Direito do mouse e escolha a opção NewPage, uma nova página será
criada, altere a propriedade Caption para Ficha e propriedade Name para TabFicha.

15. Novamente clique no objeto PgPrincipal com o botão Direito do mouse e escolha a opção NewPage, mais uma
nova página será criada, altere a propriedade Caption para Tabela e propriedade Name para TabTabela.

16. Finalmente clique no objeto PgPrincipal com o botão Direito do mouse e escolha a opção NewPage, mais uma
nova página será criada, altere a propriedade Caption para Formas de Consulta e propriedade Name para
TabConsulta.

O resultado de todo este trabalho se mostra na figura a seguir:

☞Importante - Note que os objetos DBMemClip e MemClip ficaram escondidos atrás do objeto PgPrincipal, isto
não tem importância pois quando em modo de execução estes objetos ficarão invisíveis.

Criando a Primeira Parte


Atenção que esta é a parte mais difícil e complicada, você aqui simplesmente não vai fazer nada, deixe
exatamente do jeito que está, utilizaremos esta parte apenas nos formulários que criaremos por herança.

Criando a Segunda Parte


Clique na orelha Tabela dentro do objeto PgPrincipal, o problema em se mostrar os dados de uma tabela sob
a forma de uma planilha é que campos tipo Imagem e campos tipo Texto não aparecem, solucionei este problema,
dividindo esta parte em mais três partes, uma que mostra exclusivamente os dados simples, a outra apenas para campos
tipo Imagem e a última apenas para campos do tipo Texto e vamos ao trabalho:

17. Na Component Pallete, clique na página Win32 clique no objeto PageControl e dê um clique no Form, e altere a
propriedade Align para AlClient e a propriedade Name para PgTabela.

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página Nr. 117/178
18. Clique neste objeto criado com o botão Direito do mouse e escolha a opção NewPage, uma nova página será
criada, altere a propriedade Caption para Dados e propriedade Name para TabTDados.

19. Dentro desta página na Component Pallete, clique na página Data Controls clique no objeto dbGrid e dê um
clique nesta página, altere as seguintes propriedades:
19.1. Align para AlClient
19.2. Options para [dgTitles,dgColumnResize,dgColLines,dgRowSelect,dgAlwaysShowSelection]
19.3. DataSource para DsVisao, compare como ficou:

20. Novamente clique no objeto PgTabela com o botão Direito do mouse e escolha a opção NewPage, mais uma nova
página será criada, altere a propriedade Caption para Imagem e propriedade Name para TabTImagem.

21. Dentro desta página na Component Pallete, clique na página Data Controls clique no objeto dbImage e dê um
clique nesta página, altere a propriedade Align para AlTop e a propriedade DataSource para DsVisao

22. Ainda dentro desta página na Component Pallete, clique na página Standard clique no objeto Label e dê um
clique nesta página, altere a propriedade Caption para Campo e a propriedade Font para Estilo: Negrito e Cor:
Castanho.

23. Ainda dentro desta página na Component Pallete, ainda na página Standard clique no objeto ComboBox e dê um
clique nesta página, altere a propriedade Hint para Selecione o campo a pesquisar, a propriedade ShowHint para
True e a propriedade Name para CbCampoImg.

24. Ainda dentro desta página na Component Pallete, ainda na página Standard traga outro objeto ComboBox, e
altere a propriedade Visible para False e a propriedade Name para CbCampoImgReal, compare como ficou:

25. Finalmente clique novamente no objeto PgTabela com o botão Direito do mouse e escolha a opção NewPage, mais
uma nova página será criada, altere a propriedade Caption para Texto e propriedade Name para TabTTexto.

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página Nr. 118/178
26. Dentro desta página na Component Pallete, clique na página Data Controls clique no objeto dbMemo e dê um
clique nesta página, altere a propriedade Align para AlTop e a propriedade DataSource para DsVisao

27. Ainda dentro desta página na Component Pallete, clique na página Standard clique no objeto Label e dê um
clique nesta página, altere a propriedade Caption para Campo e a propriedade Font para Estilo: Negrito e Cor:
Castanho.

28. Ainda dentro desta página na Component Pallete, ainda na página Standard clique no objeto ComboBox e dê um
clique nesta página, altere a propriedade Hint para Selecione o campo a pesquisar, a propriedade ShowHint para
True e a propriedade Name para CbCampoTxt.

29. Ainda dentro desta página na Component Pallete, ainda na página Standard traga outro objeto ComboBox, e
altere a propriedade Visible para False e a propriedade Name para CbCampoTxtReal, compare como ficou:

Criando a Terceira Parte


Clique na orelha Formas de Consulta dentro do objeto PgPrincipal e vamos ao trabalho:

30. Na Component Pallete clique na página Additional dentro dessa página de um clique no objeto SpeedButton
(prendendo-o com a tecla Shift) e dê cinco cliques nesta página, solte o objeto, foram criados cinco botões pequenos,
coloque-os um abaixo do outro modificando a propriedade Flat de todos para True. E altere as seguinte propriedades:

Glyph Name Enabled


1 ImgFiltra ButFilterOpen True
2 ImgDesFiltro ButFilterClose False
3 ImgLocaliza ButSearch True
4 ImgImprime ButPrint True
5 ImgEnviaArea ButCopyClip True

31. Na Component Pallete clique na página Standard dentro dessa página de um clique no objeto Label (prendendo-
o com a tecla Shift) e dê cinco cliques nesta página, solte o objeto, coloque-os ao lado de cada botão, altere a
propriedade Font de todos para Cor: Azul-Marinho. E altere a propriedade Caption de cada para:

Caption
1 Ativa as opções para se criar um Filtro, o Filtro permite uma seleção das fichas mostradas, limitando-as.
2 Desativa um filtro.
3 Localiza determinada Ficha.
4 Imprime todas as fichas, limitando-as caso haja filtro ativo.
5 Envia a ficha corrente para área de transferência.

Compare como ficou:

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página 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 página chamada Dialogs e dentro dessa página traga um objeto SelectDlgT, um
objeto DgPrint e um objeto DgFiltro. Altere a propriedade Name para SelPesquisa, PrtPesquisa e FilPesquisa
respectivamente.

Codificando
A codificação deste formulário não é tão complicado quando se entende toda a utilidade desta janela, óbvio
que precisei usar uma boa gama de conhecimento que tenho em linguagem Object Pascal mas adianto que não utilizei
nada estranho

1. Alterne para o Code Editor e localize a seguinte porção do código:

private
{ Private declarations }
public
{ Public declarations }

e coloque o seguinte:

private
FBM: TBookmark;
ChDuplica, fTrava: Boolean;
FiltroVisto: String;
public
procedure ChamaExterno(var Tab: TTable; aFormClass: TFormClass);
end;

uses
dModelo,
fFiltro; // Gera o Filtro

// Procedure Global para a chamadas a formulários terceiros


procedure TF_Ficha.ChamaExterno(var Tab: TTable; aFormClass: TFormClass);
begin
Screen.Cursor := crHourGlass;

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página Nr. 120/178
Tab.Close;
with aFormClass.Create(Application) do
try
ShowModal;
finally
Free;
end;
Tab.Open;
Screen.Cursor := crDefault;
end;

☞Importante - Coloque na primeira declaração do USES (fica logo abaixo da Seção interface) a unidade
DBTables pois o procedimento ChamaExterno faz uso do objeto TTable que faz parte desta biblioteca.

Aqui foram criadas algumas variáveis para uso particular do programa ou seja só funcionarão aqui dentro, são
elas:

FBM: Ponteiro para guardar a posição do arquivo quando for disparado o botão Marca Registro.
ChDuplica: Booleana que diz se é ou não para Duplicar um registro marcado.
fTrava: Booleana que informa se o Inserção em Lote foi ou não ativada.
FiltroVisto: Caso a tabela está com o filtro ativo criado e armado pelo usuário.

Foi criada também um procedimento público para poder criar e chamar formulários secundários, este
procedimento será visto com mais detalhes a frente.

2. Para o evento onShow do Formulário

procedure TF_Ficha.FormShow(Sender: TObject);


var
i : Integer;
begin
with dsVisao.DataSet do begin
for i := 0 to (FieldCount -1) do
case Fields[i].DataType of
ftMemo, ftFmtMemo :
begin
CbCampoTxt.Items.Add(Fields[i].DisplayLabel);
CbCampoTxtReal.Items.Add(Fields[i].FieldName);
end;
ftBlob, ftBCD, ftTypedBinary, ftGraphic :
begin
CbCampoImg.Items.Add(Fields[i].DisplayLabel);
CbCampoImgReal.Items.Add(Fields[i].FieldName);
end;
end;
end;
CbCampoTxt.ItemIndex := 0;
CbCampoImg.ItemIndex := 0;
CbCampoImgChange(Sender);
CbCampoTxtChange(Sender);
PgPrincipal.ActivePage := TabFicha;
PgTabela.ActivePage := TabTDados;
PosEstado1.Atualiza;
fTrava := False;
Screen.Cursor := crDefault;
end;

A primeira parte coloca e divide os nomes dos campos das tabelas em três segmentos, do tipo comum, do tipo
texto e do tipo imagem, isto é para ser colocado na segunda parte do formulário quando o usuário terá a visão da tabela

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página 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 Página FICHA como
inicial, na segunda página ativa a Página DADOS como principal, atualiza o objeto PosEstado1, acerta a variável
fTrava e retorna o cursor para o formato de uma seta.

3. Para o evento onClick do objeto ButInsert

procedure TF_Ficha.ButInsertClick(Sender: TObject);


var
i : Integer;
begin
with dsVisao.DataSet do begin
Insert;
if ChDuplica then
for i := 0 to (FieldCount -1) do
Fields[i].Value := D_Modelo.QrySQL.Fields[i].Value;
end;
PosEstado1.Atualiza;
TabFicha.SetFocus;
Keybd_event(9,0,0,0);
end;

Quando for pressionado o botão Insere ativa o comando Insert da tabela e verifica se está em modo de
Duplicação da Ficha, se estiver transfere todos os dados da Query pública para a tabela corrente campo a campo,
atualiza o objeto PosEstado1 e manda o foco para o objeto TabFicha depois simula o pressionamento da tecla TAB
isto fará com que o foco vá para o primeiro campo da TabFicha.

4. Para o evento onClick do objeto ButPost

procedure TF_Ficha.ButPostClick(Sender: TObject);


begin
with dsVisao.DataSet do Post;
if fTrava then
ButInsertClick(Sender)
else
PosEstado1.Atualiza;
end;

Quando for pressionado o botão Grava ativa o comando Post da tabela e verifica se está em modo de
Inserção de Lote, se estiver chama o procedimento de inclusão, caso contrário atualiza o objeto PosEstado1.

5. Para o evento onClick do objeto ButCancel

procedure TF_Ficha.ButCancelClick(Sender: TObject);


begin
with dsVisao.DataSet do Cancel;
if fTrava then
ButInsertClick(Sender)
else
PosEstado1.Atualiza;
end;

Quando for pressionado o botão Cancela ativa o comando Cancel da tabela e verifica se está em modo de
Inserção de Lote, se estiver chama o procedimento de inclusão, caso contrário atualiza o objeto PosEstado1.

6. Para o evento onClick do objeto ButDelete

procedure TF_Ficha.ButDeleteClick(Sender: TObject);


begin

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página Nr. 122/178
with dsVisao.DataSet do Delete;
PosEstado1.Atualiza;
end;

Quando for pressionado o botão Elimina ativa o comando Delete da tabela e atualiza o objeto PosEstado1.

7. Para o evento onClick do objeto ButFixIns

procedure TF_Ficha.ButFixInsClick(Sender: TObject);


begin
fTrava := not fTrava;
ButFixIns.Down := not fTrava;
ButDelete.Enabled := not fTrava;
if fTrava then
ButInsertClick(Sender);
end;

Quando for pressionado o botão Insere Lote pode acontecer dois momentos o primeiro pressionamento trava
e o segundo pressionamento libera, acerta a variável de controle, coloca o botão pressionado (ou despressionado
conforme o caso), desabilita (ou habilita conforme o caso) o botão de exclusão e se for para travar chama o
procedimento de inclusão.

8. Para o evento onClick do objeto ButFirst

procedure TF_Ficha.ButFirstClick(Sender: TObject);


begin
with dsVisao.DataSet do First;
end;

Quando for pressionado o botão Primeiro Registro ativa o comando First da tabela.

9. Para o evento onClick do objeto ButRw

procedure TF_Ficha.ButRwClick(Sender: TObject);


begin
with dsVisao.DataSet do moveby(-StrToInt(mskSalto.Text));
end;

Quando for pressionado o botão Salto para Trás ativa o comando MoveBy enviando o salto estipulado de
forma negativa.

10. Para o evento onClick do objeto ButPrior

procedure TF_Ficha.ButPriorClick(Sender: TObject);


begin
with dsVisao.DataSet do Prior;
end;

Quando for pressionado o botão Registro Anterior ativa o comando Prior da tabela.

11. Para o evento onClick do objeto ButNext

procedure TF_Ficha.ButNextClick(Sender: TObject);


begin
with dsVisao.DataSet do Next;
end;

Quando for pressionado o botão Próximo Registro ativa o comando Next da tabela.

12. Para o evento onClick do objeto ButFF

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página Nr. 123/178
procedure TF_Ficha.ButFFClick(Sender: TObject);
begin
with dsVisao.DataSet do moveby(StrToInt(mskSalto.Text));
end;

Quando for pressionado o botão Salto para Frente ativa o comando MoveBy enviando o salto estipulado.

13. Para o evento onClick do objeto ButLast

procedure TF_Ficha.ButLastClick(Sender: TObject);


begin
with dsVisao.DataSet do Last;
end;

Quando for pressionado o botão Último Registro ativa o comando Last da tabela.

14. Para o evento onClick do objeto ButMark

procedure TF_Ficha.ButMarkClick(Sender: TObject);


begin
with dsVisao.DataSet do FBM := getbookmark;
ButGotoMark.enabled := true;
end;

Quando for pressionado o botão Marca Registro acerta o ponteiro BookMark para guardar a posição do
registro.

15. Para o evento onClick do objeto ButGotoMark

procedure TF_Ficha.ButGotoMarkClick(Sender: TObject);


begin
with dsVisao.DataSet do gotobookmark(FBM);
end;

Quando for pressionado o botão Vai para o Registro Marcado posiciona a tabela de acordo com o ponteiro
criado com o BookMark.

16. Para o evento onClick do objeto ButFilter

procedure TF_Ficha.ButFilterOpenClick(Sender: TObject);


begin
with D_Modelo.FilPesquisa do begin
Tabela := (dsVisao.DataSet as TTable);
FiltroSQL := (dsVisao.DataSet as TTable).Filter;
FiltroVe := FiltroVisto;
if Execute then begin
FiltroVisto := FiltroVe;
with dsVisao.DataSet do begin
Close;
Filter := FiltroSQL;
Filtered := True;
Open;
end;
ButFilterOpen.Enabled := False;
ButFilterClose.Enabled := True;
end;
end;
end;

Quando for pressionado o botão Abre Filtro seta os parâmetros para o objeto FilPesquisa localizado na
D_Modelo e depois executa-o, caso seja devolvida uma resposta positiva realiza a filtragem da tabela e desabilita este

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página Nr. 124/178
botão e habilita o botão Fecha Filtro.

17. Para o evento onClick do objeto ButFilterClose

procedure TF_Ficha.ButFilterCloseClick(Sender: TObject);


begin
with dsVisao.DataSet do begin
Close;
Filtered := False;
Open;
ButFilterOpen.Enabled := True;
ButFilterClose.Enabled := False;
end;
end;

Quando for pressionado o botão Fecha Filtro limpa o filtro da tabela e desabilita este botão e habilita o botão
Abre Filtro.

18. Para o evento onClick do objeto ButSearch

procedure TF_Ficha.ButSearchClick(Sender: TObject);


var
Marca: TBookmark;
begin
D_Modelo.SelPesquisa.Tabela := (dsVisao.DataSet as TTable);
with dsVisao.DataSet do
with D_Modelo.SelPesquisa do begin
Filtro := Filter;
Marca := GetBookMark;
if not Execute then
GotoBookMark(Marca);
FreeBookMark(Marca);
end;
end;

Quando for pressionado o botão Localiza Registro seta os parâmetros para o objeto SelPesquisa localizado
na D_Modelo e depois executa-o, antes guarda em um ponteiro do tipo BookMark a posição da tabela, caso seja
devolvida uma resposta negativa retorna a posição guardada anteriormente.

19. Para o evento onClick do objeto ButPrint

procedure TF_Ficha.ButPrintClick(Sender: TObject);


begin
D_Modelo.PrtPesquisa.Tabela := (dsVisao.DataSet as TTable);
with dsVisao.DataSet do
with D_Modelo.PrtPesquisa do begin
NomeTela := 'Impressão';
NomeRel := 'Relação de';
Filtro := Filter;
Execute;
end;
end;

Quando for pressionado o botão Imprime Dados seta os parâmetros para o objeto PrtPesquisa localizado na
D_Modelo e depois executa-o.

20. Para o evento onClick do objeto ButCopyClip

procedure TF_Ficha.ButCopyClipClick(Sender: TObject);


var
i : Integer;

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página 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 botão Copia para Área de Transferência utiliza-se do objeto invisível MemClip,
com o auxílio do objeto dbMemClip, para colocar todos os dados do registro atual para dentro deste e depois
simplesmente seleciona tudo e envia para a Área de Transferência.

21. Para o evento onChange do objeto CbCampoTxt

procedure TF_Ficha.CbCampoTxtChange(Sender: TObject);


begin
CbCampoTxtReal.ItemIndex := CbCampoTxt.ItemIndex;
if CbCampoTxtReal.Items.Count > -1 then
DbMemo1.DataField := CbCampoTxtReal.Text;
end;

Quando for modicada a posição do combo que contém os campos em formato Texto da página Tabela faz as
alterações necessárias setando o objeto DBMemo1 para o novo campo.

22. Para o evento onChange do objeto CbCampoImg

procedure TF_Ficha.CbCampoImgChange(Sender: TObject);


begin
CbCampoImgReal.ItemIndex := CbCampoImg.ItemIndex;
if CbCampoImgReal.Items.Count > -1 then
DbImage1.DataField := CbCampoImgReal.Text;
end;

Quando for modicada a posição do combo que contém os campos em formato Imagem da página Tabela faz
as alterações necessárias setando o objeto DBImage1 para o novo campo.

23. Para o evento onExit do objeto TabFicha

procedure TF_Ficha.TabFichaExit(Sender: TObject);


begin
if fTrava then begin
ButPostClick(Sender);
TabFicha.SetFocus;
end;
end;

A Inserção de Registros em Lote é realizada da seguinte forma, é disparado um comando Insert para a tabela
e posicionado no primeiro campo, o usuário digitará até o último campo pressionando a tecla Tab quando ele chegar no
último campo ele pressionará mais um Tab isto fará com que este comando seja ativado, então confirmaremos a
gravação do registro digitado, chamando o procedimento para tal, e retornaremos para o primeiro campo.

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página 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 botão Duplica Registro fará com que esta trenheira (gostei do trenheira) de código
seja executado, é simples, com o auxílio do objeto Query público da D_Modelo (Objeto QrySQL) geraremos um
comando SQL que quando disparado conterá o registro atual, apenas ele, após isto basta com que após cada comando
Insert copiemos campo a campo do objeto Query para a Tabela.

25. Para o evento onClose do Formulário

procedure TF_Ficha.FormClose(Sender: TObject; var Action: TCloseAction);


begin
if FiltroVisto <> '' then
with dsVisao.DataSet do begin
if Active then Close;
Filter := '';
Filtered := False;
end;
if ButGotoMark.enabled then
with dsVisao.DataSet do FreeBookmark(FBM);
with D_Modelo.QrySQL do if Active then Close;
end;

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página Nr. 127/178
Antes do usuário sair, cancelaremos o filtro, caso exista algum, finalizaremos caso tenha sido criado o ponteiro
de guardar registros e fecharemos, caso esteje ativa, o objeto Query Público da D_Modelo.

Finalmente
Na próxima apostila criaremos a primeira utilização deste formulário através da Herança dos Objetos.

Dúvidas das Apostilas Anteriores


Como faço para criar tabelas relacionadas ?

Use o gerenciador do banco de dados para isso ou você quer criá-los via programação ? se sim não faça isso pois os
comandos variam muito de banco para banco.

Posso relacioná-las no Access ?

Claro, mas lembre-se que alguns bancos não permitem o relacionamento de Alteração e Exclusão em cascata como o
Access permite, entaum se vc quer um sistema portátil não utilize essa opção mesmo sendo ela muito prática.

ou uso MasterSource ?

Você não relaciona tabelas com as opções MasterSource e MasterFields o que você faz é criar um indice virtual, isso
apenas serve para controlar entradas e visões dos dados nada mais.

Qual a melhor solução ? Ex. Produto -> Items

Quando utilizava o Paradox naum utilizava relacionamentos deixava o sistema controlar toda a entrada dos dados,
quando passei a usar o Access comecei a definir meus relacionamentos no próprio banco mas sempre tomando o
cuidado para que o sistema naum deixe passar besteiras, acredito que vc próprio saberá o que é melhor para seu sistema
pois cada caso é uma sentença.

A minha duvida é com relação ao Access/Multiusuario, isto é possível?

Sim ele é um banco multiusuário, ou controlado o acesso livremente ou por determinados usuários com determinadas
permissões.

e com relação a distribuição?

Veja a apostila 4 como criar o Install Shield para isto.

Com o Access isto também acontece?

A forma de acesso ao Access é pelo DAO, seu cliente precisa tê-lo ou vc a permissão para instalá-lo.

o DAO3032.DLL nao foi encontrado em um determinado diretorio. O bom e velho

Isto ocorre porque vc precisa instalar o DAO 3.5, instale o APE Work disponível no endereço citado da home page do
Bruno.

Ja li sua resposta no final da apostila 7. Possuo Windows 95 e o Office ORIGINAIS !!!!! Sera que nao resolve ?!?

Dependendo naum resolve pois vc terá apenas o DAO 3.0, mas se vc conseguir conexão com ele sem problemas então
deixe a IDDAO32.DLL

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página 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 configurações que você fala na sua Home Page, desabilitei o botão de
"login prompt" no componente DataBase do Delphi, mas ainda o problema de pedir o login para acessar a base persiste.
O meu Delphi é o 3.0 e você fala que os exemplos são todos para a versão 3.02 do Delphi. Será que os meus problemas
são por causa da minha versão do Delphi ??? Onde posso arrumar um uprade para atualizar a minha versão de Delphi
???

Sempre em modo de edição ele pedirá para vc a janela Status Login, apenas com o sistema rodando que ele parará de
pedir pois entrará ou no LoginPrompt := False ou no evento OnLogin (conforme as apostilas 3 e 10). O problema naum
é com seu Delphi mas para atualizá-lo para a versão 3.02, primeiro vc tem que pegar aonde vc comprou o Delphi a
versão 3.01, depois vc vai no próprio site da Inprise e pega a atualização para 3.02, ATENÇÃO: Não baixe a 3.02 em
cima da 3.0.

A senha e pedida e se eu der o OK o erro ocorre.

O que é óbvio porque apenas neste momento que vc está tentando o acesso ao DAO.

É preferível sempre trabalhar com Querys? Quando devo usar Tables ?

Isso surgiu com o Delphi 1.0 e se estendeu com o Delphi 2.0, pois os objetos Query´s eram indiscutivelmente mais
rápidos e práticos que os Table´s mas se vc está utilizando o Delphi 3.0 ou Delphi 4.0 a Inprise já corrigiu e acertou os
objetos Table´s, então aconselho que vc os utilize.

Qual a melhor maneira de procurar um registro usado query ? Pode ser o Locate ?

Usando a cláusula Where.

Como devo fazer a consitencia do meu sistema para não deixar que registros duplicatos sejam cadastrados ? Faço a
procura em outra Query? Crio em run_time ?

Crie outra table para procura, ou uma query para procurar, mas modifique o comando SQL via programa, pois assim vc
pode utilizar uma única query para seu sistema inteiro.

Uso DBEdit ? ou a melhor opção são Edits ?

Os DBEdit são melhores.

Os indíces, ou By Order, ...Permito que o usário escolha a ordem dos dados? Neste caso coloquei no evento
OnTitleClick do DBGrid o seguinte código.

procedure TFClas.DBGridClasTitleClick(Column: TColumn);


var Chave:String;
begin
Chave:=Column.FieldName;
With QueryClas do begin
Close;
SQL.Clear;
SQL.Add('Select * from Classe');
SQL.Add('Order By ' + Chave );
Open;
end;
end;

É a melhor opção ?

Se vc está utilizando Query´s para cadastrar é, mas eu naum recomendo seu uso depois do Delphi 3.0.

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página Nr. 129/178
Em um sistema, 60% se resume em inclui, altera, exclui,consulta. Se eu estiver equivocado por favor me corrija...

Não tenho como fazê-lo no meu caso as vezes é quase 90%

Nao sei direito como funciona o relacionamento entre tabelas do Access. No clipper eu criava minhas tabelas (.DBF) e
depois com SET RELATION... relacionava a tabela PAI com a tabela FILHO. Quando posicionava o registro na tabela
PAI, seu correspondente na tabela FILHO ja era posicionado automatico. No access criei um .MDB com duas tabelas,
uma PAI e outra FILHO. Na aba de relacionamento (dentro do ACCESS97) fiz o relacionamento, salvei e abri o
DELPHI. Iniciei um novo projeto coloquei dois table/datasource/grid. Fiz as conexoes, porem quando movimento o
registro na tabela PAI, a tabela filho nao se movimenta! Isso esta correto? Se sim, entao para que serve o
relacionamento feito dentro do Access em um programa delphi? No teste que eu fiz, o relacionamento dentro do access
nao funcionou no programa em delphi.

Se vc quer movimentar o PAI e movimentar o FILHO use os parametros Master do objeto Table para isso. Os
relacionamentos no banco de dados, em qualquer deles, serve para garantir que só existirá FILHOS se existirem PAIS,
é que um PAI dependendo da regra não pode morrer ou modificar sua chave se ouverem FILHOS atrelados a eles. Para
o Delphi isso serve pois vc não precisa codificar isso.

O que voce acha do OPUS para acessar MDB em relacao ao BDE 4.51 ??? Qual a melhor opcao?

OPUS sem sombra de dúvida, é rápido, prático e seguro, utilizo o BDE para manter a integridade e portabilidade dos
sistemas para qualquer banco de dados, não sei se amanhã resolvo mudar do Access para outra coisa qualquer.

Gostaria de armazenar um conjunto de imagens diretamente no banco de dados, que pode ser Access97 ou Paradox 7.0
e depois empregá-las no meu projeto. Qual seria o tipo de campo ideal para armazenar estas imagens e qual seria o
procedimento para fazer a visualização dessas imagens? Se isto for possível(eu sei que é, só não sei como) quais os
formatos além do Bmp e ico que o delphi aceita, poderia ser empregado?

No Access e no Paradox é um campo OLE e no Delphi vc os associa a um campo DBImage, existe um exemplo nos
Demos do Delphi sobre isso. O Delphi aceita qualquer formato pois para colocar uma imagem nesses campos o que vc
faz é recortar a imagem e colar, vc pode desenvolver uma função que faça isso.

Existe algum componente que permite a "Justificação" de texto nos relatórios criados via QuickReport?

Nunca o vi, mas talvez o QR que vem com o Delphi 4 já vem com isso, vou dar uma pesquisada nele aguarde notícias.

Suponha que eu tenho 5 micros ligados em rede win95 com nenhum computador servidor dedicado(apenas
compatilhamento de arquivos e hardware). Seria possível a utilização do programa Mapa criado nas apostilas 2,3,4 e
todo a rede, elegendo por exemplo, o micro1 como local de instalação do programa e do banco de dados? Em todos os
micros temos instalados os mesmo programas (Access97, win95 e bde 4.51)

É possível sem problema nenhum e vc naum precisa do Access97 instalado nos micros apenas o Win95 - Sistema -
BDE 4.51 - DAO, para instalar tudo siga as instruções da nova apostila 4.

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página 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 versão Client/Server Suite
BDE 5.00
MS-Access 97

Arquivos trabalhados juntos com esta apostila:

Formulário : F_Ficha (criado na Apostila 11)

Objetos: DBCmpList
DBDateEdit97

Seguintes Imagens :
ImgLamp.BMP
ImgTerc.BMP
ImgTele.BMP

Prefácio
Salve, nesta apostila desvendaremos a segunda parte de como criar os cadastros dos nossos sistemas.

Na apostila passada criamos a primeira parte dos cadastros que foi a construção de um formulário que servirá
como base de todos os cadastros, neste mostrarei como utilizar o formulário criado, lembre-se que definimos quatro
cadastros: Cidade, Grupo, Alimento e Cliente. Aqui criarei o formulário para o Cadastro de Cliente que é o mais
complexo de todos, então caberá a você, após este, a criação dos formulários para os cadastros de Cidade, Grupo e
Alimento.

Como utilizar a Herança


A coisa que mais falei na apostila passada foi no tocante a Herança, então vamos fazer uso dela, inicialmente
reabra o nosso projeto e proceda da seguinte maneira:

1. A partir do Menu Principal vá em File | New... e vá na página Peso, escolha o formulário F_Ficha e clique em Ok.

Pronto, primeiramente vamos começar bem devagar, neste momento foi criado uma cópia, um espelho ou se
você prefere um novo objeto formulário baseado por herança no objeto formulário F_Ficha. NÃO altere neste
formulário criado qualquer posição dos botões, NÃO faça modificações na janela, NADA. Se tiver que fazer este tipo
de alteração faça no formulário F_Ficha pois deste modo automaticamente todos os outros formulários que foram
herdados serão alterados. Altere aqui o extritamente necessário, pois cada alteração causa um desvínculo da herança.

Para este objeto altere apenas as seguintes propriedades:

1.1. Name: F_Cliente


1.2. Caption: Cadastro de Clientes...
1.3. Salve o formulário com o nome de fCliente.PAS
Note que precisamos preencher o miolo da primeira parte (A página da ficha propriamente dita), para tanto:

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página Nr. 131/178
2. A partir do Menu Principal vá em File | New... e vá na página Business, escolha o formulário "Database Form
Wizard" e clique em Ok:

2.1. O tipo do formulário a ser criado. Para a opção Form Options marque Create a simple form (Um
formulário simples) e para a opção DataSet Options marque Create a form using TTables objects (Usando o
objeto tabela) e clique no Botão Next.

2.2. A tabela a ser usada para o formulário. Para a opção Drive or Alias name localize o Alias AlPeso e para a
opção Table Name marque Cliente e clique no Botão Next.

2.3. Campos a serem inseridos clique no Botão ">>" para ser inserido todos os campos e clique no Botão
Next.

2.4. Clique na opção Vertically para a formação dos campos na Vertical e clique no Botão Next

2.5. Posição dos Labels deixe marcada a opção Left (A esquerda) e clique no Botão Next

2.6. Completo. Desmarque a opção Generate a main form (Gera a tela como form principal) e na opção
Form Generation marque Form e clique no Botão Finish.

3. Agora selecione todos os campos e respectivos labels e digite CTRL+C vá para o formulário F_Cliente e clique na
página Ficha selecione a página e digite CTRL+V dê uma arrumada nos campos, você deve conseguir algo como isto:

Este segundo formulário criado já serviu para seu propósito pode fechá-lo cancelando qualquer procedimento
para sua gravação.

☞Importante - Existem várias maneiras de se criar este formulário que mostrei, garanto que em breve você
dominará uma maneira que mais lhe agrade, particularmente prefiro deste modo.

Acertando os campos
4. Inicilmente vamos nos ocupar dos objetos Label´s, altere as seguintes propriedades de todos:

4.1. Propriedade Caption (respectivamente):


CPF:
Nome:
Endereço:
Bairro:
CEP:
Cidade:
eMail:
Altura:

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página 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 espaço entre o campo CEP e eMail e elimine o objeto EditSIG_CIDADE,
e na página Data Controls localize o objeto DBCmpList e coloque-o no lugar deste.

☞Importante - Abra o Data Module D_Modelo, volte para o formulário F_Cliente e alterne para a janela do
programa e insira a seguinte declaração após a diretiva de compilação:

{$R *.DFM}

uses
dModelo;

6. Marque o objeto DsVisao e altere a propriedade DataSet para D_Modelo.tbCliente.

7. Para o objeto DBCmpList criado altere as seguintes propriedades:

7.1. Desça-o para o espaço aberto entre os campos CEP e eMail


7.2. CapLocaliza: Localiza determinada Cidade
7.3. Caption:
7.4. CriticaEd: False
7.5. DataSource: DsVisao (Atenção: Não marque, caso apareça F_Ficha.DsVisao)
7.6. DataField: SIG_CIDADE
7.7. GlyphLoc: ImgLamp.BMP (Enviado)
7.8. HintButLoc: Localiza determinada Cidade
7.9. MensagemCodigo: Sigla da Cidade não localizada
7.10. MensagemDescricao: Cidade não localizada
7.11. Name: CmpCidade
7.12. PosCmpCodigoSec: 0
7.13. PosCmpDescricao: 1
7.14. TbSecundaria: D_Modelo.tbCidade
7.15. TipoSQL: Access
7.16. UsaDescricao: True
7.17. UsaLocaliza: True

8. Marque este objeto e vá na página Additional e coloque um objeto SpeedButton em cima do objeto CmpCidade ao
lado do botão de localizar e altere as seguintes propriedades:

8.1. Flat: True


8.2. Glyph: ImgTerc.BMP
8.3. Hint: Chama o cadastro de Cidade
8.4. Name: ButIncCidade
8.5. ShowHint: True

9. Elimine o campo EditDAT_NASCIMENTO e coloque um DBDateEdit97 no lugar e altere as seguintes


propriedades:

9.1. DataSource: DsVisao


9.2. DataField: DAT_NASCIMENTO
9.3. Name: EditDAT_NASCIMENTO

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página 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 sequência.

O trabalho final ficou desta maneira:

Criando Mais uma Orelha


Note através do nosso modelo que a tabela de CLIENTE tem um relacionamento de 1 para N com a tabela de
TELEFONE_CLIENTE, normalmente adoto o seguinte método para o cadastro desse tipo.

11. Dê um Duplo-Clique no objeto ImageList1, clique no botão Add... e insira a imagem ImgTele.BMP (enviada)

12. Clique no objeto PgPrincipal e depois clique com o botão direito no sub-menu que aparece clique na opção New
Page.

13. Para esta nova página criada altere as seguintes propriedades:

13.1. Caption: Telefones


13.2. Name: TabTelefone

14. Crie agora três objetos:

14.1. Label e altere as seguintes propriedades:

14.1.1. Caption: Inclua aqui os telefones de Contato do Cliente:


14.1.2. Propriedade Font para:
Font.Color = clMaroon
Font.Style = [fsBold]

14.2. DataSource e altere as seguintes propriedades:

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página 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 , altere as seguintes
propriedades:

para a coluna 0

FieldName: NUM_TELEFONE
Font.Color: clNavy
Title.Caption: Número do Telefone
Title.Font.Color: clMaroon
Title.Font.Style: [fsBold]
Width: 200

para a coluna 1

FieldName: DES_FUNCAO
Font.Color: clNavy
Title.Caption: Função
PickList: Voz; FAX; Voz e FAX; PABX (Um em cada linha)
Title.Font.Color: clMaroon
Title.Font.Style: [fsBold]
Width: 104

Não vamos nos preocupar aqui com os detalhes de controlar qual telefone e de qual cliente pois esta amarração
foi realizada no DataModule através do objeto tbTELEFONE_CLIENTE, veja como ficou esta nova página:

Difícil Programação
Você vai se surpreender com a programação criada aqui, a maior parte do trabalho ficou com o formulário
anterior, este é a apenas um espelho do passado e sua programação é quase mínima e teremos apenas três trabalhos,
vamos a ela:

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página Nr. 135/178
1° Trabalho. Abrir as tabelas. Para tanto selecione o evento OnShow do formulário:

procedure TF_Cliente.FormShow(Sender: TObject; var Action: TCloseAction);


begin
with D_Modelo do begin
with tbCIDADE do begin
Tab1 := Active;
if not Tab1 then Open;
end;
with tbCLIENTE do begin
Tab2 := Active;
if not Tab2 then Open;
end;
with tbTELEFONE_CLIENTE do begin
Tab3 := Active;
if not Tab3 then Open;
end;
end;
inherited;
end;

e crie três variáveis na Seção Particular do Objeto:

private
Tab1, Tab2, Tab3 : Boolean;

Uma explicação geral é a seguinte, sempre que abro um formulário de cadastro abro respectivamente as
tabelas que ele utiliza na D_Modelo, mas como um formulário pode chamar outro formulário então corrijo isso através
de variáveis locais que armazenam se a respectiva tabela já se encontrava ou não aberta quando o formulário foi
ativado.

☞Importante - Aqui a ordem dos tratores altera o viaduto, o objeto DBCmpList exige que a tabela secundária
(tbCidade) seja aberta primeiramente que a tabela que serão gravados os dados (tbCliente).

Um outro comando que você pode estranhar é o comando inherited ele é o responsável por chamar os
comandos que estão localizados no evento OnShow do formulário Pai.

2° Trabalho. Fechar as tabelas. Para tanto selecione o evento OnClose do formulário:

procedure TF_Cliente.FormClose(Sender: TObject; var Action: TCloseAction);


begin
with D_Modelo do begin
case CriticaEdicao(dsVISAO, 'do Cliente', 'fechar') of
mrYes : tbCLIENTE.Cancel;
mrNo : begin
Action := caNone;
Exit;
end;
end;
// ***
Screen.Cursor := crHourGlass;
if not Tab3 then tbTELEFONE_CLIENTE.Close;
if not Tab2 then tbCLIENTE.Close;
if not Tab1 then tbCIDADE.Close;
end;
inherited;
end;

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página Nr. 136/178
Aqui é relativamente simples, através da função CriticaEdicao que será montada na D_Modelo verifica-se se
o estado da tabela Cliente está em estado de Edição ou Inserção em caso positivo, podemos cancelar a Edição ou
cancelar o Fechamento da janela.

Na segunda parte devolvemos o estado original das tabelas.

☞Importante - Novamente a ordem dos camarões altera o vatapá, o objeto DBCmpList exige que a tabela que serão
gravados os dados (tbCliente) seja fechada primeiramente que a tabela secundária (tbCidade).

3° Trabalho. É o botão responsável por chamar o Cadastro de Cidade para tanto de um duplo-clique no objeto
ButIncCidade para ativar o evento OnClick:

procedure TF_Cliente.ButIncCidadeClick(Sender: TObject);


begin
inherited;
ChamaExterno(D_Modelo.tbCIDADE, TF_CIDADE);
end;

Não se esqueça de declarar o formulário utilizado na USES:

uses
dModelo, fCidade;

Esse foi moleza pois basta que chamemos a função ChamaExterno localizada no formulário F_Ficha, note
que por ser uma função localizada no objeto que herdamos não precisamos nem fazer a referência para ela.

Alterando a D_Modelo
Lembra-se que na apostila referente ao DataModule avisei que algumas funções seriam posteriormente
incluídas ? Então vamos começar estas inclusões:

Função Responsável pela Verificação do Estado de uma Tabela:

1. Abra o DataModule D_Modelo através do Code Editor e localize a seção Public, insira o seguinte cabeçalho para a
declaração da função coloque-o abaixo da declaração das variáveis:

public
nmAlimento, nmCidade, nmGrupo, nmPasta_Cliente, nmPeso_Cliente, //
nmResumo_Mensal, nmTelefone_Cliente, nmCliente : String;
function CriticaEdicao(DSOrigem: TDataSource; DoQue: String; AntesDe: String) :Word;
end;

2. Após a diretiva de compilação insira os seguintes comandos:

{$R *.DFM}

function TD_Modelo.CriticaEdicao(DSOrigem: TDataSource; DoQue: String; AntesDe: String) :Word;


begin
if DSOrigem.State in [dsEdit, dsInsert] then
result := MessageDlg('Necessário cancelar a edição (ou Inclusão) ' + Doque +
' antes de ' + AntesDe + '. Deseja sair agora ?', mtConfirmation, [mbYes, mbNo], 0)
else
result := mrNone;
end;

Vamos a uma explicação geral, a função é relativamente simples, ela recebe três variáveis sendo uma delas um
objeto inteiro, uma coisa fantástica na linguagem Object Pascal é a possibilidade de passar objetos inteiros atraves de
funções ou procedimentos, são passados os seguintes:

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página 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 edição

Então caso o DataSource passado esteja em estado de Edição ou inserção será mostrada a seguinte mensagem
"Necessário cancelar a edição (ou Inclusão) Conteúdo_Doque antes de Conteúdo_AntesDe. Deseja sair agora ?" e
mostrado dois botões "Sim" ou "Não" o resultado será um dos dois, caso contrário será devolvido um resultado
mrNone.

Função Responsável pela crítica do CPF do Cliente:

1. Localize agora a seção Private, e insira o seguinte cabeçalho para a declaração da função:

private
function Maximo(nmCampo, nmTabela: String) : integer;
function Critica_CPF(sNumCpf: String) : Boolean;

2. Após a diretiva de compilação insira os seguintes comandos:

{$R *.DFM}

function TD_Modelo.Critica_CPF(sNumCpf: String) :boolean;


var
I, J, nMod, nSubTotal, nTotal, nDv: Integer;
sChar, sNumCpfCalc: String;
begin
Result := True;
if sNumCpf = '' then Exit;
sNumCpfCalc := Copy(sNumCpf,1,9);
for I := 1 to 2 do begin
nMod := 2;
nTotal := 0;
for J := Length(sNumCpfCalc) downto 1 do begin
sChar := Copy(sNumCpfCalc, J, 1);
nSubTotal := (StrToInt(sChar) * nMod);
nTotal := nTotal + nSubTotal;
Inc(nMod);
end;
nDv := (11 - (nTotal mod 11));
if nDv > 9 then nDv := 0;
sNumCpfCalc := sNumCpfCalc + IntToStr(nDv);
end;
Result := (sNumCpfCalc = sNumCpf);
end;

3. Dê um duplo clique em cima da Tabela de Clientes e marque o campo NUM_CPF para o evento OnValidade
insira os seguintes códigos:

procedure TD_Modelo.tbClienteNUM_CPFValidate(Sender: TField);


begin
if not Critica_CPF(tbClienteNUM_CPF.Value) then
Raise Exception.Create('CPF não confere com o da Receita Federal');
end;

A função é o cálculo do famoso MÓDULO 11, você já deve ter ouvido falar isso várias vezes, o cálculo para o
primeiro dígito é feito pegando-se os nove primeiros números do CPF e multiplicando-os da seguinte maneira, o
primeiro por 10, o segundo por 9 e assim sucessivamente até o nono número por 2, e este valor somado (isto é realizado
no segundo comando FOR) é aplicada a seguinte equação:

Digito1 = 11 - Resto( Soma / 11)

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página Nr. 138/178
A função MOD dá exatamente o resto de uma divisão. Se o valor deste primeiro dígito for maior que 9 o
resultado é 0, adiciona-se este digito aos outros nove e realiza-se uma nova multiplicação com os 10 números da
seguinte maneira, o primeiro por 11, o segundo por 10 e assim sucessivamente até o décimo número por 2, aplica-se a
mesma fómula anterior para encontrar o resultado do segundo dígito.

☞Importante - Neste sistema não precisaremos, mas vou colocar aqui os códigos caso você precise, da função para
a crítica do CGC de Empresas.

function TD_Modelo.Critica_CGC(sNumCgc: String) : boolean;


var
I, J, nMod, nSubTotal, nTotal, nDv: Integer;
sChar, sNumCgcCalc: String;
begin
Result := True;
if sNumCgc = '' then Exit;
sNumCgcCalc := Copy(sNumCgc,1,12);
for I := 1 to 2 do begin
nMod := 2;
nTotal := 0;
for J := Length(sNumCgcCalc) downto 1 do begin
sChar := Copy(sNumCgcCalc, J, 1);
nSubTotal := (StrToInt(sChar) * nMod);
nTotal := nTotal + nSubTotal;
inc(nMod);
if nMod > 9 then nMod := 2;
end;
nDv := (11 - (nTotal mod 11));
if nDv > 9 then nDv := 0;
sNumCgcCalc := sNumCgcCalc + IntToStr(nDv);
end;
Result := (sNumCgcCalc = sNumCgc);
end;

Finalmente
Agora basta você voltar para o formulário F_Menu para fazer a inserção dos comandos para chamar o
formulário:

procedure TF_Menu.Cliente1Click(Sender: TObject);


begin
F_Cliente := TF_Cliente.Create(Application);
F_Cliente.ShowModal;
F_Cliente.Free;
end;

Também chame a partir do menu principal Project | Options... e retire o formulário F_Cliente da área dos
Auto-Create forms (retire também o F_Ficha caso você ainda não o fez)

☞Importante - Este formulário precisa do Formulário F_Cidade já criado para funcionar.


Agora cabê a você a criação dos formulários F_Cidade, F_Grupo e F_Alimento. Até a próxima.

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página 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 versão Client/Server Suite
BDE 5.00
MS-Access 97

Arquivos trabalhados juntos com esta apostila:

Objeto : DBDateEdit97

Seguintes Imagens :
ImgLamp.BMP, ImgTerc.BMP, ImgGrava.BMP, ImgCancela.BMP

Prefácio
Salve, nesta apostila começaremos as primeiras movimentações do nosso projeto.

A movimentação basicamente é dividida em duas fases: dados de Entrada ou dados de Saída, nesta vamos
analisar a movimentação para Dados de Entrada. Esta fase deve ser lembrada como um formulário fácil e simples para
que o usuário não se confunda com o processo que ele realizará.

Entrada de Clientes
Inicialmente vamos construir a parte da movimentação relativa a Entrada de Clientes, é o momento em que o
Cliente entra no SPA e é cadastrado em algum plano

1. A partir do Menu Principal vá em File | New Form e para este objeto altere apenas as seguintes propriedades:

1.1. BorderStyle: bsDialog


1.2. Caption: Entrada de Clientes
1.3. Name: F_Entrada
1.4. Position: poScreenCenter
1.5. Salve o formulário com o nome de fEntrada.PAS

2. Crie um objeto do tipo TPanel e altere as seguintes propriedades:

2.1. BevelInner: bvLowered


2.2. BorderWidth: 4
2.3. Align: alTop

3. Crie dentro deste Panel seis objetos do tipo Label e altere as seguintes propriedades

3.1. Propriedade Caption (respectivamente):


CPF:
[Nome do Cliente]
Data:
Plano:
Qtd.Caloria:

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página Nr. 140/178
Observação:

3.2. Propriedade Font para:


Font.Color = clMaroon
Font.Style = [fsBold]

3.3. Propriedade AutoSize para True, menos para o segundo Label

3.4. Para o segundo Label altere as seguintes propriedades

3.4.1. LabNOM_CLIENTE
3.4.2. Estique-o para ficar com o tamanho do Panel

☞ Importante - Abra o Data Module D_Modelo, volte para o formulário F_Entrada e alterne para a janela do
programa e insira a seguinte declaração após a diretiva de compilação:

{$R *.DFM}

uses
dModelo;

4. Crie um objeto do tipo DataSource e altere as seguintes propriedades:

4.1. DataSet: D_Modelo.tbPasta_Cliente


4.2. Name: dsPasta_Cliente

5. Crie dentro deste Panel um objeto do tipo dbEdit e altere as seguintes propriedades

5.1. DataSource: dsPasta_Cliente


5.2. DataField: NUM_CPF
5.3. Font.Color: clNavy
5.4. Name: EditNUM_CPF

6. Ao lado deste objeto criado crie mais dois objetos do tipo SpeedButton e altere as seguintes propriedades:

6.1. Para o primeiro SpeedButton:


6.1.1. Flat: True
6.1.2. Glyph: ImgLamp.BMP
6.1.3. Hint: Localiza determinado Cliente
6.1.4. Name: ButLocCliente
6.1.5. ShowHint: True

6.2. Para o segundo SpeedButton:


6.2.1. Flat: True
6.2.2. Glyph: ImgTerc.BMP
6.2.3. Hint: Chama o cadastro de Clientes
6.2.4. Name: ButIncCliente
6.2.5. ShowHint: True

7. Crie dentro do objeto Panel1 um objeto do tipo dbDateEdit97 e altere as seguintes propriedades

7.1. DataSource: dsPasta_Cliente


7.2. DataField: DAT_CORRENTE
7.3. Font.Color: clNavy
7.4. Name: EditDAT_CORRENTE

8. Crie dentro do objeto Panel1 dois objetos do tipo DBRadioGroup e altere as seguintes propriedades

8.1. Para o primeiro DBRadioGroup:


8.1.1. DataSource: dsPasta_Cliente

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página 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 Reeducação
Plano Completo
Plano Especial de Reeducação
8.1.5. Values: (Um por Linha)
A;B; C;D
8.1.6. Columns: 2

8.2. Para o segundo DBRadioGroup:


8.2.1. DataSource: dsPasta_Cliente
8.2.2. DataField: QTD_CALORIA
8.2.3. Font.Color: clNavy
8.2.4. Items: (Um por Linha)
800 KCal
1.000 KCal
1.200 KCal
1.500 KCal
1.800 KCal
8.2.5. Values: (Um por Linha)
0800 ; 1000 ; 1200 ; 1500 ; 1800
8.2.6. Columns: 2

9. Crie dentro do objeto Panel1 um objeto do tipo DBMemo e altere as seguintes propriedades

9.1. DataSource: dsPasta_Cliente


9.2. DataField: OBS_PASTA
9.3. Font.Color: clNavy
9.4. Name: MemoOBS_PASTA

10. Acerte a propriedade TabOrder para a sequência correta.

11. Abaixo do Objeto Panel1 crie três objetos do tipo BitBtn e altere as seguintes propriedades:

11.1. Para o primeiro BitBtn:


11.1.1. Caption: &Grava
11.1.2. Glyph: ImgGrava.BMP
11.1.3. Hint: Grava os dados na Pasta do Cliente
11.1.4. Name: ButGrava
11.1.5. ShowHint: True

11.2. Para o segundo BitBtn:


11.2.1. Caption: &Cancela
11.2.2. Glyph: ImgCancela.BMP
11.2.3. Hint: Cancela e limpa a entrada dos dados
11.2.4. Name: ButCancela
11.2.5. ShowHint: True

11.3. Para o terceiro BitBtn:


11.3.1. Kind: bkClose
11.3.2. Caption: &Fechar
11.3.3. Hint: Fecha esta janela retornando ao menu do sistema
11.3.4. ShowHint: True

O trabalho final ficou desta maneira:

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página Nr. 142/178
Programando a Entrada
Lembre-se, a programação aqui é uma coisa rápida é direta, ela não deve ser aplicada em situações de risco,
como por exemplo um cadastro.

1. Inicialmente alterne para a Code Editor e na seção Private crie a seguinte chamada para o procedimento:

private
procedure AcertaInsercao;
public

2. Agora abaixo da diretiva de compilação crie o procedimento proposto:

{$R *.DFM}
uses
dModelo;

procedure TF_Entrada.AcertaInsercao;
begin
D_Modelo.tbPasta_Cliente.Insert;
LabNOM_CLIENTE.Caption := '';
end;

Este procedimento será chamado toda vez que for feito uma nova inclusão na tabela Pasta Cliente.

3. Selecione agora o evento OnShow do formulário:

procedure TF_Entrada.FormShow(Sender: TObject);


begin
with D_Modelo do begin
tbCliente.Open;
SelPesquisa.NomeTela := 'Seleciona Determinado Cliente';
SelPesquisa.Tabela := tbCliente;
tbPasta_Cliente.Open;
end;
AcertaInsercao;
end;

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página Nr. 143/178
Toda vez que o formulário for ativado, e aberta a tabela acessória tbCliente e organizado os campos dentro do
objeto SelPesquisa localizado na D_Modelo, depois aberta a tabela em que será realizada toda a movimentação a
tbPasta_Cliente e chamado o procedimento particular para colocá-la em estado de inserção.

4. Selecione o evento OnClose do formulário:

procedure TF_Entrada.FormClose(Sender: TObject; var Action: TCloseAction);


begin
with D_Modelo do begin
tbCliente.Close;
tbPasta_Cliente.Cancel;
tbPasta_Cliente.Close;
end;
end;
Aqui é relativamente simples, simplesmente fechamos as tabelas cancelando o estado de inserção da tabela
principal.

5. Vamos começar com os botões, primeiro o botão responsável para realizar a Gravação na Pasta para tanto de um
duplo-clique no objeto ButGrava para ativar o evento OnClick:

procedure TF_Entrada.ButGravaClick(Sender: TObject);


begin
if EditNUM_CPF.Text = '' then
raise exception.create('Cliente não informado');
if LabNOM_CLIENTE.Caption = '' then
raise exception.create('Cliente não cadastrado');
D_Modelo.tbPasta_Cliente.Post;
AcertaInsercao;
end;

Fazemos duas críticas simples apenas para controlar se o CPF foi preenchido e se o nome do cliente foi
encontrado (o que significará que o cliente existe), então gravamos o dado e simplesmente chamamos o procedimento
para reativar o estado de inserção.

6. O segundo botão é o responsável para realizar o Cancelamento dos dados para tanto de um duplo-clique no objeto
ButCancela para ativar o evento OnClick:

procedure TF_Entrada.ButCancelaClick(Sender: TObject);


begin
D_Modelo.tbPasta_Cliente.Cancel;
AcertaInsercao;
end;

Este aqui é simplesmente disparar um comando Cancel para a tabela e chamarmos o procedimento para
reativar o estado de inserção.

Programando o Cliente
A ligação entre a tabela Pasta_Cliente e Cliente deverá ser totalmente controlada aqui, poderiamos usar do
objeto CmpTerc para fazer este controle (igual fizemos no cadastro) mas preferi deixar o Cliente solto, então vamos
aos passos:

1. Selecione o objeto EditNUM_CPF e chame o evento OnExit:

procedure TF_Entrada.EditNUM_CPFExit(Sender: TObject);


begin
if EditNUM_CPF.Text <> '' then
with D_Modelo.tbCliente do

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página 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 não cadastrado');
end;
end;

Inicialmente verificamos se foi preenchido algo no campo, então pesquisamos na tabela Cliente com o valor
informado, caso encontre coloca o nome do cliente no Label destinado para tal, caso contrário volta o cursor para o
objeto EditNUM_CPF e mostra a mensagem de erro.

2. O primeiro o botão localizado depois do campo é o responsável para realizar a Consulta do Cliente para tanto de um
duplo-clique no objeto ButLocCliente para ativar o evento OnClick:

procedure TF_Entrada.ButLocClienteClick(Sender: TObject);


begin
with D_Modelo do
if SelPesquisa.Execute then
EditNUM_CPF.Text := tbClienteNUM_CPF.AsString;
end;
São comando simples, executamos o objeto SelPesquisa e caso ele traga uma resposta verdadeira apenas
adicionamos o valor do campo NUM_CPF da tabela cliente ao objeto EditNUM_CPF.

3. A pior coisa de um sistema, é por exemplo o Cliente não estar cadastrado e o usuário ser obrigado a sair da tela em
que se encontra e cadastrar o cliente e depois retornar, para evitar isto o segundo botão é o responsável para chamar o
Cadastro de Cliente para tanto de um duplo-clique no objeto ButIncCliente para ativar o evento OnClick:

procedure TF_Entrada.ButIncClienteClick(Sender: TObject);


begin
F_Cliente := TF_Cliente.Create(Application);
F_Cliente.ShowModal;
F_Cliente.Free;
end;

Aqui apenas disparamos a chamada ao formulário de Cliente, exatamente como é feito no menu principal, não
se esquece de adicionar o formulário fCliente a cláusula USES.

Massa Corporal
Outro exemplo de movimentação de entrada é o formulário para fazer a Massa Corporal, é o momento em
que o Cliente é pesado e sua massa é mostrada em um cálculo (Recorde este cálculo na apostila referente ao
Levantamento dos Dados):

1. A partir do Menu Principal vá em File | New Form e para este objeto altere apenas as seguintes propriedades:

1.1. BorderStyle: bsDialog


1.2. Caption: Massa Corporal
1.3. Name: F_Massa
1.4. Position: poScreenCenter
1.5. Salve o formulário com o nome de fMassa.PAS

2. Crie um objeto do tipo TPanel e altere as seguintes propriedades:

2.1. BevelInner: bvLowered


2.2. BorderWidth: 4
2.3. Align: alTop

3. Crie dentro deste Panel seis objetos do tipo Label e altere as seguintes propriedades

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página 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 formulário F_Entrada e alterne para a janela do
programa e insira a seguinte declaração após a diretiva de compilação:

{$R *.DFM}

uses
dModelo;

4. Crie um objeto do tipo DataSource e altere as seguintes propriedades:

4.1. DataSet: D_Modelo.tbPeso_Cliente


4.2. Name: dsPeso_Cliente

5. Crie dentro deste Panel um objeto do tipo dbEdit e altere as seguintes propriedades

5.1. DataSource: dsPeso_Cliente


5.2. DataField: NUM_CPF
5.3. Font.Color: clNavy
5.4. Name: EditNUM_CPF

6. Ao lado deste objeto criado crie mais dois objetos do tipo SpeedButton e altere as seguintes propriedades:

6.1. Para o primeiro SpeedButton:


6.1.1. Flat: True
6.1.2. Glyph: ImgLamp.BMP
6.1.3. Hint: Localiza determinado Cliente
6.1.4. Name: ButLocCliente
6.1.5. ShowHint: True

6.2. Para o segundo SpeedButton:


6.2.1. Flat: True
6.2.2. Glyph: ImgTerc.BMP
6.2.3. Hint: Chama o cadastro de Clientes
6.2.4. Name: ButIncCliente
6.2.5. ShowHint: True

7. Crie dentro do objeto Panel1 um objeto do tipo dbDateEdit97 e altere as seguintes propriedades

7.1. DataSource: dsPeso_Cliente

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página 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 sequência correta.

10. Abaixo do Objeto Panel1 crie três objetos do tipo BitBtn e altere as seguintes propriedades:

10.1. Para o primeiro BitBtn:


10.1.1. Caption: &Grava
10.1.2. Glyph: ImgGrava.BMP
10.1.3. Hint: Grava os dados na Pasta do Cliente
10.1.4. Name: ButGrava
10.1.5. ShowHint: True

10.2. Para o segundo BitBtn:


10.2.1. Caption: &Cancela
10.2.2. Glyph: ImgCancela.BMP
10.2.3. Hint: Cancela e limpa a entrada dos dados
10.2.4. Name: ButCancela
10.2.5. ShowHint: True

10.3. Para o terceiro BitBtn:


10.3.1. Kind: bkClose
10.3.2. Caption: &Fechar
10.3.3. Hint: Fecha esta janela retornando ao menu do sistema
10.3.4. ShowHint: True

O trabalho final ficou desta maneira:

Programando a Massa
Novamente vou frisar que a programação aqui é uma coisa rápida é direta, ela não deve ser aplicada em
situações de risco, como por exemplo um cadastro.

1. Inicialmente alterne para a Code Editor e na seção Private crie a seguinte chamada para o procedimento:

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página Nr. 147/178
private
procedure AcertaInsercao;
public

2. Agora abaixo da diretiva de compilação crie o procedimento proposto:

{$R *.DFM}
uses
dModelo;

procedure TF_Massa.AcertaInsercao;
begin
D_Modelo.tbPeso_Cliente.Insert;
LabNOM_CLIENTE.Caption := '';
end;

Este procedimento será chamado toda vez que for feito uma nova inclusão na tabela Peso Cliente.

3. Selecione agora o evento OnShow do formulário:

procedure TF_Massa.FormShow(Sender: TObject);


begin
with D_Modelo do begin
tbCliente.Open;
SelPesquisa.NomeTela := 'Seleciona Determinado Cliente';
SelPesquisa.Tabela := tbCliente;
tbPeso_Cliente.Open;
end;
AcertaInsercao;
end;

Toda vez que o formulário for ativado, e aberta a tabela acessória tbCliente e organizado os campos dentro do
objeto SelPesquisa localizado na D_Modelo, depois aberta a tabela em que será realizada toda a movimentação a
tbPeso_Cliente e chamado o procedimento particular para colocá-la em estado de inserção.

4. Selecione o evento OnClose do formulário:

procedure TF_Massa.FormClose(Sender: TObject; var Action: TCloseAction);


begin
with D_Modelo do begin
tbCliente.Close;
tbPeso_Cliente.Cancel;
tbPeso_Cliente.Close;
end;
end;
Aqui é relativamente simples, simplesmente fechamos as tabelas cancelando o estado de inserção da tabela
principal.

5. Vamos começar com os botões, primeiro o botão responsável para realizar a Gravação do Peso para tanto de um
duplo-clique no objeto ButGrava para ativar o evento OnClick:

procedure TF_Massa.ButGravaClick(Sender: TObject);


begin
if EditNUM_CPF.Text = '' then
raise exception.create('Cliente não informado');
if LabNOM_CLIENTE.Caption = '' then
raise exception.create('Cliente não cadastrado');
D_Modelo.tbPeso_Cliente.Post;
AcertaInsercao;
end;

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página Nr. 148/178
Fazemos duas críticas simples apenas para controlar se o CPF foi preenchido e se o nome do cliente foi
encontrado (o que significará que o cliente existe), então gravamos o dado e simplesmente chamamos o procedimento
para reativar o estado de inserção.

6. O segundo botão é o responsável para realizar o Cancelamento dos dados para tanto de um duplo-clique no objeto
ButCancela para ativar o evento OnClick:

procedure TF_Massa.ButCancelaClick(Sender: TObject);


begin
D_Modelo.tbPeso_Cliente.Cancel;
AcertaInsercao;
end;

Este aqui é simplesmente disparar um comando Cancel para a tabela e chamarmos o procedimento para
reativar o estado de inserção.

Últimos Passos
Um passo, que até poderia copiar é o Programando o Cliente, mas ao invés de repetir todos os comandos
prefiro que você volte e veja na seção anterior como isso é feito.

A principal parte diferente aqui é quanto ao cálculo da massa corporal, então selecione o objeto
EditPES_MEDIDO e chame o evento OnExit:

procedure TF_Massa.EditPES_MEDIDOExit(Sender: TObject);


var
ind: Integer;
begin
if LabNOM_CLIENTE.Caption <> '' then begin
with D_Modelo do
ind := Round(tbPESO_CLIENTEPES_MEDIDO.AsInteger /
((tbClienteALT_CLIENTE.AsInteger / 100) *
(tbClienteALT_CLIENTE.AsInteger / 100)));
LabMAS_CLIENTE.Caption := 'Massa coorporal é: ' + IntToStr(Ind);
with LabMAS_CLIENTE do
if ind < 20 then Caption := Caption + ' (Abaixo do Peso)'
else if ind < 26 then Caption := Caption + ' (Normal)'
else if ind < 30 then Caption := Caption + ' (Excesso de Peso)'
else if ind < 40 then Caption := Caption + ' (Obsidade)'
else Caption := Caption + ' (Obsidade Mórbida)';
end;
end;

Pronto, na saída da informação do peso, é calculada a massa corporal, apensa se existir um cliente pois
precisamos saber da altura do cliente para o cálculo de sua massa, novamente vou frisar que se você não lembra como é
realizado isto recorra a apostila referente ao Levantamento dos Dados.

Finalmente
Agora basta você voltar para o formulário F_Menu para fazer a inserção dos comandos para chamar os
formulários:

procedure TF_Menu.EntradadoCliente1Click(Sender: TObject);


begin
F_Entrada := TF_Entrada.Create(Application);
F_Entrada.ShowModal;
F_Entrada.Free;
end;

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página Nr. 149/178
procedure TF_Menu.MassaCorporal1Click(Sender: TObject);
begin
F_Massa := TF_Massa.Create(Application);
F_Massa.ShowModal;
F_Massa.Free;
end;

Também chame a partir do menu principal Project | Options... e retire os formulários F_Entrada e F_Massa
da área dos Auto-Create forms.

Na próxima apostila vamos criar uma movimentação um tanto mais complexa, portanto esteje preparado.

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página 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 versão Client/Server Suite
BDE 5.00
MS-Access 97

Arquivos trabalhados juntos com esta apostila:

Objeto : DBDateEdit97

Seguintes Imagens :
ImgCalc.BMP
ImgGrava.BMP
ImgLocaliza.BMP

Prefácio
Salve, nesta apostila vamos concluir as movimentações do nosso projeto.

Nesta segunda fase mostrarei como coordenar dados de Saída, não associe os dados de saída como retirada ou
qualquer outra coisa parecida, na verdade são dados já colocados nas tabelas mas que faltam a informação final, aquele
famoso Tchan para ficar completo.

Saída de Clientes
Vamos construir a parte da movimentação relativa a Saída de Clientes, é o momento em que o Cliente está
saindo do SPA e precisa efetuar o pagamento.

1. A partir do Menu Principal vá em File | New Form e para este objeto altere apenas as seguintes propriedades:

1.1. BorderStyle: bsDialog


1.2. Caption: Saída de Clientes
1.3. Name: F_Saida
1.4. Position: poScreenCenter
1.5. Salve o formulário com o nome de fSaida.PAS

☞Importante - Abra o Data Module D_Modelo, volte para o formulário F_Saida e alterne para a janela do
programa e insira a seguinte declaração após a diretiva de compilação:

{$R *.DFM}

uses
dModelo;

2. Crie um objeto do tipo DataSource e altere as seguintes propriedades:

2.1. DataSet: D_Modelo.tbPasta_Cliente

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página 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
Próximo Registro
Registro Anterior
Último Registro
4.3. Name: DbNavega
4.4. ShowHint: True
4.5. VisibleButtons: [nbFirst,nbPrior,nbNext,nbLast]

5. Crie dentro do objeto Panel1 um objeto do tipo BitBtn e altere as seguintes propriedades

5.1. Caption: &Localizar


5.2. Glyph: ImgLocaliza.BMP
5.3. Hint: Localiza Determinada Pasta do Cliente
5.4. Name: ButLocaliza
5.5. ShowHint: True

6. Crie agora um segundo objeto do tipo TPanel e altere as seguintes propriedades:

6.1. BevelInner: bvLowered


6.2. BorderWidth: 4
6.3. Align: alTop

7. Crie dentro do objeto Panel2 dez objetos do tipo Label e altere as seguintes propriedades:

7.1. Propriedade Caption (respectivamente):


Cliente:
Dt.Chegada:
Plano:
Qtd.Caloria: KCal
Observação:
Dt.Pagamento:
Valor:
Desconto:
Total a Pagar:

7.2. Propriedade Font para:


Font.Color = clMaroon
Font.Style = [fsBold]

☞Importante - Aqui vão algumas observações:


a. Deixe um espaço entre o label Cliente e Dt.Chegada
b. O label KCal fica na frente do Label Qtd.Caloria com um espaço para colocar um campo
c. Deixe um espaço entre o Label Qtd.Caloria e o label Observação

8. Crie dentro do objeto Panel2 um objeto do tipo Bevel e altere as seguintes propriedades

8.1. Shape: bsBottomLine

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página Nr. 152/178
☞Importante - Este objeto foi criado apenas para separar os dados, coloque-o entre os Labels Qtd.Caloria e
Observação

9. Crie dentro do objeto Panel2 três objetos do tipo dbEdit e altere as seguintes propriedades:

9.1. DataSource: dsPasta_Cliente


9.2. DataField (respectivamente): NUM_CPF, DAT_CORRENTE e QTD_CALORIA
9.3. Font.Color: clMarron
9.4. Name (respectivamente): EditNUM_CPF, EditDAT_CORRENTE e EditQTD_CALORIA
9.5. Color: clBtnFace
9.6. TabStop: False
9.7. ReadOnly: True

☞Importante - Posicione-os em frente aos labels Cliente, Dt.Chegada e Qtd.Caloria respectivamente.


10. Crie dentro do objeto Panel2 abaixo do objeto EditNUM_CPF mais um objeto do tipo dbEdit e altere as seguintes
propriedades:

10.1. DataSource: dsCliente


10.2. DataField: NOM_CLIENTE
10.3. Font.Color: clMarron
10.2. Name: EditNOM_CLIENTE
10.4. Color: clBtnFace
10.4. TabStop: False
10.4. ReadOnly: True

11. Crie dentro do objeto Panel2 na frente do Label Plano um objeto do tipo Edit e altere as seguintes propriedades

11.1. Font.Color: clMarron


11.2. Name: EditNOM_PLANO
11.3. Color: clBtnFace
11.4. TabStop: False
11.5. ReadOnly: True

12. Crie dentro do objeto Panel2 na frente do Label Dt.Pagamento um objeto do tipo dbDateEdit97 e altere as
seguintes propriedades

12.1. DataSource: dsPasta_Cliente


12.2. DataField: DAT_PAGAMENTO
12.3. Font.Color: clNavy
12.4. Name: EditDAT_PAGAMENTO

13. Crie dentro do objeto Panel2 na frente do Label Valor e Desconto respectivamente dois objetos do tipo dbEdit e
altere as seguintes propriedades:

13.1. DataSource: dsPasta_Cliente


13.2. DataField (respectivamente): VAL_TOTAL e VAL_DESCONTO
13.3. Font.Color: clNavy
13.2. Name (respectivamente): EditVAL_TOTAL e EditVAL_DESCONTO

14. Acerte a propriedade TabOrder desses três últimos objetos para uma sequência correta a partir do zero.

15. Crie dentro do objeto Panel2 na frente do objeto EditVAL_DESCONTO um objeto do tipo SpeedButton e altere
as seguintes propriedades:

15.1. Flat: True


15.2. Glyph: ImgCalc.BMP
15.3. Hint: Calcula o Desconto Padrão
15.4. Name: ButCalcDesconto

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página 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 Saída
A programação aqui (ainda bem que estamos tratando do Delphi) não é algo tão complicado, pode ser se você
desejar colocar coisas homéricas, a idéia é que o usuário localize na tabela Pasta Cliente a entrada deste Cliente, mas
lembre-se que o mesmo Cliente pode visitar várias vezes o SPA então precisamos restringir os registros, acompanhe

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página Nr. 154/178
atentamente a codificação:

1. Inicialmente alterne para a Code Editor e na seção Private crie uma variável para acumular o valor de um desconto
dado.

private
VlDesconto: Double;
public

2. Selecione agora o evento OnShow do formulário:

procedure TF_Saida.FormShow(Sender: TObject);


begin
with D_Modelo do begin
SelPesquisa.NomeTela := 'Seleciona Determinada Pasta Cliente';
SelPesquisa.Tabela := tbPasta_Cliente;
with tbCliente do begin
MasterSource := dsPasta_Cliente;
MasterFields := 'NUM_CPF';
Open;
end;
with tbPasta_Cliente do begin
Filter := 'VAL_TOTAL < 0';
Filtered := True;
Open;
end;
end;
end;

Toda vez que o formulário for ativado, é organizado os campos dentro do objeto SelPesquisa localizado na
D_Modelo, e ativado um relacionamento entre a tabela tbCliente e tbPasta_Cliente e é aberta a tabela acessória
tbCliente e depois é ativado um filtro para a tabela tbPasta_Cliente permitindo que sejam mostrados apenas os
registros aonde o Valor ainda é 0 (ou menor, isso incluirá os nulos) e aberta a tabela em que será realizada toda a
movimentação a tbPasta_Cliente.

☞ Importante - Abra a tabela ascessória primeiramente (no caso tbCliente), pois existirá uma dependência no
evento quando os dados serão mudados do objeto DsPasta_Cliente que necessitará que esta tabela esteje aberta.

3. Selecione o evento OnClose do formulário:

procedure TF_Saida.FormClose(Sender: TObject; var Action: TCloseAction);


begin
with D_Modelo do begin
with tbPasta_Cliente do begin
if dsPasta_Cliente.State = dsEdit then Cancel;
Close;
Filter := '';
Filtered := False;
end;
with tbCliente do begin
Close;
MasterSource := Nil;
MasterFields := '';
end;
end;
end;

Neste momento fechamos inicialmente a tabela principal, aplicando um comando Cancel na tabela caso os
dados estejam em momento de edição (para não acontecer uma gravação equivocada, se o usuário quer gravar então ele
deve apertar o botão Grava) depois de fechada, eliminamos o filtro da tabela, o segundo passo é fechar a tabela

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página Nr. 155/178
secundária, eliminando também a dependência entre as duas tabelas.

4. Vamos começar com os botões, primeiro o botão responsável para realizar a Gravação na Pasta para tanto de um
duplo-clique no objeto ButGrava para ativar o evento OnClick:

procedure TF_Saida.ButGravaClick(Sender: TObject);


begin
if EditDAT_PAGAMENTO.Text = '' then
Raise Exception.Create('Data de Pagamento não informada');
if EditVAL_TOTAL.Text = '' then
Raise Exception.Create('Valor não informado');
D_Modelo.tbPasta_Cliente.Post;
end;

Fazemos duas críticas simples apenas para controlar se a Data e o Valor de pagamento foram preenchidos,
então simplesmente gravamos o dado. Aqui não precisamos nos preocupar em colocar a tabela em momento de
inserção pois o Delphi trata isto automaticamente. Também, automaticamente, o registro sumirá da tela, por causa do
Filtro ativo.

5. O botão localizado ao lado da barra de navegação é o responsável para realizar a Consulta a Pasta Cliente para
tanto de um duplo-clique no objeto ButLocaliza para ativar o evento OnClick:

procedure TF_Saida.ButLocalizaClick(Sender: TObject);


begin
D_Modelo.SelPesquisa.Execute;
end;

É um simples comando aqui apenas executamos o objeto SelPesquisa ele se encarregará de posicionar no
registro correto.

6. Selecione o objeto EditVAL_TOTAL e chame o evento OnExit:

procedure TF_Saida.EditVAL_TOTALExit(Sender: TObject);


begin
if EditVal_Total.Text <> '' then
with D_Modelo.tbPasta_Cliente do
PnlTotal.Caption := Format('%10.2m', [(FieldByName('VAL_TOTAL').AsFloat - FieldByName
('VAL_DESCONTO').AsFloat)]);
end;

Aqui será feito para calcularmos o valor total a pagar, no momento da saída do campo Valor e do campo
Desconto.

7. Selecione o objeto EditVAL_DESCONTO e localize o evento OnExit, clique na seta que aparece ao lado do
campo e coloque nele a chamada EditVAL_TOTALExit.

8. O botão ao lado do EditVAL_DESCONTO é o responsável para calcular um desconto concedido para tanto de um
duplo-clique no objeto ButCalcDesconto para ativar o evento OnClick:

procedure TF_Saida.ButCalcDescontoClick(Sender: TObject);


begin
if EditVal_Total.Text <> '' then
EditVAL_DESCONTO.Text := FloatToStr(D_Modelo.tbPasta_ClienteVal_Total.AsFloat * VlDesconto)
else
MessageDlg('Informe primeiro o Valor',mtInformation,[mbOk],0);
end;

Verificamos se o Valor do Pagamento já foi preenchido, então calculamos o desconto com base na variável
VlDesconto.

9. Este agora é o coração de todo o formulário, é aqui que a maior parte foi projetada, selecione o objeto

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página 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 Reeducação'
else if FieldByName('PLN_ADOTADO').AsString = 'C' then
EdtNOM_PLANO.Text := 'Plano Completo'
else if FieldByName('PLN_ADOTADO').AsString = 'D' then
EdtNOM_PLANO.Text := 'Plano Especial de Reeducação'
else
EdtNOM_PLANO.Text := '';
if EditVal_Total.Text <> '' then
with D_Modelo.tbPasta_Cliente do
PnlTotal.Caption := Format('%10.2m', [(FieldByName('VAL_TOTAL').AsFloat - FieldByName
('VAL_DESCONTO').AsFloat)])
else
PnlTotal.Caption := Format('%10.2m', [0.00]);
with D_Modelo do
with QrySQL do begin
if Active then Close;
SQL.Clear;
SQL.Add('Select Count(NUM_CPF) from ' + NmPasta_Cliente);
SQL.Add('Where (NUM_CPF = ''' + EditNUM_CPF.Text + ''')');
Open;
LabObserva.Caption := 'Observação: Não existe';
LabDesconto.Caption := 'Desconto:';
VlDesconto := 0;
if not EOF then begin
LabObserva.Caption := 'Observação: Esta é a ' + Fields[0].AsString + 'ª visita deste cliente.';
case Fields[0].AsInteger of
2: AcertaDesc('5',0.05);
3: AcertaDesc('10',0.1);
4: AcertaDesc('15',0.15);
5: AcertaDesc('16',0.16);
6: AcertaDesc('17',0.17);
7: AcertaDesc('18',0.18);
8: AcertaDesc('19',0.19);
else
if Fields[0].AsInteger > 8 then AcertaDesc('20',0.2);
end;
end;
Close;
end;
D_Modelo.tbCliente.Refresh;
end;

Olhando assim parece complicado mas não precisamos temer tanto, o brincadeira é a seguinte, inicialmente
coloquei um procedimento dentro para mostrar no LabDesconto se existe algum desconto cedido, e setar a variável
VlDesconto com este valor.

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página Nr. 157/178
Começando o procedimento realmente, inicialmente é verificado qual é o plano que o cliente optou, depois é
calculado o valor a pagar (da mesma forma em que foi feito na saida dos campos EditVAL_TOTAL e
EditVAL_DESCONTO). Agora utilizaremos a Query ascessória para pesquisarmos dentro da tabela Pasta Cliente
quantas vezes este Cliente já veio ao SPA, e verificamos qual o valor do desconto que pode ser concedido para este
cliente (Lembra-se da regra: 2ª Visita = 5%, 3ª Visita = 10%, verifique na parte do Levantamento dos Dados), e
finalmente damos um Refresh na tabela de Cliente para que o relacionamento feito entre ela e a tabela Pasta_Cliente
possa ser efetivado, mostrando o nome do cliente corretamente.

Finalmente
Agora basta você voltar para o formulário F_Menu para fazer a inserção dos comandos para chamar os
formulários:

procedure TF_Menu.SaidadoCliente1Click(Sender: TObject);


begin
F_Saida := TF_Saida.Create(Application);
F_Saida.ShowModal;
F_Saida.Free;
end;

Também chame a partir do menu principal Project | Options... e retire o formulário F_Saida da área dos
Auto-Create forms.

Acredito que você tenha reparado os dois processos de movimentação, na anterior trabalhamos basicamente
com o momento INSERT da tabela, era apenas uma entrada simples e básica, nesta aqui pegamos aqueles dados
inseridos e trabalhamos um pouco mais, solicitando mais alguns dados para finalmente finalizarmos este Cadastro.

Em movimentações, também é possível, e admissível, criarmos uma tabela idêntica, apenas para servir como
arquivamento dos dados, ou seja, após concluirmos esta segunda fase da movimentação, passar os dados já gravados
para uma segunda tabela, tipo um Fechamento.

Na próxima apostila vamos começar a analisar como são feitos relatórios.

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página 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 versão 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

Prefácio
Salve, vamos agora começar a melhor parte de todo o nosso projeto, Relatórios. Pessoalmente não 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 relatórios (serão três neste projeto) vamos criar o relatório de Etiquetas de
Endereçamento, isso mesmo vamos imprimir etiquetas, acho isso uma coisa estremamente divertida principalmente
quando o papel engargala (isso existe ?), mas que exige além de um certo cuidado e também uma boa dose de
paciência. Inicialmente já vou avisando aos fãs do Quick Report que não irei utilizá-lo para tal serviço, o motivo é
simples Etiquetas não são uma coisa que rimam muito bem com o Windows, a menos que você utilize o Word ou um
software específico para produzí-las descobrirá que com o Quick Report, Crystal Report, Report Builder entre
outros não são muito amigáveis para produzir este tipo de arquivo. Então vou utilizar aqui os bons e velhos comandos
do arquivo Text do Pascal e simplesmente redirecionar para a saída da impressora.

Etiquetas e o Windows
Desde que me entendo trabalhando nesta área de informática tenho feito impressão com etiquetas, o pior é que
existem milhares de modos de fazê-las, principalmente porque existem milhares de diferentes etiquetas, então para esse
serviço, infelizmente isso varia de cliente para cliente, o do SPA Antes & Depois pediu para que utilizassemos as
etiquetas da marca PIMACO referência 10236MC com 1 Carreira o tamanho da Etiqueta é de 102 x 36,1 mm e são 8
etiquetas por folha (anote essas medidas pois elas são 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 são em formulário contínuo, o cliente resolveu utilizar uma impressora matricial padrão Epson FX-100 para
fazer este serviço.

A primeira coisa a fazermos é instalar a impressora no Windows, após instalada coloque como papel padrão o
Definido pelo Usuário e acerte as medidas em mm para:

Largura: 1200
Comprimento: 410
E coloque 0 na área não imprimível (isto são as margens)

Você pode estar se perguntando como cheguei a tão fabulosas medidas ? Simples vários testes, gastei quase
meia caixa de etiquetas testando, isso é uma coisa (infelizmente) muito comum a quem se aventurar a fazer este tipo de
impressão, você pode estar se perguntando também, mas porque defini o tamanho da página no tamanho de uma
etiqueta e não das oito ? Simples também, o Windows adora ao final de cada impressão mandar um caracter especial de
final de página que ordena a impressora para se posicionar no começo da próxima página, então como não gosto de

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página Nr. 159/178
perder etiquetas, e também para não 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 saída da minha impressora, isso mesmo se tiver 100
etiquetas para imprimir existirá 100 arquivos na saída da minha impressora. Esse é o jeito mais fácil ? Isso é uma
excelente pergunta, talvez você conheça milhares de outras maneiras de imprimir etiquetas com o Windows, mas
considero a maneira como a que vou fazer aqui a mais fácil, simples e eficaz.

Criando o Formulário
Vamos neste momento criar um pequeno formulário que servirá de auxílio, e também para dizer ao nosso
usuário 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: Relatório de Etiquetas de Endereçamento
1.3. Name: G_EtiqEnd
1.4. Position: poScreenCenter
1.5. Salve o formulário com o nome de gEtiqEnd.PAS

☞Importante - Abra o Data Module D_Modelo, volte para o formulário F_Saida e alterne para a janela do
programa e insira a seguinte declaração após a diretiva de compilação:

{$R *.DFM}

uses
dModelo;

☞Observação - Note que mudei a primeira letra do formulário de F para G, adoto a seguinte nomenclatura em meus
forms:

F - Cadastro, Tabelas e Movimentações


G - Geração de alguma coisa específica
R - Relatórios 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 Opção:


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 próximos 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 - Página 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) e altere as seguintes propriedades
respectivamente:

7.1. Propriedade Font para:


Font.Color = clNavy
7.2. Caption:
Ativa as opções para se criar um Filtro, o Filtro permite que a seleção dos Registro mostrados sejam
limitados.
Permite ordenar o relatório por determinados campos.
Salva o Relatório em formato Texto
Testa a posição 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: Ordenação 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 - Página Nr. 161/178
Programando a Saída
Agora começamos com a parte mais divertida do trabalho, e por sinal minha favorita, mas por favor
acompanhe atentamente esta codificação que apesar de ser simples existem alguns macetes que devem ser observados:

1. Inicialmente alterne para a Code Editor e na seção 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 variáveis: 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 Função 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);
// Ordenação
if DgOrdenaEtq.Ordem > '' then
SQL.Add('Order By ' + DgOrdenaEtq.Ordem);
Open;
if EOF then begin
Result := False;
MessageDlg('Não Existem Registros para Gerar as Etiquetas', mtInformation, [mbOk],
0);
end

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página Nr. 162/178
else
Result := True;
end;
end;

Está função é a responsável pela montagem do SQL no objeto QryEtq, aqui montamos uma query simples
associando a tabela de Cliente com a Tabela de Cidade (através do comando Left Join) as cláusulas Where e Order
By são definidas pelos objetos DgFiltroEtq e DgOrdenaEtq respectivamente, ao final basta apenas verificar se existe
ou não registros retornando uma variável lógica 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 geração');
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 responsável pelo controle da geração, inicialmente ele chama a função AcertaSQL se
existir registros, ele corrige a fonte da impressora, gera o arquivo de saída (caso a saída seja através de um arquivo
físico), 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 - Página 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 saída é para impressora se for desviamos
o arquivo para lá, agora basta apenas gravarmos linha a linha utilizando a variável pDesLinha como auxílio, ao final
(se for para impressora) fechamos o arquivo.

2. Selecione o evento OnClose do formulário:

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 formulário a Query estará encerrada.

3. Vamos começar com os botões, primeiro o botão responsável para realizar a Filtragem para tanto de um duplo-
clique no objeto ButFiltro para ativar o evento OnClick:

procedure TG_EtiqEnd.ButFiltroClick(Sender: TObject);


begin
DgFiltroEtq.Execute;
end;

Aqui é simples, basta apenas executarmos a função Execute do Objeto DgFiltroEtq que este objeto fará o
resto para nós, o filtro utilizado será armazenado nas variáveis FiltroSQL (filtro em linguagem SQL) e FiltroVe (filtro
em linguagem que o usuário entende)

4. O próximo é o botão que fará a Ordenação 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 função Execute do Objeto DgOrdenaEtq que este objeto fará o
resto para nós.

5. O próximo é o botão 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 - Página Nr. 164/178
end;

Coisa simples basta dispararmos o procedimento EnviaEtq enviando o tipo em 2

6. O próximo é o botão que fará a impressão 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 botão 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 também é fácil, criamos o arquivo na saída da impressora e questionamos se o usuário 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 formulário F_Menu para fazer a inserção dos comandos para chamar o
formulário:

procedure TF_Menu.Correspondncia1Click(Sender: TObject);


begin
G_EtiqEnd := TG_EtiqEnd.Create(Application);
G_EtiqEnd.ShowModal;
G_EtiqEnd.Free;
end;

Também chame a partir do menu principal Project | Options... e retire o formulário G_EtiqEnd da área dos
Auto-Create forms.

☞Observação - O ideal é que a impressora esteje plugada na porta LPT1 do Micro, pois imagine no meio da
impressão das etiquetas dá um erro, ou algumas etiquetas cismam de enganchar.

Na próxima apostila vamos continuar analisando os diferentes tipos de relatórios.

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página 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 versão Client/Server Suite
BDE 5.01
MS-Access 97

Arquivos trabalhados juntos com esta apostila:

Seguintes Imagens :
LogRel.JPG, ImgImprime.BMP

Prefácio
Salve, vamos começar a segunda parte dos Relatórios. Na verdade esta segunda parte será a primeira, pois
resolvi dividir este projeto (e para sua melhor compreensão) em dois tipos de relatórios do Quick Report, para este
primeiro tipo criaremos relatórios Espelho.

Mas o que são relatórios do tipo Espelho ? Me adiantei antes que você perguntasse, o negócio é o seguinte
(não é pegar um relatório e imprimir todas as letras de trás para frente para ler diante de um espelho, isto aprenderemos
no curso de espionagem e não de Delphi) este é um tipo de relatório que todos os campos dentro de um formulário
ficam sempre na mesma posição, eles já são pré-configurados para estarem ali. Pegue um bloco de Notas Fiscais se
você tivesse que imprimir o seu conteúdo, você teria que pré preparar a impressão com todos os campos em pré
determinadas posições.

Este relatório que lidaremos aqui está no Menu é se chama: Cardápio. O entendimento é simples, o usuário
informa o número de calorias de 800 Kcal a 1.800 Kcal, e montaremos um cardápio ao acaso utilizando a tabela de
alimentos.

Definindo o Relatório
Bem, de uma colada na Apostila 6 e você verá que o nosso usuário pré estabeleceu várias configurações para
os cardápios, Batendo todos as refeições chegamos ao seguinte total máximo entre elas:

Cardápio Padrão

Refeição Número de Refeições


Desjejum (café da manhã) Variando de 2 até 4
Colação (lanche da manhã) Fixa em 1
Almoço Variando de 3 até 8
Lanche Variando de 1 até 4
Jantar Variando de 3 até 10
Ceia Variando entre 1 e 2

O que pretendo fazer aqui é um trabalho simples, vou formatar uma página 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 - Página Nr. 166/178
☞Importante - Para testar a saída do formulário é bom que as bases de Grupos e Alimentos estejam carregadas,
então se você ainda não fez aconselho que você se encarregue disto.

Criando o Relatório
Vamos direto a criação do relatório 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 formulário com o nome de rCardapio.PAS

☞Importante - Abra o Data Module D_Modelo, volte para o formulário R_Cardapio e alterne para a janela do
programa e insira a seguinte declaração após a diretiva de compilação:

{$R *.DFM}

uses
dModelo;

2. Crie um objeto do tipo TQuery e altere as seguintes propriedades:

2.1. DataBase: DNmPeso


2.2. Name: QryRelato

3. Na Component Pallete na página QReport, localize o objeto chamado QuickRep, clique nele e em seguida click no
formulário e altere as seguintes propriedades:

3.1. Name: QrCardapio


3.2. PrintIfEmpty: True

☞ Importante - Normalmente a maioria dos relatório do tipo espelho não 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 página 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 seções no caso
escolhemos uma Banda de Cabeçalho de Página, ela aparecerá em todas as páginas.

5. Na Component Pallete ainda na página 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: Cardápio 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 página 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 página 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 - Página Nr. 167/178
7.2. Text: Data: e Pág: (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 Página, ela aparecerá a cada
novo registro, como o componente Quick não está associado a nenhum DataSet então 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 página 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 página 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 alteração 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 idéia, vá na nova
banda criada e repita esta operação por mais quatro vezes, criando assim um total de cinco objetos ChildBand.

12. Na Component Pallete ainda na página 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

Colação (lanche da manhã)


Almoço
Lanche
Jantar
Ceia

13. Na Component Pallete ainda na página 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 - Página Nr. 168/178
Programando a Saída
Agora começamos com a parte mais divertida do trabalho, e por sinal minha favorita, mas por favor
acompanhe atentamente esta codificação que apesar de ser simples existem alguns macetes que devem ser observados:

1. Inicialmente alterne para a Code Editor e na seção Public crie uma chamada a um procedimento e na seção Private
uma váriável 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 descrição do procedimento abaixo da diretiva de compilação:

{$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 - Página Nr. 169/178
SQL.Add('Where NUM_GRUPO = ' + Grupo);
Open;
if EOF then
MemUtil.Lines.Add('Não existe alimento para compor este cardápio')
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 responsável pela montagem de todo o cardápio, ele é o coração de todo o relatório,
primeiramente ele recebe o Grupo, uma variável 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 contém registros, e então vamos ao primeiro registro (First) e depois saltamos (MoveBy)
registros indicados através da função Random que permite geramos um número aleatório até o total de registros,
depois basta apenas colocar o registro posicionado dentro da variável.

☞Observação - É possível conforme já visto anteriormente passar qualquer tipo de variável através de uma função
ou procedimento, quando passado com o auxílio de um comando Var qualquer alteração se refletirá na variável
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 := 'Cardápio 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 - Página 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 relatório, inicialmente limpamos todos os objetos
QrMemo, depois simplesmente montamos conforme a verificação da variável.

☞Importante - Apesar de parecer, isso é apenas um Denorex, os eventos BeforePrint e AfterPrint não são como o
nome diz, antes de imprimir e depois de imprimir, na verdade são eventos relacionados ao relatório em si, o
BeforePrint acontece antes do Quick mostrar o relatório (seja em tela ou na impressora) e o AfterPrint acontece
quando se dá a saída do relatório e volta do controle ao formulário que o chamou.

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página Nr. 171/178
Finalmente
Crie a seguinte janela com o auxílio dos objetos RadioGroup e BitBtn:

☞Importante - Defina as seguintes propriedades para os objetos:


Formulário - Name - F_RCardapio (salvar com o nome de: fRCardapio)
RadioGroup - Name - RdgQtdCal
Botão de Imprimir - Name - ButImprimir (para imagem utilize a ImgImprime.BMP)
Botão de Fechar - Kind - bkClose

Para o botão de Imprimir coloque o seguinte código:

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 formulários: R_Cardapio e F_RCardapio
da área dos Auto-Create forms.

☞Observação - Faça a chamada do menu ao formulário F_RCardapio

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página 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 versão Client/Server Suite
BDE 5.01
MS-Access 97

Arquivos trabalhados juntos com esta apostila:

Seguintes Imagens :
LogRel.JPG ImgImprime.BMP

Prefácio
Salve, vamos começar a terceira e última parte dos Relatórios. O segundo tipo de relatório do Quick Report é
o relatório tipo Folha de Dados. Relatórios tipo Folha de Dados são mais fáceis que parecem, vou dizer aqui um
grande Macete para a criação destes, uso de comandos SELECT do SQL, muitas pessoas queimam a cabeça tentando
construir o relatório apenas com Table mas o grande lance aqui é criar o relatório baseado num comando SELECT
primário e sem muita complicação, associada a ele sim, objetos Table.

Este relatório que lidaremos aqui está no Menu é se chama: Divisão das Contas Mensais. Mais simples que o
primeiro, aqui o usuário informa o Mês e o Ano e simplesmente disparamos o relatório totalmente baseado na tabela de
PastaCliente, que tem os valores pagos pelos clientes em determinado período.

Definindo o Relatório
Bem, voltando a dar uma colada na Apostila 6 você verá que o nosso usuário pré estabeleceu várias
configurações para a divisão dos lucros da empresa:

20% para o médico-presidente da empresa.


40% para o coordenador dos planos alimentares.
10% para o nutricionista (caso seja efetuado os planos B ou D ).
30% (ou 40 % - caso seja efetuado os planos A ou C) para despesas gerais.

O que pretendo fazer aqui é um trabalho simples, como já disse vamos simplesmente imprimir a tabela
PastaCliente dentro de um determinado mês e ano e ao final deste, numa banda de última página (ou se você prefere
num sumário de página) com base em variáveis contendo o valor total vamos calcular a proporção de cada um. O único
problema que teremos (e este desde a definição eu fiz de propósito) é quanto ao valor para o nutricionista que tem uma
regra especial.

☞Importante - Para testar a saída do formulário é bom que a base de PastaCliente esteja carregada, então se você
ainda não fez aconselho que você se encarregue disto.

Criando o Relatório
Vamos direto criar o relatório 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 - Página Nr. 173/178
1.1. Name: R_Mensal
1.2. Salve o formulário com o nome de rMensal.PAS

☞Importante - Abra o Data Module D_Modelo, volte para o formulário R_Mensal e alterne para a janela do
programa e insira a seguinte declaração após a diretiva de compilação:

{$R *.DFM}

uses
dModelo;

2. Crie um objeto do tipo TQuery e altere as seguintes propriedades:

2.1. DataBase: DNmPeso


2.2. Name: QryRelato

3. Na Component Pallete na página QReport, localize o objeto chamado QuickRep, clique nele e em seguida click no
formulário e altere as seguintes propriedades:

3.1. Name: QrMensal


3.2. PrintIfEmpty: True
3.3. DataSet: QryRelato

☞Importante - Diferentemente dos relatório do tipo espelho estes aqui precisam estar amarrados a um objeto do tipo
tDataSet.

4. Na Component Pallete ainda na página 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 seções no caso
escolhemos uma Banda de Cabeçalho de Página, ela aparecerá em todas as páginas.

5. Na Component Pallete ainda na página 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: Divisão 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 página 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 página 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 Pág: (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 - Página Nr. 174/178
8.1. Name para BdCabecalho
8.2. BandType para rbColumnHeader - Neste caso escolhemos uma Banda de Cabeçalho de Página, ela
aparecerá a cada nova página.
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 Página, 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 Relatório, ela aparecerá
apenas quando o relatório terminar.

13. Crie dentro deste objeto criado, cinco objetos do tipo QrLabel e altere as seguintes propriedades:

13.1. Caption para Resumo Final - Médico-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 e ValTotal


respectivamente
14.2. Font: Courier New - Normal - 9 - Preto
14.3. Caption: 0 (Zero) para todos

O trabalho final ficou desta maneira:

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página Nr. 175/178
Programando a Saída
Vamos a quase finalização deste projeto, o complemento com a programação:

1. Inicialmente alterne para a Code Editor e na seção Private crie cinco váriáveis para receber a quantidade de valor
de cada plano e na seção Public crie um variável para receber o mês 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 - Página Nr. 176/178
if Active then Close;
SQL.Clear;
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');
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;

No início do relatório montamos primeiro o intervalo do mês e ano informado (de 01/mm/aa até [último
dia]/mm/aa) para a pesquisa, inclusive com os cálculos de ano bissexto, montamos a pesquisa selecionando apenas os
registros daquele intervalo e iniciamos as variáveis 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 variável.

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 auxílio da
função Format transformamos os campos String em forma de Valores Monetários.

Crie a seguinte janela com o auxílio dos objetos ComboBox, MaskEdit e BitBtn:

PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página Nr. 177/178
☞Importante - Defina as seguintes propriedades para os objetos:
Formulário - 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;_
Botão de Imprimir - Name - ButImprimir
Botão de Fechar - Kind - bkClose

Para o evento OnShow do formulário coloque o seguinte código:


procedure TF_RMensal.FormShow(Sender: TObject);
begin
CbMes.ItemIndex := StrToInt(FormatDateTime('MM',Now)) - 1;
MskAno.Text := FormatDateTime('YYYY',Now);
end;

Para o botão de Imprimir coloque o seguinte código:

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 formulários: R_Mensal e F_RMensal da
área dos Auto-Create forms.

☞Observação - Faça a chamada do menu ao formulário 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 também aproveitei e que este não seja apenas o final de mais um curso e sim o começo
para uma excelente jornada.

FIM
PDF criado por: Idelson Pessoa da Silva – idelson@bol.com.br - Página Nr. 178/178

Você também pode gostar