Sei sulla pagina 1di 43

Esse artigo faz parte da revista Clube Delphi Edio 60.

Clique aqui para ler todos os artigos desta edio

60 Dicas e Solues em Delphi!


Para comemorar a edio 60 da ClubeDelphi, reunimos neste super artigo nada mais nada menos que 60 dicas para incrementar suas aplicaes Delphi. So segredos, curiosidades, FAQs e exemplos de utilizao das principais tecnologias relacionadas ao Delphi: ClientDataSet, dbExpress, BDP, ADO.NET, ASP.NET, Indy, DBGrid, InterBase/Firebird, Quick Report e muito mais! Com certeza voc encontrar dicas valiosas para adaptar em suas aplicaes! Todos os exemplos e cdigos tambm podem ser encontrados para download no endereo deste artigo. As dicas foram construdas por Guinther Pauli (GP), Luciano Pimenta (LP) e Carlos Cantu (CC).

1. Capturando a imagem da tela (screen-shot) e salvando-a para um arquivo GP - A rotina mostrada na Listagem 1 captura a imagem do desktop, retornando um objeto do tipo TBitmap. A partir dele, possvel salvar a imagem para um arquivo ou apresentar o resultado em um formulrio, atravs de um componente Image. Por exemplo, use esse recurso para criar um relatrio de erros, que salve o estado atual da tela do usurio quando uma exceo no tratada ocorrer (uma dica enviar a imagem por e-mail para o desenvolvedor responsvel).

Listagem 1. Capturando a imagem da tela function CapturaTela: TBitmap; var dc:hdc; cv:TCanvas; begin result := TBitmap.Create; result.Width := Screen.Width; result.Height := Screen.Height; dc := GetDc(0); cv := TCanvas.Create; cv.Handle := DC; result.Canvas.CopyRect(Rect( 0, 0,Screen.Width,Screen.Height), cv,Rect(0,0,Screen.Width, Screen.Height)); cv.Free; ReleaseDC (0, DC); end; { Exemplos de utilizao } { Captura a tela e salva para o disco } CapturaTela.SaveToFile('tela.bmp'); { Exibe a tela em um componente Image } Image1.Picture.Assign(CapturaTela);

2. Capturando a imagem da tela (screen-shot) de uma mquina da rede

GP - Esse recurso bastante utilizado por aplicaes estilo trojan, permitindo que o intruso possa observar o que a pessoa na outra mquina est fazendo. Deixando o hackerismo de lado, um exemplo prtico da tcnica monitorar remotamente a ao de usurios na sua aplicao. Por exemplo, muito comum utilizar esse recurso em programas que controlam lan-houses, ou aplicaes estilo PcAnywhere ou Terminal Services. A idia simples, construmos duas aplicaes que trocam imagens atravs de sockets, usando streams. O primeiro passo construir a aplicao servidora, que deve ficar em execuo em todas as mquinas a serem monitoradas. Em uma nova aplicao VCL, coloque no formulrio umIdTCPServer da Indy. Configure seu DefaultPort para 8090 e Active para True. No seu eventoOnExecute digite o cdigo da Listagem 2. Observe que fazemos uso da rotina CapturaTela, mostrada no exemplo anterior. Na aplicao cliente, coloque um IdTCPClient da Indy e defina a propriedade Port como 8090. Coloque um Image, um Edit e um Button. No evento OnClick doButton digite o cdigo da Listagem 3. Voc pode colocar um Timer e chamar o mesmo cdigo, se quiser que a imagem seja atualizada constantemente. Ao clicar no boto, a imagem mostrar a tela do computador indicado no Edit (digite o endereo IP ou o nome da mquina).

Listagem 2. Servidor captura tela da mquina e envia pela rede procedure TForm1.IdTCPServerExecute( AThread: TIdPeerThread); var Stm : TStream; Tela: TBitmap; cmd: string; fn: string; r: integer; begin randomize; r := Random(MaxInt); fn := Format('tela%d.bmp',[r]); cmd := AThread.Connection.ReadLn;

if pos('TELA',cmd) > 0 then begin Tela := CapturaTela; Tela.SaveToFile(fn); Tela.Free; Stm := TFileStream.Create(fn, fmOpenRead + fmShareDenyNone); AThread.Connection.OpenWriteBuffer; AThread.Connection.WriteStream(Stm); AThread.Connection.CloseWriteBuffer; FreeAndNil(Stm); end; AThread.Connection.Disconnect; end;

Listagem 3. Aplicao monitora terminais remotamente procedure TForm1.Button1Click(Sender: TObject); var Stm: TStream; begin IdTCPClient1.Host := Edit1.Text; IdTCPClient1.Connect; WriteLn('TELA'); Stm := TFileStream.Create('tela.bmp',fmCreate); try while IdTCPClient1.Connected do

IdTCPClient1.ReadStream(Stm,-1,true); except end; FreeAndNil(Stm); Image1.Picture.LoadFromFile('tela.bmp'); end;

3. Obtendo dados da Web a partir de uma aplicao Delphi GP - Hoje em dia, muito comum sua aplicao precisar de informaes ou utilizar servios disponibilizados por outra aplicao. No para menos que surgiram os Web Services. Com essa tecnologia, podemos incluir em nossas aplicaes servios oferecidos por outras empresas. Por exemplo, voc pode ter um sistema de controle de estoque que, dada a falta de um determinado produto, conecta-se automaticamente aos fornecedores atravs de Web Services e pesquisa pela disponibilidade do produto, pelo melhor preo e j faz a encomenda automaticamente. Porm, a realidade nos mostra que, muitos servios na Web esto somente disponveis para acesso via browser. Ou seja, para usar o servio, preciso abrir um browser, conectar no site da empresa e usar seu servio (exemplos: envio de mensagem para celular, consulta lista telefnica, consulta ao CPF etc.). Uma sada fazer a requisio no brao. justamente o que mostrarei aqui. A idia simples: montamos uma requisio HTTP (como se nossa aplicao fosse um browser), enviamos a solicitao ao site desejado, obtemos a pgina de retorno e fazemos o parse do HTML a procura da informao desejada. Vamos a um exemplo simples: em uma nova aplicao, coloque um IdHTTP, um Label e um Button. No evento OnClickdo Button digite:

var s: string; begin s := IdHTTP1.Get('http://br.invertia.com'); Label1.Caption := copy(s,pos('Compra',s) + 115,7); end;

O cdigo anterior mostra em um Label a cotao on-line do dlar, obtida atravs da consulta HTTP ao site indicado no cdigo. Recebido o retorno, procuramos por uma palavra-chave no HTML (de preferncia que seja sempre fixa) e fazemos a captura do valor pela posio relativa.

4. Preenchendo formulrios de Web Sites programaticamente GP - No exemplo anterior, recuperamos uma pgina da Web apenas indicando a URL. Muitas vezes, no entanto, o contedo de retorno depende da passagem de parmetros ou do preenchimento de campos de um formulrio. Vou dar um exemplo: o site de pesquisa Googlepossui uma opo para traduo (ferramentas de idiomas). Antes de obter a pgina com a traduo de uma palavra/texto, precisamos passar o valor do campo desejado na requisio HTTP. exatamente isso que fiz no cdigo da Listagem 4. Nele, o texto em ingls digitado em um Memo traduzido para o portugus. Observe que o parse feito de forma totalmente manual. Imagine o leque de opes que voc ter agora, sabendo como utilizar esse recurso. Poder integrar sua aplicao a uma gama enorme de servios disponibilizados na Web, mesmo que no sejam oferecidos via Web Services.

Listagem 4. Preenchendo formulrios Web programaticamente procedure TForm1.Button2Click(Sender: TObject); var s: string; Fields: TStrings; p: integer; begin Fields := TStringList.Create; Fields.Add('text=' + memo1.lines.Text); Fields.Add('langpair=en|pt'); s := IdHTTP1.Post(

'http://translate.google.com/translate_t',Fields); p := pos('PHYSICAL',s) + 9; Memo1.lines.Clear; while s[p] <> '<' do begin Memo1.lines.Text := Memo1.lines.Text + (s[p]); p := p + 1; end; Fields.Free; end;

Nota: O preenchimento automtico de formulrios Web e a postagem de requisies HTTP via programao algo que pode prejudicar os servios disponibilizados por empresas. muito simples, por exemplo, criar um programa que fique cadastrando usurios em um site (enchendo o BD de lixo), ou fazendo propaganda em chats, ou fazendo spam para celular, usando as tcnicas aqui demonstradas. Dessa forma, web sites utilizam vrias tcnicas para impedir a ao de programas automticos: validao via cookies, sesso, IP ou ainda pedindo para que o usurio digite um texto exibido em uma imagem, que em teoria no pode ser lido atravs de programao.

5. Descobrindo quando uma pgina da Web foi atualizada GP - Nos exemplos anteriores, vimos como usar o componente IdHTTP para acessar pginas Web e preencher formulrios. Podemos usar o mesmo componente para monitorar uma determinada pgina, enviando solicitaes a cada n segundos. Guardamos o valor retornado na primeira requisio e para as subseqentes, comparamos o novo valor de retorno com o valor original. Se forem diferentes, a pgina foi atualizada. O cdigo da Listagem 5 mostra os manipuladores para os eventos OnClick de um Button e OnTimer de um Timer (esse ltimo deve iniciar com Enabled = False). A aplicao monitora a pgina da Borland e avisa quando a mesma for atualizada.

Listagem 5. Monitorando quando uma pgina foi atualizada procedure TForm1.Button1Click(Sender: TObject); begin { Declare uma varivel p do tipo string, na seo public do formulrio } p := IdHTTP1.Get('www.borland.com'); Timer1.Enabled := True; end;

procedure TForm1.Timer1Timer(Sender: TObject); begin if IdHTTP1.Get('www.borland.com') <> p then ShowMessage('A pgina foi atualizada'); end;

6. Aplicao com atualizao automtica via Web GP - Voc j deve ter visto em alguns aplicativos, como o ICQ, MSN e WinAmp, que ao serem executados, exibem uma mensagem indicando que existe uma verso mais nova do aplicativo disponvel para download. Ao confirmar a opo, o programa atualizado automaticamente em sua mquina. possvel fazer o mesmo para suas aplicaes Delphi. O primeiro passo hospedar o executvel em um diretrio de um servidor FTP. A seguir, criamos uma aplicao de abertura (chamei deLaunch) que se encarrega de iniciar a aplicao propriamente dita, fazendo antes a verificao de atualizao. Na aplicao principal, podemos incluir cdigo de verificao para garantir que a mesma seja sempre executada atravs do Launch. A Listagem 6 mostra o cdigo colocado no evento OnCreate do formulrio principal da aplicaoLaunch. Usamos um componente IdFTP da Indy para conectar ao servidor FTP onde o arquivo atualizado est hospedado (nesse caso usei minha prpria mquina local). Comparamos ento a data do arquivo remoto com a data do arquivo executvel local e, caso forem diferentes, fazemos o download da nova

verso da aplicao e a executamos. Para facilitar, o cdigo levou em conta que apenas um arquivo consta no diretrio do servidor FTP.

Listagem 6. Aplicao com atualizao automtica baixa nova verso da Web ao ser iniciada procedure TForm1.FormCreate(Sender: TObject); const fn = 'Project1.exe'; begin IdFTP1.Host := 'localhost'; IdFTP1.Username := 'anonymous'; IdFTP1.Connect; IdFTP1.List(nil); if FormatDateTime('dd/mm/yyyy HH:mm', FileDateToDateTime(FileAge(fn))) <> FormatDateTime('dd/mm/yyyy HH:mm', IdFTP1.DirectoryListing.Items[0].ModifiedDate) then if MessageDlg('Existe uma nova verso dessa ' + 'aplicao disponvel na web, deseja atualizar?', mtconfirmation,[mbok,mbcancel],0) = mrOk then begin IdFTP1.Get(fn,fn,True); FileSetDate(fn,DateTimeToFileDate( IdFTP1.DirectoryListing.Items[0].ModifiedDate)); end; IdFTP1.Disconnect; WinExec(fn,SW_SHOWNORMAL); Application.Terminate;

end;

7. Enviando mensagens para ICQ e MSN GP - Existe um Web Service que permite o envio de mensagens para o ICQ, MSN, AIM e Yahoo. Para us-lo, em uma nova aplicao VCL, clique em File|New>Other e no item WebServicesescolha WSDL Importer. A seguir digite http://www.bindingpoint.com/ws/imalert/imalert.asmx?wsdl e clique em Finish. Ser criada uma unit com o cdigo para acesso ao Web Service. Agora basta declarar imalert na clusula uses do formulrio que usar o servio e chamar as respectivas rotinas de envio. Por exemplo, o seguinte cdigo envia uma mensagem para o ICQ indicado no terceiro parmetro do mtodo:

GetInstantMessageAlertSoap.SendICQ( '','guinther','11997259 5','Testando...');

O uso desse Web Service interessante para automatizar processos de notificao de sua aplicao de negcio. Por exemplo, voc pode notificar por ICQ e MSN um determinado aluno de uma universidade quando o livro que ele retirou na biblioteca precisar ser devolvido. Tudo de forma automtica e feita pelo prprio sistema.

8. Depurando o cdigo-fonte da VCL GP - Quando executamos uma aplicao e comeamos a depurar determinado trecho de cdigo de forma passo a passo, muito comum acionar o Trace Into (F7). No entanto, voc deve notar que isso no funciona para mtodos e rotinas da VCL (um ApplyUpdates de um ClientDataSet, por exemplo), o Delphi ignora o Trace Into e passa para a linha seguinte. Em muitas situaes, necessrio depurar os fontes da VCL para ver exatamente como o Delphi responde chamada de determinado mtodo, vendo o que acontece nos bastidores. Uma forma simples de resolver o problema abrir as opes do projeto (Project|Options) e na aba Compilermarcar a opo Use Debug DCUs.

9. Usando SavePoints do ClientDataSet para simular um Undo

GP O ClientDataSet possui um interessante recurso que permite desfazer apenas uma parte de alteraes feitas em um determinado registro. Isso funciona de forma semelhante s transaes em um BD. Voc pode iniciar uma transao, efetuar todas as operaes necessrias (incluses, alteraes etc.) e, caso deseje, voltar ao estado anterior. Isso pode ser feito atravs da utilizao dos mtodos SavePoint e UndoLastChanges do ClientDataSet. O SavePoint tira uma fotografia do Data (os dados) do ClientDataSet, que pode ser reativada a qualquer momento. Podemos chamar vrias vezes o SavePoint, o ClientDataSet capaz de armazenar vrios estados internamente. Uma aplicao interessante que fiz desse recurso para simular em um formulrio de cadastro o famoso Undo dos editores de texto. fcil: crie um nico manipulador para todos os eventosOnExit dos controles Data-Aware da tela, chamando o mtodo ClientDataSet1.SavePoint. Coloque um PopupMenu no formulrio e adicione nele um item, dando o Shortcut de Alt+BkSp . No seu evento OnClick chame o mtodo ClientDataSet1.UndoLastChange(false). Aponte a propriedadePopupMenu do formulrio para o PopupMenu1 e execute a aplicao. Faa algumas alteraes nos campos do formulrio e pressione vrias vezes Alt+BkSp. Observe o efeito do Undo para cada campo.

10.

Monitorando atualizaes no dbExpress

GP - Em aplicaes dbExpress, o DataSetProvider o componente responsvel por gerar as instrues de atualizao (Delete, Insert e Update). Se voc quiser manipular esses comandos, precisar usar o evento BeforeUpdateRecord do DataSetProvider. No entanto, se apenas quiser visualizar os comandos gerados, basta utilizar o componente SQLMonitor. A maneira mais simples de configur-lo apontando sua propriedade SQLConnection para a conexo, AutoSave e Activepara True e indicando um arquivo na propriedade FileName, onde sero gerados os logs.

11.

Destacando automaticamente os campos obrigatrios em uma

tela de cadastro GP - Com certeza voc j deve, pelo menos uma vez na vida, ter preenchido um formulrio de cadastro na Web. Deve ter reparado tambm que, na maioria deles, quando clicamos no boto Enviar, uma validao feita e os campos requeridos (e no preenchidos) so destacados de alguma forma. Por exemplo, colocando-se o texto do campo em negrito e vermelho.

A rotina que criei na Listagem 7 permite simular esse comportamento em uma aplicao VCL. Para ela funcionar corretamente, preciso que voc configure no seu DataSet a propriedadeRequired dos campos TFields obrigatrios, definindo como True. Para que a Label do respectivo campo obrigatrio possa ser destacada, preciso que ela esteja apontando para o controleData-Aware atravs da propriedade FocusControl. Agora, basta fazer o teste no boto que grava os dados. Veja um exemplo de chamada da rotina no final da Listagem 7.

Listagem 7. Rotina para validar formulrios destaca campos no preenhidos function Valida(F: TForm): boolean; var i: integer; lbl: TLabel; ds: TDataSource; fn: string; c: TObject; begin for i := 0 to F.ComponentCount - 1 do begin if F.Components[i] is TLabel then lbl := F.Components[i] as TLabel; lbl.Font.color := clWindowText; lbl.Font.Style := []; if lbl.FocusControl <> nil then begin c := lbl.FocusControl; { Declare TypInfo no uses } if IsPublishedProp(c,'DataSource') then begin

ds := TDataSource(GetObjectProp(c,'DataSource')); if IsPublishedProp(c,'DataField') then begin fn := GetStrProp(c,'DataField'); if ds.DataSet.FieldByName(fn).Required then if ds.DataSet.FieldByName(fn).IsNull then begin lbl.Font.Style := [fsbold]; lbl.Font.color := clred; end; end; end; end; end; end; { Exemplo de utilizao da rotina } if not Valida(Form1) then ...

A rotina varre todos os componentes do formulrio, procurando por TLabels. Se encontrar, tenta obter uma referncia para o controle Data-Aware usando a propriedade FocusControl. A seguir, tentamos acessar as propriedades DataSource e DataField do controle para verificar se o campo est preenchido no DataSet. Aqui temos um grande problema: na VCL, os controles Data-Awareno possuem uma classe base que defina essas propriedades (o pessoal da Borland podia pelo menos ter colocado uma interface). Nesse caso, precisamos usar RTTI para obter o valor das propriedades a partir do nome, atravs das funes GetObjectProp e GetStrProp. Isso nos poupa de fazer um if para cada tipo de controle. Encontrado o TField, testamos se requerido (Required), se foi preenchido (IsNull) e de acordo com o resultado, destacamos a Label do controle.

12.

Usando diretivas condicionais de compilao

GP O Delphi permite que o desenvolvedor crie suas prprias diretivas condicionais de compilao. Por exemplo, imagine uma unit chamada Global.pas que contm rotinas gerais utilizadas pela empresa. Essa unit est includa em vrios projetos, entre eles um projeto VCL e um projeto Web. Se por algum motivo um determinado trecho de cdigo precisar ter um comportamento diferente quando compilado para Web, podemos incluir um teste condicional semelhante ao mostrado na Listagem 8. A seguir, no projeto que usa a unit, acesse o menuProject|Options e na aba Directories/Conditionals defina a diretiva na opo Conditional Defines(ex. WEB). No outro projeto, faa o mesmo, definido a diretiva VCL.

Listagem 8. Usando diretivas condicionais function GetTestValue: string; begin {$IFDEF WEB}Result := 'Estou na Web!';{$ENDIF} {$IFDEF VCL}Result := 'Estou na VCL!';{$ENDIF} end;

Outra situao tpica onde diretivas condicionais podem ser usadas: voc tem um formulrio base que usado por vrios projetos (Financeiro, Acadmico, Vestibular etc.). Porm, por algum motivo, foi necessrio fazer uma gambiarra e incluir no formulrio base um cdigo especfico do sistema Financeiro, cdigo que no poderia ser enxergado pelos outros mdulos. Isso pode ser facilmente resolvido com diretivas: envolva o cdigo especfico em um IFDEF Financeiro e defina essa diretiva no projeto Financeiro. Os demais mdulos no compilaro o cdigo protegido.

13.

Segredos do DBGrid: criando uma grade Master/Detail

GP - Na edio 44, publiquei um artigo mostrando vrios recursos interessantes do DBGrid, como a criao de colunas com CheckBox, calendrio, campos memo,

imagens, cores, ordenao etc. O cdigo-fonte est em cc.borland.com/ccweb.exe/author?authorid=222668 . Recebi centenas de emails sobre aquela publicao, de forma que resolvi aproveitar a edio e trazer mais alguns segredos sobre este que sem dvida um dos componentes mais utilizados da VCL. Neste exemplo veremos como simular um DBGrid Master/Detail, semelhante ao que faz a grid do InfoPower. O primeiro passo fazer normalmente o relacionamento Master/Detail entre os componentes DataSet da sua aplicao (via MasterSource/MasterField, DataSetFields, SQL ou mesmo usando filtros). Aqui estou relacionando dois ClientDataSets, um apontando para o arquivoEmployee.xml dos demos do Delphi e o segundo para o arquivo orders.xml. Temos ainda doisDBGrids, cada um vinculado a um DataSource/DataSet. A Listagem 9 mostra o cdigo que deve ser includo no evento OnDrawColumnCell do DBGrid1. A tcnica que usei consiste em desenhar um cone + na primeira coluna do DBGrid master (essa imagem est em um ImageList).

Listagem 9. DBGrid Master/Detail if Column.Index = 0 then begin DBGrid1.Canvas.FillRect(Rect); ImageList1.Draw(DBGrid1.Canvas,Rect.Left,Rect.Top + 1,0); if gdFocused in State then DBGrid2.SetBounds( Rect.Left + 22,Rect.Top + 2, DBGrid2.Width,DBGrid2.Height); end;

Quando o usurio clicar nesse smbolo, posicionamos o segundo DBGrid dentro do primeiro, exibindo os dados relacionados. A Figura 1 mostra o resultado obtido.

Figura 1. Simulando uma grade Master/Detail usando o DBGrid da VCL 14. Segredos do DBGrid: colunas agrupadas usando campos ADT do

ClientDataSet GP - Quando trabalhamos com arquivos locais do ClientDataSet, podemos utilizar um interessante tipo de dado na definio dos campos do DataSet, o ADT (Abstract Data Type). Vejamos como ele funciona: coloque um DBGrid, um DataSource e um ClientDataSet no formulrio e faa as devidas ligaes entre eles. Abra a propriedade FieldDefs do ClientDataSet e adicione alguns campos (ID, NOME etc.). Adicione agora um campo do tipo ftADT (propriedade DateType), chamado Localizacao. Abra sua propriedade ChildDefs e adicione dois campos do tipo string, chamados Cidade e Uf. Ou seja, o campo Localizacao abstrato, na verdade ele formado pela unio dos dois campos filhos, Cidade e Uf. Execute a aplicao e observe que o DBGrid cria um efeito especial para tratar esse tipo de campo (Figura 2). Para persistir as informaes cadastradas, basta indicar o nome do arquivo CDS na propriedade FileName do ClientDataSet.

Figura 2. Efeito no DBGrid para campos ADT 15. Segredos do DBGrid: agrupando registros

GP - Neste exemplo mostrarei como criar um efeito no DBGrid para indicar registros que estejam relacionados entre si, atravs de um ndice. Por exemplo, podemos destacar todas as vendas por data, clientes por cidade, alunos por curso e

assim por diante. Cada grupo ter uma cor de fundo, para indicar que os registros esto relacionados. Para isso, vamos fazer uso de um recurso exclusivo do ClientDataSet, o mtodo GetGroupState. No exemplo, estou utilizando um ClientDataSet apontando para o arquivo customer.xml dos demos do Delphi. Vamos agrupar os clientes pelo pas (campo Country). O primeiro passo ordenar os registros por esse campo, ento abra o editor da propriedade IndexDefs e crie um novo ndice, chamado Country e dando o GroupingLevel para 1. Aponte a propriedadeIndexName do ClientDataSet para esse ndice. D um duplo clique no componente e adicione os campos TField. No evento OnGetText do campoCountry digite o cdigo conforme mostrado na Listagem 10. A listagem tambm mostra o cdigo que deve ser includo no manipulador do evento OnDrawColumnCell do DBGrid. E finalmente, configure a propriedade AggregatesActive do ClientDataSet para True. Isso necessrio para que o GetGroupState funcione.

Listagem 10. Efeitos no DBGrid para agrupar registros const Cores : array [1..7] of integer = ($00FFF7E6,$008080FF,$00EAEAEA,$00FFB56A, $00FFECEC,$00E4E4C9,$0080FFFF); procedure TForm1.DBGrid1DrawColumnCell( Sender: TObject; const Rect: TRect; DataCol: Integer; Column: TColumn; State: TGridDrawState); var r: TRect; i: integer; begin if Column.Field.FieldName = 'Country' then begin DBGrid1.Canvas.Pen.Width := 0; DBGrid1.Canvas.FillRect(Rect); if gbFirst in ClientDataSet1.GetGroupState(1) then p := Rect.Top;

if gbLast in ClientDataSet1.GetGroupState(1) then begin DBGrid1.Canvas.Brush.Color := clWhite; DBGrid1.Canvas.Pen.Style := psDot; DBGrid1.Canvas.Font.Style := [fsbold]; r.Left := 1; r.Top := p + 1; r.Right := 170; r.Bottom := Rect.Top + 16; DBGrid1.Canvas.Rectangle(r); DBGrid1.Canvas.TextOut( 0,p + ((r.Bottom - r.Top) div 2) - 6, ClientDataSet1Country.AsString); end; end else begin DBGrid1.Canvas.Pen.Style := psSolid; i := (sl.IndexOf(ClientDataSet1Country.AsString) mod 7) + 1; DBGrid1.Canvas.Brush.Color := Cores[i]; DBGrid1.Canvas.FillRect(Rect); DBGrid1.DefaultDrawDataCell( Rect,Column.Field,State); end; end; procedure TForm1.ClientDataSet1CountryGetText( Sender: TField; var Text: String; DisplayText: Boolean); begin if sl = nil then sl := TStringList.Create; Text := ClientDataSet1Country.AsString;

if gbFirst in ClientDataSet1.GetGroupState(1) then if sl.IndexOf(Text) < 0 then sl.Add(Text); end;

Como funciona o exemplo: para cada campo de cada registro que mostrado no DBGrid, disparado o evento OnDrawColumnCell. Observe que os registros esto ordenados pelo campoCountry. Dessa forma, usei o mtodo GetGroupState para saber se o registro o primeiro (gbFirst) ou o ltimo (gbLast) do grupo. Assim podemos saber quando devemos pintar uma nova cor para indicar que os registros pertencem a um novo pas. Tambm pintamos o nome do pas uma nica vez para todo o grupo, centralizando o texto em um retngulo que obtido atravs de coordenadas calculadas. O efeito final pode ser visto na Figura 3.

Figura 3. DBGrid com agrupamento: registros destacados por pas 16. Segredos do DBGrid: gerando um relatrio em tempo de execuo

a partir do DBGrid GP - O exemplo que mostro aqui permite criar um relatrio dinamicamente a partir de um DBGrid. Crie um relatrio do tipo Quick Report chamado QRPadrao, com um ColumnHeader e umDetailBand. A seguir, declare um mtodo de classe (class procedure) conforme mostrado naListagem 11. A tcnica utilizada consiste em criar as colunas do relatrio a partir das colunas doDBGrid, preservando a ordem, ttulos, tamanho e posicionamento. Tudo feito dinamicamente, o cdigo pode ser utilizado em qualquer consulta e com qualquer tipo de DataSet. O uso de um mtodo de classe, nesse caso, facilita a chamada do relatrio, pois o prprio

mtodo cria, configura e d um preview no relatrio. Voc pode simplesmente chamar o PrintDBGrid a partir da prpria classe, sem instanci-la (fiz isso para reforar princpios da POO).

Listagem 11. Relatrio dinmico gerado a partir do DBGrid class procedure TQRPadrao.PrintDBGrid(ADBGrid: TDBGrid); var i: integer; posi: integer; col: TQRLabel; fld: TQRDBText; begin posi := 5; QRPadrao := TQRPadrao.Create(nil); with QRPadrao do begin DataSet := ADBGrid.DataSource.DataSet; for i := 0 to pred(ADBGrid.Columns.Count) do begin col := TQRLabel.Create(QRPadrao); col.Parent := QRPadrao.ColumnHeaderBand1; col.Caption := ADBGrid.Columns[i].Title.Caption; col.Top := 10; col.Left := posi; fld := TQRDBText.Create(QRPadrao); fld.Parent := DetailBand1; fld.DataSet := DataSet; fld.DataField := ADBGrid.Columns[i].Field.FieldName; fld.Left := posi; fld.Top := 10; posi := posi + ADBGrid.Columns[i].Width; end;

Preview; end; end; { Exemplo de Utilizao } TQRPadrao.PrintDBGrid(DBGrid1);

17.

Segredos do DBGrid: criando uma tabela no Word a partir dos

dados do DBGrid GP - Utilize a rotina mostrada na Listagem 12, que exporta os dados de um DataSet para uma tabela do Word, usando OLE. Voc pode chamar o cdigo a partir do seu DBGrid, podendo passar para a rotina qualquer descendente de TDataSet (TTable, TQuery, TIBQuery, TClientDataSetetc.). No endereo para download deste artigo voc encontra mais algumas rotinas semelhantes, para exportar os dados para Excel, HTML, XML e TXT.

Listagem 12. Exportando DataSet para Word { Declare ComObj no uses } procedure ExpDOC(DataSet: TDataSet; Arq: string); var A,D,T,R: Variant; Row,Column: integer; begin A := CreateOleobject('Word.basic'); A.Appshow; D := CreateOleobject('Word.Document'); R := D.Range; T := D.tables.Add( D.Range,1,DataSet.FieldCount);

for Column:=0 to DataSet.FieldCount-1 do T.cell(1,Column+1).range.text:= DataSet.Fields.Fields[Column].FieldName; Row := 2; DataSet.First; while not DataSet.Eof do begin T.Rows.Add; for Column:=0 to DataSet.FieldCount-1 do T.cell(Row,Column+1).range.text := DataSet.Fields.Fields[Column].DisplayText; DataSet.next; Row := Row+1; end; D.SaveAs(Arq); D := unAssigned; end; { Exemplo de utilizao } ExpDOC(ClientDataSet1,'teste.doc');

18.

Obtendo o nome do usurio logado no Windows

GP - Com certeza a maioria das aplicaes que criamos possui uma tela de Login. Em algumas situaes, voc pode querer suprimir essa tela e utilizar as credenciais do usurio logado no Windows. Ou seja, no ser preciso fazer o login duas vezes, a autenticao ser integrada. Tudo o que precisamos fazer obter o nome do usurio logado para ser utilizado no cdigo da aplicao. Para isso, use a rotina da Listagem 13.

Listagem 13. Capturando o nome do usurio logado no Windows

function NomeUsuario: string; const Max = 254; var Nome: string; Tam: DWORD; begin Tam := Max - 1; SetLength(Nome,Max); GetUserName(PChar(Nome),Tam); SetLength(Nome,Tam); result := Nome; end;

19.

Como saber se o InterBase/Firebird est ativo(rodando)?

GP - Utilize a funo da Listagem 14. Basta passar o nome do servidor e a porta que deseja testar, para ver se o IB/FB est rodando, como no exemplo:

Listagem 14. Rotina para saber se o IB/FB est rodando function ServerIsRunning( AHost: string; APort: integer): boolean; begin { Declare IdTCPClient no uses } with TIdTCPClient.Create(nil) do begin Host := AHost; Port := APort; Result := True; try Connect; Disconnect; except Result := False;

end; Free; end; end;

if not ServerIsRunning('localhost',3050) then ShowMessage('Servidor firebird no est ativo');

20.

Listando todos os computadores da rede que esto rodando

InterBase/Firebird GP - O que precisamos fazer listar todos os micros da rede e para cada um chamar a funoServerIsRunning do exemplo anterior. O cdigo da Listagem 15 mostra todos os computadores do domnio em ListBox1. A seguir, exibe em ListBox2 todos os computadores que esto rodando o servidor InterBase/Firebird (a rotina GetServerNames pode ser encontrada na unit NetApi, disponvel para download com este exemplo).

Listagem 15. Descobrindo onde o IB/FB est rodando na rede GetServerNames(ListBox1.Items,Edit1.Text,SV_TYPE_ALL); for i := 0 to pred(ListBox1.Items.Count) do if ServerIsRunning(ListBox1.Items[i],3050) then ListBox2.Items.Add(ListBox1.Items[i]);

21.

Como habilitar a opo Run Without Debugging no Delphi 7?

GP - Voc deve ter notado que o Delphi 8 e 2005 trazem uma nova opo no menu Run, que permite executar uma aplicao sem acionar o debugger. Com isso, a inicializao da aplicao fica bem mais rpida a partir da IDE. No endereo para download deste artigo, voc pode encontrar uma BPL que fiz que permite instalar esse recurso no Delphi 7, basta clicar emComponent/Install Packages e dar um Add na BPL.

22.

Como descompilar aplicaes Delphi?

GP - impossvel extrair o cdigo-fonte original de uma aplicao a partir de um arquivo .exe, pois o Delphi (Win32) gera cdigo nativo da CPU. No entanto, existe um utilitrio chamado FormExtractor, que capaz de extrair os arquivos dfm de uma aplicao e gerar os cabealhos dos arquivos pas. Ou seja, voc consegue recuperar todas as propriedades que tenha configurado para componentes, como instrues SQL, componentes e controles, posies, captions, textos, figuras etc. Voc pode fazer o download do utilitrio a partir do endereo deste artigo.

23.

Utilitrio para gerenciar pacotes do Delphi 2005

GP - Na edio 57, apresentamos um recurso que permite personalizar a IDE do Delphi 2005 de acordo com a necessidade desejada: podemos criar uma verso da IDE para carregar os recursos (pacotes) necessrios somente para o desenvolvimento com ASP.NET e Delphi, ou somente para VCL Win 32 e assim por diante. O problema que isso deve ser feito manualmente modificando-se o registro do Windows. Descobrimos um utilitrio excelente, que pode poupar esse trabalho e criar verses da IDE de forma simplificada. O download pode ser feito no endereo

24.

Como usar parmetros dinmicos de conexo no ADO.NET e BDP?

GP - Quando voc cria uma conexo no ADO.NET, os parmetros de acesso so colocados na propriedade ConnectionString do componente de conexo e so compilados com a aplicao. Isso um problema se voc precisar modificar algum parmetro, como as credenciais de acesso ou o caminho do banco. Felizmente o .NET Framework tem um recurso bastante interessante, chamado Dynamic Properties. Isso permite que voc armazene em um arquivo XML valores de propriedades de componentes. Podemos usar esse recurso para resolver o problema descrito anteriormente. Basta selecionar o componente de conexo, abrir o editor da propriedadeDynamicProperties e indicar que queremos parametrizar o ConnectionString. Ser criado um arquivo app.config que adicionado ao projeto e deve ser distribudo com a aplicao. Voc pode agora alterar o parmetro no prprio arquivo. Para carregar o parmetro em runtime, digite o seguinte no evento Load do formulrio:

BdpConnection1.ConnectionString := System.Configuration.ConfigurationSettings. AppSettings.Get('BdpConnection1.ConnectionString');

25.

Em uma aplicao ASP.NET, quando seleciono um item em

um DropDownList, o cdigo que coloco no evento SelectedIndexChanged no executado imediatamente, somente quando a pgina submetida, por qu? GP - Para que o evento seja disparado assim que o valor for modificado, configure para True a propriedade AutoPostBack do componente. Essa propriedade existe para vrios outros controles (ListBox,CheckBox etc.) e tem a mesma funcionalidade.

26.

Ativando o trace em pginas ASP.NET

GP - O ASP.NET possui um interessante recurso, que permite a visualizao de todas as informaes sobre uma requisio diretamente no browser, facilitando a depurao de aplicaes. Basta incluir o atributo trace=True na tag Page do arquivo aspx para que o ASP.NET devolva para o browser, juntamente com a pgina aspx gerada, informaes sobre o request, componentes, cookies, cabealhos HTTP, variveis de ambiente do servidor, objetos em sesso, estado de controles etc.

27.

Validando campos CEP e CPF em uma aplicao ASP.NET

GP - Para validar campos que precisam obedecer a um determinado formato, voc pode utilizarexpresses regulares. simples, coloque um RegularExpressionValidator e aponte sua propriedade ControlToValidate para o TextBox usado para a entrada de dados. A seguir, digite na propriedade ValidationExpression do RegularExpressionValidator a expresso regular a ser usada, sendo \d{5}(-\d{3}) para CEP e \d{3}.\d{3}.\d{3}.\d{2} para CPF. Em ErrorMessage digite a mensagem de erro a ser exibida caso a entrada seja invlida (ex.: CPF invlido). Abrindo o editor da propriedade ValidationExpression voc pode encontrar expresses pr-definidas (para e-mails, URL etc.).

28.

Personalizando a pgina de erro em ASP.NET

GP - Quando uma exceo no tratada ocorre em uma aplicao ASP.NET, uma pgina padro com o ttulo Server Error in /Nome Application. mostrada, contendo informaes como source error, stack trace etc. Para indicar uma pgina personalizada, modifique o elementoCustomErrors do arquivo Web.Config do projeto como mostrado a seguir:

<="" span=""> defaultRedirect="WebForm2.aspx"/>

29.

Como fazer DataBinding em ASP.NET?

GP - O DataBinding um dos recursos mais poderosos do .NET e permite que seja feita a vinculao de dados entre controles e objetos. Isso vai muito alm do conceito de Data-Aware que temos na VCL. Normalmente em aplicaes ASP.NET, o DataBinding ser feito ligando controles de tela (TextBoxes, por exemplo) a campos de um DataTable. Mas o recurso no se limita a apenas isso. Veja um exemplo: considere uma aplicao tpica estilo OlaMundo, que exibe em um Label o item atualmente selecionado em um ListBox (adicione alguns itens nesse componente). Para isso, selecione a Label, abra o editor da sua propriedade DataBindings, selecione a propriedade Text e a seguir digite a expresso ListBox1.SelectedItem.ToString(). Lembre-se de chamar o mtodo DataBind no Load do formulrio e de configurar o AutoPostBack do ListBox. Voc pode fazer DataBind para qualquer propriedade de qualquer controle, obtendo valores a partir de propriedades de outros componentes. Temos uma excelente flexibilidade e produtividade ao usar esse recurso.

30.

Usando o IsPostBack no ASP.NET

GP - O evento Load de um Web Form sempre disparado quando uma requisio enviada ao servidor. Em algumas situaes, precisamos que determinado bloco de cdigo seja executado somente na primeira vez. Nesse caso, preciso testar o valor da propriedade IsPostBack. O cdigo a seguir, colocado no Load do formulrio, adiciona itens em um DropDownList somente na primeira vez que a pgina for carregada:

if not IsPostBack then begin DropDownList1.Items.Add('Teste 1'); DropDownList1.Items.Add('Teste 2'); end;

31.

No ADO.NET, como criar um DataSet/DataTable em memria

programaticamente? GP - O cdigo da Listagem 16 mostra como criar uma tabela em memria usando os objetosDataSet, DataTable, DataRow e DataColumn do ADO.NET. No exemplo, crio uma tabela com dois campos e insiro dois registros. O resultado mostrado em um DataGrid.

Listagem 16. Criando DataSets/DataTables do ADO.NET programaticamente var dt: DataTable; ds: DataSet; row: DataRow; begin ds := DataSet.Create; dt := ds.Tables.Add; dt.Columns.Add('ID'); dt.Columns.Add('NOME'); row := dt.NewRow; row['ID'] := 1; row['NOME'] := 'teste 1'; dt.Rows.add(row); row := dt.NewRow; row['ID'] := 2; row['NOME'] := 'teste 2'; dt.Rows.add(row); DataGrid1.DataSource := dt; ds.WriteXml('.\dados.xml',XmlWriteMode.IgnoreSchema);

end;

32.

Como usar transaes no BDP?

GP - O cdigo da Listagem 17 mostra como envolver a execuo de dois comandos SQL usando transaes no BDP, por meio de um BdpTransaction. Os outros componentes utilizados soBdpConnection e BdpCommand. No exemplo dado, o segundo comando falha, de forma que toda a transao desfeita (Rollback). ExecuteNonQuery o mtodo de BdpCommand usado para executar comandos que no retornam um conjunto de dados.

Listagem 17. Transaes no BDP var Trans: IDbTransaction; begin BdpConnection1.Open; try Trans := BdpConnection1.BeginTransaction; try BdpCommand1.CommandText := 'update EMPLOYEE set SALARY = SALARY + 1000'; BdpCommand1.ExecuteNonQuery; BdpCommand1.CommandText := 'delete from CUSTOMER'; BdpCommand1.ExecuteNonQuery; Trans.Commit; Label1.Text := 'Commit - Transao efetuada com sucesso'; except on E: Exception do begin

Trans.Rollback; Label1.Text := 'RollBack - Alteraes no efetivadas no BD'+ e.Message; end; end; finally BdpConnection1.Close; end; end;

33.

Sabemos que o live-data um recurso exclusivo do provider da

Borland para o ADO.NET, o BDP. Existe uma forma de usar live-data em outro provider? GP - Sim, possvel usar esse recurso para qualquer provider para ADO.NET, incluindo OleDB, Oracle, SQL Server, ODBC e at mesmo Firebird .NET Provider. Considere um exemplo usando os componentes OleDbConnection, OleDbDataAdapter e DataSet. Com no so componentes do BDP, precisaramos chamar o mtodo Fill do OleDbDataAdapter em tempo de execuo para preencher o DataSet. Isso no mais necessrio devido aos novos componentes do Delphi 2005. Basta colocar um DataSync e apontar o OleDbDataAdapter na propriedade Providers. A seguir, colocamos um DataHub, apontamos o DataPort para o DataSync e configuramos a propriedadeDataSet. Ativando sua propriedade Active temos agora live-data para o provider OleDb. Esses novos componentes so tambm utilizados em aplicaes de DataSets distribudos, usando .NET Remoting e ADO.NET.

34.

No ADO.NET, como salvar os dados de um DataSet para XML?

GP - Use o mtodo WriteXml, como mostrado a seguir:

dataSet1.WriteXml('.\dados.xml',XmlWriteMode.IgnoreSchema);

Para carregar os dados, use o mtodo ReadXml.

35.

Como fazer DataBind de um array para um controle?

GP - No .NET, podemos facilmente usar um array como fonte de dados para um controle de tela, como se fossem dados vindos de uma tabela. Veja um exemplo de utilizao:

const Nomes: array[1..3] of string = ('Guinther','Pimenta','Tone'); begin ListBox1.DataSource := Nomes; end;

36.

Como usar o componente ErrorProvider?

GP - O ErrorProvider um interessante componente do .NET Windows Forms que permite indicar visualmente na tela se h um erro em um determinado controle. Para um exemplo, coloque esse componente em um formulrio e um TextBox. No evento Validating do TextBox digite:

if TextBox1.Text = '' then ErrorProvider1.SetError(TextBox1,'Preencha o valor') else ErrorProvider1.SetError(TextBox1,'')

Se o erro ocorrer, um cone piscando ser exibido ao lado do controle e a mensagem mostrada em forma de Hint. possvel personalizar o cone, a velocidade do blink etc.

37.

Como acessar um objeto COM ou ActiveX no Delphi for .NET?

GP - O .NET permite o acesso a objetos COM atravs de servios de interoperabilidade. Clique de direita em References no Project Manager e escolha Add Reference. Na aba Com Importsescolha o objeto COM que deseja acessar (ele deve estar previamente registrado). Se quiser usar um controle ActiveX a partir da IDE, clique em Component|Installed .NET Components e selecione o item na aba ActiveX Components. Por exemplo, se tiver o Acrobat Reader instalado, escolha o item Adobe Acrobat Control for ActiveX. Ser adicionado um novo componente na paleta, que voc pode usar em aplicaes Windows Forms. Para exibir um documento PDF em um formulrio, coloque o componente importado e no evento Load digite:

AxPdf1.LoadFile('delphi.pdf')

38.

Como adicionar um item nas tarefas agendadas do Windows?

GP - No endereo www.sicomponents.com/taskscheduler.html voc pode encontrar um componente que permite adicionar tarefas no Windows. Voc pode, por exemplo, criar a partir da sua aplicao uma tarefa para fazer backups no IB/FB e agendar a mesma para ser executada em tempos programados (diariamente ao meio-dia, por exemplo).

39.

Como usar pilhas e filas no Delphi?

GP - Poucos sabem, mas o Delphi j possui classes nativas para trabalhar com pilhas e filas. Na unit Contnrs voc pode encontrar as classes TQueue, usada para implementar uma lista, eTStack, para criar uma pilha. Veja um exemplo:

var s: TStack; begin s := TStack.Create; s.Push(); // adiciona um item na pilha

s.Pop; // obtm um item da pilha

40.

Inserindo registros no banco usando Stored Procedures

GP - O uso de Stored Procedures para insero de registros no banco de dados, ao invs do tradicional Insert, uma tcnica bastante utilizada por desenvolvedores, pois aumenta bastante a performance da aplicao. Com base nos parmetros da procedure, o banco pode otimizar planos de execuo e processar inseres de forma muito rpida. Considere a procedure da Listagem 18 criada no banco Employee.fdb, que insere dados na tabela Country. Em uma aplicao dbExpress, normalmente voc estar usando um SQLDataSet, DataSetProvider e ClientDataSet para acessar a tabela. Quem gera os comandos de atualizao (Insert, Delete e Update) o DataSetProvider. O que precisamos fazer interceptar o comando de insero e instruir o DataSetProvider para no gerar o Insert. Primeiro, coloque umSQLStoredProc (dbExpress), ligue-o ao SQLConnection e aponte a propriedade StoredProcNamepara Country_I. A seguir, no evento BeforeUpdateRecord do DataSetProvider, digite o cdigo que est no final da Listagem 18. Com isso no deixamos o DataSetProvider gerar o Insert e repassamos os valores inseridos para a SP.

Listagem 18. Usando Stored Procedures para inserir registros no banco de dados CREATE PROCEDURE COUNTRY_I ( COUNTRY VARCHAR(15),CURRENCY VARCHAR(10)) AS BEGIN INSERT INTO COUNTRY ( COUNTRY, CURRENCY) VALUES (:COUNTRY,:CURRENCY); END

{ Cdigo do evento BeforeUpdateRecord do DataSetProvider} if UpdateKind=ukInsert then begin

SQLStoredProc1.Params[0].AsString := DeltaDS.Fields[0].AsString; SQLStoredProc1.Params[1].AsString := DeltaDS.Fields[1].AsString; SQLStoredProc1.ExecProc; Applied := True; end;

41.

Habilitando o estilo XP

LP - Para aplicaes VCL, basta colocar o componente XPManifest (Win32) no formulrio principal do projeto, ou declarar a unit XPMan na clusula uses. Ao executar a aplicao novamente, voc j poder notar a diferena. Se estiver construindo uma aplicao .NET Windows Forms, basta chamar Application.EnableVisualStyles no construtor do formulrio e alterar para System a propriedade FlatStyle dos controles de tela.

42.

Usando o evento OnException do componente ApplicationEvents

LP - O ApplicationEvents um componente no-visual que facilita a criao de manipuladores para eventos globais da aplicao. Por exemplo, toda exceo no tratada passar pelo eventoOnException desse componente, de forma que voc pode fornecer uma sada padro para os erros de sua aplicao (como criar um formulrio personalizado de erro). Veja um exemplo:

ShowMessage(E.Message);

Se voc incluir um comentrio nesse evento, ento sua aplicao nunca exibir mensagens de erros no tratados. Esse evento tambm pode ser usado para criar relatrios de exceo.

43.

Aes pr-definidas do ActionList

LP - O ActionList com certeza um componente obrigatrio em qualquer aplicao. Alm de permitir a centralizao de cdigo para diversos itens de tela, ele possui vrias aes pr-definidas, como: formatao e procura em Memos e RichEdits, uso da rea de transferncia (copiar, colar), abrir, salvar arquivos, configuraes de impressora, abrir navegadores, enviar e-mail e trabalhar com DataSets. O ActionList possui muitos mtodos de manipulao de DataSets: TDataSetFirst, TDataSetPrior, TDataSetNext, TDataSetLast etc. Ou seja, possvel realizar todas as operaes sobre umDataSet sem digitar uma linha de cdigo. Ao criar uma Action desse tipo, no preciso indicar oDataSource: a Action detecta o DataSource pelo controle que est com o foco. Caso nunca tenha criado Actions, faa um teste: coloque um ActionList no formulrio, d um duplo clique no componente e adicione uma nova Standard Action. Escolha uma ao qualquer na lista (exemploSendMail). A seguir, basta apontar a propriedade Action de um controle de tela (um Button, por exemplo) para usar a ao.

44.

Como acessar o Firebird no Delphi 8 e 2005, em aplicaes .NET?

LP - Voc pode utilizar o provider do Firebird para ADO.NET, disponvel no sitewww.firebirdsql.com. Para instalar os componentes, acesse o menu Component|Installed .NET Components, clique no boto Select an Assembly e escolha o arquivo FirebirdSql.Data.Firebird.dllque est no diretrio de instalao do Firebird .NET Provider. Os componentes sero instalados na IDE. Caso queira utilizar o provider da Borland (BDP) para acessar o Firebird, faa o download do driver a partir do endereo prdownloads.sourceforge.net/firebird/FirebirdBDP1.0 Alpha4.exe?download. Para saber mais sobre o assunto, acesse nosso Portal do Assinante ()

45.

Criando tabelas via cdigo Delphi

LP - Se voc utiliza dbExpress, pode usar o mtodo ExecuteDirect do SQLConnection como no exemplo a seguir:

SQLConnection1.ExecuteDirect( 'create table CLUBEDELPHI ( ' + ' ID INTEGER NOT NULL, '+

' NOME VARCHAR(50));');

possvel passar outros comandos DDL, como Alter Table, Drop Table, Create Procedure etc.

46. aplicao

Distribuindo o Firebird/InterBase juntamente com a instalao da

LP - Voc pode utilizar o Inno Setup, timo gerador de instaladores, free e que no perde em recursos se comparado aos geradores comerciais. Acesse www.innosetup.com e baixe a nova verso. Na edio 38 da ClubeDelphi, existe um artigo mostrando em detalhes o Inno Setup. Ao criar a instalao da sua aplicao, possvel incluir o instalador do Firebird ou do InterBase.

47.

Criando uma verso trial da aplicao e diminuindo o tamanho do

executvel LP - H uma ferramenta bastante completa que pode realizar esse trabalho. O ASProtect(www.aspack.com) gera um novo executvel, baseado no seu, com alteraes para cancelar a aplicao aps um determinado nmero de dias ou nmero de execues. Neste mesmo endereo voc pode baixar o ASPack, utilitrio que permite comprimir seu executvel e reduzir seu tamanho em at 70 %.

48.

Como concatenar dois campos em um select no

Firebird/Interbase? LP - Para concatenar strings, voc deve utilizar dois | (pipe), como no exemplo a seguir, onde selecionamos em uma mesma coluna o endereo do cliente, juntamente com o nmero:

select ID, CLIENTE, ENDERECO || NUMERO from CLIENTES order by CLIENTE

49.

Como criar um alias no Firebird/Interbase?

LP - Para criar um alias no Firebird, basta editar o arquivo aliases.conf no diretrio de instalao do Firebird e adicionar um alias, como no exemplo:

NomeAlias = \Arquivo.fdb

No componente de acesso ao banco (SQLConnection, IBDatabase etc.), utilize o alias no lugar dastring de conexo, como por exemplo: localhost:NomeAlias. O InterBase tambm suporta esse recurso, a partir da verso 7.5.

50.

Como recuperar os metadados de tabelas do banco

Firebird/InterBase? LP - Voc deve consultar tabelas de sistema do banco de dados, como no exemplo a seguir, que retorna o nome das tabelas e os respectivos campos-chave:

select a.rdb$relation_name as Nome_Tabela, b.rdb$field_name as Campo_Chave from rdb$relation_constraints a, rdb$index_segments b where a.rdb$constraint_type = 'PRIMARY KEY' and b.rdb$index_name = a.rdb$index_name

51.

Stored Procedures selecionveis no Firebird

LP - A partir do Firebird 1.5, foi incorporado o comando Execute Statement, para a criao de SQL dinmicos. No cdigo da Listagem 19, criamos uma procedure que seleciona os registros da tabela Department do banco Employee.fdb, passando como parmetro a localizao (Location) do departamento. Com isso, podemos utilizar comandos Selects no Delphi para retornar registros da SP, como se fosse uma tabela. Por exemplo, na propriedade CommandText de um SQLDataSet (dbExpress) voc pode agora digitar o seguinte (observe que Teste o nome da SP):

Listagem 19. Stored Procedure selecionvel CREATE PROCEDURE TESTE ( ALOCATION VARCHAR(15)) RETURNS ( DEPT_NO CHAR(3), DEPARTMENT VARCHAR(25), HEAD_DEPT CHAR(3), MNGR_NO SMALLINT, BUDGET DECIMAL(12,2), PHONE_NO VARCHAR(20)) AS DECLARE VARIABLE ASQL VARCHAR(255); BEGIN if (not ALOCATION is null) then ASQL = 'select DEPT_NO, DEPARTMENT, HEAD_DEPT, '|| 'MNGR_NO, BUDGET, PHONE_NO from DEPARTMENT ' || 'where LOCATION = ''' || :ALOCATION || ''''; for execute statement ASQL into :DEPT_NO,:DEPARTMENT,:HEAD_DEPT,:MNGR_NO, :BUDGET,:PHONE_NO do suspend; end

select * from Teste('Monterey')

52.

Como usar skins na aplicao, semelhante ao ICQ?

LP - Existe um componente para VCL que permite mudar a aparncia da aplicao em tempo de execuo. Acesse www.clubedelphi.net/aplicativos/skins.zip para baixar e testar um exemplo.

53.

Utilizo o InterBase em produo, mas gostaria de usar o Firebird

para testes. Posso instalar os dois bancos em uma mesma mquina? LP - Sim, voc pode ter o InterBase e Firebird rodando na mesma mquina. preciso utilizar uma porta diferente para cada um. No Firebird 1.5, voc pode especificar uma porta diferente da 3050, acessando o arquivo firebird.conf e adicionando a seguinte linha (retire o #):

RemoteServicePort = 3051

O Interbase 7.5 tambm suporta esse recurso.

54.

Como usar transaes no dbExpress?

LP - O cdigo da Listagem 20 mostra como executar vrios comandos SQL envolvidos em uma transao no dbExpress, usando o mtodo StartTransaction do SQLConnection.

Listagem 20. Transaes no dbExpress var Trans : TTransactionDesc; begin Trans.TransactionID := 1; Trans.IsolationLevel := xilREADCOMMITTED;

Connection.StartTransaction(Trans); try { Execute aqui seus comandos SQL } Connection.Commit(Trans); except Connection.Rollback(Trans); end; end;

55.

Usando o comando CASE no Firebird

LP - A finalidade do case retornar um valor baseado em uma lista de condies exclusivas. Por exemplo, no cdigo a seguir, o valor retornado no campo Tipo_Pessoa ser Fsica ou Jurdica e no F ou J, como est armazenado originalmente na tabela:

select ID, NOME, case TIPO when 'F' then 'Fsica' when 'J' then 'Jurdica' end as TIPO_PESSOA from PESSOAS

56.

Domains: o que so e para que servem?

LP - Uma vantagem de se criar um domnio padronizar e abstrair tipos de dados. Voc pode criar um domnio e atribu-lo a outros campos da tabela do banco. O Firebird (e verses antigas do IB) no suportam campos do tipo Boolean, por exemplo, mas voc pode simular o tipo atravs de um Domain, como no cdigo da Listagem 21.

Listagem 21. Criando domnios CREATE DOMAIN DM_BOOLEAN AS CHAR(1) CHARACTER SET WIN1252 CHECK (VALUE in ('F', 'T')); CREATE TABLE CLIENTES ( ID NOME ATIVO INTEGER NOT NULL, VARCHAR(50), DM_BOOLEAN);

57.

Como utilizar caracteres acentuados no IB/FB?

CC - preciso usar charsets e collates disponveis no IB/FB. So eles que permitem ao DBA indicar ao banco quais caracteres sero aceitos nos campos alfanumricos, tanto globalmente (a nvel de BD) ou individualmente para cada campo. Veja um exemplo na Listagem 22.

Listagem 22. Usando caracteres acentuados CREATE DATABASE 'c:\banco.fdb' USER 'SYSDBA' PASSWORD 'masterkey' PAGE_SIZE 4096 DEFAULT CHARACTER SET WIN1252; CREATE TABLE TABELA( CAMPO VARCHAR(10) CHARACTER SET WIN1252 COLLATE PXW_INTL850);

58.

Como usar campos auto-incremento no IB/FB?

CC - Para simular campos auto-incremento preciso usar um generator em conjunto comtriggers. Os generators geram nmeros seqenciais quando requisitados atravs da funo interna Gen_ID. A criao de um generator feita atravs do comando Create Generator. A seguir deve-se criar um Trigger do tipo Before Insert, que vai incrementar o generator, obtendo o novo valor e atribuindo-o ao campo desejado. Veja um exemplo na Listagem 23.

Listagem 23. Usando generators CREATE GENERATOR INC_CODIGO; CREATE TRIGGER TABELA_BI FOR TABELA ACTIVE BEFORE INSERT POSITION 0 AS BEGIN IF (NEW.CODIGO IS NULL) THEN NEW.CODIGO = GEN_ID(INC_CODIGO,1); END

59.

Ao criar minhas tabelas no IB/FB, quando devo usar VarChar ao

invs de Char? CC - Utilize Char somente para campos onde voc conhece o tamanho exato da informao que ser armazenada e que esse tamanho seja fixo. Por exemplo, um campo que armazenar a sigla de um estado sempre utilizar 2 caracteres, portanto use Char(2) nesse campo. Utilize o VarCharquando o tamanho da informao que ser armazenada for varivel (ex.: Nomes, endereos etc.)

60. SQL?

Como recuperar a data e a hora do servidor IB/FB em instrues

CC - Voc pode obter a Data, Hora e Data+Hora do servidor atravs das seguintes variveis do IB/FB: Current_Date, Current_Time e Current_TimeStamp. Veja a seguir um exemplo de utilizao dessas variveis:

select current_timestamp, current_date, current_time from rdb$database

0 COMENTRIO Nenhum comentrio foi postado - seja o primeiro a comentar!

cursos relacionados posts em sequncia ltimos do autor ltimos do site


Curso NFe com Delphi e AcBr Curso Online-Aplicao Financeira com Delphi 2009 e MySQL Automao Comercial com OOP, BPLS e FIREBIRD Curso Crystal Reports XI com Delphi 2010 Curso completo de ClientDataSet Rad Studio 2007-DBX4 e Firebird 2.0-Aplicao comercial de vendas do Inicio ao Fim OLAP com o SQL Server jQuery A Biblioteca JavaScript para Webdesigners PL/SQL Oracle [Ver todos]
Voc est em: canal Delphi +Delphi: mais Publicidade artigos | vdeos | cursos |