32
janeiro 2012

The Club - megazine · 2012-07-16 · Delphi e que possui foco na multiplataforma, no artigo “Criando as primeiras aplicações em Lazarus”. Para fechar temos a quarta parte da

  • Upload
    others

  • View
    6

  • Download
    6

Embed Size (px)

Citation preview

Page 1: The Club - megazine · 2012-07-16 · Delphi e que possui foco na multiplataforma, no artigo “Criando as primeiras aplicações em Lazarus”. Para fechar temos a quarta parte da

janeiro 2012

Page 2: The Club - megazine · 2012-07-16 · Delphi e que possui foco na multiplataforma, no artigo “Criando as primeiras aplicações em Lazarus”. Para fechar temos a quarta parte da

janeiro 2012

Page 3: The Club - megazine · 2012-07-16 · Delphi e que possui foco na multiplataforma, no artigo “Criando as primeiras aplicações em Lazarus”. Para fechar temos a quarta parte da

janeiro 2012 03

Desafio The Club

- Dicas Delphi

Dicas

- Cruzada

30

Delphi Delphi

DelphiDelphi

Métodos RAVReport - de A a Z - parte 4

índiceAndroid – Carregando um database do SQLite

Editorial

122012 está aí e o mês de janeiro é o mês

onde mais do que em qualquer época do ano precisamos estar animados para que comecemos bem... 04

Criando uma aplicação Client-server no Delphi - Parte 3 05

Criando os primeiros aplicativos com Lazarus

17

28

22

LegendaInicianteIntermediárioAvançado

Autor:Thiago Cavalheiro Montebugnoli

Autor: Antonio Spitaleri

Autor:Luciano Pimenta

Autor: Leonora Golin

Page 4: The Club - megazine · 2012-07-16 · Delphi e que possui foco na multiplataforma, no artigo “Criando as primeiras aplicações em Lazarus”. Para fechar temos a quarta parte da

janeiro 201204

Bem-vindo

Delphi é marca registrada da Borland International, as demais marcas citadas são registradas

pelos seus respectivos proprietários.

Antonio Spitaleri Neto - Editor [email protected]

2012 está aí e o mês de janeiro é o mês onde mais do que em qualquer época do ano precisamos estar animados, para que co-mecemos bem o ano. E como todos sabem, o que começa bem tem tudo para acabar melhor ainda.

Para cumprirmos a meta de começar bem o ano então, prepa-ramos quatro artigos excelentes para esse mês:

Começamos com a terceira parte da matéria de Luciano Pimen-ta: “Criando uma aplicação Client – Server em Delphi”. Essa matéria sem dúvida ao longo dos últimos meses vem desmitificando a lógica Client – Server em Delphi.

Na sequência Thiago Montebugnoli segue nos apresentando a plataforma Android no artigo “Carregando uma base de dados SqlLite”.

Esse mês apresento a vocês uma nova ferramenta aqui na re-vista The Club. Trata-se do Lazarus, uma ferramenta baseada em Delphi e que possui foco na multiplataforma, no artigo “Criando as primeiras aplicações em Lazarus”.

Para fechar temos a quarta parte da viagem de nossa colabo-radora Leonora Golin pelos métodos do Rave Report no artigo “Métodos Rave Report de A a Z”.

É isso.Bom início de ano a todos e até fevereiro !

www.datasmart.com.br

www.theclub.com.br

Av. Profº Celso Ferreira da Silva, 190 Jd. Europa - Avaré - SP - CEP 18.707-150

Informações e Suporte: (14) 3732-1529

Internethttp://www.theclub.com.br

Cadastro: [email protected]: [email protected] Informações: [email protected] Cadastro: theclub_cadastro

Skype Suporte: theclub_linha1 theclub_linha2 theclub_linha3

www.twitter.com/theclubbr

Copyright The Club Megazine 2009

Diretor TécnicoMarcos César Silva

Diagramação e ArteVitor M. Rodrigues

RevisãoEliziane Valentim

ColunistasAntonio Spitaleri Neto

Bruno AlcarásEduardo Massud

Leonora GolinLuciano Pimenta

Thiago Cavalheiro Montebugnoli

Impressão e acabamento:GRIL - Gráfica e Editora

Taquarituba-SP - Tel. (14) 3762-1345

ReproduçãoA utilização, reprodução, apropriação, armazenamento em banco de dados, sob qualquer forma ou meio, de textos, fotos e outras criações intelectuais em cada publicação da revista “The Club Megazine” são terminantemente proibidos sem autorização escrita dos titulares dos direitos autorais.

Page 5: The Club - megazine · 2012-07-16 · Delphi e que possui foco na multiplataforma, no artigo “Criando as primeiras aplicações em Lazarus”. Para fechar temos a quarta parte da

janeiro 2012 05

Delphi

Continuaremos neste artigo a criação da nossa aplicação cliente-server com Delphi. Até agora, já criamos os cadastros necessá-rios para clientes, peças e veículos. Agora, precisamos criar os cadastros referentes aos serviços que a oficina realizará.

Primeiramente vamos criar o cadastro de orçamento. A lógica do sistema indica que o cliente chega e pretende fazer um serviço, portanto, a oficina cadastra um orçamento para ele. Não vamos usar agora, nosso for-mulário base de cadastro. Teremos outro for-mulário para isso, também herdado, mas com características diferentes do que já vimos.

Poderíamos usar o formulário visto até aqui, mas teríamos que fazer adaptações e deixo a cargo do leitor, se preferir, fazer isso.

Criando formulário

Na Figura 1 podemos ver nosso formulário

Criando uma aplicação client-server no Delphi

Parte III

novo. Ele tem características simples e alguns méto-dos pré-definidos (veja o fonte que esta disponível para download).

Veja a figura 1.

Figura 1. Formulário base da aplicação

Vamos criar o formulário de cadastro de or-çamento, que funcionará da seguinte maneira: o cliente chega e precisa ser cadastrado. Se o mesmo já for cadastrado, basta digitar seu nome na caixa de texto e apertar ENTER.

Page 6: The Club - megazine · 2012-07-16 · Delphi e que possui foco na multiplataforma, no artigo “Criando as primeiras aplicações em Lazarus”. Para fechar temos a quarta parte da

janeiro 201206

Mostraremos uma tela com uma consulta baseada no valor digitado pelo usuário. Essa tela de consulta pode ser genérica e usarmos em ou-tros pontos do sistema. Basta o usuário escolher o valor desejado na tela de consulta que o sistema irá preencher os dados do usuário e seu veículo.

No primeiro momento, imaginamos que o cliente possua apenas um veículo, mas ele pode ter mais de um. Assim, faça a adaptação necessária para se o cliente tiver mais, seja mostrada uma tela para o usuário escolher o veículo a ser arrumado. Veja na Figura 2 a tela de orçamento.

Veja a figura 2.

Note que além da opção de digitação para o cliente, que comentei a pouco, temos ainda o botão para pesquisa de cliente (igual ao usado no cadastro de veículos) e também o botão para incluir um novo cliente.

Nesse botão, abrimos o cadastro de clientes e depois, filtramos os dados do último cliente inse-rido, usando o MAX(nCdCliente) em um consulta auxiliar. Veja o código na Listagem 1.

Listagem 1. Filtrando o novo registro

//abre o cadastro de clientesAbreForm(TfrmCliente, frmCliente);

//após inserir, atualiza com o último cliente criadoDM.cdsUltimoCliente.Open;

DM.cdsCliente.Close;DM.cdsCliente.Params[0].AsInteger := DM.cdsUltimoClienten CdCliente.AsInteger;DM.cdsCliente.Open;

edtCliente.Text := DM.cdsClientesNmCliente.AsString;

//filtra o veículoFiltrarVeiculo(DM.cdsClientenCdCliente.AsInteger);

DM.cdsCliente.Close;

Figura 2. Tela de orçamento do sistema

O código SQL do cdsUltimoCliente, é simples:

select max(nCdCliente) as nCdCliente from CLIENTE

Para filtrar os dados do veículo, criamos mais um ClientDataSet para retornar os dados, de acordo com o cliente passado por parâmetro (filtrado no método FiltrarVeiculo). Como comentei anterior-mente, em uma aplicação real, teríamos que esco-lher o veículo, já que o cliente pode ter mais de um.

Depois da tela pronta e dos filtros configura-dos, precisamos salvar o cadastro. Vamos utilizar a mesma classe criada anteriormente e usada nos cadastros. Poderíamos criar um ClientDataSet no Data Module, e apenas preencher o mesmo com os valores digitados pelo usuário e executar o salvar da classe.

Nesse exemplo, vamos fazer diferente, vamos criar o ClientDataSet em tempo de execução. Veja o código na Listagem 2.

Listagem 2. Criando o ClientDataSet e salvando o orçamento

procedure TfrmOrcamento.Salvar;var cds: TClientDataSet; field: TField;begin cds := TClientDataSet.

Create(self);

try field := TIntegerField.Create(cds); field.FieldName := ‘nCdVeiculo’; field.DataSet := cds;

field := TStringField.Create(cds); field.Name := ‘sNmCliente’; field.FieldName := ‘sNmCliente’; field.Size := 50; field.DataSet := cds;

field := TDateTimeField.Create(cds); field.Name := ‘tDtOrcamento’; field.FieldName := ‘tDtOrcamento’; field.DataSet := cds;

field := TStringField.Create(cds); field.Name := ‘sDsProblema’; field.FieldName := ‘sDsProblema’; field.Size := 400; field.DataSet := cds;

Page 7: The Club - megazine · 2012-07-16 · Delphi e que possui foco na multiplataforma, no artigo “Criando as primeiras aplicações em Lazarus”. Para fechar temos a quarta parte da

janeiro 2012 07

field := TIntegerField.Create(cds); field.Name := ‘nIdStatus’; field.FieldName := ‘nIdStatus’; field.DataSet := cds;

//preenche Cds cds.CreateDataSet; cds.Insert; //variável auxiliar, preenchida na filtragem do veículo cds.FieldByName(‘nCdVeiculo’).AsInteger := nCdVeiculo; cds.FieldByName(‘sNmCliente’).AsString := edtCliente.Text; cds.FieldByName (‘tDtOrcamento’).AsDateTime := dtDataOrcamento.Date; cds.FieldByName (‘sDsProblema’).AsString := mmProblema.Text; cds.FieldByName (‘nIdStatus’).AsInteger := 1; //orçamento ativo cds.Post;

FClasseBase.Conection := DM.SysCar; FClasseBase.sNmTabela := ‘ORCAMENTO’; FClasseBase.Campos := cds; if FClasseBase.Salvar(true) then begin MessageDlg( ‘Registro salvo com sucesso’, mtInformation, [mbOk], 0); //limpa tela e fecha DataSet LimparCampos; dsVeiculo.DataSet.Close; nCdVeiculo := 0; end; finally field.Free; cds.Free; end;end;

Note que com a utilização da nossa classe, fica simples, salvar o orçamento. Pode parecer trabalhoso, e é, criar o ClientDataSet em tempo de execução, mas usamos aqui, apenas para fins didáticos.

Criamos o ClientDataSet, os campos neces-sários e preenchemos o valor do mesmo. Depois apenas configuramos a classe, como já fizemos na tela de cadastro. Simples e prático. Veja na Figura 3 o cadastro em execução.

Veja a figura 3.

Caso você deseje não usar esse método onde criamos o ClientDataSet em tempo de execução, basta colocar um componente no DataModule, criar os campos e alterar o Salvar para o código da Listagem 3.

Listagem 3. Alterando o método Salvar para o ClientDataSet do DataModule

procedure TfrmOrcamento.Salvar;begin DM.cdsOrcamento.CreateDataSet; DM.cdsOrcamento.Insert;

DM.cdsOrcamentonCdVeiculo.AsInteger := nCdVeiculo; DM.cdsOrcamentosNmCliente.AsString := edtCliente.

Text; DM.cdsOrcamentotDt Orcamento.AsDateTime := dtDataOrcamento.Date; DM.cdsOrcamentosDsProblema.AsString := mmProblema.Text; DM.cdsOrcamentonIdStatus.AsInteger := 1;

DM.cdsOrcamento.Post;

FClasseBase.Conection := DM.SysCar; FClasseBase.sNmTabela := ‘ORCAMENTO’; FClasseBase.Campos := DM.cdsOrcamento; if FClasseBase.Salvar(true) then ...end;

Temos ainda que fazer a validação dos campos obrigatórios. Então, criei um método, que verifica os campos obrigatórios não preenchidos e emite uma mensagem. Veja o código na Listagem 4.

Listagem 4. Validando campos obrigatórios

function TfrmOrcamento.Validar: boolean;

Figura 3. Cadastro de orçamento

Page 8: The Club - megazine · 2012-07-16 · Delphi e que possui foco na multiplataforma, no artigo “Criando as primeiras aplicações em Lazarus”. Para fechar temos a quarta parte da

janeiro 201208

begin if edtCliente.Text = ‘’ then MessageDlg(‘Campo: Nome do cliente. Preenchimento obrigatório.’, mtWarning,[mbOk], 0) else if mmProblema.Text = ‘’ then MessageDlg(‘Campo: Problema indicado pelo cliente. Preenchimento obrigatório.’, mtWarning,[mbOk], 0);

Result := (edtCliente.Text <> ‘’) and (mmProblema.Text <> ‘’);end;

No evento do botão, basta executar o código:

if Validar then Salvar;

Pesquisa genérica

Como comentei, uma funcionalidade que te-remos no orçamento é a do usuário digitar o nome do cliente, apertar ENTER e será mostrada uma tela de pesquisa de clientes com os parâmetros digitados pelo usuário.

A tela de pesquisa em si, será simples. Basta um grid e um botão de confirmação. A boa notícia, que podemos utilizar a mesma em outros pontos da aplicação, apenas mudando o DataSet esperado pelo Grid. Veja na Figura 4 a tela de pesquisa.

Veja a figura 4.

Ao olhar o código, você irá notar que temos configuração para o nome das colunas do Grid, além de mostrar a quantidade de registros encon-trados. A tela é bastante semelhante a da pesquisa do componente Localizar.

No Edit da tela de orçamento, vamos codificar seu evento OnKeyPress com o código da Listagem 5.

Figura 4. Tela de pesquisa genérica do sistema

Listagem 5. Codificando o KeyPress do Editif Key = #13 thenbegin DM.cdsPesquisaCliente.Close; DM.cdsPesquisaCliente.Params[0].AsString := UpperCase(edtCliente.Text+’%’); DM.cdsPesquisaCliente.Open;

if DM.cdsPesquisaCliente.RecordCount = 1 then edtCliente.Text := DM.cdsPesquisaClientesNm Cliente.AsString else if DM.cdsPesquisaCliente.RecordCount > 1 then begin try frmPesquisa := TfrmPesquisa.Create(self); frmPesquisa.dsPesquisa.DataSet := DM.cdsPesquisaCliente; frmPesquisa.Descricao := ‘Nome do cliente’; if frmPesquisa.ShowModal = mrOk then edtCliente.Text := DM.cdsPesquisaClientesNm Cliente.AsString finally frmPesquisa.Free;

end; end;

//se preencheu nome, então filtra o veiculo if edtCliente.Text <> ‘’ then FiltrarVeiculo(DM.cdsPesquisa ClientenCdCliente.AsInteger);end;

Note que passamos para o componente de pesquisar clientes o valor digitado pelo usuário. Se o resultado da pesquisa retornar um registro, preenchemos o valor do nome do cliente com esse registro. Caso a quantidade de registros encontra-dos, for maior, então mostramos a tela de pesquisa.

Veja que não usamos nosso código de abrir formulário, por que precisamos configurar algumas propriedades do formulário de pesquisa. Assim, passamos o DataSet que será mostrado, bem como o nome da coluna de descrição de registros.

Caso deseje usar a tela em outro formulário, basta mudar o DataSet e a variável do nome da coluna. Bem simples, com muito reaproveitamento de código. Veja na Figura 5 a tela em execução.

Veja a figura 5.

Pesquisando orçamentos

Após a criação do orçamento, os funcionários da oficina, irão verificar os problemas do veículo. Assim, necessitam preencher o parecer do orça-mento. Precisamos criar uma tela de pesquisa de

Page 9: The Club - megazine · 2012-07-16 · Delphi e que possui foco na multiplataforma, no artigo “Criando as primeiras aplicações em Lazarus”. Para fechar temos a quarta parte da

janeiro 2012 09

Figura 5. Tela de pesquisa sendo usada no orçamento

orçamentos para o usuário escolher o orçamento, salvar os dados do parecer e indicar se deseja que o orçamento, se “transforme” em uma ordem de serviço. Veja na Figura 6 a tela.

Veja a imagem 6.

A consulta que retorna os dados do orçamento esta no código a seguir:

select ORC.nCdOrcamento, ORC.nCdVeiculo, ORC.sNmCliente, ORC.tDtOrcamento, VE.sNrPlaca, VE.sNmModelo from ORCAMENTO ORC inner join VEICULO VE on VE.nCdVeiculo = ORC.nCdVeiculo where ORC.nIdStatus = 1

Estamos trazendo os dados do orçamento que estejam ativos (nIdStatus = 1). Para filtrar os dados pela placa, não refaremos a consulta, usaremos o ClientDataSet para isso. Ou seja, teremos os dados em memória, sem precisar “ir” no servidor para o novo filtro.

Veja no código da Listagem 6 o código.

Listagem 6. Filtrando os dados do ClientData-Set em memória

if edtPlaca.Text <> ‘’ thenbegin DM.cdsPesquisaOrcamento.Filter := ‘sNrPlaca = ‘ + QuotedStr(edtPlaca.Text); DM.cdsPesquisaOrcamento.Filtered := true;endelse DM.cdsPesquisaOrcamento.Filtered := false;

Verificamos se foi digitado algum valor na caixa de texto. Caso positivo, passamos para a proprieda-de Filter do ClientDataSet o que desejamos filtrar, no caso o número da placa. Note que não estamos

Figura 6. Tela de pesquisa de orçamentos

fazendo uma pesquisa aproximada, mas sim, exata.

A propriedade Filtered “ativa” o filtro. Assim, caso você deseje retornar para a pesquisa total, basta limpar a caixa de texto e clicar no botão. Para editarmos o orçamento, bastará dar um duplo clique no registro no Grid.

Aqui, vamos apenas alterar o valor do parecer na tabela, não editaremos nenhum outro dado. Você pode adaptar para editar os registros que desejar. Vamos criar um formulário com os dados do orçamento e um campo para edição. Veja na Figura 7 o formulário.

Figura 7. Editando o orçamento

O DBText1 nada mais é do que campo calcula-do que concatena os campos nome do cliente, placa e modelo. Para criar o campo calculado, acesse o componente de pesquisa de orçamentos. Abra o editor de campos e aperte Ctrl + N. Adicione as

Page 10: The Club - megazine · 2012-07-16 · Delphi e que possui foco na multiplataforma, no artigo “Criando as primeiras aplicações em Lazarus”. Para fechar temos a quarta parte da

janeiro 201210

configurações, conforme a Figura 8.

Veja a figura 8.

Para que possamos mostrar a concatenação dos campos, devemos usar o evento OnCalcFields do ClientDataSet. Adicione o seguinte código:

cdsPesquisaOrcamentos DsMensagem.AsString := cdsPesquisaOrcamentos NmCliente.AsString + ‘ - ‘ + cdsPesquisaOrcamentos NrPlaca.AsString + ‘ - ‘ + cdsPesquisaOrcamentos NmModelo.AsString;

No código, estamos preenchendo o campo, com a “junção” dos campos que queremos mostrar. Devemos agora, configurar a edição do orçamen-to, com o parecer. Não vamos usar a classe que estamos acostumados. Vamos alterar apenas um campo, acredito que não vale a pena o esforço.

Portanto, vamos apenas atualizar o parecer, usando um comando SQL simples em um método no DataModule. Veja o código na Listagem 7.

Listagem 7. Método para atualizar parecer do Orçamento

procedure TDM.AtualizarParecer(sDs Parecer: string; nCdOrcamento: integer);var sql: string; Query: TSQLQuery;begin sql := ‘update ORCAMENTO set sDsParecer = ‘ + QuotedStr(sDsParecer) + ‘ where nCdOrcamento = ‘ + IntToStr(nCdOrcamento);

Query := TSQLQuery.Create(nil);

try Query.SQLConnection := SysCar; Query.SQL.Clear; Query.SQL.Add(sql); Query.ExecSQL(); finally

Figura 8. Configurando um campo calculado no ClientDataSet

Query.Free; end;end;

Para testar, apenas chamamos o método no Salvar do formulário, conforme a Listagem 8.

Listagem 8. Salvando o parecer

if mmParecer.Text = ‘’ then MessageDlg(‘Campo: Parecer. Preenchimento obrigatório.’, mtWarning,[mbOk], 0)elsebegin DM.AtualizarParecer (mmParecer.Text, DM.cdsPesquisaOrcamentonCdOrcamento.AsInteger); MessageDlg(‘Registro salvo com sucesso’, mtInformation, [mbOk], 0); Close;end;

igura 9. Cadastro em execução

Conclusões

Vimos nesse artigo a criação da tela de orça-mento da aplicação. Também criamos algumas funcionalidades interessantes na mesma, como a tela de pesquisa, que pode ser genérica e ser usada em vários locais da nossa aplicação.

No próximo artigo, vamos começar a criar a tela de ordem de serviço que terá peculiaridades interessantes, pois precisaremos adicionar peças/serviços em memória para depois, quando o usu-ário confirmar, todos os itens serem adicionados no banco.

Um grande abraço a todos e até a próxima!

É Técnico em Processamento de Dados, desenvolvedor Delphi/C# para aplicações Web com ASP.NET e Windows com Win32 e Windows Forms. Palestrante da 4ª edição da Borland Conference (BorCon).

Autor de mais de 60 artigos e de mais de 300 vídeos aulas publicadas em revistas e sites especializados. É consultor da FP2 Tecnologia (www.fp2.com.br) onde ministra cursos de programação e banco de dados. É desenvolvedor da Paradigma Web Bussi-ness em Florianópolis-SC.

Sobre o autor

Luciano Pimenta

www.lucianopimenta.net

Page 11: The Club - megazine · 2012-07-16 · Delphi e que possui foco na multiplataforma, no artigo “Criando as primeiras aplicações em Lazarus”. Para fechar temos a quarta parte da

janeiro 2012 11

Page 12: The Club - megazine · 2012-07-16 · Delphi e que possui foco na multiplataforma, no artigo “Criando as primeiras aplicações em Lazarus”. Para fechar temos a quarta parte da

janeiro 201212

No artigo deste mês continuaremos falando do pequeno e notável Sistema Android junto com o SQLite. Pudemos conferir no mês anterior um exemplo simples de cadastro utilizando uma classe para acesso a dados. Criamos na mesma classe os comandos DML(Data Manipulation Language) e os DDL(Data Definition Language), ou seja, definimos nossa Base de Dados e manipulamos nossos dados via código.

Neste artigo irei explorar um gerenciador do Banco de Dados SQLite chamado “SQLite Expert Personal” e depois criaremos um projeto para carregar os dados inseridos pelo mesmo. Tenho como objetivo carregar um arquivo .db do SQLite que já está pronto, com suas tabelas definidas e com dados. Isto se faz necessário, pois torna fácil a manipulação e criação de estruturas para o Banco de Dados deixando a parte da programação no Android apenas para comando de Manipulação de Dados.

SQLite Expert Personal

Este gerenciador de Banco de Dados possui várias funções disponíveis suportando visualizações de várias Bases de Dados simultaneamente, permite gerenciar campos de índice e chaves primárias. Possui também ferramentas para criação de gatilhos e visões.

O “SQLite Expert Personal” tem uma interface bem simples e intuitiva para que qualquer pessoa possa utilizá-lo. É interessante informar que a versão

Android – Carregando um database do SQLite

“Professional” é paga, portanto com alguns recursos adicionais, mas no nosso caso que não queremos gastar nada utilizaremos a versão “Personal” que pode ser baixada no seguinte endereço:

http://www.sqliteexpert.com/download.html

A instalação

A instalação é bem fácil e prática, Next, Next, Next e Install, a Figura 01 nos proporciona a conclusão da mesma.

Figura 01: Instalação do SQLite Expert Personal.

Page 13: The Club - megazine · 2012-07-16 · Delphi e que possui foco na multiplataforma, no artigo “Criando as primeiras aplicações em Lazarus”. Para fechar temos a quarta parte da

janeiro 2012 13

Criando uma Base de Dados

Veremos como é fácil a manipulação no SQLite Expert Personal, depois de iniciado clique em File/New database para podermos criar nossa base de Dados, defina as seguintes configurações,

Ver Imagem 02.

Database File: C:\Users\THIAGOO\Desktop\DBTHECLUBDatabase Alias: DBTHECLUBEncoding: UTF-8Page Size: 1024Auto Vacuum: 0

Figura 02: Propriedades.

Criando uma Tabela

Para isto clique com o botão direito em cima do “DBTHECLUB” e escolha “New Table”. Em Table Name defina como TB_CLIENTE e no botão ADD adi-cionaremos os seguintes campos, veja abaixo:

Figura 03: Campos Necessários.

O comando para criar a tabela ficou da seguinte maneira:

CREATE TABLE [TB_CLIENTE] ([COD_CLI] INT NOT NULL, [TIP_CLI] VARCHAR(20), [NOM_CLI] VARCHAR(50), [END_CLI] VARCHAR(50), [BAI_CLI] VARCHAR(50),[CID_CLI] VARCHAR(40),

[EST_CLI] VARCHAR(2), [CEP_CLI] VARCHAR(15), CONSTRAINT [] PRIMARY KEY ([COD_CLI]));

Logo em seguida armazenaremos alguns dados para prosseguirmos nosso exemplo prático.

Figura 04: Exemplo de inserção de Dados na tabela TB_CLIENTE.

Criando a tabela de Metadados

Para podermos trabalhar com o SQLite precisamos criar uma tabela de controle interno denominada “android_metadata” com o seguinte campo “locale” do tipo TEXT e atribuir um registro “en_US”.

Veja a instrução SQL para isto:

CREATE TABLE android_metadata (locale TEXT);

Figura 05: Exemplo de inserção de Dados na Tabela android_metadata.

Criando uma Classe para acesso

Para isto precisamos criar um exemplo básico em Android clicando em “File/New/ Android Project” e logo em seguida crie também uma classe e importe alguns pacotes para podermos prosseguir nosso exemplo.

package Pct.BancoDados;

import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.util.ArrayList;

Page 14: The Club - megazine · 2012-07-16 · Delphi e que possui foco na multiplataforma, no artigo “Criando as primeiras aplicações em Lazarus”. Para fechar temos a quarta parte da

janeiro 201214

import java.util.List; import android.content.Context;import android.database.Cursor;import android.database.SQLException;import android.database.sqlite.SQLiteDatabase;import android.database.sqlite.SQLiteException;import android.database.sqlite.SQLiteOpenHelper;import android.database.sqlite.SQLiteStatement;

public class Base extends SQLiteOpenHelper{

}

É interessante lembrar que esta classe herda da SQLiteOpenHelper. Para entendermos melhor, iremos utilizar o arquivo gerado pelo “SQLite Expert Per-sonal”. Copie o arquivo localizado em C:\Users\THIAGOO\Desktop\DBTHECLUB ou no lugar que foi criado e cole no diretório “assets” do nosso exemplo. Neste caso programaremos uma rotina para copiar a base de dados para dentro do exemplo em questão.

Voltando a criação de nossa classe, definiremos logo em seguida alguns atributos para a mesma, veja abaixo o código completo com uma breve expli-cação de seus métodos para melhores detalhes:

public class DataBaseHelper extends SQLiteOpenHelper{ private static String DB_PATH=”/data/data/Pct.BancoDados/databases/”; private static String DB_NAME = “DBTHECLUB.db”;private SQLiteDatabase dbQuery; private final Context dbContexto;

O primeiro atributo armazenará o caminho do Banco de Dados, o segundo o Nome e as duas últimas são variáveis para controle interno sendo uma o Cursor de Nossa Classe SQLiteDatabase e outra o nosso Contexto em si.

public DataBaseHelper(Context context) { super(context, DB_NAME, null, 1); this.dbContexto = context;}

Este é o Construtor de nossa classe DataBaseHelper, ele captura e mantém uma referência do contexto passado para ter acesso aos recursos da aplicação.

public void CriarDataBase() throws IOException { boolean dbExist = checkDataBase();

if (!dbExist) { this.getReadableDatabase(); try { this.copiarDataBase(); } catch (IOException e) { throw new Error(“Erro ao copiar o Banco de Dados!”); } }}

Este Método é responsável por criar nossa Base de Dados, ou seja, uti-liza a função copiarDataBase(); para obter os dados que está na nossa pasta “assets” e jogar para nosso Sistema Android. Verifiquem que utilizamos mais uma função para checar se nossa Base de Dados já está criada, denominada checkDataBase() .

Abaixo as duas importantes funções que utilizaremos ao decorrer do artigo.

private void copiarDataBase() throws IOException{ InputStream myInput = dbContexto.getAssets().open(DB_NAME); String outFileName = DB_PATH + DB_NAME; OutputStream myOutput = new FileOutputStream(outFileName); byte[] buffer = new byte[1024]; int length; while ((length = myInput.read(buffer))>0){ myOutput.write(buffer, 0, length); } myOutput.flush(); myOutput.close(); myInput.close(); } private boolean checkDataBase(){ SQLiteDatabase checkDB = null; try { String myPath = DB_PATH + DB_NAME;checkDB = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.

Page 15: The Club - megazine · 2012-07-16 · Delphi e que possui foco na multiplataforma, no artigo “Criando as primeiras aplicações em Lazarus”. Para fechar temos a quarta parte da

janeiro 2012 15

OPEN_READONLY); } catch (SQLiteException e) {} if (checkDB != null) { checkDB.close(); } return checkDB != null ? true : false;}

public void abrirDataBase() throws SQLException{ String myPath = DB_PATH + DB_NAME;dbQuery = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY);}

public List<String> selecionaTodos(String NomeTabela, String OrdemCampo, String...TipoCampos) {List<String> list = new ArrayList<String>(); Cursor cursor = dbQuery.query(NomeTabela, TipoCampos, null, null, null, null, OrdemCampo); if (cursor.moveToFirst()) { do {list.add(cursor.getString(0) +” - “ + cursor.getString(1) + “ - “+ cursor.getString(2)); } while (cursor.moveToNext()); }

if (cursor != null && !cursor.isClosed()) { cursor.close(); } return list;} @Overridepublic synchronized void close() { if (dbQuery != null) dbQuery.close(); super.close();} }

O método abrirDataBase() permite que armazenemos todas as informa-ções referentes ao Banco de Dados em uma variável, possibilitando o uso da

mesma posteriormente.

Já o Método selecionaTodos() nos devolve uma lista de strings para poder-mos trabalhar, falaremos um pouco mais deste método quando chamarmos o mesmo pela nossa IDE do Android.

E por final finalizamos nossas variáveis com o método Close().

Criando um exemplo Básico

Depois de Criarmos nossa classe de acesso, finalizamos criando um exem-plo para selecionar todos os clientes cadastrados no SQLite, adicionamos então apenas um Label em nossa tela principal e definimos sua ID para out_text, Ver Figura 06 e logo abaixo o código fonte.

Figura 06: Tela.

<?xml version=”1.0” encoding=”utf-8”?><LinearLayout xmlns:android=”http://schemas.android.com/apk/res/android” android:orientation=”vertical” android:layout_width=”fill_parent” android:layout_height=”fill_parent” ><TextView android:id=”@+id/out_text” android:layout_width=”fill_parent” android:layout_height=”wrap_content” android:text=”@string/hello” /></LinearLayout>No evento OnCreate é onde programaremos nossa rotina para chamar o método SelecionarTodos(), abaixo o código fonte completo para melhores detalhes:

Page 16: The Club - megazine · 2012-07-16 · Delphi e que possui foco na multiplataforma, no artigo “Criando as primeiras aplicações em Lazarus”. Para fechar temos a quarta parte da

janeiro 201216

package Pct.BancoDados;

import java.io.IOException;import android.app.Activity;import android.os.Bundle;import android.widget.TextView;import java.util.List;

public class BancoDadosActivity extends Activity { TextView output; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); output = (TextView) this.findViewById(R.id.out_text); DataBaseHelper db = new DataBaseHelper(this); try { db.createDataBase(); } catch (IOException e) { e.printStackTrace(); } db.openDataBase();List<String> names = db.selecionaTodos(“TB_CLIENTE”,”COD_CLI”, “COD_CLI”, “NOM_CLI”, “TIP_CLI”); StringBuilder sb = new StringBuilder(); sb.append(“Clientes Cadastrados:\n”); for (String name : names) { sb.append(name + “\n”); } output.setText(sb.toString()); }}

Primeiro definimos uma variável para armazenar nosso resultado, denomi-nada “output”, logo em seguida instanciamos nossa classe “DataBaseHelper” criada anteriormente. Utilizaremos o método “criarDatabase()” e depois o abrirDataBase().

O método selecionaTodos() possui os seguinte parâmetros:

Nome da Tabela: TB_CLIENTEOrdenação: COD_CLI

Campos para Selecionar: COD_CLI, NOM_CLI, TIP_CLI

E por final armazenaremos em uma StringBuilder para podermos jogar em nossa variável “output”.

Figura 07: Exemplo em Run Time.

Conclusões

Pudemos aprender neste artigo um pouco da utilização da ferramenta “SQLite Expert Personal”. Vimos que a mesma possibilita a manutenção e a administração tanto da parte de criação quanto na manipulação de dados.

O objetivo deste artigo foi de demonstrar a possibilidade de ter um ban-co de dados já criado e usá-lo em uma aplicação Android. Percebemos que isto é possível e muito prático em alguns casos específicos e se torna muito viável para o desenvolvedor, pois o Banco de Dados é facilmente manipulado por fora do sistema, se tornando independente da aplicação. A criação de Classes e métodos específicos torna o sistema mais genérico e de uma fácil implementação futura.

Espero que este exemplo básico seja de grande ajuda,

Um forte abraço e até o mês que vem!

Thiago Cavalheiro Montebugnoli é tecnólogo, formado pela Faculdade de Tecnologia de Botucatu – SP (FATEC) foi consultor técnico do The Club, já desenvolveu softwares utilizando a plataforma .NET, Delphi junto com Banco de Dados SQL Server e Firebird. Atualmente trabalha no Centro de Proces-samento de Dados da Prefeitura Municipal de Itaí-SP. Possui as seguintes certificações: MCP - Microsoft Certified Professional, MCTS - Microsoft Certi-fied Technology Specialist, MCAD - Microsoft Certified Application Developer e MCSD - Microsoft Certified Solution Developer.

Sobre o autor

Thiago Cavalheiro Montebugnoli

[email protected]

Page 17: The Club - megazine · 2012-07-16 · Delphi e que possui foco na multiplataforma, no artigo “Criando as primeiras aplicações em Lazarus”. Para fechar temos a quarta parte da

janeiro 2012 17

Os programadores Delphi que antes de se “aventurarem” pelo mundo da programação visual, com janelas, botões, etc... passaram pela programação modo console com certeza se não trabalharam, ouviram falar do compi-lador FreePascal e sua IDE.

FreePascal é hoje um compilador que evoluiu bastante e teve incoraporadas diversas melhorias, inclusive a capacidade de compilação para Linux, MacOs e outras plataformas, até mesmo móveis.

Você deve estar se perguntando porque estou falando de FreePascal se o mesmo não possui boas funcionalidades para aplicações comerciais. Isso está correto, porém existe um excelente projeto OpenSource que se destina a aplicações comerciais e que faz uso do compilador FreePascal. Trata-se do Lazarus.

Quando surgiu, em suas primeiras ver-sões, a comunidade Delphi não deu muita importância ao Lazarus, devido ao fato de possuir muitos bugs e ter um visual de IDE pouco atrativo. Porém ao longo dos últimos releases , esses problemas tem sido gradual-mente solucionados e hoje podemos afirmar que Lazarus é sim uma alternativa muito boa ao Delphi nas situações em que o custo da licença do mesmo se torna inviável.

Criando os primeiros apl icat ivos com Lazarus

Não iremos propor nesse artigo a substi-tuição do Delphi pelo Lazarus. Ao contrário. Iremos mostrar que o uso integrado de ambas as ferramentas pode ser possível e até reco-mendado em alguns casos.

O que facilita e muito a vida dos progra-madores Delphi que pensam em conhecer o Lazarus é o fato de 90% ou mais dos códigos Delphi serem compatíveis com Lazarus. Além disso a própria ferramenta possui um Wizard para conversões de projetos Delphi para Lazarus e vice-versa.

O Lazarus também conta hoje com acesso nativo aos principais bancos de dados Open Source: Firebird, MySql e SqlLite.

Outra característica importante a se destacar no Lazarus é que podemos instalar a principal suíte de componentes para automa-ção comercial existente hoje: ACBr. Isso sem dúvida é de grande ajuda para quem trabalha com ECF’s e Nota fiscal eletrônica.

Download e Instalação

O site oficial do projeto é:

http://www.lazarus.freepascal.org/

Nesse site são encontradas a documentação disponível sobre o Lazarus e na seção Downloads, as diversas opções:

Veja a imagem 01.

Veja que o Lazarus está disponível não só para Windows, como também para Linux, Solaris, Mac OS entre outros. Escolha a opção que se adequa a seu sistema operacional e faça o download.

Para usuários Windows, a instalação segue o padrão de instalação, com a execução de um insta-lador que fará algumas perguntas sobre localização de arquivos entre outras.

Para Linux, existe a opção de baixar os pacotes RPM, para OpenSuse, Mandriva e outras distros derivadas do Red Hat ou então os pacotes Deb, para as distribuições baseadas em Debian, como o Ubuntu.

Após concluir a instalação, já podemos exe-cutar o Lazarus. A tela inicial, que pode variar dependendo do sistema operacional utilizado, será semelhante a vista na imagem 2:

Veja a imagem 02.

Veja que a IDE é bem semelhante ao Delphi. Assim que abrimos o aplicativo, nos é dado um

Page 18: The Club - megazine · 2012-07-16 · Delphi e que possui foco na multiplataforma, no artigo “Criando as primeiras aplicações em Lazarus”. Para fechar temos a quarta parte da

janeiro 201218

projeto já carregado com um formulário. Temos o Object Inspector à esquerda e acima a paleta de componentes.

É na paleta de componentes que está a princi-pal diferença inicial entre Delphi e Lazarus, já que muitos componentes que temos no Delphi não temos em Lazarus. Não temos por exemplo as di-versas abas de componentes de acesso a banco de dados: DbExpress, ADO, etc... As conexões a banco estão agupadas na aba SqlDB. Uma característica interessante é que temos acesso nativo ao banco de dados SqlLite.

A aba mais semelhante sem dúvida é a Stan-dard, onde temos os componentes mais básicos: Edit, Label, ComboBox, entre outros.

Lembrando que não temos, devido ao fato da ferramenta ser multiplataforma, os componentes que são característicos do Windows e que em Delphi ficam na aba Win32, como por exemplo o ListView.

Em artigos posteriores estaremos estudando em maiores detalhes os componentes do Lazarus.

Criando as primeiras aplicações.

Para começar, iremos criar uma aplicação que pedirá um valor ao usuário e retornará esse valor por extenso.

Na barra de menus do Lazarus, selecione File – New.

Na janela mostrada na imagem 3. Selecione Application.

Veja a imagem 03.

Será aberta a janela inicial do projeto.

Iremos utilizar três componentes da aba Standard:

Edit(Aba Standard):Name:Edit1;Text:’Digite o valor aqui’

Label(Aba Standard):Name:Label1;Caption:Valor por extenso

Button(Aba Standard):Name: Button1;Caption:’Extenso’

Monte o Layout do formulário conforme a imagem 4:

Imagem 04. Vamos agora ao código da aplicação:

unit Main;

{$mode objfpc}{$H+}

interface

uses Classes, SysUtils,

Imagem 01.

Imagem 02.

FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls;

type

{ TForm1 }

TForm1 = class(TForm) Button1: TButton; Edit1: TEdit; Label1: TLabel; procedure Button1Click(Sender: TObject); private { private declarations } public { public declarations } end;

var Form1: Tform1;

Page 19: The Club - megazine · 2012-07-16 · Delphi e que possui foco na multiplataforma, no artigo “Criando as primeiras aplicações em Lazarus”. Para fechar temos a quarta parte da

janeiro 2012 19

// Os três arrays a seguir são os valores por extenso que serão utilizados para a construção da // string de resultado da função extenso

Dezenas:array[0..9]ofstring=(‘Dez’,’Vinte’,’Trinta’,’Quarenta’,’Cinquenta’,’Sessenta’,’Setenta’,’Oitenta’,’Noventa’,’Cem’;

UnidadesDez:array[0..4]of string=(‘Onze’,’Doze’,’Treze’,’Quatorze’,’Quinze’);

Unidades:array[0..8]of string=(‘Um’,’Dois’,’Três’,’Quatro’,’Cinco’,’Seis’,’Sete’,’Oito’,’Nove’);

implementation

{$R *.lfm}

// Na sequência a função que receberá um valor inteiro e o devolverá por extenso

function Extenso(Valor: Integer): String;var Fator, Dezena:Integer;begin

if not(Valor in[0..100])then // Limitamos o valor a ser digitado pelo usuário, gerando uma exceção caso o mesmo seja // maior que 100

raise Exception.Create(‘Escolha um valor entre 0 e 100 !’) else begin if(Valor=0)then Result:=’Zero’ // Retorna ‘zero’ caso o número escolhido pelo usuário seja 0 else begin Fator:=Valor mod 10; // Pegamos o resto da divisão do valor por 10 Dezena:=Valor div 10; // Pegamos a parte inteira da divisão acima

if(Dezena=0)then // Se o valor for menor que 10, retornamos a string correspondente do

Imagem 03.

array Unidades Result:=Unidades[Valor-1] else begin if(Dezena=1)then begin

// Se o valor estiver entre 10 e 19, retornamos a string fazendo uso do //array UnidadesDez

if(Fator=0)then Result:=’Dez’ else begin if(Fator<=5)then Result:=UnidadesDez [Fator-1] else Result:=Dezenas[Dezena-1]+’e’+LowerCase(Unidades[Fator-1]); end; end else begin

// Caso o valor esteja acima de 19, não faremos uso do array

unidadesdez

if(Fator=0)then Result:=Dezenas[Dezena-1] else Result:=Dezenas[Dezena-1]+’ e ‘+Unidades[Fator-1]; end; end; end; end;end;

{ TForm1 }

// Aqui o evento OnClick do Button1, onde pegamos o valor digitado pelo usuário e utilizamos // a função extenso para retornar a string com o valor por extenso.procedure TForm1.Button1Click(Sender: TObject);begin Label1.Caption:=Extenso (StrToInt(Edit1.Text));end;

end.

Na sequência, vamos criar uma aplicação para exibirmos uma imagem.

Vamos utilizar quatro componentes:

Page 20: The Club - megazine · 2012-07-16 · Delphi e que possui foco na multiplataforma, no artigo “Criando as primeiras aplicações em Lazarus”. Para fechar temos a quarta parte da

janeiro 201220

OpenDialog(Aba Dialogs)

Image(Aba Additional):Name:Image1;Stretch:True

Button(Aba Standard):Name:Button1;Caption:’Selecione a imagem’;

Label(Aba Standard):Name:Label1;Caption:’Caminho da imagem’

O layout deverá ficar como na imagem 5:

Na sequência, o código da aplicação:

uses Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, ExtCtrls, StdCtrls,JPEGLib;

type

{ TForm1 }

TForm1 = class(TForm) Button1: TButton; Image1: TImage; Label1: TLabel; OpenDialog1: TOpenDialog; procedure Button1Click(Sender: TObject); private { private declarations } public { public declarations } end;

var Form1: TForm1;

implementation

{$R *.lfm}

{ TForm1 }

procedure TForm1.Button1Click(Sender: TObject);begin OpenDialog1.Filter:=’Jpeg Files|*.jpg’;

if(OpenDialog1.Execute)then begin Label1.

Caption:=OpenDialog1.FileName; Image1.Picture.LoadFromFile(OpenDialog1.FileName); end;end;

end.

Veja que para a carga da imagem não temos muita diferença entre o código que utilizaríamos no Delphi. Apenas a unit necessária para a leitura dos arquivos Jpeg, que no Delphi seria Jpeg, no Lazarus é JpegLib. Isso mostra que a adaptação de progra-madores Delphi ao Lazarus será bem tranquila.

Veja o aplicativo em execução:

Veja a imagem 06.

Para finalizar e demonstrar a compatibilidade de código entre Delphi e Lazarus, criaremos uma calculadora bem simples.

Iremos utilizar os seguintes componentes:

Button(Aba Standard):Name:btnCalcula;Caption: Calcular

ComboBox(Aba Standard)Name:cmbOperacoes;Items:’Adição’, ‘Subtração’,’Multiplicação’,

‘Divisão’;ItemIndex:0

Label(Aba Standard):Name:Label1;Caption:’Escolha a operação’

Edit(Aba Standard):Name:edtValor1;Text:’Valor 1’

Edit(Aba Standard)Name:edtValor2Text:’Valor 2’

Veja o Layout da aplicação:

Vamos ao código deste exemplo:

unit Unit1;

{$mode objfpc}{$H+}

interface

uses Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls;

type

{ TForm1 }

TForm1 = class(TForm) btnCalcula: TButton; ComboBox1: TComboBox; edtValor1: TEdit;

Imagem 05.

Page 21: The Club - megazine · 2012-07-16 · Delphi e que possui foco na multiplataforma, no artigo “Criando as primeiras aplicações em Lazarus”. Para fechar temos a quarta parte da

janeiro 2012 21

Consultor Técnico The Club.

Sobre o autor

Antonio Spitaleri Neto

[email protected]

edtValor2: TEdit; Label1: TLabel; procedure btnCalculaClick(Sender: TObject); private { private declarations } public { public declarations } end;

var Form1: TForm1;

implementation

{$R *.lfm}

{ TForm1 }

procedure TForm1.btnCalculaClick(Sender: TObject);var Result, Valor1, Valor2:Extended;begin Valor1:=StrToFloat (edtValor1.Text); Valor2:=StrToFloat (edtValor2.Text);

// Testamos os valores do combobox para obter a operação // a ser feita

case ComboBox1.ItemIndex of 0: Result:=Valor1+Valor2; 1: Result:=Valor1-Valor2; 2: Result:=Valor1*Valor2; 3: if(Valor2<>0)then // Para evitar erro de divisão por zero Result:=Valor1/Valor2;

end;

// Exibimos o resultado ShowMessage(‘O resultado é: ‘+FloatToStr(Result));end;

end.

Conclusão

A ferramenta Lazarus, além de seu grande crescimento nos últimos tempos, está tendo grandes avanços na parte de multiplataforma, área onde o Delphi também começa a se destacar com o Firemonkey e a possibilidade de compilação para MacOs.

Para usuários Linux e que precisam desenvol-ver para Windows também, Lazarus é altamente recomendado, já que é em Linux que Lazarus alcan-ça melhor desempenho. Lazarus hoje é compatível com as principais distros Linux, tanto nas versões 32 quanto 64 bits.

Lembrando que o compilador FreePascal já compila para 64 bits. Isso é ideal quando precisa-mos criar dll’s cujo alvo serão sistemas operacionais 64 bits.

Na parte de conexão a bancos de dados, em-bora ainda não possua drivers de alto desempenho, Lazarus possui conexão nativa e fácil a Firebird e MySql e além disso, para melhor desempenho, podemos instalar a suíte Zeos no mesmo, o que gera um ganho de desempenho em acesso a dados.

Como dissemos no começo do artigo, não estamos aqui propondo a substituição de Delphi pelo Lazarus e sim apresentar uma alternativa viável para as situações em que Delphi não puder ser utilizado, seja por uma questão de licença ou devido a restrições do sistema operacional.

Nos próximos artigos estarei detalhando a ferramenta e mostrando os poderosos recursos que a mesma oferece.

Por enquanto é isso. Espero que tenham gos-tado e até a próxima!

Imagem 06.

Page 22: The Club - megazine · 2012-07-16 · Delphi e que possui foco na multiplataforma, no artigo “Criando as primeiras aplicações em Lazarus”. Para fechar temos a quarta parte da

janeiro 201222

MÉTODOS RAVEReportde A a Z

SSEARCH NEXT – este método continua

a pesquisa iniciada pelo SearchFirst. Esta fun-ção retorna True se encontra uma combinação e False, se não.

SELECT BIN – este método seleciona um bin contendo BinName em sua descrição e retorna um valor Booleano se foi bem su-cedido ou não.

Example (Delphi)

SelectBin(‘UPPER’);

SELECT PAPER – este método se-leciona um tamanho de papel contendo PaperName em sua descrição e retorna um valor booleano se foi bem sucedido ou não.

Example (Delphi)

SelectPaper(‘LEGAL’);

SELECT PRINTER – Este método define a impressora atual para a primeira im-pressora em Printers que contém a substring SubStr em seu nome. ExactMatch determi-na se é necessário uma correspondência exata ou não no nome da impressora. Se nenhuma impressora for encontrada, então a impressora atual não é alterada e retorna

um valor False.

Example (Delphi)

SelectPrinter(‘Laser’, false);

SELECT REPORT – este método sele-ciona o relatório especificado por ReportNa-me. Se FullName é True, a função pesquisa o relatório cujo nome completo combina. De outra forma, pesquisa os apelidos. O resul-tado da função é se a seleção do relatório ReportName foi bem sucedida ou não.

SET BRUSH – este método configura o pincel atual para parâmetros dados. Se ne-nhum bitmap é desejado, o valor deve ser nil.

Example (Delphi)

Page 23: The Club - megazine · 2012-07-16 · Delphi e que possui foco na multiplataforma, no artigo “Criando as primeiras aplicações em Lazarus”. Para fechar temos a quarta parte da

janeiro 2012 23

RvNDRWriter1.SetBrush(clBlack, bsClear, nil);

SET COLUMNS – este método con-figura um número específico de colunas, NewColumns, com uma separação Between, entre cada coluna. A largura da coluna é calculado para caber dentro da SectionLeft atual e SectionRight.

Example (Delphi)

// Este código mostra como criar 4 colunas e enviar saída para elas. SetColumns(4,0.5);while ColumnLinesLeft > 0 do beginPrintLn(IntToStr(LinesLeft) + ‘/’ + IntToStr(ColumnLinesLeft) + ‘/’ + IntToStr(LineNum) + ‘/’ + IntToStr(ColumnNum));end; { while }

SET COLUMN WIDTH – este método configura a coluna para uma largura especí-fica, Width, com uma separação, Between, entre cada coluna. O número de colunas é calculado para caber dentro das atuais Sec-tionLeft e SectionRight.

Example (Delphi)

// Criar colunas de 2 polegadas de largura e meia polegada à parte.RvNDRWriter1.SetColumnWidth( 2.0, 0.5 );

SET DATA – Este método atribui os dados em Buffer (para BufSize bytes) para o buffer de memória. Isto pode ser útil para

longas strings que são mais de 255 caracteres.

Example (Delphi)

// Atribuir um PChar a um buffer de memória. MemoBuf.SetData(PCharVar^, StrLen(PCharVar));

SET FONT – este método configura a fonte corrente para os parâmetros dados. NewSize é o tamanho do ponto da fonte (1/72 de uma polegada).

Nota: Se estiver sendo usado um conjun-to de símbolos, é preciso usar FontCharSet depois do método SetFont.

Example (Delphi)

RvNDRWriter1.SetFont( ‘Arial’, 10 );

SET PAPER SIZE – Este método define o tamanho de papel atual da impressora se-lecionada para as configurações de uma API do Windows, Size constante (ver TDevMode.dmPaperSize) ou se Widht e Height são dife-rentes de zero, então ele irá tentar definir um tamanho de papel personalizado.

Nota: Nem todos os drivers de impres-sora suportam tamanhos de página perso-nalizados e a maioria tem valores mínimos e máximos aceitáveis.

Example (Delphi)

// Configurar papersize para 10 polegadas por 12 polegadas e depois configurar para 8.5 e 14 polegadas. RvNDRWriter1.SetPaperSize(0,10,12);RvNDRWriter1.SetPaperSize(DMPAPER_LEGAL,0,0);

SET PARAM – SetParam permite que

ao aplicativo passar parâmetros de projeto para o projeto Rave atualmente carregado. Estes parâmetros podem ser usados para controlar layouts dinâmicos, parâmetros SQL ou outros itens para imprimir em um relatório criado visualmente.

Example (Delphi)

RvProject1.SetParam (‘UserName’,UserName);

SET PEN – Este método define a pena atual para os parâmetros dados. O parâmetro NewWidth, se positivo, é a largura da caneta em unidades de impressão (pontos) e, se negativo, é a largura da caneta em 1/100ths de uma polegada.

Example (Delphi)

RvNDRWriter1.SetPen(clBlack,psSolid,-2,pmCopy);

SET PI VAR – Este método permite inicializar o valor de um PIVar (Post Initialize Variável). Qualquer PIVars de mesmo nome, que foi previamente impressa irá mostrar esse valor. Um uso comum para PIVars é imprimir um total em uma faixa de cabeçalho que seria inicializado depois na banda de rodapé. Isso funciona mesmo através de várias páginas. TRvSystem.SystemOptions.soUserFiler deve ser verdade se se estiver usando PIVars no relatório.

SET RTF – funciona exatamente como SetData, com exceção dos dados armazena-dos em Buffer que são RTF texto.

SET TAB – este método adiciona uma configuração de tabulação.

NewPos Define a posição inicial da

Page 24: The Club - megazine · 2012-07-16 · Delphi e que possui foco na multiplataforma, no artigo “Criando as primeiras aplicações em Lazarus”. Para fechar temos a quarta parte da

janeiro 201224

tabulação. Se NewPos está configurada para a constante NA, então a tabulação começa imediatamente depois da caixa de tabulação anterior.

NewJustify define se a tabulação está à esquerda (pjLeft), de centro-direita (pjRight) ou (pjCenter) justificada. Se uma largura diferente de zero é dada, então uma caixa de separador é definida e o texto deve ser justificado dentro da caixa de tabulação ao invés de justificar a posição da tabulação.

NewMargin define a distância entre o lado da caixa de tabulação e o texto em 1/100ths de uma polegada

NewLines usa as constantes BoxLi-neXxxx para definir em torno do que as linhas serão desenhadas.

NewShade define o percentual de sombreamento de fundo para usar nessa caixa de tabulação.

Example (Delphi)

ClearTabs;SetPen(clBlack, psSolid,1, pmCopy);SetTab(0.5,pjCenter,3.5,0, BOXLINEALL,0);SetTab(NA, pjCenter,1.0,0, BOXLINEALL,0);SetTab(NA, pjCenter,1.5,0, BOXLINEALL,0);SetTab(NA, pjCenter,1.5,0, BOXLINEALL,0);Bold := true;Tab(-2,NA,-2,-2,NA);Print(‘Name’);Tab(NA,NA,-2,-2,NA);Print(‘Number’);Tab(NA,NA,-2,-2,NA);Print(‘Amount 1’);Tab(NA,-2,-2,-2,NA);PrintLn(‘Amount 2’);Bold := false;

SET TOP OF PAGE – este método configura a SectionTop para a parte de baixo

da linha corrente.

Example (Delphi)

RvNDRWriter1.SetTopOfPage;

SHADE TO COLOR – esta função cria uma cor que somente tem um valor Shade-Percent de Shadecolor.

SHOW PRINT DIALOG – traz uma caixa PrintDialog padrão do Windows. Usar esta função ao Invés do componente TPrin-tDialog do Delphi.

Example (Delphi)

if RvNDRWriter1.ShowPrintDialog then beginRvNDRWriter1.Execute;end; { if }

SHOW PRINTER SETUP DIALOG – traz uma caixa PrinterSetupDialog padrão do Windows. Usar esta função ao invés do componente TPrinterSetupDialog do Delphi.

Example (Delphi)

if RvNDRWriter1.ShowPrinterSetupDialog then beginRvNDRWriter1.Execute;end; { if }

SOFT LINE – Este método deve ser chamado para ir para a próxima linha em um documento RTF exportado sem inserir um retorno de carro. Para saída baseada na im-pressora (TRvRenderPrinter, TRvNDRWriter), este método executa o mesmo que NewLine.

START – Para TRvRenderPreview, este

método inicia uma sessão de visualização e chama a primeira página para a tela de visuali-zação. Usar os métodos, PrevPage, NextPage, PrintPage, ZoomIn e ZoomOut para interagir com o usuário da tela de visualização após Start ter sido chamado. Para TRvNDRWriter, estes métodos iniciar um trabalho de im-pressão que deve ser encerrado mais tarde, com uma chamada para Concluir. Todos os manipuladores de eventos são ativos, exceto para OnPrint e OnPrintPage que são usados apenas com Execute.

Example (Delphi)

RvRenderPreview1.Start;

STRETCH DRAW – este método dese-nha o objeto gráfico Graphic, esticado ou en-colhido, para caber dentro do retângulo Rect.

Nota: StretchDraw não deve ser usado para bitmaps. Ao invés disso, usar PrintBitmap ou PrintBitmapRect.

SUPPORT BIN – este método retor-na True se o número bin (ver TDevMode.dmDefaultSource no Help API do Windows) especificado pelo BinNum é suportado pela impressora. De outra forma, retorna False.

SUPORT COLLATE – este método retorna True se a impressora suporta agrupa-mento. De outra forma, retorna False.

SUPPORT DUPLEX – este método re-torna True se a impressora suporta impressão em duas faces.

SUPPORT ORIENTATION – este método retorna True se a impressora suporta mudança de orientação.

Page 25: The Club - megazine · 2012-07-16 · Delphi e que possui foco na multiplataforma, no artigo “Criando as primeiras aplicações em Lazarus”. Para fechar temos a quarta parte da

janeiro 2012 25

SUPPORT PAPER – este método re-torna True se o número do papel especificado em PaperNum é suportado pela impressora. De outra forma, retorna False.

TAB – Este método define as configu-rações da tabulação atual para a próxima tabulação disponível. Se a próxima tab é uma caixa de tab, então as linhas para aquela tab são desenhadas neste momento, bem como qualquer sombra que se possa aplicar. O Lef-tWidth, RightWidth, TopWidth e BottomWi-dth são substituições para a largura da lateral da caixa de tab em 1/100ths de uma polegada, mas deve ser passado como a constante NA, para a largura da caneta padrão. Se os pa-râmetros LeftWidth, RightWidth, TopWidth ou BottomWidth (s) são positivos, então é a largura da caneta em unidades de impressão (pontos) e, se negativo, é a largura da caneta na 1/100ths de uma polegada. ShadeOverride é uma porcentagem de sombreamento para desenhar o fundo da caixa de tab e substitui TabShade ou a configuração original do som-breamento de uma caixa de tabulação.

Example (Delphi)

with RvNDRWriter1 do beginTab(-2,NA,-2,-2,NA);Print(‘First tab’);Tab(NA,NA,-2,-2,NA);Print(‘Second tab’);end; { with }

TAB END- este método retorna a po-sição final horizontal da caixa de tabulação especificada pelo Índice. Se o Índice é 0 então o resultado será para a tabulação corrente e se Índice for maior que o número de tabula-ções definidas, então retorna um valor de 0.0.

Example (Delphi)

// Fim da região da tabulação atual. CurrEnd := RvNDRWriter1.TabEnd( 0);

TAB START – este método retorna a posição horizontal inicial da caixa de tabulação especificada pelo Índice. Se o Índice é 0 então o resultado será a tabulação atual e se o Índice for maior que o número de tabulações definidas então será retornado um valor de 0.0.

Example (Delphi)

// Inicia região de tabulação atual CurrStart := RvNDRWriter1.TabStart( 0);

TAB WIDTH – este método retorna a largura da caixa de tabulação especificada pelo Índice. Se o Índice for 0 então o resultado será a tabulação atual e se Índice for maior que o número de tabulações definidas, então retornará um valor 0.0.

Example (Delphi)

// Largura da região de tabulação atual. CurrWidth := RvNDRWriter1.TabWidth( 0);

TEXT RECT – Este método irá desenhar texto cortado dentro do retângulo definido por Rect. O ponto (X, Y) define o ponto de partida do texto. Use CreateRect para ini-cializar Rect.

Example (Delphi)

var TxtRect: TRect; TxtXPos: double; TxtYPos: double; Txt: string;beginTxtRect := CreateRect( 1.00,1.00,3.00,3.00);TxtXPos := 0.95;TxtYPos := 0.95;Txt := ‘Text is clipped off!’;TextRect(TxtRect, TxtXPos, TxtYPos, Txt);end;

TEXT WIDTH – este método retorna o tamanho da string Text.

Example (Delphi)

var TxtLen: double;begin TxtLen := TextWidth( “How long am I?” );end;

UNREGISTER GRAPHIC – Este méto-do ajuda a gerenciar a repetição de grandes bitmaps em um trabalho de impressão. É usado para garantir que o índice usado pelo RegisterGraphic é claro. Deve-se chamar este método se um gráfico já foi previamente registrado naquele índice. Porém, é seguro e recomendado sempre chamar Unregiste-redGraphic antes de usar estes métodos de índices de gráficos.

UPDATE STATUS – Este método atuali-zará o rótulo definido pelo StatusLabel com a informação atual definida pelo estado do re-latório ou pelos itens contidos em StatusText.

Example (Delphi)

// Depois da execução do relatório, dependendo se o usuário abortou a criação dos relatórios ou não, a barra de status é atualizada com a mensagem apropriadaif Aborted then beginStatusFormat := #13’Report Canceled!’;UpdateStatus;end else beginStatusFormat := #13’Report Completed!’;UpdateStatus;end; { else }

WRITEBCD DATA – Este método escreve o conteúdo de um campo BCD per-

Page 26: The Club - megazine · 2012-07-16 · Delphi e que possui foco na multiplataforma, no artigo “Criando as primeiras aplicações em Lazarus”. Para fechar temos a quarta parte da

janeiro 201226

Consultora Técnica The Club.

Sobre o autor

Leonora Golin

[email protected]

sonalizado (do tipo dtBCD) dentro do evento OnGetRow de um componente data connec-tion. Os dados para o campo customizado deve ser escrito na mesma ordem em que os campos foram definidos no evento OnGe-tCols. O parâmetro FormatData define o valor formatado do campo, mas pode ser branco se uma saída não formatada for necessária. O parâmetro NativeData deve conter o con-teúdo não modificável do campo.

Example (Delphi)

Connection.WriteBCDData( ‘ ‘,InvoiceAmount );

WRITE BLOB DATA – Este método escreve o conteúdo de um campo blob personalizado (do tipo dtBlob / dtGraphic / dtMemo) dentro de um evento OnGetRow de um componente data connection. Os da-dos para os campos personalizados deve ser escrito na mesma ordem em que os campos foram definidos no evento OnGetCols.

Example (Delphi)

Connection.WriteBlobData( ‘’,CustomerPict );

WRITE BOOL DATA – Este método escreve o conteúdo de um campo boolean personalizado (do tipo dtBoolean) dentro de um evento OnGetRow de um componente data connection. Os dados para os campos personalizados deve ser escrito na mesma ordem em que os campos foram definidos no evento OnGetCols. Os parâmetros FormatDa-ta define o valor formatado do campo, mas pode ser branco se uma saída não formatada for necessária. O parâmetro NativeData deve conter o conteúdo não modificável do campo.

Example (Delphi)

Connection.WriteBoolData( ‘’,CustomerActive );

WRITE CURR DATA – Este método grava o conteúdo de um campo de moeda personalizado (de tipo dtFloat) dentro do evento OnGetRow de um componente de conexão de dados. Os dados para campos personalizados devem ser escritos na mesma ordem em que os campos foram definidos no evento OnGetCols. Os parâmetros formatdata definem o valor formatado do campo, mas podem ficar em branco se não for necessá-ria uma saída pré-formatada. Parâmetros NativeData devem conter o conteúdo não modificável do campo.

Example (Delphi)

Connection.WriteCurrData( ‘’,InvoiceAmount );

WRITE DATE TIME – Este método grava o conteúdo de um campo DateTime personalizado (de tipo dtDate / dtTime / dtDateTime) dentro do evento OnGetRow de um componente de conexão de dados. Os dados para campos personalizados devem ser escritos na mesma ordem em que os campos foram definidos no evento OnGetCols. Os parâmetros formatdata definem o valor formatado do campo, mas podem ficar em branco se não for necessária uma saída pré--formatada. Parâmetros NativeData devem conter o conteúdo não modificável do campo.

Example (Delphi)

Connection.WriteDateTime( ‘’,Now );

WRITE FLOAT DATA - Este método grava o conteúdo de um campo BCD perso-nalizado (de tipo dtFloat) dentro do evento OnGetRow de um componente de conexão de dados. Os dados para campos personalizados devem ser escritos na mesma ordem em que os campos foram definidos no evento OnGe-tCols. Os parâmetros formatdata definem o valor formatado do campo, mas podem ficar em branco se não for necessária uma saída pré-formatada. Parâmetros NativeData devem conter o conteúdo não modificável do campo.

Example (Delphi)

Connection.WriteFloatData( ‘’,CustomerBudget );

WRITE INT DATA – Este método grava o conteúdo de um campo integer persona-lizado (de tipo dtInteger) dentro do evento OnGetRow de um componente de conexão de dados. Os dados para campos personalizados devem ser escritos na mesma ordem em que os campos foram definidos no evento OnGe-tCols. Os parâmetros formatdata definem o valor formatado do campo, mas podem ficar em branco se não for necessária uma saída pré-formatada. Parâmetros NativeData devem conter o conteúdo não modificável do campo.

Example (Delphi)

Connection.WriteIntData( ‘’,CustomerCount );

Page 27: The Club - megazine · 2012-07-16 · Delphi e que possui foco na multiplataforma, no artigo “Criando as primeiras aplicações em Lazarus”. Para fechar temos a quarta parte da

janeiro 2012 27

Page 28: The Club - megazine · 2012-07-16 · Delphi e que possui foco na multiplataforma, no artigo “Criando as primeiras aplicações em Lazarus”. Para fechar temos a quarta parte da

janeiro 201228

Dicas DELPHI

ALTERANDO TRECHO ESPECIFICO DE UMA INSTRUÇÃO SQL

As vezes precisamos trabalhar com as instrução SQL em um determinado trecho, para que não tenha que ser refeita essa instrução podemos alterar de acordo com a linha a que precisa ser modificada, para isso utilizamos a seleção da linha da instrução, para isso utilizamos a referencia da linha a ser alterada.

SELECT ID_CLIENTE, NOME, DATA_NASCIMENTO, SEXOFROM CLIENTEWHERE ( ID_CLIENTE < 1000 )AND ( SEXO = ‘M’ )ORDER BY NOME

Como exemplo é utilizado uma instrução SQL simples, como exemplo iremos mudar a categoria do campo sexo, somente alterando a linha corres-pondente.

if cdsCliente.Active then Close;cdsCliente.SQL[6] := ‘AND (SEXO = ‘F’)’;cdsCliente.Open;

Basta utilizar esta simples função que fecha a conexão e altera a linha indicada, lembrando que a contagem destas linhas é iniciada à partir da linha 0, capturando a instrução indicada, sobrescrevendo a anterior no momento em que é reaberta a conexão com o banco de dados

EXTRAINDO CONTEÚDO DE UM CAMPO DATA

Para extrair um campo com dia, mês e ano atuais utilizamos as System Tables, que são as tabelas do sistema, propriamente ditas, elas nos dão à opção de controlar todos os registros autônomos, que não dependem dos registros disponíveis pelo usuário, isso é, são independentes das tabelas definidas pelo usuário e seus dados, um exemplo é o controle de Data e Hora extraindo suas propriedades de dia mês e ano através destas tabelas auto-geradas pelo sistema na hora em que é criado o banco.

SELECT EXTRACT(DAY FROM CURRENT_DATE) AS Dia, EXTRACT(MONTH FROM CURRENT_DATE) AS Mes, EXTRACT(YEAR FROM CURRENT_DATE) AS AnoFROM RDB$DATABASE;

Nesta instrução SQL estamos retornando como resultado o dia, mês e ano atual, de acordo com as informações extraídas do campo RDB$DATABASE, que irá trazer os dados da data atual através da tabela CURRENT_DATE, que será informada pelos dados do servidor, que é de onde está executando o serviço firebird.

EXTRAINDO TODOS OS CAMPOS DE CHAVE PRIMÁRIA DE UMA TABELA

Uma função importante realizada pelas tabelas do sistema é a listagem da quantidade de chaves primárias existentes em uma tabela para isso utilizamos uma função SQL que irá exibir todos os campos da tabela selecionada e filtrando pelo índice de listagem das chaves primárias e a tabela RDB$INDEX_SEGMENTS serve para resgatar o tipo de campo como chave primária e listando os seus índices

SELECT RDB$FIELD_NAME AS CHAVESFROM RDB$RELATION_CONSTRAINTS, RDB$INDEX_SEGMENTSWHERE RDB$RELATION_CONSTRAINTS.RDB$RELATION_NAME = ‘MOTORES’ AND RDB$RELATION_CONSTRAINTS.RDB$CONSTRAINT_TYPE = ‘PRIMARY KEY’ AND RDB$INDEX_SEGMENTS.RDB$INDEX_NAME = RDB$RELATION_CONSTRAINTS.RDB$INDEX_NAME ORDER BY RDB$FIELD_POSITION

Esta instrução irá gerenciar e listar todos os campos de chave primária existentes na tabela, facilitando a busca pelos dados da tabela.

Page 29: The Club - megazine · 2012-07-16 · Delphi e que possui foco na multiplataforma, no artigo “Criando as primeiras aplicações em Lazarus”. Para fechar temos a quarta parte da

janeiro 2012 29

EXECUTANDO THREADS EM PROCESSOS SEPARADOS NA APLICAÇÃO

Nessa dica, iremos criar um thread que servirá para ser executada em segundo plano assim que o processo principal esteja rodando no computador.

O primeiro passo é criar um tipo que herdará a classe TThread, em que seu método protegido será criado o procedimento Executar, utilizando a palavra reservada override que servirá para sobrescrever o método, além do método público onde será definido seu método de criação

type TThreadBack = class(TThread) private

protected procedure Executar; override; public constructor Create();end;

O próximo passo é criar e instanciar o método construtor

constructor TThreadBack.Create();begin

Agora estaremos colocando o método em estado de espera temporaria-mente, para que seja executado no momento necessário.

inherited Create(True);

Libera o objeto da memória assim que terminado, para que não compro-meta o processo do CPU para um objeto inutilizado

FreeOnTerminate := True;

Precisamos também definir a prioridade para o CPU, sendo do tipo TpLo-wer, que deixará o sistema trabalhando com o processo no método com sua prioridade baixa

Priority := TpLower;

E por fim inicia o Thread para que seja executado em segundo plano

Resume;end;

E para que possamos executar nosso Thread, devemos

procedure ThreadBack.Execute;begin // Aqui será executando as funções do Thread que estará em segundo planoend;

BLOQUEAR A TECLA TAB

Para bloquear a tecla TAB devemos verificar se as teclas ALT ou o próprio TAB pressionado, caso tenham sido pressionados, zeramos o valor da chave da tecla e a propriedade, e habilitando o uso com a propriedade Handled, para que não ocorra erros

if (Msg.Message = WM_KEYDOWN) AND (Msg.wParam = VK_TAB) then begin Msg.wParam:= 0; Handled:= True; end; end;

Page 30: The Club - megazine · 2012-07-16 · Delphi e que possui foco na multiplataforma, no artigo “Criando as primeiras aplicações em Lazarus”. Para fechar temos a quarta parte da

janeiro 201230

VerticalHorizontal

Page 31: The Club - megazine · 2012-07-16 · Delphi e que possui foco na multiplataforma, no artigo “Criando as primeiras aplicações em Lazarus”. Para fechar temos a quarta parte da

janeiro 2012

Page 32: The Club - megazine · 2012-07-16 · Delphi e que possui foco na multiplataforma, no artigo “Criando as primeiras aplicações em Lazarus”. Para fechar temos a quarta parte da

janeiro 2012