Você está na página 1de 30

Revista The Club Megazine - 03/2002

A utilizao, reproduo, apropriao, armazenamento em banco de dados, sob qualquer forma ou meio, de textos, fotos e outras criaes intelectuais em cada publicao da revista The Club so terminantemente proibidos sem autorizao escrita dos titulares dos direitos autorais.

Copyright The Club 2002

EDITORIAL

Editorial
THE CLUB
Rua Acre, 950 - Avar - SP - CEP 18.700-260 Informaes: (0xx14) 3732-3689 Suporte: (0xx14) 3733-1588 Fax: (0xx14) 3732-0987

Internet
http://www.theclub.com.br Cadastro: cadastro@theclub.com.br Suporte: suporte@theclub.com.br Informaes: info@theclub.com.br

Dvidas
Correspondncia ou fax com dvidas devem ser enviados ao - THE CLUB, indicando "Suporte".

Opinio
Se voc quer dar a sua opinio sobre o clube em geral, mande a sua correspondncia para a seo "Tire sua dvida".

Reproduo
A utilizao, reproduo, apropriao, armazenamento em banco de dados, sob qualquer forma ou meio, de textos, fotos e outras criaes intelectuais em cada publicao da Revista The Club so terminantemente proibidos sem autorizao escrita dos titulares dos direitos autorais.

O THE CLUB em conjunto com a VUE firmaram uma parceria para aplicao de testes especializados da Microsoft, Novell Cisco e outros. Eis alguns exemplos de certificao da Microsoft: MCP - Microsoft Certified Professional - Pessoa que passou em pelo menos um exame de certificao da Microsoft. MCSE - Microsoft Certified System Engineer - Pessoa que passou em 7 exames de certificao da Microsoft. Profissional totalmente habilitado para trabalhar com o ambiente do Windows 2000. Este profissional hoje to requisitado que, as pessoas que conquistam essa certificao tem emprego garantido na Brs e Figueiredo, o maior parceiro da Microsoft no mundo. MCDBA - Microsoft Certified DataBase Administrator - Pessoa que passou em 4 exames. Dois exames de Windows 2000 e dois de SQL Server. MCSD - Microsoft Certified Solution Developer - Pessoa que passou em 4 exames. Dois exames sobre Visual Basic ou C, um sobre SQL Server, um sobre anlise de sistemas. MCSA - Microsoft Certified System Administrator - Pessoa que passou em 4 exames sobre Windows 2000. Os exames podem ser feitos no THE CLUB. Para maiores informaes ligue para (14) 3732-3689. Informaes sobre a certificao Microsoft e os exames disponveis podem ser obtidos no endereo: http://www.microsoft.com/mcp. As inscries tambm podem ser feitas no site da VUE: http://www.vue.com.

Copyright The Club 2002 Impresso e acabamento:


Impressos Gril - Gril Grfica e Repr. Ind. Ltda.
Tel.: (0xx14) 3762.1345 - Fax: (0xx14) 3762.1259 Rua So Paulo, 447 - Cep 18.740-000 Taquarituba - SP Tiragem: 5.000 exemplares

Celso Jefferson Paganelli Presidente - The Club

Diretor - Presidente

Celso Jefferson M. Paganelli


Diretor Tcnico

Mauro SantAnna
Colaboradores
Mrio Camilo Bohm - Claudenir C. Andrade Anderson Haertel Rodrigues - Cludio Akerman
Delphi marca registrada da Borland International, as demais marcas citadas so registradas pelos seus respectivos proprietrios.

Editorial .................................................................... 03 News ........................................................................ 04 HOTSYNC com emulador ......................................... 05 Tratamento global de exceptions ............................. 08 Dicas de instrues e comandos Oracle ................... 11 Que fazer para.... Recuperar as formas de pagamento do ECF............. 15 Trabalhando com o campo BLOB no Interbase ......... 16 FireBird a continuidade do Interbase Open-Source .. 24 Eventos ..................................................................... 27 Dicas & Truques ........................................................ 30
MeGAZINE 3

NEWS

ReNet Tecnologia lana a verso 3.0 do software XTNDConnect Professional Edition


A ReNet Tecnologia Ltda lanou em Maro/2001 a verso 3.0 do software XTNDConnect Server Professional Edition (l-se Extend Connect), da Extended Systems Inc, que soluo centralizada de sincronizao e gerenciamento de equipamentos mveis, independente de plataforma. Suporta uma ampla variedade de plataformas como: Palm OS, Windows CE/Pocket PC, Symbian. Suporta conexo TCP/IP entre o equipamento mvel e o servidor atravs de RAS, PPP, rede local, e redes sem fio 802.11B, CDMA, TDMA, GSM e CDPD. Com o XTNDConnect Server, a equipe de TI tem um padro corporativo para gerenciar de maneira centralizada os equipamentos mveis, com recursos de sincronizao de servidores Groupware e/ ou servidores de banco de dados, trazendo ainda benefcios como: ferramentas para gerenciar os dados e aplicaes transferidas para os equipamentos mveis, configurar tarefas para automaticamente distribuir e configurar e distribuir aplicaes, log de status e erros. Sua interface intuitiva faz com que o processo de sincronizao seja configurado de maneira fcil e rpida, trazendo benefcios tanto para os usurios quando para a equipe de TI. Para o usurio corporativo, a integrao dos equipamentos mveis com a organizao significa fazer os equipamentos mveis mais teis e fceis de usar. A interface cliente do XTNDConnect Server PE foi desenvolvida para ser soluo transparente, intuitiva e de fcil uso. A soluo XTNDConnect Server permite que usurios de equipamentos mveis sincronizem dados como emails, agendas, contatos, tarefas, informaes de banco de dados corporativos via ODBC, alm de recursos gerenciais como: distribuio automtica de aplicativos, backup e restore de dados. Tudo isso de maneira segura, pois o XTNDConnect utiliza o algortmo de criptografia de 128 bits da CERTICOM. A soluo XTNDConnect Server testada e homologado por vrias empresas parceiras como : Agilent, Compaq, HewlettPackard, IBM, Microsoft, Nec, Palm e Toshiba. A nova verso XTNDConnect Server 3.0 Professional Edition alm dos recursos acima ainda possui : o Recurso Auto Messaging: permite que equipamentos mveis com rede wireless fiquem sempre ouvindo a rede e utilizarem a tecnologia push para receber emails, incluindo os novos recursos do Palm 705. * Nova interface grfica para o usurio, incluindo o conceito de profiles. * Protocolo de comunicao otimizao para redes wireless. * Melhorado o processo de distribuio de clientes para os equipamentos mveis. * Mail Plus para Palm OS: recurso que agiliza o processo de sincronizao de e-mail. Tambm suporta recurso de reunio (meeting requests) e tambm melhor recurso para manipulao de arquivos anexados (attachments). * Novas funes de gerenciamento no recurso MMC (Microsoft Management Console). Conhea mais sobre o XTNDconnect e a solues de computao mvel em www.renet.com.br, ou contate-nos para maiores informaes.

ReNet Tecnologia Ltda. - Tel.: 11 3872-0423

MeGAZINE

DELPHI

HOTSYNC
com Emulador
Por: Claudio Akerman
Ol amigos do The Club, estamos de volta com mais um artigo sobre a plataforma Palm. Em uma das edies anteriores, mostramos como voc pode desenvolver um sistema de Conduit usando o Delphi. Para testar seu Conduit, voc pode usar o Emulator do Palm para garantir que seu Conduit esteja funcionando perfeitamente antes de coloc-lo em produo em equipamentos Palm. isso que vamos mostrar hoje!

Configurando o ambiente

Configurando o PC
Clique com o boto direito do mouse no cone do Hotsync

Introduo
O emulador uma tima ferramenta para se testar aplicaes em desenvolvimento. Transferir uma aplicao para o Emulador muito mais rpido do que para um dispositivo Palm.

Vantagens
1) O Hotsync com o emulador mais rpido que o realizado com o prprio dispositivo; 2) Capacidade de testar vrios modelos diferentes de dispositivos; 3) Capacidade de configurar diferentes usurios; 4) No gasta bateria; 5) No necessita porta serial;

1. Marque a opo Network. As outras opes (Local e Modem) tambm podem estar marcadas.

Verso do Palm OS
O sincronismo em rede, que permite o Hotsync com o emulador, est disponvel nas verses do PalmOS superiores a 3.0, ou seja, a ROM utilizada no emulador dever ser de uma verso igual ou superior a esta. Entre na opo de Setup.

MeGAZINE

DELPHI
1 - Escolha a aba Network.

2 - Marque os usurios que tero permisso de efetuar o HotSync.

3 - Clique neste boto para ver e anotar os dados de TCP/IP da sua estao de trabalho.

Configurando o Emulador
1 - Clique com o boto direito do mouse sobre o emulador e escolha: Settings e em seguida Properties. Preencha a caixa HotSync User Name com o nome do usurio que ser utilizado para efetuar o sincronismo.

MeGAZINE

DELPHI
5 -Selecione no menu a opo Primary PC Setup. 2 - Selecione a aplicao HotSync

3 - Selecione no menu a opo Modem Sync Prefs

Escreva em Primary PC Name ou em Prymary PC Address os dados anotados do TCP/IP Settings de sua mquina.

6 - Selecione Modem na tela principal do HotSync Clique em seguida em Select Service. 7 - Voc pode deixar marcado o servio default. Service: Aimnet 4 -Selecione no menu a opo LANSync Prefs Em seguida entre com o telefone 00. 8 - Agora clique no cone do HotSync e ele ir acontecer.

Escolha a opo Network

Escolha a opo LANSync.

MeGAZINE

.NET

Tratamento Global de Exceptions


Por Mauro SantAnna (santanna@mas.com.br). Mauro um MSDN Regional Director, consultor e instrutor da MAS Informtica (www.mas.com.br), tendo ministrado treinamentos na arquitetura .NET desde outubro de 2000 para diversas empresas, dentre as quais a prpria Microsoft.
Este artigo no pretende abordar amplamente o mecanismo de tratamento de exceptions e sim mostrar um pequeno truque. Este truque NO dispensa o correto tratamento de exceptions nem a farta distribuio de try/finallys, ambos usualmente esquecidos mas isto outra longa e triste histria que ficar para outra ocasio. Muitas vezes estamos processando exceptions para tomar decises importantes na execuo dos aplicativos. No entanto, algumas vezes o tratamento e exceptions NO afeta a lgica do programa, pois estamos APENAS fazendo uma ou mais das seguintes tarefas: Traduzindo as mensagens de erro para Portugus (enquanto a verso localizada do .NET Framework no est disponvel); Mostrando as mensagens em uma caixa de dilogo mais bonitinha; Logando as mensagens de erro em um arquivo ou no System Log. Nestes casos mais simples E APENAS NELES possvel fazer um tratamento global de exceptions. Para isto, criaremos um mtodo que vai tratar as exceptions e o associaremos com um evento do aplicativo. Quem tiver familiaridade com o Delphi da reconhecer o mecanismo usado, pois ele tambm est disponvel na ferramenta da Borland.

Criando a funo de tratamento


Crie um projeto C# com formulrios no Visual Studio .NET:

Criando a funo de tratamento

Crie um projeto C# com formulrios no Visual Studio .NET::

MeGAZINE

.NET
Na classe do formulrio, crie um mtodo como o mostrado a seguir. O nome do mtodo e dos argumentos podem variar, mas os tipos dos argumentos devem ser mantidos: public void DeuPau(object sender, System.Threading.ThreadExceptionEventArgs t) { // Trata exception MessageBox.Show (this, t.Exception.Message, Deu Pau); } onde a exception foi gerada; Embora estejamos fazendo o tratamento no formulrio principal, ele funciona para todos os formulrios.

Testando
Para testar o nosso programa, devemos causar o disparo de algumas exceptions. Acrescente botes ao formulrio:

Associando o tratamento global


Precisamos agora associar as exceptions ao mtodo acima. No construtor do formulrio acrescentaremos uma linha de cdigo: public Form1() { // // Required for Windows Form Designer support // InitializeComponent(); // // TODO: Add any constructor code after InitializeComponent call // Application.ThreadException+=new System.Threading.ThreadExceptionEventHandler(DeuPau); } Note o seguinte: No h nada de mgico no cdigo acima. A classe Application foi especialmente preparada de forma a permitir que um mtodo criado depois trate as exceptions; Este mecanismo depende do message loop dentro do mtodo Application.Run(), o que por sua vez significa que este mecanismo s est disponvel para programas que usem formulrios; O fato do programa no terminar quando ocorrer uma exception tambm uma caracterstica de como feito o tratamento das exceptions no cdigo do message loop: o processamento da mensagem do Windows que disparou a exception terminado (por exemplo um click no boto ou item de menu), mas as prximas mensagens so processadas normalmente; Caso o cdigo que processe o evento trate a exception, o tratamento global no ser executado. Este um comportamento desejvel; No temos informaes especficas de onde ocorreu ou o que exatamente ocorreu. No podemos tambm reiniciar o cdigo de

Coloque o cdigo seguinte para processar os eventos Click: // Diviso por zero private void button1_Click(object sender, System.EventArgs e) { decimal x = 0; decimal y = 10 / x; Text = y.ToString(); } // Arquivo no existe private void button2_Click(object sender, System.EventArgs e) { System.IO.StreamReader Arq = new System.IO.StreamReader(xxx.www); } // Acesso a referncia nula private void button3_Click(object sender, System.EventArgs e) { object O = null; Text = O.ToString(); } // Cast invlido

MeGAZINE

.NET
private void button4_Click(object sender, System.EventArgs e) { int i = 10; object O = i; double d = (double) O; } // Converso invlida private void button5_Click(object sender, System.EventArgs e) { Convert.ToInt32(Z); } Veja um exemplo do tratamento: public void DeuPau(object sender, System.Threading.ThreadExceptionEventArgs t) { // Trata exception string Msg; if (t.Exception is DivideByZeroException) Msg = No posso dividir por zero; else if (t.Exception is System.IO.IOException) Msg = Problema no acesso a arquivo; else if (t.Exception is NullReferenceException) Msg = Referncia nula acessada; else if (t.Exception is InvalidCastException) Msg = Problema na converso de tipos; else if (t.Exception is FormatException) Msg = No posso converter o texto suprido; else Msg = Exception desconhecida\r\n + t.Exception.Message; MessageBox.Show(this, Msg, Deu Pau); }

Tratando cada exception


Voc pode identificar a exception disparada e dar um tratamento especial a cada uma delas. Voc pode tambm dar um tratamento padro s exceptions desconhecidas. Veja o cdigo para fazer isto:

Concluso
O tratamento global de exceptions, embora esteja longe de resolver todas as questes relacionadas ao tema, uma tcnica til para fazer um tratamento simples.

10

MeGAZINE

ORACLE

Dicas de Instrues e Comandos Oracle...


Mrio Camilo Bohm - Bohm,Interal Fone (011) 4221.6151 - mario@bohminteral.com.br

Neste ms, vamos discutir algumas dicas bastante teis para programao SQL e para administrao de bases Oracle. Divirtam-se!

LIMITANDO O NMERO DE LINHAS DO SELECT


Vamos tomar como hiptese uma tabela de CLIENTES com mais de 100.000 registros. Depois de orden-la por um determinado campo, LIMCRED

por exemplo, que equivale ao limite de crdito do cliente, podemos desejar ver apenas os registros mais significativos, que contm os maiores limites de crdito. Podemos para isso utilizar ento a clusula ROWNUM e definir para ela um parmetro, que corresponder ao nmero de linhas que iremos desejar no retorno do SELECT. Veja que simples:

MeGAZINE

11

ORACLE

GROUP BY E A CLUSULA HAVING


Imaginemos agora que queremos totalizar nossas vendas por cliente, utilizando para isso um join da tabela CLIENTES com a tabela PEDIDOS, que guarda no campo CHAVE_CLIENTE a identificao do CLIENTE daquele pedido, fundamentando uma CONSTRAINT FOREIGN KEY. Podemos para isso utilizar a clusula GROUP BY, agrupando, totalizando e calculando a mdia das vendas por cliente.

evidente que iremos obter tantos registros quantos forem os clientes com negcios dentro da seleo que fizermos, o que nem sempre necessrio e importante para nossas anlises. Podemos desejar como resultado, por exemplo, apenas os clientes com mais de R$ 3.150.000,00 de pedidos acumulados. Para isso, podemos utilizar a clusula HAVING dentro de nosso GROUP BY. Veja que simples:

12

MeGAZINE

ORACLE
Agora temos apenas os clientes que tem vendas acumulada acima do parmetro que definimos na clusula HAVING. Simples no?

LISTANDO OS OBJETOS DE UM USURIO


Para identificarmos e listarmos os objetos de um determinado usurio Oracle, podemos utilizar a VIEW USER_OBJECTS do dicionrio de dados.

Vamos utilizar ento essa VIEW para listarmos, em ordem de TIPO DE OBJETO e depois de NOME DE OBJETO, todos os objetos do usurio em que estivermos conectados:

MeGAZINE

13

ORACLE

A partir da fica fcil, por exemplo, listarmos apenas os objetos TABLE do usurio, em ordem de nome do objeto:

Simples tambm no mesmo? Voc vai notar, contudo, que os objetos CONSTRAINT no aparecem nessa VIEW, porque na verdade so objetos que dependem da existncia de outros e esto relacionados na VIEW USER_CONSTRAINTS. No prximo ms continuaremos com novas e interessantes dicas. At l!

14

MeGAZINE

DELPHI

Que fazer para....


Recuperar as formas de pagamento do ECF?
Por: Claudenir C. Andrade - Analista de Sistemas para Automao Comercial claudenir@bematech.com.br
Em um PDV existem vrios controles que devem ser emitidos pelo prprio ECF ou controles internos do software para manter a consistncia entre o ECF e o Software de automao comercial. Entre estes controles podemos enumerar vrios deles, por exemplo, Nmero de itens cancelados, Nmero de Itens Vendidos, Nmero de Redues ou Fechamentos Realizados, Total de Cancelamentos, total de Sangrias e Suprimentos realizados, etc.. Entre todos estes controles existe um muito critico e de importncia vital para o controle do caixa Formas de Pagamento. No ECF as formas de pagamento devem ser cadastradas no comeo do dia fiscal, antes de realizar qualquer venda no PDV. Toda vez que o operador realiza um fechamento de caixa, Reduo z Alm de zerar os totalizadores existentes o ECF tambm ir eliminar os valores e as descries das formas de pagamento cadastradas no comeo do dia. Que problema!! J imaginou se no meio do dia seu cliente necessita cadastrar uma forma de pagamento? Impossvel fazer isso em alguns ECFS. Na Bematech, utilizando a DLL BemaFI32.dll ao realizar uma venda e fechar o cupom fiscal, a dll com um comando interno cadastra as formas de pagamento automaticamente no ECF, exonerando o software da tarefa de todos os dias, ao abrir o caixa, enviar as formas de pagamento, pr-fixadas, para o ECF. Esta vantagem pode ser uma faca de dois gumes, porque? Porque assim como voc tem esta facilidade de ter o cadastramento das formas de pagamento dinamicamente, ou seja no ato da venda, o seu software possui uma probabilidade maior de estar sem sincronia, as formas de pagamento cadastradas no ECF com as formas de pagamento cadastradas em seu software. Por isso, em nossa que fazer para.. deste ms estamos falando exatamente sobre isso, como ler as formas, as descries, das formas de pagamento do ECF. Segue abaixo um algoritmo que o que fazemos 1) Chamar a funo da dll que nos devolve as formas de pagamento com seus valores 2) Destrinchar os valores das descries 3) Armazenar as descries em um array Com isso teremos este array a nossa disposio para alimentar um Combo ou um list Box, exibir para o usurio as formas de pagamentos disponveis ou , conforme comentamos nos pargrafos iniciais, emitir um relatrio das formas de pagamento. Tenho a certeza que o algoritmo abaixo ser muito til em sua aplicao. procedure TForm1.Leitura_FormasdePagamento ; Var sFormas: string; sDescricao: string; iConta:integer; aFormasPagamento: array[0..16] of string; iRet :Integer; begin for iConta := 1 to 3016 do sFormas := sFormas + ; iRet := Bematech_FI_VerificaFormasPagamento ( sFormas ); sDescricao:=Dinheiro; iConta:=0; While (iconta<=16) do begin sDescricao:=Copy( sFormas, 0, 16); if (Trim(sDescricao)=) then begin exit; end; sFormas:=Copy(sFormas,59,StrLen (Pchar(sFormas)) - 60); aFormasPagamento[iConta]:=Trim(sDescricao); iConta:=iConta+1; end;

MeGAZINE

15

DELPHI

Trabalhando com campo Blob no Interbase.


Um das caractersticas mais teis da maioria dos bancos de dados modernos a habilidade para armazenar dados binrios, por exemplo, dados de qualquer tipo, formato, ou tamanho. O InterBase foi de fato o primeiro banco de dados a caracterizar tal tipo de campo, e se refere a isto como um BLOB. Aqui est como foi definido na documentao do InterBase: O InterBase fornece um tipo (BLOB) para armazenar dados que no podem ser armazenados facilmente em um dos tipos de dados padres do SQL. Um BLOB usado para armazenar dados muito grandes de tamanho indeterminado e varivel, como imagens, arquivos de som, segmentos de vdeo ou qualquer outro tipo de informao multimidia. A ferramenta bsica para se trabalhar com campos Blob so os mtodos do TBlobField chamados LoadFromFile e SaveToFile. Se a nica coisa que voc quer fazer com um BLOB carregar um arquivo externo que contm os dados do BLOB em uma tabela da banco de dados, ou salvar os dados do BLOB em uma tabela do banco de dados para um arquivo externo, estes so os nicos mtodos que voc precisar. Porm, voc pode fazer muito mais com o BLOB utilizando os componentes nativos do Delphi. Este artigo mostra tcnicas para pegar dados Blob dentro e fora dos campos em registros de banco de dados, memria, arquivos e componentes do Delphi. O exemplo que acompanha este artigo usa uma base de dados Interbase, os componentes da palheta Interbase Express, e um ClientDataSet, mas os mesmos mtodos e tcnicas trabalharo com a maioria dos componentes dataset do Delphi. O banco de dados Interbase tem apenas duas tabelas. A primeira Blobs, e a estrutura mostrada na figura 1. O BLOB_TYPE_DOMAIN um VarChar(32) usado para receber uma descrio de texto do tipo BLOB no registro. A segunda tabela, Blob_Type, contm uma lista de tipos Blobs vlidos e usado para validar o valor do campo Blob_Type na tabela Blobs. A validao do campo Blob_Type feito por triggers Before Insert e Before Update. O valor do campo Blob_ID fornecido por um generator. CREATE TABLE Blobs( Blob_ID INTEGER NOT NULL, Blob_Type BLOB_TYPE_DOMAIN, Text_Data BLOB SUB_TYPE TEXT SEGMENT SIZE 80, Binary_Data BLOB SUB_TYPE 0 SEGMENT SIZE 512, PRIMARY KEY(Blob_ID)); Figura 1: Estrutura da tabela Blobs

Trabalhando com Bitmaps


Os mtodos LoadFromFile e SaveToFile so mtodos da classe TBlobField. TBlobField a classe de objeto de campo usada por campos Blob se voc instanciar o campo em tempo de design usando o Fields Editor, ou deixar o Delphi criar o campo dinamicamente em tempo de execuo. A figura 2 mostra o cdigo do boto Load File no form BitMap da aplicao exemplo mostrada na figura 3. Este cdigo comea configurando a propriedade InitialDir do componente TOpenDialog chamado OpenBmpDialog e ento ele chama o mtodo Execute para

16

MeGAZINE

DELPHI
mostrar a caixa de dilogo. Se o usurio escolher um arquivo e clicar no boto OK, o cdigo verifica se o ClientDataSet, cdsBlob, est em modo Browse. Neste caso o mtodo Edit do ClientDataSet chamado. Depois o mtodo LoadFromFile chamado para carregar o contedo do arquivo selecionado para dentro do campo Binary_Data do registro corrente. procedure TfrmBmp.btnLoadFileClick(Sender: TObject); begin with OpenBmpDlg do begin InitialDir := ExtractFilePath( Application.ExeName + gFileDir); if not Execute then Exit; end; if dmMain.cdsBlob.State = dsBrowse then dmMain.cdsBlob.Edit; dmMain.cdsBlobBinary_Data.LoadFromFile( OpenBmpDlg.FileName); end; Figura2: Cdigo do boto Load File do form BitMap Este cdigo s trabalha porque o campo cdsBlob ClientDataSet foi instanciado em tempo de design usando o Fields Editor, assim que o objeto instanciado TBlobField chamado cdsBlobBinary_Data poderia se usado para chamar o mtodo LoadFromFile. Se voc tentar usar: dmMain.cdsBlob.FieldByName(Binary_Data). LoadFromFile(OpenBmpDlg.FileName; voc receber um erro Undeclared identifier:LoadFromFile . Isto acontece porque o mtodo FieldByName retorna uma referencia de objeto TField e TField no tem o mtodo LoadFromFile. Se voc quer usar o FieldByName ou o array de Fields para acessar os campos, voc ter que converter a referncia para TBlobField como mostrado na instruo abaixo: dmMain.cdsBlob.TBlobField(FieldByName(Binary_Data )).LoadFromFile(OpenBmpDlg.FileName; O boto Save File do form BitMap usa um cdigo quase igual. A nica diferena que ele usa um TSaveDialog e chama o mtodo SavetoFile O BitMap o tipo mais fcil para se trabalhar com o Delphi, porque ele pode ser mostrado atravs de um componente DBImage. O nico truque para mostrar bitmaps como voc quer controlar o tamanho da imagem em relao ao tamanho do componente DBImage. Existem duas escolhas. A primeira, mostrar o bitmap com o tamanho atual configurando a propriedade Strech do DBImage para False. Se o Bitmap for maior que o componente DBImage, voc s poder ver parte da imagem. Isto provavelmente insatisfatrio desde que no exista um caminho para adicionar um scroll bar para o DBImage para permitir que os usurios movam para outras reas da imagem. Resolver o problema em relao a largura e altura fcil se todas as imagens tiverem o mesmo tamanho. Tudo o que voc tem que fazer ter certeza de configurar as propriedades Width e Height do DBImage para estar compatvel em relao a largura e altura dos seus bitmaps em tempo de design. O exemplo tem bitmaps em ambas orientaes portrait e landscape. Para resolver o problema, o mtodo SetImageSize, mostrado na figura 4, foi chamado a partir do evento AfterScroll do ClientDataSet cdsBlob. O DBImage tem uma propriedade Picture do tipo TPicture que uma referncia ao objeto TPicture que guarda o bitmap. O SetImageSize usa as propriedades Picture.Width e Picture.Height do DBImage para determinar se a orientao da imagem portrait ou landscape. Se a orientao for portrait, o mtodo configura a altura do DBImage para a altura do painel que o contm menos dois pixels e calcula a largura do DBImage para preservar a relao entre a largura e a altura. Se a orientao for landscape, o mtodo configura a largura do DBImage para a largura do painel menos dois pixels, e calcula a altura para manter a relao entre a largura e a altura. procedure TfrmBmp.SetImageSize; begin if dbiBmp.Picture.Height > dbiBmp.Picture.Width then begin if dbiBmp.Picture.Height > 0 then begin dbiBmp.Height := pnlBmp.Height - 2; dbiBmp.Width := Trunc(dbiBmp.Height * (dbiBmp.Picture.Width / dbiBmp.Picture.Height)); dbiBmp.Left := (pnlBmp.Width-dbiBmp.Width) div 2; dbiBmp.Top := 1; end; end else if dbiBmp.Picture.Width > 0 then begin dbiBmp.Width := pnlBmp.Width - 2; dbiBmp.Height := Trunc(dbiBmp.Width * (dbiBmp.Picture.Height / dbiBmp.Picture.Width)); dbiBmp.Top := (pnlBmp.Height-dbiBmp.Height)

MeGAZINE

17

DELPHI
div 2; dbiBmp.Left := 1; end; end; Figura 4: O mtodo SetImageSize Para pegar uma imagem que est no DBImage e jog-la para a rea de transferncia, chame a propriedade CopyToClipboard do componente DBImage. Para colar um bitmap da rea de transferencia para um DBImage, chame o mtodo PasteFromClipBoard. Veja na figura 5 cdigo do boto Copy and Paste. procedure TfrmBmp.btnCopyClipboardClick (Sender: TObject); begin dbiBmp.CopyToClipboard; end; procedure TfrmBmp.btnPasteClick(Sender: TObject); begin dbiBmp.PasteFromClipboard; end; Figura 5: Evento OnClick do boto Copy and Paste. Uma das desvantagens do bitmap que neste formato no h compresso, ento os arquivos so muito grandes. Se voc precisar salvar um bitmap para um arquivo e quiser diminuir o seu tamanho, voc pode convert-lo para o formato JPEG. O formato JPEG diminui muito o tamanho do arquivo. Veja na figura 6 o cdigo para salvar a imagem bitmap para jpeg. Este mtodo inicia criando uma instncia da classe TJpegImage. O cdigo converte o bitmap que est sendo mostrado no DBImage chamando o mtodo Assign do objeto JpegImage, e passando a propriedade Bitmap do objeto Picture referenciado pela propriedade Picture do componente DBImage como parmetro. Isto converte o bitmap para jpeg. Depois o mtodo SaveToFile do objeto JPegImage chamado para salvar a imagem para o arquivo BitMap.jpg. Finalmente o objeto JPegImage liberado. Voc pode reduzir a compresso e aumentar a qualidade da imagem jpeg modificando a propriedade CompressionQuality do objeto JpegImage como descrito no help.

Usando Blob em Queries


Para incluir um dado BLOB em uma query INSERT ou UPDATE, voc deve usar um parmetro para dados Blob. A figura 7 mostra o cdigo do evento OnClick do boto Insert Query do form Bitmap. Este cdigo carrega um arquivo bitmap na memria, ento usa uma query INSERT para adicionar um novo registro, que inclui um bitmap na tabela. O mtodo inicia criando um objeto FileStream que abre o arquivo Greenstone.bmp para leitura. Uma varivel string chamada Buff usada para guardar o bitmap na memria. O prximo passo configurar o tamanho do buff para o tamanho do arquivo chamando SetLenght e passando o Buff como primeiro parmetro e BinFile.Size como segundo parmetro. A prxima linha chama o mtodo Read para ler o arquivo inteiro para a string. Note que voc no pode passar a varivel string Buff como primeiro parmetro para o mtodo Read porque este parmetro um ponteiro sem tipo para localizar na memria. Instanciado voc deve passar o primeiro elemento da array string, o qual um ponteiro para o inicio do bloco de memria onde as informaes esto gravadas. procedure TfrmBmp.btnInsertQueryClick(Sender: TObject); var BinFile: TFileStream; Buff: string; begin with dmMain.ibsqlMisc do begin // Cria objeto FileStream BinFile := TFileStream.Create(ExtractFilePath( Application.ExeName) + gFileDir + Greenstone.bmp, fmOpenRead or fmShareDenyWrite); try // aloca memria para o buffer SetLength(Buff, BinFile.Size);

procedure TfrmBmp.btnSaveJpegClick(Sender: TObject); var JpegImage: TJpegImage; begin JpegImage := TJpegImage.Create; try JpegImage.Assign(dbiBmp.Picture.Bitmap); JpegImage.SaveToFile(ExtractFilePath( Application.ExeName) + gFileDir + Bitmap.jpg); finally JpegImage.Free; end; end; Figura 6: Salvando um bitmap para jpeg.

18

MeGAZINE

DELPHI
// carrega arquivo para o buffer BinFile.Read(Buff[1], BinFile.Size); // instrucao SQL para inserir a imagem. dmMain.ibsqlMisc.SQL.Add( INSERT INTO Blobs (Blob_Type, Binary_Data) + VALUES (:BlobType, :BlobData)); dmMain.ibtranMisc.StartTransaction; try // atribui parametros dmMain.ibsqlMisc.Params.ByName( BlobType).AsString := btBmp; dmMain.ibsqlMisc.Params.ByName( BlobData).AsString := Buff; // Executa query. dmMain.ibsqlMisc.ExecQuery; finally dmMain.ibtranMisc.Commit; end; finally BinFile.Free; end; end; dmMain.cdsBlob.Refresh; end; Figura 7: Cdigo do evento OnClick do boto Insert Query. O data module do exemplo contm um componente IBSQL, ibsqlMisc, que usado para inserir um novo registro. A instruo INSERT INTO Blobs (Blob_Type, Binary_Data) VALUES (:BlobType, :BlobData) incluida na propriedade SQL se o componente IBSQL e os valores forem informados para os dois parmetros na instruo SQL. Note que o parmetro BlobData informado usando a sua propriedade AsString da varivel string Buff que contm o bitmap. Finalmente o cdigo comea uma transao, executa a query, d um commit na transao e libera o FileStream. A atualizao de um campo Blob em um registro existente feito exatamente da mesma forma. Isto pode parecer estranho para usar uma varivel string para armazenar o Blob, mas esta nica opo disponvel para os componentes IBSQL e IBDataSet porque seus parametros esto em uma propriedade AsBlob. Se voc est usando componente dataset do BDE ou qualquer outro componente dataset que usem o objeto TParam para parametros, voc ter a opo de usar a propriedade AsBlob. Voc pode usar um PCHAR para armazenar o Blob e informar o PCHAR para o parmetro usando: Query1.ParamByName(BlobData).AsBlob := SomePCharThatContainsTheBlob;

Trabalhando com imagens JPEG


O trabalho com imagens JPEG muito similar ao trabalho com bitmaps, mas existe uma importante diferena. O primeiro destes que o componente DBImage no mostra as imagens JPEG. Ao invs disso voc deve usar um TImage e mover o JPEG do campo da base de dados via programao. Veja o cdigo da figura 8, ele mostra o cdigo do evento OnClick do boto View JPEG e o mtodo LoadImageFromFile que pega a imagem JPEG do campo e mostra no componente image. procedure TfrmJpeg.btnViewClick(Sender: TObject); begin LoadImageFromField (imgJpeg, dmMain.cdsBlobBinary_Data); SetImageSize; end; procedure TfrmJpeg.LoadImageFromField(Image: TImage; ImageField: TBlobField); var MemStrm: TMemoryStream; Jpg: TJPEGImage; begin if ImageField.IsNull then begin Image.Picture.Assign(nil); Exit; end; Jpg := TJPEGImage.Create; try MemStrm := TMemoryStream.Create; try ImageField.SaveToStream(MemStrm); MemStrm.Seek(0, soFromBeginning); with Jpg do begin PixelFormat := jf24Bit; Scale := jsFullSize; Grayscale := False; Performance := jpBestQuality; ProgressiveDisplay := True; ProgressiveEncoding := True; LoadFromStream(MemStrm); end; Image.Picture.Assign(Jpg) finally MemStrm.Free;

MeGAZINE

19

DELPHI
end; finally Jpg.Free; end; end; Figura 8: Mtodo que mostra um JPEG da tabela em um componente Image. O LoadImageFromFile tem dois parametros. O primeiro o componente Image que ser usado para mostrar a imagem JPEG. O segundo o campo BlobField para o campo que contm a imagem JPEG. O mtodo comea checando se o campo tem alguma informao. Se no, ele configura a propriedade Picture do componente Image para nil. Se o campo contm informao, instancias do objeto TJPEGImage e do objeto MemoryStream sero criadas. Depois o mtodo SaveToStream do objeto BlobField chamado para copiar a imagem JPEG do campo para o MemoryStream. O cdigo do bloco with configura as propriedades do objeto JPEGImage e chama o mtodo LoadFromStream para carregar a imagem JPG no objeto JPEGImage do MemoryStream. Usando a rea de transferncia com um componente Image diferente de usar a rea de transferencia com o componente DBImage, como mostrado na figura 9. Visto que o componente Image no tem o mtodo Clipboard, o objeto Clipboard do Delphi usado para copiar uma imagem fora de, ou colar uma imagem dentro, do componente Image. procedure TfrmJpeg.btnCopyClipboardClick(Sender: TObject); begin Clipboard.Open; Clipboard.Assign(imgJpeg.Picture); Clipboard.Close; end; procedure TfrmJpeg.btnPasteClipboardClick(Sender: TObject); begin imgJpeg.Picture.Bitmap.Assign(Clipboard); end; Figura 9: Cdigo dos botes Copy e Past do form JPEG. A figura 10 mostra como converter uma imagem JPEG para um bitmap e salv-lo em um arquivo. Um objeto Bitmap criado e o mtodo Assign chamado para converter o JPEG do componente Image para um bitmap e l-lo no objeto BitMap. Salvar o bitmap para um arquivo realizado chamando o mtodo SavetoFile do objeto BitMap. procedure TfrmJpeg.btnSaveAsBmpClick(Sender: TObject); var BmpImage: TBitmap; begin BmpImage := TBitmap.CREATE; try BmpImage.Assign(imgJpeg.Picture.Graphic); BmpImage.SaveToFile(ExtractFilePath( Application.ExeName) + gFileDir + Jpeg.bmp); finally BmpImage.Free end; end; Figura 10: Converting um JPEG para um bitmap. Veja o cdigo do evento OnClick boto Save BMP to DB mostrado na figura 11. Este cdigo mostra como usar BlobStream para ler uma imagem de qualquer objeto que tenha um mtodo SaveToStream. Este exemplo cria um objeto Bitmap como um bitmap. O mtodo ento insere um novo registro no ClientDataSet determinando um valor para o campo Blob_Type, cria um objeto BlobStream, e chama o mtodo SaveToStream para carregar o bitmap no campo. Finalmente o BlobStream liberado, o registro gravado e o Bitmap liberado. Note que voc deve liberar o BlobStream antes de gravar o registro ou o campo ser nulo. procedure TfrmJpeg.btnSaveBmpToDbClick(Sender: TObject); var BmpImage: TBitmap; Bs: TStream; begin BmpImage := TBitmap.Create; try BmpImage.Assign(imgJpeg.Picture.Graphic); with dmMain.cdsBlob do begin Insert; dmMain.cdsBlobBLOB_TYPE.AsString := btBmp; Bs := CreateBlobStream( dmMain.cdsBlobBinary_Data, bmWrite); try BmpImage.SaveToStream(Bs); finally Bs.Free;

20

MeGAZINE

DELPHI
end; Post; end; finally BmpImage.Free; end; end; Figura 11: Usando o BlobStream para carregar um BLOB dentro do campo da tabela. Neste caso especifico, onde a imagem era um objeto Bitmap, isto seria mais fcil chamar o mtodo Assign do BlobField para pegar o bitmap do campo. De qualquer forma, se o bitmap ou JPEG era um MemoryStream, FileStream ou qualquer outro onde Assign no poderia ser usado, voc precisaria usar um BlobStream: dmMain.cdsBlobBinary_Date.Assign(BmpImage); O cdigo da figura 12 comea criando um BlobStream. Isto feito atravs do mtodo CreateBlobStream e passando o objeto field para o campo como primeiro parmetro. O segundo parmetro o modo: bmRead, bmWrite ou bmReadWrite. Depois um MemoryStream criado e o dado BLOB copiado no MemoryStream chamando o mtodo Copy do MemoryStream. Copy tem dois parmetros, a origem dos dados, neste caso o BlobStream e o numero de bytes para cpia. A propriedade Size do BlobStream passada como o parmetro de tamanho de forma que os contedos inteiros do campo Blob sejam copiados para o MemoStream. O WAV tocado chamando uma funo da API do Windows chamada Playsound. PlaySound passado como parametro para a procedure Win32Check, que checa o valor retornado PlaySound e apresenta uma exceo se o valor retornado indicar um erro. PlaySound d trs parmetros. O primeiro indica a origem do som e pode ser o nome do arquivo, nome de recurso ou ponteiro para localizao da memria onde o som est localizado. Se o primeiro parmetro indicar um recurso, o segundo parmetro o controle do executvel que contm o recurso; de qualquer forma, o segundo parmetro nil. O terceiro parmetro consiste de uma ou mais constantes logicamente ordenadas juntamente para identificar a origem do som e a ao para tomar. Na figura 12, o terceiro parmetro SND_SYNC ou SND_MEMORY para indicar que o primeiro parmetro um ponteiro para a localizao da memria que contm o inicio do som e que a funo PlaySound no deve retornar at que o som tenha terminado. Finalmente, ambos o MemoryStream e BlobStream so liberados. Voc pode tocar um AVI usando o componente MediaPlayer do Delphi; de qualquer forma o MediaPlayer pode s usar dados em arquivos no disco. A figura 13 mostra o cdigo do evento OnClick do form Other. Este mtodo fecha o MediaPlayer, salva o contedo do campo Binary_Data no registro corrente do ClientDataSet para o disco usando o mtodo SavetoFile do objeto BlobField, ento configura a propriedade FileName do MediaPlayer para o arquivo. O usurio pode agora utilizar os botes do componente MediaPlayer para tocar o AVI. procedure TfrmOther.MediaPlayerClick(Sender: TObject; Button: TMPBtnType; var DoDefault: Boolean); begin

Trabalhando com arquivos WAV e AVI


Pegar um arquivo WAV ou AVI numa tabela no diferente do que carregar um JPEG. Use o mtodo Loadfromfile do objeto BlobField. A questo : O que voc faz com os dados uma vez no database ? Voc pode tocar um arquivo WAV usando uma funo da API do Windows chamada PlaySound, mas primeiro voc tem que carregar o WAV na memria. procedure TfrmOther.btnPlaySoundClick(Sender: TObject); var Bs: TStream; Ms: TMemoryStream; begin Bs := dmMain.cdsBlob.CreateBlobStream( dmMain.cdsBlobBinary_Data, bmRead); try Ms := TMemoryStream.Create; try // Copia o WAV para memria Ms.CopyFrom(Bs, Bs.Size); // toca o wav Win32Check(PlaySound(Ms.Memory, 0, SND_SYNC or SND_MEMORY)); finally Ms.Free end; finally Bs.Free end; end; Figura 12: Tocando um som.

MeGAZINE

21

DELPHI
MediaPlayer.Close; dmMain.cdsBlobBinary_Data.SaveToFile(ExtractFilePath( Application.ExeName) + gFileDir + Temp.avi); MediaPlayer.FileName := ExtractFilePath( Application.ExeName) + gFileDir + Temp.avi; MediaPlayer.Open; end; Figura 13: Evento OnClick do MediaPlayer Bs.Free; end; dmMain.cdsBlob.Post; end; Figura 14: Salvando um array para um campo Blob. A figura 15 mostra o cdigo do boto Save Array. Aqui um BlobStream criado e o mtodo Read chamado para ler os dados do campo Blob no array inteiro. procedure TfrmOther.btnShowArrayClick(Sender: TObject); var A: array[1..10] of Integer; Bs: TStream; I: Integer; S: string; begin // no executar se o tipo no for Binary. if dmMain.cdsBlobBlob_Type.AsString <> btBinary then Exit; // grava o registro se no estiver em modo Browse. if dmMain.cdsBlob.State <> dsBrowse then dmMain.cdsBlob.Post; // Cria o BlobStream. Bs := dmMain.cdsBlob.CreateBlobStream( dmMain.cdsBlobBinary_Data, bmRead); try // Carrega os dados a partir do BlobStream para // o Array. I := Bs.Read(A, Bs.Size); finally Bs.Free; end; // Mostra os valores. for I := 1 to 10 do S := S + IntToStr(A[I]) + -; ShowMessage(S); end; Figura 15: Evento OnClick do boto Show Array

Trabalhando com a estrutura da memria


O form Other tambm contm dois botes, Save Array e Show Array. O primeiro salva um array inteiro para o campo Blob e o segundo devolve o array e mostra os seus valores. A figura 14 mostra o cdigo do evento OnClick do boto Save Array. Este mtodo preenche um array com valores de 1 at 10. Se o ClientDataSet est em modo Browse, um novo registro ser inserido. Depois um Blo0062Stream criado para o campo Binary_Data, e o array escrito para o BlobStream chamando o mtodo Write e passando o endereo do array como primeiro parmetro e o tamanho do array como segundo. procedure TfrmOther.btnSaveArrayClick(Sender: TObject); var A: array[1..10] of Integer; I: Integer; Bs: TStream; begin //Preenche o array com valores for I := 1 to 10 do A[I] := I; //Insere um novo registro se o // CDS estiver em modo Browse if dmMain.cdsBlob.State = dsBrowse then begin dmMain.cdsBlob.Insert; dmMain.cdsBlobBlob_Type.AsString := btBinary; end; //Cria um BlobStream. Bs := dmMain.cdsBlob.CreateBlobStream( dmMain.cdsBlobBinary_Data, bmReadWrite); try //Grava o array no BlobStream. Bs.Write(A, SizeOf(A)); finally

22

MeGAZINE

DELPHI
Trabalhando com texto
O Delphi fornece muitos caminhos para facilmente pegar um texto dentro de, ou fora de, um campo memo da tabela. O componente DBMemo torna isto fcil para os usurios incluirem e editarem o texto. Os mtodos LoadFromFile e SaveToFile do objeto BlobField tornam fcil pegar um texto de, ou export-lo para, um arquivo. O contedo do campo memo pode ser designado para uma varivel string e qualquer string Delphi manipula rotinas usadas para modificar o texto. Se voc quer trabalhar com o conteudo do texto do campo memo via cdigo como um array de linhas, determine o campo para a propriedade Text um StringList. O form Text uma aplicao que demonstra os mtodos LoadFromFile e SaveToField do objeto BlobField, e assim como os mtodos CopyToClipboard e PasteFromClipboard do componente DBMemo. De qualquer forma existem algumas caracteristicas que no esto disponveis no DBMemo. Por exemplo, no h como pegar a posio do cursor como um nmero de linha e coluna. A procedure GetMemoLineCol mostrada na figura 16 mostra como fazer isto usando a API do Windows. Esta procedure pega o componente Memo como primeiro parmetro. Note que o parmetro do tipo TCustomMemo assim voc pode passar tambm um Memo ou um DBMemo. O segundo e o terceiro parmetro so parmetros var usados para retornar os numeros de linha e coluna. A procedure comea chamando a funo SendMessage e passando a propriedade Handle do componente Memo como primeiro parmetro. O segundo parmetro a constante EM_LINEFROMCHAR, que fala ao componente Memo que deveria retornar o nmero da linha que contm a posio de um caracter. O terceiro parmetro a propriedade SelStart do componente Memo, que fornece a posio do cursor como um balano entre o inicio do memo. O quarto parmetro no usado. A coluna que o cursor est calculada subtraindo a posio do cursor do inicio da linha, retornado pelo SendMessage usando a constante EM_LINEINDEX constante na posio do cursor contido na propriedade SelStart. Esta procedure chamada pelo mtodo UpdateCursorPos no form Text, que mostra a linha e a coluna corrente no status bar. UpdateCursorPos chamado no evento OnCreate do form e nos eventos OnKeyDown e OnMouseDown do componente DBMemo. // Retorna a posio do cursor no memo. procedure GetMemoLineCol(Memo: TCustomMemo; var MemoLine, MemoCol: Integer); begin with Memo do begin // linha MemoLine := SendMessage(Handle, EM_LINEFROMCHAR, SelStart, 0); // coluna MemoCol := SelStart - SendMessage ( Handle, EM_LINEINDEX, MemoLine, 0) + 1; end; end; Figura 16: A procedure GetMemoLineCol A procedure MemoCursorTo da figura 17 permite voc configurar a posio do cursor para especificar a linha e coluna. Esta procedure posiciona o cursor do componente Memo determinando um valor para a propriedade SelStart. SelStart deve ser especificada como uma posio do inicio do texto. O nmero da linha convertido para a posio chamando SendMessage com a constante EM_LINEINDEX, apenas com a procedure GetMemoLineCol mostrada na figura 14, e adicionando o nmero da coluna menos um para ele. // Manda o cursor para determinada posio no Memo. procedure MemoCursorTo(Memo: TCustomMemo; MemoLine, MemoCol: Integer); begin with Memo do SelStart := SendMessage(Handle, EM_LINEINDEX, MemoLine, 0) + MemoCol - 1; end; Figura 19: A procedure MemoCursorTo.

Concluso
Trabalhando com campos BLOB no Delphi fcil e flexvel, uma vez voc entendendo as ferramentas que esto disponveis e tambm como us-las. Voc pode armazenar qualquer string de bytes em um campo Blob apesar de que os bytes representam. Eles poderiam ser uma foto, um documento do Word, som, um filme, um array ou qualquer coisa que possa ser armazenada em um arquivo binrio no computador. O download do arquivo est disponvel no endereo: http://www.theclub.com.br/revista/Blobs0302.zip

MeGAZINE

23

DELPHI

A Continuidade do Interbase Open-Source


Por Alessandro Ferreira Suporte Tcnico The Club, suporte@theclub.com.br
Ol amigos do The Club, neste artigo iremos falar sobre o Projeto FireBird , mostrar o que , quem est a frente do mesmo e o que ele tem a nos oferecer... XML Generation New JDBC Methods Veja abaixo o preos das licenas do Borland Interbase 6.5 Server Edition Media Kit Server License - 1 user Simultaneous User License - 1 user Simultaneous User License - 10 pack Simultaneous User License - 20 pack U$ 50.00 U$ 200.00 U$ 150.00 U$ 1,200.00 U$ 2,100.00

FireBird

Interbase 6 Open-Source
Como todos sabem, em meados de Janeiro de 2000 a Borland anunciou a abertura do cdigo fonte do RDBMS Interbase, ou seja, o banco agora Open-Source. O nome Interbase at ento, no era to conhecido como os famosos Oracle e Microsoft SQL Server , ouvamos comentrios de que era um excelente banco de dados, porm devido a falta de informao e mesmo marketing a respeito do produto, o mesmo no era muito popular no Brasil, porm sendo utilizado por um nmero at razovel de Empresas e Desenvolvedores. Porm, agora sendo Open-Source imediatamente houve uma grande euforia por parte de ns Programadores, pois cansados dos problemas com tabelas Paradox ou ainda sem dispor de valores razoavelmente altos para licenciar os Bancos disponveis no mercado, o Interbase caiu do cu. Infelizmente a alegria no durou muito tempo! Pouco tempo aps a Borland anunciaria que o projeto Open-Source no teria continuidade e que verses futuras do Interbase necessitariam de licenas de uso, assim como os famosos bancos de dados j conhecidos por ns, apesar de ter um custo at razovel comparado a outros Bancos de seu porte. Recentemente a Borland lanou o Interbase 6.5 onde traz algumas implementaes, tais como: Metadata Security 64 Bit file I/O Asynchronous Cancel SQL Data Manipulation (ROWS clause) New isc_config/ibconfig File Parameters

Para maiores informaes, www.borland.com/interbase

Surge o Projeto FireBird


No demorou muito e a continuidade do Interbase como Open-Source estava novamente garantida por uma nova Empresa encabeada por Ann Harrison (conhecida como a Me do Interbase, participou de seu desenvolvimento desde o incio do produto), chamada IBPhoenix, www.ibphoenix.com, a qual tem como meta levar adiante o Interbase, agora batizado de FireBird!

Como Funciona?
No desenvolvimento Open-Source existe a colaborao de vrios programadores espalhados pelo mundo inteiro interessados no Projeto, os quais do sua colaborao das mais variadas formas tendo a coordenao de Ann Harrison no caso do FireBird. No site do Projeto FireBird voc poder encontrar diversas informaes sobre o desenvolvimento, bem como a lista completa dos Programadores que esto contribuindo com o Projeto. Veja onde o FireBird pode ser encontrado TOTALMENTE freeware: www.theclub.com.br

24

MeGAZINE

DELPHI
www.ibphoenix.com www.firebirdsql.org http://firebird.sourceforge.net ( /* seus campos */ );

Como anda o FireBird atualmente?


Recentemente (12/03/2002) foi lanada a verso 1.0.0, ou seja, a primeira verso final do FireBird aps os Release Candidates. Muitos Bugs e implementaes j foram feitas e segundo testes o FireBird tem demonstrado bastante estabilidade e segurana! Abaixo vamos descrever algumas das implementaes e novos recursos que o FB recebeu at agora. Quebrando a barreira dos 2GBs por GDB No h mais limitao no tamanho dos arquivos GDBs, eles podero chegar at onde o sistema operacional permitir. Page Size at 16k Muito importante para o Tunning no banco de dados, conforme mostra nosso artigo de Dezembro/2001 Performance no Interbase, sendo possvel agora chegar at 16K. Suporte a arquivos de 64bits O engine do FB agora compatvel com sistemas de 64bits, em resumo lhe possibilitar quebrar a barreira dos 2GBs por arquivo, desde que o SO tenha suporte a arquivos maiores que 2 e 4GB. Forced Writes recebe ON como padro em ambiente WIN32 At o Interbase 6.0 o default para Forced Writes era OFF, agora no FireBird vem como ON para qualquer novo banco de dados, o que ir auxiliar em questes de performance e integridade dos dados. Porta 3050 como default Tanto o Client, como o Server utilizam agora a porta 3050 como default. Definir a localizao de arquivos externos atravs do IBCONFIG Agora, em plataforma Windows, voc poder definir no arquivo IBCONFIG a varivel EXTERNAL_FILE_DIRECTORY, como mostra o exemplo abaixo: EXTERNAL_FILE_DIRECTORY D:\FB_Ext Com isso, na criao de uma tabela externa no ser preciso definir o path do arquivo e sim somente o nome do mesmo, como por exemplo: CREATE TABLE CADLOG EXTERNAL FILE log.txt

Implementaes na Linguagem SQL


Select First M skip N Agora no necessrio utilizar uma Stored Procedure para simular o SELECT TOP do Microsoft SQL Server ou a limitao feita atravs do RowNum no Oracle . Com o Select FIRST / SKIP voc conseguir obter os primeiros m registros retornados pela instruo SELECT. A clusula SKIP no obrigatria e pode ser utilizada sem ou com a clusula FIRST! Ela pula os n primeiros registros retornando a consulta a partir de n + 1. Veja alguns exemplos: SELECT SKIP 5 FROM CLIENTES; /* Retornar todos os registros da tabela CLIENTES a partir do 6 registro ou seja pulando os 5 primeiros */ SELECT FIRST 10 FROM CLIENTES; /* Retornar os 10 primeiros registros da tabela CLIENTES */ SELECT FIRST 10 SKIP 5 FROM CLIENTES; /* Retornar os 10 primeiros registros a partir do 6 registro */ RECREATE TABLE e RECREATE PROCEDURE Essa veio para quebrar um galho! Estas duas novas instrues permitem que voc crie uma tabela ou procedure existente sem ter que remov-la antes. A sintaxe utilizada a mesma do CREATE TABLE e CREATE PROCEDURE. UDF agora pode retornar/receber NULL Agora no FireBird possvel retornar e passar nulos para UDFs, coisa que no era possvel com UDFs no InterBase. Convero de String->Blob em INSERT e UPDATE Novo identificador de comentrio, Semelhante ao Microsoft SQL Server , o aceito como comentrio FireBird, RDBMS Open-Source de Verdade! GROUP BY com UDFs No GROUP BY, agora poder ser feita a utilizao de funes definidas pelo usurio ou seja as UDFs. Veja um simples exemplo a seguir:

MeGAZINE

25

DELPHI
SELECT RTRIM(NOME), COUNT(*) AS TOTAL FROM CLIENTES GROUP BY RTRIM(NOME); Onde est a funo SUBSTRING que at o Paradox aceita? At o Interbase 6, era necessrio registrar a funo SUBSTR() para fazer a vez do SUBSTRING() to conhecida pelos usurios do Paradox. Porm agora no FireBird ela vem nativa na linguagem SQL no sendo necessrio registrar nenhuma UDF para isso. SELECT SUBSTRING(NOME FROM 1 FOR 10) FROM CLIENTES; Instruo DROP GENERATOR At a verso 6 do Interbase tnhamos que remover um Generator no brao fazendo um DELETE na tabela de sistema RDB$GENERATORS, porm agora possvel via DDL. DROP GENERATOR GEN_ID_CLIENTES; PLANONLY Permite verificar o PLAN escolhido pelo Banco sem que a Query seja executada. Veja mais informaes sobre PLAN em nossa revista de Dezembro/2001 Performance no Interbase. Nova biblioteca de funes de usurio (UDF) O FireBird agora tem uma nova UDF de funes que est contida na FBUDF.DLL e traz vrias funes interessantes. Apesar de ter esta nova biblioteca de funes, a conhecida IB_UDF.DLL (que acompanha o Interbase 6) suportada sem problemas. O que foi corrigido at agora? As implementaes e novidades no seriam completas se no houvesse melhorias no contexto geral do Banco de Dados que infelizmente no est livre de Bugs. At o momento diversos Bugs foram corrigidos e vrios outros detectados e que certamente sero corrigidos em Releases futuros! No site do Projeto FireBird voc poder encontrar documentao completa do que foi corrigido at o momento e o que ainda est para ser corrigido. Meu GDB do Interbase 6 compatvel com o FireBird? Felizmente SIM! Ser necessrio apenas um Backup / Restore para fazer a migrao para o FireBird. Isso poder ser feito via linha de comando atravs do GBAK, vamos a instruo: Ainda no Interbase 6: gbak t seu_banco.gdb seu_banco.gbk user sysdba password masterkey Agora no FireBird 1.00: gbak r p <tam_pag> c:\seu_banco.gbk c:\seu_banco.gdb user sysdba password masterkey Se preferir poder utilizar o IBConsole para fazer o Backup / Restore. Por que devo fazer a migrao? Voc no obrigado fazer a migrao e se preferir poder continuar utilizando o Interbase 6.01 sem problema nenhum! Porm sabemos que por parte da Borland no haver nenhuma implementao ou correo de Bugs no Interbase 6.01 e que se desejar isso dever adquirir licenas do Interbase 6.5 que como j mencionamos no FREEWARE, ao passo que no FireBird voc ter um RDBMS totalmente FREE e com a certeza da continuidade do cdigo fonte aberto ou seja Open-Source, com implementaes, correes de Bugs e a sua participao em tudo isso se desejar! Porm, voc no precisa se desesperar para fazer a migrao. Se seu aplicativo est rodando sem problemas, voc poder com o tempo ir portando seu banco para o FireBird se preferir ou deixla como est. Quanto Instalei o FB no encontrei o IBConsole Bom, o IBConsole na realidade uma entre diversas ferramentas de administrao existentes no mercado. Ela, porm pertence ao Interbase 6 e pelo que pude ver at o momento no acompanha o FiredBird, porm isso no problema! Veja abaixo uma relao de ferramentas que poder utilizar: IBAccess www.ibaccess.org ou http://sourgeforge.net OpenSource/FREE IBExpert www.ibexpert.com Trial QuickDesk www.ems-hightech.com Trial IBworkbench http://www.interbaseworkbench.com/ Trial No endereo http://www.ibphoenix.com/ ibp_contrib_download.html#ADMIN poder ver mais ferramentas para administrao do Interbase e FireBird. Fique atento as novidades sobre o FireBird nos sites do Projeto e aqui na The Club Megazine, pois com certeza, vem mais coisa por ai, at a prxima.

26

MeGAZINE

DELPHI

Eventos
Anderson Haertel Rodrigues
Em linguagens de programao orientada a Objeto, temos a liberdade de criar nossas prprias Classes, nossos prprios Objetos, nossos prprios Componentes, usamos, Herana, Encapsulamento, Polimorfismo, etc, etc, etc.. Podemos tambm criar nossos prprios eventos, isto mesmo, criar nossos mtodos baseados na classe TNotifyEvent e ou ainda, criar novos eventos com parmetros prprios usando ponteiros de mtodos. Na realidade TNotifyEvent tambm um ponteiro de mtodo , declarado na unit: Classes.pas Mas, na realidade, o que um Evento? Evento a capacidade do componente em reagir a algo em que o usurio solicitou. Algo como: A) O Clique do Mouse; B) DragDrop; C) Uma tecla pressionada D) Etc. ... end; Note que temos duas partes na declarao de um evento. Primeiro, um evento requer uma varivel de dados interna, onde nesta varivel que fica armazenado o ponteiro de mtodo, e segunda, criado uma propriedade para permitir ao desenvolvedor criar o Handler de Evento em tempo de projeto.

Handlers de Eventos
So mtodos que geralmente se encontram no formulrio onde se encontra o componente que gerou o evento. O Handler de evento criado quando o usurio seleciona o Object Inspector do Delphi e escreve o mtodo associado ao Evento. Um exemplo seria o evento OnClose do Formulrio.

Eventos Padro
Todos os componentes descendentes da classe TControl herdam um conjunnto de eventos padro e, todos os componentes descendentes da classe TwinControl herdam um conjunto de eventos para controle de janelas.

Estrutura de um Evento
type TControl = Class(TComponent); private FOnClick: TNotifyEvent; FOnMouseDown: TMouseEvent; protected property OnClick : TnotifyEvent read FOnClick write FOnClick; ... property OnMouseDown: TMouseEvent read FOnMouseDown write FOnMouseDown public published

Despacho de Eventos padro


A VCL do Delphi, possui vrios eventos padro j prdefinidos. Temos quase todos os eventos que necessitamos para trabalhar com os eventos do Delphi j criados pelos projetistas da Borland. Se necessitarmos sobrepor algum evento padro do Delphi, devemos sobrepor o mtodo associado a este evento na sua Classe Pai. Exemplo: Se necessitarmos sobrepor o evento OnClick de um TButton, devemos proceder da seguinte forma: type ... TButtonNew = Class(Tbutton);

MeGAZINE

27

DELPHI
protected procedure Click; Override; end; procedure TButtonNew.Click; begin inherited Click; { Definio do cdigo. } end; utilizamos a mesma palavra reservada do Delphi para criao de propriedades property. Leia novamente Visualizao de eventos no Object Inspector se voc tiver dvidas de como o Delphi sabe diferenciar propriedades de eventos.

Nosso evento em funcionamento


Para fazer funcionar o nosso evento, devemos notifica-lo que houve o evento: ... if Assigned(FOnIncluiu) FOnIncluiu(Self);

Visualizao de eventos no Object Inspector


Antes de realmente comearmos a criar nossos eventos, quero explicar como o Delphi sabe quais as propriedades sero exibidas na Aba Properties e quais so exibidas na Aba Events. O Object Inspector usa informaes de tempo de execuo armazenadas para cada propriedade, onde, somente as propriedades que so do tipo de ponteiro de mtodos aparecem na Aba Events. Neste processo de tempo de execuo usada a famosa RTTI do Delphi.

then

Ok. No tem mistrios para a chamada do mesmo. Atento para o fato de que o resto do cdigo no necessrio, podendo ser utilizado em vrias situaes. Explicando o cdigo acima: A funo Assigned usada para verificar se o mtodo de despacho est apontando para algo, neste caso, um ponteiro de mtodo. A funo Assigned() no usada apenas para ponteiros de mtodos, pode ser usada para qualquer tipo de ponteiro. Self, o objeto atual. Neste caso, pode ser um: TDataSet, TDBGrid... enfim, vai de acordo com a sua necessidade.

A criao de Eventos
S existem duas formas para criarmos eventos. A) Criarmos eventos descendentes direto de TNotifyEvent; B) Criarmos o nosso prprio tipo de evento, com parmetros personalizados;

Criando Eventos personalizados


Para criarmos eventos personalizados, devemos ter em mente as seguintes situaes: A) Determinar quais as aes que ativaram nosso evento; B) Declarar a propriedade; C) Definir o(s) tipo(s) de mtodo(s); D) O Despacho do Evento; Vamos criar um evento que est relacionado a tecla NumLock do nosso teclado. Podemos ter um componente Panel e ou StatusBar e desejar mostrar ao usurio quando o mesmo acionou a tecla NumLock type TNumLockStatus = Class(Tpanel); TNumLockEvent = procedure(Sender: TObject; NumLockOn: Boolean) of Object; private .., FOnNumLock: TNumLockEvent;

Criando Eventos Padro


private { Private declarations } ... FOnIncluiu: TNotifyEvent Procedure SetOnInlcluiu (const Value: TNotifyEvent); public { Public declarations } ... property OnIncluiu: TNotifyEvent read FOnIncluiu write SetOnIncluiu; procedure Tform1.SetOnIncluiu (conta value: TNotifyEvent); begin FOnIncluiu := Value; end; Pronto! Criamos o nosso evento padro. Para criao de eventos,

28

MeGAZINE

DELPHI
begin protected procedure NumLock; published property OnNumLock: TNumLock read FOnNumLock write FOnNumLock; end; O que devemos fazer agora, criarmos o mtodo de despacho personalizado para o evento: procedure TNumLockStatus.NumLock; end; if Assigned(FNumLock) then FNumLock(Self, IsNumLock) ;

Concluso:
Neste artigo, mostro como criar eventos padro e personalizados para seus componentes. Mostrei o conceito de um evento, onde usa-lo e como criar eventos. A criao de eventos , um poderoso recurso que a linguagem Delphi nos oferece. Sucesso a todos e at a prxima, Anderson Haertel Rodrigues - AHR.

MeGAZINE

29

DICAS & TRUQUES

Dicas & Truques


Executar Procedure/Mtodo Genricamente
Nesta dica, mostraremos como executar uma procedure existente em vrios Forms de uma aplicao genericamente apenas atravs do nome da procedure. Por exemplo, o FormA possui a procedure FazNada e o FormB tambm possui uma procedure chamada FazNada, veja o cdigo: // tipagem para executar a procedure. type TProc = procedure(Obj: TObject; s: string); var Form1: TForm1; implementation {$R *.DFM} implementation // No Form2 tambm existe uma procedure com o // mesmo nome e parmetros. procedure TForm1.FazNada(s: String); begin ShowMessage(Faz Nada no + s); end; procedure TForm1.Button1Click(Sender: TObject); var MyProc: TProc; i: integer; begin // percorre os Forms pesquisando a Procedure. for i := 0 to Screen.FormCount - 1 do begin MyProc := Screen.Forms[i].MethodAddress(FazNada); // se encontrou, executa. if Assigned(MyProc) then MyProc(Screen.Forms[i], Screen.Forms[i].Name); end; end; end. uses TypInfo; {$R *.DFM} procedure TForm1.Button1Click(Sender: TObject); var i: integer; begin for i := 0 to Screen.FormCount - 1 do MUnits.Lines.Add(GetTypeData (Screen.Forms[i].ClassInfo)^.UnitName + {+Screen.Forms[i].Name+}); end; end. Neste exemplo utilizamos um componente TMemo com o nome de MUnits e um TButton. O projeto de exemplo referente esta dica est disponvel para download em www.theclub.com.br/revista/unitsname.zip. Essa dica interessante para a execuo de mtodos onde temos apenas o nome do mesmo contido em uma String, por exemplo. O projeto de exemplo referente esta dica est disponvel para download em www.theclub.com.br/revista/ExecutaProc.zip.

Nome das Units do Projeto em Run-Time


Neste exemplo mostramos como retornar o nome das units de um Projeto em Run-Time utilizando RTTI (Run-Time Type Information), porm isso s possvel mediante os Forms criados em memria. var Form1: TForm1;

30

MeGAZINE