tutorial delphi

33
http://www.geocities.com/WallStreet/ Exchange/1726/computing/delphi/ delphi_3.htm 2. FUNDAMENTOS DO OBJECT PASCAL O Pascal é uma linguagem surgida a partir de um projeto experimental do professor Niklaus Wirth, da Escola Politécnica de Zurique (a mesma escola onde Einstein estudou). O nome da linguagem é uma homenagem ao filósofo francês Blaise Pascal, que inventou uma máquina de calcular mecânica. A descrição formal do Pascal foi publicada em 1971. O Pascal nasceu dentro do conceito de programação estruturada, muito discutida na Europa durante os anos 60 e hoje difundido pelo mundo e incorporado em todas as linguagens modernas (C, C++, Java, Visual Basic, etc.). A idéia principal do Pascal é a ordem, administrada através de um conceito de dados baseado em tipos, requerendo declarações explícitas de todas as variáveis e controles do programa. Parte da popularidade do Pascal se deve ao compilador Turbo Pascal, da Borland, lançado em 1985. A linguagem usada no Delphi é o sucessor do Turbo Pascal, conhecido como Object Pascal. 2.1. INSTRUÇÕES CONDICIONAIS 2.1.1. INSTRUÇÕES IF Este é o tipo mais básico de instrução condicional e pode ser usada para executar um trecho de programa caso uma

Upload: cdpgohan

Post on 04-Jul-2015

662 views

Category:

Documents


3 download

TRANSCRIPT

Page 1: Tutorial Delphi

http://www.geocities.com/WallStreet/Exchange/1726/computing/delphi/delphi_3.htm

2. FUNDAMENTOS DO OBJECT PASCAL

O Pascal é uma linguagem surgida a partir de um projeto experimental do professor Niklaus Wirth, da Escola Politécnica de Zurique (a mesma escola onde Einstein estudou). O nome da linguagem é uma homenagem ao filósofo francês Blaise Pascal, que inventou uma máquina de calcular mecânica. A descrição formal do Pascal foi publicada em 1971.

O Pascal nasceu dentro do conceito de programação estruturada, muito discutida na Europa durante os anos 60 e hoje difundido pelo mundo e incorporado em todas as linguagens modernas (C, C++, Java, Visual Basic, etc.). A idéia principal do Pascal é a ordem, administrada através de um conceito de dados baseado em tipos, requerendo declarações explícitas de todas as variáveis e controles do programa. Parte da popularidade do Pascal se deve ao compilador Turbo Pascal, da Borland, lançado em 1985. A linguagem usada no Delphi é o sucessor do Turbo Pascal, conhecido como Object Pascal.

2.1. INSTRUÇÕES CONDICIONAIS

2.1.1. INSTRUÇÕES IF

Este é o tipo mais básico de instrução condicional e pode ser usada para executar um trecho de programa caso uma condição for satisfeita (if –then), ou, mais genericamente, para escolher entre duas instruções (if-then-else). A sintaxe geral da instrução if é a seguinte:

if condição then[bloco de instruções 1]else[bloco de instruções 2];

 

Page 2: Tutorial Delphi

Composto se as condições, e múltiplas declarações  Nós podemos ter várias condições para a condição se. E nós podemos ter mais do que uma declaração para a outra e em seguida cláusulas. Aqui estão alguns exemplos

if (condition1) And (condition2)   // Both conditions must be satisfied   then     begin       statement1;       statement2;       ...     end              // Notice no terminating ';' - still part of 'if'   else     begin       statement3;       statement4;       ...     end;

Note que não deve haver ponto-e-vírgula após o primeiro bloco de instruções. Isto ocorre porque a instrução if-then-else deve ser lida como uma linha inteira. Como teste, inicie um novo projeto e acrescente duas CheckBoxes e três Botões de Comando no formulário, conforme a Figura 2.1 a seguir. Não é necessário mudar os nomes ou legendas dos componentes. Dando um duplo clique no primeiro botão e escreva o seguinte código:

 

procedure TForm1.Button1Click(Sender: TObject);begin{instrução if simples}

if CheckBox1.checked then

Page 3: Tutorial Delphi

ShowMessage ('CheckBox1 está selecionada ')

end;

Este é um if simples. Durante a execução, se você clicar sobre o botão 1, e se CheckBox1 estiver selecionada, um aviso será emitido. Mas nada acontece caso CheckBox1 não esteja selecionada. Para contornar este problema, escreva o seguinte código no evento click do botão 2:

procedure TForm1.Button2Click(Sender: TObject);begin{instrução if-else}

if CheckBox1.checked then

ShowMessage ('CheckBox1 está selecionada')

else

ShowMessage ('CheckBox1 não está selecionada ')

end;

 

Agora um aviso continuará a ser emitido caso CheckBox1 esteja selecionada. Caso contrário (else), um aviso será emitido com a mensagem de que CheckBox1 não está selecionada.

Você é capaz de imaginar o que aconteceria se as duas caixas estivessem selecionadas? Neste caso, apenas o primeiro bloco será executado. Como o programa verifica que a primeira condição é verdadeira, então a segunda, dentro da lógica do if-then-else, não tem importância. Assim, a mensagem recebida seria apenas a de que CheckBox1 está selecionada. Para testar ambas as condições, escreva o código a seguir no botão 3:

procedure TForm1.Button3Click(Sender: TObject);begin

if CheckBox1.checked and CheckBox2.checked then

ShowMessage('Ambas as caixas estão selecionadas')

end;

 

Note que usamos o operador booleano and para compor uma condição de duas partes, que só será verdadeira se ambas as caixas estiverem selecionadas.

Page 4: Tutorial Delphi

2.1.2. INSTRUÇÃO CASE

Se a quantidade de condições a serem verificadas for muito grande, o uso da instrução if poderá acarretar em códigos muito complexos. Neste caso é melhor usar a instrução Case, que seleciona um valor dentro de uma lista de possíveis valores ou intervalos de valores. Uma das limitações da instrução Case do Pascal é que estes valores devem ser de tipo ordinal, ou seja, não é possível testar literais ou números reais, por exemplo.

Para testar o Case, salve o projeto anterior e inicie um novo, inserindo uma caixa de edição e dois botões, conforme a Figura 2.2 abaixo.

No evento click do botão 1, escreva o seguinte código:

procedure TForm1.Button1Click(Sender: TObject);var Numero: integer;begin

Numero := StrToInt(edit1.text);

case Numero of

1: Showmessage ('Você digitou 1');2: Showmessage ('Você digitou 2');3: Showmessage ('Você digitou 3');4: Showmessage ('Você digitou 4');5: Showmessage ('Você digitou 5');6: Showmessage ('Você digitou 6');7: Showmessage ('Você digitou 7');8: Showmessage ('Você digitou 8');9: Showmessage ('você digitou 9');10: Showmessage ('você digitou 10');

else

Showmessage ('Você digitou um número maior que 10');

Page 5: Tutorial Delphi

end;

end;

 

Note que devemos converter a propriedade text da caixa de edição, que é um string, para um valor inteiro, pois não podemos testar text diretamente. Isto é feito com a função StrToInt.

Podemos usar o Case também para testar intervalos de valores. Por exemplo, escreva o seguinte trecho no evento click do botão 2:

procedure TForm1.Button2Click(Sender: TObject);var Numero: integer;begin

Numero := StrToInt(edit1.text);

case Numero of

1..10: Showmessage ('Você digitou um número entre 1 e 10');11..20: Showmessage ('Você digitou um número entre 11 e 20');21..30: Showmessage ('Você digitou um número entre 21 e 30');31..40: Showmessage ('Você digitou um número entre 31 e 40');41..50: Showmessage ('Você digitou um número entre 41 e 50');

else

Showmessage ('Você digitou um número maior do que 50');

end;

end;

 

 

2.2. INSTRUÇÕES DE LAÇO

2.2.1. LAÇO FOR

Page 6: Tutorial Delphi

A instrução for do Pascal é semelhante à de outras linguagens, mas não é muito flexível. Não é possível estabelecer incrementos diferentes de um, embora seja possível contar para cima e para baixo. Por exemplo, inicie um novo projeto, adicione dois botões no formulário, e escreva o seguinte código no evento click do primeiro:

procedure TForm1.Button1Click(Sender: TObject);var I: integer;

begin

for I:=1 to 10 do ShowMessage(IntToStr(I));

end;

 

Estamos usando a função IntToStr para converter o número inteiro I para um string, pois a função ShowMessage só exibe strings. Clicando-se sobre o botão 1 em tempo de execução aparece uma caixa de mensagens que vai exibindo números de 1 a 10. O código abaixo pode ser inserido no segundo botão e exibirá números no sentido decrescente, isto é, de 10 a 1.

procedure TForm1.Button2Click(Sender: TObject);var I: integer;

begin

for I:= 10 downto 1 do ShowMessage(IntToStr(I));

end;

 

2.2.2. INSTRUÇÕES WHILE E REPEAT

A diferença entre os laços while-do e repeat-until é que o código da instrução repeat é sempre executado ao menos uma vez. Você pode entender essa diferença escrevendo os códigos a seguir nos botões do projeto anterior:

procedure TForm1.Button1Click(Sender: TObject);var I: integer;

beginI:=0;

while I < 10 do

begin

Page 7: Tutorial Delphi

ShowMessage(IntToStr(I));I:= I+1;

end;

end;

 

procedure TForm1.Button2Click(Sender: TObject);var I: integer;

beginI:=0;

repeat

ShowMessage(IntToStr(I));I:=I+1;

until I>10;

end;

 

Rode o programa e veja o que acontece.

Algumas observações são importantes. Primeiro, você mesmo precisa providenciar o incremento da variável contadora I, e esta variável não precisa ser inteira. Segundo, a instrução while-do exige que o bloco de instruções a ser controlado fique entre um begin e um end, o que não acontece na instrução repeat-until.

2.3. VARIÁVEIS

A linguagem Pascal é fortemente baseada em tipos de dados. O tipo de uma variável determina os valores que esta variável pode ter e as operações que podem ser executadas com ela. Também é necessário que todas as variáveis sejam declaradas antes de ser usadas, o que é feito por meio da palavra-chave var. Esta declaração pode ser feita em uma unidade, em uma procedure ou para declarar variáveis globais, tendo o seguinte aspecto:

varNumero: Integer;Fechado: Boolean;

 

Page 8: Tutorial Delphi

Uma tentativa de realizar uma operação com tipos de dados diferentes resulta em um erro de compilação. Isto aconteceria se tentássemos, por exemplo, somar Numero e Fechado.

Constantes podem ser declaradas de forma semelhante, com auxílio da palavra-chave const:

constPi = 3.141592;Nome = ‘Alvaro’;

Note que não usamos, aqui, o sinal de atribuição ":=", e sim o sinal de igualdade convencional.

O Object Pascal apresenta vários tipos de dados construídos internamente, denominados tipos pré-definidos. Também é possível construir outros tipos a partir dos pré-definidos. A Tabela 2.1 a seguir apresenta os tipos de dados pré-definidos.

Tabela 2.1 - Tipos de dados pré-definidos do Object Pascal

TIPO DE DADO

VARIAÇÃO TAMANHO OBSERVAÇÕES

ShorInt -128 a 127 1 byte  

SmallInt -32768 a 32767 2 bytes  

LongInt-2147483647 a 2147483647

4 bytes  

Integer-2147483647 a 2147483647

4 bytesNo Delphi este tipo é idêntico ao LongInt.

Byte 0 a 255 1 byte  

Word 0 a 65535 2 bytes  

Single 1.5 x10-45 a 3.4x1038 4 bytes 7-8 dígitos

Double 5.0x10-324 a 1.7x10308 8 bytes 15-16 dígitos

Extended 3.4x10-4932 a 1.1x104932 10 bytes 19-20 dígitos

Currency

-922337203675477.5808 a 922337203685477.5807

8 bytes 19-20 dígitos

Comp -263 a 263 8 bytes 19-20 dígitos

Real 2.0x10-39 a 1.7x1038 6 bytes 11-12 dígitos. Use este tipo apenas para compatibilidade com versões anteriores do

Page 9: Tutorial Delphi

Pascal

Boolean True ou false 1 byte  

AnsiChar Caracteres ANSI    

WideChar Caracteres Unicode    

Char Caracteres ANSI 1 byteNo Delphi este tipo é idêntico ao AnsiChar

ShortString Até 255 caracteres    

AnsiString Virtualmente sem limite    

String Virtualmente sem limite  Em geral, é idêntico ao AnsiString

Variant    Pode conter qualquer tipo de dados

Como o Object Pascal é uma linguagem fortemente estruturada, você não poderá realizar operações entre variáveis de tipos diferentes. Será necessário, então, convertê-las para o tipo adequado antes de realizar a operação. A Tabela 2.2 a seguir mostra as funções de conversão mais utilizadas.

Tabela 2.2 - Funções de conversão de tipos mais utilizadas

FUNÇÃO DESCRIÇÃO

Chr Converte um número ordinal em um caractere ANSI

RoundConverte um real em um inteiro, arredondando a parte decimal

TruncConverte um real em um inteiro, truncando a parte decimal

IntRetorna a parte inteira de um argumento de ponto flutuante

IntToStr Converte um número em um string

StrToIntConverte um string em um inteiro, levantando uma exceção (erro) caso o string não represente um inteiro válido

StrToIntDefConverte um string em um inteiro, usando um valor padrão se o string não estiver correto

ValConverte um string em um número (rotina incluída para compatibilidade com o Turbo Pascal)

StrConverte um string em um número, usando parâmetros de formatação (rotina incluída para compatibilidade com o Turbo Pascal)

FloatToDecimal Converte um valor de ponto flutuante em um registro

Page 10: Tutorial Delphi

(record) incluindo sua representação decimal (expoente, dígitos, sinal)

FloatToStrConverte um valor de ponto flutuante para sua representação string usando formatação padrão

StrToFolat Converte um string e, um valor de ponto flutuante

Além dos tipos pré-definidos, o Object Pascal emprega a idéia de tipos de dados definidos pelo usuário, que foi introduzida pela primeira vez no Pascal, não estando presente nas linguagens anteriores. Os programadores podem definir seus próprios tipos de dados por meio de construtores de tipos, tais como subintervalos (subranges), matrizes (arrays), registros (records), enumerações, ponteiros e conjuntos. A seguir, discutiremos brevemente cada um destes tipos.

2.3.1. TIPOS ENUMERADOS

Este tipo permite que você crie uma lista organizada de itens. Para usar um tipo você deve antes declará-lo com a palavra reservada type. Por exemplo, um tipo enumerado que descreve os dias da semana pode ser declarado da seguinte maneira:

implementation{$R *.DFM}

typeSemana = (Segunda, Terça, Quarta, Quinta, Sexta, Sábado, Domingo);

 

Espaços em branco não são permitidos dentro de um elemento. Uma vez declarado um tipo, você deve declarar uma variável pertencente a este tipo. Não usamos o tipo diretamente, mas sim uma variável deste tipo. Por exemplo, vamos supor que queiramos construir um programa que forneça o nome da pessoa escalada para um plantão semanal. Poderíamos declarar uma variável Plantao da seguinte forma:

varPlantao : Semana;

Para atribuir valores à variável Plantao escreva simplesmente:

Plantao := Segunda;Plantao := Terça;etc.

 

2.3.2. TIPOS SUBRANGE

Page 11: Tutorial Delphi

O tipo subrange (subintervalo) permite que você defina um intervalo válido de respostas que um usuário pode inserir em um programa, tal como o número de horas trabalhadas em um mês, a faixa de idade dos membros de um clube, etc. Um subintervalo pode conter os seguintes tipos: boolean, char, integer e tipos enumerados.

A declaração de um tipo subintervalo é similar àquela de um tipo enumerado:

typeSalario_faixa1 = 500 .. 1000;

 

Note que usamos dois pontos para separar os limites do suintervalo, e não vírgulas. Isto permite que o compilador identifique o tipo como um subintervalo e não um tipo enumerado. A seguir, devemos declarar uma variável como pertencente ao tipo declarado anteriormente:

varSalario_Ana : Salario_faixa1;

 

Quando um programa usando subintervalos é executado, e se um valor atribuído a um tipo subintervalo estiver fora do intervalo, o programa gerará um erro de tempo de execução. Veremos mais tarde como capturar este erro de modo a avisar ao usuário que ele deve entrar novamente com os dados, sem que o programa seja abortado. Para que o teste de intervalo seja executado, você deve antes incluir a diretiva de compilação {$R+} no programa, da seguinte forma:

procedure Tform1.ButtonClick (Sender : Tobject);{$R+}

typeSalario_faixa1 = 500 .. 1000;

varSalario_Ana : Salario_faixa1;

 

2.3.3. TIPOS ARRAY

Arrays são matrizes, isto é, coleções ordenadas de elementos de um mesmo tipo de dados, que faz uso de um índice para dar acesso aos itens da coleção. Como array já é um tipo, basta declarar uma variável como array, da seguinte forma:

Page 12: Tutorial Delphi

varDia_da_semana: array [1..7] of string;Dia_do_mês: array [1..31] of integer;

 

Note que separamos os valores mínimo e máximo de um array por dois pontos. Os arrays declarados acima são unidimensionais, isto é, seus elementos podem ser dispostos formando uma única linha. Para atribuir valores a um array proceda da seguinte forma:

beginDia_da_semana [1] := ‘Domingo’;Dia_da_semana [2] := ‘Segunda-feira’;Dia_da_semana [3] := ‘Terça-feira;Dia_da_semana [4] := ‘Quarta-feira’;Dia_da_semana [5] := ‘Quinta-feira’;Dia_da_semana [6] := ‘Sexta-feira’;Dia_da_semana [7] := ‘Sábado’;end;

 

Para armazenar valores de um array em outra variável, podemos escrever:

varDia : string;

beginDia := Dia_da_semana [1];end;

 

e assim por diante. A declaração de arrays multidimensionais é semelhante à de arrays unidimensionais. Por exemplo, para declarar um array a ser usado como uma tabela 30x30, escrevemos:

varBi_array: array [1..30,1..30] of currency;

 

Note que os elementos de um array podem pertencer a qualquer tipo de dados pré-definido ou definido pelo usuário. Os elementos de um array podem ser até mesmo outro array, mas por enquanto ficamos por aqui.

2.3.4. TIPOS RECORD (REGISTRO)

Page 13: Tutorial Delphi

O tipo de dados Record provavelmente é o mais versátil à disposição, pois pode conter tipos de dados heterogêneos. Por exemplo, a folha de pagamento de uma empresa conterá dados do tipo string (nome, endereço, etc), dados do tipo currency (salário), dados do tipo TDateTime (data de contratação) e assim por diante. Não poderíamos usar um array, pois este tipo só pode conter dados de um mesmo tipo. O tipo Record resolve o problema e, mais uma vez, devemos declarar o tipo de dados antes de usá-lo:

typeFolha_Pgto = RecordNome: String;Data_Cont : TDateTime;Salario: currency;end;

varFolha_Abril: Folha_Pgto;

begin

Folha_Abril.Nome := ‘Ana Paula Magalhães’;Folha_Abril.Data_Cont := 10/02/1998;Folha_Abril.Salário := 2200;

end;

 

Note que você deve usar um ponto para separar o nome do Record do nome do campo a que você está se referindo. O Object Pascal, e várias linguagens modernas fornecem uma maneira mais fácil de executar esta operação, usando a instrução With:

begin

With Folha_Abril do begin

Nome := ‘Ana Paula Magalhães’;Data_Cont := 10/02/1998;Salário := 2200;

end;

end;

 

Aqui, o primeiro "end" é da instrução With. A documentação do Object Pascal sugere que você use With quando for possível, pois isto diminui o tempo de execução.

Page 14: Tutorial Delphi

Os tipos Record também podem conter arrays e são bastante usados quando se requer bancos de dados simples. Veremos que o Delphi permite a implementação de estruturas de dados bastante complexas, usando bancos de dados Dbase, Paradox, Access, etc. Contudo, vez por outra não é necessária toda esta sofisticação e é conveniente optar pelos tipos Record. Além disso, nesses casos simples não será necessário instalar os drivers de bancos de dados

3. USANDO COMPONENTES

3.1. CONVENÇÕES DE NOMES PARA COMPONENTES

É sempre bom estabelecer convenções de nomes para componentes do Delphi, sob risco de não se saber, no meio de um projeto mais complicado, qual o tipo de um componente cujo nome é, por exemplo, "dados". A Tabela 3.1 a seguir apresenta alguns exemplos.

Tabela 3.1

Componente Nome em Português

Prefixo Exemplo

Form Formulário frm frmAbrir

Check BoxCaixa de Verificação

chk chkLeitura

Combo BoxCaixa de Combinação

cbo cboPortuguês

ButtonBotão (de comando)

cmd/but cmdCancelar

Label Rótulo lbl lblNome

Edit(Caixa de) Edição

txt/edt txtTelefone

Image Imagem img imgPrincipal

FileListBoxCaixa de Lista de Arquivos

fil filAbrir

DirectoryListBoxCaixa de Lista de Diretórios

dir dirSalvar

Nomes de componentes são locais aos formulários que os contém. Por exemplo, dois formulários diferentes podem conter componentes com o mesmo nome. Usuários iniciantes costumam se preocupar um pouco com isto, mas é como se, em duas casas diferentes, houvessem duas filhas chamadas Ana Paula, também de pais diferentes. Mesmo que se encontrassem, os pais delas jamais fariam confusão.

Page 15: Tutorial Delphi

3.2. O BLOCO DE NOTAS BLOCO.DPR

Processamento de textos é uma das funções básicas dos computadores e o Delphi oferece algumas ferramentas poderosas relacionadas a texto. Nosso objetivo inicial é projetar um Bloco de Notas simplificado que funcione a partir da caixa de memorando do Delphi e que disponha dos seguintes recursos:

Edição básica: inserção e exclusão de texto, movimentação do cursor, etc.;

Seleção de texto; Cortar, copiar e colar textos.

Futuramente, nosso Bloco de Notas se transformará em um editor mais poderoso, capaz de abrir e salvar arquivos do tipo texto e de funcionar também a partir de menus.

O Bloco de Notas usará as seguintes propriedades de componentes do Delphi:

Text: string que contém o texto em uma Caixa de Edição, Memorando ou Rich Edit. O tamanho máximo é 64 kBytes.

Enabled: se for true, o componente é disponível; Visible: se for true, o componente é visível; SelText: string que contém apenas o texto selecionado em uma Caixa

de Edição, Memorando ou Rich Edit.

A propriedade Enabled (que significa "habilitado" ou "disponível") é comum a vários componentes do Delphi. Quando o componente está desabilitado ele aparece acinzentado e o usuário não tem acesso a ele, seja com o mouse seja de outra forma qualquer. Um componente invisível está carregado na memória, o usuário não tem acesso a ele, mas em certas circunstâncias pode ser acessado por meio de código. Por exemplo, você pode alterar certas propriedades de um componente invisível por meio de código, mas não pode definir o foco sobre ele.

Além disso, vamos precisar do método SetFocus, cuja sintaxe é a seguinte:

Objeto. Setfocus.

O "Foco" é uma propriedade comum a todos os componentes do Delphi. Apenas um objeto pode ter o foco de cada vez e apenas objetos visíveis podem receber o foco. Geralmente, o objeto que tem o foco é diferenciado dos outros por uma legenda ou título realçado. Em tempo de execução, o usuário define o foco clicando sobre os objetos ou usando a tecla TAB. O método Setfocus também define o foco para um objeto em tempo de execução, mas de maneira automática. Se ocorrer uma tentativa de definir o foco em um objeto invisível ou desabilitado, um erro de execução será gerado.

a) Criando a interface de BLOCO.DPR

Page 16: Tutorial Delphi

Inicie um novo projeto e desenhe, no formulário, uma Caixa de Memorando (Memo) e quatro botões de comando, conforme ilustrado na Figura 3.1 a seguir.

b) Definindo as propriedades

Defina as propriedades dos componentes de acordo com a Tabela 3.2 a seguir.

Tabela 3.2

COMPONENTE PROPRIEDADE DEFINIÇÃO

Formulário WindowState Maximized

Memo Name txtBloco

Text (vazio)

ScrollBars Vertical

Botão de Comando 1 Name cmdCortar

Caption &Cortar

Botão de Comando 2 Name cmdColar

Caption Co&lar

Botão de Comando 3 Name cmdApagar

Caption &Apagar

Botão de Comando 4 Name cmdSair

Caption &Sair

Note que Memo suporta textos com várias linhas e tem uma barra de paginação vertical. Esta barra de paginação não é um objeto adicional, mas faz parte do componente memorando. O Delphi cuida de toda a automação necessária para a rolagem do texto. Você pode pensar que a disposição dos componentes mostrados na Figura 3.1 é um pouco desorganizada (e realmente

Page 17: Tutorial Delphi

é!). Contudo, em tempo de projeto, não é necessário posicionar os componentes precisamente alinhados no formulário. O alinhamento será feito de maneira automática e muito precisa na inicialização do programa.

c) Escrevendo o código

Neste aplicativo iremos copiar e cortar o texto, sendo necessário usar uma variável para armazenamento temporário de texto. Declare a variável CortaTexto na seção Private da unidade:

type..private

{Private daclarations}CortaTexto : string;. .

O primeiro botão a ser implementado é o "Apagar". Este botão apagará todo o texto da caixa de texto, indiscriminadamente. Tudo o que temos a fazer é "anular" a propriedade text da caixa de memorando. Para tanto, dê dois cliques sobre o botão apagar e escreva o seguinte código:

procedure TfrmBloco.cmdApagarClick (Sender : TObject);begin

txtBloco.Text := ‘ ‘;txtBloco.SetFocus;

end;

Após apagar o texto, o que é feito na primeira linha, devemos jogar o foco novamente na caixa de memorando, pois após clicar o botão "Apagar" o foco ficou com ele. Seria desagradável se o usuário tivesse que clicar na caixa de memorando toda vez que usasse o botão "Apagar". O computador não se importa de prestar este pequeno favor.

O botão "Sair" também é fácil :

procedure TfrmBloco.cmdSairClick (Sender : TObject);begin

Close;

end;

Os manipuladores para os botões "Cortar" e "Colar" requerem um raciocínio adicional. O que desejamos fazer é cortar um trecho de texto para ser colado

Page 18: Tutorial Delphi

em algum outro lugar. Logo, será necessário armazenar o texto recortado em alguma variável temporária, o que será conseguido com a variável CortaTexto. Clique sobre o botão "Cortar" e escreva o seguinte trecho:

procedure TfrmBloco.cmdCortarClick (Sender : TObject);begin

CortaTexto := txtBloco.SelText; txtBloco.SelText := ‘ ‘;txtBloco.SetFocus;

end;

A primeira linha armazena o conteúdo do texto selecionado na variável CortaTexto. A segunda apaga o texto selecionado, dando um efeito de que o texto foi recortado. Finalmente, a última linha joga o foco novamente na caixa de memorando. O manipulador para o botão "Colar" atua de modo inverso a "Cortar", ou seja, devemos recuperar o texto armazenado em CortaTexto e atribuí-lo à propriedade SelText da caixa de memorando, conforme descrito a seguir.

procedure TfrmBloco.cmdColarClick (Sender : TObject);begin

txtBloco.SelText := CortaTexto; txtBloco.SetFocus;

end;

O nosso "mini-editor" já funciona bem, mas algumas melhorias são necessárias. Primeiro, caso o usuário queira redimensionar o formulário, os botões e a caixa de texto não o acompanharão. Este problema pode ser contornado de duas formas. Uma delas envolve o uso do evento Resize do formulário. Este evento ocorre sempre que o formulário é redimensionado, seja por meio do mouse, seja por meio dos ícones de maximizar e minimizar. Resize também ocorre quando o formulário é exibido pela primeira vez, na entrada do programa. O que devemos fazer é ajustar a caixa de texto automaticamente no formulário cada vez que este for redimensionado, o que pode ser conseguido com alguns cálculos.

Com o formulário ativo, vá até o Object Inspector e escolha a opção Events. Clique duas vezes sobre o evento Resize para abrir o manipulador de eventos adequado. Neste manipulador, escreva o código abaixo.

procedure TfrmBloco.FormResize (Sender : TObject);begin

Page 19: Tutorial Delphi

If frmBloco.Width > 50 thenbegin

txtBloco.Top := 0;txtBloco.Left := 0;txtBloco.Width := frmBloco.ClientWidth;txtBloco.Height := frmBloco.ClientHeight - cmdCortar.Height;cmdCortar.Left := 0;cmdColar.Left := cmdCortar.Width;cmdApagar.Left := 2 * cmdCortar.Width;cmdSair.Left := frmBloco.ClientWidth - cmdSair.Width;cmdCortar.Top := frmBloco.ClientHeight - cmdCortar.Height;cmdColar.Top := frmBloco.ClientHeight - cmdColar.Height;cmdApagar.Top := frmBloco.ClientHeight - cmdApagar.Height;cmdSair.Top := frmBloco.ClientHeight - cmdSair.Height;

end;

end;

Estudando a procedure de Resize com cuidado você verá que estamos simplesmente alterando valores de propriedades dos componentes. Em Delphi isto é feito com muito mais freqüência do que você pode imaginar. As primeiras quatro linhas ajustam a caixa de memorando propriamente dita, de forma que sobre espaço em baixo para os botões (é por isso que a altura do botão Cortar - cmdCortar.Height - é descontada). As linhas seguintes ajustam a posição de todos os botões, atuando sobre as propriedades Left e Top.

Como exercício, fica a tarefa de descobrir qual a finalidade do comando If ... Then.

Outra maneira de implementar a mudança automática de tamanho é mudando a propriedade Align de txtBloco para alClient. Isto significa que o memo será automaticamente alinhado em toda a área interna do formulário (área do cliente). Contudo, ao menos neste caso, o efeito obtido não será muito bom, pois estaremos escondendo os botões. Se estivéssemos trabalhando com menus e não com botões não haveria problema, mas isso fica para o próximo capítulo.

3.2.1. MOSTRANDO BITMAPS EM BOTÕES

Os botões de comando convencionais não permitem mostrar bitmaps, mas o Delphi fornece também o componente BitBtn, na página Additional da Paleta de Componentes, que realiza exatamente esta função.

Uma vez inserido este componente, você pode escolher o tipo de bitmap, alterando o valor da propriedade Kind, que pode ser: bkOK, bkYes, bkHelp, bkAbort, bkAll, bkIgnore, bkCancel, bkNo, bkClose e bkRetry. Uma vez

Page 20: Tutorial Delphi

definida esta propriedade, a legenda e o bitmap do botão serão automaticamente inseridos. Talvez você fique preocupado em ver a lagenda aparecer em inglês, mas você sempre pode alterar a propriedade caption manualmente.

Se você não gostou dos bitmaps exibidos pelo Delphi, você pode escolher os seus próprios, alterando a propriedade Glyph. Você também pode alterar a propriedade NumGlyphs para criar um botão animado com até quatro quadros.

 

3.2.2. EXIBINDO DICAS DE COMPONENTES

O Delphi permite que você exiba dicas de botões e demais componentes, ou seja, quando você posicionar o mouse sobre um botão com dicas habilitadas, uma pequena caixinha explicativa aparecerá. Existem quatro propriedades que podem ser alteradas para personalizar as dicas:

ShowHint: se for true, habilita a exibição de dicas; Hint: string que contém o texto explicativo; HintColor: constante que define a cor de fundo da caixa de dicas; HintPause: valor, medido em milisegundos, que determina o tempo que

o mouse deve permanecer sobre o botão para a dica aparecer.

Exemplo:

procedure TForm1.FormCreate (Sender : TObject);begin

cmdCortar.ShowHint := true;cmdOK.Hint := ‘Recorta o texto selecionado’;Application.HintColor := clAqua;Application.HintPause := 200;

end;

3.2.3. EXIBINDO CORES NO DELPHI

Existem duas maneiras de se exibir cores no Delphi:

a) Usando cores pré-definidas:

Cores pré-definidas são acessadas por meio das seguintes constantes:

Tabela 3.3

clBlack Preto clMaroon Marron-terra

clBlue Azul clNavy Azul-marinho

clDkGray Cinza escuro clOlive Verde-oliva

Page 21: Tutorial Delphi

clFuchsia Lilás clPurple Roxo

clGray Cinza clRed Vermelho

clGreen Verde clSilver Prata

clLime Verde-limão clWhite BrancoclLtGray Cinza claro clYellow Amarelo

Os valores destas cores vêem do tempo dos monitores de dezesseis cores e ainda são úteis em várias circunstâncias. Por exemplo, para mudar a cor de fundo de uma caixa de edição para azul, em tempo de execução, escreva:

Edit1.color:=clBlue;

b) Usando a função RGB()

Esta função permite o acesso a todas as cores que o seu monitor é capaz de mostrar, tendo a seguinte sintaxe:

Cor := RGB( vermelho, verde, azul);

onde Vermelho, Verde e Azul são parâmetros do tipo byte que variam de zero até 255. Uma cor RGB, deste modo, é formada por uma parcela de vermelho, uma parcela de verde e uma parcela de azul. Estas são as chamadas cores básicas aditivas. A função RGB permite combinar 255 valores de cores três a três, resultando em mais de dezesseis milhões de cores possíveis. O número final de cores será limitado pelo seu monitor e pela configuração dele. Por exemplo, para mudar a cor de fundo de uma caixa de edição para azul (zero partes de vermelho, zero partes de verde e 255 partes de azul), em tempo de execução, escreva:

Edit1.color:=RGB(0, 0, 255);

3.3. TRATAMENTO DE EXCEÇÕES E UM RELÓGIO DESPERTADOR

É comum que programadores iniciantes não se preocupem com erros e que até alimentem a vã esperança de que o usuário nunca realizará determinada ação que resultaria em um erro em tempo de execução. Os usuários, por outro lado, não parecem pensar assim e, se existe uma maneira de travar o seu programa, pode ter certeza de que o usuário a encontrará.

O Delphi emprega a palavra reservada exception (exceção) para se referir a erros em tempo de execução. A expressão "tratamento de exceções" significa o desenvolvimento de rotinas que sejam capazes de capturar um erro e tratá-lo de forma adequada, evitando o colapso do programa. A sintaxe de um manipulador de exceções é a seguinte:

Page 22: Tutorial Delphi

try[bloco de comandos]except[código de tratamento de erros]end;

Quando você estiver rodando um programa dentro do IDE do Delphi, os manipuladores de exceção somente funcionarão caso a opção Break On Exception do menu Tools | Environment Options estiver desligada. Caso contrário, o programa parará a execução em qualquer exceção, independentemente dos manipuladores.

Uma grande utilidade dos manipuladores de exceção é na validação de dados de entrada e vamos nos valer desta característica para construir um relógio despertador que mostre a hora certa e seja capaz de emitir um alarme quando a hora ajustada já tiver decorrido.

O programa de relógio-despertador utiliza, ainda, algumas funções do Delphi, descritas abaixo.

Time$: retorna a hora atual do sistema, no formato hh:mm:ss; TimeToStr: converte dados do formato Time para String; StrToTime: converte dados do formato String para Time.

Para iniciar o projeto do Relógio Despertador, posicione os seguintes componentes em um formulário, conforme a Figura 3.2:

Dois Rótulos; Dois Botões de Opção; Um Timer.

Um rótulo (página Standard), ou label, é basicamente um componente não editável para saída de dados. Deve ser usado em substituição à caixa

de texto sempre que não for permitido que o usuário edite o texto. Estaremos usando dois rótulos neste projeto: um deles servirá de "display" para mostrar as

Page 23: Tutorial Delphi

horas. Este componente deve ser um rótulo, pois não queremos, evidentemente, que o usuário edite a hora atual !; o outro rótulo terá uma finalidade mais prosaica, servindo apenas para indicar a função da caixa de textos. Rótulos constituem, portanto, um maneira fácil de se imprimir textos no formulário. Para modificar o texto em tempo de execução, mude a propriedade "caption" (rótulos não têm a propriedade "text").

Os botões de opção, algumas vezes denominados "botões de rádio", são semelhantes àqueles botões push-button encontrados em vários tipos de

aparelhos de som. A finalidade é convidar o usuário a escolher apenas uma opção dentre várias.

O componente Timer tem a propriedade Interval ajustada para 1000 ms, ou 1 s, pois desejamos que a hora seja mostrada no display a intervalos de 1 segundo. A Tabela 3.4 mostra as definições dos objetos de Alarme.DPR.

Na seção private da unidade, declare as seguintes variáveis: AlarmeOn e Tempo.

private

{Private declarations}AlarmeOn : boolean;Tempo : TTime;

 

Para começar a inserção do código de optOpção, clique duas vezes nos botões de opção e digite os seguintes trechos:

procedure TfrmAlarme.optOnOffClick(Sender: TObject);begin

AlarmeOn:=false;

end;

 

procedure TfrmAlarme.RadioButton1Click(Sender: TObject);begin

AlarmeOn:=true;

end;

Tabela 3.4

OBJETO PROPRIEDADE DEFINIÇÃO

Page 24: Tutorial Delphi

Formulário Nome frmAlarme

Rótulo Nome lblDispaly

Legenda (vazio)

FonteMS Sans Serif 24 negrito

Caixa de Edição Nome txtAjuste

Botão de Opção 1

Nome optOn

Botão de Opção 2

Nome optOff

Timer Interval 1000

AlarmOn é uma variável booleana que definirá se o som de alarme deve estar ligado ou desligado.

O próximo passo é escrever o código de validação de entrada da caixa de texto txtAjuste. Não queremos que o usuário escreva qualquer coisa nesta caixa. Somente números no formato de hora devem ser permitidos. Para realizar a validação, tentamos converter o texto de txtAjuste para Time. Se a conversão falhar, significa que o texto não é uma hora válida. O erro é capturado e a caixa de edição recebe o texto anterior.

procedure TfrmAlarme.Timer1Timer(Sender: TObject);begin

tryTempo:=StrToTime(txtAjuste.text);except{erro de conversão}beep;txtAjuste.text:=TimeToStr(Tempo);end;

if txtAjuste.text <> '' thenbegin

if (Time > StrToTime(txtAjuste.text)) thenbegin

if AlarmeOn thenbegin

Beep;

end;

end;

Page 25: Tutorial Delphi

end;

lblDisplay.caption:=Tempo;

end;

 

As próximas linhas verificam se a hora ajustada é maior do que a hora atual. Caso seja, um bip é acionado a cada segundo. A última linha do programa exibe a hora atual no display.

Resumindo, o funcionamento do alarme é simples. A cada segundo é gerado um evento de Timer e, capturando este evento, verificamos se o tempo ajustado em txtAjuste é maior ou menor do que o tempo do display lblDisplay. Se for maior, e se o botão de opção estiver na posição "Ligado", fazemos o alto-falante emitir um "bip" a cada segundo. Cada vez que ocorre um evento Timer a função Time$ é usada para atualizar a hora em lblDisplay.

3.4. NOTA SOBRE OS CÓDIGOS ASCII, ANSI E UNICODE

O ASCII é um código de caracteres de 8 bits (1 byte) desenvolvido na época em que só o DOS existia. Com estes 8 bits não é possível representar mais do que 256 caracteres, mas no início as coisas eram mais simples e, memórias de computador, mais caras. O ANSI também é um código de 8 bits, mas inclui alguns caracteres não suportados pelo ASCII. O Windows 3.1 usava o ANSI como padrão, suportando também o ASCII.

O Unicode é um código de 16 bits desenvolvido pela International Standards Organization (ISO), com possibilidade para 65.536 caracteres diferentes. Este espaço é suficiente para acomodar todos os caracteres usados no mundo atualmente, incluindo línguas antigas como sânscrito e hieroglifos egípcios. Também existe espaço vago suficiente para que não se precise preocupar com isto durante mais algumas centenas de anos. O Unicode é totalmente suportado pelo Windows 95 e pelo Windows NT, convertendo-se caracteres do ANSI para o Unicode e vice-versa. Os caracteres são armazenados em ANSI pelo sistema operacional e manipulados em Unicode pelo Delphi.

3.5. ERROS COMUNS EM PROGRAMAÇÃO

3.5.1. FORMULÁRIOS MUITO CARREGADOS

O Delphi disponibiliza uma quantidade fantástica de componentes e é grande a tentação de usar todos em um só formulário. Esta estória é semelhante à de um grande jornal brasileiro que, certa vez, completou a instalação de um parque gráfico de última geração. No dia seguinte, a primeira página do jornal

Page 26: Tutorial Delphi

continha reportagens escritas em todas as cores e fontes disponíveis nos equipamentos, como se os jornalistas não tivessem resistido à tentação de fazer todas as experiências possíveis de um só vez.

O Delphi oferece mais de uma solução para este problema da "densidade gráfica", tais como componentes giratórios (spin buttons), caixas "drop-down", páginas "tab-strip" e outros. A melhor ferramenta, contudo, é uma boa programação gráfica dos formulários. Outra maneira de evitar o carregamento dos formulários é usar componentes carregados dinamicamente, isto é, à medida que o programa vai sendo executado. Lembre-se, o uso excessivo de componentes não será visto como um sinal de que o programador conhece profundamente a linguagem, mas sim como um sinal de amadorismo.

3.5.2. FALTA DE IDENTAÇÃO E ESPAÇAMENTO

O Delphi não exige que você idente o código e compilará trechos de código identados ou não exatamente da mesma maneira. Ainda assim, você descobrirá que a identação é uma ferramenta poderosa na documentação de programas. Facilidade de leitura não é um preciosismo, mas sim um instrumento de depuração muito usado. Infelizmente, linguagens mais antigas, especialmente linguagens para MainFrame, não permitiam a identação nem a presença de linhas em branco. Pior para elas !

3.5.3. USAR NOMES LONGOS

Outra prática desaconselhável é usar nomes longos para variáveis e constantes. Alguns desenvolvedores, em vez de chamar um simples botão de cmdOK, preferem escrever cmdOKformulárioFechaArquivoSemSalvar. Esta prática é totalmente desnecessária e dificulta enormemente a leitura (se bem que eu tenho a impressão de que a intenção destes programadores é justamente esta.).

3.5.4. PROCEDIMENTOS LONGOS

Sempre é possível quebrar um procedimento longo em outros menores, aumentando a reusabilidade do código e facilitando o entendimento. Além disso, procedimentos muito longos tornarão o programa susceptível a estouro de memória.