Upload
trinhdieu
View
233
Download
4
Embed Size (px)
Citation preview
Revista The Club Megazine - 01/2004A 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® 2004
MeGAZINEMeGAZINEMeGAZINEMeGAZINEMeGAZINE 33333
EDITORIALEDITORIALEDITORIALEDITORIALEDITORIAL
Editorial
Celso Jefferson PaganelliPresidente - The Club
Editorial ............................................................................ 03Write Printer - Criando impressões rápidas para o Delphi ... 04Trabalhando com eventos ................................................. 14Retrospectiva .................................................................... 16Intraweb - Programação Alternativa .................................. 18Usando o Object Repository .............................................. 24Perguntas & Respostas ...................................................... 26
THE CLUBAv. Celso Ferreira da Silva, 190
Jd. Europa - Avaré - SP - CEP 18.707-150Informações: (0xx14) 3732-3689
Suporte: (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® 2004
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’Anna
ColaboradoresEmerson Facunte
Delphi é marca registrada da Borland International, asdemais marcas citadas são registradas pelos seus
respectivos proprietários.
Primeiramente, gostaria de desejar à todos um 2004 cheio de muito sucesso erealizações e que possamos estar juntos por mais este ano que se inicia!
2004 com certeza será marcado por muitas novidades, começando pelo Delphi 8 quejá está pronto e segundo informações extra-oficiais, sua versão trial estará disponívelaté o final deste mês de janeiro. Nós já tivemos a oportunidade de fazer um test-drivenesta versão, e sinceramente, superou nossas expectativas. O desenvolvimento paraplataforma Microsoft .Net não será o mesmo após o lançamento do Delphi 8, vale apena aguardar!
Enquanto o Delphi 8 não está disponível, vamos começando mais uma The ClubMegazine com um artigo que foi muito solicitado ao nosso setor de suporte, o qual tratasobre a impressão rápida via Delphi, fazendo tratamentos para impressão local e emrede e ainda em portas USB, confira...
Prosseguindo, uma pequena referência sobre a manipulação de eventos no Delphi enosso amigo Emerson Facunte num artigo dividido em duas partes que irá apresentaralguns macetes para desenvolvimento de aplicações para internet via IntraWeb paraobter o melhor resultado.
E para finalizar, algumas dicas sobre o funcionamento do Object Repository doDelphi, recurso bastante interessante e pouco explorado por muitos programadores, eencerramos com a sessão Perguntas & Respostas, onde estão compartilhadas algumasdas dúvidas que passaram pelo suporte neste mês.
Boa leitura e um 2004 cheio de sucesso!
MeGAZINEMeGAZINEMeGAZINEMeGAZINEMeGAZINE44444
Sempre que falamos de impressão rápida (padrão DOS)dentro do Delphi, normalmente optamos pela impressão atravésdos comandos AssignFile, ReWrite e Writeln. Esses comandosfuncionam satisfatoriamente, digo satisfatoriamente, porque emalguns casos apresentaram problemas, como por exemplo,ocultar determinados caracteres de uma palavra no meio do textoimpresso, não permite uma verificação se a impressora estápronta para a impressão e também não controlam quando váriaspessoas mandam suas impressões para a mesma impressora e aomesmo tempo.
Diante desses problemas criamos um projeto onde fazemos asimpressões rápidas (padrão DOS) através da procedureWritePrinter da unit WinSpool. Para entendermos um poucomelhor primeiramente vamos verificar quais os recursos queessa procedure nos dará ao utilizá-la e depois passo a passocriaremos os projetos de exemplo.
Como essa impressão irá funcionarO Delphi nos traz já há bastante tempo uma unit chamada
WinSpool que, apesar de não ser muito utilizada, é bastante útilpois contém métodos que permitem fazer uma impressão rápida(padrão DOS) como o Writeln, mas utilizando o Spool daimpressora.
Para isso antes de iniciarmos a impressão executamos umafunction que irá fazer um contato com a impressora verificandose a mesma está pronta para o trabalho, caso positivo fazemosmais algumas inicializações para o Spool e começamos a enviaros trabalhos de impressão. Neste momento se essa impressora jáestá em uso o nosso trabalho de impressão entra na fila do spool efica aguardando a sua vez.
Veja que neste momento já resolvemos alguns dos problemasmencionados no início, que é a verificação se a impressora está
pronta e controlar quando a impressora já está em uso. Mas omais importante é que tudo isso é feito sem perder a velocidadeno momento da impressão.
Na verdade essa unit WinSpool traz inúmeros métodos paracontrole do Spool de impressão e que renderiam várias matériasem nossa revista, mas isso deixaremos para outra oportunidade,pois por enquanto trataremos somente das funções as quaisestaremos utilizando em nosso projeto.
Iniciando os trabalhosNeste primeiro projeto iremos aproveitar para entender um
pouco sobre as funções utilizadas da unit WinSpool para fazer asimpressões. E um detalhe importante é que essas impressõesforam testadas com as versões do Delphi3 e Delphi6 e ambasfuncionaram perfeitamente.
Vamos iniciar os nossos trabalhos criando um novo projeto,chamado Exemplo1.
Neste novo projeto visualize a unit e declare na seçãoimplementation a unit WinSpool.
Em seguida coloque um botão no form e no evento onClickdeste botão inclua as seguintes instruções:
procedure TForm1.Button1Click(Sender: TObject);
var
hPrinter: THandle;
BytesWritten: DWORD;
DocInfo: TDocInfo1;
NomeImp, Texto: String;
begin
NomeImp := LerImpressora;
if not OpenPrinter(PChar( NomeImp ),
hPrinter, nil) then
WritePrinterWritePrinterWritePrinterWritePrinterWritePrinterCriando impressões rápidas para o DelphiCriando impressões rápidas para o DelphiCriando impressões rápidas para o DelphiCriando impressões rápidas para o DelphiCriando impressões rápidas para o Delphi
Por André Colavite
DelphiDelphiDelphiDelphiDelphi
MeGAZINEMeGAZINEMeGAZINEMeGAZINEMeGAZINE 55555
DelphiDelphiDelphiDelphiDelphi
raise exception.create(‘THE CLUB - Impressora
não encontrada!’);
{ Informações para o spool de impressão }
DocInfo.pDocName := PChar( ‘THE CLUB - Testando
trabalho de impressão’ );
DocInfo.pOutputFile := nil;
DocInfo.pDatatype := ‘RAW’;
if StartDocPrinter(hPrinter, 1, @DocInfo) = 0 then
Exit;
if not StartPagePrinter(hPrinter) then
Exit;
Texto := ‘Imprimindo Primeira linha’;
WritePrinter(hPrinter, PChar(Texto),
Length(Texto), BytesWritten);
Texto := ‘ Imprimindo Segunda coluna da Primeira
linha’;
WritePrinter(hPrinter, PChar(Texto),
Length(Texto), BytesWritten);
{ Executa um Eject da folha }
WritePrinter(hPrinter, PChar(#13+#10),
Length(#13+#10), BytesWritten);
Texto := ‘Imprimindo Segunda linha do relatorio’;
WritePrinter(hPrinter, PChar(Texto),
Length(Texto), BytesWritten);
EndPagePrinter(hPrinter);
EndDocPrinter(hPrinter);
ClosePrinter(hPrinter);
end;
Neste evento onClick executamos uma function chamada
LerImpressora ao qual será criada com a seguinte
estrutura:
function LerImpressora: String;
var
MyPrinter, MyDriver, MyPort: array[0..100] of
Char;
DevMode: THandle;
begin
Printer.GetPrinter(MyPrinter, MyDriver, MyPort,
DevMode);
Result := MyPrinter;
end;
Para essa function LerImpressora funcionar devemosdeclarar a unit Printers na seção implementation e tambémdeclarar essa function acima da seção var da unit. Conformeexemplo abaixo:
function LerImpressora: String;
var
Form1: TForm1;
Neste momento podemos gravar o projeto e testá-lo, ao qualfará a impressão na impressora selecionada como padrão noWindows.
Entendendo os comandos utilizados.Como podemos observar, é bastante simples a criação de
relatórios utilizando essas funções da unit WinSpool. Sendoassim vamos aproveitar para verificar os detalhes de cada funçãoutilizada no Exemplo1.
OpenPrinter(PChar( NomeImp ), hPrinter, nil)Retorna o controle identificando a impressora ou servidor de
impressora especificado.Param1 - String que especifica o nome da impressora ou
servidor de impressora.Param2 - Variável que recebe o handle de identificação da
impressora aberta.Param3 - Este valor pode ser nulo.
StartDocPrinter(hPrinter, 1, @DocInfo)Informa ao Spooler de impressão que o documento pode ser
armazenado no Spool para impressão.Param1 – Identifica a impressoraParam2 – Especifica a versão da estrutura a ser usada. Para
o Windows 95 devemos especificar o valor 2 e as demais versõesdevemos especificar o valor 1.
Param3 – Variável do tipo TDocInfo1
StartPagePrinter(hPrinter)Informa ao Spooler que uma página está a ponto de ser
impressa na impressora especificada.Param1 – Identifica a impressora
WritePrinter(hPrinter, PChar(Texto),Length(Texto), BytesWritten);
Informa ao Spooler quais os dados a serem enviados para aimpressora selecionada.
Param1 – Identifica a impressoraParam2 – Array de bytes que contém os dados que deverão
ser enviados para a impressoraParam3 – Especifica o tamanho, em bytes, do Array
MeGAZINEMeGAZINEMeGAZINEMeGAZINEMeGAZINE66666
DelphiDelphiDelphiDelphiDelphi
Param4 – Variável que conterá a quantidade de bytesenviados para a impressora.
EndPagePrinter(hPrinter);Informar o fim da página atual e o começo da página
seguinte para a impressora especificada.Param1 - Identifica a impressora
EndDocPrinter(hPrinter);Finaliza o trabalho de impressão.Param1 - Identifica a impressora
ClosePrinter(hPrinter);Fecha a impressora especificada.Param1 - Identifica a impressora a ser fechada.
Maiores detalhes sobre essas e outras funções existentes naunit WinSpool recomendo que sejam verificadas através do helpdo Delphi.
Criando um projeto mais complexo.Como agora já conhecemos um pouco como trabalhar com
essas funções, deixaremos as idéias fluírem e começaremos autilizá-las de uma forma mais complexa. Como por exemplo,criar um projeto onde fazemos a impressão de dados de um bancode dados separando os campos por coluna, e fazendo o controle daimpressão de cabeçalho. Sendo assim mãos a obra.
Primeiro passo crie um novo projeto no Delphi, chamadoExemplo2, e em seguida adicione um novo form neste projeto.
Para o Form principal deixaremos o nome Form1 mesmo,para o segundo form coloque FrmPreview e unPreview para asua unit.
A idéia desse projeto é criar uma estrutura genérica paraimpressão de relatórios utilizando as funções da unit WinSpool,sendo assim essa unit unPreview com o FrmPreview poderão serutilizados em outros projetos para a geração de relatórios rápidos.
Começaremos a montar o FrmPreview, sendo assim coloqueneste form um componente Memo, altera a sua propriedadeAlign para o valor alClient e na propriedade Font / Nameselecione a fonte Courier New.
DeclaraçõesVisualize a unit unPreview e nesta unit faça as declarações
que estão especificadas a seguir:
Declarar na seção Private uma variável do tipo string
chamada ArqPreview
private
ArqPreview: String;
public
end;
Declarar acima da seção var as Functions e Procedures queimplementaremos na unit, veja a seguir:
function GeraArqTemp: String;
function LerImpressora: String;
function Imp_Inicio(Const pNomeImp, pNomeTrabalho,
pTipo: String; pPreview: Boolean): Boolean;
procedure Imp_InicializaPagina;
procedure Imp_Fim;
procedure Imp_Linha(SaltaLin, EspacoCol: Integer;
Texto: String; TamTotal: Integer; Alinha: Char);
procedure Imp_Ejeta;
Declarar na seção var duas variáveis, veja a seguir:
var
FrmPreview: TFrmPreview;
hPrinter: THandle;
BytesWritten: DWORD;
E na seção implementation declarar as units WinSpool ePrinters, veja a seguir:
implementation
Uses WinSpool, Printers;
Implementando as Functions e ProceduresA primeira function que iremos implementar na unit, será a
LerImpressora que é responsável por retornar informações daimpressora atualmente selecionada para impressão. Essafunction ficará com a seguinte estrutura:
function LerImpressora: String;
var
MyPrinter, MyDriver, MyPort: array[0..100]
of Char;
DevMode: THandle;
begin
Printer.GetPrinter(MyPrinter, MyDriver,
MyPort, DevMode);
Result := MyPrinter;
end;
MeGAZINEMeGAZINEMeGAZINEMeGAZINEMeGAZINE 77777
DelphiDelphiDelphiDelphiDelphi
A próxima function é a Imp_Inicio ao qual será responsávelpor inicializar a impressão passando as informações necessáriaspara o Spool da impressora. Nesta function utilizaremos osseguintes parâmetros:
pNomeImp – Nome da impressora para onde o trabalho deimpressão será enviado
pNomeTrabalho – Nome do trabalho de impressão que seráapresentado na fila do Spool
pTipo – Passar o valor RAW ou TEXT. RAW - deixou a impressão na matricial mais rápida TEXT - imprimiu com impressora USBpPreview – Indica se iremos mostrar um preview do relatório
Essa function Imp_Inicio tem um retorno do tipo Boolean aoqual indicará se a inicialização do relatório foi realizada comsucesso e se podemos começar a impressão dos dados. Veja aestrutura da function Imp_Inicio a seguir:
function Imp_Inicio(Const pNomeImp, pNomeTrabalho,
pTipo: String; pPreview: Boolean): Boolean;
var
DocInfo: TDocInfo1;
begin
Result := False;
if not WinSpool.OpenPrinter(PChar( pNomeImp ),
hPrinter, nil) then
raise exception.create(‘THE CLUB -
Impressora não encontrada!’);
DocInfo.pDocName := PChar( pNomeTrabalho );
DocInfo.pOutputFile := nil;
if pPreview then
begin
DocInfo.pOutputFile := PChar( GeraArqTemp );
FrmPreview := TFrmPreview.Create( Nil );
FrmPreview.ArqPreview := DocInfo.pOutputFile;
end;
DocInfo.pDatatype := PChar( pTipo );
if StartDocPrinter(hPrinter, 1, @DocInfo) = 0 then
Exit;
if not StartPagePrinter(hPrinter) then
Exit;
Result := True;
end;
Nesta function Imp_Inicio fazemos uma chamada para afunction GeraArqTemp, ao qual será responsável pela criação donome do arquivo temporário que armazenará o relatório para serapresentado no Preview, caso o usuário selecione visualizar orelatório no Preview. Essa function terá a seguinte estrutura:
function GeraArqTemp: String;
var
TempDir: array[0..MAX_PATH] of char;
Buffer : array[0..MAX_PATH] of Char;
begin
GetTempPath(MAX_PATH, @TempDir);
GetTempFileName(@TempDir, ‘CLUB’, 0, Buffer);
Result := Buffer;
end;
Esta procedure GetTempfileName utilizada necessita dosseguintes parâmetros:
Parametros 1. Diretorio, 2. Prefixo, 3. 0 -> indica que não irá repetir o nome do arquivo, 4. Variável que irá receber o nome gerado
A procedure Imp_InicializaPagina é responsável pelainicialização da página que será enviada para o Spool deimpressão. Essa procedure terá a seguinte estrutura:
procedure Imp_InicializaPagina;
begin
if not StartPagePrinter(hPrinter) then
raise exception.create(‘THE CLUB -
Problemas na inicialização da página!’);
end;
Em seguida iremos criar a próxima function que será aImp_Fim, ao qual será responsável pela finalização do relatório.Essa procedure terá a seguinte estrutura:
procedure Imp_Fim;
begin
EndPagePrinter(hPrinter);
EndDocPrinter(hPrinter);
WinSpool.ClosePrinter(hPrinter);
if Assigned( FrMPreview ) then
begin
try
FrmPreview.Memo1.Lines.LoadFromFile
( FrmPreview.ArqPreview );
FrMPreview.ShowModal;
{ Exclui o arquivo temporário }
try
DeleteFile( FrmPreview.ArqPreview );
except end;
MeGAZINEMeGAZINEMeGAZINEMeGAZINEMeGAZINE88888
DelphiDelphiDelphiDelphiDelphi
finally FreeAndNil( FrMPreview ); end; end;end;
Nesta procedure também iremos apresentar o form contendoa visualização dos dados em preview. Mas iremos observar que éum preview bem simples, ao qual foi criado para mostrar quepodemos criar um arquivo contendo os dados enviados para aimpressora.
A próxima procedure a ser criada é a Imp_Linha ao qual seráutilizada para fazer a impressão das linhas do relatório. Nestaprocedure implementamos alguns controles a mais, como porexemplo, impressão da linha com ou sem o salto da linha,espaçamento para fazer impressão em coluna e alinhamento adireita ou a esquerda dessas colunas.
Os parâmetros criados para essa procedure foram:SaltaLin - Qtde de linhas que saltará a partir da última linha
impressaEspacoCol - Espaço em caracteres que existirá entre as
colunasTexto - String a ser impressaTamTotal - Tamanho total da string, utilizado para
impressão em colunaAlinha - Alinhamento da coluna E = Esquerda - D = Direita
A estrutura da procedure ficará da seguinte forma:
procedure Imp_Linha(SaltaLin, EspacoCol: Integer;
Texto: String; TamTotal: Integer; Alinha: Char);
var
i: integer;
Espaco: string;
begin
{ adiciona as linhas }
for i:=1 to SaltaLin do
WritePrinter(hPrinter, PChar(#13+#10),
Length(#13+#10), BytesWritten);
{ Calcula o espaço q determinado o tamanho total
do campo }
Espaco := StringOfChar(‘ ‘, TamTotal-
Length(Texto));
if Alinha = ‘E’ then
Texto := Texto+Espaco
else if Alinha = ‘D’ then
Texto := Espaco+Texto;
{ adiciona espaço entre as colunas }
Texto := StringOfChar(‘ ‘, EspacoCol)+Texto;
{ Imprime o texto }
WritePrinter(hPrinter, PChar(Texto),
Length(Texto), BytesWritten);
end;
A última procedure a ser implementada nesta unit é aprocedure Imp_Ejeta, ao qual será responsável pela salto depágina e pela controle de finalização da página atual no Spool.
A estrutura dessa procedure ficará da seguinte forma:
procedure Imp_Ejeta;
var ch: Char;
begin
ch:= #12;
WritePrinter( hPrinter, @ch, 1, BytesWritten );
EndPagePrinter(hPrinter);
end;
Pronto, neste momento finalizamos a criação da unit quepoderá ser utilizada na criação de qualquer relatório em nossosprojetos.
Utilizando a unit unPreviewA segunda parte desse projeto será a utilização dessas
functions e procedures que criamos na unit unPreview. Sendoassim volte ao form principal do nosso projeto e coloque osseguintes componentes descritos a seguir:
Table,DataSource,DBNavigatorDBGridPrintDialogPanel - Dentro desse Panel coloque os seguintes componentes:GroupBox - Dentro desse GroupBox coloque um Label3 componentes ButtonRadioGroupCheckBox
Esses componentes serão configurados da seguinte forma:
Componente TableName: Table1DatabaseName: DBDEMOSTableName: Employee.db
Componente DataSourceName: DataSource1DataSet: Table1
MeGAZINEMeGAZINEMeGAZINEMeGAZINEMeGAZINE 99999
DelphiDelphiDelphiDelphiDelphi
Componente DBNavigatorName: DBNavigator1Align: alTopDataSource: DataSource1
Componente PanelName: Panel1Align: alBottomCaption: vazio
Componente DBGridName: DBGrid1Align: alClientDataSource: DataSource1
Componente PrintDialogName: PrintDialog1
Componente GroupBoxName: GroupBox1Caption: Impressora selecionada
Componente LabelName: Label1
Componente RadioGroupName: RadioGroup1Caption: TipoColumns: 1ItemIndex: 0Items: RAW TEXT
Componente CheckBoxName: CheckBox1Caption: Preview
Componentes ButtonsName: Button1Caption: Imprimir registros
Name: Button2Caption: Selecionar Impressora
Name: Button3Caption: Relatório Simples
Após configurar todos esses componentes o form ficaráparecido com a imagem 1. (abaixo)
No evento onclick dos botões iremos montar os relatóriosutilizando as instrução da unit unPreview, sendo assim oprimeira passo é declarar na seção implementation a unitunPreview, conforme exemplo a seguir:
implementation
Uses UnPreview;
Iniciaremos com o Button2 onde iremos chamar oPrintDialog para que assim o usuário possa selecionar aimpressora a ser utilizada:
procedure TForm1.Button2Click(Sender: TObject);
begin
MeGAZINEMeGAZINEMeGAZINEMeGAZINEMeGAZINE1 01 01 01 01 0
DelphiDelphiDelphiDelphiDelphi
if PrintDialog1.Execute then
Label1.Caption := LerImpressora;
end;
No evento onclick do Button3 criaremos um relatóriobastante simples ao qual nos permitirá fazer um teste deimpressão. A instrução desse evento ficará da seguinte forma:
procedure TForm1.Button3Click(Sender: TObject);
{ Observação: Caracteres utilizados para impressora
Epson }
Const
NegOn = #27+#71; NegOff = #27+#71;
ItaOn = #27+#52; ItaOff = #27+#52;
CondOn = #15; CondOff = #18;
begin
{ Imprimindo um simples relatório com
EPSON FX-1170 }
if Imp_Inicio( Label1.Caption, ‘Impressão de
relatório Simples - THE CLUB’, ‘RAW’,
CheckBox1.Checked) then
begin
Imp_InicializaPagina;
Imp_Linha(01, 00, ‘Essa e a primeira linha
do relatorio’, 0, ‘D’);
Imp_Linha(00, 20, ‘Segunda coluna impressa’,
0, ‘D’);
Imp_Linha(01, 00, NegOn+’Negrito’+NegOff, 0,
‘D’);
Imp_Linha(00, 10, ItaOn+’Italico’+ItaOff, 0,
‘D’);
Imp_Linha(00, 10, CondOn+’Condensado Primeira
linha’, 0, ‘D’);
Imp_Linha(00, 10, ‘Condensado Segunda
linha’+CondOff, 0, ‘D’);
Imp_Ejeta;
Imp_InicializaPagina;
Imp_Linha(01, 00, ‘Imprimindo a próxima
página do relatório’, 0, ‘D’);
Imp_Linha(01, 00, ‘Segunda linha impressa’, 0,
‘D’);
Imp_Ejeta;
Imp_Fim
end;
end;
Finalizando iremos criar o relatório principal ao qual imprimeos dados do componente Table e faz o controle de cabeçalho ecoluna. A seguir podemos verificar as instruções criadas dentrodo evento onClick do Button1.
procedure TForm1.Button1Click(Sender: TObject);
var nLin: Integer;
Tipo: String;
procedure Cabecalho;
begin
Imp_InicializaPagina;
{ Impressão do Cabeçalho }
Imp_Linha(01, 00, ‘Código’, 6, ‘E’);
Imp_Linha(00, 03, ‘Nome’, 15, ‘E’);
Imp_Linha(00, 02, ‘Sobrenome’, 24, ‘E’);
Imp_Linha(00, 02, ‘Data’, 10, ‘E’);
Imp_Linha(00, 01, ‘Valor’, 12, ‘D’);
Imp_Linha(01, 00, StringOfChar(‘-’, 80), 80,
‘E’);
nLin := nLin + 2;
end;
begin
Table1.First;
if RadioGroup1.ItemIndex = 0 then
Tipo := ‘RAW’ // Dica: Imprime com matricial
// Epson mais rápido
else
Tipo := ‘TEXT’; // Dica: Funciona para
// impressora USB
if Imp_Inicio( Label1.Caption, ‘Impressão de dados
Employee - THE CLUB’, Tipo, CheckBox1.Checked) then
begin
{ Impressão dos dados }
nLin := 0;
While not Table1.Eof do
begin
if nLin = 0 then
begin
Cabecalho;
end;
Imp_Linha(01, 00, Table1.FieldByName
(‘EmpNo’).AsString, 5, ‘D’);
Imp_Linha(00, 04, Table1.FieldByName
(‘FirstName’).AsString, 15, ‘E’);
Imp_Linha(00, 02, Table1.FieldByName
(‘LastName’).AsString,
Table1.FieldByName(‘LastName’).
DisplayWidth, ‘E’);
Imp_Linha(00, 02, FormatDateTime
(‘dd/mm/yyyy’, Table1.FieldByName
(‘HireDate’).AsDateTime), 10, ‘E’);
Imp_Linha(00, 01, FormatFloat(‘###,##0.00’,
MeGAZINEMeGAZINEMeGAZINEMeGAZINEMeGAZINE 1 11 11 11 11 1
DelphiDelphiDelphiDelphiDelphi
Table1.FieldByName(‘Salary’).asFloat),
Table1.FieldByName(‘Salary’).DisplayWidth, ‘D’);
Inc( nLin );
if nLin >= 62 then
begin
Imp_Ejeta;
nLin := 0;
end;
Table1.Next;
end;
Imp_Ejeta;
Imp_Fim
end;
end;
Pronto, neste momento estamos com o projeto de relatórioquase pronto, faltando somente implementar o evento onShow doForm onde abriremos a Table1 e iremos mostrar qual aimpressora que está selecionada como padrão. Veja exemplo doevento onShow do form a seguir:
procedure TForm1.FormShow(Sender: TObject);
begin
Table1.Open;
Label1.Caption := LerImpressora;
end;
Agora podemos compilar o nosso projeto e efetuar os testes deimpressão e de apresentação do preview.
Redefinindo o Whiteln da unit SystemEspero que não estejam cansados, pois temos um último
exemplo a seguir ao qual nos ajudará bastante caso já tenhamoscriado algum relatório utilizando os comandos AssignFile,ReWrite, Writeln e CloseFile da unit System.
A idéia desse novo projeto é redirecionar as chamadas dasprocedures da unit System para as procedures da unit queiremos criar, sendo assim toda vez que seu projeto chamar umaimpressão pelo Writeln ele estará chamando a procedure Writelnque iremos criar ao qual usará a impressão pelo WritePrinter.Vamos entender melhor assim que criarmos o projeto de exemplo,portanto mãos a obra.
Crie um novo projeto, chamado Exemplo3, e neste novoprojeto crie uma nova unit sem form chamada unImpTH.
Nesta unit unImpTH iremos iniciar os trabalhos com asdeclarações, pois precisamos declarar na seção Uses as seguintes
units:
Uses Windows, WinSpool, Printers, SysUtils, Dialogs;
Depois necessitamos declarar as procedure e functions queserão criadas posteriormente.
function LerImpressora: String;
procedure AssignFile(var FTH: TextFile;
FileNameTH: String);
procedure CloseFile(var FTH: TextFile);
procedure WriteLn(var FTH: TextFile;
TextoTH: String);
procedure ReWrite(var FTH: TextFile);
E para finalizar as declarações iremos declarar duasvariáveis na seção var.
var
hPrinter: THandle;
BytesWritten: DWORD;
Agora iremos implementar as procedures e function, sendoassim iniciaremos com a function LerImpressora, ao qualconterá as seguintes instruções:
function LerImpressora: String;
var
MyPrinter, MyDriver, MyPort: array[0..100]
of Char;
DevMode: THandle;
begin
Printer.GetPrinter(MyPrinter, MyDriver,
MyPort, DevMode);
Result := MyPrinter;
end;
Em seguida criaremos a procedure AssigFile ao qual devemoscriar com parâmetros idênticos aos da procedure da unit System,ficando a procedure da seguinte forma:
procedure AssignFile(var FTH: TextFile; FileNameTH:
String);
var
DocInfo: TDocInfo1;
PD: TPrintDialog;
begin
{ Chama o PrintDialog para selecionar a
impressora }
PD := TPrintDialog.Create(Nil);
MeGAZINEMeGAZINEMeGAZINEMeGAZINEMeGAZINE1 21 21 21 21 2
DelphiDelphiDelphiDelphiDelphi
try
if not PD.Execute then
Exit;
finally
PD.Free;
end;
if not WinSpool.OpenPrinter(PChar( Printer.
Printers[Printer.PrinterIndex] ),
hPrinter, nil) then
raise exception.create(‘THE CLUB -
Impressora não encontrada!’);
DocInfo.pDocName := ‘Impressão THE CLUB’;
DocInfo.pOutputFile :=
PChar( FileNameTH );//’c:\arq.txt’;
{ Foi testado o DataType com o valor RAW e TEXT
RAW -> deixou a impressão matricial mais rápida
TEXT -> imprimiu com impressora USB }
DocInfo.pDatatype := ‘RAW’;
if StartDocPrinter(hPrinter, 1, @DocInfo) = 0 then
Exit;
if not StartPagePrinter(hPrinter) then
Exit;
end;
A próxima procedure será a ReWrite, mas essa somente serácriada para anular a chamada da procedure da unit System, poisnão implementaremos nenhuma funcionalidade na mesma. Vejaa procedure a seguir:
procedure ReWrite(var FTH: TextFile);
begin
// criado somente para anular a
// function da unit System
Exit;
end;
A procedure CloseFile é a próxima a ser criada e esta seráutilizada para finalizar a impressão da página e do relatório,conforme pode ser observado a seguir:
procedure CloseFile(var FTH: TextFile);
begin
EndPagePrinter(hPrinter);
EndDocPrinter(hPrinter);
WinSpool.ClosePrinter(hPrinter);
end;
E para finalizar criaremos as procedures Write e Writeln aoqual farão a impressão dos dados para a impressora, veja queseguem com os mesmos parâmetros das originais.
procedure Writeln(var FTH: TextFile; TextoTH:
String);
begin
TextoTH := TextoTH + #13+#10;
WritePrinter(hPrinter, PChar(TextoTH),
Length(TextoTH), BytesWritten);
end;
procedure Write(var FTH: TextFile; TextoTH: String);
begin
WritePrinter(hPrinter, PChar(TextoTH),
Length(TextoTH), BytesWritten);
end;
Bem neste momento finalizamos a criação da unit unImpTHe agora podemos fazer o teste implementando no projeto umsimples relatório usando o Writeln para impressão.
No início usaremos o Writeln da unit System e depois iremosdeclarar a nossa unit unImpTH e poderemos observar o mesmorelatório sendo impresso utilizando o Spool de impressão.
Implementando o form Principal do projetoNo form principal coloque dois botões, configurando-os da
seguinte forma:
Button1Caption: Exemplo de Whiteln – 1
Button2Caption: Exemplo de Writeln – 2
Após configurar os dois botões o form do projeto ficaráparecido com a imagem2. (abaixo)
MeGAZINEMeGAZINEMeGAZINEMeGAZINEMeGAZINE 1 31 31 31 31 3
DelphiDelphiDelphiDelphiDelphi
No evento onclick do Button1 iremos incluir a seguinteinstrução:
procedure TForm1.Button1Click(Sender: TObject);
var F: TextFile;
begin
{ Manda para impressora na rede }
AssignFile(f, ‘\\Servidor\EpsonFX’);
Rewrite(f);
Writeln(f, ‘Linha1’);
Write(f, ‘Linha1’);
Writeln(f, ‘Linha2’);
CloseFile(f);
end;
No evento onclick do Button2 iremos incluir a seguinteinstrução:
procedure TForm1.Button2Click(Sender: TObject);
var Texto1 : string;
F : TextFile;
Valor : Extended;
T : Integer;
begin
{ Gerar um arquivo }
AssignFile(F,’c:\writeln.txt’);
Rewrite(F);
T := 21; { Tamanho total da string,
que deverá ser impresso }
Texto1 := ‘THE CLUB’;
Valor := 1.00;
Writeln(F,Format(‘%s%’+IntToStr
(T-Length(Texto1))+’s%8.2f’,
[Texto1,’ ‘,Valor])+
‘Fim da linha’);
Texto1 := ‘THE CLUB DELPHI DELP’;
Valor := 100.21;
Writeln(F,Format(‘%s%’+IntToStr
(T-Length(Texto1))+’s%8.2f’,
[Texto1,’ ‘,Valor])+’Fim da linha’);
Texto1 := ‘THE’;
Valor := 1000.10;
Writeln(F,Format(‘%s%’+IntToStr
(T-Length(Texto1))+’s%8.2f’,
[Texto1,’ ‘,Valor])+’Fim da linha’);
Writeln(F,#12); // Ejeta a página
CloseFile(F);
end;
Vejam que esses dois exemplos foram criados utilizando aprocedures da unit System do Delphi.
Neste momento se compilarmos o projeto poderemos observarque os relatórios serão impressos sem passar pelo Spool deimpressão.
Agora para passarmos a utilizar as procedures da nossa unitunImpTH, basta declará-la na seção implementation do seuprojeto.
Um detalhe importante, sempre essa unit unImpTH deve serdeclarada depois da unit System, por esse motivo que a colocamosna seção implementation, conforme exemplo abaixo:
implementation
Uses UnImpTH;
Pronto, faça novamente os testes no relatório e poderáobservar que o mesmo foi impresso utilizando o spool daimpressora e as procedure da nossa unit unImpTH.
ConclusãoBem, aqui finalizamos um artigo que gostei bastante, pois
nos trará um pouco mais de recurso para as impressões rápidaspelo Delphi.
Um grande abraço a todos e um 2004 com muita Paz, Saúdee bons negócios.
Até a próxima.
DownloadOs projetos de exemplo deste artigo estão disponíveis para
download em:
http://www.theclub.com.br/revista/download/Imp-WritePrinter.zip
Sobre o autorAndré ColaviteConsultor Técnico do The [email protected]
MeGAZINEMeGAZINEMeGAZINEMeGAZINEMeGAZINE1 41 41 41 41 4
DelphiDelphiDelphiDelphiDelphi
Quase todos os códigos que você escreve são executados diretaou indiretamente em resposta a algum evento. Um evento é umtipo especial de propriedade que representa uma ocorrência emtempo de execução, muitas vezes uma ação do usuário. O códigoque responde diretamente a um evento, chamado controlador deevento, é uma procedure do Delphi.
Gerando um novo controlador de eventoVocê pode gerar um esqueleto de um evento para ser utilizado
por um form ou para outros componentes. Para criar umcontrolador de evento faça o seguinte:
1 – Selecione um componente.2 – Vá até o Object Inspector e clique na aba Events. A partir
daí você terá acesso a todos os eventos do componente selecionado.3 – Selecione o evento que você quiser e então dê um duplo
clique ou pressione as teclas Ctrl+Enter simultaneamente. Istofará com que o editor de código do Delphi seja acionado e o cursorseja posicionado dentro do esqueleto do evento, mais precisamentedentro do bloco begin...end.
4 – Agora basta você digitar o código que você quer que sejaexecutado assim que este evento for disparado.
Gerando um controlador para um evento default.Alguns componentes tem um evento default, que é o evento
chamado com mais freqüência. Por exemplo, o evento padrão docomponente Button é o evento OnClick. Para saber qual é oevento default de um determinado componente basta que emtempo de desenvolvimento você dê um duplo clique sobre ocomponente. Então o editor de código do Delphi será acionado e ocursor será posicionado dentro do esqueleto do evento, no blocobegin...end. Mas vale lembrar que nem todos os componentes temevento default. Alguns componentes como o TBevel por exemplonão responde a qualquer evento. Outros componentes respondemde forma diferente quando se dá um duplo clique. Por exemplo,alguns componentes abrem um editor de código ou uma janela dediálogo.
Localizando eventosSe você gerou um evento default para um determinado
componente através de um duplo clique, você pode localizaraquele evento da mesma forma, ou seja, dê um duplo clique sobre
o componente e então o editor de código do Delphi será acionado eo cursor será posicionado dentro do esqueleto do evento. Paralocalizar um evento que não é default, faça o seguinte:
1 – No form, selecione o componente ao qual você querprocurar pelo evento.
2 – Vá até o Object Inspector e clique na aba Events3 – Selecione o evento que você quiser e então dê um duplo
clique ou pressione as teclas Ctrl+Enter simultaneamente. Istofará com que o editor de código do Delphi seja acionado e o cursorseja posicionado dentro do esqueleto do evento, mais precisamentedentro do bloco begin...end.
Associando um evento com outro evento jáexistente
Você pode reutilizar um código fazendo que um determinadoevento responda para mais de um evento. Por exemplo, muitasaplicações fazem com que alguns botões sejam equivalentes acomandos do menu. Sendo assim em sua aplicação, quando umbotão for executar a mesma coisa que um determinado item domenu você pode fazer com que eles compartilhem do mesmoevento.
Vamos fazer um teste:1 – No form inclua um componente MainMenu e um
componente Button.2 – Dê um duplo clique no componente Button para que o
evento default seja ativado e então digite o seguinte:
procedure TForm1.Button1Click(Sender: TObject);
begin
ShowMessage(‘Evento OnClick do botão.’);
end;
3 – Agora crie alguns itens no componente MainMenu.Selecione um dos itens e vá até o Object Inspector. Clique na abaEvents e selecione o evento OnClick. Clique no botão onde temuma setinha para baixo. Fazendo isto lhe aparecerá o nome doevento OnClick do botão, por exemplo Button1Click. Selecioneeste item e compile o programa.
Agora você pode clicar no botão ou no item do menu do quevocê escolheu que ambos usarão a mesma procedure ou evento.
Trabalhando com eventosTrabalhando com eventosTrabalhando com eventosTrabalhando com eventosTrabalhando com eventosPor Claudinei Rodrigues
DelphiDelphiDelphiDelphiDelphi
Este é o caminho mais simples para se reutilizar eventos. ODelphi também fornece o Action Lists, Action Bands que tambémpermitem este reaproveitamento de código. Mas falaremos maissobre estes componentes numa outra oportunidade.
Usando o parâmetro SenderO parâmetro Sender de um evento indica qual componente
chamou um determinado evento. Algumas vezes ele é muito útilquando se tem vários componentes compartilhando o mesmoevento comportando-se de forma diferente dependendo de qualcomponente o chamou. Você pode fazer isto utilizando oparâmetro Sender em uma instrução if...then....else.
Tomando como exemplo a rotina que escrevemosanteriormente, vamos fazer uma modificação no evento OnClickdo botão. Como você pode ver a seguir nós estamos verificandoatravés do Sender qual o componente que chamou o evento.Outro detalhe interessante é que o Sender tem uma propriedadechamada ClassName que retorna o nome da classe docomponente que a chamou.
procedure TForm1.Button1Click(Sender: TObject);
begin
if Sender = Button1 then
ShowMessage(‘Este evento foi chamado pelo
Button1.’)
else
ShowMessage(‘Este evento foi chamado
pelo ‘+Sender.ClassName); end;
Deletando eventosQuando você deleta um componente do form, o próprio Delphi
remove a declaração do componente da unit, mas os eventos nãosão removidos. Caso você tenha algum outro componenteassociado ao evento deste componente que você acabou de deletar,ele continuará funcionando. Você pode deletá-los manualmente,mas se você for fazer isto, não esqueça que além da procedurevocê também deve remover a declaração que está no inicio daunit. Caso isto não seja feito, um erro ocorrerá no sistema.
ConclusãoO objetivo deste artigo foi dar uma idéia de como se utilizar os
eventos no Delphi para programadores iniciantes nestaferramenta. O Delphi é uma linguagem muito poderosa que nosdá inúmeros recursos.
Sobre o autorClaudinei Rodrigues,Consultor Técnico do The [email protected]
MeGAZINEMeGAZINEMeGAZINEMeGAZINEMeGAZINE1 61 61 61 61 6
RetrospectivaRetrospectivaRetrospectivaRetrospectivaRetrospectiva
RetrospectivaRetrospectivaRetrospectivaRetrospectivaRetrospectiva
Este mês em nossa restrospectiva, chegamos a 1998, com o lançamento do Delphi4 e claro, sua grande aceitação por parte do mercado.
Também tivemos uma matéria sobre o ADO, tecnologia recém lançado pelaMicrosoft e que viria a se tornar um padrão para acesso à banco de dados empraticamente todas as linguagens de programação. Esta matéria, escrita por MauroSant’Anna, mostrou que a utilização do ADO deixava mais rápido o acesso ao bancode dados do que as outras tecnologias existentes. No mercado também começavama aparecer empresas que vendiam componentes ADO específicos, como oADOSolutions, Adonis, etc.
O nosso amigo Mário Camilo Bohm também participou, com uma matéria sobretravamento de registros com o banco de dados Oracle.
Importante lembrar também que haviam pessoas neste ano que ainda estavamresistentes a trocar o seu velho Windows 95 pelo Windows 98, o que gerava muitosproblemas e aborrecimentos, tantos para nós desenvolvedores quantos para osusuários finais.
Em Setembro/98 a Microsoft estava para saber o que iria acontecer sobre oprocesso que a Sun moveu contra ela, por causa do Java, alegando que a Microsofthavia alterado o código do Java, assim quebrando a filosofia do "escreva uma vez,rode em qualquer lugar". Mais tarde veríamos que o Java, apesar de uma linguagempoderosa, não costumava "rodar em qualquer lugar", e tampouco houveconsequências graves para a Microsoft, apesar dos apuros que ela passou, inclusivecom o processo dos mais de 20 estados americanos, com a acusação de monopólio.
Enfim, 98 foi um ano interessante e cheio de novidades! Ele deixou saudades...
Até o mês que vem!
MeGAZINEMeGAZINEMeGAZINEMeGAZINEMeGAZINE1 81 81 81 81 8
DelphiDelphiDelphiDelphiDelphi
Salve, salve Delphianos!
Antes de concluir a última parte do artigo sobre WebServices,vamos iniciar uma luta inglória contra o Intraweb. Calma,calma! Não quero destruir o Intraweb, e sim demonstrar o queresta de bom nesta “fantástica” ferramenta.
Neste artigo, iniciaremos o desenvolvimento de aplicaçãocompleta para Intraweb, extraída do meu livro Delphi 7 Internete Banco de Dados.
Antes de iniciar nosso projeto com banco de dados, devemoscriar nossa base no Firebird/Interbase.
Figura 1 Registrando Servidor Local Interbase Figura 2 criação do banco de dados Clientes.GDB
Entre no IBConsole e caso não tenha registrado o ServidorLocal, selecione a opção Server/Register e informe aspropriedades conforme a figura 1.
No campo UserName digite SYSDBA (com letras maiúsculas),e no campo PassWord digite masterkey (com letras minúsculas).Estas informações são para o usuário padrão.
Agora vamos criar o banco de dados Clientes.GDB.
Selecione a opção DataBase/Create Database e crie um novobanco de dados como ilustra a figura 2.
Por Emerson Facunte
IntraWebIntraWebIntraWebIntraWebIntraWebProgramação AlternativaProgramação AlternativaProgramação AlternativaProgramação AlternativaProgramação Alternativa
MeGAZINEMeGAZINEMeGAZINEMeGAZINEMeGAZINE 1 91 91 91 91 9
DelphiDelphiDelphiDelphiDelphi
Agora iremos criar os objetos do banco de dadosClientes.GDB.
Dentro do Interative SQL execute os seguintes comandos:
Criação da Tabela TBCLIENTEcreate table tbcliente( cod_cliente integer not null, razao_social varchar(50), endereco varchar(50), cidade varchar(50), estado varchar(2), cep varchar(8), email varchar(50), primary key (cod_cliente) );
Execute o comando através das teclas CTRL-E.
Criação do Generatorcreate generator gen_clientes;
Execute o comando através das teclas CTRL-E.
Criação da Trigger TGClientesset term ||;
CREATE TRIGGER TG_CLIENTES FOR TBCLIENTEACTIVE BEFORE INSERT POSITION 0A SBEGIN NEW.COD_CLIENTE = GEN_ID(GEN_CLIENTES,1);END ||SET TERM;
Execute o comando através das teclas CTRL-E. Com issofinalizamos a criação dos objetos.
Finalize o IBConsole, e vamos iniciar nossas atividades noDelphi.
Através das opções File/New/Other..., selecione a seçãoIntraweb e escolha o modelo Stand Alone Application with DataModule (figura 3).
Selecione o DataModule e insira um objeto do tipoTSQLConnection. Através do duplo-clique, já na tela deconfiguração, aponte para a nossa conexão Clientes, criadaanteriormente.
Figura 3 Iniciando a aplicação
Altere também a propriedade LoginPrompt para false.Nunca esqueça de fazer esta alteração, pois numa aplicaçãoservidora, não existe a possibilidade do usuário interagir no logindo banco de dados.
Agora vamos inserir o objeto para manipular nossa tabela declientes. Insira um objeto do tipo TSQLDataSet, e altere asseguintes propriedades:
Objeto de InclusãoInsira um objeto do tipo TSQLQuery e altere as propriedades
que seguem.
Na propriedade PARAMS do SQLInclui altere os tipos dosparâmetros para String.
MeGAZINEMeGAZINEMeGAZINEMeGAZINEMeGAZINE2 02 02 02 02 0
DelphiDelphiDelphiDelphiDelphi
Objeto de AlteraçãoInsira um objeto do tipo TSQLQuery e altere as propriedades
que seguem.
Na propriedade PARAMS do SQLAltera altere os tipos dosparâmetros para String, com exceção do parâmetro PCODIGO,que deve ser Integer.
Objeto de ExclusãoInsira um objeto do tipo TSQLQuery e altere as propriedades
que seguem.
Na propriedade PARAMS do SQLExclui altere o tipo doparâmetro para Integer.
Criando o Formulário PrincipalNo formulário principal (FormMain), adicione um componente
do tipo TMainMenu, e configure as opções como segue:
Arquivo SobreInclusão Clientes InformaçõesManutenção/ConsultaFinaliza
A figura 4 ilustra o nosso menu principal.
Insira um objeto do tipo TIWMenu (seção IW Standard), ealtere a propriedade Attached Menu para MainMenu1. Narealidade estamos vinculando nosso objeto MainMenu1 com oIWMenu1 do Intraweb.
Figura 4 Menu Principal
Configure a propriedade BackGroundColor do objeto FormMainpara $00DDFFFF. Amigos, isto é apenas uma sugestão de cor.
Insira os componentes que seguem no FormMain.
A figura 5 ilustra o nosso formulário principal.
Figura 5 Formulário principal
MeGAZINEMeGAZINEMeGAZINEMeGAZINEMeGAZINE 2 12 12 12 12 1
DelphiDelphiDelphiDelphiDelphi
Agora iremos codificar duas opções do menu principal:Finaliza e Informações/Sobre.
Selecione a opção Finaliza no objeto MainMenu1 e insira o códigoque segue no evento OnClick.
WebApplication.Terminate(‘Até logo !’);
Neste evento estamos finalizando a aplicação e apresentandoa mensagem “Até Logo !”, ao usuário.
Agora selecione a opção Informações/.Sobre e insira o código quesegue.
WebApplication.ShowMessage(‘Cadastro de Clientes’
+#13#10+ ‘Versão 1.0’,smAlert);
Neste evento apresentamos uma janela de diálogo ao usuário,com as informações da aplicação. Bastante simples, não?
Criando o Formulário de Inclusão
Através das opções File/New/Other..., selecione a seçãoIntraweb e escolha o modelo Application Form (figura 6).
Figura 6 Criando um novo formulário
Altere a propriedade Name do formulário para FmInclusao eBackGroundColor para $00DDFFFF. . Grave a unit com o nomeun_inclusao.
Insira os componentes que seguem no FmInclusao..
MeGAZINEMeGAZINEMeGAZINEMeGAZINEMeGAZINE2 22 22 22 22 2
DelphiDelphiDelphiDelphiDelphi
Agora vamos codificar o formulário.
Insira a unit DataModuleUnit na cláusula uses do formulário.
uses
ServerController, DatamoduleUnit;
No evento OnClick do objeto btDesiste insira o código que segue:
Hide;
Para que possamos retornar ao formulário de origem,utilizamos o método Hide do formulário.
Agora vamos codificar o evento OnClick do objeto btConfirma.
try
{Inclui Cliente}
with DataModule1.SQLInclui do
begin
ParamByName(‘prazao’).Value:=edRazao.Text;
ParamByName(‘pendereco’).Value:=
edEndereco.Text;
ParamByName(‘pcidade’).Value:=edCidade.Text;
ParamByName(‘pestado’).Value:=edUf.Items
[edUf.ItemIndex];
ParamByName(‘pcep’).Value:=edCep.Text;
ParamByName(‘pemail’).Value:=edEmail.Text;
ExecSQL;
end;
WebApplication.ShowMessage(‘Cliente incluido
com sucesso’,smSameWindow);
except
WebApplication.ShowMessage(‘Houve um problema
na inclusão do cliente’, smSameWindow);
end;
Hide;
Vamos analisar o código.
MeGAZINEMeGAZINEMeGAZINEMeGAZINEMeGAZINE 2 32 32 32 32 3
DelphiDelphiDelphiDelphiDelphi
Nesta primeira parte, iniciamos um bloco protegido.
try
Em seguida, estamos atribuindo parâmetros ao objetoSQLInclui do DataModule1.
{Inclui Cliente}
with DataModule1.SQLInclui do
begin
ParamByName(‘prazao’).Value:=edRazao.Text;
ParamByName(‘pendereco’).Value:=
edEndereco.Text;
ParamByName(‘pcidade’).Value:=edCidade.Text;
ParamByName(‘pestado’).Value:=edUf.Items
[edUf.ItemIndex];
ParamByName(‘pcep’).Value:=edCep.Text;
ParamByName(‘pemail’).Value:=edEmail.Text;
E finalmente executando a operação e apresentando amensagem de sucesso na operção.
ExecSQL;
WebApplication.ShowMessage(‘Cliente incluido com
sucesso’,smSameWindow);
Figura 7 Formulário inclusão de clientes
Em caso de erro, estamos criando o bloco except.
except
WebApplication.ShowMessage(‘Houve um problema
na inclusão do cliente’, smSameWindow);
end;
E apresentando a mensagem do problema.
A figura 7 ilustra o nosso formulário de inclusão de clientes.
Concluímos a primeira parte do nosso tutorial. Até apróxima.
Imensa luz e sucesso a todos.
Sobre o autorEmerson Facunte é Consultor de Tecnologia
com diversos livros publicados, especialista emdesenvolvimento de aplicações e-businessutilizando a ferramenta Delphi, baseado emwebSnap, dataSnap, BizSnap e ISAPI/ApacheModules.
MeGAZINEMeGAZINEMeGAZINEMeGAZINEMeGAZINE2 42 42 42 42 4
DelphiDelphiDelphiDelphiDelphi
O Object Repository torna mais fácil o compartilhamento deformulários, caixas de diálogo, frames e data modules. Eletambém fornece templates para novos projetos e wizards queguiam o usuário na criação de forms e projetos. O repositório émantido no arquivo Delphi32.dro que fica por default nosubdiretório \BIN. Este arquivo é do tipo texto que contém asreferências para itens que aparecem na caixa de diálogoRepository e New Items.
Compartilhando itens dentro de um projetoVocê pode compartilhar itens dentro de um projeto sem que
seja necessário adicioná-los ao repositório. Quando você abre acaixa de diálogo New Itens, File | New | Other, você verá umapágina com o nome do seu projeto. Esta página lista todos osforms, data modules constantes no seu projeto. Você pode derivarum novo item a partir de um item já existente e modificá-lo deacordo com a sua necessidade.
Adicionando itens ao Object RepositoryVocê pode adicionar seu próprio projeto, forms, frames e data
modules para aqueles já disponíveis no Object Repository. Paraadicionar um item ao Object Repository faça o seguinte:
1 – Se o item é um projeto ou está em um projeto, abra oprojeto.
2 – Para um projeto, escolha Project | Add To Repository.Para um form ou data module, clique com o botão direito no iteme escolha a opção Add To Repository.
3 – Digite uma descrição, titulo e autor.
4 – Informe em qual página você quer que o item apareça nacaixa de diálogo New Item, então digite o nome da página ouselecione alguma que esteja disponível no combobox Page. Se vocêdigitar o nome de uma página que não exista, o Object Repositorycriará uma nova página.
5 – Escolha Browse para selecionar um ícone pararepresentar o objeto no Object Repository.
6 – Clique em OK.
Compartilhando objetosVocê pode compartilhar objetos com o seu grupo de trabalho
ou time de desenvolvimento tornando o repositório disponível narede. Para utilizar um repositório compartilhado, toda a equipedeve acessar o mesmo diretório compartilhado. Sendo assim façao seguinte:
1 – Com o Delphi aberto escolha a opção Tools | EnvironmentOptions.
2 – Na página Preferences, localize o painel SharedRepository.
Em Directory informe o diretório onde você quer localizar orepositório compartilhado. Esteja ciente de informar um diretórioonde toda a equipe de desenvolvimento tenha acesso.
A primeira vez que um item for adicionado ao repositório, umarquivo DELPHI32.DRO será criado no diretório que estácompartilhado.
Usando um item do Object Repository no projeto
Usando oUsando oUsando oUsando oUsando oObject RepositoryObject RepositoryObject RepositoryObject RepositoryObject Repository
Por Claudinei Rodrigues
MeGAZINEMeGAZINEMeGAZINEMeGAZINEMeGAZINE 2 52 52 52 52 5
DelphiDelphiDelphiDelphiDelphi
Para acessar um item no Object Repository, escolha File |New | Other.
A caixa de diálogo New Items aparecerá mostrando todos ositens disponíveis. Dependendo do tipo de item que você queirausar, você terá três opções para adicionar o item ao seu projeto:
· Copy· Inherit· Use
Copy - Copiando um itemEscolha Copy para fazer uma cópia exata de um item
selecionado e adicioná-lo em seu projeto. Futuras modificaçõesfeitas no item no Object Repository não serão refletidas em suacópia e as alterações feitas na cópia não irão alterar a original.
Inherit - Herdando um itemEscolha Inherit para derivar uma nova classe a partir de um
item selecionado no Object Repository e adicionar uma novaclasse para o seu projeto. Quando você recompila o seu projeto,qualquer modificação que tenha sido feita para o item no ObjectRepository será refletida em sua classe derivada. As modificaçõesfeitas na classe derivada não terão efeito no item do ObjectRepository. Inherit está disponível para forms, caixa de diálogo edata modules, mas não para projetos. Esta opção é apenas parareutilização de itens dentro de um mesmo projeto.
Use - Usando um itemEscolha a opção Use quando você quiser que o próprio item
selecionado torne-se parte de seu projeto. As modificações feitasneste item serão refletidas em todos os projetos que tem este itemadicionado. Utilize esta opção com muita atenção. A opção Useestá disponível para forms, caixa de diálogos e data modules.
Usando templates de projetosOs templates são projetos pré-designados que você pode usar
como ponto de partida para novos projetos. Para criar um novoprojeto a partir de um template, faça o seguinte:
1 – Escolha File | New | Other para que você tenha acesso acaixa de diálogo New Items.
2 – Escolha a página Projects.3 – Selecione o projeto de template que você quer e pressione
OK.4 – Na caixa de diálogo Select Directory, informe um diretório
onde será armazenado o novo projeto.
Os arquivos de template são copiados para o diretórioespecificado, onde você poderá modificá-los. O projeto original nãoserá afetado.
Modificando os itens compartilhados.Se você modificar um item no Object Repository, sua
modificação irá afetar a todos os novos projetos que usem esteitem assim como os projetos existentes que tenham adicionado oitem com a opção Use ou Inherit. Para evitar a propagação demodificações para outros projetos, você pode fazer o seguinte.
· Copie o item e modifique-o apenas no projeto corrente.· Copie o item para o projeto corrente, modifique-o, e então
adicione-o ao repositório com um outro nome.
Especificando um projeto default, um novo form e um novoform principal
Por default, quando você escolhe File | New | Application ouFile | New | Form, um form em branco aparece.
Você pode modificar este comportamento reconfigurando orepositório.
1 - Vá até o menu do Delphi e clique em Tools|Repository.2 – Se você quiser especificar um projeto default, selecione a
página Projects e escolha um item abaixo de Objects. Entãoselecione o checkbox New Project.
3 – Se você quiser especificar um form default, selecione umapágina do repositório como por exemplo Forms, selecione ocheckbox New Form. Para especificar o form principal para onovo projeto, selecione o checkbox Main Form.
4 – Agora clique em OK.
ConclusãoEste artigo tem o objetivo de oferecer uma explanação sobre o
trabalho com o repositório de objetos. Mais uma opção do Delphique nos auxilia muito no dia a dia. E pra você que ainda nãoconhecia, com certeza isto também lhe será muito útil.
Sobre o autorClaudinei Rodrigues,Consultor Técnico do The [email protected]
MeGAZINEMeGAZINEMeGAZINEMeGAZINEMeGAZINE2 62 62 62 62 6
Perguntas & RespostasPerguntas & RespostasPerguntas & RespostasPerguntas & RespostasPerguntas & Respostas
Pergunta: Migrei minha aplicação para o IntraWeb 5 eencontrei uma série de problemas. Quais os passos necessáriospara compatibilizar minha aplicação com o IW5?
Resposta: O primeiro passo é ignorar todos os avisos queforem gerados ao abrir o IWForm. Após isso, acesse o arquivo deprojeto DPR e faça as seguintes alterações:
{ Versão Anterior }
program Fishfact;
uses
IWInitStandAlone,
Main in ‘Main.pas’ {formMain: TIWFormModuleBase},
ServerController in ‘ServerController.pas’
{IWServerController: TIWServerControllerBase};
{$R *.res}
begin
IWRun(TFormMain, TIWServerController);
end.
{ Nova Versão }
program Fishfact;
uses
DBClient,
Forms,
IWMain,
Main in ‘Main.pas’ {formMain: TIWFormModuleBase},
ServerController in ‘ServerController.pas’
{IWServerController: TIWServerControllerBase};
{$R *.res}
begin
Application.Initialize;
Application.CreateForm(TformIWMain, formIWMain);
Application.Run;
end.
Agora, abra o formulário principal do projeto IW e adicione aseguinte instrução, antes do final da unit, ou seja, anotes “end.”:
initialization
TformMain.SetAsMainForm;
è TformMain é a classe do seu formulário principal.
Agora, abra o seu ServerController...
{ Versão Anterior }
unit ServerController;
{PUBDIST}
interface
uses
SysUtils, Classes, Forms, IWServerControllerBase;
MeGAZINEMeGAZINEMeGAZINEMeGAZINEMeGAZINE 2 72 72 72 72 7
type
TIWServerController =
class(TIWServerControllerBase)
private
public
end;
implementation
{$R *.dfm}
end.
{ Nova Versão }
unit ServerController;
{PUBDIST}
interface
uses
SysUtils, Classes, Forms, IWServerControllerBase;
type
TIWServerController =
class(TIWServerControllerBase)
private
public
end;
implementation
{$R *.dfm}
initialization
TIWServerController.SetServerControllerClass;
end.
Pronto, com isso poderá recompilar e executar a aplicaçãosem problemas!
Dúvida enviada por AT&M Informática Ltda, Sapiranga/RS.
Pergunta: Encontrei um código para registrar um arquivoOCX no registro do Windows mas o mesmo não estáfuncionando! Gostaria de saber o que está errado ou caso tenhaoutro código que faça a mesma coisa, favor me enviar.
Os erros gerados durante a compilação são os seguintes:
[Error] Unit1.pas(30): Undeclared identifier:
‘TDllRegisterServer’[Warning] Unit1.pas(34): Comparing signed and unsigned
types - widened both operands[Fatal Error] Project1.dpr(5): Could not compile used unit
‘Unit1.pas’
Resposta: As classes mencionadas da mensagem de errofazem parte da unit ActiveX, assim sendo, bastará declarar aunit “ActiveX” na lista de units que irá compilar sem problemas.
implementation
uses ActiveX;
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
var
OCXHand: THandle;
RegFunc: TDllRegisterServer;
begin
OCXHand := LoadLibrary (‘SeuArquivo.ocx’);
RegFunc:= GetProcAddress
(OCXHand, ‘DllRegisterServer’);
if RegFunc < 0 then
ShowMessage(‘Erro!’);
FreeLibrary (OCXHand);
end;
Dúvida enviada por Atual Tecnologia Em Informatica,Araçatuba/SP.
Pergunta: Gostaria de saber como verificar a versão doDAO instalado na máquina.
Resposta: Para retornar a versão do DAO instalado namáquina, poderemos tentar instanciar um objeto DAO via OLEAutomation, veja o código a seguir:
implementation
Uses comObj;
{$R *.DFM}
procedure TForm1.Button1Click(Sender: TObject);
const
DAOConst36 = ‘DAO.DBEngine.36’;
DAOConst35 = ‘DAO.DBEngine.35’;
var DBEngine: Variant;
begin
try
DBEngine := CreateOLEObject(DAOConst36);
Perguntas & RespostasPerguntas & RespostasPerguntas & RespostasPerguntas & RespostasPerguntas & Respostas
MeGAZINEMeGAZINEMeGAZINEMeGAZINEMeGAZINE2 82 82 82 82 8
// DBEngine := CreateOLEObject(DAOConst35);
showmessage( ‘DAO, versão ‘+DBEngine.Version+’
está instalado’ );
except On E: Exception do
ShowMessage(E.Message+’ DAO não instalado ‘);
end
end;
Dúvida enviada por Elmar Processamento De Dados Ltda,João Pessoa/PB.
Pergunta: O gerador de relatórios Report Builder possuirecursos para que o usuário final possa desenvolver seus própriosrelatórios, inclusive gerando consultas SQL. Porém, não estouconseguindo utilizá-lo corretamente com dbExpres e IBExpressvisto estar apresentando alguns problemas. O que necessito fazerpara utilizar o RB corretamente com estas engines de acesso?
Resposta: Para utilizar o acesso ao DBExpress e IBExpresspelo Report builder do Delphi7 devemos adicionar os pacotesreferentes a esses acessos, pois os mesmos não foram adicionadosao Delphi. Portanto para adicioná-los devemos fazer os seguintespassos:
Instalando o DBExpress:Abra o Delphi e acesso o menu Component opção Install
Packages, clique no botão Add e no diretório do System ouSystem32 do Windows selecione o arquivo rbDBE77.bpl
Instalando o IBExpress:Para o IBExpress foi necessário abrir o DPK e compilá-lo, pois
somente adicionando o pacote ocorreu um erro devido a diferençade versões. Portanto selecione no Delphi o menu File opção Open,depois no diretório Source do Report Builder selecione o arquivorbIBE77.dpk. Estando com o pacote aberto clique no botãoCompile e depois no botão Install e pronto pode fechar o pacote,pois o mesmo já está instalado no delphi.
Fazendo esses dois passos você habilitará o acesso do ReportBuilder do Delphi7 para o DBExpress e IBExpress.
Dúvida enviada por Procel Informática Ltda, Florianópolis/SC.
Pergunta: Gostaria de saber como obter a lista dos tipos depapéis disponíveis no QuickReport.
Resposta: No caso do QReport, o mesmo possui uma
tipagem própria com nomes dos papeis que não coincidem com ostipos pré-definidos no Windows. Assim sendo, adicione estesvalores “fixos” ao seu ComboBox, pois, estes são dos tipos possívelaceitos pelo QR:
TQRPaperSize = (Default, Letter, LetterSmall,
Tabloid, Ledger, Legal, Statement, Executive, A3,
A4, A4Small, A5, B4, B5, Folio, Quarto, qr10X14,
qr11X17, Note, Env9, Env10, Env11, Env12,
Env14, CSheet, DSheet, ESheet, Custom)
Para pegar o valor do ComboBox e alterar no QReport, utilizeo seguinte:
implementation
uses QrPrNtr, TypInfo;
{$R *.dfm}
procedure SetPaper(const PaperName: string; QR:
TQuickRep);
var
Paper : TQRPaperSize;
begin
Paper := TQRPaperSize(GetEnumValue(TypeInfo
(TQRPaperSize),PaperName));
QR.Page.PaperSize := Paper;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
SetPaper(‘LetterSmall’, QuickRep1);
// ou
SetPaper(ComboBox.Items[ComboBox.ItemIndex],
QuickRep1);
end;
Dúvida enviada Elson Carlos Almeida, Irecê/BA.
Pergunta: Tentei abrir a seguinte instrução e ocorreu umerro:
select codigo , sum(quantidade) from tabela1
where (sum(quantidade))>100
group by codigo
Constatei que é pela cláusula “where”, então pergunto, não épossível fazer where por campo calculado? Qual a maneiracorreta de abrir uma instrução do tipo? Onde o campo a sercomparado é um SUM?
Perguntas & RespostasPerguntas & RespostasPerguntas & RespostasPerguntas & RespostasPerguntas & Respostas
MeGAZINEMeGAZINEMeGAZINEMeGAZINEMeGAZINE 2 92 92 92 92 9
Resposta: A condicional referente ao SUM deve seraplicada ao GROUP BY e não na cláusula where. Isso pode serfeito através da cláusula HAVING (que funciona como umWHERE para o GROUP), veja abaixo:
SELECT Company, SUM(sales) AS TOTALSALES
FROM Sales1998
WHERE (State = “CA”)
GROUP BY Company
HAVING (SUM(Sales) >= 1000)
ORDER BY Company
Dúvida enviada por CyberSul - Soluções em Informática,Porto Alegre/RS.
Pergunta: Com faço para ativar/desativar uma triger noInterbase, via programação Delphi.
Resposta: Poderá utilizar o componente IBScript e nesteadicionar a seguinte instrução para desativar sua trigger:
ALTER TRIGGER SUA_TRIGGER
INACTIVE BEFORE INSERT POSITION 0
AS
BEGIN
/* instruções da Sua_Trigger */
END
Para executar utilize:
IBScript.ExecuteScript;
Dúvida enviada por Sinval Alcântara Lopes, São Paulo/SP.
Pergunta: Por que quando eu vou digitar algum códigopara um evento qualquer no Delphi 7 ele coloca automaticamentelogo após a palavra “begin” a palavra de herança “inherited”?
Exemplo:
procedure
TFormCadastroCidade.IBQueryQtdSecoesNUMERO_SECOESGetText(
Sender: TField; var Text: String; DisplayText:
Boolean);
begin
inherited; // <-
end;
Resposta: Isso ocorre porque possivelmente o Sr. estejatrabalhando com herança de formulários, ou seja, oTformCadastroCidade foi herdado com opção inherit a partir deum outro formulário.
Quando trabalhamos com este tipo de arquitetura, o Delphiinsere esta chamada automaticamente, porque ele “imagina” quevocê possa ter um código no formulário “base” que deverá serexecutado neste formulário herdado.
Por exemplo, no formulário “base” você possui no eventoOnClose a instrução:
Action := CaFree;
Em todos os formulários herdados a partir deste formulário“base”, automaticamente irão executar esta mesma instrução.Suponhamos que em um destes formulários herdados vocênecessite acrescentar algum código específico:
Inherited;
ShowMessage(‘Meu Código!’);
A cláusula Inherited irá forçar a execução do código originalexistente no formulário “base” e logo em seguida o seu códigoespecífico.
A cláusula Inherited irá aparecer nos formulários herdados,mesmo que não haja código para aquele evento no formulário“base”, contudo, não trás nenhum problema e recomendo nãoremovê-la.
Dúvida enviada por Rodrigo José Marques, Itaúna/MG.
Pergunta: Conforme exemplo que estou envinado emanexo, estou tentando alterar uma Query, mas ao tentar fazeresta operação, ocorre a seguinte mensagem: Query: Canoot modify a read-only dataset.
Gostaria que vocês me apontassem o que estou fazendo deerrado neste programa.
Resposta: Quando adicionamos instruções um pouquinhomais complexas em um Query, como exemplo um ORDER BY, amesma tornar-se-a read-only. Nestes casos, para que possamoseditá-la é necessário utilizar um componente UpdateSQL, bemcomo alterar a propriedade CachedUpdates da Query para True.Veja seu projeto com esta implementação.
Dúvida enviada por Infoque Informatica Produtos ServicosLtda, São Roque/SP.
Perguntas & RespostasPerguntas & RespostasPerguntas & RespostasPerguntas & RespostasPerguntas & Respostas
MeGAZINEMeGAZINEMeGAZINEMeGAZINEMeGAZINE3 03 03 03 03 0
Perguntas & RespostasPerguntas & RespostasPerguntas & RespostasPerguntas & RespostasPerguntas & Respostas
Pergunta: Usando o Interbase tem como fazer segurançade tabelas a nível de registro? Exemplo: Temos um cadastro deconta bancaria. Alguns usuários poderão acessar apenas a conta“25889-3” E outros usuários poderão acessar apenas a conta“71658-9”. Hoje temos no sistemas segurança a nível de tela e debotão, mas não sabemos como dar acesso a nível de registro, comopoderíamos fazer isso?
Resposta: Infelizmente não existe este tipo de controle porparte do Interbase, sendo necessário você efetuar um controle“manual” para seus usuários. Uma alternativa seria você criaruma tabela onde ficarão cadastrados seus usuários/senhas, euma tabela “detalhe” ligada a esta tabela onde irão ficar asconfigurações a que cada usuário terá direito. Dessa forma, aoiniciar o aplicativo você irá solicitar o login do usuário e tendocom isso as opções que o mesmo poderá ter acesso. No casoespecífico de “registros”, ao entrar no formulário de contas,recomendaria você utilizar um componente Query com um“Select” que não mostre nenhum registro a princípio:
Select * From Contas where ID is null;
Quando o usuário acessar o Form, você irá solicitar umapesquisa para que o mesmo escolha a conta que deseja acessar.Após a pesquisa, faça uma comparação entre a conta escolhida ea conta configurada na tabela de permissões e caso não hajarestrição, permita ou não o acesso.
Temos um exemplo de controle de usuários publicado emnossa revista de Junho/2003 “Acesso - Controlando eIdentificando Usuários”. Caso não possua a revista poderáacessar em nosso site, www.theclub.com.br.
Dúvida enviada por New Century Gestão e Informática,Santo André/SP.
Pergunta: Como faço pra construir aqueles forms comformato e desenhos diferenciados, como imitando um aparelho desom, com fundo semelhante a metal lixado, cantos arredondados,contornos e coisas do tipo? Como exemplo, veja o form usado noQuick Time, Media Player, etc. Tentei deixar meu formtransparente, e deu pra causar alguns efeitos, mas o que maisposso fazer? Inserir um BMP no form com o formato desejado?
Resposta: Estas aplicações trabalham com “Skins” quepossibilitam “moldar” o formulário de acordo com imagens. Existeuma suite de componentes da empresa KsDev que possibilitamudar a aparência dos formulários via Delphi. Poderá baixaruma cópia de avaliação no site do fabricante, www.ksdev.com,não é gratuíto.
Existe um outro componente chamado “Scheme VCL” o qualé gratuíto, porém, mais simples. Poderá baixar em: http://www.torry.net/vcl/forms/effects/ksscheme.zip.
Dúvida enviada por Samuel Della Savia de Oliveira, SãoPaulo/SP.
Pergunta: Gostaria de fazer um cálculo registro a registrono Rave Report imprimindo a diferença de dias entre uma datagravada em um campo e a data atual do sistema. Como possofazer isso?
Resposta: Isso poderá ser feito programando o eventoOnGetRow do componente RvCustomDataSet, onde iremospesquisar os componentes “dentro” do projeto Rave e atribuirvalores aos mesmos. Exceto o fato de termos que pesquisarcomponentes, a abordagem fica bem parecieda com o queestamos acostumados a fazer no QuickReport. Veja o código aseguir:
implementation
uses RVClass, RVProj, RvCsData;
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
begin
rvTestes.ExecuteReport(‘Rep_Employee’);
end;
// evento OnGetRow do componente RvDataSetConnection
procedure TForm1.rvdsEmployeeGetRow(Connection:
TRvCustomConnection);
var
Dias: Double;
P: TRavePage;
D: TRaveDataText;
begin
// Pesquisa o Report e a Página.
P := RvTestes.ProjMan.FindRaveComponent
(‘Rep_Employee.MainPage’, nil) as TRavePage;
// Localiza o DataText D := RvTestes.ProjMan.FindRaveComponent
(‘DataText4’, P) as TRaveDataText;
// Cálcula # dias
Dias := Date - tabEmployee.FieldByName
(‘HireDate’).AsDateTime;
// Atribui ao Datatext
D.Text := FormatFloat(‘000’, Dias);
Connection.DoGetRow; end;
Dúvida enviada por Denis Fonseca Loureiro, Salvador/BA.