32
agosto 2008

The Club - megazine · é feito instalando-se uma placa com um circuito dentro da console. Desta forma, durante anos os fabricantes de software e os piratas travaram uma verdadeira

  • Upload
    ngohanh

  • View
    219

  • Download
    0

Embed Size (px)

Citation preview

agosto 2008

agosto 2008

agosto 2008 03

LegendaIniciante

Intermediário

Avançado

Índice

Editorial

04 05

Coluna Mauro Sant’Anna

Copiar um software sem remunera-ção às pessoas e empresas que o criaram é algo que todo fabricante de software teme. Evidentemente existem proteções legais, como a “Lei de Software” de 1991 – antes de 1991 *não* era crime copiar software no Brasil.

É o fim de Pirataria?

Delphi

Capturando imagem e video de sua webcam

Leitura de Gabaritos “uma abordagem

prática”

16

.NET

Expressão lambda foi adicionada ao Visual Basic 2008 e C# 3.0, com o objetivo de apoiar ”Language Integrated Queries “(LINQ) .Quanto mais você utilizar a Expressão lambda, mais você verá sua po-tência e flexibilidade.

Lambda Expressions

18

Miscelânea Dicas

DelphiComo instalar o pacote de componente Deci-sion Cube no Delphi 2007

Pegando a versão do Firebird que está rodando no servidor Descobrir o nome da tabela no ClientDataSet

Desenhar uma linha sobre os regis-tros do DBgrid

Habilitar e desbilitar botões no form de forma genérica

ASP.NETRotina para conversor de valores por extenso

25

27

A maioria dos bancos de dados hoje em dia roda no sistema cliente/servidor. Isso significa que o banco de dados fica como um serviço e toda vez que a aplicação necessita de dados, ela conecta com esse serviço e pega as informações. Isso também significa que você tem que instalar o Gerenciador, configurar conexões, hostnames, portas e tudo mais.

SQLite - o pequeno notável

21

06Delphi 2007

Utilizando DBExpress 4 e Firebird em uma aplicação Win32

Olá caros associados, é com muita alegria que eu digo, “sejam bem vindos”, bem vindos à nova fase que nos The Club estamos vivendo, acredito que tudo na vida passa por fases, e a fase que acabamos de entrar é de inovações e crescimento.

11

agosto 200804

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

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

Internethttp://www.theclub.com.br

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

Skype Suporte: theclub_linha1 theclub_linha2

Copyright The Club Megazine 2008

Diretor TécnicoMarco César Silva

Diagramação e ArteVitor M. Rodrigues

RevisãoMarcos César Silva

ColunistasAlessandro FerreiraFabiano BelmonteFellipe Capolupo

Luís Alexandre de OliveiraMarcos César SilvaMauro Sant´AnnaVictory Fernandes

Impressão e acabamento:GRILL - Gráfica e EditoraRua São Paulo, nº 447

Cep: 18740-00 - Taquarituba-SPTel. (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.

Bem-vindo

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

pelos seus respectivos proprietários.

Marcos Césa Silva - Editor [email protected]

Olá caros associados, é com muita alegria que eu digo, “sejam bem-vindos”, bem-vindos à nova fase que nos The Club estamos vivendo, acre-dito que tudo na vida passa por fases, e a fase que acabamos de entrar é de inovações e crescimento. Com muita energia e entusiasmo toda uma reestruturação está sendo feita, com o principal objetivo de oferecer um conteúdo técnico da melhor qualidade e um suporte ágil. Claro que não é possível fazer uma revolução do dia para a noite, espero que todos enten-dam, mas acredito que todos perceberão a novas mudanças que virão por ai. E para começar, é de roupa nova que entrego a vocês a edição de Nº 167 do The Club Megazine, agora organizada em seções, sendo elas seção Delphi, .Net, Miscelâneas aberta para assuntos como banco de dados, me-todologias de programação entre outras novidades, e além da já conhecida Dicas e Truque, criamos mais uma novidade, a seção Dicas .Net.

Nesta ponto da leitura vendo a criação de seções específicas em .Net o leitor deve estar se perguntando se o The Club está perdendo o interesse em Delphi, a resposta é não, apenas estamos abrindo mais espaço para outras tecnologias também de interesse de muitos associados, e mantendo o compromisso de inovação.

Neste mês passamos a contar com novos colaboradores, e a volta de antigos amigos como Victory Fernandes que neste mês escreve sobre o uso de leitores de gabaritos e a sua integração com aplicações Delphi. E vendo a necessidade de muitos programadores iniciantes, tive a iniciativa de escrever um artigo com conceitos básico de como criar uma aplicação usando Delphi 2007, dbExpress e o Banco de dados Firebird.

Temos Fabiano Belmont que em seu primeiro artigo para nossa revista escreve sobre Expressões Lambda, mostrando mais um pouco do potencial da linguagem C# no framework 3.5. Na seção Miscelâneas Luiz Alexandre Oliveira traz o artigo sobre o compacto banco de dados SQLite, com toda sua simplicidade, leveza e aplicabilidade. Verá também na coluna de nosso antigo colaborador Mauro Sant’ Anna, uma interessante matéria sobre a pirataria e como empresas estão se adaptando ao longo dos anos para evitar este mal.

Desejo a todos uma boa leitura e boa sorte a todos nós.

agosto 2008 05

Sobre o autor

Coluna Mauro Sant’Anna

Mauro Sant’Anna nunca trabalhou na Microsoft, mas conhece bastante a empresa, já que é MVP e “Regional Director of the Year”. Ele coordena os cursos na M. A. S. Informática (www.mas.com.br) e bloga em Português em http://blogs.vstsrocks.com.br e em inglês em http://maurosjungle.spaces.live.com .

Copiar um software sem remuneração às pessoas e empresas que o criaram é algo que todo fabricante de software teme. Evidente-mente existem proteções legais, como a “Lei de Software” de 1991 – antes de 1991 *não* era crime copiar software no Brasil.

No entanto, as proteções legais são de eficácia limitada, especialmente contra usuários domésticos. Por cau-sa disto, muitas empresas adotaram

medidas técnicas de “proteção contra cópia” para tentar impedir a distribuição indiscriminada do seu software. Por exemplo, os DVDs feitos para a console de jogo XBOX da Microsoft são “especiais” e só tocam em um drive modificado. Por outro lado, os piratas sempre apareciam com contra-medidas que permitiam a cópia apesar dos bloqueios. No caso do “Xbox” o “destravamento” é feito instalando-se uma placa com um circuito dentro da console. Desta forma, durante anos os fabricantes de software e os piratas travaram uma verdadeira guerra de medidas, contra-medidas e contra-contra-medidas. Por exemplo, a Microsoft constantemente modifica o circuito do Xbox de for-ma a fazer com que so circuitos de destravamento deixem de funcionar.

No caso de softwares para microcomputa-dores, ainda na década de oitenta, apareceram truques visando impedir a cópia de disquetes. Um deles previa até mesmo danificar o disquete com um furo feito por um “laser”! Depois apareceram os dispositivos de hardware, verdadeiras “chaves” (“dongles” em inglês), ligados inicialmente nas por-tas de impressora e mais recentemente nas portas USB. O software exigia a presença destas “chaves” para poder rodar. Ou seja, o software até poderia ser facilmente copiado, mas não era possível copiar

O Fim da Pirataria?o dispositivo físico que o software exigia. Quando a mídia padrão passou a ser discos óticos (CD ou DVD), também surgiram truques para impedir a cópia deste tipo dos discos.

Todos estes métodos tinham características em comum: oneravam a produção do software, irrita-vam os usuários legítimos e sempre eram quebra-dos pelos piratas. Dada a eficácia limitada dessas medidas, a maioria dos fabricantes de software simplesmente abandonou a proteção contra cópia e assumiu a posição de que a pirataria era parte do “preço de se fazer negócio”. Os piratas ganharam.

Hoje, no entanto a Internet abre novas possibi-lidades no sentido de reduzir ou até mesmo acabar completamente com a pirataria.

Em primeiro lugar, vários produtos podem rodar em uns ambientes “hospedados” e acessíveis através de navegador Internet. Este acesso exigiria cadastro e pagamento prévio utilizando senhas e criptografia para garantir a inviolabilidade, de forma semelhante a usadas pelos bancos em seus aplicativos de “home banking”. Por exemplo, tanto a Microsoft como o Google vendem serviços de hospedagem de correio eletrônico corporativo, que dispensam a compra, instalação e manutenção de um servidor de correio.

Uma segunda possibilidade é um esquema misto, onde o software roda essencialmente na estação, mas recorre a um servidor para alguma função importante. Por exemplo, um software de contabilidade poderia ter toda a entrada de dados remota, mas armazenaria os dados e rodaria rela-tórios em um servidor central.

As alternativas acima exigem acesso a Internet ou todo o tempo ou pelo menos uma boa parte do tempo. E se o acesso à Internet não for confiável? Bem, isso está cada vez mais raro e tende a desapa-

recer. Mas, mesmo neste caso, o software poderia consultar um servidor central periodicamente apenas para pegar uma espécie de “código de au-torização” ou atualizações. Embora ainda suscetível a ataques, caso as atualizações sejam bastante freqüentes – por exemplo, uma vez por semana – os piratas terão que trabalhar rapidamente para quebrar e distribuir a nova versão, algo que pode se revelar simplesmente impraticável.

Na verdade, já estamos vendo as primeiras implementações deste tipo de tecnologia. A “ati-vação” através da Internet presente em alguns pro-dutos da Microsoft como Windows e Office é ume pequeno exemplo do que está por vir. Outro bom exemplo é o “XBox Live”, um serviço pago no qual usuários da console de jogos XBox pode não apenas jogar com outras pessoas, mas também adquirir novos jogos ou extensões a jogos já existentes. Diga-se de passagem, o serviço não funciona se a sua console tiver sido “desbloqueada”.

A distribuição de software através da internet tem também o benefício de eliminar intermediá-rios, fazendo que uma parcela maior do dinheiro pago pelo usuário chegue ao fabricante. Ela tam-bém acabará com o argumento de que o software tem que ser mais caro para compensar os usuários que não pagam. Com todo mundo pagando, o preço individual deve cair, o que ainda tira mais um incentivo da pirataria.

agosto 200806

Delphi

Seguindo a linha de publicações voltadas à integração de sistemas computacionais a dispositivos externos diversos, apresentamos neste artigo uma abordagem prática para desenvolvimento de aplicativos integrados a leitores de gabaritos, neste caso específico, leitores da série LOHS da HS Informática (www.hsinformatica.com.br).

Leitores de Gabaritos OMR - Conceitos gerais

Os leitores de gabaritos são utilizados para a rápida correção de avaliações objetivas em escolas e concursos que utilizem a folha de gabarito padrão, po-

rém essas não são as únicas utilidades dos leitores OMR. Por possuírem boa precisão e velocidade, são utilizados também nas áreas de pesquisas de opinião, indústria (apontamentos e controle de qualidade, por exemplo), loterias e outros jogos, área de saúde (para controle de medicamentos, visitas ao paciente etc) e negócios em geral, para a leitura de informações de forma mais ágil e con-fiável, reduzindo a margem de erro de leitura na contagem das respostas.

Tais equipamentos utilizam processo reflexivo para detectar o preenchimento das marcas. Nesse processo um feixe de luz é emitido e caso a opção não esteja assinalada o feixe será reflexivo, e caso esteja marcada, o feixe de luz não será recebido de volta, conforme Figura 1. Dessa forma pode-mos dizer que caso não haja resposta marcada, o retorno binário é “1”, caso contrário é “0”. Essa é uma informação importante, pois a usaremos para interpretar a leitura feita pela LOHS de um gabarito.

Figura 01: Leitura dos gabaritos por processo reflexivo

Leitura de Gabaritos Uma abordagem prática

O equipamento LOHS

Nos testes realizados foi utilizado o modelo LOHS40mi Manual conforme mostrado na Figura 2, que faz a leitura de formulários com largura fixa de tamanho 3 ¼” (82,5 mm),este modelo permite dispor da tecnologia de leitura óptica com reduzido investimento, e constitui um equipamento robusto, compacto e simples de operar,

Figura 02: Equipamento LOHS40mi Manual utili-zado nos testes

A conexão do LOHS com o computador pode ser feita de duas formas – através da porta Serial (RS232), ou da porta USB, sendo a opção de porta USB disponível apenas para os modelos LOHS4mi, LOHS40mi, LOHS4mi-CEF.

Durante os testes, o LOHS foi utilizada a co-municação através da porta USB do computador. Para tal, fez-se necessária a instalação de drivers disponibilizados pelo fabricante e documentados no manual do mesmo. Esses drivers criam outra porta serial no seu computador, chamada de Porta Serial Virtual(Virtual Com Port – VCP). A configura-ção da porta deverá ser a seguinte:

• 2 stop bits;• 1 start bit;• 8 bits/caracter;• Sem paridade;

• Full duplex;• Velocidade: 9600 bps;

Após a adição da nova porta, o LOHS está pronto para ser reconhecido e conectado no computador. Para maiores detalhes sobre os dri-vers, procedimento de instalação e configuração consulte o manual do equipamento, disponível no site do fabricante.

Encontra-se também disponível no site do fabricante um software de teste e configuração conforme mostrado na Figura 3. Esse aplicativo é o primeiro passo para garantir que o equipamento está pronto para ser utilizado.

Figura3: Tela principal do software gratuito de teste e configuração do equipamento fornecido pelo fabricante.

Depois de instalado, podemos dar inicio aos nossos testes. Selecione a porta serial a qual o LOHS está conectado, após a seleção da porta, digite o número de linhas do seu gabarito. Para tal, é necessária uma breve explicação sobre o número de linhas de um gabarito, chamados também de

agosto 2008 07

“Clocks”. Os clocks são um dos conceitos mais importan-

tes para a leitura óptica, pois é através dele que o leitor diferencia uma linha da outra, são marcações pretas alinhadas à lateral do gabarito. Um clock equivale a uma linha. A seguir um exemplo de um gabarito com 35 linhas, ou seja, 35 clocks, conforme mostrado na Figura 4.

Figura4: Clocks de um gabarito.

Uma vez configurada a porta serial e digitado o número de linhas no aplicativo de teste, devemos clicar no botão “abre serial”. Esse comando configu-ra o seu computador com os parâmetros de comu-nicação necessários ao LOHS, acessa a porta serial e inicia a comunicação com o equipamento.

Com a porta serial configurada e aberta, clique no botão “Ler” e insira um formulário no equipamento. A imagem da leitura do gabarito é exibida no espaço ao lado dos comandos conforme mostrado na Figura 5.

Repita a leitura quantas vezes for necessário

para testar o equipamento e confira se o resulta-do dos valores lidos apresentados no aplicativo correspondem com a marcação feita no gabarito. Antes de sair do aplicativo e teste, clique em “Fe-cha Serial” para restaurar as configurações padrão da porta e libera-la para que outros dispositivos possam usá-la.

Além do software de teste, encontra-se dispo-nível no site do fabricante diversos outros softwares que facilitam a comunicação e a leitura de infor-

mações dos gabaritos, incluindo a biblioteca LOHS.dll que permite a integração com o equipamento a partir do seu aplicativo desenvolvido em qualquer plataforma Win32.

A biblioteca LOHS.dll

O acesso ao download do manual da LOHS.

dll só é possível através de senha fornecida pelo fabricante, e além do manual utiliza-se como re-ferência o aplicativo demo de uso da dll também disponível para download, conforme mostrado na Figura 06.

Neste aplicativo é possível se verificar as

chamadas às funções disponibilizadas na LOHS.dll, conforme mostrado a seguir no código fonte 01:

Fgura5: Leitura de um gabarito a partir do software de testes.

Figura6: Aplicativo demo de uso da LOHS.dll em Delphi.

agosto 200808

Um problema encontrado pela maioria dos desenvolvedores ao utilizar este equipamento é que a alternativa para comunicação utilizando a dll do próprio fabricante do equipamento não é gratuita! Ou seja, o fabricante além de vender o equipamento, vende também a dll de acesso ao equipamento que é protegida por hardlocks Pro-teq ou Hasp. É um contra-senso, mas é como se a Bematech além de vender impressoras fiscais – ECF, cobrasse também pela venda das dlls de acesso ao seu próprio equipamento.

Para um cliente que adquira duas máquinas e deseje utilizar o seu software que se integra ao equipamento através da LOHS.dll, o cliente precisará adquirir 2 licenças de uso da dll, caso contrário não conseguirá utilizar os 2 equipamentos ao mesmo tempo.

Infelizmente este tipo de política de licenças onera demais as soluções de software dos de-senvolvedores, e os mesmos acabam buscando soluções alternativas que possibilitem maior flexi-bilidade e autonomia.

Protocolo de comunicação com o LOHS

Uma alternativa ao uso da biblioteca LOHS.dll, que dispensa a necessidade da compra de licenças, é utilizar a comunicação direta com o equipamento através do seu protocolo de comunicação. Desta

forma é possível ter total autonomia sobre o processo de comunicação com o equipamento independente de soluções de terceiros, de forma que ao aconselhar a sua solução, tudo o que o cliente precisará fazer é adquirir o equipamento e nada mais, enquanto para solução de outros desenvolvedores, cada novo cliente terá ainda de pagar para adquirir a dll.

Esse protocolo em formato texto deve ser rigidamente seguido para que a comunicação entre o equipamento e o computador acontece de forma correta, conforme a lista de principais comandos apresentada na Tabela 1.

De das informações da tabela anterior que lista os principais bytes de um quadro de dados, veremos agora como o quadro é formatado, sua sintaxe. A estrutura de formação dos quadros é sempre igual, variando apenas o tamanho total do quadro e o tipo de CRC utilizado, salvo a resposta de leitura de cartão. O quadro é formatado da seguinte maneira:

• Utilizando CRCo <STX> <TAM> <ID> <TEXTO> <ETX>

<CRC1> <CRC2>• Utilizando XORo <STX> <TAM> <ID> <TEXTO> <ETX>

<XOR1>

Para um mesmo quadro de dados é possível se obter uma das duas respostas anteriores, a depen-der da configuração do tipo de CRC utilizado.

Com base na estrutura geral dos quadros apresentada é possível enviar comandos ao equi-pamento e receber o retornos. A seguir alguns comandos são apresentados.

Comando Beep

Esse comando faz com que o LOHS soe um beep ao recebê-lo.

• Formato do Comando Utilizando CRCo <STX> <06> <03> <ETX> <CRC1>

<CRC2>• Formato do Comando Utilizando XORo <STX> <05> <03> <ETX> <XOR1>

O LOHS responderá esse comando com ACK, caso seja enviado com sucesso, ou NACK, caso possua algum erro.

Comando Habilita Leitura

Comanda o LOHS a realizar uma leitura de um cartão que deverá ser introduzido pelo operador.

function AbreSerial( porta : char; bps : longint; paridade : char; databits : char; stopbits : char; cModelo : Byte; cNumLinhasFrente : Byte; cNumColunasFrente : Byte; cNumLinhasVerso : Byte; cNumColunasVerso : Byte; cNumCodBarras : Byte; LeituraDupla : Boolean) : ShortInt; stdcall; external ‘.\LOHS.DLL’;

function LerCartao() : TResultBiblioteca; stdcall; external ‘.\LOHS.DLL’;function LerCartaoParametro() : TResultBiblioteca; stdcall; external ‘.\LOHS.DLL’;function FechaSerial() : ShortInt; stdcall; external ‘.\LOHS.DLL’;function Aceita() : Boolean; stdcall; external ‘.\LOHS.DLL’;procedure Alarme; stdcall; external ‘.\LOHS.DLL’;procedure DesligaMotor; stdcall; external ‘.\LOHS.DLL’; código fonte 01

Abreviação Nome Descrição Valor Byte

STX Star of Text Marca o início do quadro de dados 02H

ETX End of Text Marca o fim do quadro de dados 03H

ACK Acknowledgement Indica o recebimento de um quadro SEM erro

06H

NACK Negative Acknowledgement Indica o recebimento de um quadro COM erro

15H

CRC Cyclic Redundancy Check O CRC16 é um verificador constituído de 2 Bytes, gerado através de um polinômio. Uti-lizado para testar a consistência dos dados recebidos em um quadro.

Word Resulta-do do Cálculo do polinômio (2 Bytes)

XDR Exclusive OR Também utilizado para teste de consistência do quadro e é montado através da operação XOR

Byte Resultado da operação XOR

Tabela1: Comandos LOHS

agosto 2008 09

• Formato do Comando Utilizando CRCo <STX> <06> <01> <ETX> <CRC1>

<CRC2>• Formato do Comando Utilizando XORo <STX> <05> <01> <ETX> <XOR1>

O LOHS responderá esse comando com ACK, caso seja enviado com sucesso, ou NACK, caso possua algum erro.

Após a leitura do cartão, um quadro é enviado automaticamente do LOHS para o computador, contendo:

1. Quadro de dados do cartão, caso a leitura seja feita corretamente.

2. Quadro de Estado de Leitura Errônea, caso a leitura seja feita incorretamente.

Se o quadro recebido for o de dados do cartão, o mesmo deverá ser tratado pelo computador. O formato do quadro é o seguinte:

• Formato do Quadro Utilizando CRCo <STX> <TAM> <F1> <TEXTO> <ETX>

<CRC1> <CRC2>• Formato do Quadro Utilizando XORo <STX> <TAM> <F1> <TEXTO> <ETX>

<XOR1>

No caso de haver erro de leitura, o Quadro de Estado de Leitura Errônea é recebido, o quadro segue o seguinte formato:

• Formato do Quadro Utilizando CRCo <STX> <07> <F0> <ESTADO> <ETX>

<CRC1> <CRC2>• Formato do Quadro Utilizando XORo <STX> < 06> < F0> < ESTADO > <ETX>

<XOR1>

O byte ESTADO carrega consigo a descrição do erro na leitura. Para identificar qual o erro, ou os erros, devemos verificar o byte ESTADO bit a bit. Os valores dos bits são conforme Tabela 2.

Tabela2: Bits de Leitura Errônea

Para lista completa de comandos e suas res-pectivas descrições, consulte o manual de progra-mação do equipamento.

Exemplo em Delphi de integração com equipamento LOHS

Com um pouco de conhecimento em Delphi e com base na estrutura do protocolo do equipamen-to é possível implementar funções que formatem mensagens a serem enviadas, tratem e interpretem as mensagens recebidas.

A seguir apresentamos a implementação da função de Beep descrita anteriormente, onde o pri-meiro passo é criar um novo projeto e adicionar o seguinte código ao evento OnClick de um botão.

Ver código fonte 02

No código, uma função chamada “Beep” é chamada e o seu retorno, do tipo String, é atribuído à variável “Comando”. A seguir é apresentado o código executado pela função “Beep”.

Ver código fonte 03

A função “Beep” cria a estrutura básica do comando, calcula e concatena à String resultante, os valores dos bytes de CRC, conforme descrito no protocolo de comunicação do equipamento. O resultado é então transmitido através da função “Envia_Comando” que faz o acesso à porta serial através do componente TCommPortDriver, confor-me código apresentado a seguir:

Ver código fonte 04

Bit Informação

0 Erro de RAM

1 Uso futuro

2 Leitora foi ativada mas não foi passado cartão

3 Leitura inconsistente (em caso de múltipla leitura)

4 Número de clocks lidos diferente do definido pelo comando. Define tamanho do buffer

5 Uso futuro

6 Uso futuro

7 Uso futuro

procedure TForm1.BtnBeepClick(Sender: TObject);var comando: String;begin comando := Beep; //Chama funcao Beep da Unit LOHS_OMR Envia_Comando(Comando, ‘BEEP’); //Envia comando para porta serialend;

// Função: faz soar o beep interno do equipamento.Function Beep: String;begin Comando := stx + #06 + #03 + etx; //Cria estrutura básica do comando Calculo_CRC16(comando, MyCRC); //Calcula o CRC do comando result := comando + chr(hi(MyCRC)) + chr(lo(MyCRC));end;

//Funcao genérica utilizada para enviar o comando pela porta serial e escrever no memo.Function TForm1.Envia_Comando(Comando, DescritivoComando: String): Boolean;begin result := false;

try //tenta enviar comando pela serial Result := CommPortDriver1.SendString(comando); except memo1.Lines.add(DescritivoComando + ‘ - Erro ao enviar comando’); end;

if result then //se enviar corretamente memo1.Lines.add(DescritivoComando + ‘ - Comando Enviado com Sucesso’);else //Senão, acusa na tela o erro ocorrido memo1.Lines.add(DescritivoComando + ‘ - Erro ao enviar comando’);end;

código fonte 02

código fonte 03

código fonte 04

agosto 200810

Além do comando de Beep podem ser imple-mentados os comandos conforme lista a seguir. A implementação dos demais comandos segue a mesma sistemática, e permite a implementação do tratamento de todos os comandos disponíveis no manual do fabricante.

Ver código fonte 05

Com base nos códigos apresentados anterior-mente e na documentação completa fornecida pelo fabricante foi implementado um demo em Delphi, conforme apresentado na Figura XX, dis-ponível para download em www.igara.com.br/downloads/lohs_omr/projeto_lohs_omr_v1.zip, e que implementa todos os recursos necessários à configuração e comunicação com o equipamento LOHS, permitindo que sua aplicação tenha controle completo sobre o equipamento sem a necessidade do uso de soluções de terceiros, reduzindo custos e dando maior flexibilidade e autonomia ao seu aplicativo.

Maiores informações podem ser obtidas no site

www.igara.com.br/produto.php?cod_produto=113

Conclusões

Leitores óticos para automação do processo de leitura de gabaritos são uma necessidade nos dias de hoje, onde grande parte dos processos de correção e leitura de provas ou gabaritos precisa ser feita com agilidade e precisão. Entretanto nem sempre temos à mão soluções simples e baratas de integração entre software e o equipamento, tendo a necessidade de depender de dlls proprietárias ou licenças onerosas, “amarrando” o usuário ao fabri-cante do equipamento. Neste artigo apresentamos solução, que permite redução de custos, e total autonomia para o desenvolvedor, que passa a ter controle completo do processo de comunicação entre seu software e o equipamento, uma vez que a implementação é baseada no protocolo de co-municação de dados do fabricante, possibilitando mudanças futuras no processo de comunicação, aumentando assim o diferencial competitivo do seu software frente aos concorrentes.

Links

www.hsinformatica.com.brTecnologia da Informação e Conhecimento.

Function Habilita_Leitura: String;Function Reseta: String;Function Beep: String;Function Ativa_Teste_Comunicacao: String;Function Desativa_Teste_Comunicacao: String;Function Nro_De_Linhas: String;Function Verificador(vVerificador: String): String;Function Nro_De_Clocks(vNroClocks: string): String;Function Mascara_De_Leitura(vMascara1, vMascara2: char): String;Function Tipo_Controle_De_Fluxo(vTipo_De_Fluxo: char): String;Function Nro_De_Leituras(vNro_De_Leituras: String): String;Function trata_Informacao_texto(buffer: String; var Resposta: TStrings): Boolean;Function Transmite_Buffer_i(Nro_Buffer: char): String;Function Exibe_Display(Mensagem:String) :String;Function Transmite_Versao: String;

código fonte 05

Figura7: Aplicativo demo em Delphi demonstrando a implementação de todos os comandos do protocolo.

Sobre os autores

Victory Fernandes é Engenheiro Mestrando em Redes de Computadores, e de-senvolvedor sócio da TKS Software - Soluções de Automação e Softwares Dedicados. Pode ser contatado em [email protected], ou através dos sites www.igara.com.br – www.igara.com.br/victory

Fellipe Capolupo é estudante de Engenharia Elétrica e desenvolvedor da TKS Software - Soluções de Automação e Softwares Dedicados. Pode ser contatado em [email protected]

agosto 2008 11

Criando uma Agenda de Telefones

Quando vamos escrever um artigo sempre buscamos temas inovadores e inéditos, mas ai surge um dilema, não é todo dia que surgem grandes

novidades, e muitas vezes para programadores de primeira viagem, o que eles precisam é o bom “arroz com feijão”, assim este artigo tem como ob-jetivos passar os conceitos básicos para iniciantes no Delphi de como fazer uma pequena aplicação usando técnicas simples de criação, conexão e manutenção de dados, e para os desenvolvedores mais experientes que ainda não tiveram contato com a ferramenta, também é valida uma leitura para se familiarizarem com a IDE do Delphi 2007 e reforçarem o conhecimento.

1. Criação do Banco de dados

Criaremos uma simples agenda telefônica, armazenando os contatos e seus respectivos nú-meros de telefones. Assim teremos duas tabelas a CONTATOS a e TELEFONES, veja na figura 1 o diagrama de ER (Entidade Relacionamento). Alem das duas tabelas criaremos o relacionamento entre as duas tabelas com a condição de deleção em cascata (delete cascade), para quando o contato for excluído, os telefones relacionados do contato também seja apagados. Além destes um generator será criado para incrementar o numero seqüencial da chave primária. Assim para criação do banco de dados execute o script a seguir em qualquer ferramenta de manutenção do banco firebird, no meu caso eu uso o IBExpert Personal Edition (no final do artigo encontrará os link das ferramentas disponíveis citadas ).

Delphi 2007

/*Script de criação do banco*/SET SQL DIALECT 3;CREATE DATABASE ‘LOCALHOST:E:\THECLUB\Artigo\IntroducaoD2007\CONTATOS.FDB’USER ‘SYSDBA’ PASSWORD ‘masterkey’PAGE_SIZE = 4096;

/*Script de criação da tabela contatos */CREATE TABLE CONTATOS ( ID_CONTATO INTEGER NOT NULL, NOME VARCHAR(80), APELIDO VARCHAR(20), ENDERECO VARCHAR(80), CIDADE VARCHAR(80), UF

CHAR(2), PRIMARY KEY (ID_CONTATO));

/*Script de criação da tabela telefones*/CREATE TABLE TELEFONES ( ID_CONTATO INTEGER NOT NULL, ITEM INTEGER NOT NULL, NUMERO VARCHAR(13), TIPO VARCHAR(20), PRIMARY KEY (ID_CONTATO, ITEM));

/*Script de criação do relacionamento entre tabelas telefones e contatos*/alter table TELEFONES

Figura 1 - Diagrama de ER (Entidade Relacionamento)

Utilizando DBExpress 4 e Firebird em

uma aplicação Win32

agosto 200812

add constraint FK_TELEFONES_CONTATOSforeign key (ID_CONTATO)references CONTATOS(ID_CONTATO)on delete CASCADE;

/*Script de criação do Generator da criação do código de Contatos*/CREATE GENERATOR GEN_ID_CONTATO;

2. Criando a aplicação

Com nosso banco de contatos criado iremos criar nossa aplicação, para isto no Delphi 2007 vá em File -> New -> VCL Forms Application – Delphi for Win 32, e salvaremos a unit unContatos.pas e o projeto como Contatos.dproj, no form altere as seguintes propriedades:

Caption = ‘Agenda Telefônica’Name = frmContatos

Iremos agora criar um Datamodule para criamos a conexão e componentes de acesso a dados, desta forma em New -> Others.. em New Items (Figura 2) na categoria Delphi Files, e salve-o como unDM.pas e sua propriedade Name = DMContatos.

2.1. A conexão

Agora selecione o componente SQLConnection na paleta dbexpress e adicione-o no Datamodule, e altere sua propriedade Name para sqlConexao. Com um duplo clique no componente iremos abrir o editos de propriedades de conexão, clique em Add Connection para criamos uma nova conexão, em Driver Name selecione “Interbase” e em Con-nection Name “CONTATOS”, confirme e em Connec-tion Settings basta apenas informar o caminho do banco de dados na propriedade Database (Figura 2), clique em Ok e pronto a conexão está feita, veja na figura 3 as propriedades preenchidas no compo-nente, além é claro da propriedade params:

Altere mais tres propriedades, uma é o Lo-ginPrompt = False, para que ao ativar a conexão seja confirmado usuário e senha, e VendorLib = ‘fbclient.dll’, aonde iremos usar a DLL cliente do firebird, e deixe a conexão ative com a propriedade Active = True (Figura 3).

Figura 2 – New Items

Figura 3 - Editor de propriedades de conexão

Figura 3 – propriedades do sqlConexao

2.2. Componentes de consulta

Incluiremos agora os componentes de consulta ao banco, primeiro um SQLDataset para a consulta de contatos que chamaremos sdsContatos, e um outro para exibir os telefones do contato com o nome sdsTelefones, ambos devem ter a proprieda-de SQLConnection apontando para o sqlConexao. Este dois componentes estarão ligados de maneira a criar um relacionamento mestre detalhe, para isto adicione um terceiro componente, o DataSource da paleta DataAccess que receberá o nome de dsContatos. Este componente Datasource deve estar com a propriedade Dataset “Ligada” ao sds-Contatos, e o componente de sdsTelefones com a propriedade Datasource ligada dsContatos.

agosto 2008 13

Iremos agora na propriedade CommandText, inserir a instrução SQL de consulta ao contatos como pode ver na Figura 4:

No caso do sdsTelefone receberá na proprieda-de CommandText, a seguinte instrução:

select * from TELEFONESwhere ID_CONTATO = :ID_CONTATO

Observe que para os Telefones incluímos uma cláusula where onde o parâmetro :ID_CONTATO através do dsContatos, faz o filtro do relaciona-mento mestre detalhe.

Agora adicione os TFields em ambos compo-nentes sqlDataset, para isto de um duplo clique no componente para abrir o Fields Editor e adicione os campos (Add Fields.. Ctrl + A), após incluir os campo selecione o campo chave primária, e no ObjectInspector altere as propriedades do Pro-viderFlags pfInUpdate, pfInWhere e pfInKey para True, no caso dos demais campos deixe a apenas a propriedade pfInUpdate como True. Este proce-dimento deve ser feito para os dois componente SqlDataSet. Apenas para testar as configurações destes componentes ative o sdsContatos e depois o sdsTelefones alterando a propriedade Active para True, após o teste e verificando que as ligações e instruções estão corretas volte a propriedade para false, o que é o padrão neste caso.

2.3. Trabalhando com Clientdatasets

Neste ponto adicionaremos os componentes Clientdataset que ira trabalhar desconectados do banco, assim coloque no datamodule dois Clien-tdataset e um DataSetProvider que se encontram na paleta DataAccess, veja abaixo as propriedades alteradas de cada um dos três componentes:

DataSetProviderName = dspContatosDataSet = sdsContatos

ClientDataSet de Contatos Name = cdsContatos ProviderName = ‘dspContatos’

Adicione os Campos no Fields Editor e configu-re os Provider flags da mesma forma que foi feito para os componentes SqlDataset, veja que além dos campos já existentes um campo novo é criado, este campo que no exemplo foi criado automaticamente com o nome de cdsContatossdsTelefones é um TDataSetField, ou seja é um campo responsável pelo relacionamento entre os dois clientdatasets, após ligar a propriedade DataSetField ao cdsConta-

Figura 4 – Instrução SQL de consulta dos contatos

Figura 5 - Os componente no Datamodule

tossdsTelefones, adicione os campos e configure-os da mesma forma feita anteriormente ao outros componente, veja na figura 5 os componente no Datamodule.

ClientDataSet de Telefones Name = cdsTelefonesDataSetField = cdsContatossdsTelefones

2.4. A Interface

Voltaremos ao form frmContatos para “De-senhar” a tela de manutenção dos dados dos contatos e dos telefones, para que os componente dataware possam “enxergar” os componentes do datamodule, adicione o datamodule na uses do form frmContatos (Alt + F11). Veja abaixo os prin-cipais componentes inseridos e suas propriedades alteradas, veja que para a entrada dos telefones

uso um Dbgrid. Na Figura 6 poderá ver como deve ficar o layout da tela, sendo apenas uma sugestão, onde as cores, botões e imagens, podem dar um visual muito agradável para aplicação, isto vai da criatividade do programador na hora de fazer esta “perfumaria”.

DataSource1 DataSet = DMContatos.cdsContatosDataSource2 DataSet = DMContatos.cdsTelefones

DBEdit1 DataField = ‘ID_CONTATO’ DataSource = DataSource1

agosto 200814

DBEdit2 DataField = ‘NOME’ DataSource = DataSource1

DBEdit3 DataField = ‘APELIDO’ DataSource = DataSource1

DBEdit4 DataField = ‘ENDERECO’ DataSource = DataSource1

DBEdit5 DataField = ‘CIDADE’ DataSource = DataSource1

DBEdit6 DataField = ‘UF’ DataSource = DataSource1

DBNavigator1 DataSource = DataSource1

DBNavigator2 VisibleButtons = [nbInsert, nbDelete, nbPost, nbCancel] DataSource = DataSource2

DBGrid1 DataSource = DataSource2

2.5. A Programação

Ate este momento apenas adicionamos com-ponentes, alteramos e ligamos propriedades, agora chegou a hora de uma pouco mais de ação, iremos digitar algumas linhas de código responsáveis por gerar código, gravar informações e confirmar atualizações e exclusões. Assim voltando nova-mente no datamodule DMContatos, incluiremos no datamodule função AutoInc já bastante co-nhecida de programadores mais experientes, esta

função tem por objetivo informar o nome de um generator e retornar seu novo valor, veja o código da função abaixo:

function TdmBase.AutoInc(Generator: string; Conexao: TSQLConnection): Integer;var SQLGen: TSQLDataSet;begin SQLGen := TSQLDataSet.Create(Application); try SQLGen.SQLConnection := Conexao; SQLGen.CommandText := ‘Select Cast(Gen_Id(‘ + Generator + ‘,1) as Integer) as Codigo From Rdb$Database’; SQLGen.Open; Result := SQLGen.FieldByName(‘Codigo’).AsInteger; SQLGen.Close; finally SQLGen.Free; end;end;

Figura 6 – Tela de Contatos

No evento BeforePost do cdsContatos iremos usar a função AutoInc para atribuir para o campo ID_CONTATO o novo valor do generator GEN_ID_CONTATO. Para isto selecione e componente cdsContatos e na aba Events do object Inspector, de um duplo clique no evento BeforePost e inclua o código abaixo:

procedure TDMContatos.cdsContatosBeforePost (DataSet: TDataSet);begin if cdsContatos.State in dsInsert then cdsContatosID_CONTATO.AsInteger := AutoInc(‘GEN_ID_CONTATO’,sqlConexao);end;

No caso da tabela Telefones que possui uma chave primaria composta, o campo ID_CONTATO é atribuído automaticamente através pelo relaciona-mento mestre detalhe entre os ClientDataset, devi-do mantermos o mesmo nome em ambas tabelas relacionadas. Para o segundo campo da chave, o

agosto 2008 15

campo ITEM apenas iremos atribuir o contador do numero de telefones de um contato, para simplifi-car invés de ficarmos usando contadores, apenas ire verificar o numero de registros de telefones, e atribuir este valor somando + 1 para o campo no evento BeforePost do cdsTelefones.

procedure TDMContatos. cdsTelefonesBeforePost (DataSet: TDataSet);begin if cdsTelefones.State in [dsInsert] then cdsTelefonesITEM.AsInteger := cdsTelefones.RecordCount;end;

Com tudo isto falta um ultimo código que irá gravar todas as alterações no banco, o ApplyU-pdates assim no evento AfterPost do cdsContatos, adicione o código:

procedure TDMContatos.cdsContatosAfterPost (DataSet: TDataSet);begin cdsContatos.ApplyUpdates(0);end;

Uma ultima sugestão: para não repetir o código do ApplyUpdates na deleção, e também na para as atualizações e exclusões de telefones, ligue o evento

AfterDelete do cdsContatos ao evento já criado dsContatosAfterPost, faça o mesmo para AfterDe-lete e AfterPost do cdsTelefones.

Pronto, temos um simples cadastro de conta-tos e telefones (Figura 7).

Conclusão

Como foi dito no inicio este artigo teve por objetivo, introduzir conceitos básicos para um ini-ciante na “arte da programação”, proporcionando um programador de primeira viagem criar uma aplicação simples e útil. Agora para os mais expe-rientes posso provar que tirando a interface da IDE

Figura 7 – A agenda de contatos

do Delphi 2007, onde a disposição de componentes e recursos mudou completamente, no que diz res-peito à programação, tudo continua praticamente igual ao que era no Delphi 7.

Despeço-me com um grande abraço a todos, e ate o mês que vem.

Links

http://www.ibexpert.com/downloadcenter/http://www.ibphoenix.com/main.nfs?a=ibpho

enix&s=1219112666:25325&page=ibp_download

Sobre o autor

Marcos César Silva, Consultor de Sistemas na consultoria de sistemas DataSmart e Consultor Técnico do The Club, Bacharel em Ciência da Computação, MBA em Gestão Empre-sarial, Certificações MCAD (Microsoft Certified Application Developer) e MCSD.NET (Microsoft Certified Solution Developer .NET)

agosto 200816

Recentemente fui questionado por um amigo relativamente leigo em informá-tica como poderia gravar as imagens de sua webCam em seu computador,

sugeri a ele um dos muitos aplicativos disponíveis que tem este tipo de recurso, depois dessa nossa conversa surgiu uma pergunta que veio curiosi-dade “nata” da maioria dos programadores, e se um dos meus clientes solicitasse este recurso no seu aplicativo? Isto poderia acontecer, este seria um recurso bastante útil, desde cadastros clientes de uma vídeo locadora, recepção de hotéis, ate sistemas mais simples de monitoramento para segurança.

Assim comecei a pesquisa na imensidão da In-ternet, entre muito “lixo eletrônico” que encontrei pela frente, achei um componentinho freeware, bastante simples e eficiente o TCamera. Este componente junto do projeto de exemplo pode ser encontrado no link:

www. theclub.com.br/revista/rev0808/pega-webcam.zip

Instalando o TCamera

Descompacte o arquivo TCamera.zip em um diretório qualquer de sua máquina, no Delphi em File | Open abra o arquivo TWebCam.dpk, abrindo o pacote clique nos botões compile e Install, e em Tools | Enviroment Options na abra Library Path adicione o caminho onde descompactou o componente. Feche o pacote, não precisa salva-lo, Simples não é?!!!

Criando a Aplicação

Vamos cria uma simples aplicação para conhecermos alguns dos recursos deste compo-nente, assim no Delphi em File | New clique em

Application para criar uma nova aplicação, na unit1 insira o componente TCamera que se encontra na paleta Yves, que será responsável por capturar, exibir, gravar vídeo e imagem tudo em apenas um componente, um componente Image para exibir uma foto capturada, e três botõs, um para gravar o vídeo, outro para parar a gravação e um terceiro para capturar a foto. Veja na figura 1 a sugestão do layout do formulário.

Veja na Figura 2 o exemplo do aplicativo fil-mando e na Figura 3 ele capturando a foto.

Agora no form adicione o evento Onshow onde ativaremos o capturar da Imagem apenas atribuindo true para a propriedade Camera1.Actif como pode ver abaixo:

Capturando Imagem e Vídeo de sua WebCam

agosto 2008 17

Camera1

Image1

Figura 1

Figura 3

Figura 2

procedure TForm1.FormShow(Sender: TObject);begin try Camera1.Actif := True; except MessageDlg(‘Não foi possilve capturar a Imagem da WebCam!’, mtError, [mbOk], 0); end;end;

No Botão captura foto iremos adicionar o seguinte código, aonde salvo a foto em formato bmp no diretório raiz usando a função CaptureIma-geDisque do componente, logo a seguir carrego a imagem no componente TImage.

procedure TForm1.BitBtn1Click(Sender: TObject);begin Camera1.FichierImage := ‘c:\Foto.bmp’; Camera1.CaptureImageDisque; Image1.Picture.LoadFromFile(‘c:\Foto.bmp’);end;

Para iniciar a gravação da imagem usaremos a função CaptureVideoDisque, salvando o vídeo em formato avi também no diretório raiz:

procedure TForm1.BitBtn2Click(Sender: TObject);

begin Camera1.FichierVideo := ‘c:\Video.avi’;

Camera1.CaptureVideoDisque;end;

agosto 200818

E para parar a gravação StopVideo, como pode ver a seguir:

procedure TForm1.BitBtn3Click(Sender: TObject);begin Camera1.StopVideo;end;

Agora para parar a captura da imagem apenas atribua False para Camera1.Actif , isto pode ser feito num clique de botão o no Destroy do próprio formulário:

Sobre o autor

Marcos César Silva, Consultor de Sistemas na consultoria de sistemas DataSmart e Consultor Técnico do The Club, Bacharel em Ciência da Computação, MBA em Gestão Empre-sarial, Certificações MCAD (Microsoft Certified Application Developer) e MCSD.NET (Microsoft Certified Solution Developer .NET)

procedure TForm1.FormDestroy(Sender: TObject);begin Camera1.Actif := False;end;

Conclusão

Agora posso dormir tranqüilo, se um cliente quiser “inventar moda” de capturar imagens na sua aplicação, temos um recurso simples e prático, que pode ser implementado rapidamente.

Ate mais e boa sorte com seus clientes.

lagosto 2008 19

código fonte 02

Expressão lambda foi adicionada ao Visual Basic 2008 e C# 3.0, com o objetivo de apoiar ”Language Integrated Queries “(LINQ) .Quanto mais você utilizar a Expressão lambda, mais você verá sua potência e flexibilidade.

A lambda é uma grande inovação da linguagem, mas para você que está iniciando agora como desenvolvedor ou tem pouco tempo com a linguagem

pode parecer bem complicado. Não desanime, pois quando você começar a conhecer mais sobre lambda irá entender o quanto ela pode ser útil para o seu dia a dia.

Métodos Anônimos

Não poderia falar sobre expressão lambda sem falar de método anônimos que é uma das evoluções existentes no framework 2.0 lançado no final de 2005. Eles podem ser usados para passar um bloco de código para um delegate, de acordo com o parâmetro do delegate, também podem ser utilizados em lugares onde a criação de um método não é realmente necessária.Vejamos abaixo dois exemplos, um utilizando delegate e outro utilizando métodos anônimos.

Ver códigos fontes 01 e 02

Note que não precisamos escrever o método ImprimeMensagem, fazemos diretamente.

No entanto, métodos anônimos tem uma desvantagem no que diz respeito à legibilidade. Ele modifica a escrita e o código, por vezes se torna realmente difícil de ler.

Então, se tivermos realmente que fazer alguma coisa que seja fácil de ler, e também simples de usar, é aí que as expressões lambda trabalham a

nosso favor.Por isso muitos dizem que as Expressão

lambda são uma evolução natural dos Métodos Anônimos.

Expressão lambda?

O C# 2.0 introduziu o conceito de métodos

anônimos, que permitem que blocos de código se-jam escritos “em linha” onde delegamos os valores esperados. Assim podemos escrever códigos mais inteligentes e com um menor número de linhas.

As expressões lambda são muito utilizadas quando escrevemos métodos anônimos, elas nos permitem trabalhar de uma forma mais inteligente e lógica. Eles também se tornam muito úteis quan-

Lambda Expressionsclass ShowClassDelegate{ delegate void MeuDelegate(); public void EiMetodo() { MeuDelegate del = new MeuDelegate(ImprimeMensagem); del(); } void ImprimeMensagem() { Console.WriteLine(“E ai!!”); }}

Veja como fica com Métodos Anônimos

class ShowClassComAnonimos{ delegate void MeuDelegate(); public void EiMetodo() { MeuDelegate delAnonimo = delegate() { Console.WriteLine(“E ai!!”); }; delAnonimo(); } }

código fonte 01

agosto 200820

código fonte 03

código fonte 04

código fonte 05

Sobre o autor

do escrevemos expressões LINQ para pesquisa e também podem ser utilizadas em funções, como anteriormente já comentadas conseguimos escre-ver funções muito mais enxutas.

Criamos uma Lambda desta forma (parametro { =>} o que teremos de retorno), onde o “=>” e o operador e o que vem a antes dele é o parâmetro e após, o retorno.

Vamos dizer que queremos uma função que irá receber um inteiro, e irá retornar se o inteiro é superior a 10.

private bool Emaiorq10(int i){ if (i > 10) return true; else return false;}

A mesma função pode ser escrita como uma expressão lambda, em uma linha.

(int i => i > 10);

A Expressão lambda faz o mesmo trabalho como a função acima. O mais interessante é que podemos escrever isso em apenas uma linha.

Agora vamos criar uma classe para que pos-samos exemplificar melhor a Expressão lambda, como disse anteriormente ela é muito utilizada em consultas LINQ que é o que veremos a seguir:

public class Carros{ public string Marca { get; set; } public string Modelo { get; set; } public int Ano { get; set; }

}

Agora vou construir e popular minha Classe de Carros.

Ver código fonte 03

PS: Se você ainda não está familiarizado com

o C# 3.0 deve estar estranhando a criação das pro-priedades com os gets e sets direto e também a da Lista de carros populando direto no construtor sem antes ter criado um construtor para fazer isso. Pois bem, “seja bem-vindo”, essas são apenas duas de muitas novidades da linguagem, mas isto é assunto para o próximo artigo.

Eu mostrei como criar e instanciar um List<Carro> já passando os valores, agora vou utilizar alguns métodos chamados métodos esten-didos no namespace LINQ onde podemos fazer consultas em coleções.

Ver código fonte 04

Note que o (p =>) é Expressão lambda, que no

List<Carro> Carros = new List<Carro>{ new Carro { Modelo = “Astra”, Marca=”Chevrolet”, Ano=2005}, new Carro { Modelo = “Corsa”, Marca=”Chevrolet”, Ano=2004}, new Carro { Modelo = “Stilo”, Marca=”FIAT”, Ano=2008}, new Carro { Modelo = “Doblo”, Marca=”FIAT”, Ano=2006}, new Carro { Modelo = “Escort”, Marca= “Ford”, Ano=2000}, new Carro { Modelo = “Explorer”, Marca=”Ford”, Ano=2007}};

var Resultado = Carros.Where(p => p.Marca == “FIAT”);var Resultado1 = Carros.Average(p => p.Ano);

var Resultado2 = Carros.Where(p => p.Ano > 2005);var Resultado3 = Carros.Where(p => p.Modelo.Contains(“o”)) .OrderBy(o => o.Ano);

primeiro exemplo especifica um filtro para a Marca “FIAT” em seguida utilizamos uma lambda a partir do Objeto Carro para calcular a média. A partir daí podemos explorar vários exemplos de utilização.

Ver código fonte 05

Pra finalizar, um filtro utilizando o Contains que funciona como o Like do SQL e um OrderBy para ordenar o resultado pelo ano.

Bem pessoal espero ter passado o conceito básico da Expressão lambda, agora é só você se aprofundar e colocar em prática mais uma das novidades do C# e Visual Basic .NET 9.

Fabiano BelmonteSenior Architect da InfoMoney.com, especialista em aplicações e-Business com larga experiência em

B2B (Submarino.Com e Saraiva.Com). Trabalha há 5 anos com a tecnologia .Net, aplicando conhecimentos nas diversas áreas: instituições financeiras (sistema SPB), e-Commerce, gerenciamento logístico entre outras. Trabalhando com Visual Studio desde suas primeiras versões, responsável pela implementação de uma Metodologia de trabalho e melhoras significativas no resultados e na qualidade do time de Desen-volvimento de muitas empresas por onde passou como (Saraiva.Com) e ferramentas como TFS (Team Foundation Server).

Foi palestrante em eventos como Codificando. NET 2008 e outros eventos sobre Tecnologia .NET.Instrutor da e-TNIAX Group especialista em C#, ASP.NET e Silverlight. www.etniax.com.br

agosto 2008 21

A maioria dos bancos de dados hoje em dia roda no sistema cliente/servidor. Isso significa que o banco de dados fica como um serviço e toda vez que a aplicação necessita de dados, ela conecta com esse serviço e pega as informa-ções. Isso também significa que você tem que instalar o Gerenciador, configurar conexões, hostnames, portas e tudo mais.

O SQLite tem uma aboragem diferente: você não precisa instalá-lo, não precisa configurá-lo. Ele é uma biblioteca em C que gerencia bancos de dados direto no

sistema de arquivos. Todo seu banco de dados fica em um arquivo e essa pequena biblioteca controla o arquivo. Ele é executado sem a necessidade de utilização de um SGDB.

Você deve estar acostumado com bancos de dados relacionais cuja estrutura cliente-servidor exige a instalação do servidor de banco de dados. O SQLite não tem nada disto, ele pode ser com-pactado juntamente com a aplicação. Imagine um arquivo chamado “Agendas.db” contendo todas as tabelas do seu sistema. Você só terá de compactar este arquivo junto com sua aplicação para distribuir seu programa . Lembra do formato .DBF, comum entre as aplicações clipper ? Ou os arquivos .MDB do access ? Pois é, o sqlite tem o mesmo foco, proporcionar uma estrutura de banco de dados simples em arquivo para ser distribuído juntamente com aplicações standalone, e além disso implementa parcialmente o padrão SQL92, permite transações e triggers.

O SQLite não possui licença alguma, ele to-

O pequeno notáveltalmente disponibilizado pelos autores, a Hwaki (www.hwaki.com), ou seja, qualquer pessoa pode baixar as fontes no site, compilar, modificar, execu-tar, utilizar, sem problema algum, porém o site do SQLite ressalta que alguns usuários devem adquirir uma permissão para usar o SQLite:

1. Caso use em instituições não-publicas.2. Usar em instituições que não reconhe-

cem o autor.3. Deve publicar a licença em lugar visível

para os usuários. Salvo essas condições o SQLite é totalmente

livre para ser usado. O SQLite tem algumas restrições quanto ao

SQL92 e você pode ver elas no site http://www.sqlite.org/cvstrac/wiki?p=UnsupportedSql , as principais ausências podem ser vistas abaixo:

1. Instrução DELETE em múltiplas tabe-las.

2. Extract em tipos timestamp a. Select extract (year from timestamp ‘

2008-08-08’);3. Criação de domínios.4. Suporte Completo ao ALTER TABLE

(Somente algumas funcionalidades estão imple-mentadas)

Algumas Características do SQLite:

• Software Livre e Multiplataforma; • O Banco de dados é guardado em um

único arquivo; • Suporta base de dados acima de 2

terabytes; • Suporta Strings e Blob’s acima de 2

gigabytes; • Implementa a maioria do SQL92; • Suporte parcial a triggers e views; • Ainda não possui suporte a integridade

referencial;

Situações onde o SQLite funciona bem:

• A maioria dos sites web; • Bases de dados internas ou temporá-

rias; • Programas locais; • Substituto de bancos de dados de gran-

de porte em testes e demostrações; • Formato de arquivo de programas; • Dispositivos e programas embutidos;

agosto 200822

• Ensino de banco de dados.

Exemplos de uso:

O SQLite é utilizado em inúmeras aplicações desktop bem como em dispositivos eletrônicos, incluindo celulares, pocket pcs com celulares e MP3 Players.

Ferramentas:

Abaixo, segue algumas ferramentas para mani-pulação de arquivos baseados no SQLite.

SQLiteSpy (free)http://www.yunqa.de/delphi/doku.php/pro-

ducts/sqlitespy/index

SQLite Managerhttp://www.sqlitemanager.org/

Links:

Abaixo, segue alguns links para complementar o estudo desse artigo:

Site Oficial SQLite: http://www.sqlite.org/

SQLite ODBC Driverhttp://www.ch-werner.de/sqliteodbc/

Para fazer o download para plataforma Windows acesse o site do desenvolvedor :

http://www.sqlite.org/download.html. Clique em sqlite-3.6.0.zip

Iniciando o SQLLite

Vou abrir o prompt DOS ate a pasta onde se encontra o sqlite3.exe . No meu caso, o arquivo se encontra em C:\. Vamos criar um banco de dados. Para isso digite SQLite3 agenda.db. Essa linha no prompt seria equivalente a instrução SQL de CREATE DATABASE.

Observe a figura 1 Dê um Enter e pronto, seu banco Foi criado.

Observe a figura 2

Vamos criar uma tabela simples de Agendas. No prompt do comando digite C:\sqlte3 agenda.db .

Veja o exemplo abaixo(Figura 3):

Figura 1

Figura 2

Figura 3

agosto 2008 23

Agora vamos popular a tabela de Agendas utilizando o comando Insert

Veja código fonte 01

Dê um select para listar os registrosVeja código fonte 02

O ambiente console não é uma das interfaces mais agradáveis.

Para sorte de todos, existe uma ferramen-ta freeware com interface gráfica amigável, o SqlitePsy. Ele é um compacto gerenciador de banco de dados baseado no SQLite3. Ele lê arquivos e executa instruções SQL em cima desses arquivos. Sua interface gráfica facilita a exploração, análise e manipulação de base de dados SQLite3.

Faça o download da ferramenta em : http://www.yunqa.de/delphi/doku.php/products/sqli-tespy/index

Iniciando o SqliteSpy

Para criar um novo banco de dados clique em File/New DataBase. Criei um banco de dados exemplo chamado Agendamento ( figura 4).

Para criar uma nova instrução SQL clique file/

New SQL . A figura 5 demonstra a criação de uma tabela. Tecle F9 para executar a instrução

Nesse outro exemplo utilizo a instrução Insert

(figura 6) Aqui a tabela já está populada (Figura 7). Exemplo de utilização do comando Select

(Figura 8) Vamos criar uma tabela para gravar as modi-

ficações do telefones (figura 9)

Criando trigger no SQLLite3 com SQLSpy

A trigger é disparada quando uma tabela é modificada, quando ocorre ações de usuário no sistema. O exemplo abaixo (figura10), cria uma trigger que terá por finalidade gravar o valor antigo do campo telefone da tabela Agendas sempre que ela for alterada;

sqlite> insert into Agendas VALUES (1,’Alexandre, ‘3733-0011’);sqlite> INSERT INTO agendas VALUES (2,’Marcos’, ‘3452-6927’);

sqlite> select * from Agendas;1|Alexandre|3733-00112|Marcos|3452-6927sqlite>

código fonte 01

código fonte 02

Figura 4

Figura 5

Figura 6

agosto 200824

Conclusão

O SQLite3 é um banco de dados versátil , leve, portável e que não necessita instalação.

O fato dele permitir migrar o arquivo para ambientes diferentes é muito interessante, o que facilita também seu backup, já que todo seus dados estão contidos em apenas um arquivo. Ele é uma ótima sugestão para ser utilizado em ambientes educacionias assim como em testes.

Notas do consultor:

SGDB Um Sistema Gerenciador de Banco de

Dados ou SGDB é um conjunto de programas utilizados para criar e manter um banco de dados.

Padrão SQL 92 Padrão de regras básicas para manipu-

lação da informação nos bancos de dados relacionais

Sobre o autor

Luís Alexandre de Oliveira é Téc-nologo em Processamento de Dados ,graduado pela Faculdade de Técnologia de Sorocaba, Consultor técnico do The Club

Docente do curso técnico informática - Etec de Avaré e do curso Tecnologia em Redes de Computadores - Fatec Eduvale – Avaré

Figura 7

Figura 8

Figura 10

Figura 9

agosto 2008 25

Dicas DELPHIComo instalar o pacote de com-ponente Decision Cube no Delphi 2007

Abra o pacote dss.dpk que se encontra no diretório:

“C:\Arquivos de programas\CodeGear\RAD Studio\5.0\source\Win32\xtab”

Compile-o; em seguida abra o pacote dcldss.dpk que se encontra no mesmo diretório já citado diretório, clique com o botão direito em Requires | Add Reference.. e adicione ao pacote a referen-cia do arquivo dclbde.dcp que se encontra-se no seguinte diretório:

“C:\Arquivos de programas\CodeGear\RAD Studio\5.0\lib”

Compile-o e instale o pacote.

Finalmente em Tools | Options | Library - Win32, adicione em Library Path o caminho dos arquivos compilados do pacote:

“C:\Arquivos de programas\CodeGear\RAD Studio\5.0\source\Win32\xtab”

Pronto a Paleta de Decision Cube já estará disponível em Tool Palette.

Pegando a versão do Firebird que está rodando no servidor

type TForm1 = class(TForm) Button1: TButton; procedure Button1Click(Sender: TObject); function ObterVersaoServidor(const Servidor: string; const Usuario: string =

‘SYSDBA’; const Senha: string = ‘masterkey’): string; private { Private declarations } public { Public declarations } end;var Form1: TForm1;

Implementation

uses IBServices;

{$R *.dfm}procedure TForm1.Button1Click(Sender: TObject);begin ObterVersaoServidor(‘NOME’); caption := ObterVersaoServidor(‘NOME’);end;function TForm1.ObterVersaoServidor(const Servidor: string; const Usuario: string = ‘SYSDBA’; const Senha: string = ‘masterkey’): string; var IBServerProperties: TIBServerProperties; begin IBServerProperties := TIBServerProperties.Create(nil); try IBServerProperties.ServerName := Servidor; IBServerProperties.LoginPrompt := False; IBServerProperties.Params.Add(Format(‘user_name=%s’, [Usuario])); IBServerProperties.

Params.Add(Format(‘password=%s’, [Senha])); IBServerProperties.Active := True; try IBServerProperties.Options := IBServerProperties.Options + [Version]; IBServerProperties.FetchVersionInfo; Result := Format(‘%s %s %d’, [IBServerProperties.

VersionInfo.ServerVersion, IBServerProperties.VersionInfo.ServerImplementation, IBServerProperties.VersionInfo.ServiceVersion]); finally IBServerProperties.Active := False; end; finally IBServerProperties.Free; end; end;

end.

Descobrir o nome da tabela no ClientDataSet

uses DbCommon; function NomedaTabela(DataSet:

agosto 200826

TDataSet): String; begin Result:=GetTableNameFromSQL(((FindComponent((DataSet as TClientDataSet).ProviderName) as TDataSetProvider).DataSet as TSQLQuery).Text) end;

Desenhar uma linha sobre os re-gistros do DBgrid

var Form1: TForm1;implementation{$R *.dfm}procedure TForm1.BGrid1DrawColumnCell(Sender: TObject; const Rect: TRect; DataCol: Integer; Column: TColumn; State:

TGridDrawState);begin if Table1.FieldByName(‘PUR_DATE’).AsDatetime > StrToDate(‘01/01/1992’) then

begin DBGrid1.Canvas.Pen.Color:=clRed; DBGrid1.Canvas.Pen.

Width:=2; DBGrid1.Canvas.MoveTo(0,Rect.top+8); DBGrid1.Canvas.LineTo(DBGrid1.Width,Rect.Top+8); end else DBGrid1.DefaultDrawColumnCell(Rect,DataCol,Column,State);end;

end.

Habilitar e desbilitar botões no form de forma genérica

procedure TForm1.BitBtn4Click(Sender: TObject);var i: integer;begin for i:= 0 to componentcount -1 do if (Components[i] is TButton) then (Components[i] as TButton).Enabled :=false;end;

agosto 2008 27

Rotina para conversor de valores por extenso

A conversão de valores numéricos em valores por extenso é uma neces-sidade muito comum em sistemas, podendo ser usado na impressa de

cheques, recibos e duplicatas. Esta dica não tem a pretensão de ser um artigo, e outras lógicas até mais eficiente podem ser aplicadas para o mesmo objetivo, assim veja abaixo a classe de conversão com comentários aonde podemos praticar o uso da linguagem C#:

Figura 1 Classe Extenso

Ver código fonte 01

Ver Figura 02 Para usar a classe de valores por extenso,

adicione em um form um textbox para entrada do valor, um label para exibir o valor por extenso e um botão para a conversão do valor, veja abaixo o evento do clique do botão onde é declarada e usada a classe de conversão, obseve que o namespace do projeto é o mesmo da classe, assim não há neces-siade de declarar a classe no using do form:

Ver código fonte 02

Baixe o exemplo através do link:http://www.theclub.com.br/downloads/rev0808/ ValorPorExtenso.zip

using System;using System.Collections.Generic;using System.Linq;using System.Text;

namespace ValorPorExtenso{ class Extenso { //propriedade privada da classe private double _Valor;

public double Valor { get { return _Valor; } }

/// <summary> /// Método principal da classe /// Retorna o Valor por extenso /// </summary> /// <returns>string</returns> public string ValorPorExtenso(double Valor) { _Valor = Valor; int Centavos; try { //Verifica a parte decimal, ou seja, os centavos Centavos = (int)Math.Round((_Valor - Math.Truncate(_Valor)) * 100, MidpointRounding.ToEven);

//Verifica apenas a parte inteira _Valor = Math.Truncate(_Valor);

//Caso existam centavos if (Centavos > 0) { // Caso seja 1 não coloca “Reias” mas sim “Real” if (_Valor == 1) return “Um Real e “ + RetornaDecimal(Centavos) + “Centavos”; else return RetornaInteiro((int)_Valor) + “ Reais e “ + RetornaDecimal(Centavos) + “Centavos”; } else {

código fonte 01

Dicas ASP.NET

agosto 200828

//Caso seja 1 não coloca “Reias” mas sim “Real” if (_Valor == 1) return “Um Real”; else return RetornaInteiro((int)_Valor) + “ Reais”; } } catch { return “Erro na conversão”; } }

/// <summary> /// Retorna os valores decimais /// </summary> private string RetornaDecimal(int Numero) { string Retorno= “”; try { if (Numero == 0) Retorno = “”; else if ((Numero >= 1) && (Numero <= 19)) { string[] Lista = new string[] { “Um”, “Dois”, “Três”, “Quatro”, “Cinco”, “Seis”, “Sete”, “Oito”, “Nove”, “Dez”, “Onze”, “Doze”, “Treze”, “Quatorze”, “Quinze”, “Dezasseis”, “Dezassete”, “Dezoito”, “Dezanove” }; Retorno = Lista[Numero - 1] + “ “; } else if ((Numero >= 20) && (Numero <= 99)) { string[] Lista = new string[] { “Vinte”, “Trinta”, “Quarenta”, “Cinquenta”, “Sessenta”, “Setenta”, “Oitenta”, “Noventa” }; if ((Numero % 10) == 0) Retorno =

Lista[Numero / 10 - 2] + “ “; else Retorno = Lista[Numero / 10 - 2] + “ e “ + RetornaDecimal(Numero % 10) + “ “; } return Retorno; } catch { return “ Erro do retorno decimal”; } } /// <summary> /// Retorna os valores decimais /// </summary> private string RetornaInteiro(int Numero) { string Retorno = “”; try { if (Numero < 0) Retorno = “-” + RetornaInteiro(-Numero); else if (Numero == 0) Retorno = “”; else if ((Numero >=1) && (Numero <= 19)) { string[] Lista = new string[] {“Um”, “Dois”, “Três”, “Quatro”, “Cinco”, “Seis”, “Sete”, “Oito”, “Nove”, “Dez”, “Onze”, “Doze”, “Treze”, “Quatorze”, “Quinze”, “Dezasseis”, “Dezassete”, “Dezoito”, “Dezanove”}; Retorno = Lista[Numero - 1] + “”; } else if ((Numero >=20) && (Numero <= 99)) { string[] Lista = new string[] { “Vinte”, “Trinta”, “Quarenta”, “Cinquenta”, “Sessenta”, “Setenta”, “Oitenta”, “Noventa” }; if ((Numero % 10) ==0) Retorno = Lista[Numero / 10 - 2];

código fonte 01 código fonte 01

agosto 2008 29

else Retorno = Lista[Numero / 10 - 2] + “ e “ + RetornaDecimal(Numero % 10); } else if (Numero == 100) Retorno = “Cem “; else if ((Numero >=101) && (Numero <= 999)) { string[] Lista = new string[] { “Cento”, “Duzentos”, “Trezentos”, “Quatrocentos”, “Quinhentos”, “Seiscentos”, “Setecentos”, “Oitocentos”, “Novecentos” }; if (Numero % 100 == 0) Retorno = Lista[Numero / 100 - 1] + “ “; else Retorno = Lista[Numero / 100 - 1] + “ e “ + RetornaInteiro(Numero % 100); } else if ((Numero >=1000) && (Numero <= 1999)) { int Resto = Numero % 1000; if (Resto == 0) Retorno = “Mil “; else if (Resto <= 100) Retorno = “Mil e “ + RetornaInteiro(Resto); else Retorno = “Mil, “ + RetornaInteiro(Resto); } else if ((Numero >=2000) && (Numero <= 999999)) { int Resto = Numero % 1000; if (Resto == 0) Retorno = RetornaInteiro(Numero / 1000) + “ Mil “; else if (Resto <= 100)

Retorno = RetornaInteiro(Numero / 1000) + “ Mil e “ + RetornaInteiro(Resto); else Retorno = RetornaInteiro(Numero / 1000) + “ Mil, “ + RetornaInteiro(Resto); } else if ((Numero >= 1000000) && (Numero <= 1999999)) { int Resto = Numero % 1000000; if (Resto == 0) Retorno = “Um Milhão “; else if (Resto <= 100000) Retorno = RetornaInteiro(Numero / 1000000) + “ Milhão e “ + RetornaInteiro(Resto); else Retorno = RetornaInteiro(Numero / 1000000) + “ Milhão, “ + RetornaInteiro(Resto); } else if ((Numero >= 2000000) && (Numero <= 999999999)) { int Resto = Numero % 1000000; if (Resto == 0) Retorno = RetornaInteiro(Numero / 1000000) + “ Milhões “; else if (Resto <= 100000) Retorno = RetornaInteiro(Numero / 1000000) + “ Milhões e “ + RetornaInteiro(Resto); else Retorno = RetornaInteiro(Numero / 1000000) + “ Milhões, “ + RetornaInteiro(Resto); } else if ((Numero >= 1000000000) && (Numero <= 1999999999)) {

código fonte 01 código fonte 01

agosto 200830

int Resto = Numero % 1000000000; if (Resto == 0) Retorno = “Um Bilhão “; else if (Resto <= 1000000000) Retorno = RetornaInteiro(Numero / 1000000000) + “ Bilhão e “ + RetornaInteiro(Resto); else Retorno = RetornaInteiro(Numero / 1000000000) + “ Bilhão, “ + RetornaInteiro(Resto); } return Retorno; } catch { return “ Erro ao pegar o valor decimal”; } } }}

namespace ValorPorExtenso{ public partial class Form1 : Form { public Form1() { InitializeComponent(); }

private void button1_Click(object sender, EventArgs e) { Extenso E = new Extenso(); double Valor = Convert.ToDouble(tbValor.Text); lbExtenso.Text = E.ValorPorExtenso(Valor); } }}

Figura 2 – Form de utilização da classe

código fonte 02código fonte 01

agosto 2008

agosto 2008