29

Revista The Club Megazine - 06/2003 · Como parte da nova estratégia de seus produtos, a Borland ® lançou recentemente sua primeira IDE para desenvolvimento de aplicações para

  • Upload
    dokhanh

  • View
    305

  • Download
    7

Embed Size (px)

Citation preview

Page 1: Revista The Club Megazine - 06/2003 · Como parte da nova estratégia de seus produtos, a Borland ® lançou recentemente sua primeira IDE para desenvolvimento de aplicações para
Page 2: Revista The Club Megazine - 06/2003 · Como parte da nova estratégia de seus produtos, a Borland ® lançou recentemente sua primeira IDE para desenvolvimento de aplicações para

Revista The Club Megazine - 06/2003A utilização, reprodução, apropriação, armazenamento em banco de dados,sob qualquer forma ou meio, de textos, fotos e outras criações intelectuaisem cada publicação da revista “The Club” são terminantemente proibidos

sem autorização escrita dos titulares dos direitos autorais.Copyright© The Club® 2003

Page 3: Revista The Club Megazine - 06/2003 · Como parte da nova estratégia de seus produtos, a Borland ® lançou recentemente sua primeira IDE para desenvolvimento de aplicações para

MeGAZINEMeGAZINEMeGAZINEMeGAZINEMeGAZINE 33333

EDITORIALEDITORIALEDITORIALEDITORIALEDITORIAL

Editorial

Celso Jefferson PaganelliPresidente - The Club

Editorial ............................................................................ 03Dicas & Truques ................................................................. 04Interatividade com Intraweb .............................................. 08Usando o TOleContainer para integrar oMS-Word a aplicações Delphi ............................................. 12Acesso: Identificando e controlando usuários no sistema .. 16Do Clipper para o Delphi ................................................... 23

THE CLUBRua Acre, 950 - Avaré - SP - CEP 18.700-260

Informações: (0xx14) 3732-3689Suporte: (0xx14) 3733-1588

Fax: (0xx14) 3732-0987

Internethttp://www.theclub.com.br

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

DúvidasCorrespondência ou fax com dúvidas devem serenviados ao - THE CLUB, indicando "Suporte".

OpiniãoSe você quer dar a sua opinião sobre o clube em

geral, mande a sua correspondência para a seção"Tire sua dúvida".

ReproduçãoA utilização, reprodução, apropriação,

armazenamento em banco de dados, sob qualquerforma ou meio, de textos, fotos e outras criações

intelectuais em cada publicação da Revista“The Club” são terminantemente proibidos sem

autorização escrita dos titulares dos direitosautorais.

Copyright© The Club® 2003

Impressão e acabamento:Impressos Gril - Gril Gráfica e Repr. Ind. Ltda.

Tel.: (0xx14) 3762.1345 - Fax: (0xx14) 3762.1259Rua São Paulo, 447 - Cep 18.740-000

Taquarituba - SPTiragem: 5.000 exemplares

Diretor - Presidente

Celso Jefferson M. Paganelli

Diretor Técnico

Mauro Sant’AnnaColaboradores

Marcelo Nogueira, Alexandre Magno, Anderson H.Rodrigues, Emerson Facunte, Mario C. Bohm

Delphi é marca registrada da BorlandInternational, as demais marcas citadas são

registradas pelos seus respectivos proprietários.

Olá amigos do The Club,Como parte da nova estratégia de seus produtos, a Borland ® lançou recentemente

sua primeira IDE para desenvolvimento de aplicações para a plataforma Microsoft .Net®, trate-se do C#Builder. Caso tenha interesse em obter maiores informações sobre estenovo produto, poderá acessar o site http://www.borland.com.br/csharpbuilder/.

Bem, vamos falar sobre nosso foco principal, ou seja, o Delphi! Iniciamos nossarevista com a consagrada sessão “Dicas & Truques”, na qual apresentamos umacoletânea de dicas interessantes e úteis no cotidiano do programador Delphi.

Ainda perdido no mundo Matrix, Emerson Facunte mostra como interagirdinâmicamente em páginas web através dos poderes fornecidos pelo Intraweb, que estácada dia melhor.

Este mês temos o prazer de apresentar o mais novo colaborador da The ClubMegazine, estou falando do nosso amigo, Reginaldo Rubens da Silva, mais um féra quevem compartilhar seus conhecimentos com a comunidade The Club, trazendo umexcelente artigo sobre o componente TOleContainer, aplicado na integração entre Delphix Word, seja benvindo Reginaldo.

Continuando, como anda o controle de acesso de usuários em sua aplicação? Bem,recebemos perguntas de inúmeros associados solicitando um exemplo ou uma forma deimplementar este tipo de controle em aplicações Delphi e mediante isso, preparamos umartigo demonstrando uma das abordagens possíveis para este tipo de controle, eesperamos estar contribuindo para melhorar a qualidade e segurança em seu software.

E fechando com chave de ouro, Bruno Sonnino traz o artigo “Do Clipper para oDelphi”, onde demonstra uma solução completa na migração e compartilhamento dedados entre aplicações Clipper e Delphi, através do Advantage Database Server, fornecido noBrasil pela Renet Tecnologia.

Aproveitem e até a próxima, lembrando que qualquer dúvida ou sugestão, sinta-se avontade em nos contatar.

Page 4: Revista The Club Megazine - 06/2003 · Como parte da nova estratégia de seus produtos, a Borland ® lançou recentemente sua primeira IDE para desenvolvimento de aplicações para

MeGAZINEMeGAZINEMeGAZINEMeGAZINEMeGAZINE44444

Como apresentar o número da linha e coluna emum DBGrid?

O DBGrid possui estas informações, porém elas não estãovisíveis para acesso direto. Contudo, podemos derivar uma classea partir de TDBGrid e utilizá-las sem problemas...

implementation

{$R *.DFM}

type

TMostraProp = class (TDBGrid);

{evento OnColEnter do DBGrid}

procedure TForm1.DBGrid1ColEnter(Sender: TObject);

begin

Caption := Format(‘Coluna: %2d; Row: %2d’,

[TMostraProp(DbGrid1).Col,

TMostraProp(DbGrid1).Row]);

end;

{ evento OnDataChange do DataSource }

procedure TForm1.DataSource1DataChange(Sender:

TObject; Field: TField);

begin

DBGrid1ColEnter(Sender);

end;

Como implementar um log de todos os errosgerados na aplicação?

Isso poderá ser implementado utilizando um componenteTApplicationEvents (aba Additional), interceptando seu eventoOnException e gerando um arquivo texto com as mensagens deerros geradas durante a execução do aplicativo. Para isso,adicione um componente TapplicationEvents no Form principal desua aplicação e abra o evento OnExxception onde iremos programaro seguinte:

procedure TFormLog.LogException(Sender: TObject; E:

Exception);

var

NomeDoLog: string;

Arquivo: TextFile;

begin

{

preparar o arquivo de log

utiliza o nome da aplicação, trocando a extensão

para “.log”.

}

NomeDoLog := ChangeFileExt(Application.Exename,

‘.log’);

{ pega ponteiro para o arquivo }

AssignFile(Arquivo, NomeDoLog);

{ verifica se existe }

Dicas & TDicas & TDicas & TDicas & TDicas & Truquesruquesruquesruquesruques

Page 5: Revista The Club Megazine - 06/2003 · Como parte da nova estratégia de seus produtos, a Borland ® lançou recentemente sua primeira IDE para desenvolvimento de aplicações para

MeGAZINEMeGAZINEMeGAZINEMeGAZINEMeGAZINE 55555

if FileExists(NomeDoArquivo) then

Append(Arquivo) { se existir, apenas adicionalinhas } else

ReWrite(Arquivo); { cria um novo se não existir

}

try

{ grava Data e Hora + Mensagem de erro }

WriteLn(Arquivo, DateTimeToStr(Now) + ‘:’ +

E.Message);

{ mostra mensagem original de erro }

Application.ShowException(E);

finally

{ fecha o arquivo }

CloseFile (LogFile);

end;

end;

Para testar, bastará por exemplo em um botão, gerar umaexceção de divisão por zero:

procedure TForm1.Button1Click(Sender: TObject);

var

a, b, c: Integer;

begin

a := 10;

b := 0;

c := a div b;

ShowMessage(IntToStr(c));

end;

Arredondamento de valoresA partir do Delphi 6, temos uma função chamada

SimpleRoundTo que tem a finalidade de arredondar valores combase no número de casas decimais informadas. Esta função estádisponível na unit Math, juntamente com diversas outras funçõesmatemáticas. A função SimpleRoundTo recebe os seguintesparâmetros:

function SimpleRoundTo(const AValue: Double; const

ADigit: TSimpleRoundToRange = -2): Double;

Sendo o valor a ser arredondado e o número de

dígitos, que por padrão é igual a dois.

implementation

uses Math;

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);

begin

SimpleRoundTo(1.234, -2) { retorna 1.23 } SimpleRoundTo(1.235, -2) { retorna 1.24 } SimpleRoundTo(-1.235, -2) { retorna -1.23 }end;

Nas versões anteriores ao Delphi 6, podemos utilizar a funçãoRound, contudo esta função retorna um valor inteiro, e sendoassim temos que dispor de um pequeno macete:

Round( 1.234 * 100 ) / 100;

Onde 1.234 é o valor a ser arredondado. Para fazerarredondamento com dois dígitos, multiplicamos o valor por 100 edividimos o resultado do Round por 100, o que irá retornar o valorarredondado e com dois dígitos. Caso necessite de três dígitos,bastará multiplicar por 1000 e dividir o resultado por 1000.

Como desabilitar o CTRL+ALT+DEL no Windows9x e XP/NT/2000?

No caso do Windows 9x, isso é bastante simples de ser feitodevido a arquitetura desta versão permitir este tipo e controle,como mostra o código abaixo:

const

SPI_SCREENSAVERRUNNING = 97;

var

OldValue: Longbool;

begin

{ habilita } SystemParametersInfo(SPI_SCREENSAVERRUNNING,

Word(True), @OldValue, 0);

{ desabilita } SystemParametersInfo(SPI_SCREENSAVERRUNNING,

Word(False), @OldValue, 0);

end;

Contudo, no caso do Windows XP/NT e 2000, nãoencontramos até o momento como desabilitar esta combinação deteclas, mas é possível desativar o acesso ao TaskManager, ao LogOffe Close, com o código abaixo:

uses

Registry;

procedure EnableCTRLALTDEL(YesNo : boolean);

const

sRegPolicies =

‘\Software\Microsoft\Windows\CurrentVersion\Policies’;

Dicas & TDicas & TDicas & TDicas & TDicas & Truquesruquesruquesruquesruques

Page 6: Revista The Club Megazine - 06/2003 · Como parte da nova estratégia de seus produtos, a Borland ® lançou recentemente sua primeira IDE para desenvolvimento de aplicações para

MeGAZINEMeGAZINEMeGAZINEMeGAZINEMeGAZINE66666

begin

with TRegistry.Create do

try

RootKey:=HKEY_CURRENT_USER;

if OpenKey(sRegPolicies+’\System\’,True) then

begin

case YesNo of

False:

begin

WriteInteger(‘DisableTaskMgr’,1);

end;

True:

begin

WriteInteger(‘DisableTaskMgr’,0);

end;

end;

end;

CloseKey;

if OpenKey(sRegPolicies+’\Explorer\’,True) then

begin

case YesNo of

False:

begin

WriteInteger(‘NoChangeStartMenu’,1);

WriteInteger(‘NoClose’,1);

WriteInteger(‘NoLogOff’,1);

end;

True:

begin

WriteInteger(‘NoChangeStartMenu’,0);

WriteInteger(‘NoClose’,0);

WriteInteger(‘NoLogOff’,0);

end;

end;

end;

CloseKey;

finally

Free;

end;

end;

procedure TForm1.Button1Click(Sender: TObject);

begin

EnableCTRLALTDEL(true);

end;

Criando ToolTips em aplicações Delphi.Esta dica foi enviada por um de nossos associados e achamos

bastante interessante. Mediante isso, implementamos algumas

funcionalidades para deixá-la mais genérica e estamoscompartilhando com todos associados The Club. A apresentaçãodo ToolTip baseia-se na API CreateWindowEx, como podemos ver aseguir:

private

{ procedure para capturar form ativo }

procedure ActiveFormChange(Sender: TObject);

public

end;

{ utilizado na apresentação do ToolTip }

const

TTS_BALLOON = $40;

TTM_SETTITLE = (WM_USER + 32);

var

Form1: TForm1;

{ utilizado na apresentação do ToolTip }

hTooltip: Cardinal;

TI: TToolInfo;

Buffer: array[0..255] of Char;

implementation

uses unTeste;

{$R *.dfm}

{

cria o ToolTip utilizando a API do Windows

CreateWindowEx

}

procedure CreateToolTips(hWnd: Cardinal);

begin

hToolTip := CreateWindowEx(0, ‘Tooltips_Class32’,

nil, TTS_ALWAYSTIP or TTS_BALLOON,

Integer(CW_USEDEFAULT),

Integer(CW_USEDEFAULT),Integer(CW_USEDEFAULT),

Integer(CW_USEDEFAULT), hWnd, 0,

hInstance, nil);

if hToolTip <> 0 then

begin

SetWindowPos(hToolTip, HWND_TOPMOST, 0, 0, 0,

0, SWP_NOMOVE or SWP_NOSIZE or

SWP_NOACTIVATE);

TI.cbSize := SizeOf(TToolInfo);

TI.uFlags := TTF_SUBCLASS;

TI.hInst := hInstance;

end;

Dicas & TDicas & TDicas & TDicas & TDicas & Truquesruquesruquesruquesruques

Page 7: Revista The Club Megazine - 06/2003 · Como parte da nova estratégia de seus produtos, a Borland ® lançou recentemente sua primeira IDE para desenvolvimento de aplicações para

MeGAZINEMeGAZINEMeGAZINEMeGAZINEMeGAZINE 77777

end;

{

Adiciona o ToolTip para o objeto passado como

parâmetro

}

procedure AddToolTip(Hwnd: DWord; Lpti: PToolInfo;

IconType: Integer; Text, Title: PChar);

var

Item: THandle;

Rect: TRect;

begin

Item := hWnd;

if (Item <> 0) and (GetClientRect(Item, Rect))

then

begin

Lpti.hwnd := Item;

Lpti.Rect := Rect;

Lpti.lpszText := Text;

SendMessage(hToolTip, TTM_ADDTOOL, 0,

Integer(Lpti));

FillChar(Buffer, SizeOf(Buffer), #0);

LStrCpy(Buffer, Title);

if (IconType > 3) or (IconType < 0) then

IconType := 0;

SendMessage(hToolTip, TTM_SETTITLE, IconType,

Integer(@Buffer));

end;

end;

Poderemos escolher o estilo do ToolTip alterando umparâmetro no momento da criação do mesmo, podendo ser:

0 – Sem Ícone 1 – Ícone Informação 2 – Ícone Aviso 3 – Ícone Erro

Continuando nossa rotina, a procedure abaixo é responsávelem adicionar o ToolTip aos componentes do Form ativo nomomento.

procedure TForm1.ActiveFormChange(Sender: TObject);

const

TipoDoIcone = 1;

var

i: integer;

begin

with Screen.ActiveForm do

begin

{ Cria o ToolTip com base no Handle do Form

ativo }

CreateToolTips(Handle);

for i := 0 to ComponentCount-1 do

if Components[i] is TWinControl then

{ adiciona o ToolTip para os componentes

do Form ativo }

AddToolTip(TWinControl(Components[i]).

Handle, @TI, TipoDoIcone,

PChar(TWinControl(Components[i]).Hint),

‘Título do ToolTip’);

end;

end;

procedure TForm1.FormCreate(Sender: TObject);

begin

{ Ligando este evento, poderemos tratar todos os

Forms em uma única procedure }

Screen.OnActiveFormChange := ActiveFormChange;

end;

O projeto de exemplo referente esta dica está disponível noendereço: http://www.theclub.com.br/download/tooltip.zip.

Como exportar de tabelas ligadas através do ADOpara outros formatos?

Esta é uma dica bastante interessante e útil para quem faz oacesso a banco de dados através da engine ADO. O ADO permiteutilizar o Microsoft Jet para além de acessar tabelas, exportardados das mesmas para vários formatos, podendo ser feitodiretamente através do método Execute do objeto TAdoConnection, asaber:

var

Path: string;

begin

Path := ExtractFilePath(Application.ExeName);

{ Exportar dados para Paradox }

ADOConnection1.Execute(‘SELECT * INTO Clientes IN

“‘ + Path + ‘“ “Paradox 7.x;” FROM CLIENTES’);

{ Exportar dados para o Excel }

ADOConnection1.Execute ‘SELECT * INTO Clientes IN

“‘ + Path + ‘clientes.xls” “Excel 8.0;”

FROM CLIENTES’);

{exportar para html}

ADOConnection1.Execute (‘SELECT * INTO

[Clientes.htm] IN “‘ + Path + ‘“ “HTML Export;” FROM

CLIENTES’);

end;

Neste exemplo, exportamos para Paradox, Excel e HTML.

Dicas & TDicas & TDicas & TDicas & TDicas & Truquesruquesruquesruquesruques

Page 8: Revista The Club Megazine - 06/2003 · Como parte da nova estratégia de seus produtos, a Borland ® lançou recentemente sua primeira IDE para desenvolvimento de aplicações para

MeGAZINEMeGAZINEMeGAZINEMeGAZINEMeGAZINE88888

Salve amigos do The Club! Será que esta revista é real? Ocomputador que você utiliza existe mesmo? Sejam bem-vindos aoMundo de Matrix. Vocês podem escolher: pílula azul levará vocêspara um mundo de interatividade, onde o sexto sentido é apenasum coadjuvante, ou a pílula vermelha, onde você aprenderáalguns truques sobre Intraweb.

Agora, falando apenas com você, isso mesmo, você amigo!Sabia que você é inteligente e capaz de mudar coisas ao seuredor? Fazer com que o amor da sua vida, que nem sabe que vocêexiste, se apaixone por você através de simples palavras? Isto éinteratividade. Você pode, você deve fazê-lo. Não deixe paraamanhã, pois o amanhã foi ontem!

Vamos aproveitar a era da interatividade, e desenvolver umsimples projeto utilizando o Intraweb. Simples projeto? Amigosessa é a chave para o sucesso: interatividade. Interaja, imagine,faça.

Apesar de simples, recomendo tomar a pílula azul (não estoufalando do Viagra, hein!) e aproveitar melhor o objetivo doprojeto.

Let´s go friends !!!

Crie um novo projeto, através das opções File/New/Other...,selecione a seção Intraweb e escolha o modelo Stand AloneApplication.

Em seguida, selecione o diretório do nosso projeto (exemploc:\intraweb\theclub).

Insira a unit SysUtils, na cláusula uses da aplicação, para

Interatividade com IntrawebInteratividade com IntrawebInteratividade com IntrawebInteratividade com IntrawebInteratividade com Intraweb

que possamos fazer algumas operações.

Grave toda a aplicação, e insira os componentes que seguemno FormMain:

DelphiDelphiDelphiDelphiDelphi

Por Emerson Facunte

Page 9: Revista The Club Megazine - 06/2003 · Como parte da nova estratégia de seus produtos, a Borland ® lançou recentemente sua primeira IDE para desenvolvimento de aplicações para

MeGAZINEMeGAZINEMeGAZINEMeGAZINEMeGAZINE 99999

A figura 1 ilustra nosso formulário.

Figura 1 formulário do projeto

Agora vamos codificar o botão btAdicao. No evento OnClick dobotão, insira o código que segue:

var n1,n2,total:single;

operacao:integer;

begin

try

n1:=StrtoFloat(edN1.Text);

n2:=StrtoFloat(edN2.Text);

total:=0;

operacao:=(Sender as TIWButton).Tag;

case operacao of

1:total:=n1+n2;

2:total:=n1-n2;

3:total:=n1*n2;

4:total:=n1/n2;

end;

edTotal.Text:=FloatToStr(total);

except

on EZeroDivide do

WebApplication.ShowMessage(‘Divisão por zero !’);

on EOverFlow do

WebApplication.ShowMessage(‘Aconteceu OverFlow !’);

//

end;

Antes de analisar o código, selecione os demais botões, eassocie o código do evento OnClick, como ilustra a figura 2.

DelphiDelphiDelphiDelphiDelphi

Page 10: Revista The Club Megazine - 06/2003 · Como parte da nova estratégia de seus produtos, a Borland ® lançou recentemente sua primeira IDE para desenvolvimento de aplicações para

MeGAZINEMeGAZINEMeGAZINEMeGAZINEMeGAZINE1 01 01 01 01 0

DelphiDelphiDelphiDelphiDelphi

Figura 2 associação do evento OnClick aos demais botões.

Vamos analisar o código.

var

n1,n2,total:single;

operacao:integer;

Neste primeiro bloco estamos declarando variáveis paraexecução da operação matemática (n1, n2 e total), bemcomo uma variável auxiliar (operação) com o intuito deassociar o botão que estão chamando o evento. Em cadabotão, definimos valores diferentes para a propriedade TAG,que será facilmente assimilado por nossa aplicação.

try

n1:=StrtoFloat(edN1.Text);

n2:=StrtoFloat(edN2.Text);

total:=0;

operacao:=(Sender as TIWButton).Tag;

Em seguida, iniciamos um bloco protegido (try), econvertemos o conteúdo dos campos de edição edN1 e edN2,para o tipo float. Neste mesmo bloco estamos iniciando avariável total, e atribuindo à variável operacao, o valor contidona propriedade TAG de um objeto do tipo TIWButton, que em nossocaso, são representados pelos botões btAdicao, btSubtracao,btMultiplicacao e btDivisao.

case operacao of

1:total:=n1+n2;

2:total:=n1-n2;

3:total:=n1*n2;

4:total:=n1/n2;

end;

Neste bloco, fazemos as devidas operações de acordo com obotão pressionado:

edTotal.Text:=FloatToStr(total);

Em seguida, atribuímos ao objeto edTotal o resultado daoperação.

.

except

on EZeroDivide do

WebApplication.ShowMessage(‘Divisão por zero !’);

on EOverFlow do

WebApplication.ShowMessage(‘Aconteceu OverFlow !’);

//

end;

Por fim, tratamos duas exceções EZeroDivide (divisão porzero), e EOverFlow (Overflow na operação). Repare que em casode erro, estamos apresentando mensagens ao usuário. É muitoparecido com o famoso Application.ShowMeesage. Neste caso,utilizamos o WebApplication.ShowMessage.

Figura 3 projeto em execução

Em seguida temos nossa mensagem de erro. A figura 4ilustra um erro de divisão por zero.

A figura 3, ilustra nossa aplicação em tempo de execução.

Page 11: Revista The Club Megazine - 06/2003 · Como parte da nova estratégia de seus produtos, a Borland ® lançou recentemente sua primeira IDE para desenvolvimento de aplicações para

MeGAZINEMeGAZINEMeGAZINEMeGAZINEMeGAZINE 1 11 11 11 11 1

DelphiDelphiDelphiDelphiDelphi

O poder está em suas mãos.

Quem sabe esta calculadora possa oferecer inúmerasoperações, científicas, financeiras, entre outras, econquistar um novo mundo.

Não desistam, o Arquiteto tem um plano para nós.

Muita luz e sucesso a todos!!!

Emerson Facunte

Figura 4 - erro [ divisão por zero ]

Emerson Facunte é Consultor deTecnologia com diversos livros publicados,especialista em desenvolvimento de aplicaçõese-business utilizando a ferramenta Delphi,baseado em webSnap, dataSnap, BizSnap eISAPI/Apache Modules.

Sobre o autor

Page 12: Revista The Club Megazine - 06/2003 · Como parte da nova estratégia de seus produtos, a Borland ® lançou recentemente sua primeira IDE para desenvolvimento de aplicações para

MeGAZINEMeGAZINEMeGAZINEMeGAZINEMeGAZINE1 21 21 21 21 2

DelphiDelphiDelphiDelphiDelphi

1. IntroduçãoÉ comum nos depararmos com a necessidade de desenvolver

aplicações Delphi nas quais haja a possibilidade da edição dedocumentos de texto. Nestes casos, temos como possível solução, aconstrução de um “pseudo editor de textos” usando componentesdo próprio Delphi, como por exemplo o TRichEdit. No entanto, estasolução pode implicar em tempo adicional para conclusão doaplicativo em questão e, além disso, há também o fato de que amaioria dos usuários de computadores já está acostumada a usaro Microsoft Word como editor de textos. Então, para quereinventar a roda ?

De modo a poupar trabalho para a implementação de umnovo editor de textos, como, também, para permitir que o usuáriocontinue dispondo de todos os recursos oferecidos pelo MicrosoftWord, sem ter a necessidade de executá-lo paralelamente aaplicação Delphi, podemos utilizar ocomponente TOleContainer, quepermitirá “embutir” o Word emnossa aplicação.

2. O ComponenteTOleContainer

O componente TOleContainer seencontra disponível a partir dapaleta System do Delphi e, como sepode constatar através do próprioHelp deste componente, o mesmodispõe de várias propriedades emétodos.

Para efeito de exemplo deutilização das principaispropriedades e métodos envolvidosna utilização do TOleContainer comoferramenta para a integração deaplicativos Delphi e o MS-Word,desenvolveu-se uma aplicaçãoexemplo, conforme descrito abaixo.

Usando o TOleContainer para integrarUsando o TOleContainer para integrarUsando o TOleContainer para integrarUsando o TOleContainer para integrarUsando o TOleContainer para integraro MS-Word a aplicações Delphio MS-Word a aplicações Delphio MS-Word a aplicações Delphio MS-Word a aplicações Delphio MS-Word a aplicações Delphi

Figura 1 – Opção Arquivo do menu da aplicação

Somente foi inclusa no menu a opção Arquivo, visto que, nomomento em que for criado um objeto no OleContainer, o menu daaplicação embutida (nesse caso o Word) é mesclado com o menuda aplicação Delphi. Dessa maneira, o menu da aplicação Delphise encarrega das opções referentes às operações de criação,abertura, fechamento, salvamento e impressão do documento,bem como do encerramento da aplicação. O menu da aplicaçãoembutida trará as demais opções, tais como: Editar, Inserir,Formatar, Ferramentas, etc.

O objeto OleContainer deve ser inserido sobre um panel para queeste, no momento da criação de um objeto, fique restrito às

3. A Aplicação ExemploA aplicação foi desenvolvida utilizando um Form, no qual foi

inserido um Menu (TMainMenu), conforme a Figura 1.

Por Reginaldo Rubens da Silva

Page 13: Revista The Club Megazine - 06/2003 · Como parte da nova estratégia de seus produtos, a Borland ® lançou recentemente sua primeira IDE para desenvolvimento de aplicações para

MeGAZINEMeGAZINEMeGAZINEMeGAZINEMeGAZINE 1 31 31 31 31 3

DelphiDelphiDelphiDelphiDelphi

dimensões do panel. A opção align do OleContainer deve serconfigurada como alClient, de forma que o OleContainer ocupe todo oespaço disponível no panel, como também pode ser visto na Figura1.

3.1. O Funcionamento da AplicaçãoA fim de ilustrar a utilização do componente TOleContainer,

nossa aplicação implementou as operações de criação, a abertura,o fechamento, o salvamento (através das opções Salvar e Salvarcomo...) e a impressão de um documento.

3.1.1. A criação de um novo documentoA operação de criação de um documento foi implementada a

partir da opção Novo, do menu Arquivo. A criação se dá a partirdo método CreateObject do OleContainer, conforme a Figura 2.

Esse método tem como parâmetros OleClassName e Iconic. Oparâmetro OleClassName é do tipo string e se refere à classe doobjeto que desejamos criar. Por exemplo, para criarmos umdocumento do Word, precisamos definir o parâmetro OleClassNamecomo Word.Document.8.

Figura 2 – Procedimento executado pela opção Novo, do menu Arquivo

Esses nomes de classes podem ser pesquisados a partir dachave HKEY_CLASSES_ROOT do registro do Windows,utilizando-se do editor de registros (Regedit). A partir dessachave do registro é possível saber o nome da classe associada aqualquer tipo de documento, como por exemplo, uma imagem jpg(.jpg), um arquivo html (.htm ou .html), uma planilha do excel(.xls) e vários outros. Já o parâmetro Iconic é do tipo boolean. SeIconic for definido como True, o objeto do OleContainer será criado emforma de um ícone e seu conteúdo somente poderá ser editadoatravés do duplo-clique do mouse. Já, se for definido como False, oparâmetro Iconic determina que o objeto criado estará disponívelimediatamente para a edição.

No caso da nossa aplicação exemplo, imediatamente apósclicar a opção Novo, do menu Arquivo, o usuário já tem a suadisposição um novo documento do Word para editar.

3.1.2. A abertura de um arquivo existenteDe forma semelhante a criação de um documento, a abertura

de um já existente ocorre através do acionamento da opçãoAbrir..., do menu Arquivo, que faz uma chamada ao métodoCreateObjectFromFile, como se pode ver através da Figura 3

Figura 3 – Procedimento executado pela opção Abrir, do menu Arquivo

Page 14: Revista The Club Megazine - 06/2003 · Como parte da nova estratégia de seus produtos, a Borland ® lançou recentemente sua primeira IDE para desenvolvimento de aplicações para

MeGAZINEMeGAZINEMeGAZINEMeGAZINEMeGAZINE1 41 41 41 41 4

DelphiDelphiDelphiDelphiDelphi

A diferença entre este método e o utilizado anteriormentepara a criação de um documento, está no fato de que nãoinformamos como parâmetro a classe do objeto, mas sim ocaminho de um arquivo, a partir do qual um novo objeto serácriado no OleContainer.

Ao informarmos o caminho do arquivo, o próprio OleContainerse encarrega de determinar qual a classe do documento queestamos abrindo. Assim como ocorre no método CreateObject,podemos comandar a criação do objeto em forma de ícone oumodo normal.

Quando criamos um objeto a partir de um arquivo, o mesmonão é exibido através da interface da sua aplicação de origem (nonosso caso, o Word), mas sim, disposto como se fossesimplesmente um Memo, como se pode notar a partir da Figura 4.

Figura 4 – Abertura de documento usando o métodoCreateObjectFromFile.

A interface da aplicação de origem somente seráacionada se o OleContainer receber um duplo-clique domouse.

No entanto, pode não ser conveniente quedeixemos a cargo do usuário executar este duplo-clique sobre o OleContainer, a fim de exibir o documentona sua interface original. Para solucionar esteproblema, podemos fazer uso do método Perform, herdado peloOleContainer da classe TControl.

Utilizando o método Perform, juntamente com a mensagemWM_LBUTTONDBLCLK da Api do Windows, podemos simular oduplo-clique do mouse sobre um componente. É exatamente issoque ocorre imediatamente após a abertura do documento peloOleContainer em nossa aplicação exemplo, como também pode servisto acima, na Figura 5.

Figura 5 (acima)– Documento aberto com o envio da mensagemWM_LBUTTONDBLCLK

A fim de facilitar a interação com o usuário, foi utilizado umOpenDialog, presente na guia de componentes Dialogs, para que omesmo informe a localização e o nome do arquivo que desejaabrir.

3.1.3. O Fechamento de um DocumentoEm algum momento, pode ser necessário fechar um

documento que se encontra aberto. Para isso, acionamos ométodo DestroyObject do OleContainer, através da opção Fechar, domenu Arquivo, conforme Figura 6.

Figura 6 – Procedimento executado pela opção Fechar, do menuArquivo.

O único detalhe a ser considerado neste ponto, é que se ousuário não salvou o documento antes de solicitar o fechamentodo mesmo, perderá todas as informações. O componente nãodispõe de nenhum método ou propriedade explícitos quepermitem identificar se houve alteração no documento desde oúltimo salvamento. Esse é um problema que merece ser estudadoa parte.

Page 15: Revista The Club Megazine - 06/2003 · Como parte da nova estratégia de seus produtos, a Borland ® lançou recentemente sua primeira IDE para desenvolvimento de aplicações para

MeGAZINEMeGAZINEMeGAZINEMeGAZINEMeGAZINE 1 51 51 51 51 5

DelphiDelphiDelphiDelphiDelphi

3.1.4. O Salvamento de um DocumentoO menu arquivo dispõe as opções Salvar e Salvar como...

destinadas a gravação física do conteúdo do documento atual.Caso o usuário se utilize da opção Salvar, sem ter salvo odocumento nenhuma vez desde a sua criação, a própria aplicaçãose encarregará de disparar a opção Salvar como..., que interagecom o usuário através de um SaveDialog, também disponível naguia de componentes Dialogs, de modo que o mesmo informe alocalização e o nome do arquivo com que deseja que o documentoseja salvo.

Ambas as opções de salvamento chamam o métodoSaveAsDocument do OleContainer. Esse método, ao contrário doSaveToFile, faz com que o arquivo seja salvo com toda aformatação necessária para que o mesmo possa ser lido pela suaaplicação de origem (a qual estamos apenas embutindo em nossaaplicação Delphi).

3.1.5. Imprimindo um DocumentoDado que o OleContainer não substituirá nossa opção de menu

Arquivo pela original, da aplicação embutida, temos deimplementar uma maneira de acionar o comando de impressãoda aplicação. No caso do Word, uma das formas de comandar aimpressão é através do pressionamento das teclas CTRL+P. Maisuma vez, vamos simular uma ação do usuário de forma quenosso documento possa ser impresso.

Para enviar uma seqüência de teclas para um componente denossa aplicação, ou até mesmo para outra aplicação que estárodando, podemos utilizar a função SendKeys, disponível a partirda unit SndKey32.pas, que se encontra dentro da pasta\Info\Extras\SendKeys do CD de instalação do Delphi. A sintaxedessa função prevê como parâmetros a seqüência de teclas a serenviada e um flag, indicando se a função deve aguardar oprocessamento da mensagem referente a cada uma as teclasenviadas antes de enviar a próxima.

A Figura 7 ilustra a utilização da função SendKeys para asimulação do pressionamento da tecla de atalho do comando deimpressão do Word, dessa maneira, o OleContainer exibirá a caixade diálogo de impressão.

Figura 7 – Uso da função SendKeys para a impressão dodocumento.

4. OleContainer para Gravação de Documentos emBanco de Dados

O OleContainer pode ser utilizado para interfacear oarmazenamento de documentos num banco de dados.

Através do uso dos métodos LoadFromStream e SaveToStream,aliados a um objeto TStream, podemos ler documentos noOleContainer a partir de um campo Blob de uma base de dados, bemcomo gravar documentos do OleContainer para o campo da base dedados.

5. Considerações FinaisComo pode ser visto acima, o OleContainer pode facilitar a vida

do programador em muitas situações e, até mesmo, incrementaras aplicações desenvolvidas em Delphi. Um ponto, que pode servisto por muitos como desvantagem para o uso do OleContainer é ofato de que o mesmo causará a execução do Word (ou de outraaplicação) paralelamente ao aplicativo Delphi. No entanto, omesmo ocorreria se fosse necessário utilizar o Word como editorde textos separado da aplicação Delphi, sendo que, nesse caso,ainda teríamos o inconveniente de ficar alternando entre as duasaplicações. Dessa forma, para o usuário, trata-se de uma únicaaplicação rodando, uma única interface e, além do mais, seprecisarmos tratar de alguma forma o conteúdo dos documentoseditados no OleContainer, podemos fazê-lo diretamente, como, porexemplo, a inclusão desse numa base de dados, como foi citadoacima.

Este artigo, bem como a aplicação implementada paraexemplo, limitaram-se a demonstrar o uso do OleContainer apenaspara a criação/edição de documentos do Word. No entanto,utilizando-se dos conceitos aqui abordados e dos métodosempregados para as operações com o OleContainer, pode-se utilizá-lo para a integração com outras aplicações, como, por exemplo,Corel Draw, Excel, Power Point e muitas outras.

Reginaldo Rubens da Silva,Bacharel em Ciência da Computação pelaUniversidade do Vale do Itajaí – UNIVALI.Mestrando em Ciência da Computação naUniversidade Federal de Santa Catarina.Professor Substituto do Curso Técnico em Informáticado Colégio Agrícola de Camboriú (CAC/UFSC).Analista/Programador na Universidade do Vale doItajaí.Co-Autor do Livro Métodos de Ordenação –Implementação, Análise e Desempenho em Delphi.Editora Visual Books.

Sobre o autor

Page 16: Revista The Club Megazine - 06/2003 · Como parte da nova estratégia de seus produtos, a Borland ® lançou recentemente sua primeira IDE para desenvolvimento de aplicações para

MeGAZINEMeGAZINEMeGAZINEMeGAZINEMeGAZINE1 61 61 61 61 6

DelphiDelphiDelphiDelphiDelphi

IntroduçãoSem dúvidas, uma das principais necessidades de uma

aplicação, além de suprir as necessidades do usuário, é o controleàs opções que cada usuário poderá acessar no aplicativo, sendoeste, se bem implementado um diferencial bastante atraente emum sistema.

Neste artigo estaremos demonstrando como implementar umcontrole de usuários, trabalhando com Interbase/Firebird, mas alógica aplicada poderá ser utilizada com qualquer banco de dadosou tabelas desktop.

LógicaA idéia é bem simples! Primeiro, vamos percorrer nosso

formulário e buscar todos os componentes, o quais temosinteresse em controlar, pegar as informações importantes, comoexemplo, nome do formulário onde ele está, seu caption, seu nomee alimentar um treeview criando uma interface bastante simples eintuitiva ao usuário final. Neste treeview ele terá a possibilidade deconfigurar os ítens que determinado usuário poderá acessar ounão.

Estas informações ficarão armazendas em nosso banco dedados e, quando o usuário for efetuar o login na aplicação, vamosverificar primeiramente se o nome do usuário e a senhaconferem com o que estão armazenados, e se sim iremospercorrer todos os ítens pertencentes à este usuário e configuraras opções, habilitando somente os ítens no qual ele possui acessopermitido.

Estrutura das tabelasIremos trabalhar basicamente com duas tabelas, sendo a

primeira onde iremos armazenar as informações principais dosusuários, ou seja, Código, Login, Nome, Senha e Data, a qualchamaremos de USUARIOS. A outra tabela ficará responsávelem armazenar os ítens dos usuários, ou seja, os módulos nos

quais ele terá ou não acesso, onde basicamente sua estruturaserá a seguinte: Código, Sequência, Índice do Menu, Parent, Form, Objeto,Descrição e Permissão. Vamos as estruturas:

CREATE TABLE USUARIOS

(

USU_ID INTEGER NOT NULL,

USU_LOGIN VARCHAR (30) NOT NULL,

USU_NOME VARCHAR (50) NOT NULL,

USU_SENHA VARCHAR (30) NOT NULL,

USU_DATA DATE

);

ALTER TABLE USUARIOS ADD CONSTRAINT PK_USUARIOS

PRIMARY KEY (USU_ID);

CREATE TABLE USUARIOITENS

(

USU_ID INTEGER NOT NULL,

USU_SEQUENCIA INTEGER NOT NULL,

USU_MENUINDEX INTEGER,

USU_PARENT INTEGER,

USU_FORM VARCHAR (200),

USU_OBJETO VARCHAR (255),

USU_DESCRICAO VARCHAR (255),

USU_PERMISSAO CHAR(1) NOT NULL

);

ALTER TABLE USUARIOITENS ADD CONSTRAINT

PK_USUARIOITENS PRIMARY KEY (USU_ID, USU_SEQUENCIA);

ALTER TABLE USUARIOITENS ADD CONSTRAINT

FK_USUARIOITENS_USUARIOS FOREIGN KEY (USU_ID)

REFERENCES USUARIOS (USU_ID) ON DELETE CASCADE;

Crie também um Generator para utilizarmos comoincrementador na tabela de usuários:

Acesso:Acesso:Acesso:Acesso:Acesso:por Alessandro Ferreira, [email protected]

Identificando e controlando usuários no sistema

Page 17: Revista The Club Megazine - 06/2003 · Como parte da nova estratégia de seus produtos, a Borland ® lançou recentemente sua primeira IDE para desenvolvimento de aplicações para

MeGAZINEMeGAZINEMeGAZINEMeGAZINEMeGAZINE 1 71 71 71 71 7

DelphiDelphiDelphiDelphiDelphi

CREATE GENERATOR

GEN_USUARIOS_ID;

Bem, após estamos com o banco dedados pronto e com as tabelas criadas,vamos por a mão na massa e começar aimplementação no Delphi.

Definindo a conexão e oprojeto

Neste exemplo, iremos efetuar aconexão com o Interbase/Firebirdutilizando a dbExpress (disponível a partirdo Delphi 6) por conveniência, mas comomencionei no início deste artigo, esteexemplo poderá ser adaptado àqualquer banco e engine de conexão.

Crie um novo projeto, menu File |New do Delphi e adicione um DataModuleao mesmo, o qual nomearemos dedmAcesso. Insira um componentesqlConnection e nomeie como cnxAcesso econfigure o acesso como mostra a figura1.

Confirme com OK e ative a conexãoalterando a propriedade Connected paraTrue. Vamos aos demais componentes econfigurações:

Figura 1

Page 18: Revista The Club Megazine - 06/2003 · Como parte da nova estratégia de seus produtos, a Borland ® lançou recentemente sua primeira IDE para desenvolvimento de aplicações para

MeGAZINEMeGAZINEMeGAZINEMeGAZINEMeGAZINE1 81 81 81 81 8

DelphiDelphiDelphiDelphiDelphi

Nosso dmAcesso ficará parecido com a Figura2:

Figura 2

Estando configurada a conexão com as tabelas do banco dedados, implemente o Form principal deste nosso projeto adionandoum componente MainMenu e uma ToolBar com algumas opções,como mostra a Figura 3.

Cadastro e Configuração de UsuáriosAgora iremos preparar o “motor” de nosso projeto, ou seja, o

Form onde iremos cadastrar e configurar as permissões para cadausuário.

Neste Form, para facilitarmos o entendimento, insiranovamente os componentes de acesso as tabelas (sqlDataSet,DataSetProvider, ClientDataSet e DataSource) análogo ao que fizemos nodmAcesso, porém declarando a unit referente o dmAcesso na lista deuses deste Form (ex.: uses unDMAcesso) e utilizando a mesmaconexão “cxnAcesso” na propriedade sqlConnection dos componentessqlDataSets. Adicione também um componente PageControl definindoneste duas páginas sendo: “Usuários do Sistema” e “Módulos do Sistema”.

Na primeira “página”, insira DBEdits,DBGrid, DBNavigator, como mostra aFigura 4.

Na segunda “página” iremosutilizar um componente Treeview,porém não utilizaremos o Treeviewnativo do Delphi e sim o TXTreeViewque nos oferece um CheckBox em cadaítem, através do qual o usuário poderámarcar e desmarcar opções nomomento da configuração, veja aFigura 5.

A idéia será cadastrarmos os dados principais do usuário eapós isso uma rotina será disparada para “varrer” todos oscomponentes de um Form especificado e adicionar estes“componentes” como dados detalhes do usuário recém cadastrado,além de preencher o Treeview com as mesmas opções para quepossamos configurar as opções desejadas. Isso tudo irá exigir umpouco de trabalho, porém nada muito complicado, mas simminucioso!

No evento AfterPost do cdsUsuarios iremos fazer achamada da procedure GravaItems_E_PreencheTreeview, conformepoderá ser visualizado na Listagem 1:

procedure TfmModulos.cdsUsuariosAfterPost(DataSet:TDataSet);begin { Confirma gravação } cdsUsuarios.ApplyUpdates(0); { Quando inclui um novo usuário, gera os itens natabela detalhe } if (Estado = dsInsert) and(cdsUsuariosItens.IsEmpty) then GravaItems_E_PreencheTreeview(fmMenu,trvModulos);end;

Listagem 1 – evento AfterPost do cdsUsuarios

O procedimento GravaItems_E_PreencheTreeview recebecomo parâmetros o nome do Form que deverá ser “vasculhado” e onome do Treeview que deverá ser preenchido, como mostra aListagem 2:

procedure GravaItems_e_PreencheTreeview(oFormMenu:TForm; trvModulos: TXTreeView);var i, l: Integer; Node: TTreeNode;

Page 19: Revista The Club Megazine - 06/2003 · Como parte da nova estratégia de seus produtos, a Borland ® lançou recentemente sua primeira IDE para desenvolvimento de aplicações para

MeGAZINEMeGAZINEMeGAZINEMeGAZINEMeGAZINE 1 91 91 91 91 9

DelphiDelphiDelphiDelphiDelphi

Figura 3

Figura 4

Figura 4

begin try { limpa o Treeview } trvModulos.Items.Clear; { Sequencia única para cadaregistro

(poderá ser utilizado um“generator” no banco de dados } Seq := 0;{Varre todos os componentes do Form} with oFormMenu do begin for i := 0 to ComponentCount-1do begin { Se for um MainMenu

(Varre os items do menu) } if Components[i] is TMainMenuthen for l := 0 toTMenu(Components[i]).

Items.Count-1 do

AdicionaItem(GetNodeFromText(TrvModulos, ‘Items do Menu’),TMenu(Components[i]).

Items[l], trvModulos);{ adiciona os outros controles )

if Pos(UpperCase(Components[i].ClassName), OutrosObjetos) > 0 thenAdicionaOutrosControles(TrvModulos,GetNodeFromText(TrvModulos,‘Outras Opções’),TControl(Components[i]));

end; end; finally trvModulos.FullCollapse; end;end;

Listagem 2 – Procedimento GravaItems_E_PreencheTreeview

Observe que são chamados alguns procedimentosauxiliares dentro do GravaItems_E_PreencheTreeview, sendo:

procedure AdicionaItem(pNode:TTreeNode; pMenuItem: TMenuItem;TrvModulos: TXTreeView);

procedure AdicionaOutrosControles(Trv: TXTreeview; pNode: TTreeNode; Controle:

TControl);

Page 20: Revista The Club Megazine - 06/2003 · Como parte da nova estratégia de seus produtos, a Borland ® lançou recentemente sua primeira IDE para desenvolvimento de aplicações para

MeGAZINEMeGAZINEMeGAZINEMeGAZINEMeGAZINE2 02 02 02 02 0

DelphiDelphiDelphiDelphiDelphi

Ambos procedimentos tem por finalidade adicionar controles(ítens) ao Treeview, porém, um específico para ítens de menu e ooutro para os demais componentes, como por exemplo, umTToolButton.

Outro procedimento importante neste contexto é oPreencheTreeview, que tem a finalidade de percorrer os registrosarmazenados no cdsUsuariosItens e preencher o Treeview com osítens anteriormente armazenados, para o usuário posicionado nomomento. Este procedimento recebe dois parâmetros a saber:

procedure PreencheTreeview(trvModulos: TXTreeView;cdsUsuarioItens: TClientDataSet);

O primeiro parâmetro indica o Treeview que irá receberos ítens e o segundo indica o nome do ClientDataSet que deverá serlido. Um detalhe importante que não podemos deixar de abordar,é em relação a criptografia da senha. Bancos de dados como oInterbase/Firebird ou tabelas Paradox podem ser facilmenteabertos pelos espertinhos de plantão, fazendo com que nossocontrole de acesso ao sistema fique vulnerável. Para evitar isso,no evento BeforePost do cdsUsuarios fazemos a criptografia dasenha, como mostra a Listagem 3:

procedure TfmModulos.cdsUsuariosBeforePost(DataSet:TDataSet);var Senha: String;begin { compara senha } Senha :=cdsUsuarios.FieldByName(‘USU_SENHA’).AsString; if (Senha <> edConfSenha.Text) then begin ShowMessage(‘Senha não confere!

Favor digitá-la novamente!’); cdsUsuarios.FieldByName(‘USU_SENHA’).Clear; edConfSenha.Clear; DBEdit_Senha.SetFocus; Abort; end; { guarda estado atual da tabela } Estado := DataSet.State; { atribui código sequencial de um generator } if cdsUsuarios.State = dsInsert then begin cdsUsuarios.FieldByName(‘USU_ID’).AsInteger := AutoInc(‘GEN_USUARIOS_ID’, dmAcesso.cnxAcesso); cdsUsuarios.FieldByName(‘USU_SENHA’).AsString :=

Cript(Senha, ‘CRIPT’); end;end;

Listagem 3 – Evento BeforePost cdsUsuarios

A função CRIPT responsável pela criptografia dos dados estádisponível no dmAcesso que poderá ser encontrado no projeto deexemplo.

Existem vários outros procedimentos utilizados nesta unit,contudo de menor importância e que poderão ser encontrados noprojeto de exemplo referenciado no final deste artigo.

Formulário de LoginBem, o passo final agora é a implementação do formulário de

login, ou seja, onde iremos solicitar o nome do usuário e senha dousuário e partir destes, habilitar o acesso ao sistema,configurando as opções de acordo com o usuário logado. Este Formé bastante simples, como poderá ser visto na Figura 6:

Figura 6

Após o usuário informar o Login e a Senha, faremos avalidação como mostra a Listagem 4:

procedure TfmLogin.BT_OKClick(Sender: TObject);

begin

{ Controle número de tentativas de acesso ao

sistema }

Inc(Tentativas);

if Tentativas > 3 then

begin

ShowMessage(‘Número de tentativas esgotado! ‘);

Application.Terminate;

end;

with dmAcesso do

begin

cdsUsuarios.Close;

sdsUsuarios.Close;

sdsUsuarios.CommandText := ‘select *

from USUARIOS where USU_LOGIN = ‘ +

QuotedStr(edLogin.Text);

sdsUsuarios.Open;

{ verifica se encontrou o Login }

if sdsUsuarios.IsEmpty then

begin

ShowMessage(‘Login não cadastrado!’);

edLogin.SetFocus;

Exit;

end;

{ verifica se a senha está correta }

if edSenha.Text <>

Page 21: Revista The Club Megazine - 06/2003 · Como parte da nova estratégia de seus produtos, a Borland ® lançou recentemente sua primeira IDE para desenvolvimento de aplicações para

MeGAZINEMeGAZINEMeGAZINEMeGAZINEMeGAZINE 2 12 12 12 12 1

DelphiDelphiDelphiDelphiDelphi

Trim(Cript(sdsUsuarios.FieldByName

(‘USU_SENHA’).AsString, ‘DESCRIPT’)) then

begin

ShowMessage

(‘Senha Incorreta, tente novamente!’);

edSenha.SetFocus;

Exit;

end;

{ configura as permissões do usuário }

cdsUsuarios.Open;

with cdsUsuariosItens do

begin

First;

while not EOF do

begin

ConfiguraMenu(Application.MainForm,

FieldByName(‘USU_OBJETO’).AsString,

FieldByName(‘USU_PERMISSAO’).AsString);

Next;

end;

end;

{ se validou OK, não executa o evento

OnCloseQuery }

fmLogin.OnCloseQuery := nil;

{ Fecha o form de senha }

Close;

end;

end;

A validação consiste em executar um Select na tabela deusuários, passando como parâmetros o Login e a Senha digitadospelo usuário, que serão descriptografados para serem utilizandosneste Select. Se este Select retornar positivo, iremos percorrer osregistros da tabela de ítens do usuário e fazer a configuração dasopções do mesmo através da chamada do procedimentoConfiguraMenu, que pode ser visualizado na Listagem 7:

procedure ConfiguraMenu(oForm: TForm; Item,

Permissao: String);

var

C: TComponent;

begin

C := oForm.FindComponent(Item);

try

if (C <> nil) then

begin

{ configura itens do menu }

if C is TMenuItem then

begin

if Permissao = ‘S’ then

TMenuItem(C).Enabled := True

else

TMenuItem(C).Enabled := False;

end

else { configura outros objetos } begin

if Permissao = ‘S’ then

TMostraProp(C).Enabled := True

else

TMostraProp(C).Enabled := False;

end;

end;

finally

C := nil;

end;

end;

Listagem 7

Observe que os parâmetros informados são o nome do Formonde serão pesquisados e configurados os componentes. Atravésdeste parâmetro, executamos um FindComponent utilizando oparâmetro Item que contém o nome do componente à serconfigurado e por fim, se o componente for encontrado (variável C<> Nil) e o parâmetro Permissao for igual a “S”, o referidocomponente será habilitado. Observe que nos caso decomponentes que não sejam TMenuItem, fazemos um typecast com aclasse TmostraProp declarada na mesma unit apenas para teracesso de forma genérica as propriedades e métodos protegidos docomponente em questão.

ConclusãoNeste pequeno artigo procurei passar uma idéia básica de

uma das abordagens possíveis para o controle de acesso deusuários à um aplicativo. A criptografia utilizada foi bastantesimples e somente utilizada no campo senha, mas de acordo como nível de seus usuários e com a relevância dos módulos e dadoscontidos na aplicação, essa criptografia deverá se estender aosdemais campos das tabelas, obtendo-se assim total integridade esegurança deste controle. Alguns procedimentos não foramabordados no artigo, mas o projeto de exemplo contémcomentários em praticamente todos os procedimentos. Comcerteza este é apenas um “ponta-pé” inicial, o qual servirá de basepara várias outras implementações e melhorias.

Espero que todos tenham gostado, lembrando que dúvidas esugestões serão benvidas. Abraços e até a próxima.

O componente TXTreeView que foi o Treeview utilizado noprojeto de exemplo, acompanha o projeto de exemplo. O projeto deexemplo referente este artigo está disponível para downloadem:http://www.theclub.com.br/revista/download/ControleAcesso.zip.

Page 22: Revista The Club Megazine - 06/2003 · Como parte da nova estratégia de seus produtos, a Borland ® lançou recentemente sua primeira IDE para desenvolvimento de aplicações para

MeGAZINEMeGAZINEMeGAZINEMeGAZINEMeGAZINE 2 32 32 32 32 3

Clipper/DelphiClipper/DelphiClipper/DelphiClipper/DelphiClipper/Delphi

Um problema que vez por outra aparece para osdesenvolvedores Delphi é a migração de sistemas antigos, escritosem Clipper, para Delphi: são sistemas implantados há váriosanos na empresa, já com diversas “atualizações” e uso bastantedifundido.

Sua substituição não pode ser feita de qualquer maneira, poiso sistema está implantado em praticamente todos osdepartamentos e os arquivos dbf contém a vida da empresa nosúltimos 10 a 15 anos.

Além disso, o desenvolvimento de um novo sistema, do portedo que está implantado, levaria muito tempo para ser finalizado.Como fazer para que o novo sistema conviva pacificamente com oantigo enquanto os módulos vão sendo desenvolvidos ? Énecessário que ambos sistemas acessem e atualizem os mesmosdados, de maneira transparente, sem conflitarem entre si.

Pensando numa soluçãoA primeira idéia que vem à mente é usar a BDE com

arquivos DBF. Esta abordagem tem o problema de não permitiro uso dos índices nativos do Clipper (ntx) e ter problemas delocking - o sistema de travamento de registros da BDE não é omesmo do Clipper. Usando-se a RDD MDX, para dBase IV,disponível no Clipper 5.01, 5.2 e 5.3 pode resolver o problema deíndices, mas não resolve o problema de travamento de registros.

Além disso, o driver BDE para arquivos dBase não trazmuita confiabilidade, as reindexações constantes são aindanecessárias. O que parecia uma solução passa a ser um problemaainda maior.

A segunda idéia é abandonar definitivamente os arquivosdbf, passando para uma solução cliente/servidor, muito maisrobusta - MS-SQL Server, Oracle, Interbase, MySql, PostgreSQLsão alguns bancos de dados sugeridos quando surge esta idéia.Sem dúvida, o uso de bancos de dados como estes traria grandesvantagens ao sistema: maior confiabilidade e robustez, maiorvelocidade e menor tráfego na rede. Porém há um problema: oque fazer enquanto o sistema está sendo desenvolvido ? Osistema, neste caso, deve ser desenvolvido de uma única vez eimplantado totalmente: um dia, os usuários, ao chegarem ao

trabalho e ligarem seu computados, ao invés de encontrarem asua velha e familiar tela DOS, encontrarão um sistema novinhoem folha, escrito em Delphi, acessando um banco de dadosCliente/Servidor.

Esta idéia, na teoria, é excelente, mas na prática...Imaginemsó quando, neste dia, os chamados de suporte começarem aaparecer de todos os departamentos da empresa - partes doprograma que não funcionam, consolidações que não foramfeitas ou estão incorretas, operadores que não sabem operar osistema (há pouco tempo atrás, alguns operadores nem sabiammexer no mouse, agora isto acontece menos). Tudo isto, além doproblema do que fazer com os dados antigos: deve-se migrá-lospara a nova plataforma com o mínimo de perdas possível. Semdúvida, esta é uma idéia viável, embora de difícil implementação.

Uma abordagem mais convenienteO ideal seria uma solução que permitisse usar os arquivos

dbf antigos, com o mínimo de modificações no sistema Clipper (sepossível, nenhuma mudança) e que tivesse confiabilidade paranão trazer mais problemas. Desta maneira, o sistema poderia serdesenvolvido modularmente, com cada módulo sendo testadoantes de ser implantados e com os problemas da implantaçãosolucionados antes da passagem para o próximo módulo. Umaopção é o Advantage Database Server, que permite acessar astabelas dbf com a confiabilidade de um banco de dados Cliente/Servidor.

O Advantage Database Server (ADS) não é uma ferramentanova (ela está na versão 6). Ela é uma ferramenta Cliente/Servidor multiplataformas, que permite acessar tabelas dbf.Como todas ferramentas Cliente/Servidor, consiste de duaspartes, o cliente e o servidor, que se comunicam pela rede, usandoo protocolo IP ou IPX. O ADS, embora acesse tabelas dbf,trabalha de maneira muito diferente do Clipper ou do dBase.

O Clipper e o dBase são ferramentas desktop, onde todo oprocessamento é feito na estação e o servidor é um meroarmazenador de informações. Por exemplo, quando queremossaber qual o total de vendas de ontem, devemos trazer a tabela devendas do servidor para a estação, totalizar as vendas de ontem e

Do Clipper para o DelphiDo Clipper para o DelphiDo Clipper para o DelphiDo Clipper para o DelphiDo Clipper para o DelphiMigração tranqüila com o Advantage Database ServerMigração tranqüila com o Advantage Database ServerMigração tranqüila com o Advantage Database ServerMigração tranqüila com o Advantage Database ServerMigração tranqüila com o Advantage Database Server

Por Bruno Sonnino

Page 23: Revista The Club Megazine - 06/2003 · Como parte da nova estratégia de seus produtos, a Borland ® lançou recentemente sua primeira IDE para desenvolvimento de aplicações para

MeGAZINEMeGAZINEMeGAZINEMeGAZINEMeGAZINE2 42 42 42 42 4

mostrar o resultado. Isto faz que o tráfego da rede seja muitogrande, pois toda a tabela passa pela rede. Além disso, o tempopara se obter o resultado depende também da velocidade da rede,além de ser completamente dependente da capacidade deprocessamento da estação cliente.

Outro problema que ocorre com freqüência é a necessidade dereindexação: como todo o processamento é feito no cliente, aoinserir alguma informação, o índice é atualizado no cliente. Casoa estação saia do ar, o dbf estará atualizado, mas o índice não,obrigando a reindexação. Além destes problemas, outro, nãodiretamente ligado à arquitetura do Clipper é a ausência dogerenciamento de transações: quando a impressora trava nomeio da nota fiscal, parando o sistema, como saber o que foigravado e o que não foi ?

Cliente/Servidor com o ADSCom as ferramentas Cliente/Servidor, todas as informações

são processadas no servidor e apenas os resultados sãotransferidos para o cliente. Ao invés do cliente receber toda atabela e separar os dados que lhe interessa, ele requisita aoservidor o que deseja, o servidor processa e envia os resultados.Isto, além de reduzir o tráfego na rede, aumenta a confiabilidade:todo o processamento é feito pelo servidor, que gerencia asrequisições, trava os registros internamente, mantém os índices epode controla as transações.

Caso uma estação saia do ar, isto não afeta os índices, quesão mantidos pelo servidor e uma impressora travada no meio danota faz que toda a transação seja desfeita, voltando ao estadoanterior à emissão da nota. Temos assim o aumento davelocidade, tanto de processamento como da rede e deconfiabilidade do sistema, pois não precisamos nos preocupar comreindexações ou gravações pela metade.

Isto não é característica deste ou daquele gerenciador debancos de dados, mas de todos os gerenciadores de bancos dedados Cliente/Servidor. O que diferencia um do outro são ascaracterísticas internas, sua velocidade, capacidade de gerenciarmais ou menos usuários e maneira de acesso a dados.

O ADS, como as outras ferramentas, também tem estascaracterísticas e, pelo fato de acessar tabelas dbf, traz a robusteze confiabilidade ao acesso dos arquivos dbf. Ela é umaferramenta multi-plataforma, existem versões de servidores paraWindows (NT/2000/XP ou 95/98/ME), Linux ou Netware. Osclientes podem ser feitos com Clipper (mais adiante veremoscomo transformar uma aplicação Clipper para que ela se tornecliente de um servidor ADS), FiveWin, Delphi/Kylix, ou qualqueroutra linguagem que possa utilizar a ODBC ou ADO. Uma vezadquirido servidor ADS, pode-se usar qualquer clientegratuitamente. O cliente é completamente independente doservidor e pode estar em plataforma completamente diferentedeste. Por exemplo, podemos criar um cliente Kylix que acessa o

servidor Windows ou então um cliente Delphi que acessa oservidor Linux ou Netware. A comunicação entre eles é feita peloprotocolo IP ou IPX.

Desta maneira, pode-se adquirir o ADS para desenvolver amigração do sistema Clipper para Delphi e, enquanto isso nãoacontece, transformar o sistema Clipper para cliente/servidor,aumentando sua velocidade e confiabilidade, sem custo adicional.

O ADS permite utilizar os índices e memos Clipper (NTX/DBT) ou FoxPro (CDX/FPT). Caso você esteja usando os índicesNTX em sua aplicação Clipper e não queira mudá-la, podecontinuar usando-a simultaneamente com os módulos jáconvertidos sem nenhum problema.

Convertendo uma aplicação Clipper para ADSAs aplicações Clipper não necessitam de nenhuma conversão

para poderem acessar os mesmos arquivos que uma aplicaçãoDelphi com ADS. Porém, é recomendado que se faça a conversão,para poder aproveitar dos recursos que o ADS oferece: consultasno servidor, maior robustez e confiabilidade e gerenciamento detransações, além de evitar a corrupção de dados devido ao acessoconcorrente aos dbfs pela aplicação Delphi, com ADS e Clipper,sem ADS.

A maneira mais fácil de converter a aplicação é fazendo alinkedição com as bibliotecas do ADS. Não é necessária nenhumamodificação do código fonte e ele passa a poder usar os recursosdo ADS. Esta linkedição faz com que o programa Clipper, aoinvés de usar a RDD padrão (DBFNTX ou DBFCDX), passe ausar a RDD do ADS (DBFCDXAX ou DBFNTXAX),comunicando-se com o servidor para efetuar as operações nastabelas.

Para isto, basta incluir o objeto DBFCDXAX.OBJ ouDBFNTXAX.OBJ, a biblioteca DBFAXS.LIB e as bibliotecas decomunicação no script de linkedição. Por exemplo, para linkeditaro programa MEUPROG com o rtlink, bastaria um comandocomo o seguinte:

rtlink fi meuprog,dbfcdxax lib

dbfaxs,axscomm,clipper,extend,terminal

O programa estaria pronto para acessar o ADS. Umaobservação deve ser feita neste comando: as variáveis LIB e OBJde ambiente devem conter os diretórios onde estão os objetos ebibliotecas do ADS. O comando acima é valido quando se usa acomunicação IPX com o servidor. Para usar comunicação IP,você deve usar a biblioteca axipcomm ao invés de axscomm edeve carregar o programa ADSDOSIP.EXE antes de iniciar aaplicação (este programa pode ser carregado quando se inicializao Windows). Com isso, você estará acessando o servidor e apenasos dados necessários passarão a trafegar pela rede. Quando umaestação travar ou cair, não haverá mais a necessidade de

Clipper/DelphiClipper/DelphiClipper/DelphiClipper/DelphiClipper/Delphi

Page 24: Revista The Club Megazine - 06/2003 · Como parte da nova estratégia de seus produtos, a Borland ® lançou recentemente sua primeira IDE para desenvolvimento de aplicações para

MeGAZINEMeGAZINEMeGAZINEMeGAZINEMeGAZINE 2 52 52 52 52 5

reindexação.Um segundo passo é a utilização de comandos específicos do

ADS, como o controle de transações ou criptografia de tabelas. OADS introduz os novos comandos BEGIN TRANSACTION,COMMIT TRANSACTION e ROLLBACK TRANSACTION, parao controle de transações. Para usar estes e outros comandos, vocêdeve incluir o arquivo DBFCDXAX.CH no arquivo fonte, com#include “dbfcdxax.ch”, recompilá-lo e linkeditar o executávelnovamente. Desta maneira, você passa a ter acesso aos comandospróprios do ADS.

O terceiro passo é otimizar as pesquisas e a recuperação dedados, fazendo que os filtros e pesquisas sejam processados noservidor e não no cliente. Este é um passo mais demorado, querequer um estudo mais detalhado do código, verificando filtros,índices, mudando índices NTX para CDX (o ADS usa osmúltiplos índices do CDX para otimização de pesquisas, o que nãofaz com o NTX. Desta maneira, é melhor usar o driver CDX aoinvés do NTX).

ADS e DelphiPara usar o ADS com Delphi, você tem uma série de opções:· Usar a BDE e o driver ODBC· Usar o driver ADO para ADS· Usar a API do ADS para acesso direto· Usar o TADSDatasetDentre estas, sem dúvida nenhuma, o TADSDataset é o

melhor, pois acessa diretamente o ADS, permite usar os recursosque o ADS oferece, com uma interfaceconhecida. Para o acesso a dados, estãodisponíveis os componentes TADSTable,TADSQuery e TADSStoredProc, muitosemelhantes aos componentes de acesso adados incluídos com o Delphi.

Você deve estar se perguntado por queum componente TADSStoredProc: osarquivos DBF não tem stored procedures. OADS permite que sejam criadas funções emDLLs, e usadas como Stored Procedures.Desta maneira, você pode criar uma funçãonuma DLLs (ou SO, em Kylix) e usa-la noADS, com o componenteTADSStoredProcedure.

Além destes componentes, você aindatem o TADSDictionary, um dicionário dedados, que agrupa as tabelas, trazendo aindaoutras características aos dados:

· Integridade referencial· Valores default para campos· Restrições de valores de campos· Views

Com o uso do TADSDictionary você passa a ter os mesmosrecursos de um banco de dados completo, definindo suas regrasde negócio no próprio banco de dados. Uma coisa deve ser notadaaqui: embora o dicionário de dados traga estes recursos, ainda épossível acessar os arquivos dbf sem ele, possibilitando ainconsistência de dados. Para ter estes recursos integrados aobanco de dados, você deve usar o formato proprietário de arquivo,ADT que, porém, é incompatível com o Clipper.

Exemplo de acessoOs componentes de acesso a dados são gratuitos e vêm com os

fontes. Você pode instalá-los nas diversas versões do Delphi 32bits, bem como no Kylix, para criação de clientes Linux. Uma vezinstalados, eles ficam na guia Advantage, como mostrado naFigura 1

A partir daí, você pode usá-los como os outros componentes deacesso a dados. Para exemplificar seu uso, crie um novo projeto einclua um TADSTable. Configure sua propriedadeDatabaseName para ADTDemoData. Da mesma maneira que naBDE, você pode configurar aliases, apontando para umdeterminado diretório. Eles podem ser configurados usando oAdvantage Data Architect, mostrado na Figura 2.

Figura 1 - Guia Advantage de componentes

Figura 2 - Advantage Data Architect configurando Aliases

Clipper/DelphiClipper/DelphiClipper/DelphiClipper/DelphiClipper/Delphi

Page 25: Revista The Club Megazine - 06/2003 · Como parte da nova estratégia de seus produtos, a Borland ® lançou recentemente sua primeira IDE para desenvolvimento de aplicações para

MeGAZINEMeGAZINEMeGAZINEMeGAZINEMeGAZINE2 62 62 62 62 6

Uma vez configurados osaliases, eles podem ser usados comos componentes do Delphi. Comovocê pode ver na Figura 2, existemtrês tipos de tabelas que o ADSsuporta, ADT/ADI/ADM, DBF/CDX/FPT e DBF/NTX/DBT. Os doisúltimos usam as tabelas dbfnormais e o primeiro usa umformato de tabelas proprietário quetraz algumas vantagens sobre oDBF, mas não é suportado peloClipper. Caso você queiracompartilhar tabelas com clientesClipper e Delphi, este tipo de tabelasnão pode ser usado.

Voltando ao projeto, configure apropriedade TableName paraproducts.adt. O Alias queescolhemos é um alias para tabelasADT. Configure a propriedadeActive para True.

Adicione um TDataSource,configurando a propriedade DataSet paraADSTable1. Finalmente, inclua umaTDBGrid, configurando a propriedadeDataSource para DataSource1. Os dadosda tabela devem ser mostrados na grade,como vemos na Figura 3.

Como você pode ver, a maneira detrabalho é exatamente igual àquela comoutras engines de dados. Você pode usar ocomponente TADSQuery para criarconsultas SQL, da mesma maneira quecom o componente TQuery. As consultassão processadas pelo servidor e seuresultado retornado à aplicação.

A aplicação Clipper a ser migradaPara mostrar a possibilidade de migração do Clipper para o

Delphi, iremos usar uma aplicação simples em Clipper, quepermite editar e filtrar um cadastro de produtos. Este é umexemplo da aplicação que está rodando na empresa há váriosanos e que deve ser portada para Windows. Como normalmenteestas aplicações são muito grandes, não consistindo de ummódulo apenas, elas são portadas aos poucos, com os dados sendomantidos em comum pela aplicação antiga e nova.

O programa Clipper está mostrado na Listagem 1. Ele usa odriver DBFCDX, que acessa os índices FoxPro CDX e os memos

Figura 4 - Tela do cadastro de produtos

Figura 3 - Projeto de exemplo com ADSTable

FPT. Para compilá-lo e linkeditá-lo, foram usados os seguintescomandos:

set include=c:\clip52\include

set lib=c:\clip52\lib

clipper produtos /m/n/w/a/b

rtlink fi produtos lib

clipper,extend,dbfcdx,terminal

Uma vez compilado, ele fica com uma tela semelhante àFigura 4.

Clipper/DelphiClipper/DelphiClipper/DelphiClipper/DelphiClipper/Delphi

Page 26: Revista The Club Megazine - 06/2003 · Como parte da nova estratégia de seus produtos, a Borland ® lançou recentemente sua primeira IDE para desenvolvimento de aplicações para

MeGAZINEMeGAZINEMeGAZINEMeGAZINEMeGAZINE 2 72 72 72 72 7

Este programa permite fazer a manutenção do cadastro deprodutos, incluindo, alterando ou excluindo informações. Pode-seainda filtrar os dados do cadastro, usando-se a tecla F10. Épedida uma descrição e são filtrados todos os registros que temdescrições iniciadas com o valor selecionado.

Usando ADS na aplicação ClipperPara usar nossa aplicação Clipper em conjunto com a

aplicação Delphi acessando o ADS não precisaríamos fazernenhuma modificação, mas é interessante mudá-la para que elatambém possa usar o ADS e com isso se beneficiar das vantagensque o ADS traz, além de permitir que os dados sejam gerenciadosde maneira centralizada, trazendo ainda mais confiabilidade erobustez.

Para isto, devemos fazer duas modificações:· Alterar o código fonte, removendo as chamadas que são

relativas à requisição do uso da RDD DBFCDX, recompilando-o· Efetuar a linkedição, usando as bibliotecas ADSPara o primeiro passo, devemos apenas comentar as duas

linhas do início do programa, que requerem o uso da RDD efazem-na como padrão para a aplicação:

request dbfcdxRDDSetDefault(“dbfcdx”)

Após isto, devemos recompilar a aplicação e efetuar alinkedição, com os comandos:

set obj=c:\ads\clipper\clip52set lib=c:\clip52\lib;c:\ads\clipper\clip52;

c:\ads\clipper\comm;c:\ads\clipper\adsdosiprtlink fi produtos,dbfcdxax libdbfaxs,axipcomm,clipper,extend,terminal

Os primeiros dois comandos definem variáveis de ambientecom os diretórios onde estão localizados os arquivos objeto eas bibliotecas necessárias. O terceiro comando efetua alinkedição usando as bibliotecas do ADS e a comunicação IPcom o servidor. Note que, para usar a comunicação IP,precisamos carregar o programa ADSDOSIP.EXE antes deexecutar nosso programa. Como este programa funciona emWindows 32 bits, um programa Clipper usandocomunicação IP só pode rodar em estações Windows 32 bits.Para executar a aplicação Clipper em estação Dos, você deveusar a comunicação IPX.

Ao executar o programa novamente, estaremosacessando o banco de dados usando o ADS, de maneiracliente/servidor. Se quisermos, podemos otimizar o uso doservidor, alterando comandos, utilizando funções específicasdo ADS ou implementando o gerenciamento de transações.Porém, como queremos apenas aposentar o programaClipper, migrando-o para Delphi, estas modificações são

suficientes para nossos objetivos. Podemos iniciar odesenvolvimento da aplicação Delphi.

Criando a aplicação DelphiUm primeiro passo antes da criação da aplicação

propriamente dita é a criação de um alias apontando para nossosdados. Desta maneira, teremos flexibilidade de alteração dalocalização: caso queiramos mudar de uma base de dados de testepara uma base de dados de produção, basta alterar a localizaçãodo alias, sem precisar recompilar o programa Delphi.

Isto é feito com o Advantage Data Architect, usando a opçãoTools/Alias Configuration. A Figura 2 mostra a tela deconfiguração. Selecione o botão New Alias, e dê o nome deProdutos ao novo alias. Escolha o diretório onde estão os dados e otipo DBF/CDX/FPT. Salve o alias e feche o Advantage DataArchitect.

Abra o Delphi e crie uma nova aplicação. Coloque umcomponente TADSTable na Form, alterando a propriedadeDatabaseName para Produtos, o alias que criamos.

Altere a propriedade TableName para produtos.dbf e dê umclique duplo na tabela para abrir seu editor de campos. Cliquecom o botão direito do mouse e selecione Add Fields, paraadicionar os campos no editor. Selecione todos os campos, menosDATA_CAD e DATA_CPRA e arraste-os para a Form, deixando-os a uma distância de 0.5 centímetro do topo e da esquerda. Sãocriados labels e edits para todos os campos.

Altere a propriedade Caption da Form para Manutenção deProdutos e as propriedades Caption dos Labels, fazendo-os maisamigáveis. Altere a propriedade ReadOnly do edit relativo aocódigo para True e mude sua propriedade Color para clBtnFace.Insira 5 botões abaixo dos edits, alterando a propriedade Captiondeles para Inclui, Exclui, Anterior, Próximo e Filtra. Insira umlabel na parte direita da tela, ao lado do código, alterando suapropriedade Caption para Filtrado e sua propriedade Visible paraFalse. Você deve ter uma tela semelhante à da Figura 5.

Figura 5 - Tela de Manutenção de Produtos em Delphi

Clipper/DelphiClipper/DelphiClipper/DelphiClipper/DelphiClipper/Delphi

Page 27: Revista The Club Megazine - 06/2003 · Como parte da nova estratégia de seus produtos, a Borland ® lançou recentemente sua primeira IDE para desenvolvimento de aplicações para

MeGAZINEMeGAZINEMeGAZINEMeGAZINEMeGAZINE2 82 82 82 82 8

Em Clipper, configuramos o ambiente de trabalho no código,com comandos como “SET DELETED ON”. No Delphi, temos ocomponente TADSSettings, que permite configurar o formato dadata e se os registros excluídos são mostrados ou não. Insira umcomponente TADSSettings e altere sua propriedade DateFormatpara dd/mm/yy e sua propriedade ShowDeleted para False.

No evento OnCreate da Form, coloque o seguinte código, paraabrir a tabela:

procedure TForm1.FormCreate(Sender: TObject);

begin

ADSTable1.Open;

end;

Feche a tabela no evento OnDestroy com o código:

procedure TForm1.FormDestroy(Sender: TObject);

begin

ADSTable1.Close;

end;

Quando inserimos um novo registro, precisamos de um novocódigo de produto, gerado automaticamente. Para isso, colocamosmais uma tabela, que nos dá o último código. Usaremos nestecaso uma TADSQuery que recupera o maior código da tabela,adicionando 1 a ele. Coloque na Form uma TADSQuery,configurando a propriedade DatabaseName para Produtos e apropriedade SQL para:

select max(codigo) as NovoCod from produtos

Dê um clique duplo na Query, para abrir o editor de campos eadicione o campo NovoCod.

A alteração de campos quando o dado é inserido normalmenteé feito no evento OnNewRecord da tabela. Selecione este eventoda tabela ADSTable1, colocando o seguinte código:

procedure TForm1.AdsTable1NewRecord(DataSet:

TDataSet);

begin

ADSTable1Data_Cad.Value := Date;

ADSQuery1.Open;

ADSTAble1Codigo.AsInteger :=

ADSQuery1NovoCod.AsInteger+1;

ADSQuery1.Close;

end;

Com isso, podemos colocar o código do evento OnClick dobotão Inclui:

procedure TForm1.Button1Click(Sender: TObject);

begin

ADSTable1.CheckBrowseMode;

ADSTable1.Insert;

ADSTable1.Post;

end;

Gravamos os dados pendentes, inserimos um novo registro eem seguida, gravamos este novo registro. O motivo de fazermosisto é devido ao fato de como estamos obtendo o novo código -pegamos o maior código disponível no momento. Se nãogravássemos imediatamente, um segundo usuário poderia obtero mesmo código enquanto estivéssemos editando os dados.Poderíamos evitar isso mantendo uma tabela auxiliar com oúltimo código, mas desta maneira estamos mantendocompatibilidade com nosso programa Clipper.

O código do botão Exclui é:

procedure TForm1.Button2Click(Sender: TObject);

begin

ADSTable1.CheckBrowseMode;

if MessageDlg(‘Confirma exclusão do

produto ?’,mtConfirmation,[mbYes,mbNo],0) =

mrYes then

ADSTable1.Delete;

end;

Solicitamos a confirmação da exclusão e, em caso afirmativo,excluímos o produto. Para os códigos dos botões Anterior ePróximo, coloque o seguinte:

procedure TForm1.Button3Click(Sender: TObject);

begin

ADSTable1.CheckBrowseMode;

ADSTable1.Prior;

end;

procedure TForm1.Button4Click(Sender: TObject);

begin

ADSTable1.CheckBrowseMode;

ADSTable1.Next;

end;

O código do botão de filtragem pergunta a descrição e filtra osdados, conforme o que foi solicitado. A indicação Filtrado émostrada na tela, quando os dados são filtrados:

procedure TForm1.Button5Click(Sender: TObject);

var

Clipper/DelphiClipper/DelphiClipper/DelphiClipper/DelphiClipper/Delphi

Page 28: Revista The Club Megazine - 06/2003 · Como parte da nova estratégia de seus produtos, a Borland ® lançou recentemente sua primeira IDE para desenvolvimento de aplicações para

MeGAZINEMeGAZINEMeGAZINEMeGAZINEMeGAZINE 2 92 92 92 92 9

Filtro : String;

begin

Filtro := InputBox(‘Filtro de

produtos’,’Descrição’,’’);

if Filtro = ‘’ then begin

ADSTable1.Filtered := False;

Label6.Visible := False;

ADSTable1.First;

end

else begin

ADSTable1.Filter := ‘Descricao =

‘’’+UpperCase(Filtro)+’*’’’;

ADSTable1.Filtered := True;

Label6.Visible := True;

ADSTable1.First;

end;

end;

Desta maneira, nossa aplicação está encerrada. Ao executá-la, você deverá ter uma tela como a da Figura 6.

Figura 6 - Aplicação Clipper Portada para Delphi

ConclusõesUma das grandes dificuldades ao portar uma aplicação

escrita em Clipper para Delphi é o que fazer com as tabelas queestão sendo usadas enquanto o sistema está sendo portado. OADS permite compatibilizar o uso de Clipper e Delphisimultaneamente, resolvendo também o problema da migraçãodos dados.

Enquanto se está desenvolvendo o sistema em Delphi, pode-secontinuar a usar o sistema em Clipper, com maior robustez econfiabilidade, além da diminuição do tráfego na rede. O ADSpermite elaborar sistemas com componentes semelhantes àqueles

disponíveis no Delphi, usando inclusive os mesmos componentesdata-aware para a edição dos dados.

Outro benefício do ADS é a possibilidade de portar o sistemapara o Kylix. Caso criássemos uma aplicação CLX, bastariarecompilá-la em Kylix para obtermos uma aplicação Linuxacessando o banco de dados.

“Artigo originalmente publicado na revista ClubeDelphi 37.Cedido como parceria para a The Club pelos editores destapublicação, esse artigo está garantido sob as leis de Copyright”

Listagem 1 – Programa Clipper

#include “inkey.ch”

procedure Produtoslocal _tsav :=savescreen(0,0,24,79),nTecla,cDescr,NovoCod,; wnom,wfor,west,wpre,wcom,wgrufieldcodigo,descricao,fornec,preco,val_cpra,grupo,estoquememvar getlistrequest dbfcdxRDDSetDefault(“dbfcdx”)set deleted onset date britishtela(‘Manuten‡„o de Produtos’)select 1net_use(“produtos”)set index to produtosset order to codigo

wnom := space(40)wfor := space(3)wgru := space(2)wpre := wcom := west := 0select 1go topsetkey(K_CTRL_INS,{|| readkill(.t.)})setkey(K_CTRL_DEL,{|| readkill(.t.)})setkey(K_CTRL_PGUP,{|| readkill(.t.)})setkey(K_CTRL_PGDN,{|| readkill(.t.)})setkey(K_F10,{|| readkill(.t.)})while .t. @ 24,0 say ‘Ctrl-Ins - Insere Ctrl-Del - ApagaPgUp - Ant PgDn - Pr¢x F10 - Filtra’ wnom = descricao wfor = str(fornec,3)

Sobre o autorBruno SonninoÉ desenvolvedor cliente/servidor certificado pela Borland

Brasil e autor dos livros “Desvendando Aplicações comDelphi 6”, “Kylix – Delphi para Linux” e “365 Dicas deDelphi”, além de criador de diversos utilitários publicados nosite PC Magazine norte-americana (www.pcmag.com). Podeser contatado pelo e-mail: [email protected].

Clipper/DelphiClipper/DelphiClipper/DelphiClipper/DelphiClipper/Delphi

Page 29: Revista The Club Megazine - 06/2003 · Como parte da nova estratégia de seus produtos, a Borland ® lançou recentemente sua primeira IDE para desenvolvimento de aplicações para

MeGAZINEMeGAZINEMeGAZINEMeGAZINEMeGAZINE3 03 03 03 03 0

wpre = preco west = estoque wcom = val_cpra wgru = grupo @ 2, 5 SAY “C¢digo : “+str(Codigo,6,0) @ 4, 5 SAY “Descri‡„o :” get wnom picture “@!” @ 6, 5 SAY “Fornecedor :” get wfor @ 8, 5 SAY “Pre‡o Venda :” get wpre picture “@E999,999,999.99” @ 10, 5 SAY “Pre‡o Custo :” get wcom picture “@E999,999,999.99” @ 12, 5 SAY “Grupo Prod. :” get wgru @ 14, 5 SAY “Estoque :” get west picture “999” read nTecla := lastkey() rec_lock() replace descricao with wnom,fornec with val(wfor),; preco with wpre,val_cpra with wcom,grupo withwgru,estoque with west unlock if nTecla = K_CTRL_INS go bottom NovoCod := Codigo+1 add_rec() replace codigo with NovoCod,data_cad with date() unlock elseif nTecla = K_CTRL_DEL if Alert(‘Confirma exclus„o ?’,{‘Sim’,’N„o’}) ==1 rec_lock() delete unlock go top endif elseif nTecla = K_PGUP skip -1 elseif nTecla = K_PGDN skip elseif nTecla = K_CTRL_PGUP go top elseif nTecla = K_CTRL_PGDN go bottom elseif nTecla = K_F10 @ 24,0 clear to 24,79 cDescr := space(40) @ 24,0 say ‘Descri‡„o :’ get cDescr picture “@!” read @ 24,0 clear to 24,79 if empty(cDescr) set filter to go top @ 0,70 to 0,78 double else set filter to descricao = trim(cDescr) go top @ 0,70 say “Filtrado” if eof() Alert(‘Registro n„o encontrado’)

set filter to go top @ 0,70 to 0,78 double endif endif elseif nTecla = K_ESC exit endifenddoclose databaserestscreen(0,0,24,79,_tsav)return

procedure Tela(Titulo)@ 0,0 clear to 24,79@ 0,0 to 23,79 double@ 0,10 say ‘ ‘ +Titulo+’ ‘return

procedure net_use(Arquivo)local cSav := savescreen(24,0,24,79)@ 24,0 clear to 24,79@ 24,0 say “Abrindo arquivo “+Arquivo+”....”while .t. use (Arquivo) shared if .not. neterr() restscreen(24,0,24,79,cSav) return endif inkey(1)enddoreturn

procedure rec_locklocal nReg := recno(),cSav := savescreen(24,0,24,79)@ 24,0 clear to 24,79@ 24,0 say “Travando registro “+str(nReg,6,0)+”....”while .t. if dbRLock(nReg) restscreen(24,0,24,79,cSav) return endif inkey(.5)enddoreturn

procedure add_reclocal cSav := savescreen(24,0,24,79)@ 24,0 clear to 24,79@ 24,0 say “Adicionando registro....”while .t. append blank if .not. neterr() restscreen(24,0,24,79,cSav) return endif inkey(0.5)enddoreturn

Clipper/DelphiClipper/DelphiClipper/DelphiClipper/DelphiClipper/Delphi