Você está na página 1de 96

1

CURSO DE DELPHI
2

1. Delphi 4.0 Básico......................................................................................................................................5


2. Introdução................................................................................................................................................5
3. Ambiente...................................................................................................................................................6
4. Projeto.......................................................................................................................................................8
5. Formulário..............................................................................................................................................10
a) Definindo um evento...........................................................................................................................13
6. Componentes visuais..............................................................................................................................13
7. Barra de ferramentas............................................................................................................................15
8. Lista de imagens.....................................................................................................................................16
9. Barra de status.......................................................................................................................................17
a) Grid......................................................................................................................................................17
b) Edit......................................................................................................................................................18
c) Label....................................................................................................................................................20
d) Exercício..............................................................................................................................................20
e) Combo box...........................................................................................................................................21
f) Radio group..........................................................................................................................................22
g) Check box............................................................................................................................................23
h) FIM......................................................................................................................................................24
i) Image....................................................................................................................................................25
j) Animate................................................................................................................................................27
10. Object Pascal........................................................................................................................................27
a) Unit......................................................................................................................................................28
11. Tipos de dados......................................................................................................................................29
a) Constantes............................................................................................................................................30
b) Constantes tipadas...............................................................................................................................31
12. Dados estruturados..............................................................................................................................32
a) Array Estático......................................................................................................................................32
b) Array Dinâmico...................................................................................................................................32
c) Record..................................................................................................................................................33
d) Set........................................................................................................................................................34
13. Procedimentos e funções.....................................................................................................................35
14. Manipulação de strings.......................................................................................................................38
a) Atribuição............................................................................................................................................38
b) Concatenação.......................................................................................................................................38
c) Caracter de controle.............................................................................................................................39
d) Funções................................................................................................................................................39
1 - IntToStr...........................................................................................................................................39
2 - StrToIntDef.....................................................................................................................................39
3 - FormatFloat....................................................................................................................................40
4 - StrToFloat.......................................................................................................................................40
5 - UpperCase e LowerCase................................................................................................................41
6 - StrToDate e DateToStr...................................................................................................................41
7 - StrToTime e TimeToStr.................................................................................................................41
8 - Pos..................................................................................................................................................41
9 - Copy...............................................................................................................................................42
10 - Length...........................................................................................................................................42
11 - Botando a Mão na Massa.............................................................................................................43
16. Matemática...........................................................................................................................................45
17. Trigonometria......................................................................................................................................46
18. Estatística..............................................................................................................................................46
19. Matemática Financeira........................................................................................................................46
20. Lógica booleana....................................................................................................................................47
a) Expressões Lógicas..............................................................................................................................47
3
b) Valores Booleanos...............................................................................................................................47
c) Operadores Relacionais.......................................................................................................................47
d) Operadores booleanos.........................................................................................................................48
e) Comando If..........................................................................................................................................49
1 - if Com Mais de Um Comando........................................................................................................49
2 - if Aninhado.....................................................................................................................................50
f) Comando Case.....................................................................................................................................50
g) Comando For.......................................................................................................................................51
h) Comando While...................................................................................................................................51
i) Comando Repeat..................................................................................................................................52
j) Continue e Break..................................................................................................................................53
k) Botando a Mão na Massa....................................................................................................................53
21. Banco de dados.....................................................................................................................................55
a) Database Desktop...............................................................................................................................55
b) Criar um Alias.....................................................................................................................................56
c) Definir o Diretório de Trabalho...........................................................................................................56
d) Criar Tabelas.......................................................................................................................................56
e) Criar Índices.........................................................................................................................................58
f) Editar Dados.........................................................................................................................................59
22. Borland Database Engine....................................................................................................................59
a) Formatar a Data...................................................................................................................................60
b) Formatar Número................................................................................................................................61
c) Database Explorer................................................................................................................................61
23. Componentes de Banco de Dados.......................................................................................................62
a) Table....................................................................................................................................................62
b) Fields...................................................................................................................................................62
c) DataSource...........................................................................................................................................64
d) Componentes Data Aware...................................................................................................................64
24. Eventos e Métodos de Banco de Dados..............................................................................................65
a) Excluir..................................................................................................................................................65
b) Alterar..................................................................................................................................................66
c) Próximo e Anterior..............................................................................................................................66
d) Consistência do Banco de Dados........................................................................................................66
1 - Consistir CGC................................................................................................................................66
2 - Consistir Código.............................................................................................................................67
25. Relatório...............................................................................................................................................68
a) Quick Report........................................................................................................................................68
1 - Componente QuickRep..................................................................................................................69
2 - Bands..............................................................................................................................................69
3 - DataSet...........................................................................................................................................70
4 - Cabeçalho.......................................................................................................................................70
5 - Cabeçalho de Coluna......................................................................................................................71
6 - Linha de Detalhe.............................................................................................................................71
7 - Sumário...........................................................................................................................................71
8 - Rodapé............................................................................................................................................72
9 - Imprimindo com Quick Report......................................................................................................72
26. Arquivos sequenciais...........................................................................................................................73
a) Funções Básicas...................................................................................................................................73
1 - Renomeando um Arquivo...............................................................................................................73
2 - Excluindo um Arquivo...................................................................................................................74
3 - Copiando um Arquivo....................................................................................................................74
4 - Testando se um Arquivo Existe......................................................................................................74
5 - Lendo e Gravando Arquivos..........................................................................................................75
6 - Gravando um Arquivo Já Existente................................................................................................75
4
7 - Lendo um Arquivo.........................................................................................................................76
8 - Gerando Um Arquivo HTML.........................................................................................................76
27. Arquivos INI.........................................................................................................................................78
a) Estrutura do Arquivo INI.....................................................................................................................78
1 - Classe TIniFile................................................................................................................................79
1.1 - Criando um Arquivo INI.........................................................................................................79
1.2 - Criando uma Seção..................................................................................................................79
1.3 - Gravando uma Chave..............................................................................................................79
1.4 - Lendo uma Chave....................................................................................................................79
1.5 - Apagando uma Chave..............................................................................................................80
1.6 - Apagando uma Seção..............................................................................................................80
28. Imprimindo com TPrinter..................................................................................................................80
a) Classe TPrinter.....................................................................................................................................80
1 - Propriedades...................................................................................................................................80
2 - Métodos..........................................................................................................................................81
b) Classe TCanvas...................................................................................................................................81
1 - Propriedades...................................................................................................................................81
2 - Métodos..........................................................................................................................................82
c) Praticando a Impressão com TPrinter..................................................................................................82
1 - Evento OnClick..............................................................................................................................83
2 - Procedimento AbrirRelatorio.........................................................................................................84
3 - Procedimento FecharRelatorio.......................................................................................................84
4 - Função Fator...................................................................................................................................84
5 - Procedimento ImprimirCabecalho..................................................................................................85
6 - Procedimento ImprimirDetalhe......................................................................................................86
7 - Procedimento ImprimirRodape......................................................................................................87
29. Experts..................................................................................................................................................88
a) Database Form Wizard........................................................................................................................88
1 - Primeira janela:...............................................................................................................................88
2 - Segunda janela:...............................................................................................................................88
3 - Terceira janela:...............................................................................................................................88
4 - Quarta janela:..................................................................................................................................88
5 - Quinta janela:..................................................................................................................................88
b) Quick Report Wizard...........................................................................................................................89
1 - Primeira janela:...............................................................................................................................89
2 - Segunda janela:...............................................................................................................................89
c) Outros Wizards....................................................................................................................................90
30. Localização...........................................................................................................................................90
a) Units de constantes..............................................................................................................................90
31. Componentes........................................................................................................................................90
a) Receita de Instalação...........................................................................................................................90
32. Typecast................................................................................................................................................91
a) Typecast por tipo de dado....................................................................................................................91
1 - Boolean...........................................................................................................................................91
2 - Integer.............................................................................................................................................91
3 - Char................................................................................................................................................91
4 - Checked Typecast...........................................................................................................................91
5 - Outras funções................................................................................................................................92
6 - Fields..............................................................................................................................................92
33. Debug....................................................................................................................................................92
a) Passo a passo........................................................................................................................................92
b) Direto ao ponto....................................................................................................................................92
1 - Mudando o valor.............................................................................................................................93
5
6

1. DELPHI 4.0 BÁSICO


A idéia básica deste curso é mostrar detalhadamente as principais características do Delphi 4.0 ao invés de mostrar
superficialmente tudo o que o Delphi tem. Foi necessário optar pela profundidade em detrimento da abrangência porque o
Delphi é exageradamente abrangente (e isso é muito bom !). Nem mesmo um curso com milhares de páginas daria conta de
tudo com a profundidade necessária.
Este curso foi escrito para programadores principiantes, mas programadores experientes em outras linguagens também
vão se beneficiar. Ao ler este curso o programador vai ter uma base sólida sobre a qual construir o seu conhecimento.
Ao longo do curso vamos construir um programa, não um simples exemplo, mas um programa real, com utilidade
prática. O leitor vai receber dicas e orientações profissionais. Cada linha de código vai ser comentada. Cada propriedade
importante será explicada. Tudo passo a passo nos mínimos detalhes.
Com o conhecimento adquirido aqui o programador estará apto a criar programas num ambiente visual, com
tratamento de eventos, acessando banco de dados e emitindo relatórios. Isso é um excelente começo para um programador
profissional.
Os mais experientes podem ler os livros "Kylix - Delphi para Linux" e "Delphi 5 Tópicos Avançados"

2. INTRODUÇÃO
Para começar, pode-se dizer que Delphi é uma linguagem de programação. Mas isso é pouco. Na verdade Delphi é um
ambiente integrado de desenvolvimento, ou Integrated Development Environment (IDE).
Delphi está se tornando a linguagem usada para treinar novos profissionais nas escolas, faculdades e cursinhos por ser
fácil de aprender. Ao mesmo tempo está sendo largamente usada nas empresas para desenvolver sistemas com as tecnologias
mais quentes do momento: Orientação a Objeto, Cliente/Servidor, Internet, etc. Uma linguagem simples – baseada no bom e
velho Pascal – e evoluída, que incorpora todos os recursos mais modernos da informática, tinha mesmo que virar mania
nacional e internacional.
O que é que o Delphi tem que os outros não têm ?
É muito difícil listar todas as grandes qualidades do Delphi, mas vamos mostrar pelo menos as principais.
Em primeiro, segundo, terceiro e quarto lugares: Delphi é uma linguagem compilada.
Totalmente, completamente, cabalmente, cem por cento compilada. Lembre-se que "Compilação = + eficiência –
bugs".
Em seguida vem a facilidade de uso.
Com Delphi qualquer criança brinca e se diverte. Exageros à parte, qualquer pessoa esforçada consegue aprender.
Componentes e mais componentes.
O Delphi trouxe com sucesso para a informática o conceito de "peças intercambiáveis" criado por Henry Ford – o
fundador da fábrica de automóveis Ford. Antes das peças intercambiáveis, os carros eram feitos à mão. Um a um. Peça por
peça. Logicamente uma peça feita para um carro não se encaixava em outro carro. Se você acha que comprar peças nas
oficinas autorizadas hoje em dia é caro, imagine naquela época! Com Delphi os programas podem ser feitos com componentes
que estão disponíveis aos milhares por aí. Muitos deles são grátis. É só usar.
Delphi não é banco de dados.
Pode parecer contraditório mas isso é uma qualidade. Por não ser banco de dados o Delphi permite que o programador
escolha livremente o banco de dados mais indicado para cada caso. Delphi oferece conectividade nativa com bancos de dados
de todos os níveis, desde Paradox e Access até MS-SQL Server e Oracle. Além disso também tem suporte a ODBC e,
consequentemente, a todos os bancos de dados que têm driver ODBC.
Last but not least, Delphi sempre acompanha a última palavra em tecnologia.
O.O., Client/Server, Internet, ActiveX, etc. Delphi está antenado com tudo o que acontece de novidade na informática.
A pequena família Delphi
Antes de começar a estudar o Delphi 4.0, é importante conhecer toda a sua família. São ao todo 3 irmãos e um
priminho chato.
 Delphi 4.0 Standard, o caçula - É o menorzinho da família mas tem tudo o que um programador precisa para fazer
programas profissionais sérios, sem dever nada a ninguém. Linguagem de programação Orientada a Objeto, compilador
super-rápido e eficiente, mais de 85 componentes padrões, acesso nativo aos bancos de dados mais comuns – MS-Access,
FoxPro, Paradox e dBase – e outros bancos de dados via ODBC.
 Delphi 4.0 Professional, o irmão do meio - Faz tudo o que o irmão menor faz e ainda traz acesso ao banco de dados
Interbase, ferramentas para Internet, controles ActiveX e mais de 120 componentes com código fonte – ideal para quem
quer se aventurar pelo maravilhoso mundo da criação de componentes.
 Delphi 4.0 Client/Server, o big brother - Este aqui está com tudo e não está prosa. Tem tudo o que um programador pode
sonhar. Além de tudo o que os irmãos menores têm o Delphi 4.0 Client/Server acessa nativamente os bancos de dados
Oracle, Informix, Sybase, MS-SQL Server, DB2 e Interbase. Como o próprio nome já diz, trabalha com a arquitetura
cliente/servidor.
 Delphi 1.0, o priminho chato - Todos os Delphi brothers funcionam maravilhosamente bem com Windows de 32 bits –
Windows 95, Windows 98 e Windows NT. Se você tiver que desenvolver qualquer programa para Windows 3.1 não tem
7
alternativa. Somente o Delphi 1.0 funciona com Windows de 16 bits. Dentro do CD-ROM do Delphi 4.0 vem também a
versão 1.0 para suprir essa carência.
Este curso é sobre Delphi 4.0 e somente a versão 4.0 será tratada neste curso. Assim que for lançado o Delphi 6 será
feita a atualização deste curso.
Para você saber qual versão está instalada na sua máquina dê um clique no menu "Help --> About". Vai aparecer uma
janela informativa com o nome da versão.

3. AMBIENTE
Quem nunca brincou de cabra-cega ? Pois é. Pode ser muito engraçado ver os outros correndo com os olhos vendados
mas quando chega a nossa vez … Não tem graça nenhuma e a brincadeira pode custar alguns galos na cabeça. Usar o Delphi
sem conhecer o ambiente de trabalho é brincar de cabra-cega.
Antes de botar a mão na massa
Quando o Delphi é instalado ele cria um grupo de programas com vários ícones dentro. Vai ser muito bom dar uma
olhada nesses ícones para saber o que são e para que servem.

Ícone Descrição

Delphi 4 Este aqui é bem óbvio: é o próprio Delphi 4.0

BDE Administrator Borland Database Engine – popularmente conhecido como BDE – é o mecanismo de acesso a
banco de dados. Através do BDE Administrator você vai configurar os bancos de dados para que o
Delphi possa acessá-los.

Database Explorer É por aqui que você vai mexer com bancos de dados (criar, alterar, ver o conteúdo, etc.). Tem
algumas funções em comum com o BDE Administrator.

Database Desktop Outro utilitário para manutenção de bancos de dados. Faz a mesma coisa que o Database Explorer.
Mantido apenas por motivos saudosistas.

Image Editor Como editor de imagens este programa é apenas sofrível, mas ele é mais do que isso. É também um
editor de recursos.

Help O Delphi não é famoso por ter os melhores arquivos de ajuda on-line mas nos momentos de
desespero eles estão à disposição. Afie o seu inglês e good luck.
Tabela 1: Ícones

Estes sujeitos ainda vão dar muito o que falar. Cada um deles vai ser explicado nos mínimos detalhes no momento
oportuno.
Como é a cara dele ?
O Delphi tem essa cara desengonçada, assusta até criancinha. Por outro lado, quem não é o mais bonito tem que ser o
melhor. Com essa aparência esquisita o Delphi consegue colocar na ponta do mouse tudo o que você precisa. Rápido e fácil.
8

Figura 1: Ambiente

 
Vamos ver bem de perto o esqueleto dessa coisa chamada Delphi. Quando você clica no ícone do Delphi 4, ele abre 4
janelas, sendo que 3 ficam bem visíveis e 1 fica um pouco escondida atrás das outras. Vamos a elas:

(A) Barra de tarefas - É a janela que fica na parte superior do vídeo. Ela contém o menu, os botões de atalho e a palheta
de componentes. Tudo o que há de mais importante está aqui. Olho nela.

(B) Form1 - É a janela que fica no lado direito do vídeo. Para falar a verdade Form1 não é o nome dessa janela. Esse é
apenas um nome provisório que pode ser mudado depois. Daqui para frente vamos chamar essa janela de Form – sem
o 1 – para generalizar. Botões, caixas de edição, rótulos, tudo será aplicado no Form criando a "cara" do seu
programa.

(C) Object inspector - É a janela que fica no lado esquerdo do vídeo. Object inspector em bom português significa
inspetor de objeto. E faz juz ao nome. O objetivo dessa janela é inspecionar as propriedades e métodos dos objetos.
Não entendeu nada ? Tudo bem. Imagine que um botão é um objeto (Não estou falando do botão da sua camisa, não.
É botão desses que você fica clicando com o mouse.). Esse botão certamente tem várias propriedades – cor, tamanho,
posição, etc. – e vários métodos – o que o programa deve fazer quando alguém clicar, o que fazer quando alguém
passar com o mouse por cima, etc. Não seria uma boa idéia se existisse alguma coisa que mostrasse para o
programador todos os métodos e todas as propriedades de cada objeto ? Pois essa boa idéia é o Object inspector.
Entendeu agora ?

(D) Unit1.pás - É a janela oculta. Fica bem atrás do Form1. Para ver essa janela afaste o Form1 para o lado (arraste a
barra de cabeçalho onde está escrito Form1). Mais uma vez, Unit1 é só um nome provisório que pode ser mudado
depois. Vamos adotar aqui o nome genérico Unit – sem o 1. Quem conhece Pascal agora está pensando: "Ufa ! Que
alívio … Encontrei algo conhecido.". Quem não conhece Pascal não está entendendo nada. Bem, essa tal de Unit é
onde você vai escrever o programa propriamente dito. A Unit é o cérebro por trás do rostinho bonito do Form.

Na hora de programar você vai ter que ficar pulando de uma janela para outra mil vezes por dia. Para alternar
rapidamente use as teclas de atalho.
F10 – Pula do Form ou Unit ou Object Inspector (o que estiver ativo) para a Barra de Tarefas e vice-versa.
F11 – Pula do Form ou Unit (o que estiver ativo) para o Object Inspector e vice-versa
F12 – Pula do Form para Unit e vice-versa.
 
9
10

4. PROJETO
Delphi é um menino bem organizado. Não sai fazendo programas assim, com qualquer um, de qualquer jeito... Precisa
ter tudo bem projetado.
Projeto em Delphi nada tem a ver com projeto secreto ou plano de construção de qualquer coisa. Projeto é mais
parecido com uma coleção de coisas: Forms, Units, Helps, etc.
Como é esse tal de projeto ?
Quando você abre o Delphi, automaticamente é criado um projeto novo com um Form e uma Unit.
Vamos fazer uma experiência
Crie um diretório no seu disco rígido. Por exemplo: C:\DELPHILAB\CAPITULO3
Abra o Delphi. Como eu já disse, o Delphi criou um projeto novinho em folha para você.
Agora salve o projeto. Clique no menu "File --> Save All" ou no botão de atalho "Save All".
Vai aparecer uma caixa de diálogo para salvar arquivo. O nome do arquivo é Unit1.pas e o tipo é Delphi Unit (*.pas).
Procure o seu diretório (aquele que você criou há pouco) e clique no botão Save.
Vai aparecer outra caixa de diálogo para salvar arquivo. O nome do arquivo agora é Project1.dpr e o tipo é Delphi
Project (*.dpr). Clique no botão Save.
Use o Windows Explorer para olhar dentro do seu diretório. Você deve encontrar 6 arquivos.
 
Arquivo Conteúdo

Project1.cfg Apesar de ter a extensão *.cfg este é um arquivo texto. Guarda diversas opções do compilador. Discutir
estas opções está fora do escopo deste curso. Para a maior parte dos casos as opções default funcionam
perfeitamente.

Project1.dof Apesar de ter a extensão *.dof este é um arquivo texto. Guarda diversas opções do projeto. Estas opções
você configura usando a caixa de diálogo Project Options que vamos ver mais à frente.

Project1.dpr Contém o código fonte principal do seu projeto. O próprio Delphi cria e mantém este programa.
Apesar da extensão *.dpr também é um arquivo texto. Seja um bom menino e não toque aqui. Se você
quiser ver o que tem dentro clique no menu "Project  ViewSource". Veja mas não toque! Basicamente
o que esse programa faz é mostrar o Form principal e ficar esperando esse Form ser fechado. No nosso
exemplo não tem erro: só tem um Form, logo o único Form só pode ser o principal.

Project1.res É o arquivo de recursos do seu projeto. Pode conter imagens, textos, ícones e outras recursos que o seu
projeto precisar. Inicialmente contém apenas o ícone do projeto. Para abrir este arquivo use o editor de
recursos. Clique no menu "Tools  Image Editor". Dentro do editor de recursos clique em "File 
Open". Procure o arquivo Project1.res no seu diretório. Clique no botão Open.

Unit1.dfm Contém a definição do Form. Tudo o que o form tem – botões, painéis, caixas de edição, etc. – está
definido aqui dentro. No nosso caso o Form está vazio porque não colocamos nada dentro dele ainda.
Colocar componentes ou alterar as propriedades do Form vai fazer o Delphi alterar este arquivo.

Unit1.pas Finalmente encontramos uma coisa onde você pode mexer … com cuidado! Este vai ser o seu programa.
O Delphi escreve as partes principais, mas a parte mais difícil fica com você.
Tabela 2: Arquivos

Outros tipos de arquivos podem fazer parte do projeto e serão vistos no momento oportuno. Aguarde…
Você não deve renomear estes arquivos diretamente através do Windows Explorer ou do DOS.
Para mudar o nome do projeto – e consequentemente mudar o nome dos arquivos *.dpr, *.cfg, *.res e *.dof - clique no
menu "File --> Save Project As …" e digite o nome que quiser na caixa de diálogo para salvar arquivos.
Para mudar o nome da Unit – arquivos *.dfm e *.pas – clique no menu "File --> Save As …". Os nomes podem mudar
mas as extensões devem permanecer as mesmas.
Como tudo isso funciona ?
Já vimos que um projeto Delphi é composto de seis tipos principais de arquivos. Já vimos que alguns arquivos são de
propriedade quase exclusiva do Delphi. Ninguém mexe com eles. Já vimos que o seu programa vai ficar dentro da Unit e que a
janela que o seu programa vai mostrar fica no Form. E daí ?
Daí que para um programa Delphi ser executado ele precisa ser transformado em um arquivo executável (com a
extensão *.exe). Isso acontece pelo processo de compilação. A compilação empacota todas essas informações em um único
arquivo que vai ter o mesmo nome do projeto, só que com a extensão *.exe, naturalmente.
11
Para quem ainda não captou a importância da compilação aqui vai a explicação:
Quando o programador faz um programa, o programador escreve em uma língua mais ou menos humana. Delphi, por
exemplo, parece inglês. Já o computador não entende bulhufas da linguagem humana. A língua do computador é binária, é só
zerinho-um.
Está na cara que alguém tem que traduzir a linguagem de programação – quase humana – para a linguagem da
máquina. Quem faz isso é o compilador.
Os compiladores produzem alguns efeitos colaterais muito benéficos para o programador. O efeito principal é a
velocidade. Um programa compilado roda muito mais rápido do que um programa não compilado. Outro efeito é a
consistência que o compilador faz de todo o programa durante o processo de compilação. Com isso o compilador aponta erros
de programação mais comuns, reduzindo o número de bugs.
Profissionalizando o seu projeto
O projeto tem algumas opções interessantes para dar uma aparência mais profissional ao seu programa.
Clique no menu "Project --> Options".
Clique na aba Application.
Essa aba tem uma caixa de edição chamada Title. Aqui você pode escrever um nome para o seu programa. Digite
"Hello World". Esse nome vai aparecer perto do ícone quando o seu programa for minimizado.
Logo abaixo tem outra caixa de edição chamada Help File. Não digite nada aqui por enquanto. Aguarde para usar no
dia que você tiver um arquivo de ajuda on-line. Um programa profissional tem que ter ajuda on-line, lembre-se disso.
Depois vem o botão Load Icon. Clique nesse botão e procure por um ícone. Serve qualquer arquivo com a extensão
*.ico. Quando você executar o seu programa o ícone escolhido vai aparecer no canto superior esquerdo do Form.
Para o seu próprio bem-estar não faça mais nada aqui! Clique no botão OK e pronto.
Hello World!
Chegou o momento tão esperado: O seu primeiro programa Delphi !
Definição do programa: Mostrar uma janela com a mensagem "Hello, World". Só isso.

Figura 2: Hello World

Vamos aproveitar o mesmo projeto que foi salvo no item anterior. Se você fechou o Delphi, abra-o novamente. Para
reabrir o projeto clique no menu "File --> Open", procure o seu diretório, clique sobre o arquivo Project1.dpr e clique no botão
Open.
Para reabrir um projeto sem ter que procurar o diretório clique no menu File --> Reopen e escolha o projeto na lista
que vai aparecer. Se a lista não aparecer é porque não tem nenhum projeto fechado para ser reaberto.
Certifique-se que o Form esteja visível. Se necessário use as teclas de atalho – F10, F11 ou F12, lembra?
Para mostrar a mensagem no seu Form, você vai precisar de um componente chamado Label. Procure na barra de
tarefas, dentro da palheta de componetes, na aba Standard. O componente Label é um botão com a letra A em cima.
Clique sobre o componente Label. O componente vai mudar de forma, parecendo que afundou. Agora clique sobre o
Form. Vai aparecer a palavra "label1" escrita no Form.
O Object Inspector mudou. Se você clicar sobre o Form ele vai mostrar as propriedades do Form. Se você clicar sobre
o "label1" ele vai mostrar as propriedades do Label.
Procure entre as propriedades do Label listadas no Object Inspector uma propriedade chamada Caption. Essa
propriedade contém o texto que vai ser mostrado pelo label. Clique sobre a propriedade Caption e digite "Hello, World!".
Mude também a propriedade Font do Label. Clique sobre a propriedade Font. Vai aparecer um minúsculo botão com
três pontinhos. Clique sobre esse botão e vai aparecer uma caixa de diálogo de fonte. Escolha a fonte Arial, o estilo Bold Italic,
o tamanho 36 e a cor Red. Clique no botão OK.
Pronto! Agora é só botar pra rodar. Clique no menu "Run --> Run" ou use a tecla de atalho F9 ou use o botão de
atalho "Run".
12
E então? Está orgulhoso ? Pois deveria estar mesmo. Você fez um bom trabalho.
Mais arquivos
Quando você mandou rodar o "Hello World", o Delphi automaticamente compilou e executou o programa. Como
resultado foram gerados mais arquivos dentro do diretório onde reside o projeto. Vamos a eles.

Arquivo Conteúdo

Arquivos com Arquivos com extensão iniciando por ~ (til) são apenas back-up dos arquivos originais: *.~df
extensão *.~* corresponde a *.dfm, *.~pa corresponde a *.pas, *.~dp corresponde a *.dpr, e assim por diante.
Estes arquivos podem ser excluídos sem nenhum prejuízo para o projeto.

Unit1.dcu É a versão compilada da Unit1.pas. Este arquivo é gerado sempre que necessário: na primeira vez em que
um projeto é compilado ou quando a Unit correspondente é alterada.
Este arquivo também pode ser excluído sem prejudicar o projeto.

Project1.exe É o programa executável.


Tabela 3: Mais arquivos

5. FORMULÁRIO
Windows é conhecido como o sistema das janelas porque a principal
forma de comunicação entre os programas e os humanos que usam este sistema
são as janelas. O que o Formulário tem a ver com isso? Tudo!
Vamos nos comunicar
Afinal de contas, qual a diferença entre Form e janela?
Um programa tem dois estados diferentes. O primeiro estado é o
desenvolvimento. Neste momento o programador usa o Form para desenhar
como vai ser a aparência da janela que o programa vai mostrar. O segundo
estado é a execução. É quando o programa está sendo usado e mostra a janela
em seu formato final, com todas as funcionalidades.
A grosso modo pode-se dizer que Form é o protótipo da janela.
Propriedades
Vamos investigar mais a fundo esse tal de Form.
Reabra o projeto que você criou na página anterior .
Agora selecione o Form clicando sobre a área pontilhada
Object Inspector mostra o nome do Form na primeira linha
Logo abaixo mostra duas abas: Properties e Events
Clique na aba Properties

O Object Inspector está mostrando agora uma lista longa, muito longa,
quase interminável de propriedades. Não entre em pânico ainda. Vamos ver as
propriedades mais importantes e o que fazer com elas.

Figura 3: Propriedades do Form


Propriedade Função

AutoScroll Sabe quando você abre um documento no editor de textos e o editor põe uma barra de rolagem
no lado direito para que você possa navegar pelo documento, um pedaço de cada vez ? Para a
13
sua janela também ter esse efeito coloque AutoScroll=True. Se você quiser que sua janela tenha
tamanho fixo use AutoScroll=False. Isso é importante quando o seu programa for usado em
vídeos com resoluções diferentes. No nosso Form de exemplo coloque False.

Caption É o texto que aparece na borda superior da janela. Geralmente usado para descrever o que a
janela faz. No nosso Form de exemplo coloque "Hello World"

Color É a cor de fundo do Form. Clique sobre a propriedade Color. Vai aparecer um botão com uma
seta para baixo. Clique sobre este botão. Vai aparecer uma lista de cores. Escolha clBlue.
Agora o seu Form está colorido.

Font Aqui você escolhe a fonte do Form. Todos os componentes – botões, labels, etc. – que você
colocar no Form de agora em diante usarão essa fonte como default. Você vai poder especificar
uma fonte diferente para cada componente do Form se quiser mas é mais fácil definir como
default a fonte mais usada. Para definir uma fonte para este Form clique sobre a propriedade
Font. Vai aparecer um botão com reticências ("…"). Clique sobre este botão. Vai aparecer a
janela Font. Selecione fonte Arial, cor Black, tamanho 8, estilo Regular e nenhum efeito.
Clique no botão OK. Dica: Sempre selecione uma fonte True Type – indicado pelo símbolo TT
na lista de seleção de fontes da janela Font. Isso é importante quando o seu programa for usado
em vídeos com resoluções diferentes.

Icon Serve para definir um ícone específico para esta janela. Lembre-se que você pode definir um
ícone válido para todo o projeto. Se você não definir um ícone aqui, esta janela vai mostrar o
ícone do projeto definido em Project Options. Para definir um ícone para esta janela clique
sobre a propriedade Icon. Vai aparecer um botão com reticências ("…"). Clique sobre este
botão. Vai aparecer a janela Picture Editor. Clique no botão Load…  Vale qualquer arquivo
*.ico. Clique no botão OK. Clique no botão OK de novo. Pronto. A sua janela já tem um ícone
próprio, diferente do ícone geral do projeto.

Name É o nome que será usado pelo seu programa quando for se referenciar ao Form. Deve ser um
nome sem caracteres especiais ou espaço em branco. Se você digitar um nome errado o Delphi
vai mostrar a mensagem "… is not a valid component name".Clique sobre a propriedade Name
e digite um nome. Procure criar um padrão de nomes. Alguns projetos grandes podem ter
dezenas de Forms. Se os nomes não forem padronizados vai ser difícil achar um Form na hora
em que você precisar dele. No nosso exemplo digite: frmHello

Position Indica onde a janela vai aparecer quando o programa for executado. Clique sobre a propriedade
Position. Vai aparecer um botão com a seta para baixo. Clique sobre o botão. Vai aparecer uma
lista com as opções: poDefault – Esta opção permite que o próprio Windows determite a
posição e o tamanho do Form em tempo de execução.poScreenCenter – Esta opção mostra a
janela centralizada. Esqueça as outras opções. E mais: nunca, eu disse nunca, deixe na
posição poDesigned ! Isso vai fazer com que a janela apareça na mesma posição em que o
Form foi desenhado. Se o seu programa for executado em um vídeo com resolução diferente
daquela em que o Form foi desenhado a janela poderá aparecer fora do vídeo. Em outras
palavras, não vai aparecer em lugar nenhum !

Scaled Faz o ajuste no tamanho da janela e todos os componentes dentro dela caso a resolução do
vídeo onde o seu programa está sendo executado seja diferente da resolução do vídeo onde
você desenhou o Form. Isso não funciona muito bem mas deixe essa propriedade sempre True.

WindowState Determina como a janela vai aparecer: minimizada, maximizada ou normal. Clique sobre a
propriedade WindowState. Vai aparecer um botão com uma seta para baixo. Clique sobre o
botão. Vai aparecer uma lista com as opções wsMinimized, wsMaximized e wsNormal.
Escolha a opção wsNormal.
Tabela 4: Propriedades do Form

Vamos ver como ficou ?


Depois de fazer todas estas alterações, vamos executar o programa novamente para ver como ficou. Clique no menu
"Run  Run". Que tal ? Ficou bom ?
Eventos
14
Evento é uma coisa que acontece. E o que pode acontecer com um Form ? Ele pode ser criado, destruído, mostrado,
clicado, etc. Isso é importante: Você pode dizer ao Form exatamente o que fazer quando ocorrer um evento.
Clique na aba Events do Object Inspector. Outra lista incomensurável. Paciência. Vamos ver os principais eventos.

Figura 4: Eventos do Form


 
Evento Função

OnActivate Acontece sempre que o Form é ativado.

OnClick Acontece sempre que o Form é clicado com o mouse.

OnClose Acontece sempre que o Form é fechado.

OnCreate Acontece uma única vez quando o Form é criado.

OnDblClick Acontece sempre que o Form recebe um duplo click.

OnShow Acontece sempre que o Form é mostrado.


Tabela 5: Eventos do Form

A) DEFININDO UM EVENTO
Para definir o que o Form deve fazer quando ocorrer um evento faça o seguinte:
Dê um clique duplo sobre a caixa de edição ao lado do evento, por exemplo OnClick.
15
Com isso o Delphi vai criar uma procedure dentro da Unit com um nome default. No caso do evento OnClick o nome
da procedure é FormClick.
Uma alternativa é digitar o nome da procedure na caixa de edição ao lado do evento. Dessa forma o Delphi vai criar a
procedure com o nome digitado. Use o nome default sempre que possível para facilitar o trabalho de manutenção.
Digite dentro da procedure – entre o begin e o end; - os comandos que serão executados toda vez que alguém clicar
sobre o Form. Só para testar digite o comando:
ShowMessage(‘Alguém me clicou !’);
A procedure deve ter ficado assim:
procedure TfrmHello.FormClick(Sender: TObject);
begin
   ShowMessage('Alguém me clicou!');
end;
Vamos ver como ficou ?
Clique no menu "Run --> Run". Clique sobre a janela do Hello World. Se deu tudo certo deve ter aparecido a
mensagem "Alguém me clicou !".
Experimente agora os outros eventos: OnCreate, OnDestroy, OnClose, OnActivate e OnDblClick. Coloque uma
mensagem apropriada para cada evento. Assim você vai saber em que momento cada evento acontece. Rode o programa
novamente e observe o que acontece.
Você não deve apagar uma procedure criada pelo Delphi.
Quando uma procedure não for mais necessária exclua os comandos entre o begin e o end; da procedure. Ao salvar o
projeto o próprio Delphi vai apagar a procedure e todas as referências a ela feitas dentro do projeto.

6. COMPONENTES VISUAIS
O Windows introduziu uma série de componentes visuais para facilitar a comunicação homem-máquina, ou mulher-
máquina, conforme o caso. Estes componentes são comuns a todos os programas para Windows.
O Delphi possui uma coleção completa desses componentes visuais. Estão todos na palheta de componentes que você
viu lá atrás (Figura 1: Ambiente). Todos são parecidos e se comportam mais ou menos do mesmo jeito. Depois que você pegar
intimidade com os principais componentes, os outros vão ser bolinho.
Os componentes têm propriedades e eventos tal qual o Form. Neste capítulo veremos apenas as propriedades. Para
trabalhar com eventos é necessário maior conhecimento de Object Pascal, que será visto nos próximos capítulos.
Construindo a interface
Vamos ver na prática como construir a interface visual usando os componentes. Para isso vamos desenhar um Form
de verdade, com alguma utilidade prática.
Definição do Form:
Cadastro de clientes com as operações básicas - inclusão, alteração, exclusão e consulta.
Dados cadastrais dos clientes:
Código de identificação, Nome, CGC/MF, Endereço, Nome da pessoa de contato, Status, Telefone, Preferências e
Valor do limite de crédito.
Vamos lá:
Crie um diretório no seu disco rígido. Por exemplo: C:\DELPHILAB\CAPITULO5
Crie um projeto novo. Para isso abra o Delphi e clique no menu "File --> New Application"
Reveja todas as recomendações feitas em relação ao projeto e ao Form nos capítulos anteriores (título do projeto,
fonte, propriedades do Form, etc.)
Salve o projeto com o nome de "pcliente.dpr" e a unit com o nome "ucliente.pas" no seu diretório de trabalho.
Não se esqueça de salvar o projeto de tempos em tempos durante o exercício.
Menu principal
Procure pelo componente MainMenu na palheta de componentes, na aba Standard. Parando o mouse sobre um
componente – sem clicar - o Delphi mostra uma dica com o nome do componente correspondente.
Clique no componente MainMenu.
Clique sobre o Form – pode ser em qualquer lugar do Form
Outra maneira de adicionar um componente no Form é clicar no menu "View --> Component List".
O Delphi vai abrir uma janela com a lista de componentes em ordem alfabética. Você só precisa digitar o nome do
componente e clicar no botão "Add to form".
Note que o verdadeiro nome do MainMenu é TmainMenu.
O Delphi colocou um botão dentro do Form e mais nada. E agora ? Onde está o menu ?
Clique sobre a propriedade Items no Object Inspector
Clique sobre o botão das reticências que apareceu ao lado da propriedade. O Delphi abriu o editor de menu e o Object
Inspector está mostrando as propriedades de um MenuItem.
Clique na propriedade Caption do MenuItem no Object Inspector
Digite o texto que você quer que apareça no menu. Ex.: "Arquivo" e tecle ENTER
O editor de menu mostra uma caixa pontilhada ao lado e outra abaixo da palavra "Arquivo". Se você clicar sobre a
caixa do lado, vai incluir outro item de menu. Se você clicar na caixa de baixo vai incluir um sub-menu do "Arquivo".
16
Crie os itens "Incluir", "Alterar", "Excluir", "Próximo" e "Anterior"
Crie um sub-item em "Arquivo" com o texto "Sair"
Para criar teclas de atalho digite um "&" no Caption do MenuItem.
Por exemplo: "&Incluir" faz com que a letra "I" apareça no menu sublinhada e o usuário poderá ativar a função de
inclusão teclando "Alt+I".

Figura 5: Menu Principal

Vamos implementar agora a opção "Sair". As outras opções vão ser implementadas mais tarde.
Quando o usuário clicar a opção "Sair", o programa deve fechar o Form.
Dê um duplo clique no componente MainMenu
Clique na opção "Sair" no editor de menu
Clique na aba Events no Object Inspector
Dê um duplo clique ao lado do evento OnClick
Coloque o comando Close para fechar o Form

Figura 6: Menu Principal - respondendo a evento

7. BARRA DE FERRAMENTAS
17
A barra de ferramentas é um conjunto de botões que dá acesso rápido às funções principais do Form.
Procure na palheta de componentes, na aba Win32, o componente ToolBar.
Clique no componente ToolBar
Clique no Form
O Delphi colocou uma barra grudada no menu. Só a barra, sem nada dentro. Você precisa incluir os botões.
Clique com o botão direito do mouse sobre a barra ToolBar.
Apareceu um menu pop-up. Observe as opções "New Button" e "New Separator".
Clique na opção "New Button"
Apareceu um botão na barra. Observe que o Object Inspector está mostrando as propriedades do ToolButton – o botão
da barra de ferramentas.
Clique na propriedade Name
Altere o nome para algo significativo, como "btSair" para o botão com a função de sair
Clique na propriedade Hint
Digite o texto que vai aparecer quando o mouse passar sobre o botão. No botão "btSair" digite "Sair".
Clique na propriedade ShowHint
Mude o valor da propriedade para True. Quando ShowHint é False o texto digitado em Hint não aparece em momento
algum
Crie botões para cada opção do menu (sair, incluir, alterar, excluir, anterior e próximo). Naturalmente se o menu
tivesse dezenas ou centenas de opções você criaria botões apenas para as funções principais. Para cada botão mude as
propriedades Name, Hint e ShowHint
Não se preocupe ainda com as imagens dos botões. Vamos colocá-las daqui a pouco. Aguarde.
Crie um separador para colocar entre as opções de edição e as opções de consulta.
Clique com o botão direito do mouse sobre o ToolBar
Clique na opção "New Separator" do menu pop-up
Clique-e-arraste o separador até ficar entre os quatro primeiros botões e os dois últimos
Para dar uma aparência de Office 97 à sua barra de tarefas:
Clique na barra de tarefas
Clique no Object Inspector, na opção Flat
Mude a opção para True

Figura 7: Barra de Ferramentas

O botão btSair vai fazer exatamente a mesma coisa que a opção "Sair" do menu. Em termos de programa isso
significa que o evento OnClick do botão vai "apontar" para a mesma procedure do evento OnClick da opção do menu.
Selecione o botão btSair
Clique na aba Events do Object Inspector
Clique no evento OnClick
Selecione a procedure Sair1Click na lista
Pronto. Toda vez que o usuário clicar no botão btSair a procedure Sair1Click vai ser executada e o Form vai fechar
(por causa do comando Close).
 

8. LISTA DE IMAGENS
18
Lista de imagens é exatamente o que o nome diz: é uma lista de imagens. Funciona como um curinga. Qualquer
componente que precise de uma lista imagens pode fazer uso do componente lista de imagens.
A barra de ferramentas é um desses componentes. Vamos colocar uma ImageList no Form para escolher as imagens
que aparecerão nos botões da barra de ferramentas.
Procure na palheta de componentes, na aba Win32, o componente ImageList.
Clique no componente ImageList
Clique no Form
O Delphi colocou um botão colorido no Form. Observe o Object Inspector. O ImageList tem duas propriedades
importantes: Height (altura) e Width (largura). Essas propriedades definem o tamanho das imagens, igual para todas as
imagens da lista. No nosso exemplo o tamanho default (16 X 16) está ótimo. Deixe do jeito que está.
Agora vamos adicionar as imagens à lista.
Clique no botão do ImageList com o botão direito do mouse
Clique na opção "ImageList Editor" do menu pop-up que apareceu
Outra maneira de abrir o ImageList Editor é dar um duplo clique no botão do ImageList.
Clique no botão Add do ImageList Editor
Apareceu uma caixa de diálogo "Add Images".
Usando a caixa de diálogo, procure o diretório Imagens no CD-ROM
Selecione a imagem "Sair.bmp"
Clique no botão Open
A imagem selecionada agora aparece no ImageList Editor. Na parte superior existem algumas opções:
Crop faz com que a imagem fique alinhada pela parte superior esquerda. A imagem vai ser truncada se for maior que
o tamanho da ImageList – propriedades Height e Width.
Strech faz com que a imagem seja esticada ou encolhida, conforme o caso, para caber no tamanho da ImageList
Center faz com que a imagem fique alinhada pelo centro, truncando se for maior.
Continue adicionando imagens, uma para cada botão da barra de ferramentas. Use as imagens "Incluir.bmp",
"Editar.bmp", "Apagar.bmp", "Voltar.bmp" e "Avançar.bmp"
Observe que cada imagem recebe um número a partir de zero. Esse número vai ser útil para associar cada botão da
barra de ferramentas à sua imagem correspondente.
Clique no botão OK
Ainda não aconteceu nada. Os botões da barra de ferramentas continuam em branco. Falta associar a lista de imagens
à barra de ferramentas.
Clique na barra de ferramentas
Clique na propriedade Images do Object Inspector
Clique no botão com a seta para baixo que aparece ao lado da caixa de edição da propriedade Images
Selecione a ImageList que aparece na lista de ImageLists
A sua barra de ferramentas está pronta.
Você pode especificar uma segunda lista de imagens para a sua barra de ferramentas na propriedade HotImages. As
imagens da lista HotImages aparecem quando o mouse passa sobre o botão.
 

Figura 8: ImageList

9. BARRA DE STATUS
19
A barra de status é o rodapé do Form. Pode ser usada para uma infinidade de coisas. Mostrar mensagens para o
usuário, data e hora, enfim, qualquer informação útil ou inútil.
No nosso caso vamos usar a barra de status com três finalidades: (a) indicar se o registro corrente – aquele que está
aparecendo no Form – está sendo incluído ou editado (b) mostrar mensagens e (c) mostrar a hora.
Procure o componente StatusBar na palheta de componentes, na Aba Win32.
Clique no componente StatusBar
Clique no Form
O Delphi colocou uma barra de status no rodapé do Form. A barra de status já está pronta para mostrar uma
mensagem de cada vez. É só usar a propriedade SimpleText. Como fazer para mostrar três informações simultaneamente ?
Dividindo a barra de status em painéis.
Clique com o botão direito do mouse na barra de status
Clique na opção Panels Editor do menu pop-up
Um duplo clique sobre a barra de status também abre o Panels Editor.
Clique com o botão direito do mouse sobre a área em branco do Panels Editor
Clique na opção Add do menu pop-up
Ou então aperte a tecla "Insert"
Repita até definir três painéis. O tamanho de cada painel pode ser controlado pela propriedade Width. Observe que
apareceram divisões na barra de status do Form. A barra de status está pronta.

Figura 9: StatusBar

A) GRID
Grid é um componente que tem a aparência de uma planilha de cálculo. Possui células distribuídas em linhas e
colunas. Existem duas versões básicas de grid: StringGrid e DBGrid. Os dois grids têm a mesma aparência. A diferença está na
origem dos dados que aparecem nas células.
O DBGrid faz parte de uma família de componentes conhecida como Data Aware Controls. São componentes
conectados diretamente ao banco de dados. Use o DBGrid quando quiser conectá-lo a um banco de dados. As células são
preenchidas com dados do banco de dados. (Os bancos de dados serão vistos mais adiante).
O StringGrid não é conectado a nenhum banco de dados. O programa é responsável pelo preenchimento das
informações nas células.
No nosso exemplo precisamos conectar o grid ao banco de dados (O banco de dados ainda não foi criado. Estamos
trabalhando apenas a interface visual por enquanto). O objetivo desse grid é mostrar a relação de clientes já cadastrados.
Procure na palheta de componentes, na aba Data Controls, o componente DBGrid.

Clique no componente DBGrid


Clique no Form
Vamos trabalhar as propriedades do DBGrid.
20

Propriedade Função

Align Determina como o DBGrid vai se alinhar ao Form.alNone = Não alinha; alTop = Alinha na parte superior;
alBottom = Alinha na parte de baixo; alLeft = Alinha à esquerda; alRight = Alinha à direita; alClient = Enche
o Form com o DBGrid. Mude para AlTop, assim o DBGrid vai grudar na barra de ferramentas.

Columns Define as colunas do grid. Não mexa aqui agora. Vamos voltar a essa propriedade quando criarmos o banco de
dados.

DataSource Diz ao DBGrid de onde vêm os dados que vão aparecer no grid. Não mexa por enquanto.

Font Funciona do mesmo jeito que a propriedade Font do Form. Se foi definida uma fonte default no Form então
você não precisa alterar nada aqui. Vale a mesma dica do Form: use sempre (eu disse SEMPRE) fontes
TrueType.

Name Pode ser qualquer nome. Mude para gridCliente.

Options Dê um duplo-clique sobre a propriedade Options e vai abrir uma lista de opções. dgEditing: Quando
verdadeiro, permite que o usuário digite diretamente no grid incluindo, alterando ou excluindo informações.
Mude para False porque vamos criar outros componentes para fazer a edição dos dados.
Tabela 7: Propriedades do DBGrid

Todas as propriedades que têm o mesmo nome têm a mesma função. Por exemplo: A propriedade Color no Form faz a
mesma coisa que a propriedade Color no Grid.

Figura 10: DBGrid

B) EDIT
Edit, também conhecido como caixa de edição, serve para mostrar valores e também para receber valores digitados
pelo usuário. Assim como o grid, existem duas versões básicas de caixa de edição: Edit e DBEdit.
DBEdit é um Data Aware Control e deve ser conectado a um banco de dados. O Edit, ao contrário, não é conectado ao
banco de dados.
Vamos colocar um DBEdit no Form para editar o campo "Código". Procure na palheta de componentes, na aba Data
Controls, o componente DBEdit.
Clique sobre o componente Edit.
Clique sobre o Form.
Observe o Object Inspector. Ele está mostrando as propriedades da caixa de edição.

Propriedade Função
21
Color É a cor de fundo da caixa de edição. Deixe a cor normal, que é clWindow. Quando a caixa de edição for
usada somente para mostrar algum valor, sem permitir que o usuário digite nada, é bom alterar a cor para
clBtnFace. Apenas uma atitude simpática para avisar ao usuário que ali ele não pode digitar. Para alterar a
cor do texto contido na caixa de edição use a propriedade Font.

DataField Indica qual campo do banco de dados vai ser mostrado no DBEdit. Vamos ver com detalhes mais adiante.

DataSource Funciona do mesmo jeito que o DataSource do DBGrid. Vamos ver com detalhes mais adiante.

Enabled Em algumas situações o programa deve controlar se o usuário pode ou não alterar o valor contido numa
caixa de edição. Enabled=True significa que a caixa está disponível para digitação. Quando
Enabled=False o usuário não pode digitar e o texto contido na caixa aparece na cor cinza-desmaiada. O
mesmo efeito pode ser obtido usando a propriedade ReadOnly. Queremos que o usuário digite o código do
cliente por isso deixe Enabled=True.

Font Propriedade já conhecida

Name É o nome da caixa de edição. Escolha sempre um nome significativo. Isso vai facilitar a sua vida e a vida
de quem for fazer manutenção no seu programa. Esta caixa de edição vai ser usada para digitar o código
do cliente. Batize-a de "edCodigo".

ReadOnly Faz o mesmo efeito do Enabled. ReadOnly=True é a mesma coisa que Enabled=False e vice-versa. A
vantagem do ReadOnly é que ele não deixa o texto que aparece na caixa de edição com aquela cor cinza-
desmaiada. No nosso caso, deixe ReadOnly=False. Dica: Quando quiser impedir a digitação em uma caixa
de edição não use a opção Enabled=False. Use ReadOnly=True tomando o cuidado de alterar também a
cor de fundo para clBtnFace para indicar que a caixa está bloqueada. Assim é mais elegante.
Tabela 8: Propriedades do DBEdit

Figura 11: DBEdit

C) LABEL
Label é um rótulo, geralmente usado para descrever o conteúdo de outro componente.
O componente Label está na palheta de componentes, na aba Standard.
22
Clique no componente Label
Clique no Form
Clique-e-arraste o label para colocá-lo ao lado do DBEdit que já está no Form.
Clique na propriedade Caption no Object Inspector
Mude o valor da propriedade Caption para "Código"

Figura 12: Label

D) EXERCÍCIO
Faça com os outros campos do cadastro de clientes o mesmo que foi feito com o código do cliente.
Coloque no Form os campos: Nome, CGC/MF, Logradouro, Complemento, Cidade, CEP, Nome da pessoa de
contato, Telefone e Valor do limite de crédito. Serão nove pares de componentes Label + Edit.
Os campos restantes – Status, Preferências, Estado – serão incluídos depois, com outros componentes.

Figura 13: Exercício

E) COMBO BOX
23
É uma caixa de edição combinada com uma lista de opções. Funciona assim: Na caixa de edição o usuário poderá
digitar livremente o que quiser. Na lista de opções o usuário poderá escolher uma das opções pré-estabelecidas.
Existem duas versões de combo box: ComboBox e DBComboBox (Data Aware).
Coloque um DBComboBox no Form do seu projeto. O DBComboBox está na palheta de componentes, aba Data
Controls. Este combo box vai ser usado para informar o estado (UF) do cliente.
Observe no Object Inspector as propriedades do combo box. Por ser um tipo de caixa de edição tem quase todas as
propriedades da própria caixa de edição. Vamos ver as propriedades:

Propriedade Função

Color, DataField, Propriedades já conhecidas


DataSource, En-
abled, Font e
Name

Items É onde você vai definir a lista de opções. Clique sobre a propriedade Items. Vai aparecer o famoso botão
das reticências. Clique sobre ele. Vai aparecer uma janela chamada "String List Editor". Aqui você pode
digitar uma lista de palavras, sendo uma em cada linha. Escreva a lista de estados: PR, SC, RS, SP, RJ,
MG, etc., um em cada linha. Clique no botão OK.

Style Essa propriedade controla o comportamento do combo box. As opções são: csDropDown – Permite
digitação livre na caixa de edição e seleção na lista de opções. csDropDownList – Não permite digitação
na caixa de edição. O usuário terá que escolher uma das opções da lista. csSimple – Permite digitação livre
na caixa de edição mas não mostra a lista de opções. Para selecionar um item da lista o usuário deve usar
as setas do teclado. Não é interessante que o usuário invente um novo estado, por isso use a opção
csDropDownList. As outras opções (csOwnerDrawFixed e csOwnerDrawVariable) não serão discutidas
neste curso.
Tabela 9: Propriedades do Combo Box

Não esqueça de colocar no Form um label para descrever o combo box.

Figura 14: Combo Box

F) RADIO GROUP
24
Radio Group parece um seletor de frequência de rádio. Quando um botão do grupo é pressionado o outro salta, de
forma que um e somente um botão fica selecionado de cada vez.
Vamos usar o Radio Group para informar o Status do cliente, que pode ser Ativo ou Inativo.
Coloque um DBRadioGroup dentro do Form e dê uma espiada nas propriedades.

Propriedade Função

Color, DataField, Propriedades já conhecidas


DataSource, En-
abled, Font e
Name

Caption É o título que aparece na parte de cima do Radio Group. Coloque algo que descreva o grupo.
O Radio Group atual mostra o Status, então escreva "Status".

Columns Número de colunas de Radio Buttons. Normalmente as opções do Radio Group ficam listadas em uma
única coluna mas nada impede que sejam arranjadas em várias colunas. No caso atual coloque duas
colunas.

Items São as opções de seleção propriamente ditas. Clique sobre a propriedade Items. Clique sobre o botão das
reticências. Vai aparecer uma janela chamada String List Editor. Digite as opções, uma em cada linha. No
caso atual escreva "Ativo" e "Inativo". Clique no botão OK.

Values Muitas vezes as informações são armazendadas nos bancos de dados na forma de códigos. Por exemplo: a
opção "Ativo" pode ser gravada simplesmente como o código "A" e "Inativo" como código "I". A
propriedade Values é a tabela de conversão entre a codificação do banco de dados e a opção descritiva da
propriedade Items. Os códigos devem ser digitados na mesma ordem em que aparecem as opções em
Items. Clique sobre a propriedade Values. Clique sobre o botão das reticências. Vai aparecer uma janela
chamada String List Editor. Digite as opções, uma em cada linha. No caso atual escreva "A" e "I". Clique
no botão OK.
Tabela 10: Propriedades do Radio Group

Figura 15: Radio Group

G) CHECK BOX
25
Check box significa "Caixa de Marcação". É uma caixa onde uma opção pode ser marcada ou não, verdadeira ou
falsa. Quando a opção é verdadeira a caixa aparece marcada e quando a opção é falsa a caixa aparece sem a marcação.
Com o Radio Group você só pode escolher uma e somente uma opção entre as opções disponíveis. Com o Check Box
você pode escolher uma, todas, nenhuma, quantas opções você quiser.
Vamos usar o DBCheckBox para mostrar as preferências do cliente.. As opções são "Artigos de Luxo", "Pechinchas"
e "Utilidades". Coloque três DBCheckBoxes no Form, um para cada opção.
Lá vêm as propriedades…

Propriedade Função

Color, DataField, Já são propriedades conhecidas.


DataSource Font,
Enabled e Name

Caption É a descrição da opção que poderá ser selecionada. No check box que vai representar a opção "Artigos de
Luxo" escreva "Artigos de Luxo" no Caption. Nos outros dois escreva "Pechinchas" e "Utilidades".

AllowGrayed Uma tradução de AllowGrayed poderia ser "Permite Cinza". Esse "cinza" não é a cor, mas um estado
intermediário, nem verdadeiro e nem falso ou então verdadeiro e falso simultaneamente. Isso não é nada
esotérico e é muito útil, quando usado adequadamente. AllowGrayed=True significa que o Check Box
pode ficar no estado "cinza". Exemplo: quando você marca um bloco no Word que contém um trecho de
texto em negrito e outro trecho de texto não negrito e você abre a caixa de diálogo da Fonte, o Check Box
da opção Negrito fica cinza para indicar que a opção negrito é verdadeira e falsa para o bloco de texto
selecionado.
Tabela 11: Propriedades do Check Box

Figura 16: Check Box

H) FIM
A interface com o usuário está pronta. Não esqueça de salvar o projeto. Esse projeto ainda vai ser muito útil no futuro.
26
Outros componentes visuais
Além dos componentes que já vimos existem muitos outros. Vamos dar uma olhada superficial em alguns
componentes interessantes. Para não estragar o nosso Form crie um novo projeto.
Radio button
Radio button é muito parecido com Radio Group mas ao invés de representar um grupo de botões de rádio, o radio
button é um botão só.
Funciona assim: Você põe no Form um Radio Button para cada opção. Se você pode escolher uma entre duas opções
coloque dois Radio Buttons no Form. Serão dois componentes trabalhando em conjunto.
Radio Button não tem versão Data Aware, ou seja, não pode ser ligado ao banco de dados.

Figura 17: Radio Button

O Radio Button está na palheta de componentes, na aba Standard.

Propriedade Função

Color, Font, Já são propriedades conhecidas.


Enabled e Name

Caption É a descrição do item que poderá ser selecionado. Por exemplo: Se o Radio Button vai representar a opção
"Ativo" digite "Ativo" no Caption.

Checked Checked=True significa que esta é a opção selecionada.


Tabela 12: Propriedades do Radio Button

Observe que na prática o Radio Group e o Radio Button funcionam da mesma forma. Qual o melhor ? Aquele que
você achar mais fácil de usar. Você decide.
Bitbtn
Qualquer programa que se preze faz uso de botões. O Delphi provê botões de todos os tipos e qualidades para todos os
gostos. Um dos campeões de audiência é o BitBtn.
Bitbtn (pronuncia-se Bit Button) é um botão que pode ter uma imagem dentro. Este tipo de botão aceita foco, ou seja,
o usuário pode colocar o foco sobre ele usando a tecla Tab e pressioná-lo usando a barra de espaço.
Enquanto a barra de ferramentas é um conjunto de botões, o bitbtn é um botão isolado.
Continuamos lá na palheta de componentes, dentro da aba Additional.
27

Figura 18: Bitbtn

Vamos às propriedades.

Propriedade Função

Caption, Font, Propriedades já conhecidas.


Enabled e Name

Glyph É a imagem que vai aparecer no botão. O Delphi já tem um conjunto de imagens pré-definidas – ver
propriedade Kind – mas você pode colocar a imagem que quiser aqui, desde que seja no formato bitmap.

Kind É o tipo do botão. Cada tipo já tem valores pré-definidos para as propriedades Caption, Glyph e
ModalResult. Os tipos podem ser bkOpen, bkClose, bkOK, bkCancel, etc.

Layout Define a posição em que o Glyph vai aparecer: Esquerda, direita, acima ou abaixo do Caption.
Tabela 13: Propriedades do Bitbtn

I) IMAGE

De que vale um sistema visual se não há nada interessante para ver? Vamos colocar uma imagem nesse trem.
Procure lá na palheta de componentes, dentro da aba Additional, o componente Image. É aquele botão colorido com
cara de paisagem. Põe um componente desses no Form. Apareceu um quadrado transparente no Form, certo ?
28

Figura 19: Image

Vamos às propriedades.

Propriedade Função

Enabled e Name Propriedades já conhecidas

AutoSize Quando AutoSize=True o componente Image vai se ajustar ao tamanho da imagem. Se a imagem for
maior do que o componente então o componente aumenta. Se a imagem for menor então o componente
diminui. Quando AutoSize=False só o pedaço da imagem que couber no componente vai aparecer.
Dica: Para manter o controle sempre do mesmo tamanho e fazer a imagem caber dentro dele use a
propriedade Strech.

Center Center=True centraliza a imagem dentro do componente. Center=False posiciona o canto superior
esquerdo da imagem no canto superior esquerdo do componente. Não faz efeito quando AutoSize=True
ou Strech=True.

IncrementalDisplay Pode ser que o computador demore a desenhar muito a imagem. Isso acontece quando a imagem é
muito grande. IncrementalDisplay=True vai mostrando os resultados parciais, imagens intermediárias e
aproximadas da imagem final. IncrementalDisplay=False só mostra a imagem quando a imagem está
completamente pronta para ser mostrada.

Picture É a imagem que vai ser mostrada. Pode ser bitmap, ícone ou windows metafile (o famoso clipart).
Clique sobre a propriedade Picture. Clique sobre o botão das reticências. Clique no botão Load. Procure
a imagem que você quiser mostrar. O diretório C:\Windows costuma ter várias imagens em formato
bitmap. Selecione uma imagem e clique no botão Open. Clique no botão OK. Se a imagem não aparecer
dentro do componente, use as propriedades AutoSize ou Strech.

Strech Strech=True muda o tamanho da imagem para ficar igual ao tamanho do componente. Se o tamanho da
imagem não for proporcional ao do componente isso pode distorcer a imagem. Para mudar o tamanho
do componente sem mudar o tamanho da imagem use a propriedade AutoSize.
Tabela 14: Propriedades de Image

J) ANIMATE
29
Esse componente é animado. Ele mostra um video clip no formato AVI desde que o clip não tenha som. O próprio
Windows tem alguns vídeos – que o Delphi traz para o componente Animate automaticamente - ou você pode usar o seu AVI
favorito.
Vamos lá na palheta de componentes, dentro da aba Win32. Eu disse Win32.

Figura 20: Animate

Vamos às propriedades.

Propriedade Função

Caption, Enabled, Propriedades já conhecidas.


Font, Glyph, Lay-
out e Name

Active Active=True bota a imagem para se mexer. Active=False faz a imagem parar.

Commom AVI É uma lista com os AVIs disponíveis no Windows. aviNone não mostra vídeo nenhum. Escolha um
diferente de aviNone e coloque Active=True. Viu?

FileName É o nome do arquivo AVI. FileName e CommomAVI são propriedades mutuamente exclusivas. Ou você
escolhe um dos CommomAVI ou você escolhe um arquivo AVI através dessa propriedade. Lembre-se:
somente arquivos no formato AVI sem áudio podem ser mostrados com o componente Animate.

Repetitions Coloque aqui o número de vezes que o vídeo vai se repetir. Zero significa para sempre.
Tabela 15: Propriedades do Animate

Não precisa nem rodar o programa para ver como ficou. É só colocar a propriedade Active=True para ver o resultado.

10. OBJECT PASCAL


Object Pascal nada mais é do que o bom e velho Turbo Pascal, só que muito mais turbinado. A boa notícia é que o
Pascal agora é orientado a objeto. A notícia melhor ainda é que você não precisa saber quase nada de orientação a objeto para
trabalhar com Object Pascal. A notícia mais espetacular é que quem sabe trabalhar com alguma versão anterior do Pascal vai
aproveitar todo o conhecimento que já tem !
Embora o conhecimento de orientação a objeto não seja obrigatório, esse conhecimento é muito útil para extrair o
máximo dos recursos que o Object Pascal põe à sua disposição. Nesse curso vamos ver apenas os aspectos mais básicos da
orientação a objeto por se tratar de um tópico muito avançado.

A) UNIT
30
Como já foi dito anteriormente, a Unit é o cérebro por trás do rostinho bonito do Form. É a Unit que contém a lógica e
a memória do programa.
Para esclarecer as coisas vamos passar um Raio-X numa Unit. Vamos criar um projeto novo, colocar um componente
e um evento só para dar o "contraste".
Crie um projeto novo – ver página Projeto
Defina um evento OnCreate para o Form – ver página Formulário
Coloque um label no Form – ver página Componentes visuais
Agora vamos ver como ficou a Unit:

unit Unit1;

interface
uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs;
type
  TForm1 = class(TForm)
    Label1: TLabel;
    procedure FormCreate(Sender: TObject);
    private
      { Private declarations }
    public
      { Public declarations }
end;
var
  Form1: TForm1;

implementation
{$R *.DFM}
procedure TForm1.FormCreate(Sender: TObject);
begin
end;
end.

1) Unit - Define o nome da Unit. Tem que ser igual ao nome do arquivo *.pas. No exemplo o nome da Unit é Unit1 e o nome
do arquivo *.pas é Unit1.pas. Não mexa aqui. Se você quiser mudar o nome da Unit salve o arquivo *.pas com outro nome
usando o menu "File --> Save As…".

2) Interface - Interface é uma das seções do Object Pascal. A seção interface é uma seção declarativa. Nela são declarados
variáveis e procedimentos.

3) Uses - Lista de units que contêm variáveis e procedimentos usados pela Unit atual. No exemplo as palavras Windows,
Messages, SysUtils, etc. são nomes de units que a Unit1 usa. O próprio Delphi colocou essa lista aqui e o próprio Delphi
se encarrega de acrescentar os nomes das units necessárias à medida em que você vai colocando componentes no Form.
Você também pode incluir units na lista. Por exemplo: Quando um FormA usa o FormB, você deve colocar na cláusula
Uses do FormA o nome da Unit do FormB. Até agora todos os exemplos que vimos são projetos com um único Form. Por
esse motivo ainda não usamos a cláusula Uses.

4) "Type TForm1 = Class(Form)" - O significado dessa instrução quase cabalística é muito simples. Em linguagem de
gente essa instrução quer dizer: "Sr. Pascal, por favor eu quero definir um novo tipo de Form. O nome do novo tipo de
Form será TForm1. Este novo tipo de Form terá as mesmas características que todos os Forms têm e mais algumas
características próprias. Essas características próprias serão descritas entre o Type e o primeiro end.". Não mexa nessa
instrução. Para mudar o nome do Form use a propriedade Name no Object Inspector.

5) Características do Form - A região abaixo do "Type TForm1 = Class(Form)" e acima do "private" é onde o Delphi
coloca as definições de componentes e eventos usados pelo Form. No exemplo podemos ver o label declarado em "Label1:
TLabel;" e o evento OnCreate declarado em "procedure FormCreate(Sender: TObject);". Deixe que o Delphi administre
essa região. Não exclua nenhum componente ou evento à mão. Se precisar excluir um componente, retire-o do Form. O
Delphi vai apagar a declaração do componente automaticamente. Se quiser excluir um evento apague as linhas de
comando dentro da procedure e o Delphi faz o resto.

6) Private e public - Finalmente o Delphi deixou um lugarzinho onde você vai poder mexer. Coloque na região Private as
declarações de variáveis e procedimentos que só podem ser vistos dentro da própria Unit. Coloque na região Public as
31
declarações de variáveis e procedimentos que poderão ser vistos em qualquer Unit que declare a Unit atual na sua cláusula
Uses. Um projeto pode ter mais de um Form. Se o FormA declarar em sua cláusula Uses o FormB então o FormA vai
poder usar tudo o que está na região Public do FormB mas não vai poder usar nada que estiver declarado na região Private.

7) Var Form1: TForm1 - Mais uma instrução que não tem nada de misteriosa. Isso aqui quer dizer: "Sr. Pascal, lembra da
definição do novo tipo de Form chamado TForm1 ? Pois bem, agora eu quero declarar aqui um Form com nome de Form1
do tipo TForm1." Complicou ? Esclarecerei. Da mesma forma que a planta da casa não é a casa o TForm1 não é um
Form. TForm1 é um mapa, um plano para a construção de um Form. O Form de verdade, aquele que será criado e vai
aparecer para o usuário, é o Form1 (sem o T).

8) Implementation - Dentro da seção Implementation são definidos os procedimentos que foram declarados na seção
Interface.

9) {$R *.DFM} - Esse comando faz a ligação entre a unit Unit1 e o Form que está em Unit1.dfm. Não mexa.

10) Procedure - Lembra do evento OnCreate ? Lembra que um procedimento foi declarado na seção Interface, dentro do
TForm1, para tratar esse evento ? Pois bem. Estamos agora na seção Implementation. O procedimento que foi declarado
na Interface deve ser definido na Implementation. No nosso exemplo o procedimento FormCreate não faz absolutamente
nada. Só tem o begin e o end. (No futuro vamos ver o que fazer entre o begin e o end.)

11) END - Toda unit deve terminar com o comando end seguido de um ponto-final. Nada pode ser colocado após o end com
ponto-final.

11. TIPOS DE DADOS


Todo programa, Object Pascal ou não, processa dados (ou não seria um programa). Alguns dados são constantes,
outros são variáveis. Alguns representam datas, outros representam quantidades, outros ainda representam textos. Constantes,
variáveis e tipos de dados são o meio apropriado para definir dados que o programa vai processar.
Variáveis
Variáveis são identificadores que simbolizam dados que podem ser alterados durante o processamento. São usadas
para guardar dados temporariamente.
As variáveis precisam ser declaradas antes de serem usadas. Existem muitos lugares dentro da Unit onde uma variável
pode ser declarada. O lugar onde a variável é declarada tem grande influência sobre a sua "visibilidade". Uma variável é
visível quando pode ser usada por uma procedure ou função.

interface. . .

  private     { Private declarations }


      bytUmByteNaAreaPrivada: byte;

  public     { Public declarations }


      intNumeroInteiro: integer;
      dblNumeroFlutuante: double;
      booVerdadeiroFalso: boolean;
      strStringCurto: string[50];
      strStringLongo: string;
end;

var
  Form1: TForm1;
  strStringNaInterface: string[1];

implementation
{$R *.DFM}

procedure TForm1.FormCreate(Sender: TObject);


var
  intInteiroNaProcedure: integer;
begin
end;
...
As variáveis declaradas na região private de um Form são visíveis somente pelas procedures e functions do próprio
Form.
32
As variáveis declaradas na região public de um Form são visíveis por todas as procedures e functions do próprio
Form. Também são visíveis por procedures e functions de outra Unit que tenha declarado esta Unit em sua cláusula Uses.
As variáveis declaradas na seção interface (3) são visíveis por todas as procedures e functions da Unit. Também são
visíveis por procedures e functions de outra Unit que tenha declarado esta Unit em sua cláusula Uses.
As variáveis declaradas dentro de uma procedure ou function (4) só são visíveis pela própria procedure ou function.
São conhecidas como variáveis locais. Quando a procedure/function é chamada a variável é criada. Quando a
procedure/function termina a variável é destruída.
Observe que a palavra reservada var não é permitida das regiões private e public mas é obrigatória na seção
interface e na procedure.

 Tipos de Dados

Pascal é uma linguagem famosa por sua forte "tipagem" de dados. Toda variável precisa ser declarada e na declaração
da variável é definido um tipo de dado fixo.
O tipo de dado indica se a variável vai conter um valor numérico ou uma data ou um texto, etc. Existem muitos tipos
de dados. Vamos ver somente os tipos mais comuns.
Existe um tipo de dado "variant", mas isso já é outra história…

Tipo de Dado Valores permitidos

SmallInt Número inteiro -32768 a +32767

Integer Número inteiro -2147483648 a +2147483647

ShortInt Número inteiro -128 a +127

Byte Número inteiro 0 a 255

Single Número com ponto flutuante 1.5 x 10^-45 a 3.4 x 10^38

Double Número com ponto flutuante 5.0 x 10^-324 a 1.7 x 10^308

String[???] String de caracteres String curto. O número de caracteres é declarado entre colchetes.
Tamanho máximo de 255 caracteres

String String de caracteres String longo limitado apenas pela memória disponível

Boolean Valores booleanos Verdadeiro ou Falso

TDateTime Data e hora Data e hora


Tabela 16: Tipos de Dados

Existem muitos outros tipos de dados. Para consultar uma lista mais completa veja a documentação ou a ajuda on-line
do Delphi.

A) CONSTANTES
Ao contrário das variáveis, as constantes podem ou não ser declaradas. As constantes não declaradas são expressões
constantes. As constantes declaradas podem ser tipadas - têm um tipo de dado explicitamente declarado - ou não tipadas – o
tipo de dado fica implícito.
Expressões constantes
Uma expressão constante é qualquer valor usado por um programa que não pode ser alterado. Exemplos de expressões
constantes:
132
‘Pascal é legal !’
2+2

B) CONSTANTES TIPADAS
33
As constantes tipadas têm um tipo de dado – integer, string, etc. -, por isso se chamam "tipadas". Funcionam como
variáveis "read only" com um valor inicial. O valor de uma constante tipada é inicializado na própria declaração e não pode ser
alterado pelo programa.

...
interface
...
var
   Form1: TForm1;
   strStringNaInterface: string[1];

const
   cStrConstTipadaNaInterface: string = 'Valor Inicial';

implementation

{$R *.DFM}

procedure TForm1.FormCreate(Sender: TObject);


const
   cIntConstTipadaNaProcedure: integer = 0;
var
   intInteiroNaProcedure: integer;
begin

end;

Constante declarada na seção Interface


Constante declarada dentro da procedure
Constantes não podem ser declaradas nas regiões Private ou Public.
Por motivo de compatibilidade com o Delphi 1.0 o valor das constantes tipadas PODE ser modificado !
Existe uma opção chamada "Assignable Typed Constants" em Project Options que, se estiver marcada, faz com que as
constantes tipadas possam ser modificadas.
Clique no menu "Project  Options", veja na aba Compiler. Se esta opção estiver marcada, desmarque-a.
Constantes não tipadas
As constantes não tipadas não têm nenhum tipo de dados associado a elas. São apenas um nome para um expressão
constante.
À primeira vista parece não ter utilidade nenhuma. Nada mais errado. É muito comum uma expressão constante ser
usada várias vezes dentro de um programa. Quando essa expressão constante precisa ser mudada … Pobre programador. Vai
ter procurar no programa inteiro onde aquela expressão constante se repete para alterá-la.
Um programador prevenido declara a expressão constante como constante não tipada e depois, quando necessário, só
precisa alterar a declaração da constante e recompilar o programa.

const
   cStrConstNaoTipadaTexto = 'Valor Inicial';
   cIntConstNaoTipadaNumero = 12.34;

Uma constante não tipada pode ser declarada onde quer que uma constante tipada também possa.

12. DADOS ESTRUTURADOS


34
Já vimos alguns tipos de dados usados para definir variáveis e constantes. Cada variável vista até aqui é capaz de
guardar um único valor de um único tipo de dado. Com tipos de dados estruturados você vai quebrar essa barreira.

A) ARRAY ESTÁTICO
Com arrays você pode criar uma variável que é capaz de conter mais de um valor simultaneamente.

var
   arrIntDezNumeros: array[1..10] of double;
   arrStr120Nomes: array[1..12, 1..10] of string;

const
   arrIntDigitos: array[0..9]
      of integer = (0, 1, 2, 3, 4, 5, 6, 7, 8, 9);

Observe:
Onde quer que você possa declarar uma variável, você pode declarar uma variável do tipo array.
Onde quer que você possa declarar uma constante, você pode declarar uma constante do tipo array.
O tamanho do array é definido pelo intervalo entre colchetes após a palavra reservada array. Ex.: O intervalo [1..20]
indica que o array pode conter 20 valores.
O tipo de dado do array é definido pelo tipo de dado declarado após a palavra reservada of. Todos os valores de um
array têm o mesmo tipo de dado.
Para inicializar uma constante do tipo array você precisa declarar uma lista de expressões constantes com o mesmo
número de valores e do mesmo tipo de dado que a constante representa. No exemplo, a constante arrIntDigitos representa dez
valores (do zero ao nove) do tipo integer, consequentemente a lista de expressões constantes deve ter dez valores inteiros.
Um array pode ter mais de uma dimensão, ou seja, pode ser um array de arrays. No exemplo, o array arrStr120Nomes
é capaz de guardar dez arrays (1..10) compostos por doze arrays (1..12) cada um. Por isso o arrStr120Nomes é capaz de
guardar 120 nomes (10 X 12).
Provavelmente você deve estar se perguntando: "Ué ? Se uma variável array guarda mais de um valor, como é que eu
vou pegar um valor específico dessa variável ?"
Fácil. Existe uma coisa chamada índice. É o índice que determina qual dos valores do array você vai obter. Na
declaração do array são informados os valores mínimo e máximo do índice na cláusula que fica entre conchetes.
No array arrIntDezNumeros está declarado [1..10] logo o índice pode valer de 1 a 10.
ArrIntDezNumeros[1] é o primeiro valor do array
ArrIntDezNumeros[2] é o segundo valor do array … e assim por diante até chegar ao índice 10.
Lembre-se: Tudo é relativo. Um outro array pode declarar para o índice outros valores como mínimo e máximo.

B) ARRAY DINÂMICO
Arrays dinâmicos funcionam do mesmo modo que os arrays estáticos. A diferença é que o array estático tem um
tamanho pré-definido e o array dinâmico pode mudar de tamanho.
arrIntDinamicoNumeros: array of double;
Na declaração dos arrays dinâmicos não são informados os valores mínimo e máximo do índice (não tem aquela
cláusula entre colchetes, por exemplo [1..10]).
O tamanho do array dinâmico é definido e alterado em tempo de execução com o comando SetLength. Com esse
comando o array pode ser aumentado ou diminuido sem prejudicar os valores contidos no array. Para que o array seja capaz de
guardar dez valores faça:
SetLength(arrIntDinamicoNumeros, 10);
Um array dinâmico é sempre indexado a partir de zero. Por exemplo, um array com 10 valores é indexado de 0 a 9,
como se tivesse a cláusula [0..9] na declaração.
Arrays dinâmicos também podem ser multidimensionais. Observe a declaração:
arrStrDinamicoNomes: array of array of string;
A declaração "array of array of …" não é erro de tipografia. Isso diz ao Pascal que você quer um array de arrays.
A definição do tamanho de um array dinâmico multidimensional é bastante flexível. Você pode definir o tamanho de
todas as dimensões simultaneamente ou definir uma dimensão primeiro e outra depois.
SetLength(arrStrDinamicoNomes, 3);
SetLength(arrStrDinamicoNomes[0], 5);
SetLength(arrStrDinamicoNomes[1], 8);
35
SetLength(arrStrDinamicoNomes, 10, 12);

O primeiro SetLength diz que o array tem três linhas e nenhuma coluna.
O segundo diz que a primeira linha tem 5 colunas.
O terceiro diz que a segunda linha tem 8 colunas.
O último diz que o array tem 10 linhas e 12 colunas.
Tentar acessar um valor de um array dinâmico antes de atribuir o tamanho com o comando SetLength provoca uma
mensagem de erro "Access Violation".

C) RECORD
Com records você pode criar uma variável que contém outras variáveis.

...
// Declaração (1)
type
   TEndereco = record
      strLogradouro: string;
      strComplemento: string;
      strCidade: string;
      strEstado: string;
      intCep: integer;
end;
...

// Declaração (2)
var
   recEnderecoComercial: TEndereco;
   recEnderecoResidencial: TEndereco;
...
 
procedure TForm1.FormCreate(Sender: TObject);

// Declaração (3)
   type
      TTelefone = record
         strPrefixo: string[4];
         strNumero: string[9];
         strRamal: string[5];
   end;

// Declaração (4)
   const
   recMeuTelefone: TTelefone =
      (strPrefixo: '041';
       strNumero: '334-3434';
       strRamal: '222');
...

No exemplo, você pode ver duas declarações diferentes. A declaração type (1) que define um tipo de dado record e a
declaração var (2) que define uma variável do tipo declarado.
A declaração type também pode ser usada dentro de uma procedure (3).
Uma constante tipada pode usar um record como tipo de dados (4).
Se o Pascal fosse gente, você diria assim:

 Declaração (1) - "Sr. Pascal, tenho aqui em minhas mãos um grupo de informações afins: logradouro, cidade,
cep, etc. Essas informações agrupadas formam um endereço."

 Declaração (2) - "Sr. Pascal, preciso guardar informações sobre dois endereços diferentes, um comercial e outro
residencial. Endereço, como o sr. já sabe, foi definido previamente."
36
 Declaração (3) - "Sr. Pascal, tenho outro grupo de informações que gostaria de agrupar: prefixo, número do
telefone e ramal. Esse agrupamento, sr. Pascal, é válido somente dentro desta procedure."

 Declaração (4) - "Sr. Pascal, o número do meu telefone é prefixo 041, número 334-3434, ramal 222. Ao término
dessa procedure, esqueça o meu número."

Só isso. Simples, não ?


E como fazer para pegar o valor de uma variável que está dentro do record ? Faça assim: nome da variável record +
um ponto + o nome da variável básica, tudo junto, sem espaço.
No exemplo, recEnderecoComercial é o nome da variável que contém um grupo de dados de endereço (logradouro,
complemento, etc.). Para pegar o CEP faça assim:

recEnderecoComercial.intCep

Com os records é possível montar estruturas de dados bastante complexas. Só para dar uma idéia da complexidade
saiba que um record pode conter outro record sucessivamente.

type
   TPrimeiro = record
      a: string;
      b: string;
      c: string;
end;
type
   TSegundo = record
      x: TPrimeiro;
      y: TPrimeiro;
      z: TPrimeiro;
end;
type
   TTerceiro = record
      i: TSegundo;
      j: TSegundo;
      k: TSegundo;
end;
var
   recTudo: TTerceiro;

A variável recTudo é do tipo TTerceiro. O tipo de dado TTerceiro contém três variáveis do tipo TSegundo. As
variáveis do tipo TSegundo contêm três variáveis do tipo TPrimeiro. As variáveis do tipo TPrimeiro contêm três variáveis do
tipo string.
Essa estrutura contém (1 x 3 x 3 x 3) = 27 strings. Para obter um string específico faça:

recTudo.i.x.a
recTudo.i.x.b
...
recTudo.k.y.c

. . . e assim sucessivamente.

D) SET
Set é uma estrutura de dados que permite guardar uma coleção de valores.

// Declaração (1)
type
   setPedraDeBingo = set of 0..99;
...
// Declaração (2)
var
   binCartela: setPedraDeBingo;
   abcMultiplaEscolha: set of ‘a’...‘e’;
37
...
// Declaração (3)
   binCartela := [14, 22, 35, 43, 87];
   abcMultiplaEscolha := [‘b’, ‘c’, ‘d’];

 Declaração (1) - Primeiro você declara o conjunto de valores permitidos como um tipo de dado. No exemplo, o
conjunto de valores para setPedraDeBingo é de 0 a 99. Uma alternativa é declarar o conjunto de valores na
própria declaração da variável, como em abcMultiplaEscolha (2).

 Declaração (2) - Depois você declara uma variável do tipo conjunto, declarado anteriormente.

 Declaração (3) - Por último você pode atribuir um sub-conjunto de valores à variável.
 
 

13. PROCEDIMENTOS E FUNÇÕES


Agora sim, vamos começar a programar de verdade. Até aqui vimos o ambiente, fizemos design, estudamos teorias…
Tudo muito bom, tudo muito bonito, mas … cadê a programação ? A programação está aqui: Procedures e functions.
Procedures e functions são blocos de comandos. Dentro desses blocos você vai escrever o seu programa. A idéia
básica é bem antiga: "Dividir para conquistar". Ao invés de escrever um programão monolítico, você divide o programão em
pequenas rotinas mais simples.
Procedures
Nós já vimos a criação de procedures quando estudamos eventos. Quando damos um duplo-clique em um evento do
Form ou de algum componente o Delphi automaticamente declara uma procedure. Dentro dessa procedure você escreve os
comandos que serão executados quando o evento ocorrer.
O que o Delphi faz automaticamente você pode fazer manualmente. Não é tão ruim quanto parece.
Tal qual as variáveis, as procedures também precisam ser declaradas. Na verdade as procedures precisam de duas
declarações: uma na seção interface e outra na seção implementation.
Na seção interface é declarado um header que vai indicar o nome, os parâmetros e a visibilidade da procedure.
Na seção implementation ficam os comandos que vão compor a procedure propriamente dita.
Declaração na Seção Interface

...
interface
...
type
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
procedure MinhaProcedurePrivate(strMeuParametro: string; var intMeuParametro: integer);
procedure MinhaProcedureSemParametro;

public
{ Public declarations }
procedure MinhaProcedurePublic(intOutroParametro: integer);
end;

var
Form1: TForm1;

procedure MinhaProcedureNaInterface(strUmParametro: string);

implementation

{$R *.DFM}

...
38
Onde quer que uma variável possa ser declarada, uma procedure também pode. A única restrição é que, dentro de uma
região, as variáveis têm que ser declaradas primeiro e as procedures depois. As regras sobre visibilidade também são as
mesmas.
As procedures que tratam eventos são declaradas pelo próprio Delphi na região acima da Private.
Procedures privadas do Form criadas por você devem ser declaradas na região Private.
Procedures públicas do Form criadas por você devem ser declaradas na região Public.
Procedures podem ser declaradas diretamente na seção interface, fora da declaração do Form.
Uma declaração de procedure tem os seguintes elementos:

Elemento Descrição Exemplo

procedure Palavra reservada obrigatória procedure

Nome Nome que vai identificar a procedure. MinhaProcedurePrivate

Lista de parâmetros Lista de parâmetros é uma lista de variáveis que serão (strMeuParametro: string;
intercambiadas entre a procedure que está sendo declarada e a var intMeuParametro: integer)
rotina que a chamou. Cada parâmetro tem um tipo de dado. A
lista de parâmetros é opcional (uma procedure pode não
precisar de parâmetro nenhum).
Tabela 17: Elementos da declaração de procedure

Existem quatro formas de intercâmbio de parâmetros:

 Valor: É a forma default. O valor do parâmetro é passado da rotina que chamou para a procedure que é chamada.
O parâmetro pode ser usado como uma variável local dentro da procedure. Se a procedure alterar o valor da
variável o novo valor NÃO vai alterar o valor da variável na rotina que chamou.

 Variável: É declarada pela palavra reservada var. O valor do parâmetro é passado da rotina que chamou para a
procedure que é chamada. O parâmetro pode ser usado como uma variável local dentro da procedure. Se a
procedure alterar o valor da variável o novo valor VAI alterar o valor da variável na rotina que chamou.

 Constante: É declarada pela palavra reservada const. O valor do parâmetro é passado da rotina que chamou para
a procedure que é chamada. O parâmetro NÃO pode ser usado como uma variável local dentro da procedure. A
procedure NÃO pode alterar o valor da constante.

 Saída: É declarada pela palavra reservada out. O valor do parâmetro é desprezado pela procedure que é chamada.
O parâmetro pode ser usado como uma variável local dentro da procedure. Se a procedure alterar o valor da
variável o novo valor VAI alterar o valor da variável na rotina que chamou.

No exemplo, o parâmetro strMeuParametro é passado por valor e o parâmetro intMeuParametro é variável.


Podem ser declarados valores default para os parâmetros.

procedure MinhaProcedureComDefault(dblParmSemDefault: double;


strMeuParm: string = ‘Um string default’;
intOutroParm: integer = 99);

Quando uma procedure é chamada, os parâmetros que aceitam default podem ser omitidos. Os valores informados no
header serão atribuídos aos parâmetros omitidos.
Em uma lista de parâmetros, os parâmetros que não têm valores default devem sempre vir antes dos parâmetros com
valores default. No exemplo, o parâmetro dblParmSemDefault – que não tem valor default – é declarado antes dos outros
parâmetros.
Declaração na Seção Implementation

...
implementation
{$R *.DFM}
procedure TForm1.FormCreate(Sender: TObject);
begin

end;
39
procedure TForm1.MinhaProcedurePrivate(strMeuParametro: string;
var intMeuParametro: integer);
begin

end;
...

procedure MinhaProcedureNaInterface(strUmParametro: string);


begin

end;

end.

Na seção implementation é que a procedure ganha corpo. O header é redeclarado e logo abaixo do header aparece o
bloco de comandos (begin e end).
Observe que o header das procedures declaradas dentro do Form (dentro da declaração type) ganha uma cláusula para
indicar que pertence ao Form:
procedure TForm1.MinhaProcedurePrivate
As procedures declaradas diretamente na seção interface não têm essa cláusula.
Pergunta: "Vamos botar o quê entre o begin e o end ? Cadê o recheio ?". Calma. Os comandos para rechear o bloco de
comandos vão ser explicados mais à frente.
Chamando uma Procedure

...
implementation

{$R *.DFM}

procedure TForm1.FormCreate(Sender: TObject);


var
intVariavelLocal: integer;
begin

MinhaProcedurePrivate(‘Um texto qualquer’, intVariavelLocal);

end;

...

Ao chamar uma procedure, os parâmetros têm que ser em igual número, tipo de dado e ordem aos declarados no
"header", salvo em caso da procedure aceitar valores default como parâmetros.
No exemplo, a procedure MinhaProcedurePrivada tem dois parâmetros, o primeiro é do tipo string, o segundo é do
tipo integer e não pode ser constante (no "header" o segundo parâmetro foi declarado como var).
Functions
Tudo o que foi dito sobre procedures vale também para functions. Functions têm que ser declaradas na interface e na
implementation; functions podem ter parâmetros; as formas de intercâmbio de parâmetros são as mesmas; tudo igual às
procedures.
Basicamente functions são procedures que retornam um valor. Só isso. Mas esse pequeno detalhe faz uma grande
diferença. Além de fazer tudo o que uma procedure faz, uma function pode ser usada como se fosse uma variável read-only.
Declaração na Seção Interface

...

function MinhaFunction(intOutroParametro: integer): double;


...

Observe as diferenças:
Palavra reservada function no lugar de procedure.
40
Declaração do tipo de dado da function (ex.: double). Para retornar um valor, a função precisa declarar que tipo de
dado tem esse valor.
Declaração na Seção Implementation

function TForm1.MinhaFunction(intOutroParametro: integer): double;


begin

end;

As diferenças são as mesmas da declaração do header na seção interface.


Chamando uma Function

...
procedure TForm1.FormCreate(Sender: TObject);
var
intVariavelLocal: integer;
dblVariavelDouble: double;
begin
dblVariavelLocal := MinhaFunction(intVariavelLocal);

MinhaFunction(intVariavelLocal);
end;
...

O valor resultante de uma function pode ser usado como se fosse uma variável read-only (primeira linha) ou pode ser
descartado (segunda linha).

14. MANIPULAÇÃO DE STRINGS


Já vimos que string é um tipo de dado. Mas não é um tipo de dado qualquer. É o mais importante porque é o mais
"humano" dos tipos de dados. Não importa como o dado é armazenado internamente. Na hora de mostrar o dado ao usuário
humano o programa vai ter que converter o dado em um formato que nós, mortais, possamos entender. Os principais formatos
em que o computador costuma apresentar informações aos humanos são o formato gráfico – cores, formas, botões, etc. – e o
formato texto – string, para os íntimos.

A) ATRIBUIÇÃO
Atribuição é a mesma coisa que copiar um string – variável ou constante – para uma variável qualquer do mesmo tipo.
Label1.Caption := ‘Hello, World’;
Caption é uma propriedade do componente Label1, conforme vimos em Componentes visuais.
O sinal := é o comando de atribuição. O pessoal que não está acostumado com Pascal acha estranho esse símbolo, mas
é assim mesmo: dois-pontos seguido de sinal de igual sem espaço entre eles.
‘Hello, World’ é o string que está sendo atribuído ao Caption. No exemplo estamos usando uma expressão constante
mas é permitido o uso de quaisquer variáveis e constantes do tipo string.
Após a execução desse comando o Label1 vai mostrar o string ‘Hello, World’.
Esse exemplo também mostra que as propriedades dos componentes do Form podem ser mudadas em tempo de
execução.

B) CONCATENAÇÃO
Concatenação é a ligação de dois ou mais strings.

...
var
strNome: string;
begin
strNome := ‘Antônio Maria’;
Label1.Caption := ‘Bom dia, Sr. ’ + strNome;
end;
...
41
O sinal de adição (+) usado entre duas strings faz a concatenação.
No exemplo, o label vai mostrar: "Bom dia, Sr. Antônio Maria".

C) CARACTER DE CONTROLE
Os caracteres de controle são expressões constantes do tipo string compostas pelo símbolo # seguido de um número
inteiro de 0 a 255. O número corresponde à tabela ASCII.

...
var
strNome: string;
begin
strNome := ‘Antônio Maria’;
Label1.Caption := ‘Bom dia, Sr. ’ + strNome +
#13#10‘Como vai a sua tia ?’;
end;
...

#13 é o caracter de controle para carriage-return.


#10 é o caracter de controle para line-feed.
Para concatenar um caracter de controle a uma expressão constante é só encostar um no outro sem nenhum espaço em
branco no meio. Note que para concatenar uma variável a um caracter de controle é preciso usar o sinal de concatenação +.
No exemplo, o label vai mostrar: "Bom dia, Sr. Antônio Maria" em uma linha e "Como vai a sua tia ?" na linha de
baixo.

D) FUNÇÕES
Existe uma infinidade de funções para manipulação de strings em Delphi. Vamos ver o funcionamento das mais
comuns.

1 - INTTOSTR
IntToStr converte um número inteiro em string.

...
var
intNumero: integer;
begin

intNumero := 1234;

Label1.Caption := ‘O número é ’ + IntToStr(intNumero);

end;
...

A propriedade Caption é uma variável do tipo string. Não é possível atribuir um número inteiro diretamente a uma
variável string. É preciso primeiro fazer a conversão.

2 - STRTOINTDEF
StrToIntDef converte um string em número inteiro.

...
var
   intNumero: integer;
begin
intNumero := StrToIntDef(‘1234’, 222);
Label1.Caption := ‘O número é ’ + IntToStr(intNumero);
intNumero := StrToIntDef(‘Isso não é número!’, 333);
Label2.Caption := ‘O número é ’ + IntToStr(intNumero);
42
end;
...

Caso o string não contenha um número válido a função retorna o valor default (o segundo parâmetro da função). O
Label1 vai mostrar a mensagem: "O número é 1234". Já o Label 2 vai mostrar a mensagem: "O número é 333" porque o string
passado para a função não é um número, daí a função vai retornar o valor default 333.

3 - FORMATFLOAT
FormatFloat converte um número de ponto flutuante em string.

...
var
dblNumero: double;
begin
dblNumero:= 1234.567;
Label1.Caption := ‘O número é ’ +
FormatFloat(‘###,##0.0000’, dblNumero);
end;
...

A função FormatFloat recebe dois parâmetros. O primeiro funciona como uma máscara de edição e o segundo é o
valor que se deseja converter.
A máscara de edição é composta por caracteres que especificam o formato:

Caracter Descrição

# Suprime dígitos não significativos (zeros à esquerda)

0 (zero) Não suprime os zeros, mesmo que os zeros não sejam significativos.

, (vírgula) Separador de milhares. Na hora da formatação o Delphi substitui a vírgula pelo caracter de separação
definido na variável de ambiente ThousandSeparator.

. (ponto) Separador de casas decimais. Na hora da formatação o Delphi substitui o ponto pelo caracter de separação
definido na variável de ambiente DecimalSeparator.
Tabela 18: Caracteres da máscara de edição

4 - STRTOFLOAT
StrToFloat converte um string em um número de ponto flutuante.

...
var
dblNumero: double;
strString: string;
begin
strString := ‘1234,567’;
dblNumero := StrToFloat(strString);
Label1.Caption := ‘O número é ’ + FormatFloat(‘###,##0.0000’, dblNumero);
end;
...

O string passado como parâmetro deve conter somente números, um sinal + ou – opcional e um ponto decimal
também opcional.
Na máscara de edição da função FormatFloat o ponto decimal é necessáriamente um ponto e o separador de milhares
tem que ser uma vírgula.
Na função StrToFloat, o ponto decimal da string tem que ser o mesmo sinal configurado na variável de ambiente
DecimalSeparator.
No exemplo, se DecimalSeparator for uma vírgula tudo vai funcionar. Se o DecimalSeparator estiver configurado
como ponto ou outro sinal qualquer vai aparecer uma mensagem de erro em tempo de execução.
43

5 - UPPERCASE E LOWERCASE
UpperCase converte o string para letras maiúsculas e LowerCase converte o string para letras minúsculas.

...
var
strNome: string;
begin
strNome := ‘Antônio Maria’;
Label1.Caption := ‘Bom dia, Sr. ’ + UpperCase(strNome);
Label2.Caption := ‘Bom dia, Sr. ’ + LowerCase(strNome);
end;
...

O label1 vai mostrar o nome em letras maiúsculas: "Bom dia, Sr. ANTôNIO MARIA".
O label2 vai mostrar o nome em letras minúsculas: "Bom dia, Sr. antônio maria".
Nem tudo é perfeito. As duas funções têm sérios problemas com caracteres internacionais (letras acentuadas, por
exemplo), muito comuns na língua portuguesa.

6 - STRTODATE E DATETOSTR
StrToDate converte um string em data e DateToStr converte uma data em string.

...
var
strString: string;
datUmaData: TdateTime;
begin
Label1.Caption := ‘Hoje é dia ’ + DateToStr(Date);
datUmaData := StrToDate(‘13/08/1998’);
Label2.Caption := ‘Hoje é dia ’ + DateToStr(datUmaData);
end;
...

O label1 vai mostrar a data corrente, retornada pela função Date. Qualquer variável do tipo TDateTime pode ser
passada para a função DateToStr.
O label2 vai mostrar o dia 13/08/1998.

7 - STRTOTIME E TIMETOSTR
StrToTime converte um string em hora e TimeToStr converte uma hora em string.

...
var
strString: string;
datUmaData: TdateTime;
begin
Label1.Caption := ‘Hora:’ + TimeToStr(Now);
datUmaData := StrToTime(’12:30’);
Label2.Caption := ‘Hora informada: ’ + TimeToStr(datUmaData);
end;
...

O label1 vai mostrar a hora atual, retornada pela função Now. Qualquer variável do tipo TDateTime pode ser passada
para a função TimeToStr.
O label2 vai mostrar a hora 12:30:00.

8 - POS
44
Pos é uma função que retorna a posição de um substring dentro de um string.

...
var
strNome: string;
intPosicao: integer;
begin
strNome := ‘Antônio Maria’;
intPosicao := Pos(‘Maria’, strNome);
Label1.Caption := ‘O nome contém Maria na posição ’ + IntToStr(intPosicao));
end;
...

No exemplo, o nome "Antônio Maria" contém o substring "Maria" a partir do 9° caracter.

...
intPosicao := Pos(‘Manoel’, strNome);
...

Nesse outro exemplo, a função Pos vai retornar zero porque o substring "Manoel" não está contido no nome.

9 - COPY
A função Copy copia um substring de um string
...

var
strNome, strPrimeiroNome: string;
intPosicao: integer;
begin
strNome := ‘Antônio Maria’;
intPosicao := Pos(‘ ’, strNome);
strPrimeiroNome := Copy(strNome, 1, intPosicao);
Label1.Caption := ‘Bom dia, sr. ’ + strPrimeiroNome;
end;
...

No exemplo, a função Pos procura o primeiro espaço em branco (que indica o fim do primeiro nome). Depois a
função Copy copia o substring que está entre a posição 1 e a posição do espaço em branco.
Não é por acaso que entre o primeiro caracter e o espaço em branco está o nome "Antônio" sem o "Maria".

10 - LENGTH
A função Length retorna o tamanho de um string.

...
var
strNome: string;
intTamanho: integer;
begin
strNome := ‘Antônio Maria’;
intTamanho := Length(strNome);
Label1.Caption := ‘O tamanho do nome é ’ + IntToStr(intTamanho);
end;
...

Com isso você vai descobrir que o nome "Antônio Maria" tem treze letras. Acredite: Isso tem mais utilidade do que
parece.
45
11 - BOTANDO A MÃO NA MASSA
Vamos retomar aquele projeto Pcliente.dpr de Componentes visuais.
Você vai ter duas tarefas: A primeira é inicializar as variáveis de ambiente, a segunda é ativar o relógio da barra de
status do Form (você preparou um cantinho na barra de status para mostrar a hora, lembra ?)
Inicializar Variáveis de Ambiente
Você ainda não foi apresentado a elas, mas vai ser. As variáveis de ambiente são variáveis pré-definidas pelo próprio
Delphi para configurar formato de data, hora, valores monetários, nomes dos dias da semana, etc. A inicialização das variáveis
de ambiente não é obrigatória. O Delphi vai buscar no Windows os valores default para elas. Alguns programadores mais
precavidos preferem inicializar essas variáveis para evitar surpresas, caso o Windows onde o programa vai rodar não esteja
configurado adequadamente.
Abra o projeto Pcliente.dpr
Crie um evento OnCreate no form
Dentro da procedure FormCreate inclua os seguintes comandos:

...
procedure TfrmCliente.FormCreate(Sender: TObject);
begin
ThousandSeparator := '.'; // Separador de milhares
DecimalSeparator := ','; // Ponto decimal
ShortDateFormat := 'dd/mm/yyyy'; // Formato de data
DateSeparator := '/'; // Separador de data
TimeSeparator := ':'; // Separador de hora

// Nome abreviado para os meses


ShortMonthNames[1] := 'Jan';
ShortMonthNames[2] := 'Fev';
ShortMonthNames[3] := 'Mar';
ShortMonthNames[4] := 'Abr';
ShortMonthNames[5] := 'Mai';
ShortMonthNames[6] := 'Jun';
ShortMonthNames[7] := 'Jul';
ShortMonthNames[8] := 'Ago';
ShortMonthNames[9] := 'Set';
ShortMonthNames[10] := 'Out';
ShortMonthNames[11] := 'Nov';
ShortMonthNames[12] := 'Dez';

// Nome dos meses por extenso


LongMonthNames[1] := 'Janeiro';
LongMonthNames[2] := 'Fevereiro';
LongMonthNames[3] := 'Março';
LongMonthNames[4] := 'Abril';
LongMonthNames[5] := 'Maio';
LongMonthNames[6] := 'Junho';
LongMonthNames[7] := 'Julho';
LongMonthNames[8] := 'Agosto';
LongMonthNames[9] := 'Setembro';
LongMonthNames[10] := 'Outubro';
LongMonthNames[11] := 'Novembro';
LongMonthNames[12] := 'Dezembro';

// Nome abreviado dos dias da semana


ShortDayNames[1] := 'Dom';
ShortDayNames[2] := 'Seg';
ShortDayNames[3] := 'Ter';
ShortDayNames[4] := 'Qua';
ShortDayNames[5] := 'Qui';
ShortDayNames[6] := 'Sex';
ShortDayNames[7] := 'Sáb';

// Nome longo dos dias da semana


LongDayNames[1] := 'Domingo';
LongDayNames[2] := 'Segunda';
46
LongDayNames[3] := 'Terça';
LongDayNames[4] := 'Quarta';
LongDayNames[5] := 'Quinta';
LongDayNames[6] := 'Sexta';
LongDayNames[7] := 'Sábado';

// Valores Monetários

CurrencyString := 'R$'; // Símbolo de valor monetário


CurrencyFormat := 0; // Formato para valor positivo
// (0 = "R$1,00")
NegCurrFormat := 2; // Formato de valor negativo
// (2 = "R$-1,00")
CurrencyDecimals := 2; // Número de casas decimais

end;
...

Ativar Relógio na Barra de Status


Para fazer funcionar o relógio vamos precisar de um componente Timer.
Procure na palheta de componentes, na aba System, o componente Timer
Coloque um componente Timer no Form
Altere a propriedade Interval para 60000 (o intervalo é medido em milissegundos, logo, 60000 significa um minuto)
Mude para a aba Events do Object Inspector
Crie um evento ONTimer (esse evento vai ser ativado a cada intervalo de 60000 milissegundos)
Dentro da procedure Timer1Timer coloque o comando abaixo:

...
procedure TfrmCliente.Timer1Timer(Sender: TObject);
begin
StatusBar1.Panels[0].Text := Copy(TimeToStr(Now), 1, 5);
end;
...

Observe:
StatusBar1 é o nome da barra de status.
Panels[0] é a primeira divisão da barra de status.
Text é a propriedade de Panels que contém o texto que será mostrado.
Now é a data e hora correntes.
O comando copy entrou aí só para extrair os cinco primeiros caracteres da hora (hh:mm) e eliminar a parte dos
segundos (os dois últimos caracteres).
Esse esquema só tem um probleminha: a hora só vai aparecer na barra de status depois de um minuto (foi você quem
mandou o timer só ser ativado a cada 60 segundos). Para fazer com que a hora seja mostrada logo que o programa inicie você
precisa mandar executar a procedure Timer1Timer.
Inclua na procedure FormCreate o comando:

...
procedure TfrmCliente.FormCreate(Sender: TObject);
begin
...
Timer1Timer(nil);
end;
...

A procedure Timer1Timer pede um parâmetro Sender. Nesse caso o Sender não é necessário. Por esse motivo pode-se
passar nil, que é um valor nulo.

Figura 21: Barra de Status com relógio


 
47

16. MATEMÁTICA
Calma. A matemática que vamos ver aqui não tem nada de complexa, muito pelo contrário. Ninguém precisa ter medo
das quatro operações básicas, precisa ? E algumas funções trigonométricas, estatísticas e financeiras ? Computemos, então !
Operações Básicas

Operador Operação Exemplo

+ Adição dblSalario + dblAumento

- Subtração dblSalario – dblImposto

* Multiplicação dblSalario * 1.55

/ Divisão dblSalario / intNumeroDependentes

div Divisão entre números inteiros. 4 div 3

mod Resto da divisão entre números inteiros 8 mod 3


Tabela 19: Operações matemáticas básicas

Observe:

A adição, subtração e multiplicação entre números inteiros vai resultar em um número inteiro.
As mesmas operações envolvendo um número de ponto flutuante vai resultar em um número de ponto flutuante.
A divisão sempre resulta em um número de ponto flutuante, mesmo se o divisor, o dividendo e o quociente forem
inteiros.
A operação de divisão entre inteiros (div) sempre resulta em um número inteiro. O resultado é arredondando para
baixo, truncando as casas decimais.
As variáveis do tipo data (TDateTime) são, na verdade, variáveis de ponto flutuante, onde a parte inteira representa a
data e a parte decimal representa a hora.
Isso significa que as operações matemáticas funcionam com datas.
Por exemplo: para calcular uma data daqui a 30 dias, calcule Date + 30
Ordem de Precedência
Na matemática algumas operações têm precedência sobre outras.
Em uma expressão aritmética a multiplicação e a divisão são calculadas antes da adição e da subtração, a menos que
sejam usados parênteses para alterar a ordem. Quando uma expressão contém duas operações de mesmo nível (uma adição e
uma subtração, por exemplo) a expressão é calculada da esquerda para a direita.
O Pascal obedece às regras da matemática.
Para efeito de precedência os operadores mod e div são equivalentes à divisão.

...
X := A + Y * Z - B;
X := (A + (Y * Z)) - B;
...

No exemplo, as duas expressões são equivalentes. Primeiro é calculado Y * Z, depois soma-se A e por fim subtrai-se
B.

17. TRIGONOMETRIA
48
Delphi vem com uma coleção completa de funções trigonométricas. Para quem gosta …

Função Operação Exemplo

Sin Seno de um ângulo em radiano X : = Sin(1.570796)

Cos Cosseno de um ângulo em radiano X : = Cos(3.141593)

Tan Tangente de um ângulo em radiano X : = Tan(0.785398)

DegToRad Converte um ângulo em grau para radiano X : = Sin(DegToRad(90))


X : = Cos(DegToRad(180))
X : = Tan(DegToRad(45))
Tabela 20: Funções trigonométricas

Estes são apenas alguns exemplos. Para uma relação completa leia a documentação do Delphi.
As funções trigonométricas, estatísticas e financeiras estão na unit Math.
Para ter acesso a essas funções você deve declarar a unit Math na cláusula Uses, caso contrário o compilador mostrará
a mensagem: "Undeclared identifier…"

18. ESTATÍSTICA
Função Operação Exemplo

Mean Média aritmética dos valores de um array do x : = Mean(arrNotas)


tipo Double

Norm Média geométrica dos valores de um array do x : = Norm(arrNotas)


tipo Double

StdDev Desvio padrão dos valores de um array do tipo x : = StdDev(arrNotas)


Double
Tabela 21: Funções estatísticas

Estes são apenas alguns exemplos. Para uma relação completa leia a documentação do Delphi.

19. MATEMÁTICA FINANCEIRA


Função Operação Exemplo

FutureValue Calcula o valor futuro de um investimento Calcular o valor futuro de um investimento cujo valor
inicial seja de 10.000,00 com desembolso de 500,00 ao
fim de cada mês durante 12 meses a uma taxa de 2,5%
a.m.
FutureValue(0.025, 12, -500.00, -10000.00,
ptEndOfPeriod)

InterestRate Calcula a taxa de um investimento Calcular a taxa de um investimento cujo valor inicial
seja de 10.000,00 com desembolso de 500,00 ao fim de
cada mês durante 12 meses para que o valor futuro seja
de 20.346,66
49
InterestRate(12, -500, -10000.00, 20346.66,
ptEndOfPeriod)

NumberOfPeriods Calcula o número de períodos de um Calcular o número de períodos de um investimento


investimento cujo valor inicial seja de 10.000,00 com desembolso de
500,00 ao fim de cada mês a uma taxa de 2,5% a.m.
para que o valor futuro seja de 20.346,66
NumberOfPeriods(0.025, -500, -10000.00, 20346.66,
ptEndOfPeriod)
Tabela 22: Funções financeiras

Estes são apenas alguns exemplos. Para uma relação completa leia a documentação do Delphi.

20. LÓGICA BOOLEANA


O que seria dos computadores (e do Sr. Spock) se não existisse a lógica ? Sem a lógica os computadores não poderiam
tomar decisões. Sem tomar decisões os computadores não seriam mais do que uma reles calculadora super-desenvolvida.
"Elementar, meu caro Watson."
A lógica em Object Pascal é implementada por comandos condicionais – tais como if e case – e comandos de
repetição – repeat, while e for. Todos esses comandos têm em comum o uso de expressões lógicas.

A) EXPRESSÕES LÓGICAS
O que caracteriza uma expressão é o seu resultado. Uma expressão aritmética tem como resultado um número. Uma
expressão lógica tem como resultado um valor booleano: verdadeiro ou falso. Em outras palavras, uma expressão lógica é uma
pergunta à qual a resposta tem que ser ou verdadeiro ou falso.

B) VALORES BOOLEANOS
As palavras reservadas True e False representam os valores booleanos Verdadeiro e Falso, respectivamente. Os
valores booleanos são a forma mais simples de expressão lógica pois já são o resultado da expressão em si.
Onde quer que uma expressão lógica possa ser usada, os valores booleanos também podem.

...
var
booVerdadeiroOuFalso: boolean;
begin
booVerdadeiroOuFalso := True;
...

C) OPERADORES RELACIONAIS
Os operadores relacionais comparam dois operandos e dão um valor booleano como resultado.

Operador Descrição Exemplo

= Igualdade dblMinhasDividas = 0.00

<> Diferença dblMeuSalario <> dblSalarioMinimo

< Menor que ‘Zeferino’ < ‘Aarão’

> Maior que intQtdContasAPagar > 20


50
<= Menor ou igual dblMeuSaldoNoBanco <= 0.00

>= Maior ou igual dtDataNascimentoDoMatuzalem >= dtMinhaDataNascimento


Tabela 23: Operadores relacionais

Os operandos devem ser de tipos compatíveis entre si, com exceção de inteiros que podem ser comparados com reais.
Nada de comparar um string com um inteiro ou coisa parecida.

D) OPERADORES BOOLEANOS
Os operadores booleanos fazem com valores booleanos o que os operadores aritméticos fazem com números. Você
que já sabe somar e subtrair, agora vai aprender a NOTear, ANDear, ORear e XORear …

Operador Descrição

Not "NÃO": Inverte o valor de um operando booleano. Se o operando é verdadeiro o resultado é falso. Se o
operando é falso o resultado é verdadeiro.

And "E": Se os dois operandos são verdadeiros o resultado é verdadeiro. Se um dos dois operandos é falso o
resultado é falso.

or "OU": Se os dois operandos são falsos o resultado é falso. Se um dos dois operandos é verdadeiro o
resultado é verdadeiro.

xor "OU EXCLUSIVO": Se os dois operandos são verdadeiros ou os dois operandos são falsos o resultado é
falso. Se um operando é verdadeiro e o outro é falso o resultado é verdadeiro.
Tabela 24: Operadores booleanos

var
booVerdadeiro, booFalso: boolean;
dblSalario, dblSaldoBancario: double;
intQtdContasAPagar: integer;
begin
dblSalario := 122.00;
intQtdContasAPagar := 200;
dblSaldoBancario := -800.00;
booVerdadeiro := not (dblSalario > 1000.00);
booFalso := not (intQtdContasAPagar = 200);
booVerdadeiro := (dblSalario > 100.00) and (dblSalario < 1000.00);
booFalso := (booVerdadeiro) and (dblSalario > intQtdContasAPagar);
booVerdadeiro := (dblSaldoBancario > 0.00) or (dblSalario < 1000.00);
booFalso := (intQtdContasAPagar < 10) or (dblSalario > 500);
booVerdadeiro := (dblSaldoBancario > 0.00) xor (dblSalario < 1000.00);
booFalso := (intQtdContasAPagar = 200) xor (dblSalario = 122.00);
...

Observe:
Os operadores and, or e xor precisam de dois operandos. O operador not só precisa de um operando.
O uso dos parênteses não é obrigatório mas é altamente recomendável. Uma expressão como "dblSaldoBancario >
0.00 or dblSalario < 1000.00" sem parênteses será interpretada como "dblSaldoBancario > (0.00 or dblSalario) < 1000.00"
pelo Object Pascal. Isso vai resultar em na mensagem de erro do compilador: "Operator not applicable to this operand type".
Faz sentido, afinal de contas o operador or não funciona com operandos de ponto flutuante 0.00 ou dblSalario.

E) COMANDO IF
O comando if decide se um comando deve ser executado ou não com base em uma expressão lógica.
O if tem dois formatos básicos, um com else outro sem else.

if expressão-lógica then comando;


51
ou

if expressão-lógica then
comando
else
outro-comando;

Se a expressão-lógica for verdadeira então o comando é executado senão o outro-comando é executado.


Por comando entende-se qualquer comando reconhecido pelo Object Pascal, isso inclui, mas não se limita a outro
comando if e chamadas a funções e procedures.

Exemplos de if

 Exemplo de if sem cláusula else:

if dblSaldoBancario > 0.00 then


ShowMessage('Milagre!');

 Exemplo de if com cláusula else:

if dblSaldoBancario > 0.00 then


ShowMessage('Milagre!')
else
ShowMessage('Isso é normal.');

Um erro de programação muito comum é colocar um ponto-e-vírgula antes da cláusula else. Note que no exemplo não
há ponto-e-vírgula antes do else.
Outro erro básico é o de colocar mais de um comando na cláusula then ou else.

if dblSaldoBancario > 0.00 then


ShowMessage('Milagre!');
ShowMessage('Essa mensagem vai aparecer sempre.');

Ao contrário do que possa parecer a segunda mensagem vai aparecer sempre, não importando se a expressão lógica é
verdadeira ou falsa.
Somente um comando é permitido após as cláusulas then e else.
Para colocar mais de um comando nessas cláusulas crie um comando composto.
Os delimitadores begin e end envolvem um grupo de comandos e, para todos os efeitos, funcionam como se fosse um
comando só.

1 - IF COM MAIS DE UM COMANDO


 Exemplo de if sem cláusula else:

if dblSaldoBancario > 0.00 then


begin
ShowMessage('Milagre!');
dblSaldoBancario := dblSaldoBancario – 500.00;
end;

 Exemplo de if com cláusula else:

if dblSaldoBancario > 0.00 then


begin
ShowMessage('Milagre!');
dblSaldoBancario := dblSaldoBancario – 500.00;
end
else
begin
ShowMessage('Isso é normal.');
dblSaldoBancario := dblSaldoBancario + 500.00;
52
end;

2 - IF ANINHADO
if aninhado é um if colocado dentro de outro if, no lugar do comando após o then ou o else.

 Exemplos de if aninhado:

if dblSaldoBancario > 0.00 then


if dblSalario > 5000.00 then
ShowMessage('Milagre Duplo!');

A mensagem "Milagre Duplo !" só vai aparecer se o saldo bancário for maior que zero e o salário maior que 5.000,00.

if dblSaldoBancario > 0.00 then


ShowMessage('Milagre!')
else
if dblSalario < 200.00 then
ShowMessage('Isso é mais do que normal.');

A mensagem "Isso é mais do que normal." só vai aparecer se o saldo bancário não for maior que zero e o salário
menor que 200,00.

F) COMANDO CASE
O comando case é uma forma alternativa de if aninhado. Ao invés de colocar um if dentro de outro sucessivamente,
usa-se o case para organizar esse aninhamento. Pena que existam tantas restrições e contra-indicações ao case.
O formato básico do case é:

case expressão-de-seleção of
lista-de-valores1: comando1;
...
lista-de-valoresn: comandon;
else
comando;
end

Observe:
A expressão-de-seleção é uma expressão do tipo inteiro, booleano, char, enumerado ou subconjunto. Outros tipos de
dados, tais como string, ponto flutuante, data, etc. não são permitidos.
A lista-de-valores é uma lista de valores que será comparada com a expressão-de-seleção. A única condição de
comparação possível é a igualdade.
Comando é um comando que será executado se a lista-de-valores for igual à expressão-de-seleção. Aqui se aplica a
mesma restrição do if: Somente um único comando é permitido. Para executar mais de um comando, use o comando composto.
A cláusula else não é obrigatória.

 Exemplo de Case

case intQtdContasAPagar of
0: ShowMessage(‘Milagre!');
1,2,3: ShowMessage(‘Cuidado!');
4..10: ShowMessage(‘Perigo!');
else
ShowMessage(‘Falência Total!');
end;

A lista-de-valores pode ser uma lista com um valor só (no exemplo, o zero), pode ser uma lista com valores contínuos
ou não, separados por vírgula (1, 2, 3) e pode ser um intervalo de valores contínuos separados por dois pontos (4..10).

G) COMANDO FOR
53
O comando for é um comando de repetição. O for vai incrementar ou decrementar um contador e repetir um comando
(ou um comando composto) até que o contador atinja um valor pré-determinado.
Os formatos básico do for são:

for contador := valor-inicial to valor-final


do comando;

ou

for contador := valor-inicial downto


valor-final do comando;

Observe:
O contador é uma variável do tipo inteiro, booleano, char, enumerado ou subconjunto. Outros tipos de dados, tais
como string, ponto flutuante, data, etc. não são permitidos.
O contador tem que ser declarado no mesmo bloco de comandos do for, ou seja, se o for estiver dentro de uma
procedure o contador tem que ser declarado na mesma procedure.
Valor-inicial é o valor atribuído ao contador.
O contador vai ser incrementado (to) ou decrementado (downto) até atingir o valor-final.
Cada vez que o contador mudar o comando vai ser executado.

 Exemplo de For

procedure TForm1.MinhaProcedure;
var
x: integer;
begin
...
for x := 1 to 10 do
ShowMessage(‘Mensagem número ' + IntToStr(x));
...
for x := 10 downto 1 do
begin
ShowMessage(‘Contagem regressiva: ' + IntToStr(x));
ShowMessage(‘Faltam ' + IntToStr(x - 1) + ‘para acabar’);
end;
...
end;

Observe que o contador x está declarado dentro da procedure onde o for é usado.
No primeiro for o x começa valendo 1 e vai aumentando de 1 em 1 até 10. As mensagens "Mensagem número 1",
"Mensagem número 2", …, "Mensagem número 10" aparecem sucessivamente.
No segundo for o x começa em 10 e vai diminuindo (downto) de 1 em 1 até 1. Note o uso do comando composto
delimitado por begin e end.

H) COMANDO WHILE
O comando while também é um comando de repetição. O while vai repetir um comando (ou um comando composto)
enquanto uma expressão lógica for verdadeira.
O formato básico do while é:

while expressão-lógica do comando;

Observe:
A expressão-lógica é uma expressão lógica que será testada antes de executar o comando. Vale qualquer expressão
lógica envolvendo qualquer tipo de dado.
O comando vai ser executado enquanto a expressão-lógica for verdadeira.
 Exemplo de While

...
x := 1;
while x <= 10 do
begin
54
ShowMessage(‘Mensagem número ' + IntToStr(x));
Inc(x);
end;
...
x := 10;
while x >= 1 do
begin
ShowMessage(‘Contagem regressiva: ' + IntToStr(x));
ShowMessage(‘Faltam ' + IntToStr(x - 1) + ‘para acabar’);
Dec(x);
end;
...

Os comandos while acima fazem rigorosamente a mesma coisa que os comandos for vistos no exemplo anterior.
A procedure Inc incrementa e a procedure Dec decrementa o valor de uma variável do tipo inteiro.
Um erro de programação frequente é esquecer de incluir comandos para mudar o resultado da expressão lógica.
No primeiro exemplo, se a variável x não fosse incrementada o seu valor permaneceria sempre menor que 10. O
programa executaria o comando do while para sempre !

I) COMANDO REPEAT
O comando repeat é parecido com o while. O repeat repete um bloco de comandos de acordo com uma expressão-
lógica.
O while executa o comando se a expressão-lógica for verdadeira, o repeat executa os comandos se a expressão-lógica
for falsa.
O while testa a expressão-lógica para depois executar o comando, o repeat executa os comandos para depois testar a
expressão-lógica.
O formato básico do repeat é:

repeat
comando1;
...
comandon;
until expressão-lógica;

Observe:
A expressão-lógica é uma expressão lógica que será testada antes de executar o comando. Vale qualquer expressão
lógica envolvendo qualquer tipo de dado.
O comando1…comandon são os comandos que serão executados enquanto a expressão-lógica for falsa
Ao contrário dos comandos anteriores, o repeat pode conter qualquer número de comandos, sem a necessidade de usar
um comando composto.

 Exemplo de Repeat

...
x := 1;
repeat
ShowMessage(‘Mensagem número ' + IntToStr(x));
Inc(x);
until x > 10;
...
x := 10;
repeat
ShowMessage(‘Contagem regressiva: ' + IntToStr(x));
ShowMessage(‘Faltam ' + IntToStr(x - 1) + ‘para acabar’);
Dec(x);
until x < 1;
...
Os comandos repeat acima fazem rigorosamente a mesma coisa que os comandos for vistos no exemplo anterior.
A procedure Inc incrementa e a procedure Dec decrementa o valor de uma variável do tipo inteiro.
Vale a mesma advertência feita para o while: Não esqueça de alterar o resultado da expressão lógica ou o programa
corre o risco de entrar em looping.
55
J) CONTINUE E BREAK
Os comandos continue e break são usados para alterar o fluxo do processamento dos comandos for, while e repeat.
O break termina o comando for, while ou repeat e continua o processamento no comando seguinte.

...
x := 1;
repeat
ShowMessage(‘Essa mensagem só aparece uma vez !');
Inc(x);
break;
until x > 10;
ShowMessage(‘Continua aqui após o break !');
...

O continue pula o resto do bloco de comandos e continua na próxima iteração do comando for, while ou repeat.

...
x := 1;
repeat
ShowMessage(‘Essa mensagem aparece 10 vezes !');
Inc(x);
continue;
ShowMessage(‘Essa mensagem não aparece nunca !');
until x > 10;
...

K) BOTANDO A MÃO NA MASSA


Vamos dar continuidade àquele projeto Pcliente.dpr de Componentes visuais.
Um dos dados do cadastro de clientes é o CGC. Precisamos criar uma função de consistência para evitar que um CGC
incorreto seja cadastrado. Vamos apenas declarar a função; não vamos usá-la ainda.
Função Consistir CGC
Primeiro vamos declarar a função para consistir CGC na região private do Form. Assim:

...
private
{ Private declarations }
function CGCValido(const strParmCGC: string): boolean;
...

A função vai receber um CGC como parâmetro e vai retornar verdadeiro quando o CGC for válido ou falso quando o
CGC não for válido.
Agora vamos declarar a função na seção implementation.

...
implementation
...
function TfrmCliente.CGCValido(const strParmCGC: string): boolean;
var
j: integer;
strTmpCGC, strTmpCGCDV: string;
begin

// Copiar apenas números de strParmCGC para strCGC

for j := 1 to Length(strParmCGC) do
if (Copy(strParmCGC, j, 1) >= '0') and
(Copy(strParmCGC, j, 1) <= '9') then
strTmpCGC := strTmpCGC + Copy(strParmCGC, j, 1);

// Se CGC está vazio então desprezar


56
if Trim(strTmpCgc) = EmptyStr then
begin
CGCValido := False;
exit;
end;

// O CGC deve ter 14 dígitos. Completar com zeros à esquerda


strTmpCGC := Copy('00000000000000', 1, 14 – Length(strTmpCGC))
+ strTmpCGC;

// Guardar o dígito verificador informado


strTmpCGCDv := Copy(strTmpCgc, 13, 2);

// Calcular o DV do CGC e comparar com o DV informado


CGCValido := (strTmpCgcDV = CalcularDV(strTmpCgc));

end;
...

Na última linha do CGCValido há uma referência à função CalcularDV. Essa função também precisa ser declarada.
Agora a região private do Form vai ficar assim.

...
private
{ Private declarations }
function CGCValido(const strParmCGC: string): boolean;
function CalcularDV(const strParmCGC: string): string;
...

A função CalcularDV na seção implementation é assim:

...
implementation
...
function TfrmCliente.CalcularDV(const strParmCGC: string): string;
var
strTmpDVCalc, strTmpPeso: string;
intTmpSoma, intTmpDigito, i, j: integer;
begin
strTmpDVCalc := EmptyStr;
intTmpDigito := 0;

// Estabelecer os pesos para o 1o. DV


strTmpPeso := '543298765432';

// Calcular duas vezes (uma para cada dígito verificador)


for j := 1 to 2 do
begin
intTmpSoma := 0;
// Somar 12 vezes (uma para cada dígito do CGC)
for i := 1 to 12 do
begin
intTmpSoma := intTmpSoma +
StrToInt(copy(strParmCGC, i, 1)) *
StrToInt(copy(strTmpPeso, i, 1));
end;

// Se já está na segunda vez


// Então Somar o 13o. dígito

if j = 2 then
intTmpSoma := intTmpSoma + (2 * intTmpDigito);

// Calcular o módulo 11
57
intTmpDigito := (intTmpSoma * 10) mod 11;
if intTmpDigito = 10 then
intTmpDigito := 0;

// Guardar o DV calculado
strTmpDVCalc := strTmpDVCalc + IntToStr(intTmpDigito);

// Os pesos para o segundo DV são diferentes do primeiro


strTmpPeso := '654329876543';
end;

// Retornar o valor do DV calculado

CalcularDV := strTmpDVCalc;
end;
...

21. BANCO DE DADOS


Banco de sangue guarda sangue, banco de dinheiro guarda dinheiro, banco de dados guarda dados. Parece fácil, mas
não é.
Na verdade existem quatro coisas diferentes que são popularmente chamadas de banco de dados: (1) Sistema
gerenciador de banco de dados, (2) estrutura lógica, (3) estrutura física e (4) dados propriamente ditos.
Neste emocionante capítulo vamos usar as ferramentas do Delphi para definir as estruturas de dados e finalmente
veremos como o Delphi se integra aos sistemas gerenciadores de banco de dados para armazenar e recuperar dados.
Conceitos Básicos
Antes de meter a mão na massa é preciso conhecer os conceitos básicos relacionados aos bancos de dados. Este curso
não pretende esgotar o assunto, mas dar uma visão geral para facilitar a compreensão dos próximos tópicos.

 Sistema gerenciador de banco de dados (SGBD): Programa usado para guardar, organizar e recuperar dados.
Ex.: MS-SQL Server, Oracle, Sybase, etc.

 Estrutura lógica do banco de dados: Definição dos dados que o banco de dados vai conter, especificando
tabelas, colunas, relacionamentos, etc.

 Estrutura física do banco de dados: Arquivos onde os dados são gravados. Ex.: No Paradox cada tabela
corresponde a um arquivo com extensão *.db; no Access várias tabelas são agrupadas em um único arquivo com
extensão *.mdb.

 Tabela: Tabelas são agrupamentos de dados afins dentro da estrutura lógica. As tabelas são divididas em linhas e
colunas. Ex.: Uma tabela de clientes agrupa dados de todos os clientes cadastrados. Cada linha da tabela de
clientes contém dados de um cliente específico. Cada coluna da tabela de clientes representa um atributo dos
clientes – o nome, o código, o logradouro, etc.

A) DATABASE DESKTOP
O Delphi vem com um programa chamado
Database Desktop. Com esse utilitário é possível
administrar os bancos de dados (em todos os sentidos
da expressão), criar as estruturas lógica e física e até
mesmo alterar os dados contidos nesses bancos de
dados.

Figura 22: Database Desktop


Para abrir o Database Desktop, clique na
opção "Tools  Database Desktop" no menu do Delphi
Vamos ver agora, passo a passo, os procedimentos para criar as estruturas lógica e física de um banco de dados
usando o Database Desktop.
58
B) CRIAR UM ALIAS
"Alias" é um apelido, um nome que aponta para um SGBD e uma estrutura física. Os programas escritos em Delphi
usam o alias para chegar ao banco de dados.
No menu do Database Desktop, clique na opção "Tools  Alias Manager".

Figura 23: Novo alias

Clique no botão New


Digite o nome do alias no combo box Database Alias: "MEUALIAS"
O Driver Type indica o SGBD. Vamos usar Paradox e para isso deixe o driver STANDARD.
No Path digite o path do diretório onde as tabelas Paradox vão residir: C:\DELPHILAB\CAPITULO13
O diretório indicado no Path já deve estar criado. O Database Desktop vai dar a mensagem "Invalid Path" se o
diretório não existir.
Clique no botão OK e confirme no botão Yes.
Também podem ser usados o Database Explorer ou o BDE Administrator para criar alias.

C) DEFINIR O DIRETÓRIO DE TRABALHO


Vamos informar ao Database Desktop que queremos usar o alias MEUALIAS como o diretório de trabalho. Esse
passo não é obrigatório mas vai tornar a sua vida muito mais fácil.
No menu do Database Desktop clique na opção "File --> Working Directory".
Vai abrir uma janela com dois combo boxes: Working Directory e Aliases
No combo box Aliases (na parte de baixo) selecione o alias MEUALIAS
Clique no botão OK
A partir de agora MEUALIAS vai ser o alias default para o Database Desktop.

D) CRIAR TABELAS
Vamos criar a tabela de clientes para continuarmos o exercício iniciado em Componentes visuais.
No menu do Database Desktop clique na opção "File --> New --> Table"
Selecione Paradox 7 como tipo da tabela e clique no botão OK
59

Figura 24: Criar tabela

A estrutura da tabela de clientes será assim:

Nome do Campo Tipo de Dado Tamanho

CODIGO Long integer

CGC Alpha 18

NOME Alpha 50

CONTATO Alpha 50

TELEFONE Alpha 15

VALOR_CREDITO Number

LOGRADOURO Alpha 50

COMPLEMENTO Alpha 50

CIDADE Alpha 50

ESTADO Alpha 2

CEP Alpha 10

STATUS Alpha 1

LUXO Logical

PECHINCHA Logical

UTIL Logical
Tabela 25: Estrutura da tabela de exemplo

 Field Name: Digite o nome do campo


60
 Type: Informe o tipo de dado. Para ver os tipos de dados válidos selecione o Type e aperte a tecla "barra de
espaço". Vão aparecer todos os tipos de dados possíveis. Selecione o tipo de dado apropriado para a coluna.
 Size: Quando necessário informe o tamanho.
 Key: Na coluna Key, na linha do campo CODIGO aperte uma tecla qualquer (pode ser a barra de espaço)
para indicar que o código é a chave primária da tabela. Se tudo der certo deve aparecer um asterisco.

Cada SGBD tem seus próprios tipos de dados que não são necessariamente iguais aos tipos de dados do Delphi.
Apesar das diferenças, existem tipos compatíveis entre si.
Ex.: Alpha, Logical e Number em Paradox são, respectivamente, compatíveis com string, boolean e double do Delphi.

Figura 25: Estrutura da tabela

Clique no botão Save As.


Digite o nome da tabela: CLIENTE
Clique no botão Save
Pronto. A tabela de clientes está criada.

E) CRIAR ÍNDICES
Índices de tabelas têm a mesma função dos índices de livros: são um caminho direto a uma informação. Você já criou
um índice no tópico anterior. A chave primária da tabela é um índice. Outros índices secundários podem ser criados.
Os índices secundários são usados para melhorar a performance e, no caso de SGBDs locais, para ordenação dos
dados.
Vamos criar um índice secundário no campo NOME, assim vai ser possível obter os dados dos clientes ordenados por
nome, quando necessário.
Clique na opção "File --> Open --> Table"
Clique na tabela CLIENTE.DB
Clique na opção "Table --> Restructure"
Vai aparecer a janela Restructure idêntica à usada para criar a estrutura da tabela.
Selecione a opção "Secondary Indexes" no combo box Table Properties
Clique no botão "Define…"
Vai aparecer a janela Define Secondary Index
Selecione o campo NOME na lista Fields
Clique no botão "-->" (seta para direita)
Clique no botão "OK"
Vai aparecer a janela "Save Index As"
Digite o nome do índice: "idxNOME"
Clique no botão "OK"
Clique no botão "Save"
61

Figura 26: Criação de índices secundários

F) EDITAR DADOS
O Database Desktop permite incluir, alterar e excluir dados das tabelas.
Clique na opção "File --> Open --> Table"
Clique na tabela CLIENTE.DB
Clique no botão Open
Clique na opção do menu "Table --> Edit Data" ou aperte o botão F9
Agora é só digitar dentro dos campos.

Figura 27: Database Desktop - Edição de Tabela

22. BORLAND DATABASE ENGINE


Também conhecido por BDE é o mecanismo usado pelo Delphi para acessar SGBDs. O BDE funciona como o "meio
de campo" entre um programa escrito em Delphi e o SGBD.
62
O BDE do Delphi 4 Standard tem drivers para os SGBDs Paradox, Access, dBase e FoxPro. O Delphi 4 Professional
vem com driver para InterBase, além dos já mencionados. O Delphi 4 Client/Server tem todos os anteriores e mais MS-SQL
Server, Oracle, Sybase e Informix.
Qualquer SGBD que tenha driver ODBC (Open DataBase Connectivity) pode ser acessado via BDE qualquer que seja
a versão do Delphi.
Você deve estar se perguntando: "Como é que o BDE sabe qual SGBD e qual base de dados deve usar ?"
O BDE não adivinha nada. O próprio programa Delphi, quando pede qualquer serviço do SGBD ao BDE, informa o
alias. Pelo alias o BDE descobre tudo o que precisa para acessar o SGBD e a estrutura corretos.
Os SGBDs locais, entre eles o Paradox, podem ser acessados sem o alias, mas vamos fazer de conta que não sabemos
disso.
BDE Administrator
BDE Administrator é um utilitário usado para administrar o BDE. Com ele configuram-se aliases, drivers de SGBD,
formatos de data, hora e números.
Para abrir o BDE Administrator clique no botão Start do Windows e em seguida "Programs  Borland Delphi 4 
BDE Administrator".

Figura 28: BDE Administrator

Na parte esquerda vemos duas abas: Databases e Configuration.


Na aba Databases estão os aliases já configurados. Aqui os aliases podem ser alterados, criados ou excluídos.
Para criar um alias no BDE Administrator clique na palavra Databases que aparece no topo da lista de aliases com o
botão direito do mouse e em seguida clique na opção New. Depois é só seguir as instruções.
Na aba Configuration são configurados os drivers e formatos. Geralmente as configurações default dos drivers é
adequada. Não vamos mexer nelas.
Com relação aos formatos, alguns ajustes são necessários.

A) FORMATAR A DATA
Clique no sinal + ao lado da palavra Configuration
Clique no sinal + ao lado da palavra System
Clique no sinal + ao lado da palavra Formats
Clique na palavra Date

Figura 29: BDE Administration - aba Configuration


63
Passe a opção FOURDIGITYEAR para True. Essa opção faz o BDE formatar o ano com quatro dígitos.
Passe a opção MODE para 1. Essa opção determina a ordem em que o dia, mês e ano aparecem na data. Ex.: MODE =
1 formata a data como dd/mm/aa.
Deixe a opção YEARBIASED em True. Essa opção soma 1900 ao ano, quando o ano passado ao BDE tiver apenas 2
dígitos. Ex.: O ano 95 é transformado em 1995 pelo BDE quando YEARBIASED é True.
LEADINZEROM é o zero à esquerda do mês. True faz o mês 1 aparecer como 01.
LEADINZEROD é o zero à esquerda do dia. True faz o dia 1 aparecer como 01.
SEPARATOR é o símbolo de separação da data. Normalmente usa-se a barra (/).

B) FORMATAR NÚMERO
Clique no sinal + ao lado da palavra Configuration
Clique no sinal + ao lado da palavra System
Clique no sinal + ao lado da palavra Formats
Clique na palavra Number

Figura 30: BDE Administrator – aba Configuration – opção Number

Certifique-se que a opção DECIMALSEPARATOR seja vírgula e THOUSANDSEPARATOR seja ponto.


A opção LEADINGZERON igual a True põe um zero à esquerda de números entre 1 e –1. Ex.: 0,14 ao invés de ,14

C) DATABASE EXPLORER
Database Explorer (DE) é um utilitário que facilita a navegação pelos aliases, estruturas lógicas e dados do banco de
dados.

Figura 31: Database Explorer


64
Selecionando o alias MEUALIAS o Database Explorer mostra a definição do alias.
Com um duplo clique no MEUALIAS o DE mostra uma pasta Tables.
Com um duplo clique Tables o DE mostra uma lista com as tabelas contidas no alias.
Com um duplo clique na tabela CLIENTES.DB o DE mostra a definição da tabela.
Observe no lado direito a aba Data. Clicando nessa aba o DE mostra o conteúdo da tabela.
Com um duplo clique na pasta Fields o DE mostra a lista de campos da tabela CLIENTES.DB.
Com um duplo clique na pasta Indices o DE mostra a lista de índices da tabela.

23. COMPONENTES DE BANCO DE DADOS


Os componentes Data Aware já foram vistos em Componentes visuais. Para que esses componentes funcionem, eles
precisam ser "conectados" a um campo de uma tabela do banco de dados.
Agora vamos ver os componentes "conectores". Abra aquele projeto Pcliente.dpr de Componentes visuais. A sua
tarefa será completar o projeto para atualizar a tabela de clientes que você acabou de criar.

A) TABLE
Table é o componente que representa a tabela. Através do Table o programa Delphi pode acessar e alterar os dados
contidos na tabela.
Coloque um componente Table no Form. O Table está na aba Data Access da palheta de componentes.
Vamos ver as propriedades:

Propriedade Função

Active Active indica o estado da tabela. False = tabela fechada, True = tabela aberta. Coloque Active= True

DatabaseName É o nome do database onde está a tabela. Digite MEUALIAS (o nome do alias) ou selecione o alias na
lista.

Filter É um filtro para selecionar alguns registros da tabela. Coloque aqui uma expressão lógica e somente os
registros que satisfaçam a expressão serão selecionados. Ex.: Para selecionar clientes do estado do
Paraná com limite de crédito superior a R$10.000,00 o filtro seria VALOR_CREDITO > 10000
AND ESTADO = ‘PR’

Filtered Indica se o Filter está valendo ou não. Para selecionar todos os clientes cadastrados deixe em False.

IndexName É o nome do índice secundário que vai ser usado para ordenação e pesquisa. Quando está em branco o
índice usado é a chave primária. Mude para idxNOME.

Name É o nome do componente Table e não precisa ser igual ao nome da tabela. Coloque tblCliente

TableName É o nome da tabela exatamente como ela está definida no SGBD. Clique sobre a propriedade
TableName e selecione a tabela CLIENTE.DB na lista.
Tabela 26: Propriedades do componente Table

B) FIELDS
Uma tabela tem várias colunas ou campos (nome, código, cgc, etc.). Vamos agora definir esses campos com o Fields
Editor.
Clique com o botão direito no componente tblCliente
Clique na opção Fields Editor do menu pop-up
Vai aparecer uma pequena janela em branco com o título frmCliente.tblCliente
Clique com o botão direito sobre essa janela
Clique na opção Add All Fields do menu pop-up
ou use a tecla de atalho CTRL+F.
65

Figura 32: Fields Editor

Na janela do Fields Editor você pode reorganizar a ordem dos campos (isso é útil quando se trabalha com DBGrid) ou
selecionar um campo para alterar suas propriedades.
Vamos ver as propriedades dos campos:

Propriedade Função

DisplayFormat Permite colocar uma máscara nos valores do campo. Essa máscara é aplicada aos campos no momento
em que não estão sendo editados. Selecione o campo VALOR_CREDITO na janela Fields Editor e
coloque a máscara ###,##0.00 . O caracter # representa um dígito. Se o dígito naquela posição for um
zero à esquerda aparece em branco. O caracter 0 representa um dígito. Se o dígito naquela posição for
um zero à esquerda aparece um zero mesmo.

DisplayLabel É o nome que vai aparecer no cabeçalho do DBGrid. Selecione cada campo do Fields Editor e mude o
DisplayLabel. para algo mais compreensível. Ex.: Selecione o campo VALOR_CREDITO e mude o
DisplayLabel para Limite de Crédito

EditFormat Aplica uma máscara de edição no momento em que o campo estiver sendo editado. Funciona de modo
semelhante ao DisplayFormat.

FieldName É o nome do campo exatamente como foi definido no SGBD. Não mexa.

Index Não tem nada a ver com o índice da tabela. Esse Index determina a ordem em que os campos
aparecem no DBGrid. O primeiro campo tem Index = 0, o segundo tem Index = 1 e assim por diante.
Selecione o campo CGC e passe o Index para 2. Observe que o CGC agora aparece depois do NOME.
Outra maneira de alterar o Index é clicar e arrastar o campo na janela Fields Editor.

MaxValue É o valor máximo do campo. Com 0 (zero) o campo fica limitado pelo valor máximo que o tipo de
dado do SGBD pode guardar. Selecione o campo CODIGO e coloque 10000 no MaxValue. Selecione
VALOR_CREDITO e coloque 50000 no MaxValue, assim o maior valor possível será R$50.000,00

MinValue É o valor mínimo do campo. Com 0 (zero) o campo fica limitado pelo valor mínimo que o tipo de
dado do SGBD pode guardar. Selecione o campo CODIGO e coloque 1 no MinValue.

Name É o nome do campo dentro do programa Delphi. Pode ser alterado mas o nome default é aceitável.
Não precisa mexer.

Required Informa se o campo é obrigatório ou não para o SGBD. Isso não significa que passando a propriedade
Required para True manualmente o campo passará a ser obrigatório. Para garantir a obrigatoriedade de
um campo sem que este seja obrigatório no SGBD use o evento OnValidate.

Visible Indica se o campo vai aparecer no DBGrid ou não. Essa propriedade não tem qualquer efeito sobre os
outros componentes Data Aware. Selecione os campos de VALOR_CREDITO até UTIL no Fields
Editor e passe a propriedade Visible para False. Todos os campos selecionados não vão aparecer no
DBGrid.
Tabela 27: Propriedades do componente Field
66
C) DATASOURCE
O Delphi não permite conectar um componente Data Aware diretamente a um componente Table. É preciso conectar
o componente Data Aware a um DataSource e conectar o DataSource ao Table.
Vamos lá: Coloque um componente DataSource no Form. O DataSource está na aba Data Controls da palheta de
componentes.
Vamos ver as propriedades do DataSource:

Propriedade Função

DataSet É a conexão do DataSource com o Table. Clique na propriedade DataSet e selecione o Table
tblCliente na lista.

Name É o nome do componente DataSource. Como sempre, é importante escolher um nome apropriado.
Digite dsCliente.
Tabela 28: Propriedades do componente DataSource

Você deve estar se perguntando: "Pra quê esse DataSource ? Porque eu não posso conectar os componentes Data
Aware diretamente ao Table ?"
Porque Table não é a única fonte de dados possível. Outra fonte é o Query (que não será discutido nesse curso). O
DataSource evita que os componentes Data Aware tenham que lidar com tipos de fontes de dados diferentes.

D) COMPONENTES DATA AWARE


O Form frmCliente está cheio de componentes Data Aware que foram colocados lá em Componentes visuais. Agora
chegou a hora de conectar esses componentes ao Data Source.
Selecione todos os componentes Data Aware do Form. Aperte a tecla CTRL e clique nos componentes. Certifique-se
que somente componentes Data Aware sejam selecionados. Nada de Label, Menu ou outra coisa qualquer.
Todos os componentes Data Aware têm uma propriedade chamada DataSource. Mude a propriedade DataSource para
dsCliente.
Nesse momento o DBGrid deve estar mostrando o conteúdo da tabela Clientes (nem que seja uma tabela vazia!). Se
não estiver mostrando nem o cabeçalho verifique se a propriedade Active do Table tblCliente está True.
Agora vem a parte mais trabalhosa. Vamos associar cada componente Data Aware a um campo da tabela (menos o
DBGrid que mostra todos os campos visíveis de uma vez).
Selecione o componente edCodigo
Mude a propriedade DataField do edCodigo para CODIGO
Repita esse processo para todos os componentes Data Aware (menos o DBGrid).

Figura 33: Componente Data Aware conectado


67
24. EVENTOS E MÉTODOS DE BANCO DE DADOS
Por enquanto o projeto Pcliente.dpr ainda não faz muita coisa. As opções do menu e os botões não têm nenhuma
função. Vamos resolver esse problema agora.
Incluir
O Form frmCliente tem duas opções para inclusão: uma opção no menu e um botão na barra de ferramentas. Vamos
começar pelo menu.
Clique sobre a opção Incluir. Atenção: faça isso sobre o Form em modo de design. Se você clicar sobre a opção
Incluir em modo de execução não vai acontecer nada !
Isso vai criar uma procedure associada ao evento OnClick da opção Incluir. Dentro da procedure criada inclua os
comandos: ...
procedure TfrmCliente.Incluir1Click(Sender: TObject);
begin
edCodigo.SetFocus;
tblCliente.Insert;
end;
...

O comando edCodigo.SetFocus foi colocado aí para posicionar o cursor no campo código.


No comando, tblCliente é o nome do componente Table e Insert é o método do componente Table que inclui um
registro em branco na tabela. Os componentes Data Aware associados aos campos da tabela (edCodigo, edNome, etc.) vão
ficar em branco e liberados para digitação.
Isso resolve o problema do menu. E o botão ? Quando o usuário clicar o botão btIncluir o programa vai ter que
executar exatamente a mesma procedure, como se a opção Incluir do menu tivesse sido clicada.
Existem dois métodos para solucionar esse caso.

 Primeiro Método:
Toda vez que o botão for clicado, comandar um "clique" virtual para o menu.
Selecione o botão btIncluir
Clique na aba Events do Object Inspector
Dê um duplo clique ao lado do evento OnClick
Inclua o comando Incluir1.Click na procedure criada. O comando Incluir1.Click manda um "clique" à opção Incluir
do menu e o menu vai reagir como se o próprio usuário tivesse clicado lá.

...
procedure TfrmCliente.btIncluirClick(Sender: TObject);
begin
Incluir1.Click;
end;
...

 Segundo Método:
Associar o evento OnClick do botão btIncluir à procedure Incluir1Click.
Selecione o botão btIncluir
Clique na aba Events do Object Inspector
Clique ao lado do evento OnClick
Selecione a procedure Incluir1Click na lista de eventos
Desta forma, quando o botão btIncluir for clicado a procedure Incluir1Click vai ser executada.

A) EXCLUIR
Excluir um registro é tão fácil quanto incluir.
Com o Form em modo de design clique na opção Excluir do menu.
Inclua o comando tblCliente.Delete na procedure criada

...
procedure TfrmCliente.Excluir1Click(Sender: TObject);
begin
tblCliente.Delete;
end;
...
68
Associe o evento OnClick do botão btExcluir à procedure Excluir1Click e pronto !

B) ALTERAR
A opção Alterar deve funcionar como uma confirmação das alterações feitas no registro, ou seja, o usuário altera um
campo qualquer e depois confirma a alteração.
Com o Form em modo de design clique na opção Alterar do menu.
Inclua o comando tblCliente.Post na procedure criada

...
procedure TfrmCliente.Alterar1Click(Sender: TObject);
begin
if tblCliente.State in [dsInsert, dsEdit] then
tblCliente.Post;
end;
...

Note que o comando tblCliente.Post só é executado quando a tabela está em estado de inserção ou edição (dsInsert
ou dsEdit).
Não esqueça de associar o evento OnClick do botão btAlterar à procedure Alterar1Click !

C) PRÓXIMO E ANTERIOR
As opções Próximo e Anterior são em tudo semelhantes Essas opções avançam ou voltam um registro na tabela.
Com o Form em modo de design clique na opção Próximo do menu.
Inclua o comando tblCliente.Next na procedure criada
Com o Form em modo de design clique na opção Anterior do menu.
Inclua o comando tblCliente.Prior na procedure criada

...
procedure TfrmCliente.Pesquisar1Click(Sender: TObject);
begin
tblCliente.Next;
end;

procedure TfrmCliente.Anterior1Click(Sender: TObject);


begin
tblCliente.Prior;
end;
...

Não esqueça de associar os eventos OnClick dos botões btAvancar e btVoltar às respectivas procedures.

D) CONSISTÊNCIA DO BANCO DE DADOS


O programa já está quase pronto. Já tem inclusão, alteração, exclusão e uma pesquisa rudimentar (para frente e para
trás). Falta fazer a consistência (ou crítica) para evitar que valores errados sejam gravados no banco de dados.

1 - CONSISTIR CGC
Lembra daquela função para calcular dígito verificador de CGC que fizemos em Lógica booleana ? Vamos usá-la
agora. Todos os Fields têm um evento chamado OnValidate. Esse evento é disparado sempre que o campo vai ser gravado no
banco de dados.
Clique com o botão direito o componente Table tblCliente
Clique na opção Fields Editor do menu pop-up
Selecione o campo CGC
Clique na aba Events do Object Inspector
Dê um duplo clique no evento OnValidade
Faça uma chamada à função CGCValido

...
69
procedure TfrmCliente.tblClienteCGCValidate(Sender: TField);
begin
if not CGCValido(tblClienteCGC.Value) then
begin
edCGC.SetFocus;
raise EDataBaseError.Create('O CGC está incorreto');
end;
end;
...

Vamos por partes:

 tblClienteCGC é a definição do campo de CGC da tabela de cliente dentro do programa Delphi.


 tblClienteCGC.Value é o conteúdo, aquilo que foi digitado no campo de CGC da tabela de cliente.
 CGCValido é a função que retorna True quando o CGC passado como parâmetro está válido.
 raise é o comando que cria uma exceção e interrompe o processo de atualizar o banco de dados.
 EDatabaseError indica que a exceção que está ocorrendo é relacionada ao banco de dados. No caso, a
exceção é o CGC incorreto.

2 - CONSISTIR CÓDIGO
O código da tabela de clientes não pode ter duplicidade (o código é a chave primária). Vamos fazer uma procedure
testar se o código digitado já está cadastrado.
Crie uma procedure para responder ao evento OnValidate do Field tblClienteCodigo, do mesmo jeito que foi feito
para o CGC.
...
procedure TfrmCliente.tblClienteCODIGOValidate(Sender: TField);
var
tblTemporaria: TTable;
begin
if tblCliente.State in [dsInsert] then
begin
tblTemporaria := TTable.Create(nil);
tblTemporaria.DataBaseName := tblCliente.DatabaseName;
tblTemporaria.TableName := tblCliente.TableName;
tblTemporaria.Open;
if tblTemporaria.FindKey([tblClienteCODIGO.Value]) then
begin
edCodigo.SetFocus;
raise EDatabaseError.Create('Código em duplicidade');
end;
tblTemporaria.Free;
end;
end;
...

Vamos por partes:

 tblTemporaria é um componente Table que vai acessar a tabela de Clientes para verificar se o código está em
duplicidade. É necessário criar um novo componente Table para não mexer no tblCliente. O tblCliente está em
fase de validação para inclusão de registro e não pode mudar para outro registro.

 O tblTemporaria foi declarado como se fosse uma variável local. Qual a diferença entre o Table colocado no
Form e o componente declarado como variável local ? Nenhuma ! Foi feito desse jeito apenas para mostrar que é
possível.

 tblTemporaria := TTable.Create(nil) é o comando que cria o componente Table em tempo de execução.


Quando o componente é jogado no Form o próprio Delphi se encarrega de fazer a sua criação.

 tblTemporaria.DatabaseName := tblCliente.DatabaseName e tblTemporaria.TableName :=


tblCliente.TableName fazem o tblTemporaria acessar a mesma tabela e o mesmo database do tblCliente.

 tblTemporaria.Open é a mesma coisa que tblTemporaria.Active := True, ou seja, abre a tabela.


70

 tblTemporaria.FindKey([tblClienteCODIGO.Value]) procura na tabela pelo código e retorna True se


encontrar. FindKey faz a procura comparando o valor entre colchetes com o índice da tabela especificado na
propriedade IndexName. Como nada foi especificado na propriedade IndexName, o FindKey entende que a
pesquisa deve ser feita pela chave primária.

 tblTemporaria.Free faz a destruição do que foi criado com TTable.Create(nil). É uma boa técnica de
programação usar Free para liberar tudo que foi criado com Create.

Parabéns ! O seu programa está pronto !

25. RELATÓRIO
A impressão de relatórios é uma necessidade na maioria dos sistemas. Quem tem Delphi tem tudo para imprimir
relatórios.
O Delphi vem com dois mecanismos básicos para gerar relatórios: (1) Quick Report e (2) TPrinter. Além disso
existem muitos geradores de relatórios de terceiros que podem ser adquiridos à parte, tais como Report Builder e
ReportSmith.
O TPrinter permite manipular diretamente a impressora. Cada texto impresso é posicionado na página através de um
sistema de coordenadas calculadas em pixels. Isso é tão difícil quanto parece. É melhor pular esse método.
No Quick Report o relatório é desenhado em um ambiente visual como se fosse um Form. Esse método é bem mais
fácil. Vamos a ele.

A) QUICK REPORT
Desenhar um relatório com o Quick Report é assim: Você cria um novo Form e nesse Form em branco você desenha o
relatório usando os componentes próprios do Quick Report (esses componentes estão na aba QReport da palheta de
componetes).
Para fazer o programa imprimir o relatório ou mostrar uma prévia do relatório em vídeo, você deve incluir uma opção
de impressão – no menu ou botão - em um Form que seja visível ao usuário (pode ser o Form principal do sistema). O Form do
relatório em Quick Report não fica visível ao usuário.
Imagine um projeto Project1 que tem um Form chamado Form1. Para fazer um relatório, crie um outro Form
chamado Form2. Desenhe seu relatório no Form2. Coloque um botão ou coisa parecida no Form1. Defina uma procedure para
responder ao evento do botão. Nessa procedure mande imprimir o relatório do Form2. Não esqueça de declarar o Form2 na
cláusula uses do Form1.
A unit do Form1 vai ficar assim:

...
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls,
Forms, Dialogs, StdCtrls, Unit2;
...
procedure TForm1.Button1Click(Sender: TObject);
begin
Form2.QuickRep1.Preview;
end;
...

Note a declaração da Unit2 (a unit do Form2) na cláusula uses do Form1.


Note também a procedure Button1Click, que responde ao evento OnClick do botão Button1. QuickRep1 é o nome do
relatório que está no Form2. O método preview do QuickRep1 mostra uma prévia do relatório em vídeo. Para fazer o
programa mandar o relatório diretamente para a impressora é só substituir o método preview pelo método print.

 Desenhando o relatório

Vamos retomar o projeto Pcliente e fazer um relatório de clientes. O relatório vai conter nome, contato, telefone e
limite de crédito.
71
1 - COMPONENTE QUICKREP
O componente QuickRep é a base para a construção do relatório. É dentro do QuickRep que o relatório vai ser
desenhado.
Abra o projeto Pcliente.dpr
Crie um Form novo: clique na opção do menu do Delphi "File --> New Form" ou clique no botão New Form da barra
de ferramentas.
Mude a propriedade Name do Form para frmRelatorio.
Salve o Form com o nome Urelat.pas
Coloque um componente QuickRep no Form novo. O QuickRep está na aba QReport da palheta de componentes.

2 - BANDS
As bands do QuickRep dividem o relatório em faixas de acordo com a função. Existe uma faixa para o cabeçalho,
outra para o rodapé, outra para a linha de detalhe, etc.
Dê um duplo clique na propriedade Bands do QuickRep
Vão aparecer as opções HasColumnHeader, HasDetail, HasPageFooter, HasPageHeader, HasSummary e HasTitle.

Opções da Função
propriedade Bands

HasTitle Põe uma faixa (band) para edição do título do relatório. Título é aquela parte do relatório que só
aparece no topo da primeira página, depois do cabeçalho. Coloque False.

HasPageHeader Põe uma faixa para edição do cabeçalho. O cabeçalho aparece no topo de cada página do relatório.
Coloque True.

HasDetail Põe uma faixa para edição de linha de detalhe. A linha de detalhe aparece uma vez para cada registro
da tabela. Coloque True.

HasColumnHeader Põe uma faixa para edição do cabeçalho de coluna. Essa faixa aparece entre o cabeçalho e a linha de
detalhe. Coloque True.

HasPageFooter Põe uma faixa para edição do rodapé. Essa faixa aparece no fim de cada página. Coloque True.

HasSummary Põe uma faixa para edição do sumário. Essa faixa aparece no fim da última página do relatório, antes
do rodapé. Coloque True.
Tabela 29: QuickRep - Bands - Opções

Veja como ficou:

Figura 34: Componente QuickRep


72
3 - DATASET
A próxima propriedade do QuickRep é a DataSet. Essa propriedade aponta para a fonte dos dados que serão
impressos. A fonte dos dados, neste caso, vai ser a tabela Cliente.
Coloque um componente Table no Form
Mude as propriedades do Table para acessar a tabela Cliente

Propriedade do Valor
Table

Active True

DatabaseName MEUALIAS

IndexName IdxNOME

Name TblCliente

TableName Cliente.db
Tabela 30: Propriedades do componente Table para o relatório

Selecione o componente QuickRep


Mude a propriedade DataSet para tblCliente
Outras Propriedades do QuickRep

Propriedade Função

Name Nome do componente.


Mude para relCliente

ReportTitle É o nome que vai aparecer na fila de impressão do Windows ou da rede.


Mude para Relatório de Clientes

Options Estas opções permitem impedir que o cabeçalho apareça na primeira página ou que o rodapé
apareça na última. Isso é útil se você quiser que o título ou a faixa de fim de relatório apareçam
isolados, sem cabeçalho ou rodapé.
No projeto atual deixe como está.

Page Define o formato da página. Altura, largura, margens, orientação (retrato ou paisagem), etc.
Tabela 31: Propriedades do componente QuickRep

4 - CABEÇALHO
Vamos desenhar o cabeçalho na faixa PageHeader.
Selecione a faixa PageHeader
Clique e arraste a âncora inferior da faixa para aumentar o tamanho. Âncoras são aqueles pontos pretos que aparecem
em volta do componente selecionado.
Coloque um componente QRLabel na faixa PageHeader. Note que os componentes não podem ser movidos de uma
faixa para outra.
Centralize o componente QRLabel mudando a propriedade Alignment para taCenter e a propriedade AlignToBand
para True.
Mude a propriedade Caption para "Relatório de Clientes" (sem as aspas).
Mude a opção Size da propriedade Font para 20
Se você quiser pode incluir uma imagem (um logotipo, por exemplo).
Coloque um componente QRImage na faixa PageHeader.
Clique na propriedade Picture
Clique no botão das reticências
Escolha uma imagem com o Picture Editor
73

Figura 35: Cabeçalho

5 - CABEÇALHO DE COLUNA
Vamos desenhar o cabeçalho de coluna na faixa ColumnHeader.
Coloque 4 componentes QRLabel na faixa ColumnHeader (um para cada coluna do relatório).
Altere as propriedades Caption para Nome, Contato, Telefone e Limite de Crédito.
Altere o Style das propriedades Font para Underline e Italic.
Só para enfeitar um pouco vamos colocar uma linha separando o cabeçalho das linhas de detalhe.
Coloque um componente QRShape na faixa ColumnHeader
Mude a opção Width da propriedade Pen para 4. Isso vai engrossar a linha.
Mude a propriedade Shape para qrsHorLine. O componente QRShape tem várias formas pré-definidas. qrsHorLine é a
linha horizontal.
Estique a linha por toda extensão do relatório usando as âncoras.

Figura 36: Cabeçalho de Coluna

6 - LINHA DE DETALHE
Vamos desenhar a linha de detalhe na faixa Detail.
Coloque 4 componentes QRDBText na faixa Detail (um para cada coluna do relatório). Faça com que eles fiquem
grudados na parte superior da faixa.
Reduza a altura da faixa até não sobrar espaço entre os componentes e o fim da faixa. Se sobrar algum espaço, as
linhas de detalhe vão aparecer afastadas.
Mude a propriedade DataSet de cada componente QRDBText para tblCliente. Isso vai indicar a fonte dos dados.
Mude as propriedades DataField para os respectivos campos de cada coluna do relatório.
Na última coluna (Limite de Crédito) mude a propriedade Alignment para taRightJustify. Tradicionalmente os
números são alinhados à direita.
Na última coluna mude a propriedade AutoSize para False. Quando AutoSize é igual a True o campo é esticado ou
encolhido para caber o texto valor a ser impresso. O problema é que o AutoSize estica o campo fixando a posição da borda
esquerda, o que acaba desalinhando os campos alinhados à direita.
Coloque a máscara de edição ###,##0.00 na propriedade Mask.

Figura 37: Linha de Detalhe

7 - SUMÁRIO
Vamos desenhar o sumário do relatório na faixa Summary. Vamos colocar nessa faixa um totalizador para imprimir o
somatório dos limites de crédito.
Coloque na faixa Summary um componente QRExpression. Esse componente é um curinga que pode imprimir um
valor constante, um campo da tabela ou um valor calculado.
Mude as propriedades Alignment para taRightJustify e AutoSize para False.
Clique na propriedade Expression. Essa é a propriedade que contém a fórmula a ser calculada.
Digite a fórmula SUM(tblCliente.VALOR_CREDITO).
74
Para ver outras fórmulas clique no botão das reticências ao lado da propriedade Expression. Isso vai abrir o
Expression Wizard que vai ajudar a criar outras fórmulas.
Mude o Style da propriedade Font para Bold.
Coloque a máscara de edição ###,##0.00 na propriedade Mask.
Mude a propriedade Master para relCliente.
Toda fórmula que contém funções agregadoras (somatório, média, mínima, máxima, etc.) precisa de um Master. Esse
Master indica quando calcular (o que entra ou não no cálculo). O relCliente em Master indica que toda vez que uma linha de
detalhe for impressa, essa linha vai ser totalizada.
Coloque um QRLabel ao lado do QRExpr
Mude o Caption para Total:
Mude o Style da propriedade Font para Bold

Figura 38: Sumário

8 - RODAPÉ
Vamos desenhar o rodapé do relatório na faixa PageFooter.
Coloque um componente QRSysData na faixa PageFooter à esquerda. Esse componente é usado para imprimir
informações do sistema, tais como data, hora e número da página.
Mude a propriedade Data para qrsDate (data corrente).
Coloque outro componente QRSysData na faixa PageFooter à direita..
Mude a propriedade Data para qrsPageNumber (número da página).
Coloque um componente QRLabel próximo ao número da página.
Mude a propriedade Caption para Página:
Mude o Size da propriedade Font de todos os componentes do rodapé para 8
Para dar um toque final coloque mais uma linha separando o rodapé das linhas de detalhe, do mesmo jeito que foi
feito no cabeçalho das colunas.

Figura 39: Rodapé

9 - IMPRIMINDO COM QUICK REPORT


Agora que o relatório está desenhado, vamos colocar a opção de impressão no Form principal.
Abra o Form frmCliente
Inclua a Unit do relatório – Urelat – na cláusula uses
Inclua um botão na barra de ferramentas do Form. Se você esqueceu como fazer, veja o tópico Barra de Ferramentas
em Componentes visuais.
Coloque uma figura de impressora no botão. Veja o tópico Lista de Imagens no Componentes visuais.
Inclua uma opção Imprimir no menu. Veja o tópico Menu em Componentes visuais.
Inclua uma procedure para tratar o evento OnClick da opção Imprimir do menu.
Associe o evento OnClick do botão Imprimir à mesma procedure.
A procedure deve ficar assim:

unit Ucliente;
75
interface
uses
Windows, . . ., DBTables, Urelat;
...
procedure TfrmCliente.Imprimir1Click(Sender: TObject);
begin
frmRelatorio.relCliente.Preview;
end;
...

Observações:
 A unit do relatório (Urelat) é declarada na cláusula Uses.
 frmRelatorio é o nome do Form do relatório.
 relCliente é o nome do componente QuickRep no Form frmRelatorio.
 Preview é o comando que mostra o relatório no vídeo. Se quiser imprimir diretamente na impressora é só
substituir o comando Preview pelo Print.

Quando executar o programa você vai ver o relatório no vídeo assim:

Figura 40: Preview do Relatório

26. ARQUIVOS SEQUENCIAIS


Está certo. Com Delphi você tem todos os principais bancos de dados do mundo à sua disposição. Então porque você
iria querer manipular arquivos sequenciais ? Arquivos são como BomBril: Têm mil e uma utilidades.
Por exemplo: Os arquivos podem ser acessados por virtualmente todas as linguagens de programação. Por esse motivo
os arquivos costumam ser usados como interface entre aplicativos diferentes. De que outra forma, um aplicativo de
Contabilidade escrito em Cobol poderia importar dados de um aplicativo de Contas a Receber escrito em Delphi ?
Neste capítulo você vai aprender a manipular arquivos: ler, gravar, renomear, excluir, etc.

A) FUNÇÕES BÁSICAS
O Delphi vem com um conjunto de funções de manipulação de arquivos.

1 - RENOMEANDO UM ARQUIVO
A função RenameFile renomeia um arquivo, retornando True se o arquivo foi renomeado.

...
if RenameFile(‘ARQUIVO.OLD’, ‘ARQUIVO.NEW’) then
ShowMessage(‘Arquivo renomeado.’)
else
ShowMessage(‘Erro ao renomear arquivo’);
...

No exemplo, o arquivo "Arquivo.old" vai mudar de nome para "Arquivo.new".


Quando o PATH não é informado, o arquivo deve estar no diretório corrente.
76
Atenção: Quando é informado o PATH do nome antigo mas não é informado o PATH do nome novo, a função
RenameFile MOVE o arquivo para o diretório corrente.

...
RenameFile(‘C:\Windows\ARQUIVO.OLD’, ‘ARQUIVO.NEW’);
...

No exemplo, o arquivo chamado "C:\Windows\Arquivo.old" vai mudar de nome para "Arquivo.new" e vai mudar
para o diretório corrente (que pode até ser ou não o próprio C:\Windows)

2 - EXCLUINDO UM ARQUIVO
A função DeleteFile exclui um arquivo, retornando True se o arquivo foi excluído.

...
if DeleteFile(‘ARQUIVO.OLD’) then
  ShowMessage(‘Arquivo excluído.’)
else
ShowMessage(‘Erro ao excluir arquivo’);
...

No exemplo, o arquivo "Arquivo.old" vai ser excluído.


Quando o PATH não é informado, a função procura o arquivo no diretório corrente.

3 - COPIANDO UM ARQUIVO
O Delphi não tem nenhuma função para copiar arquivos mas você pode usar a função do próprio Windows.

...
if CopyFile(‘ARQUIVO.OLD’, ‘ARQUIVO.NEW’, True) then
ShowMessage(‘Arquivo copiado.’)
else
ShowMessage(‘Erro ao copiar arquivo’);
...

No exemplo, o arquivo "Arquivo.old" vai ser copiado para "Arquivo.new".


Quando o PATH do arquivo original não é informado, a função procura o arquivo no diretório corrente.
Quando o PATH do arquivo de destino não é informado, a função grava o arquivo no diretório corrente.
O terceiro parâmetro é do tipo booleano (True ou False) e indica o que fazer caso o arquivo de destino já exista.
Quando True e o arquivo de destino já existe, a função aborta a cópia. Quando False e o arquivo de destino já existe, a função
grava por cima.
Atenção: A função CopyFile não aceita variáveis do tipo string como parâmetros dos nomes dos arquivos. Aceita
somente variáveis do tipo Pchar. Quando necessário, faça o typecast.

...
var
strTmpArqOrig, strTmpArqDest: string;
...
if CopyFile(Pchar(strTmpArqOrig), Pchar(strTmpArqDest), True)
then
ShowMessage(‘Arquivo copiado.’)
else
ShowMessage(‘Erro ao copiar arquivo’);
...

Observe que as variáveis strTmpArqOrig e strTmpArqDest são do tipo string. Se não fosse feito o typecast
Pchar(strVariavelString) o compilador acusaria erro de incompatibilidade entre tipo de dado string e Pchar.

4 - TESTANDO SE UM ARQUIVO EXISTE


A função FileExists testa se um arquivo existe e retorna True se encontrou.
77
...
if FileExists(‘C:\ARQUIVO.TXT’) then
ShowMessage(‘Arquivo existe.’)
else
ShowMessage(‘Arquivo não existe.’);
...

5 - LENDO E GRAVANDO ARQUIVOS


Ler e gravar arquivos em Delphi é uma tarefa fácil. Para quem já conhece alguma versão anterior do Pascal é mais
fácil ainda porque não mudou praticamente nada.
Gravando um Arquivo Novo
Observe o exemplo abaixo. Neste exemplo estamos criando um arquivo novo (chamado ARQUIVO.NEW) e
gravando quatro registros com a mensagem "Hello World !".

...
var
tfArquivo: TextFile;
strRegistro: string;
x: integer;
begin
strRegistro := ‘Hello World !’;
AssignFile(tfArquivo, ‘c:\Windows\Temp\Arquivo.new’);
Rewrite(tfArquivo);
for x := 0 to 3 do
Writeln(tfArquivo, strTmpRegistro + ‘(‘ + IntToStr(x) + ‘)’);
CloseFile(tfArquivo);
end;
...

Primeiro, é preciso declarar uma variável do tipo arquivo. No exemplo, a variável tfArquivo é do tipo TextFile (um
arquivo texto).
Depois usa-se o comando AssignFile para associar um arquivo (no exemplo, "c:\Windows\Temp\Arquivo.new") à
variável declarada. A partir deste ponto, a variável tfArquivo representará o arquivo associado a ela. Usar uma variável não
associada a algum arquivo gera erro de I/O em tempo de execução.
O comando Rewrite regrava o arquivo. Em outras palavras, se o arquivo já existe, o Rewrite apaga e cria um novo
arquivo vazio.
Para gravar o conteúdo do arquivo, usa-se o comando Write ou Writeln. Os dois comandos gravam um string no
arquivo. A diferença é que o Writeln grava no final do string uma marca de LF/CR (Line Feed/Carriage Return). Esta marca
indica o fim do registro ou o fim de uma linha.
Para encerrar a gravação, deve-se fechar o arquivo com o comando CloseFile.

6 - GRAVANDO UM ARQUIVO JÁ EXISTENTE


Em muitas situações precisamos adicionar novas informações a um arquivo já existente. No exemplo abaixo estamos
incluindo mais registros ao arquivo criado anteriormente.

...
var
tfArquivo: TextFile;
strRegistro: string;
x: integer;
begin
strRegistro := ‘Olá Mundo !’;
AssignFile(tfArquivo, ‘c:\Windows\Temp\Arquivo.new’);
Append(tfArquivo);
for x := 0 to 3 do
Writeln(tfArquivo, strTmpRegistro + ‘(‘ + IntToStr(x) + ‘)’);
CloseFile(tfArquivo);
end;
...
78
A única diferença entre este e o exemplo anterior está na substituição do comando Rewrite pelo comando Append.
Enquanto o Rewrite cria um arquivo novo, o Append abre o arquivo e se prepara para gravar novos registros no fim do
arquivo. Se o arquivo não existir, ocorre um erro com a mensagem "File not found" em tempo de execução.

7 - LENDO UM ARQUIVO
Vamos agora ler o arquivo que foi gravado nos passos anteriores.

...
var
tfArquivo: TextFile;
strRegistro: string;
begin
AssignFile(tfArquivo, ‘c:\Windows\Temp\Arquivo.new’);
Reset(tfArquivo);
Readln(tfArquivo, strTmpRegistro);
while not Eof(tfArquivo) do
begin
ShowMessage(strTmpRegistro);
Readln(tfArquivo, strTmpRegistro);
end;
CloseFile(tfArquivo);
end;
...

Com o comando Reset o arquivo fica aberto para leitura.


O comando Readln lê um registro.
A função EOF (sigla de End Of File, fim de arquivo em ingl&ecircs) retorna True quando o arquivo chegou ao fim.

8 - GERANDO UM ARQUIVO HTML


Com essa tecnologia tão simples e antiga, é possível gerar páginas para internet com dados extraídos de qualquer
banco de dados. Pode até não ser o método mais fácil, mas está ao alcance de qualquer um com poucos conhecimentos de
HTML.
Vamos usar a conhecida tabela CLIENTE.DB para gerar uma página HTML com nome, telefone e contato de cada
cliente.
...
var
tfArquivo: TextFile;
strRegistro: string;
tblCliente: TTable;
begin
tblCliente := TTable.Create(nil);
tblCliente.DatabaseName := 'MEUALIAS';
tblCliente.TableName := 'CLIENTE.DB';

AssignFile(tfArquivo, 'C:\Windows\Temp\CLIENTE.html');
Rewrite(tfArquivo);

strRegistro :=
'<html><head> <title> Relação de Clientes </title> </head>';
Writeln(tfArquivo, strRegistro);

strRegistro :=
'<body><p align="center"> <font face="Arial"color="#FF0000">';
Writeln(tfArquivo, strRegistro);

strRegistro :=
'<big><big><big><big>Relação de Clientes </big></big></big></big>';
Writeln(tfArquivo, strRegistro);

strRegistro :=
'</font></p>';
79
Writeln(tfArquivo, strRegistro);

strRegistro := '<table border="1" width="100%">';


Writeln(tfArquivo, strRegistro);

strRegistro := ' <tr>';


Writeln(tfArquivo, strRegistro);

strRegistro := ' <td width="33%"><big>Nome</big></td>';


Writeln(tfArquivo, strRegistro);

strRegistro := ' <td width="33%"><big>Telefone</big></td>';


Writeln(tfArquivo, strRegistro);

strRegistro := ' <td width="34%"><big>Contato</big></td>';


Writeln(tfArquivo, strRegistro);

strRegistro := ' </tr>';

Writeln(tfArquivo, strRegistro);

tblCliente.Open;
while not tblCliente.EOF do
begin
strRegistro := ' <tr>';
Writeln(tfArquivo, strRegistro);
strRegistro :=
' <td width="33%"><font color="#400040"><small><font face="Arial">' +
tblCliente.FieldByName('NOME').Value +
'</font></small></font></td>';
Writeln(tfArquivo, strRegistro);

strRegistro :=
' <td width="33%"><font color="#400040"><small><font face="Arial">' +
tblCliente.FieldByName('TELEFONE').Value +
'</font></small></font></td>';
Writeln(tfArquivo, strRegistro);

strRegistro :=
' <td width="34%"><font color="#400040"><small><font face="Arial">' +
tblCliente.FieldByName('CONTATO').Value +
'</font></small></font></td>';
Writeln(tfArquivo, strRegistro);

strRegistro := ' </tr>';

Writeln(tfArquivo, strRegistro);

tblCliente.Next;
end;

tblCliente.Close;

strRegistro := '</table>';
Writeln(tfArquivo, strRegistro);

strRegistro := '<p>Documento gerado em ' + DateToStr(now) +


'</body></html>';
Writeln(tfArquivo, strRegistro);
CloseFile(tfArquivo);
end;
...
80
Os comandos de gravação de arquivos são idênticos aos já estudados nos exemplos anteriores. Os comandos de leitura
de tabelas do banco de dados também já são conhecidos.

Veja abaixo uma lista como os comandos HTML mais importantes usados neste exemplo. (Uma explicação detalhada
dos comandos HTML estão além do escopo deste curso).

Comando Descrição

<HTML> Início do arquivo HTML

<HEAD> Área de cabeçalho da página

<TITLE> Título da página que aparece na barra superior do browser.

<BODY> Corpo da página, que aparece na área de visualização do browser.

<TABLE> Declaração de tabela, semelhante às tabelas usadas no MS-Word. Não tem nada em comum com tabelas
de bancos de dados.

<BORDER> Declara o formato da borda da tabela.

<WIDTH> Indica a largura da tabela ou da coluna da tabela, de acordo com o escopo.

<TR> Declara uma linha da tabela.

<TD> Declara uma coluna da tabela.


Tabela 32: Comandos HTML

Este código vai gerar um arquivo CLIENTE.HTML que poderá ser aberto em um browser. Experimente.

27. ARQUIVOS INI


Arquivos INI são arquivos de configuração. São chamados assim porque têm a extensão *.ini. Cada programa pode
ter um ou mais arquivos INI que por sua vez podem conter uma infinidade de parâmetros.
Esses arquivos foram muito usados no tempo do Windows 3.x. A partir do Windows 95 foi introduzido o Registry,
um novo conceito em termos de configuração.
Com o advento do Registry, os arquivos INI deveriam ter sido aposentados, mas não foi isso o que aconteceu.
Existem programas que foram escritos no tempo do Windows 3.x e que usam arquivos INI até hoje.
Se você vai criar um programa novo, use o Registry, mas se você precisa fazer manutenção em programas antigos, é
bom saber como usar os arquivos INI.
Vamos ver neste capítulo como criar configurações usando arquivos INI.

A) ESTRUTURA DO ARQUIVO INI


Os arquivos INI são divididos em seções. Cada seção é dividida em chaves. Cada chave é um parâmetro que possui
um valor.
...
[windows]
load=
run=
NullPort=None
device=Epson Stylus COLOR 500,EPS500,LPT1:

[Desktop]
Wallpaper=(None)
TileWallpaper=0
WallpaperStyle=0
Pattern=(None)
81
...
O exemplo na página anterior é um trecho do arquivo WIN.INI que está no diretório do Windows.
As seções são declaradas entre colchetes (observe as seções [WINDOWS] e [DESKTOP]).
As chaves ficam dentro de uma seção (na seção Desktop as chaves são Wallpaper, TileWallpaper, WallpaperStyle e
Pattern)
Cada chave possui um valor (por exemplo, TileWallpaper=0).

1 - CLASSE TINIFILE
O Delphi tem uma classe chamada TiniFile, declarada na unit IniFiles, que faz manipulação de arquivos INI.

1.1 - Criando um Arquivo INI


Um arquivo INI não precisa ser criado. Ao inserir o valor em uma chave, o arquivo será criado automaticamente (se
ainda não existir).

1.2 - Criando uma Seção


Da mesma forma que o arquivo, uma seção não precisa ser explicitamente criada. Ao inserir o valor em uma chave, a
seção da chave será criada automaticamente (se ainda não existir).

1.3 - Gravando uma Chave


A classe TIniFile tem vários métodos para gravar chaves, um para cada tipo de dado.
O mesmo método pode ser usado para criar uma chave nova ou alterar o valor de uma chave já existente.

...
var
iniMeuArquivo: TIniFile;
begin
iniMeuArquivo := TIniFile.Create('C:\Windows\MEUINI.INI');
iniMeuArquivo.WriteString('MINHA SECAO', 'MINHA CHAVE', Edit1.Text);
iniMeuArquivo.Free;
end;
...

O método Create não cria o arquivo MEUINI.INI. Este método é o construtor da classe e apenas instancia a classe.
Este método recebe como parâmetro o nome do arquivo INI com o qual se quer trabalhar.
O método WriteString grava Edit1.Text como valor na chave "Minha chave" da seção "Minha seção".
O método WriteString cria tudo o que for necessário para guardar o valor da chave. Se o arquivo não existe, cria o
arquivo. Se a seção não existe, cria a seção. Se a chave não existe, cria a chave.
Atenção: Não esqueça de declarar a unit IniFiles na cláusula uses.
Métodos para gravar chaves com outros tipos de dados são: WriteBool (booleano), WriteInteger (número inteiro),
WriteFloat (ponto flutuante), WriteTime (hora), WriteDate (data), WriteDateTime (data e hora).
A única diferença entre esses métodos é o tipo de dado do terceiro parâmetro (o valor da chave), que muda de acordo
com o método.

1.4 - Lendo uma Chave


Tal qual a gravação, a classe TIniFile também tem diversos métodos para ler chaves, um para cada tipo de dado.

...
var
iniMeuArquivo: TIniFile;
begin
iniMeuArquivo := TIniFile.Create('C:\Windows\MEUINI.INI');
Label1.Caption := iniMeuArquivo.ReadString('MINHA SECAO', 'MINHA CHAVE', '{sem valor}');
iniMeuArquivo.Free;
end;
...

O método ReadString lê o valor na chave "Minha chave" da seção "Minha seção".


82
Caso a chave "Minha chave" ou a seção "Minha seção" não existam, o método ReadString retornará o valor default,
declarado como terceiro parâmetro. No exemplo o valor default é "{sem valor}".
Métodos para ler chaves com outros tipos de dados são: ReadBool (booleano), ReadInteger (número inteiro),
ReadFloat (ponto flutuante), ReadTime (hora), ReadDate (data), ReadDateTime (data e hora).
A única diferença entre esses métodos é o tipo de dado do terceiro parâmetro (o valor default), que muda de acordo
com o método.

1.5 - Apagando uma Chave


Às vezes é necessário apagar uma chave. Para isso, use o método DeleteKey.

...
var
iniMeuArquivo: TIniFile;
begin
iniMeuArquivo := TIniFile.Create('C:\Windows\MEUINI.INI');
iniMeuArquivo.DeleteKey('MINHA SECAO', 'MINHA CHAVE');
iniMeuArquivo.Free;
end;
...

1.6 - Apagando uma Seção


Para apagar a seção inteira, inclusive as chaves dentro dela, use o método EraseSection.

...
var
iniMeuArquivo: TIniFile;
begin
iniMeuArquivo := TIniFile.Create('C:\Windows\MEUINI.INI');
iniMeuArquivo.EraseSection('MINHA SECAO');
iniMeuArquivo.Free;
end;
...

O método EraseSection não apaga o arquivo INI, mesmo que a última seção tenha sido excluída.

28. IMPRIMINDO COM TPRINTER


Existem dúzias de geradores de relatórios mais ou menos integrados ao Delphi. O próprio Quick Report, o
ReportBuilder, o ReportSmith, etc. Teoricamente você jamais teria que se preocupar com os aspectos de baixo nível da
impressão, certo ? Errado.
O Quick Report é muito bom mas não é mágico; tem as suas limitações. Outros geradores de relatórios são muito
caros ou muito lentos e também não são perfeitos.
Quando não dá para usar um gerador de relatórios, o jeito é fazer impressão direta.

A) CLASSE TPRINTER
A classe TPrinter encapsula a interface do Windows com a impressora. Possui propriedades e métodos para
impressão.

1 - PROPRIEDADES

Propriedade Descrição

Canvas Representa a superfície da página. Possui métodos para escrever texto e desenhar figuras
geométricas. (Veja o tópico Classe TCanvas abaixo).
83
Fonts Lista com os nomes das fontes suportadas pela impressora selecionada. Tipo de dado: TString.

Orientation Determina em que sentido será impressa a página: poLandscape imprime na horizontal e poPortrait
imprime na vertical.

PageHeight Altura da página em número de pixels.

PageNumber Número da página corrente que está sendo impressa. É atualizado automaticamente.

PageWidth Largura da página em número de pixels.

PrinterIndex Seleciona em qual impressora o relatório será impresso. Este índice refere-se à propriedade Printers
(abaixo). Para selecionar a impressora padrão do sistema atribua o valor –1 ao PrinterIndex.

Printers Lista com todas as impressoras instaladas no Windows. A impressora selecionada é indicada pela
propriedade PrinterIndex. Tipo de dado: TString.

Title É o nome do relatório que vai aparecer no gerenciador de impressão. Tipo de dado: String
Tabela 33: Propriedades da classe TPrinter

2 - MÉTODOS

Propriedade Descrição

Abort Cancela a impressão de um relatório.

BeginDoc Inicia a impressão de um relatório. Tem que ser executado antes de começar a imprimir qualquer
coisa.

EndDoc Encerra a impressão de um relatório. Tem que ser executado ao fim da impressão.

NewPage Muda de página e incrementa a propriedade PageNumber.


Tabela 34: Métodos da classe TPrinter

B) CLASSE TCANVAS
Lembra do famoso "Plano Cartesiano" ? Aquele das coordenadas x e y ? Pois é. Agora você vai ver a utilidade prática
dessa coisa.
A classe TCanvas é um Plano Cartesiano. É com a classe TCanvas que o programa vai mandar para a impressora
textos, figuras geométricas e imagens.
A posição dos textos e figuras na página do relatório é determinada pelo sistema de pares ordenados (x, y). As
coordenadas são medidas em pixels. O topo da página, por exemplo, está nas coordenadas (0, 0).

1 - PROPRIEDADES

Propriedade Descrição

Brush Configura o "pincel" usado para pintar o fundo das figuras geométricas: Cor e estilo. Tipo de dado:
TBrush.

Font Configura a fonte usada para imprimir o texto: Nome da fonte, cor, tamanho, estilo, etc. (Não
confunda com a propriedade Fonts do TPrinter.) Tipo de dado: TFont.

Pen Configura a "caneta" usada para desenhar linhas soltas e as linhas que delimitam a parte externa de
84
figuras: Cor, largura, estilo, etc. Tipo de dado: TPen.

PenPos Indica a posição corrente da caneta, onde o próximo texto ou figura será impresso. Tipo de dado:
TPoint.
Tabela 35: Propriedades da classe TCanvas

2 - MÉTODOS

Propriedade Descrição

Rectangle Desenha um retângulo preenchendo-o com o padrão definido na propriedade Brush.

LineTo Desenha uma linha entre o ponto determinado por PenPos e o ponto passado como parâmetro.
Geralmente é usado em conjunto com MoveTo.

MoveTo Muda a posição corrente (PenPos) para o ponto passado como parâmetro.

TextOut Imprime um string na posição passada como parâmetro.


Tabela 36: Métodos da classe TCanvas

C) PRATICANDO A IMPRESSÃO COM TPRINTER


Vamos imprimir um relatório usando a impressão com TPrinter. Vai ser um relatório simples, do tipo que qualquer
gerador de relatórios pode fazer.
A impressão direta já é, por si só, uma coisa um pouco complicada. A idéia é simplificar o exemplo para não
complicar a explicação, certo ?

Definição do Relatório:

Imprimir o cadastro de clientes usando a tabela CLIENTE.DB.


Vamos começar ...
Seção Interface
Crie um projeto novo.
Na cláusula uses declare a unit Printers.
Coloque no Form um botão.
Coloque no Form um componente TTable.
Na propriedade DatabaseName coloque o alias MEUALIAS.
Na propriedade TableName coloque a tabela CLIENTE.DB.
Declare todos os fields da tabela (Clique com o botão direito do mouse sobre o TTable; selecione "Fields Editor" no
menu pop-up; clique com o botão direito do mouse na janela "Form1.Table1"; clique na opção "Add Fields" do menu pop-up;
selecione todos os campos na lista "Available Fields" e clique no botão OK.).
Na parte private do Form, declare a variável intPrivLinhaPixel, os procedimentos AbrirRelatorio, ImprimirCabecalho,
ImprimirDetalhe, ImprimirRodape, FecharRelatorio e a função Fator. (A finalidade de cada declaração será vista mais tarde.)

unit Unit1;
interface
uses . . ., Printers;

type
TForm1 = class(TForm)
Button1: TButton;
Table1: TTable;
Table1CODIGO: TintegerField;
Table1CGC: TStringField;
Table1NOME: TStringField;
Table1CONTATO: TStringField;
Table1TELEFONE: TStringField;
Table1VALOR_CREDITO: TFloatField;
85
Table1LOGRADOURO: TstringField;
Table1COMPLEMENTO: TstringField;
Table1CIDADE: TStringField;
Table1ESTADO: TStringField;
Table1CEP: TStringField;
Table1STATUS: TStringField;
Table1LUXO: TBooleanField;
Table1PECHINCHA: TbooleanField;
Table1UTIL: TBooleanField;
var
 private
   intPrivLinhaPixel: integer;

   procedure AbrirRelatorio;
   procedure ImprimirCabecalho;
   procedure ImprimirDetalhe;
   procedure ImprimirRodape;
   procedure FecharRelatorio;
   function Fator(intParmOperando: integer):
    integer;
...

1 - EVENTO ONCLICK
Crie um procedimento para responder ao evento OnClick do botão. O procedimento deve conter o seguinte código:

...
procedure TForm1.Button1Click(Sender: TObject);
begin
AbrirRelatorio;
ImprimirCabecalho;

Table1.Open;
while not Table1.EOF do
begin

if intPrivLinhaPixel > 3400 then


begin
ImprimirRodape;
Printer.NewPage;
ImprimirCabecalho;
end;

ImprimirDetalhe;

Table1.Next;
end;

ImprimirRodape;
FecharRelatorio;
end;
...

Este procedimento lê cada linha da tabela e imprime o relatório.


É necessário um procedimento para abrir e outro para fechar o relatório (que serão explicados abaixo).
A variável intPrivLinhaPixel guarda o número em pixels da próxima linha a ser impressa. Quando esse número
ultrapassa 3400 está na hora de mudar de página.
Entre o rodapé de uma página e o cabeçalho de outra, há o comando "Printer.NewPage". Esse comando faz a
impressora mudar de página.
Pergunta: De onde surgiu esse Printer ?
Resposta: Printer é uma instância da classe TPrinter. Você não precisa declarar e nem instanciar a classe TPrinter. O
próprio Delphi faz isso automaticamente quando encontra a unit Printers declarada na cláusula uses.
86
2 - PROCEDIMENTO ABRIRRELATORIO
O procedimento deve conter o seguinte código:

...
procedure TForm1.AbrirRelatorio;
begin
Printer.Title := 'Relatório de Clientes';
Printer.PrinterIndex := -1;
Printer.Orientation := poPortrait;

Printer.BeginDoc;

Printer.Canvas.Font.Name := 'Courier New';


Printer.Canvas.Font.Size := Fator(8);
Printer.Canvas.Font.Style := [];
Printer.Canvas.Font.Color := clBlack;

intPrivLinhaPixel := 0;
end;
...

Printer.Title é o título que vai aparecer no Gerenciador de Impressão.


Atribuir –1 ao Printer.PrinterIndex faz com que a impressora default do sistema seja selecionada.
Atribuir poPortrait ao Printer.Orientation faz imprimir o relatório na posição vertical. Para imprimir na horizontal,
atribua o valor poLandscape.
O comando Printer.BeginDoc inicia a impressão.
As características da fonte a ser usada (nome, estilo, tamanho e cor) são atribuídas ao Printer.Canvas.Font
O estilo da fonte pode ser qualquer combinação entre os valores: fsItalic, fsBold, fsUnderline. Por exemplo, para que
a fonte fique em negrito e sublinhada, atribua [fsBold, fsUnderline] ao Printer.Canvas.Font.Style.
Existem várias cores pré-declaradas, como por exemplo: clBlue, clRed, clGray, clGreen, etc. Para uma relação
completa, consulte o tipo de dado TColor na documentação do Delphi.

3 - PROCEDIMENTO FECHARRELATORIO
O procedimento deve conter o seguinte código:

...
procedure TForm1.FecharRelatorio;
begin
Printer.EndDoc;
end;
...

O relatório fica retido na fila da impressora até que seja liberado. O comando que libera o relatório da fila é o
Printer.EndDoc.
Para abortar o relatório, use o comando Printer.Abort.

4 - FUNÇÃO FATOR
Você já sabe que para localizar um ponto sobre a "superfície" do papel, precisa-se de um par ordenado (x, y), onde x e
y representam a coluna e a linha.
A unidade de medida usada pela classe TCanvas é o pixel. O problema é que cada modelo de impressora tem uma
resolução diferente do outro. E daí ? Daí que o ponto (x1, y1) em um modelo de impressora não fica no mesmo lugar que em
outro.
Em outras palavras, quando o relatório é impresso em uma impressora com resolução diferente daquela na qual o
programa foi desenvolvido, o relatório sai torto, desproporcional, às vezes pequeno demais, outras vezes tão grande que
ultrapassa os limites da folha de papel.
Para minimizar esse problema, todas as coordenadas, tamanhos, e comprimentos devem ser calculados
proporcionalmente em função da resolução da impressora.
O problema é: "Se um ponto fica na coluna 100 na impressora que tem 2.880 pixels de largura, em que coluna esse
ponto deveria ficar numa impressora com 1.660 pixels ?" Para resolver esse problema, é só usar a regra de três.
87
É isso que a função Fator faz.

...
function TForm1.Fator(intParmOperando: integer): integer;
var
intTmpOperando: integer;
douTmpFatorHeight: double;
douTmpFatorWidth: double;
begin
douTmpFatorHeight := Printer.PageHeight / 3969;
douTmpFatorWidth := Printer.PageWidth / 2880;

if douTmpFatorHeight < douTmpFatorWidth then


intTmpOperando := Trunc(intParmOperando * douTmpFatorHeight)
else
intTmpOperando := Trunc(intParmOperando * douTmpFatorWidth);

if intTmpOperando = 0 then
intTmpOperando := 1;

Result := intTmpOperando;
end;
...

Nos testes do programa de exemplo, foi usada uma impressora Epson Stylus Color 500, com 2.880 pixels de largura
por 3.969 de altura.
Printer.PageHeight e Printer.PageWidth são, respectivamente, a altura e a largura em pixels da "superfície" de
impressão da impressora selecionada.
São calculados dois fatores, um para altura e outro para largura. Vale o menor deles.
O operando (que pode ser uma coluna, linha, comprimento, etc.) é multiplicado pelo fator. O resultado da função é o
operando proporcional ao fator.
Esta solução não é cem por cento segura e existem muitas outras formas de resolver o mesmo problema. Você deve
procurar a solução mais adequada ao seu problema.

5 - PROCEDIMENTO IMPRIMIRCABECALHO
O procedimento deve conter o seguinte código:

...
procedure TForm1.ImprimirCabecalho;
var
intTmpPos: integer;
strTmpTexto: string;
rectTmpBmp: TRect;
bmpTmpBitmap: TBitmap;
begin

// Imprimir bitmap
if FileExists('C:\Windows\Circles.bmp') then
begin
bmpTmpBitmap := TBitmap.Create;
bmpTmpBitmap.LoadFromFile('C:\Windows\Circles.bmp');

rectTmpBmp.Top := Fator(100);
rectTmpBmp.Bottom := Fator(350);
rectTmpBmp.Left := Fator(100);
rectTmpBmp.Right := Fator(300);

Printer.Canvas.StretchDraw(rectTmpBmp, bmpTmpBitmap);
bmpTmpBitmap.Free;
end;

// Imprimir texto
Printer.Canvas.Font.Color := clBlack;
88
Printer.Canvas.Font.Size := Fator(16);
Printer.Canvas.Font.Style := [fsBold];

strTmpTexto := 'Relatório de Clientes';


intTmpPos := (2870 – Printer.Canvas.TextWidth(strTmpTexto)) div 2;
Printer.Canvas.TextOut(Fator(intTmpPos), Fator(150), strTmpTexto);

strTmpTexto := 'Impresso Diretamente por TPrinter';


intTmpPos := (2870 – Printer.Canvas.TextWidth(strTmpTexto)) div 2;
Printer.Canvas.TextOut(Fator(intTmpPos), Fator(250), strTmpTexto);

// Imprimir as linhas
Printer.Canvas.Pen.Width := Fator(12);
Printer.Canvas.MoveTo(Fator(100), Fator(400));
Printer.Canvas.LineTo(Fator(2800), Fator(400));

Printer.Canvas.Pen.Width := Fator(4);
Printer.Canvas.MoveTo(Fator(100), Fator(425));
Printer.Canvas.LineTo(Fator(2800), Fator(425));

intPrivLinhaPixel := 460;
end;
...

Para imprimir um bitmap: Instancie a classe TBitmap; carregue o arquivo com o bitmap desejado; declare a posição
onde o bitmap deve ser impresso numa variável do tipo TRect e mande imprimir com o comando
Printer.Canvas.StrechDraw.
Para imprimir um string centralizado: Defina a fonte (nome, tamanho, estilo e cor) usando Printer.Canvas.Font;
Calcule a coluna em pixels onde o texto deve ser impresso (use o método Printer.Canvas.TextWidth para obter o tamanho do
string a ser impresso); imprima o string com o método Printer.Canvas.TextOut.
Para imprimir uma linha horizontal: Defina a largura da "caneta", para desenhar uma linha mais grossa ou mais fina,
usando a propriedade Printer.Canvas.Pen.Width; posicione a "caneta" no início da linha com o método
Printer.Canvas.MoveTo; desenhe a linha com o método Printer.Canvas.LineTo.
Nos métodos da classe TCanvas que recebem uma coordenada, o primeiro parâmetro é a coluna e o segundo a linha.
Ex.: Printer.Canvas.MoveTo(100, 200) Move a "caneta" para a coluna 100 na linha 200.

6 - PROCEDIMENTO IMPRIMIRDETALHE
O procedimento deve conter o seguinte código:

...
procedure TForm1.ImprimirDetalhe;
var
strTmpTexto: string;
begin

// Imprimir um retângulo
Printer.Canvas.Brush.Color := clSilver;
Printer.Canvas.Pen.Width := Fator(1);

Printer.Canvas.Rectangle(Fator(100), Fator(intPrivLinhaPixel), Fator(2800),


Fator(intPrivLinhaPixel + 100));

// Imprimir um string dentro do retângulo


Printer.Canvas.Font.Color := clBlue;
Printer.Canvas.Font.Style := [fsBold];
Printer.Canvas.Font.Size := Fator(12);

strTmpTexto := Table1NOME.Value;
Printer.Canvas.TextOut(Fator(110), Fator(intPrivLinhaPixel + 10), strTmpTexto);

intPrivLinhaPixel := intPrivLinhaPixel + 130;

// Retornar a configuração original


89
Printer.Canvas.Brush.Color := clWhite;
Printer.Canvas.Font.Color := clBlack;
Printer.Canvas.Font.Style := [];
Printer.Canvas.Font.Size := Fator(8);

// Imprimir detalhes
strTmpTexto := 'Endereço: ' + Table1LOGRADOURO.Value;
Printer.Canvas.TextOut(Fator(100), Fator(intPrivLinhaPixel), strTmpTexto);
strTmpTexto := 'Compl.: ' + Table1COMPLEMENTO.Value;
Printer.Canvas.TextOut(Fator(1500), Fator(intPrivLinhaPixel), strTmpTexto);

intPrivLinhaPixel := intPrivLinhaPixel + 60;

strTmpTexto := 'Cidade..: ' + Table1CIDADE.Value;


Printer.Canvas.TextOut(Fator(100), Fator(intPrivLinhaPixel), strTmpTexto);
strTmpTexto := ' UF: ' + Table1ESTADO.Value;
Printer.Canvas.TextOut(Fator(1500), Fator(intPrivLinhaPixel), strTmpTexto);
strTmpTexto := 'CEP: ' + Table1CEP.Value;
Printer.Canvas.TextOut(Fator(2000), Fator(intPrivLinhaPixel), strTmpTexto);

intPrivLinhaPixel := intPrivLinhaPixel + 70;


end;
...

Para imprimir um retângulo: Defina a cor de fundo do retângulo com a propriedade Printer.Canvas.Brush.Color;
defina a largura da "caneta" para desenhar a borda do retângulo com a propriedade Printer.Canvas.Pen.Width; desenhe o
retângulo com o método Printer.Canvas.Rectangle. Esse método recebe como parâmetros dois pares ordenados. O primeiro
indica o ponto superior esquerdo do retângulo e o segundo, o ponto inferior direito.
Para imprimir um string dentro do retângulo: Defina a cor, o tamanho e o estilo da fonte do string a ser impresso com
a propriedade Printer.Canvas.Color; imprima o string usando o método Printer.Canvas.TextOut passando como
coordenada um ponto dentro do retângulo.
Retornar a configuração original: Depois de modificar a configuração (fonte, brush, etc.) para imprimir uma figura ou
um texto em destaque, a configuração deve ser refeita para retornar aos valores originais.

7 - PROCEDIMENTO IMPRIMIRRODAPE
O procedimento deve conter o seguinte código:

...
procedure TForm1.ImprimirRodape;
var
strTmpTexto: string;
begin
// Imprimir as linhas
Printer.Canvas.Pen.Width := Fator(4);
Printer.Canvas.MoveTo(Fator(100), Fator(3700));
Printer.Canvas.LineTo(Fator(2800), Fator(3700));

Printer.Canvas.Pen.Width := Fator(12);
Printer.Canvas.MoveTo(Fator(100), Fator(3725));
Printer.Canvas.LineTo(Fator(2800), Fator(3725));

// Imprimir o texto
Printer.Canvas.Font.Color := clGray;
Printer.Canvas.Font.Size := Fator(8);
Printer.Canvas.Font.Style := [fsBold];

strTmpTexto := 'Página: ' + IntToStr(Printer.PageNumber);


Printer.Canvas.TextOut(Fator(100), Fator(3770), strTmpTexto);

strTmpTexto := 'Data: ' + DateToStr(Date);

Printer.Canvas.TextOut(Fator(2400), Fator(3770), strTmpTexto);


90
intPrivLinhaPixel := 0;
end;
...

O rodapé do relatório consiste de duas linhas paralelas (semelhantes às usadas no cabeçalho), a data da impressão e o
número da página.
Para obter o número da página, use a propriedade Printer.PageNumber.
 

29. EXPERTS
Fast-food da programação. É isso o que são os experts. O Delphi é capaz de gerar em instantes programas para
diversas finalidades: Banco de dados, relatórios, etiquetas, etc. Tal qual fast-food, os programas gerados pelos experts ficam
prontos rapidamente e até funcionam, mas falta alguma substância. Não deixe de complementá-los com aquele tempero que só
um programador humano pode dar.

A) DATABASE FORM WIZARD


É o expert para criar Forms de banco de dados com inclusão, alteração, exclusão e consulta.
Vamos criar um projeto novo para atualização da tabela de clientes.
Clique na opção "File --> New" do menu do Delphi
O Delphi vai mostrar a janela New Items
Clique na aba Business
Clique no ícone Database Form Wizard
Clique no botão "OK"
Outra maneira de fazer a mesma coisa é ir direto à opção do menu "Database --> Form Wizard".

1 - PRIMEIRA JANELA:
Nessa janela você vai informar as características básicas do Database Form.
Escolha a opção "Create a simple form" porque vamos trabalhar com uma única tabela.
Escolha a opção "Create a form using TTable objects" porque vamos trabalhar com o componente Table e não com
Query.
Clique no botão "Next"

2 - SEGUNDA JANELA:
Aqui você vai informar para qual tabela o Database Form vai ser criado.
Selecione o alias MEUALIAS no combo box "Driver or alias name"
Selecione a tabela CLIENTE.DB na lista de tabelas "Table Name"
Clique no botão "Next"

3 - TERCEIRA JANELA:
Os campos que vão aparecer no Form são selecionados aqui.
Selecione todos os campos
Clique no botão "Next"

4 - QUARTA JANELA:
A disposição dos campos no Form pode ser horizontal, vertical ou em forma de grid.
Selecione "Horizontally"
Clique no botão "Next"

5 - QUINTA JANELA:
Aqui pode-se optar pela criação de um Data Module (o Data Module não foi tratato neste livro) e se o form criado vai
ser o form principal do projeto.
91
Marque a opção "Generate a main form"
Selecione "Form only"
Clique no botão "Finish"
O resultado é um form pronto, completamente funcional. As únicas restrições são a ausência de qualquer consistência
dos dados e o uso de DBEdit para qualquer tipo de campo. Essas restrições são vencidas com um mínimo de esforço porque o
form gerado pelo Database Form Wizard pode ser alterado ao gosto do freguês.

Figura 41: Database Form Wizard


 

B) QUICK REPORT WIZARD


É o expert para criar relatórios com Quick Report.
Vamos usar o mesmo projeto criado no tópico Database Form Wizard para a prática do Quick Report Wizard.
Abra o projeto do Database Form Wizard (se não estiver aberto)
Clique na opção "File --> New" do menu do Delphi
O Delphi vai mostrar a janela New Items
Clique na aba Business
Clique no ícone Quick Report Wizard
Clique no botão "OK"

1 - PRIMEIRA JANELA:
Nessa janela você vai informar o estilo do relatório.
Selecione List Report
Clique no botão "Start Wizard"

2 - SEGUNDA JANELA:
Aqui você vai informar para qual tabela o relatório vai ser criado.
Selecione o alias MEUALIAS no combo box "Alias or directory"
92
Selecione a tabela CLIENTE.DB no combo box "Table name"
Selecione os campos Nome, Contato, Telefone e Valor do crédito na lista "Available fields"
Clique no botão "Finish"
O resultado é bastante parecido ao alcançado em Relatório, quando o relatório foi desenhado à mão.
Podemos agora incluir no form gerado pelo Database Form Wizard um botão para imprimir o relatório.
Coloque um componente Button no Form gerado pelo Database Form Wizard
Inclua a unit do Form do relatório na cláusula uses
Crie uma procedure para responder ao evento OnClick do botão
Inclua dentro da procedure o comando Form3.QuickRep1.Preview; onde Form3 é o nome do Form do relatório,
QuickRep1 é o nome do componente QuickRep no Form3 e Preview é o comando para mostrar o relatório no vídeo.
 

C) OUTROS WIZARDS
Existem muitos outros wizards. Use-os à vontade, mas lembre-se: Por mais que você goste de fast-food não dá para
viver só disso. O programador humano ainda tem muito trabalho.

30. LOCALIZAÇÃO
Antigamente a palavra "localizar" significava "Tornar local; fixar ou limitar a determinado lugar" - obrigado, Aurélio!
Hoje existe mais um significado: "Traduzir os labels e mensagens de um programa para a língua nativa de um país". Você já
deve ter visto que muitas mensagens que um programa escrito em Delphi emite aparecem em inglês. Mesmo se todos os
usuários fossem fluentes em inglês acho que nós devemos prestigiar a nossa língua portuguesa.

A) UNITS DE CONSTANTES
Muitas das mensagens que um programa em Delphi mostra são tiradas de units de constantes. São units que só contêm
variáveis do tipo constante. Para traduzir as mensagens é só mudar os strings dentro dessas units.
Quando o Delphi é instalado as units de constantes são postas no diretório C:\Program Files\Borland\Delphi4\Source\
Vcl. As units de constantes são bdeconst.pas, consts.pas, dbconsts.pas, oleconst.pas, stdactns.pas.
Use o editor de textos do próprio Delphi ou mesmo o Notepad para editar e traduzir as strings. Não tenha medo de
danificar as units. Se alguma coisa sair errada você pode recuperar as units originais no próprio CD-ROM do Delphi.
Depois de traduzidas coloque as units no diretório C:\Program Files\Borland\Delphi4\Lib
Agora é só recompilar os seus programas e as mensagens vão aparecer traduzidas.

31. COMPONENTES
Pelas suas andanças na internet você vai encontrar sites cheinhos de componentes novos e, muitas vezes, grátis. É só
baixar e instalar.
Antes de sair por aí baixando e instalando tudo o que você vir por aí, cabe uma palavra de cautela. Se esses
componentes são tão bons e tão úteis, porque são grátis ? Quem garante que não contêm bugs ou mesmo código nocivo (um
vírus ou coisa parecida) ? Até hoje não foi reportado nenhum caso de vírus transmitido desse jeito mas … como já dizia minha
avó: "Seguro morreu de velho. Precavido ainda está vivo."

A) RECEITA DE INSTALAÇÃO
Copie o componente ISIComboBox.pas (486 bytes) para um diretório qualquer no seu winchester (ex.: C:\
DELPHILAB\COMPONENTE).
Esse componente é um combo box comum, não faz nada que o ComboBox normal não faça; serve só para
treinamento de instalação de componentes.
Feche todos os arquivos abertos no Delphi clicando no menu "File --> Close all"
Clique na opção do menu "Component --> Install component"
Aparece a janela Install Component
Clique no botão "Browse" ao lado da caixa de edição "Unit File Name"
Aparece a janela "Unit File Name"
Os componentes podem ser distribuídos em forma de Delphi Unit (*.pas) ou Delphi Compiled Unit (*.dcu). Selecione
o tipo de arquivo apropriado ao componente que você quer instalar. O componente ISICombobox está em formato *.pas.
Selecione Delphi Unit (*.pas)
93
Procure o diretório onde você gravou o ISIComboBox.pas
Selecione o arquivo ISIComboBox.pas
Clique no botão "OK"
Clique novamente no botão "OK"
O componente ISIComboBox deve estar na aba "Samples" da palheta de componentes. Note que cada componente
pode aparecer em uma aba diferente ou mesmo criar uma nova aba. A aba do componente é definida no comando
RegisterComponents da procedure Register.  

32. TYPECAST
Delphi é uma linguagem fortemente tipada. Cada variável, cada expressão constante, tudo tem um tipo de dado. Por
um lado isso é bom porque impede erros de programação comuns. Por outro lado às vezes você realmente precisa atribuir ou
comparar variáveis com tipos de dados incompatíveis entre si. Daí a necessidade de typecast.
Grosso modo, typecast é a capacidade de um tipo de dado fingir que é outro.

A) TYPECAST POR TIPO DE DADO


Typecast por tipo de dado é a transformação de uma expressão constante ou uma variável de um tipo de dado em
outro tipo de dado.

1 - BOOLEAN
if boolean(1)
  then ShowMessage(‘O número 1 é True’);

O comando boolean(1) converte a expressão constante 1 no valor booleano correspondente.

2 - INTEGER
ShowMessage('O código ASCII para a letra A é ' +
  IntToStr(Integer('A')));

O comando Integer('A') converte a expressão constante 'A' no valor inteiro correspondente.


Note que Integer('A') é diferente de StrToInt('A').
Integer('A') retorna 65 e StrToInt('A') resulta em erro porque a expressão ‘A’ não contém um número válido.

3 - CHAR
ShowMessage('O código ASCII 72 é a letra ' + Char(72));

O comando Char(72) converte a expressão constante 72 no caracter correspondente.

4 - CHECKED TYPECAST
Checked typecast usa os operadores is e as.
is é o operador usado para checar qual o tipo de dado de uma variável.
as é o operador usado para converter o tipo de dado de uma variável.

...
procedure TForm1.Button1Click(Sender: TObject);
begin
  if Sender is TButton then
     (Sender as TButton).Caption := ‘É UM BOTÃO’;
end;
...

Sender is TButton testa se Sender é um TButton.


(Sender as TButton).Caption é a propriedade Caption do TButton Sender. Colocar Sender.Caption não funciona
porque Sender é do tipo TObject e TObject não tem a propriedade Caption.
94
 

5 - OUTRAS FUNÇÕES
Existem outras funções que convertem tipos de dados. As funções envolvendo strings foram discutidas na página
Manipulação de Strings.

Função Descrição

Trunc Converte número real em inteiro truncando a parte fracionária. Ex.: Trunc(12.9) retorna 12

Round Converte número real em inteiro arredondando. Ex.: Round(12.9) retorna 13

6 - FIELDS
As variáveis do tipo Field – vistas na página Banco de Dados – também têm a sua forma de typecast.
Normalmente o valor de um Field é obtido através da propriedade Value

...
Edit1.Text := Table1NOME.Value;
...

O campo nome é do tipo string, por isso é compatível com a propriedade Text do Edit1. E se o campo fosse de outro
tipo de dado ?

...
Edit1.Text := Table1DATA_NASCIMENTO.AsString;
...

O campo data de nascimento é do tipo Date e não é compatível com a propriedade Text. O typecast é feito pela
propriedade AsString, que converte o Value em string.
 

33. DEBUG
"Desculpe a nossa falha." Esse parece ser o lema dos programadores, tal é o número de bugs que infestam os
programas. Por outro lado parece impossível desenvolver um projeto com mais de 50 mil linhas de código sem nenhum erro.
Como resolver esse problema ? Ou pelo menos reduzí-lo ? O Delphi tem algumas ferramentas muito úteis para debug.
Vamos usá-las.

A) PASSO A PASSO
Executar um programa passo a passo ajuda a ver o programa em ação, ver por onde ele está passando e ver onde está
o problema.
Abra o projeto que você quer debugar e use a opção do menu "Run --> Trace Into" ou a tecla F7 ou o botão da barra
de ferramentas "Trace Into".
A linha do programa que vai ser executada aparece marcada em azul com uma seta verde ao lado.

B) DIRETO AO PONTO
Quando você já sabe mais ou menos onde está o problema, ou ao menos em que procedure o problema acontece, você
pode ir direto ao ponto.
Abra no editor de texto no ponto onde você quer suspender a execução do programa. Marque uma linha de código
com um clique na barra do lado esquerdo do editor de texto. A linha marcada aparece em vermelho. Marque quantas linhas
você quiser.
O programa vai suspender a execução no momento em que passar pela linha marcada. Depois você pode continuar a
execução com a tecla F7 (para continuar passo a passo) ou F9 (para continuar direto, sem interrupções até a próxima linha
marcada.
95

Figura 42: Suspendendo a execução em um ponto do programa

Quanto vales ?
Para saber o valor de uma variável em tempo de execução, suspenda a execução do programa no ponto onde você
quer ver o valor da variável (marcando uma linha ou usando o Trace Into). Quando o programa for suspenso no ponto
desejado, pare o cursor sobre a variável. O valor vai aparecer em um "hint".
Também é possível usar o velho método do Watch. Clique na opção do menu "Run --> Add Watch" ou "Ctrl+F5".
Digite o nome da variável na caixa de edição Expression e clique OK. Vai aparecer uma janela com a lista de watches
definidos e os respectivos valores. Você pode definir quantos watches quiser.

Figura 43: Watch

1 - MUDANDO O VALOR
Você pode mudar o valor de uma variável manualmente em tempo de execução.
Suspenda a execução do programa no ponto em que você quer mudar o valor da variável.
Clique na opção do menu "Run --> Evaluate / Modify".
Vai aparecer a janela Evaluate/Modify.
Digite o nome da variável que você quer modificar na caixa de edição Expression e clique no botão "Evaluate".
96
O valor da variável vai aparecer na caixa de edição Result.
Digite o novo valor da variável na caixa de edição New Value e clique no botão "Modify".
Pronto. Agora o valor da variável é o que você digitou.

Figura 44: Evaluate / Modify


 

Você também pode gostar