Escolar Documentos
Profissional Documentos
Cultura Documentos
Índice
4.1 Comentários.................................................................................................... 29
4.2 Declarações..................................................................................................... 29
4.3 O Ponto-e-Vírgula e o Ponto .......................................................................... 30
4.4 Diretivas de Compilação ................................................................................ 31
4.5 Operadores...................................................................................................... 31
4.6 Principais Tipos de Dados .............................................................................. 34
4.6.1 Tipos de Dados Simples ......................................................................... 34
4.6.2 Tipos Estruturados.................................................................................. 39
4.6.3 Tipos Procedurais ................................................................................... 46
4.6.4 Variants................................................................................................... 49
4.6.5 Classes .................................................................................................... 50
4.6.6 Referências de Classe (metaclasses) ...................................................... 53
4.6.7 Interfaces ................................................................................................ 54
4.7 Comandos da Delphi Language...................................................................... 57
4.7.1 Comando de Decisão .............................................................................. 57
4.7.2 Case < X > of.......................................................................................... 60
4.7.3 While . . . do ........................................................................................... 61
4.7.4 For . . . do................................................................................................ 61
4.7.5 Break e Continue .................................................................................... 63
4.7.6 Repeat ..................................................................................................... 64
possível. Em muitos aspectos então, Borland é para o Pascal o que a Sun é para o
Java.
nota: O grid de tamanho 4x4 como o da figura é uma boa opção, pois permite uma boa
visão do alinhamento dos componentes sem ser demasiadamente pequeno
nota: a princípio, não desmarque o auto create forms & data modules para evitar
problemas. Se não desejar que os forms sejam criados automaticamente, vá à tela acima
e retire-os da lista dos forms que são criados automaticamente. Aliás, jamais deixe que o
Delphi crie todos os formulários. Deixe para criá-los apenas quando forem necessários e
destrua-os quando terminar de usar. Assim, o programa se torna mais leve e não
consumirá recursos e memória sem necessidade!
Na janela maior, que é o editor propriamente dito, podemos abrir várias Units
ao mesmo tempo, como na figura, para trabalharmos com o código de diversos
formulários simultaneamente. Assim como o Form Designer, o Code Editor também
pode ser personalizado, bastando acessar o menu Tools > Editor Options. Não
mencionaremos todas as configurações possíveis aqui, porque muitas delas já estão
ótimas como estão e devem ser deixadas em paz, e também para não nos
aprofundarmos sem necessidade em assuntos menos importantes. Abaixo, vemos a
palheta Color das propriedades do editor, onde configuramos as cores dos elementos
do código-fonte:
nota: o Delphi 7, por default, configura Strings, comentários e números com a mesma cor
– a Navy. Usar cores diferentes, não importam quais, para estes elementos torna o código
mais fácil de ler, destacando cada tipo diferente de elemento. Assim, não se corre o risco
de comentários serem confundidos com strings, strings numéricas se confundirem com
números verdadeiros, etc.
estamos para criar. Assim, podemos reutilizar outros eventos ao invés de implementar o
mesmo código várias vezes. Um evento é compatível com outros desde que possuam os
mesmos parâmetros – com os mesmos tipos de dados, mesma ordem e mesma
quantidade, ou seja, se suas assinaturas forem as mesmas.
O Object Inspector pode ser customizado pelo usuário no menu Tools >
Environment options > Object Inspector, mostrado abaixo:
• Standard
Nela estão os componentes básicos de uma interface gráfica: Edit, Button,
ComboBox, RadioButton, CheckBox, MainMenu... Sem dúvida é a mais usada.
• Additional
Sob certos aspectos é semelhante à Standard, mas possui componentes de
interface mais incrementados como BitBtn, SpeedButton, MaskEdit e StaticText.
Além disso, é nela que estão componentes de imagem (Image) e de gráficos
(Chart)
• Win32
Nesta palheta podemos encontrar componentes para barra de status, barra de
progresso, barra de ferramentas, calendário, etc. Também temos o PageControl,
Os layouts são salvos na pasta Bin do Delphi, em arquivos com extensão .dst.
Assim, podemos fazer um backup deles para que seu layout favorito não se perca!
Basta arrastar os botões para uma das barras de ferramentas do delphi e ele
será adicionado!
nota: é interessante colocar alguns botões como o de compilar e os de find, replace e find
in files que são bastante usados e ajudam muito!
ele ocorre só nessa iteração. Mas como fazer para que o programa só pare na
iteração 100 para inspecionarmos o código e descobrir o erro? Pois o Break Point
possui um editor onde podemos entre outras coisas, definir uma condição de parada!
Para tanto, é só clicar com o botão direito no círculo vermelho e ir ao menu “Break
point properties...” para exibir a tela abaixo:
2.9.3 Evaluate/Modify
Usado para ver e modificar valores de variáveis e propriedades em tempo de
execução. Pode ser acessado no menu Debug > Evaluate/Modify que aparece ao
clicarmos com o botão direito no Code Editor:
a expressão (desde que seja algo que possa receber valor! Nada de querer atribuir um
novo valor para uma função, por exemplo!). Uma característica interessante do
Evaluate é que ele dá acesso para outros debuggers como os watches e o inspect,
que será visto a seguir.
2.9.4 Inspect
O inspect é uma janelinha bem parecida com o Object Inspector que nos
permite observar todas as propriedades possíveis de um elemento passado para ele.
Se passarmos um componente por exemplo, podemos ver os valores de todas as suas
propriedades, inclusive as posições de memória onde seus métodos estão alocados!
Vejamos um Inspect em ação exibindo os dados de um formulário:
nota: Todos os debuggers vistos devem trabalhar em conjunto com os Break Points, pois
não faz muito sentido analisar um trecho de código ou o estado atual de um componente
com o programa em “movimento”. Até por que ele executa em milésimos de segundo!
3.2 Projetos
Um projeto Delphi, na verdade, é o programa propriamente dito e sua sintaxe é
idêntica à do Pascal. Este programa apenas cria os formulários, onde efetivamente se
concentram todas as funcionalidades da aplicação (mas existem as aplicações
console, que não usam formulários, e aí sim as funcionalidades devem se concentrar
no programa!). O projeto é armazenado pelo Delphi em um arquivo com extensão .dpr
e para visualizar seu código fonte, basta ir ao menu Project > View Source:
3.3 As Units
As Units são arquivos que representam uma coleção de tipos, classes,
procedimentos, funções, constantes, etc. que podem ser importadas e utilizadas durante o
desenvolvimento. Vamos dar uma olhada na estrutura de uma Unit vazia:
Em “unit” fica o nome do arquivo correspondente à unit, que também será o nome
utilizado ao importá-la. Após isso, vêem as 4 seções nas quais uma Unit pode ser dividida:
• Interface: é a seção pública da Unit. Tudo que for declarado aqui será visível fora
da Unit. Nesta seção ficam declarados todos os “serviços” oferecidos pela Unit, que
depois devem ser implementados na seção implementation.
• Implementation: esta seção é onde implementamos procedimentos, funções e
classes declaradas na seção interface. Esta seção é privada, ou seja, seus
elementos são visíveis apenas dentro da Unit. É possível fazer declarações de
3.4 Formulários
Os formulários criados através do Form designer são serializados pelo Delphi
em arquivos de texto com extensão .dfm (VCL) ou .xfm (CLX), e devido a isso, não
vemos nenhum código de inicialização para instanciar componentes ao criar um
formulário, como acontece em IDE’s Java.
Esses dados serializados são incorporados ao executável em forma binária
durante a compilação e ao executar o programa, os componentes são criados com base
nestas informações serializadas. Isso acaba por deixar o código fonte de um formulário
mais limpo, pois apenas a parte que foi implementada pelo desenvolvedor fica visível na
Unit. Vamos dar uma “espiada” no conteúdo de um dfm de um Form bem simples:
bibliotecas o tempo todo. Qualquer componente instalado na IDE, por exemplo, deve estar
armazenado num pacote, que é instalado posteriormente no Delphi. Os pacotes, assim
como os programas e os Project Groups, são considerados projetos pelo Delphi e são
salvos com a extensão .dpk. Ao serem compilados, os pacotes geram dois tipos de
arquivos, os dcp e os bpl. Os dcp servem para que um pacote importe outros que ele
precise usar. Já os bpl são as tais bibliotecas tipo dll citadas acima. São eles os arquivos
que podem ser usados por programas Delphi, inclusive o próprio Delphi.
4 Delphi Language
Veremos agora a sintaxe da linguagem Delphi, seus principais comandos, declarações e
tipos de dados. Alguns podem se perguntar “mas não é Object Pascal???”. Sim, era
mesmo, só que a Borland oficializou o nome da linguagem como Delphi mesmo há pouco
tempo atrás (note inclusive que no help do Delphi 7 aparece “Delphi Language Reference”
no cabeçalho ao invés de “Object Pascal Reference”). Mesmo assim ainda podemos
encontrar muito material, mesmo recente, ainda se referindo a ela como Object Pascal.
4.1 Comentários
Existem três tipos de marcadores de comentário em Delphi:
Você pode usar marcadores fixos de comentário, mas você não pode iniciar um
comentário com um tipo de marcador de comentário e terminar usando outro. Com a
exceção do marcador de comentário de linha '/ /', os comentários no Delphi podem
atravessar linhas múltiplas.
Podemos usar os tipos diferentes de comentários para propósitos diferentes,
como um para colocar observações no código – o comentário propriamente dito – e
outro para desabilitar código fonte ao invés de deletar.
4.2 Declarações
Programas, procedimentos, e funções são todos compostos de declarações. Cada
declaração cria uma linha executável de código.
Declarações podem ser simples ou compostas. Exemplos de declarações simples são
ilustrados por atribuição a variáveis simples, atribuição de função, e chamadas de
procedimento.
Você também pode ter declarações compostas onde você poderia ter uma declaração
simples. Uma declaração composta é um agrupamento de declarações tratadas como
um bloco.
O começo de uma declaração composta sempre é delimitado pela palavra reservada
BEGIN. O fim de uma declaração compostas é delimitado pela palavra reservada END.
if X = 10 then
begin
ShowMessage( X é igual a 10' );
X:= 11;
end;
if X = 10 then
begin
ShowMessage( X é igual a 10' );
X := 11 //Note que essa linha não possui “;”
end;
Outro ponto de dúvidas comum para novatos é quanto ao uso de End sem que o
Begin apareça. Na maioria dos casos, a paridade do Begin . . End existe. Porém, há
alguns casos em que onde você tem um End sem Begin. A ocorrência mais comum
disto é a instrução Case, mas há outros (por exemplo, em blocos try . . . finally, para
uso dentro de definições de registro, etc.). O melhor modo para ficar confortável com
este tipo de omissão é se lembrar que outra palavra chave ou construtor sempre será
achado para estar substituindo a declaração Begin, ou que uma declaração End
sempre será encontrada para ajudar a terminar uma declaração.
Mais uma nota sobre pontuação em programas Object Pascal: o End final do
programa é seguido por ponto e não por um ponto-e-vírgulas. O ponto final indica ao
compilador que é o fim do programa.
4.5 Operadores
O operador de atribuição em Delphi é o sinal de dois pontos-igual (":="). É diferente do
sinal igual ("=") que é usado para testar igualdade e para definição de tipos.
Se você estiver vindo C, você terá que se acostumar a usar sinal de igual (‘=’) “normal”
(unário) para testar para igualdade, e o operador de atribuição binário (:=) para fazer
atribuição. Note que não há nenhum sinal de igual binário ("= =") testar para igualdade
em Pascal.
Operadores Aritméticos
Operador Operação Tipo operando Resultado Exemplo
+ adição integer, real integer, real X+Y
+ unário sinal positivo integer, real integer, real +X
- subtração integer, real integer, real X–Y
- unário sinal negativo integer, real integer, real -X
* multiplicação integer, real integer, real X*Y
/ divisão real integer, real real X/Y
div divisão inteira integer integer X div Y
mod resto da divisão integer integer X mod Y
Operadores Booleanos
Operador Operação Tipo operando Resultado Exemplo
not negação (não) boolean boolean not X
and conjunção (e) boolean boolean X and Y
or disjunção (ou) boolean boolean X or Y
xor ou exclusivo boolean boolean X xor Y
Operadores de String
Operador Operação Tipo operando Resultado Exemplo
+ concatenação string string ‘Delphi’ + ‘7’
Operadores de Classe
Operador Operação Tipo operando Resultado Exemplo
objeto tratado
objeto, como sendo Sender as
as typecast
classe/interface instância da TButton
classe/interface
objeto é
objeto,
is instância de boolean Sender is TEdit
classe/interface
classe
nota: por convenção, todo nome de tipos de dados criados pelo usuário, como os que
vamos fazer mais a frente, deve começar com “T” de type
4.6.1.1 Enumerações
Como Integer, Real, Char e Boolean são bem simples, vamos nos deter aos dois
últimos. As enumerações são tipos de dados compostos por uma lista de valores
constantes, sendo que uma variável deste tipo pode assumir apenas um destes valores
por vez. Exemplo:
Aqui, declaramos o tipo TMoeda na seção type de uma Unit e em seguida uma
variável deste tipo na seção var, chamada Moeda. Depois, a inicializamos com o valor
mdDolar na seção opcional initialization da Unit. A variável Moeda só pode assumir um dos
4 valores definidos para o tipo TMoeda. As enumerações são amplamente utilizadas no
Delphi e podemos ver várias propriedades deste estilo, como por exemplo, a propriedade
Align, presente em vários componentes visuais como o formulário.
4.6.1.2 Sub-range
Os tipos sub-range são criados simplesmente restringindo o conjunto de valores de
um tipo qualquer. Vamos ver um exemplo:
Neste caso, criamos o tipo TPorcentagem pela restrição de valores do tipo Integer
(que possui um intervalo de -2147483648 à 2147483647). Assim, uma variável do tipo
TPorcentagem só pode receber um valor que esteja entre 0 e 100.
A criação de um sub-range não se restringe aos números. Pode-se fazer a mesma
coisa com caracteres e até mesmo com enumerações.
4.6.1.3 String
Versões mais velhas de Pascal implementaram strings como arrays de 8-bits de
caractere. Porém, há vários problemas com o tipo string original do Pascal. Primeiro, é
limitado a só 255 caracteres. Segundo, não termina com um 0 binário (caractere nulo).
Considerando que a string terminada em nulo é muito utilizada em Windows, UNIX, e
outros sistemas operacionais escritos principalmente em C e linguagem assembly, o
programador é forçado a converter strings de Object Pascal para strings terminadas
em nulo.
Por causa destas e outras limitações, o Delphi 2.0 introduziu um tipo novo de string.
Este tipo novo substitui os strings mais velhos. Assim, como char, há dois tipos de
string em Object Pascal: short strings e long strings. O short string é o tipo
tradicional do Object . O long strings é alocado dinamicamente e administrado
automaticamente para você; pode ter o tamanho que a memória disponível permita, e
sempre é terminado em nulo.
Cada tipo de string (longo e curto) inclui um contador de referência escondido que o
Delphi mantém. Quando o contador de referência para da string for igual a zero, a
memória é limpa automaticamente.
Strings, como caracteres, também são delimitados por aspas simples. Se você
precisar colocar uma aspas simples dentro de uma string, coloque duas aspas
simples lado a lado, assim a linguagem Object Pascal os interpretará como uma única.
Você pode usar os operadores relacionais padrão já discutidos para comparar strings,
Object Pascal tem uma grande variedade de procedimentos de manipulação de
strings embutidos. Você também pode tratar strings como se elas fossem array de
caracteres.
var
s : string;
ch1, ch2 : char;
begin
s := 'Hello';
ch1 := s[1];
ch2 := s[2];
ShowMessage( 'Caracteres 1 e 2 são ' + ch1 + ' ' + ch2 );
end;
Quanto ao tipo String, ele é tratado pelo Delphi como uma cadeia de caracteres e
pode-se acessar seus elementos como se ele fosse um array, que se inicia na posição 1 e
vai até a posição n, além de também podermos declarar uma variável String com um
número limitado de caracteres. O exemplo a seguir ilustra este tratamento dado às Strings:
nota: o Delphi fornece várias funções para trabalhar com strings, dentre elas podemos
destacar:
Delete(string qualquer, índice inicial, nº. de caracteres) – exclui uma parte de uma string,
sendo que a parte começa em ‘índice inicial’ e tem o tamanho passado em ‘nº. de
caracteres’.
Copy(string qualquer, índice inicial, nº. de caracteres) – função que retorna uma cópia de
parte de uma string passada como argumento. O significado dos argumentos é o mesmo
de Delete.
Pos(substring, string) – se a ‘substring’ está contida dentro da ‘string’, esta função retorna
o índice de onde a ‘substring’ começa. Agora, se não existir a ‘substring’ dentro da ‘string’,
ela retorna zero.
4.6.2.1 Sets
Os sets são tipos que representam um conjunto de valores, assim como os
conjuntos que aprendemos na matemática, podendo-se realizar operações como união,
intersecção e pertinência sobre eles (veja na tabelinha de operadores e operações de
conjuntos). Porém, os sets têm uma limitação em relação aos outros tipos estruturados;
eles só suportam a criação de conjuntos de tipos ordinais. Mas o que é um tipo ordinal? É
um tipo de dados cujos valores possuem uma ordem. Integer é um tipo ordinal (-2, -1, 0, 1,
2,...), Boolean (False, True), Char também (‘a’, ‘b’, ‘c’,...) por que são usados os códigos
ASCII dos caracteres e as enumerações, cujos valores são tratados internamente como
números inteiros (o compilador do Delphi não entende o ‘mdDolar’ que fizemos acima
diretamente como foi declarado, mas como um número) Bem, vamos ver um set em ação:
4.6.2.2 Arrays
Vamos aos arrays, também conhecidos por aí como vetores. Arrays são listas de
elementos do mesmo tipo de dados, em que cada elemento possui um índice onde é
armazenado. Em Delphi, os arrays podem ser estáticos ou dinâmicos.
Os arrays estáticos são aqueles que possuem nº. fixo de elementos, definido
durante a declaração, que não pode mudar em tempo de execução. Diferentemente de
outras linguagens, o Delphi permite que os índices de um array estático comecem a partir
de qualquer número inteiro, mesmo negativos. Vejamos a declaração de arrays estáticos:
Neste exemplo podemos ver a flexibilidade na criação dos índices para um array,
bem como as formas para ler e escrever nos índices.
Só até aí vimos vetores, ou seja, arrays unidimensionais. Vamos ver agora como
criar matrizes, os arrays multidimensionais:
Podemos notar duas formas de trabalhar com matrizes, a forma “array de array” e
a forma “direta”, que trata a matriz diretamente como matriz. Podemos usar estas duas
formas tanto na declaração como também durante a leitura e escrita de elementos.
Agora os arrays dinâmicos. Estes são os que podem esticar ou encolher durante a
execução do programa. Outra diferença entre eles e os estáticos, além do dinamismo é
claro, é que arrays dinâmicos SEMPRE começam no índice zero (o que implica que não
podemos fazer aquela brincadeira do “array negativo” com eles!) e devem ser declarados
sem índices.
Para trabalharmos com arrays dinâmicos, podemos utilizar algumas rotinas do
Delphi que permitem realizar a mudança de tamanho e a obtenção do tamanho e do maior
e menor índices. Vamos a elas:
Neste caso, só podemos declarar no estilo “array de array”, já que pra fazer a
declaração de matriz “direta” precisaríamos de índices. Para inicializá-las com SetLength,
temos duas alternativas: na primeira, a mais fácil, acrescentamos mais parâmetros à
SetLength de acordo com o nº. de dimensões. A outra, mais complexa, consiste em criar
1º as linhas, sem as colunas, para depois criar as colunas de cada linha, uma por uma.
Esta abordagem, embora trabalhosa, tem suas vantagens, pois ganhamos a flexibilidade
de criar uma matriz em que cada linha tem um nº. diferente de colunas, o que não é
possível da primeira forma.
4.6.2.4 Files
Os files ou arquivos são seqüências de dados de mesmo tipo que podem ser
persistidos em disco – como arquivos! Existem diversas rotinas no Delphi para
manipular arquivos, das quais veremos algumas a seguir:
Como foi dito anteriormente, o Delphi se utiliza exatamente deste esquema para
implementar o tratamento de eventos. Eventos em Delphi nada mais são que referências a
tipos procedurais, sendo que o mais famoso de todos é o TNotifyEvent, cuja assinatura é:
Familiar? Acredito que sim, pois esta é a assinatura da maioria dos eventos do
Delphi, que recebem apenas o objeto que realizou a ação como argumento.
vamos a um exemplo bem simples. Imagine que estamos no Form Designer e que
nossa tela tem apenas um botão (TButton). Quando vamos ao Object Inspector e clicamos
2 vezes no evento OnClick, o Delphi cria um procedure com a assinatura do TNotifyEvent
e o chama de TForm1.Button1Click. Isso quer dizer que este procedure é um método da
classe TForm1 que estamos programando, ou seja, ele pertence ao formulário e não ao
botão como muitos pensam. Mas como o Button1 sabe que aquele método do formulário é
o seu OnClick para executa-lo? Aí entra a magia dos tipos procedurais! Aquele OnClick em
que a gente clica para criar o evento na verdade é uma propriedade, assim como Caption,
Font, etc., do tipo TNotifyEvent. Assim, ela pode apontar para qualquer método que tenha
a estrutura do TNotifyEvent, assim como o nosso Button1Click!
Ao clicar 2 vezes no Object Inspector, automaticamente a referência OnClick do
Button1 é configurada para apontar para o método Button1Click do Form1 que o Delphi
criou. Assim, quando o programa roda, o botão executa o método indiretamente através da
referência ao ser clicado, exatamente como fizemos com a função Quadrado!
4.6.4 Variants
A classe Variant é modelada depois do tipo Variant intrínseco em versões prévias de
Delphi e Borland C++. Objetos variants são essencialmente variáveis sem tipo, isto
significa que eles podem assumir tipos diferentes automaticamente. O tipo variant
permite a uma variável mudar seu tipo dinamicamente (em tempo de execução). Por
exemplo, no pedaço seguinte de código, o x é variant reconhecido primeiro como um
Integer, e depois como uma string:
Uma variável de tipo variant pode conter boolean, date/time, Integer, objetos OLE
Automation, real, e valores de string. Também podem armazenar arrays com
elementos destes tipos, inclusive arrays de variants.
Há dois valores especiais que podem ser usados como valores de variants: Null e
Unassigned. Se o valor do variant for null, a variável não tem dado ou eles foram
perdidos. O valor unassigned informa que a variável não recebeu nenhum valor.
4.6.5 Classes
As classes são estruturas que servem de modelo abstrato para a que
possamos criar objetos, ou instâncias concretas a partir dela. O Delphi trata suas
classes com um tipo de dados estruturado qualquer, tanto que elas também devem ser
declaradas na seção type das Units.
Uma classe Delphi é composta basicamente de campos (fields), métodos e
propriedades, cujo acesso pode ser restringido como private, protected, public ou ainda
published. Vamos ver e discutir a estrutura típica de uma classe:
nota: esse esquema de controle de acesso só é válido para membros de Units diferentes.
Se duas classes estão na mesma Unit, elas têm acesso a todos os membros uma da outra
e passam a ser “friend classes”. Mas isso não é ruim? Depende. Às vezes podemos querer
que várias classes e sub-rotinas trabalhem em conjunto para alcançar seus objetivos.
Assim, pode ser indispensável que elas possam ter acesso total aos dados das outras.
Mas se você não quer que isso ocorra, basta criar uma única classe por Unit.
partes read e write, que dizem a ela o que deve ser lido e o que deve ser escrito no
membro que ela encapsula. Mas podem existir propriedades somente de leitura
(read-only) e somente de escrita (write-only), bastando omitir uma destas partes.
• Construtores: São tipos especiais de métodos responsáveis pela criação dos
objetos da classe e pela inicialização dos seus campos. Por convenção,
construtores Delphi são sempre chamados de Create ou algo como
“CreateAlgumaCoisa” ou então “CreateFazendoAlgumaCoisa”... mas sempre tendo
o Create como base. Quando criamos uma classe, os construtores da superclasse
são herdados, mas podem ser escondidos se declararmos outro construtor no
mesmo nível de acesso, mesmo que tenha assinatura diferente do original.
• Destruidores: São métodos responsáveis pela liberação dos recursos alocados por
um objeto durante sua existência. Como não existe um garbage collector no Delphi
7, todo objeto instanciado deve ser manualmente liberado pelo destruidor. por
convenção, os destruidores são chamados de Destroy ou algo que tenha Destroy
como base. Também existe um destruidor herdado definido na classe TObject, que
pode ser sobrescrito, usando a diretiva override. Atenção agora: o Create deve ser
ocultado, mas o Destroy deve ser sobrescrito com override. Isso porque Destroy é
um método virtual, enquanto que Create é estático.
4.6.7 Interfaces
Interfaces são como uma espécie de classe abstrata que fornece apenas
declarações de métodos para serem implementados por uma classe. Aí dizemos que a
classe implementa a interface e é obrigada a implementar todos os métodos que ela
fornece.
No Delphi, a interface raiz é a “IInterface” (foi convencionado que todo nome de
interface deve começar com “I”), que possui 3 métodos: QueryInterface, _AddRef e
_Release. Assim, toda interface criada deve ser derivada de IInterface e assim terão estes
3 métodos. mas então, se eu criar uma interface personalizada e implementa-la numa
classe, vou precisar implementar estes métodos esquisitos? Não necessariamente!
Acontece que estes métodos já estão implementados numa classe chamada
TInterfacedObject. Assim, basta herdar sua classe de TInterfacedObject e implementar
apenas a interface personalizada, sem se preocupar com os 3 métodos esquisitos (afinal,
herdaremos a implementação padrão). Mas afinal, o que estes métodos fazem? Eles têm a
ver com o controle do tempo de vida de objetos referenciados por variáveis de interface.
Estes objetos não precisam ser destruídos como os objetos comuns, pois são controlados
por contagem de referências. E quem controla isso são as implementações destes
métodos na TInterfacedObject.
Existem algumas restrições nas interfaces em relação às classes:
(lembrando que não há herança múltipla no Delphi! Coloque apenas uma classe e depois
quantas interfaces quiser!). Dentro da classe, implementamos os métodos fornecidos pela
interface, escolhendo a visibilidade que bem entendermos para eles.
Note que em ambos os exemplos anteriores, < declaração > pode ser uma declaração
simples ou composta. Também nota que o inteiro o bloco inteiro if . . . then é
considerado uma única declaração, assim o único ponto-e-vírgula pertence ao término
da declaração (ou depois de < declaração > no primeiro caso depois do segundo <
declaração > no segundo caso).
Você pode aninhar quantas declarações If você queira, mas na maioria dos casos
onde você tem muitas condições para conferir, construir um Case é melhor escolha.
Aqui está a sintaxe de uma declaração if . . . then que usa declarações compostas:
if x < 5 then
if y > 4 then
z := 0
else
z := 1;
Para que if o else pertence? A identação parece sugerir que pertence ao primeiro if,
mas na verdade pertence ao segundo. Neste exemplo, se x é maior ou igual a 5, a
parte do else nunca será executada. O else pertence ao if interno , e só executará se
x for menor que 5 e y é menor ou igual a 4.
Embora o Pascal não tenha nenhum operador de fim explícito "end if", o ponto-e-
vírgula serve para este propósito. Note porém que sempre é ilegal colocar um ponto-e-
vírgula em frente a uma cláusula else, porque a cláusula if/then/else é uma única
declaração. Porque a cláusula if/then/else é uma única declaração, a regra é esta na
Linguagem Object Pascal, o else pertence ao if mais interno.
Dada esta regra, como você pudesse associar o else oscilante do último exemplo,
com o primeiro if? Com este conhecimento, nós podemos resolver o problema prévio
passando de uma declaração simples para uma declaração composta.
Aqui temos um exemplo:
if x < 5 then
begin
if y > 4 then
z := 0
end
else
z := 1;
Agora criando uma declaração composta, o end da declaração de inicial servirá como
o terminador para o if interno. A outro parte da declaração executará agora se x for
maior ou iguala a 5.
case <variável> of
<variável(is)> : <declaração>;
< variável(is)> : < declaração >;
else
< declaração >;
end;
A instrução Case pega uma variável e a compara com possíveis valores. Valores
múltiplos podem aparecer debaixo do mesmo Case, separado por vírgulas. Aqui está
um exemplo de uma estrutura Case:
Case Ch of
'A'..'Z', 'a'..'z': ShowMessage('Letra');
'0'..'9': ShowMessage('Número');
'+', '-', '*', '/': ShowMessage(Operador');
else
ShowMessage('Caractere Especial');
end; // case
Neste exemplo, nós estamos testando o valor da variável Ch (que é do tipo char) e
mostrando 'Letra' se ela é uma letra maiúscula ou minúscula, 'Número' se ela é um
número, ou 'Operador' se ela é um operador. Se nenhum dos casos anteriores for
verdadeiro, a cláusula else é executada, e as palavras ‘Caractere Especial’ são
mostradas.
Também note que qualquer uma das declarações em um Case pode ser declarações
simples ou composta. Se você precisar executar múltiplas linhas de código para um
determinado caso, você tem que colocar o código dentro um begin . . . end.
Loop
Loop é uma das atividades fundamentais que você empregará em qualquer linguagem
de programação. Objecto Pascal oferece várias alternativas de loop. Cada tipo
particular para uma circunstância específica.
4.7.3 While . . . do
O loop While executa declarações até que a condição declarada no While fique falsa.
Como em todas as estruturas, você pode ter declarações simples ou compostas. Aqui
está um exemplo de uma declaração composta:
i := 10;
while i > 0 do
begin
i := i - 1;
ShowMessage(‘Este é um loop!’ );
end; // while
Este exemplo mostrará ‘Este é um loop!’ dez vezes. Note que o loop While impedirá
que as declarações internas sejam executadas, se a condição for inicialmente falsa.
4.7.4 For . . . do
O loop For é diferente do loop While pois ele sempre executa um número especificado
de vezes, determinado pela variável de controle. A sintaxe geral do For é mostrada
abaixo:
for i := 10 to 100 do
ShowMessage( ‘Loop’ );
Como este loop executa, o valor de i é 10 na primeira vez. Para cada volta, é
incrementado i. O loop continua até que i alcance o valor de 100 (o valor final). Na
última passagem do loop, i é igual a 100. É incrementado novamente, e o loop termina
porque o valor de i é agora maior que o valor final.
Para este tipo de loop não é necessário incrementar a variável de controle; há uma
modificação para o porque volta, downto por sua vez faz com que a variável i seja
decrementada e não incrementada para cada volta.
Note que neste exemplo que há só um pontro-e-vígula, e só um lugar possível para ele.
A declaração For leva uma única declaração ou uma declaração composta, porém, a
declaração do if..then..else é uma única declaração, e assim não há nenhuma
necessidade do begin...end.
Seja cauteloso ao usar a variável de controle. Deve ser declarado como um tipo
ordinal (um número ou um tipo enumerado definido pelo usuário) e deve estar dentro
do escopo do loop. Também, depois que o loop for executado, o valor da variável de
controle será um passo além para o 'to' ou 'downto' . Você não pode mudar o valor
da variável de controle dentro do loop.
O loop For é a melhor opção de loop quando você sabe com antecedência os valores
que você passará para o loop. Ele é utilizado freqüentemente para o acesso aos
elementos de um array.
A declaração Continue neste caso impedirá que qualquer número menor que 5 de
seja impresso, o resto da volta é saltado, e a condição de volta é re-avaliada. Se o
usuário entrar em um número maior que 10, o valor ainda será impresso, mas o loop
termina.
A declaração Continue é particularmente útil para saltar ou evitar dados inválidos ou
cálculos. Se o usuário entrar com algo diferente do que você quis, então você pode
usar Continue voltando ao início do loop e conseguir o dado novamente.
4.7.6 Repeat
repeat
comando1;
comando2;
comando3;
until
<condições>
Exemplo:
if not <condição> then
raise Exception.Create(‘Condição inválida!’);
Este código dispara uma exceção do tipo Exception (a “mãe” de todas as exceções
Delphi) sempre que <condição> for falsa.
Quanto ao bloco try..finally, seu uso é indicado principalmente para garantir que um
determinado recurso alocado pelo programa seja liberado, aconteça o que acontecer. Por
exemplo, se você instancia um objeto, ele deve ser liberado manualmente (não temos
garbage collector), mas se houver uma exceção antes que o código de liberação seja
executado, o objeto continuará vagando pela memória, ocupando espaço e gastando
recursos da máquina! Mas se o protegermos o código que utiliza o objeto com o bloco try e
colocarmos o código de liberação no finally, ele garantirá que o objeto será liberado de
qualquer jeito, com ou sem exceções! Outro uso pode ser o fechamento de arquivos, ou
fazer o cursor voltar ao normal (pro caso de o mudarmos e ocorrer uma exceção que o
manteria modificado, como ficar eternamente com a ampulheta). A sintaxe de um bloco
try..finally é:
try
comando1;
comando2;
finally
comando3;
comando4;
end;
with Memo1
do begin
Line := Perform(EM_LINEFROMCHAR, SelStart, 0);
Column := SelStart - Perform(EM_LINEINDEX, Line, 0);
Label1.Caption := IntToStr(Line + 1);
Label2.Caption := IntToStr(Column + 1);
end;
Agora responda: o que é “SelStart”? Uma variável? Uma função? Uma propriedade do
Memo1? O que são “Line” e “Colunm”?
Esse é o problema; o with torna o código fonte mais confuso para o leitor, pois fica
difícil de determinar a quem pertencem os elementos referenciados, apesar de poupar o
trabalho do escritor...
Mas o pior defeito do comando with é esconder os valores das expressões dos
debuggers do Delphi. Portanto, se usar with você não poderá ver os valores das variáveis
ao parar a execução do programa com Break Point. E também não adianta “apelar” para
Whatches ou Evaluate/Modify... nada consegue acessar estes valores!
Por isso, os prejuízos que conseguimos com este comando acabam se tornando
maiores que seus benefícios e seu uso é desencorajado.
// declaração de variáveis
var
// simples
Numero: Integer;
// lista
Palavra1, Palavra2, Palavra3: String;
// inicializando na declaração
OutroNumero: Integer = 0;
// declaração de constantes
const
// true constants
ConstanteInteira = 10;
ConstanteString = ‘Texto constante’;
ContanteExpressao = 30 + (25 mod 2);
// typed constants
MaisUmNumero: Integer = 100;
OutraString: String = ‘Nada Não!’;
Nums: array[0..9] of Char = ('0', '1', '2', '3', '4', '5', '6', '7', '8',
'9');
nota: Ao contrário do que ocorre na instrução return do Java por exemplo, a execução do
programa não sai da função ao atribuirmos o resultado a ela em Delphi, ou seja, se você
atribuir um valor ao result mas ainda houverem instruções depois, todas elas serão
executadas. A função só retorna o valor após executar todas as suas instruções.
Agora com lista (os de mesmo tipo são separados com vírgula e os de tipos diferentes são
separados com ponto-e-vírgula. Agrupar parâmetros de mesmo tipo em lista é opcional):
procedure P(Parametro1, Parametro2: Integer; Parametro3: String);
Com default (se nada for passado como argumento, assume o valor da inicialização):
procedure P(Parametro1: Integer; Parametro2: Boolean = True);
E agora sem parâmetros (veja que não é necessário colocar parênteses vazios em Delphi):
procedure P;
procedure P; overload;
procedure P(I: Integer); overload;
procedure P(S: String; B: Boolean); overload;
É só isso! Basta que eles tenham o mesmo nome, mas com listas de parâmetros
diferentes, e a diretiva overload em cada versão sobrecarregada.
5 Componentes
A programação típica em Delphi é bastante centralizada na adição e configuração
de componentes da Palheta de Componentes no Form Designer. Então, vamos ver
alguns conceitos e propriedades básicas dos componentes.
5.4 TForm
Os componentes da classe TForm são os formulários sobre os quais incluímos
outros componentes e através do qual criamos a telas da aplicação. Suas
propriedades mais importantes são:
5.5 Botões
Temos 3 componentes que representam diferentes tipos de botões, cada um
com suas funcionalidades especificas. São eles o TButton, TBitBtn e o TSpeedButton.
Eles possuem propriedades comuns, que veremos agora:
Agora vamos dar uma olhada no TBitBtn. O maior diferencial deste botão em relação
ao TButton é o suporte à imagens, o que significa que podemos colocar um ícone
nele, através da propriedade Glyph. Outras propriedades existem em função deste
ícone: Margin e Spacing, que controlam respectivamente a margem que deve ser
respeitada antes do glyph e o espaço entre o glyph e o caption. Há também a
propriedade layout que informa a posição do glyph (à esquerda, direita, acima ou
abaixo em relação ao caption). Estas três propriedades estão também no
TSpeedButton.
O botão do tipo SpeedButton é diferente dos outros. Ele não pode ser
acessado por tabulações como os outros e não pode receber foco, comportamento
encontrado em botões de barras de ferramentas por exemplo. Possui uma propriedade
exclusiva entre os botões, a Flat, que quando verdadeira, esconde o contorno do
botão até que o mouse passe sobre ele.
5.6 O Label
Componente usado para criar um rótulo, tipicamente usado com edits. Um
Label não pode receber foco nem pode ser editado em tempo de execução. Sua
funcionalidade básica se restringe a exibir um texto pela propriedade Caption. Possui
também a propriedade FocusControl, que faz com que o controle referenciado por ela
receba o foco, se o Caption do Label estiver com configurado com um atalho Alt +
tecla, configurado com um “&” antes do caractere que servirá de tecla de atalho junto
com Alt.
5.7 Os Edits
São os componentes tipo caixa de texto de uma única linha onde o usuário
pode digitar um texto qualquer. O Delphi fornece 3 edits básicos: TEdit, TMaskEdit,
TLabeledEdit.
O MaskEdit é um edit especial, cujo Text pode ser formatado usando máscaras, com a
propriedade EditMask. Basta utilizar o editor de mascaras que não tem mistério! Já o
LabeledEdit é um edit que já vem com um Label embutido, que agiliza ainda mais a
criação de telas. A propriedade EditLabel permite configurar as propriedades do Label
embutido. de novidade só temos as propriedades LabelPosition e LabelSpacing, que
controlam a posição (esquerda, direita, acima e abaixo) e a distância do Label interno
em relação ao edit.
5.8 O Painel
Um painel é um componente do tipo TPanel, que é um contêiner para outros
componentes. è usado para organizar o layout do Form, agrupando componentes,
portanto suas funcionalidades se restringem ao projeto na maioria dos casos. Sus
propriedades mais usadas são as que controlam a aparência das bordas:
Seus valores definem se a borda será “pra fora” (raised), “pra dentro” (lowered) ou
nehuma.
Pode-se criar efeitos interessantes combinando de formas diferentes as bordas do
Panel.
5.10 RadioButton
O RadioButton é um componente usado para implementar uma seleção onde
as opções são mutuamente exclusivas, ou seja, o usuário só pode marcar um valor.
O estado do RadioButton pode ser lido através da propriedade Checked, que é
True se ele estiver marcado e False caso contrário.
Fato curioso é que se houverem vários RadioButtons no mesmo parent, eles
assumen automaticamente o comportamento de mútua exclusão, sem precisar de
nenhuma programação!
5.11 CheckBox
Assim como o RadioButton, serve para implementar seleções, mas com a
CheckBox o usuário pode marcar várias opções ao mesmo tempo. Também possui a
propriedade Checked, que guarda seu estado, exatamente como o RadioButton.
5.12 RadioGroup
Usado para simplificar a criação de vários RadioButtons agrupados. Nele, cada
RadioButton é tratado como uma linha editada na propriedade Items. Para saber qual
deles está selecionado, usamos a propriedade ItemIndex, que começa no Item 0 e
termina no Item n-1 (para que nenhum item seja marcado, configure ItemIndex como -
1).
Quanto à organização dos RadioButtons em seu interior, o Radiogroup
costuma colocar um por linha, o que nem sempre fica bonito... Para resolver este
impasse, basta configurar a propriedade Colunms para o número de colunas desejado!
5.13 ComboBox
As ComboBoxes são como Edits com uma lista embutida que se abre ao
clicarmos no botão com a setinha à direita. Vamos ver suas propriedades mais
manjadas:
• Items: Igual à Items do RadioGroup, é a lista dos itens que aparecerão na lista
quando o botão for pressionado.
• ItemIndex: Também é como à do RadioGroup, retornando o índice do item da lista
que está selecionado. Se não há itens selecionados, ItemIndex assume o valor -1.
• DropDownCount: Número máximo de itens que aparecerão na lista suspensa. Se
o número de itens for maior que o valor de DropDownCount, uma barra de rolagem
aparece.
• Sorted: Se esta propriedade for habilitada, os itens serão ordenados.
• Style: Determina o estilo do display da ComboBox. Serve principalmente para
controlar se ela é editável (csDropDown) ou se serve apenas para seleção
(csDropDownList).
• Text: É o texto do elemento corrente.
5.15 PopupMenu
Componente usado para implementar menus estilo pop-up (não diga!), que
aparecem quando clicamos com o botão direito. A criação de itens é idêntica à do
MainMenu.
5.16 Toolbar
É o componente usado para criar barras de ferramentas. Sua propriedades
mais usadas são:
a tbsDropDown, usada para fazer um ToolButton como o Run do Delphi, que tem
um menuzinho abaixo! Para se usar este estilo, devemos preencher a propriedade
DropdownMenu.
• DropdownMenu: Associa o ToolButton a um PopupMenu, criando assim a listinha
que surge quando o ToolButton é criado.
5.17 ImageList
Chegou a hora de falarmos a respeito da tão comentada ImageList, que já deu
as caras nos tópicos sobre menus e Toolbar. Este componente guarda uma lista de
imagens para compartilhar com outros componentes, principalmente com Menus e
barras de ferramentas, que a referenciam a ImageList pela propriedade Images, e
depois por ImageIndex obtém uma das imagens armazenadas nela.
Normalmente não se configura nenhuma propriedade da ImageList, apenas
adicionamos imagens a ela, dando um duplo click para chamar o editor, que faz as
operações de adicionar excluir ou mudar as imagens. Não há complicações para usá-
lo!
5.19 Diálogos
Os diálogos são os componentes que encapsulam os principais diálogos do
Windows, como o diálogo de abertura de arquivos, salvamento de arquivos, diálogo de
impressão, de fonte, de cores... todos estão lá!
O método central de um diálogo é o Execute, usado para abrir a janela do
diálogo para que o usuário interaja com ele. O método execute é uma função booleana
que retorna True se o usuário confirmou a operação executada pelo diálogo, clicando
no botão OK. Se o usuário desistir da operação clicando em cancelar, Execute retorna
False. Desta forma podemos testar este retorno e só implementar nosso código
quando o usuário realmente confirmar a operação. A seguir temos uma visão geral de
alguns diálogos: