32
Outubro 2009

The Club - megazine · da paleta Additional, altere o align do BitBtn para alRigth e o caption para “Imprimir Mala Direta”, para o primeiro label altere o caption para “Dados

Embed Size (px)

Citation preview

Outubro 2009

Outubro 2009

Outubro 2009 03

Delphi

InfoNews

.NET

.NET

Delphi

Explorando Records em Delphi 2009

16Autor: Antonio Spitaleri

Desafio The Club

- Sudoku

Dicas Delphi

- Alterar propriedade buttonstyle das toolbars liga-das ao actionma-nager em tempo de execução:- Criando uma...

índiceSistema de contatos com mala direta

Editorial Delphi

06Qual desenvolvedor nunca se apavorou só com a hipótese de ter perdido uma base de dados do cliente? E quando este pesadelo se tornou realidade, quantas horas de... 04

Rapidinhas

05Journaling System - A solução definitiva contra perda de dados - parte I 12

Herança Visual de formulários em Windows Forms

20Acesso a dados com JQuery

26 29 30LegendaInicianteIntermediárioAvançado

Autor: Mateus André Chies

Autor: Felipe Santos Autor: Luciano Pimenta

Autor: Djonatas Tenfen

Autor: Vitor Manuel Rodrigues

Outubro 200904

Bem-vindo

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

pelos seus respectivos proprietários.

Marcos César Silva - Editor [email protected]

Olá amigos

Qual desenvolvedor nunca se apavorou só com a hipótese de ter perdido uma base de dados do cliente? E quando este pesadelo se tornou realida-de, quantas horas de trabalho e às vezes até de sono formam perdidas, muitas vezes sem sucesso, tentando recuperar os precisos dados de nosso cliente. Assim neste mês em nossa matéria de capa “Journaling System – A solução definitiva contra perda de dados”, Felipe Santos aborda no caso de falhas ambientais que possam corromper nossos banco de dados, a prevenção, recuperação e restauração do banco de dados Interbase o uso da tecnologia Journaling System.

Nosso consultor Antonio Spitaleri com seu artigo “Explorando Records em Delphi 2009”, dá uma aula conceitual sobre as estruturas do tipo records, discutindo desde detalhes técnicos de sua criação e alocação de memória até comparações com o uso de classes.

Agora para os programadores iniciantes que sempre pedem projetos de exemplo, algo que possam trazer para o mundo real, o nosso colunista Mateus André Chies, criou um projeto de exemplo que se transformou no artigo “Sistema de contatos com mala direta”, neste artigo Mateus mostra, posso a posso, desde a criação do banco de dados ate a configuração dos componentes, além é claro de como criar uma solução para organizar nossos contatos.

E nossa sessão .Net Luciano Pimenta mostras uma técnica muita usado pelos programadores Delphi agora em .net, que é o uso do con-ceito de Herança da Programação Orientada a Objetos (POO), para o reaproveitamento de formulários com características semelhantes como é o caso de formulários de cadastro, neste seu artigo “Herança Visual de formulários em Windows foms”, Luciano dá uma ótima contribuição para os programadores novatos em .Net que pretendem iniciar novos projetos com herança visual.

Também em nossa sessão .Net temos também o artigo “Acesso a da-dos com JQuery” de nosso colunista Djonata Tenfen, que segue na sua seqüência de artigos abordando a tecnologia JQuery.

Boa leitura e até o próximo mês, abraço a todos.

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

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

Internethttp://www.theclub.com.br

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

Skype Suporte: theclub_linha1 theclub_linha2 theclub_linha3

www.twitter.com/theclubbr

Copyright The Club Megazine 2009

Diretor TécnicoMarcos César Silva

Diagramação e ArteVitor M. Rodrigues

RevisãoTassiane Fileto

ColunistasAntonio Spitaleri Neto

Djonatas TenfenFelipe Santos

Luciano PimentaMateus André ChiesVitor M. Rodrigues

Impressão e acabamento:GRIL - Gráfica e Editora

Taquarituba-SP - Tel. (14) 3762-1345

ReproduçãoA utilização, reprodução, apropriação, armazenamento em banco de dados, sob qualquer forma ou meio, de textos, fotos e outras criações intelectuais em cada publicação da revista “The Club Megazine” são terminantemente proibidos sem autorização escrita dos titulares dos direitos autorais.

Outubro 2009 05

InfoNews

Nota Fiscal Eletrônica

A vilã do momento é a NFe. Alguns já estão utilizando, ou-tros estão implantando e muitos ainda terão de implantar.

A dica é simples, não deixe para última hora, se o seu sistema não está integrado com a NFe, e se nenhum cliente solicitou essa é hora de correr atrás. Os contadores estão avisando os empresários em cima da hora sobre a obrigato-riedade de implantação da NFe, e ainda estão jogando toda a responsabilidade em cima dos desenvolvedores, tirando o corpo fora da questão. E como já bem sabemos, para o cliente “tudo é fácil, é só um botãozinho”, e sabemos que a coisa não é assim.

Então se prepare, já avise seus clientes sobre como será o processo de implantação, custos adicionais e informações sobre a NFe.

1º Delphi Conference

Corre a informação de que a Embarcadero promoverá um encontro para os desenvolvedores Delphi será o “1º Delphi Conference”, até o fechamento desta edição ainda não havia sido divulgado data nem local, o que se sabe é que será no mês de novembro de 2009 e que tem vários nomes de peso para apresentação das palestras. Então se prepare, pois esse evento promete muito.

RapidinhasDelphi no Windows 7

Estamos testando já há algum tempo o Delphi no Windows 7 e os resultados são positivos, ele se mostra um sistema estável, ágil e segundo nossos técnicos está rodando o Delphi sem problema. Diferente do que acontece no Windows Vista. Portanto se alguém ainda estava com medo de instalar o Windows 7, pode rodar sem medo.

Outubro 200906

Delphi

Neste artigo irei demonstrar uma ma-neira fácil e útil de se armazenar os contatos dos cartões pessoais que recebemos de empresa e pessoas. Muitas vezes guardamos em gavetas, onde muitos são extraviados, ou os mais organizados compram porta cartões para guardar os cartões de visitas.

Criando o Banco de Dados

Vamos lá, a base do sistema será em banco de dados Firebird 1.5, utilizando Delphi 2007 para o desenvolvimento, vamos modelar conforme a listagem 1, onde temos a criação e definição do GENERATOR, posteriormente temos a tabela e seus atributos com seus respectivos tipos de dados, ainda temos a criação da chave primária e do gatilho que é acionado no evento de Inserir os dados na tabela.

Sistema de Contatos com Mala Direta

Listagem 1: Criação do Banco de Dados

****Generated by IBExpert****/SET SQL DIALECT 3;SET NAMES NONE;SET CLIENTLIB ‘fbclient.dll’;CREATE DATABASE ‘127.0.0.1:C:\BANCO\CONTATOS.FDB’USER ‘SYSDBA’ PASSWORD ‘masterkey’PAGE_SIZE 4096DEFAULT CHARACTER SET NONE;/****Generators****/CREATE GENERATOR GEN_CONTATOS_ID;SET GENERATOR GEN_CONTATOS_ID TO 8;/****Tables****/CREATE TABLE CONTATOS ( CODIGO INTEGER NOT NULL,

NOME VARCHAR(100), ENDERECO VARCHAR(200), NUMERO INTEGER, BAIRRRO VARCHAR(30), CEP VARCHAR(9), CIDADE VARCHAR(60), UF VARCHAR(2), FONE VARCHAR(13), FAX VARCHAR(13),

CELULAR VARCHAR(13), EMAIL VARCHAR(75), SITE VARCHAR(250),

ATIVIDADE VARCHAR(200));/****Primary Keys****/ALTER TABLE CONTATOS ADD CONSTRAINT PK_CONTATOS PRIMARY KEY (CODIGO);/****Triggers for tables****/

Outubro 2009 07

CREATE TRIGGER CONTATOS_BI FOR CONTATOSACTIVE BEFORE INSERT POSITION 0ASBEGIN IF (NEW.CODIGO IS NULL) THEN NEW.CODIGO = GEN_ID(GEN_CONTATOS_ID,1);END^SET TERM ; ^

Construindo nossa aplicação

Crie uma nova aplicação no Delphi 2007 através do menu File, New, VCL Forms Applica-tion, defina o width para 850 e o Heigth para 456 junto a palheta Object Inspector, agora salve sua aplicação utilizando a teclas de atalho Ctrl + Shift + S, para o .pas salve com uPrincipal, e para o projeto Contatos. Vamos começar montar o Layout da nossa aplicação, adicione 2 TPanel da palheta Standart da aba Tool Palete, remova o caption das duas Panel, e para uma defina a propriedade Align para alTop e a outra para alBottom, adicione um componente TPageControl da paleta Win32 e defina a propriedade Align para alClient, clique no centro PageControl e adicione duas páginas, clicando de direita e acessando o menu New Page, para a primeira altere o caption para “Contatos” e a segunda para “Dados”.

Adicione um componente Tlabel da paleta

Standart no panel superior, e defina a fonte através da propriedade Font da paleta object Inspector para tamanho 16pt, e estilo da fonte para negrito e altero o Caption para “Lista de Contatos”.

Selecione a página de contatos e adicione uma Tpanel, remova o caption e altere o align para alTop, adicione 4 Tlabel, 1 TEdit e mais um BitBtn da paleta Additional, altere o align do BitBtn para alRigth e o caption para “Imprimir Mala Direta”, para o primeiro label altere o caption para “Dados da Consulta:”, posicione o Edit logo abaixo do pri-meiro label, e altere o name para “edt_consulta”, posicione a segunda label logo abaixo do Edit e altere o caption para “Consultando por:”, posicione o terceiro label logo a direta o label anterior, altere o caption para “Selecione uma coluna clicando no título”, o name para “lbl_consulta” e a Font para cor vermelho, e estilo para negrito. Posicione o quarto label para próximo ao BitBtn de Imprimir, altere o name para “lbl_total”, nesse label vamos mostrar o total de registros. No centro dessa página vamos adicionar um TDbGrid da paleta Data Controls, e altere o align para alClient.

Muito bem, agora vamos configurar nossa conexão, adicione um TsqlConnection da paleta dbExpress, altere o name para “CON”, altere a propriedade LoginPrompt para “False”, e depois configure a conexão com o banco de dados criado. Adicione TSQLDataSet da mesma paleta, altera a propriedade name para “SQL”, configure o SQLConnection para “CON”, e na propriedade CommandText adicione o código da listagem 2, que é a instrução SQL para selecionarmos os dados do bando de dados criado.

Listagem 2: Command Text

select * from CONTATOS

Feito essas configurações, vamos adicionar

os campos no nosso SQL, duplo clique sobre o componente abrira uma janela, nessa janela clique de direita e acione o menu Add All Fields, agora é possível visualizar todos os campos da nossa tabela no banco de dados, selecione o campo CODIGO, acesse a propriedade ProviderFlags, pfInKey e altera para “true”, nosso SQL está pronto.

Agora adicione um TDataSetProvider da paleta Data Access, altere o name para “DSP” e configure o DataSet para “SQL”. Também adicione um TClientDataSet, altere o name para “CDS”, relacione a propriedade ProviderName com o DSP, duplo clique sobre ele e botão direito do mouse, Add All Fields, agora já temos todos os campos no nosso CDS, selecionando um campo de cada vez é possível altera a propriedade DisplayLabel para o Label que você deseja que aparece na DbGrid e junto aos campos, mas tome cuidado, não altere a propriedade FieldName. Agora ative o nosso CDS. E por último adicione um TDataSource da paleta DataAccess, altere o name para “DS” e configure a propriedade DataSet para “CDS”.

Agora basta ligar a propriedade DataSource da DBGrid com o nosso DataSouce DS e já é possível visualizar os nosso campos na DBGrid.

Vamos automatizar nosso operações, adicione um componente TImageList da paleta Win32, duplo clique sobre ele e através do botão Add adicione uma imagem relacionada a cada uma das seguintes operações Inserir, Editar, Cancelar, Salvar e Excluir. Mais tarde iremos utilizar essas imagens, para fins visuais.

Adicione um componente TActionList da paleta Standart, relacione a propriedade Images a nossa Lista de Imagens TImageList1. Através dessa lista de ações é que vamos acionar nossas transações com o banco de dados. Duplo clique sobre o

Outubro 200908

componente, abrirá uma nova janela, acesse New Standart Action, vamos adicionar as nossa ações, abrirá uma nova janela, role até encontrar o nó Dataset, com a tecla Ctrl pressionada selecione os seguintes itens, TDataSetInsert, TDataSetDelete, TDataSetEdit, TDataSetPoste e TDataSetCancel, clique em Ok.

Agora temos a lista das nossas ações, sele-cione DataSetInsert1 altere o caption para Inserir, relacione a propriedade DataSource ao DS, altere a propriedade Hint para Inserir e na propriedade ImageIndex selecione a imagem relacionada ao Inserir, agora basta repetir essas configurações para as demais ações, adequando-as as suas respectivas funcionalidade, nome e imagem.

Adicione 5 TBitBtn na panel inferior, confi-gure todos com Width 100 e heigth para 47, e respectivamente da esquerda para direta, altera a propriedade Action para as ações da lista de ações para Inserir, Editar, Cancelar, Salvar e Excluir. Salve o projeto. Ainda nessa panel inferior adicione um componente TDBNavigator, relacione o DataSource ao DS, e na propriedade VisibleButtons configure para true apenas os botões First, Prior, Next e Last, que são Primeiro, Anterior, Próximo e Último respectivamente, os demais altere para false. O formulário ficou similar a figura 1.

Veja a Figura 1: Formulário

Selecione o PageControl e clique na aba Da-dos, agora vamos adicionar os campos ao formu-lário, duplo clique sobre o CDS e selecione todos

os campos, e os arraste para o formulário e organize a disposição conforme a figura 2.

Veja a Figura 2: Cam-pos

Mas você deve estar

se perguntado, - Mas não vamos programar nada? Calma, vamos agora fazer as

implementações. Selecione o Form acesse o evento FormShow e vamos abrir

nosso CDS, forçar a sempre abrir com o PageCon-trol na página, que tem o DBGrid e adicionar a la-

bel lbl_total o total e registro que tem selecionado no DBGrid, implementado a listagem 3.

Listagem 3: FormShow

DS.DataSet.Open; PageControl1.ActivePage := TabSheet1; PageControl1.ActivePageIndex := 0; lbl_total.Caption := IntToStr(cds.RecordCount)+’ Regsitro(s)’;

Selecione o ClientDataSet, no evento After-Post, implemente a codificação da listagem 4, e no evento AfterDelete relacione com o evento AfterPost, essa implementação tem a função de grava no banco de dados cada vez que se aciona o botão Salvar ou Excluir.

Listagem 4: AfterPost

Figura 2: Campos

Figura 1: Formulário

Outubro 2009 09

CDS.ApplyUpdates(0); CDS.Close; CDS.Open;

Vamos fazer as implementações na DBGrid, no evento DblClick apenas codifique para acionar o botão de alterar, para quando estiver navegando sobre os registros e der duplo clique nele automa-ticamente entrará em modo de edição. Ainda na DBGrid no evento TitleClick, vamos implementar a listagem 5, para índex os dados pela coluna que foi selecionada, ainda preencher a lbl_consulta com o nome do campo selecionado, que servirá no filtro das informações.

Listagem 5: TitleClick

try (DS.DataSet as TClientDataSet).

IndexFieldNames := Column.FieldName; lbl_consulta.Caption := Column.FieldName; edt_consulta.SetFocus; except ShowMessage(‘Essa coluna não pode ser ordena!!!’); end;

Selecione o TEdit edt_consulta e vamos progra-mar nossa consultas personalizadas, que sempre que o algo é alterado em um TEdit é acionado o evento Change, utilizaremos esse evento para aplicar nosso filtros. Conforme Listagem 6.

Listagem 6: Filtros

try if edt_consulta.Text <> ‘’ then //Verifica se o campo não etsa vazio begin

cds.Filtered := False; //Desativa o filtro CDS.Filter := lbl_consulta.Caption+’ like ‘’%’+edt_consulta.Text+’%’’’;// Mosta o filtro // que sempre que

encontrar algo na coluna do DbGrid que foi selecionado cds.Filtered := True; //Aplica o filtro lbl_total.Caption := IntToStr(cds.RecordCount)+’ Regsitro(s)’;//Conta quanot regisro tens filtrado end else begin cds.Filtered := False; //Desativa o filtro lbl_total.Caption := IntToStr(cds.RecordCount)+’ Regsitro(s)’;//Conta quanot regisro tens filtrado end; except ShowMessage(‘A consulta não pode ser realizada!!!’+#13+’Selecione uma coluna na grade.’); end;

Agora vamos programar os nosso controles entre as abas do PageControl, esse controles serão implementados no evento StateChange do DataSource, DS. Sempre que o DS estiver em modo de Insert ou Edit vamos ativar a aba Dados e jogar o foco para o primeiro campo, caso contrário, voltamos o foco para a aba Contatos. Conforme a listagem 7.

Listagem 7: StateChange

if DS.DataSet.State in [dsEdit,dsInsert] Then

begin PageControl1.ActivePage := TabSheet2; PageControl1.ActivePageIndex := 1; TabSheet1.Enabled := False; TabSheet2.Enabled := True; DBEdit2.SetFocus;

end else begin PageControl1.ActivePage := TabSheet1; PageControl1.ActivePageIndex := 0; TabSheet1.Enabled := True; TabSheet2.Enabled := False; end;

Feito todas essas implementações, basta com-pilar e começar a inserir, alterar e excluir os dados do nosso banco de dados.

Vamos montar nossas etiquetas de Mala Direta dos nossos contatos, através do RaveReports, adi-cione um componente TRvProject altere o name para “RVREL”, adicione um TRvSystem e altere o name para RVSYS, relacione o componente RVREL na propriedade Engine com o “RVSYS”, e por último adicione um componente TRvDataSetConnection altere o name para “RVDSCDS”, na propriedade DataSet selecione o ClientDataSet “CDS”. Salve o projeto e de um duplo clique sobre o RVREL, o Rave abrira.

Já com o RaveReports aberto, salve o projeto com o nome de ETIQUETAS.rav, agora acesse o menu File – New Data Object, selecione Direct Data View, Next, aparece o componente RVDSCDS, selecione e Finish. Agora já temos uma conexão do RaveReposts com a nossa aplicação, que se conecta com o banco de dados.

Agora adicione um DataView1Region, con-figure do tamanho útil da página, adicione um

Outubro 200910

DataView1DataBand relacione a propriedade DataView com a DataView1, altere o Heigth para 0,800 e ainda altere a propriedade Columms para 2, dessa maneira o relatório será gerado em duas colunas. Agora vamos adicionar nossos campos. Pressionando a tecla Ctrl selecione os campos NOME, ENDERECO, NUMERO, BAIRRO, CIDADE, CEP e UF, arraste para dentro da DataBand e os disponha conforme a figura 3. Pressione F9 e reja o resultado do relatório, não esqueça que é neces-sário já ter dados cadastrados para poder melhor visualizar, salve o projeto.

Veja a Figura 3. Relatório De volta no Delphi, selecione o componente

RVREL, e na propriedade ProjectFile selecione o arquivo ETIQUETAS.rav, e no botão de Imprimir Mala Direta vamos acionar o relatório, conforme

Figura 3. Relatório

Figura 4: Resultado Final

Técnico em Informática, bacharelando em Sistemas de Informação.

Sobre o autor

Mateus André Chies

[email protected]

listagem 8, conforme os dados filtrados na DBGrid, então dessa maneira quando quiser imprimir eti-quetas para determinados registros, basta filtrar na DBgrid e imprimir.

Listagem 8. Imprimir

RVREL.Open; RVREL.SelectReport(‘Etiquetas’,False); RVREL.Execute;

Assim chegamos ao fim, agora basta executar-mos o sistema, cadastrar vários registros e imprimir

as etiquetas automaticamente. Veja resultado na figura 4.

Veja a Figura 4: Resultado Final Conclusão

O principal objetivo desse artigo e apresentar uma solução para organizar os cartões pessoais que guardamos, geralmente organizadamente, agora têm sempre a mão, basta acessar o sistema e consultar, quando desejar encontrar alguém que atue em determinada atividade, ou ramo. E ainda de forma automatizada pode se gerar etiquetas para enviar Mala Direta.

Outubro 2009 11

Outubro 200912

Olá pessoal,

Esse mês quero apresentar a vocês uma tecnologia realmente revolucionária da famí-lia de bancos de dados InterBase – o Sistema Journaling. Uma maneira definitiva de preve-nir, recuperar e restaurar ambientes inteiros em caso de corrupção, perda e até mesmo desastres contra nossos bancos de dados.

Que atire a primeira pedra quem nunca pas-sou por algum problema de corrupção de bancos de dados InterBase/Firebird? Ou mesmo outro SGDB? Noites e noites mal dormidas, recuperando bases de dados com validações, backups, restores ou mesmo com procedimentos ultra-sofisticados, como pumps de tabelas, extração de scripts e inserções manuais. E não estou falando apenas de grandes empresas, grandes bancos de dados. Os pequenos consumidores de bancos de dados sofrem também com dias ou mesmo meses de dados perdidos por conta de uma corrupção.

Então poderíamos pensar: O InterBase/Fire-bird não oferece segurança alguma! Precisamos de um gerenciador mais moderno, mais robusto!

É certo e comprovado que a grande maioria

dos problemas de corrupção de bancos de dados está relacionada à infra-estrutura. Seja por conta de falhas de discos, memória, gerenciamento de Sistemas Operacionais, panes elétricas, enfim. E por mais que possamos investir uma pequena fortuna preparando ambientes extremamente seguros, estaremos sempre sujeitos a esse tipo de problema.

Mas sim, cabe ao gerenciador de banco de dados oferecerem uma solução, uma opção mais segura aos seus usuários.

E é nesse ponto que entra o Sistema Jour-naling. Uma alternativa para aumentar significa-tivamente a seguranças de nossos ambientes e, em especial, nossos bancos de dados, com baixo investimento. Pois só quem perdeu sabe dizer quanto custa um dia de trabalho perdido. E apesar de ser revolucionário, o Sistema Journaling não é tão recente assim. Está disponível nos bancos de dados InterBase desde sua versão 2007, lançado há quase 3 anos.

Vamos durante esse artigo, que também di-vidiremos em duas partes, mostrar a fundo como funciona e como aplicar o Sistema Journaling na prática.

JOURNALING SYSTEM

Pois bem, o Sistema Journaling é uma tecnolo-gia embarcada no gerenciador de banco de dados InterBase que cria um ambiente para prevenção e recuperação possíveis falhas nos bancos de da-dos, causadas, como disse anteriormente, quase sempre devido à falhas de ambiente. Para o seu melhor funcionamento, o Sistema Journaling atua em duas partes. A recuperação de curto tempo, também conhecida como Short-Term-Recovery, e a recuperação de longo tempo – o Long-Term-Recovery. Vamos então entender e estudar suas principais características e aplicações.

SHORT-TERM-RECOVERY

Vejam como a idéia é bem simples. Ao ativar o Sistema Journaling, o InterBase irá desativar (se assim estiver configurado) a opção Forced Writes do banco de dados, forçando assim a gravação as-síncrona dos dados. Então o Sistema Journaling irá utilizar um espaço em disco, indicado por nós, para armazenar em tempo real todas as informações, todo o conteúdo de todas as transações aplicadas sobre o banco de dados, em arquivos chamados Journal Files. Sim, todas as transações e seus Inserts, Updates, Deletes, Creates, Drops, Alters e etc., antes de serem aplicadas no banco de dados,

Outubro 2009 13

seus conteúdos serão gravados nos Journal Files. Independentemente se essas transações serão depois confirmadas (comitts) ou canceladas (roll-backs). E para que? Mais simples ainda! Em caso de qualquer parada inesperada de sistema, como um pique de energia, um restart abrupto do ser-vidor, uma queda do serviço que seja, o InterBase e o Sistema de Journaling irá, automaticamente, aplicar no banco de dados, o conteúdo das tran-sações que estavam “no ar” no momento da pane, recuperando as informações que estavam sendo gravadas, atualizadas ou excluídas, garantindo assim a integridade do banco de dados. E são essas pequenas paradas, pequenas falhas que, em pouco tempo, tornam nosso banco de dados tão corrom-pido que sua recuperação se torna um verdadeiro desafio. Abaixo trago dois links importantes que tratam sobre as principais causas de corrupção de bancos de dados:

http://edn.embarcadero.com/article/29515

h t t p : / / w w w. i b p h o e n i x . c o m / m a i n .nfs?a=ibphoenix&page=ibp_err_problem

Mas se iremos gravar e criar arquivos Journal concorrendo com nosso banco de dados que está em produção, isso não irá trazer perda de perfor-mance? Não se criarmos de maneira correta.

CRIANDO O SISTEMA JOURNAL

Relembrando: o Sistema Journaling irá utilizar um espaço em disco indicado para criação de arquivos de Journal. Está aqui um ponto chave do processo. Definir esse espaço. Antes mesmo de começar a trabalhar, precisamos definir uma unidade, um disco onde serão criados os arquivos de Journal (Journal Files). E é imprescindível que

esse disco não seja o mesmo disco onde está lo-calizado o banco de dados de produção. Podemos então separar um novo disco, ligado ao mesmo computador, mas que esteja conectado à outra controladora, ou, de preferência, um outro disco ligado a outro computador, conectado ao nosso servidor InterBase através de uma conexão de rede estável e segura. Essa escolha é fundamental para que o Sistema Journaling não comprometa o desempenho de nosso ambiente.

Por ser algo novo, algo que nosso banco de dados não possui hoje, para ativar o sistema de Journal precisamos programar uma parada extremamente rápida do banco de dados que desejamos aplicar. É importante salientar que essa parada acontecerá apenas uma única vez. Então, uma vez que estamos com o banco exclusivo para nós, podemos utilizar comandos DDL ou mesmo o utilitário IBConsole para criação do Journal.

Segue abaixo um exemplo de comando para essa criação:

CREATE JOURNAL ‘d:\databases\journal\employee\emp’LENGTH 65000CHECKPOINT LENGTH 10000CHECKPOINT INTERVAL 120PAGE SIZE 8192

PAGE CACHE 2500PREALLOCATE 325000TIMESTAMP NAME Enabled;

• O comando Create Journal é seguido de um caminho. Esse caminho indica o local onde

serão gravados, gerados os arquivos Journal Files. No caso de nosso exemplo, esse caminho é o D:\databases\Journal\Employee. Na sequência apara a palavra Emp. Essa palavra servirá como prefixo aos nomes dos arquivos que serão gerados nessa pasta.

• O LENGTH (65000) define a geração de um novo arquivo de journal a cada 500MB (65000x8kb). O LENGTH default 500 gera um novo arquivo a cada 8MB. O tamanho de cada arquivo de journal vai depender do tamanho do banco de dados. É claro que se os arquivos de journal forem muito pequenos, mais arquivos serão gerados, o que pode gerar um problema de performance. Uma dica para definir o tamanho dos arquivos Journal é medir quanto cresce seu banco de dados por dia. Quanto maior for o crescimento/dia de seu banco, maior também deve ser o tamanho de cada Journal File. Pessoalmente não indico que seja inferior a 100 Mb.

• O CHECKPOINT LENGTH em 10000 significa que o checkpoint do banco irá ocorrer a cada 80MB (10000x8k). O CHECKPOINT LENGTH default é 500, isso significa uma checagem a cada 4M (500x8k). Este parâmetro é muito particular, pois define o número de bytes que será aplicado no banco após um crash do servidor e influenciará no tempo da recuperação automática em caso de pane. Sua definição dependerá se o Journal está sendo criado no mesmo servidor ou em outro, se local ou remoto.

• O CHECKPOINT INTERVAL é semelhante ao parâmetro anterior, porém determina o check-point em segundos e não em páginas. Você pode escolher uma das duas opções. Se as duas opções estiverem marcadas, o InterBase validará a que acontecer primeiro.

Outubro 200914

• O PAGE SIZE determina o tamanho da página interna de gravação dos arquivos de Jour-nal, semelhando ao pagesize do próprio banco de dados. O valor desse parâmetro deve ser sempre o dobro do tamanho do pagesize do banco de dados.

• O PAGE CACHE determina o número de páginas de Journal que serão armazenadas em cache. Esse parâmetro também é muito impor-tante, pois um cache pequeno pode ser tornar um problema de performance.

• O PREALLOCATE é a opção que temos de pré-alocar um espaço no disco de Journal. Basta multiplicar quantos arquivos de Journal desejamos pré-criar e multiplicar pelo valor indicado na opção LENGTH. Nesse exemplo iremos pré-alocar 5 arqui-vos de 500 Mb. Esse parâmetro é especialmente particular se o disco reservado para Journal tam-bém for utilizado por algum outro processo, evitan-do que acabe o espaço em disco inesperadamente. Quando esses cinco arquivos forem totalmente preenchidos, então novos arquivos serão criados um a um.

• E por fim o TIMESTAMP NAME Enable indica que os arquivos de Journal terão em seu nome uma gravação indicando o dia/mês/ano/hora/minuto e segundo em que foram criados.

Podemos também utilizar o utilitário IBConsole para realizar essa ativação do Sistema Journal:

Veja a Imagem 1.

Imagem 2 – Tela para configuração dos parâmetros

de ativação do Sistema Journaling

Veja a Imagem 3.

Logo após a criação do Journal, seu ambiente já poderá ser liberado para uso e, assim, instan-

Imagem 3 – Visualização do diretório onde foram gerados os Journal Files

Imagem 1 – Caminho para o Menu de criação do Sistema Journal

Outubro 2009 15

Felipe Santos é especialista em InterBase. Trabalha com o InterBase desde 2001. atuando como consultor e instrutor do produto em todo Brasil. Especialista em ambientes críticos. Atua e trabalha com os maiores clientes do InterBase no Brasil. Participante ativo na comunidade, com diversos artigos publicados. Participante do grupo de beta testers mundial do produto. Palestrante em eventos como IB Tour, Borcon Conference, CodeRage Latin América, Delphi Developers Day, Linux Day, entre outros. Atualmente trabalhando na área técnica do InterBase na Presence Tecnologia – agente oficial especializado do produto no Brasil.

Sobre o autor

Felipe Santos

[email protected]

Imagem 4 – Arquivo InterBase.Log contendo um trecho onde o Sistema Journaling foi utilizado.

taneamente, seus Journal Files começaram a ser utilizados. No exemplo acima podemos verificar que no diretório reservado foi criado:

• Um arquivo chamado IB_JOURNAL, que será o responsável pelo gerenciamento o sistema Journal,

• Um arquivo chamado EX.2009-10-05T23-02-20Z.1.JOURNAL que é nosso primeiro Journal File já criado com o tamanho determinado no passo anterior.

• 5 a r q u i v o s EX.PREALLOCATED.X.JOURNAL que são os cinco arquivos que já deixamos pré-alocados. Quando o Sistema Journal começar a utilizar esses arquivos, os mesmo serão automaticamente renomeados para o padrão do primeiro arquivo.

Agora, e daqui para frente, todas as transa-ções desse banco de dados irão alimentar nossos arquivos de Journal.

Em caso de uma eventual falha o Sistema Jour-nal irá executar o processo de Short-Term-Recovery

para aplicar as últimas transações que foram perdi-das no processo. A imagem abaixo mostra trecho do arquivo de Log do InterBase (Interbase.Log) que exibe o momento em que o Sistema Journal realizou a recuperação de curto tempo:

Veja a Imagem 4.

São apenas três passos: 1 - Iniciando o proces-so. 2 - Aplicando o Journal File e 3 - Encerrando o processo. Simples, rápido e seguro.

Dessa forma fechamos a implementação da primeira etapa do Sistema de Journal. Só com esse procedimento já aumentamos significativamente a segurança de nossos bancos de dados, indepen-dentemente se seu porte.

A segunda etapa consiste na criação de um ambiente para o arquivamento dos arquivos de

Journal e do banco de dados. Mas esse é um assunto para nossa segunda parte do artigo, no próximo mês. Não percam!!!

CONCLUSÃO

É fácil perceber o quanto o Sistema de Journaling passa a ser fundamental para nossos ambientes. Se você é desenvolve-dor, imagine o nível de segurança que você pode oferecer aos seus clientes, dos pequenos aos gran-des. Se você é usuário de InterBase/Firebird, pense

o quanto esse simples procedimento pode te ajudar a diminuir e muito o seu tempo de parada, economi-

zando todos os tipo de recursos. E tudo isso sem precisar investir em sofisticadas plataformas de infra-estrutura, como Storages, diversos servidores, espelhamento de discos, etc. Basta um HD a mais e uns minutinhos para ativação. Se você já utiliza o InterBase versão 2007 ou superior, não perca mais tempo e comece já a utilizar esse fabuloso recurso. Se você é usuário InterBase versões anteriores ou Firebird, experimente, teste esse recurso baixando uma cópia de avaliação do produto. Lembrando sempre que, se você é desenvolvedor utilize a versão Developer Edition do InterBase SMP 2009, disponível gratuitamente no site da Embarcadero (http://www.embarcadero.com) . Essa versão per-mite o uso dos completos recursos de Journal. Vale lembrar também que o Sistema Journaling não está disponível nas versões Desktop e To-Go Edition do InterBase, por se tratar de versões voltadas para aplicações locais, sem acesso via rede, que dispensa esse tipo de segurança adicional.

No próximo artigo voltaremos para mostrar com detalhes de como tornar seu Sistema Jour-naling muito mais poderoso com o sistema de Ar-chiving, completando assim sua solução definitiva contra perda de dados. Está imperdível! Até lá.

Referência:InterBase 2009 Operations Guide – cap. 9.

Outubro 200916

Os programadores Delphi, mesmo aqueles sem muita experiência, já conhecem ou pelo menos ouviram falar de records ou estruturas nessa linguagem.

Records são tipos de dados criados pelo programador, conceito similar ao de classes, porém records contém apenas atributos e classes contém além desses os famosos mé-todos que manipulam os atributos.

Essa é a diferença mais superficial, digamos assim, além disso, existe outro fator importante a ser considerado quando trabalhamos com records e classes, que é a forma de alocação em memória pelo compilador de cada um.

Existem dois tipos de alocação: Estática e dinâmica. A primeira é a alocação utilizada para va-riáveis, sejam elas globais ou locais e para os nossos records. No caso de alocação estática o programa utiliza uma área de memória conhecida com pilha,

E x p l o r a n d o R e c o r d s e m

Delphi 2009onde as variáveis ficam até que a função onde fo-ram declaradas acabe (no caso das variáveis locais) ou até que o programa seja encerrado (no caso de variáveis globais). O conceito de pilha é justamente o que nos vem à mente quando pensamos na pala-vra: Uma sequência de objetos dispostos um sobre o outro onde o primeiro a entrar é o primeiro a sair. Esse conceito fica ainda mais claro se imaginarmos a seguinte situação em um aplicativo:

Temos a variável global nomeuser que é solicitada ao usuário quando da abertura do aplicativo.

Temos a função soma que utiliza as variáveis locais num1 e num2 que realizam uma soma comum.

É fácil visualizar o seguinte, assim que o apli-cativo é iniciado a variável nomeuser é alocada na pilha, depois com a chamada da função as variáveis num1 e num2 são alocadas também. Assim que a função termina, o programa destrói as variáveis num1 e num2 que foram as últimas a entrar e, portanto primeiras a sair. A variável nomeuser que foi alocada primeiro será liberada por último,

quando o aplicativo for encerrado.

Alocação dinâmica é utilizada por arrays não dimensionados e classes. Nesse tipo de alocação, o programa cria um ponteiro para um espaço de memória contido em uma área chamada “heap”. Quando trabalhamos com alocação dinâmica precisamos criar o espaço e liberá-lo depois de utilizado. Um exemplo é a criação de formulários em Delphi. Veja o código:

Try Form1:=tform1.create(self);Form1.showmodal;Finally Freeandnil(form1);End;

Nessa sequência, criamos o objeto e conse-quentemente o espaço em memória para form1 e depois liberamos o espaço e o ponteiro que referenciava esse espaço com freeandnil. Essa técnica é utilizada em Delphi com a grande maioria

Outubro 2009 17

das classes.

Já foi possível perceber que além da diferença inicial, records e classes são alocados de forma diferente. Records de forma estática e classes de forma dinâmica.

Por serem alocados de forma estática, records podem ser passados com parâmetros de funções e pode servir de valor de retorno, o que não se faz possível com classes.

Além disso, a partir do Delphi 2006, é possível inserir métodos em records, o que pode ser muito útil em alguns casos. Nesse artigo estarei falando um sobre como podemos explorar melhor os re-cords no Delphi 2009.

Records e Funções

Em determinadas situações, precisamos passar vários valores para uma função ou fazer com que alguma função retorne um conjunto de valores. Uma alternativa nesses casos é utilizar arrays, porém podemos também fazer uso de records, o que impede que passemos ou retornemos arrays de tamanho incorreto, causando vazamentos de memória.

Criaremos a seguir um pequeno exemplo de função de validação de usuários que receberá alguns dados para realizar a validação e nos devolverá nome, código e nível de usuá-rio. Não entrarei em detalhes com relação ao método de consul-ta ao banco que utilizarei para fazer a validação já que o foco do artigo são os records.

De início criaremos dois records: um para ser passado para a função e outro para permitir que a função retorne os três valores desejados:

TypeDadosEntrada=Record Nomeusuário:string; Senha:string;End;

TypeDadosRetorno=Record Usuariologado:string; Codigousuario:integer; Nível:string;End;

Repare que a declaração de records é igual à de classes apenas com a diferença da palavra record que indica qual tipo de dado estamos criando.

Iremos agora à função:

Function Validausuario(dados:DadosEntrada):DadosRetornovar sql:string;sdsvalida:tsqldataset; Begin Try Sql:=’select * from USERS where LOGIN= ’+quotedstr(dados.nomeusuario)+’ and SENHA =

’+quotedstr(dados.senha); Sdsvalida:=tsqldataset.create(nil); With sdsvalida do Begin Sqlconnection:=conexao; Commandtext:=sql; Open; If

Outubro 200918

recordcount>0 then Begin Result.Usuariologado:=fieldbyname(‘NOME’).asstring; Result.CodigoUsuario:=fieldbyname(‘CODIGO’).asstring; result End; End; Finally Sdsvalida.free; End;End;

Na função, fazemos um login simples e arma-zenamos as informações de saída no Record, o que nos possibilita ter dois valores de saída. Nesse caso são dois, mas poderiam ser mais bastando para isso a inserção de mais campos no Record.

Records com Métodos

A partir do Delphi 2006, Records em linguagem Object Pascal passaram a contar com mais uma funcionalidade passando a aceitar métodos além dos campos normais. Isso sem dúvida é uma gran-de funcionalidade que pode ser explorada pelos desenvolvedores Delphi.

Como se comportam como variáveis estáti-

cas, ao usarmos records com métodos, podemos usufruir de uma maior agilidade já que o Record é liberado de memória assim que o escopo onde foi declarado termina.

Vamos construir um exemplo simples agora para utilizarmos essa funcionalidade dos Records. Iremos declarar um Record que armazenará nome e alguns dados de uma pessoa. Nesse Record teremos o construtor e um método que fará a alteração da senha.

TypePessoa=Record Nome:string;

RG:string; Cpf:string; Senha:string; Constructor Create(Pnome:string); Procedure alterasenha(Psenha:string);End;

Implementação dos métodos:

Constructor Create(Pnome:string);

Figura 1

Outubro 2009 19

Consultor Técnico The Club.

Sobre o autor

Antonio Spitaleri Neto

[email protected]

Begin Nome:=Pnome;End;

Procedure alterasenha(senha:string);Begin Senha:=Psenha;End;

Iremos agora criar uma pequena aplicação exemplo para ilustrar o uso deste Record que criamos:

Abra o Delphi 2009 e inicie uma nova aplicação, monte o formulário de acordo com a figura 1:

Veja a Figura 1. No evento onclick do Button faça:

procedure TForm1.Button1Click(Sender: TObject);var RefPessoa:Pessoa;begin RefPessoa.create(edtnome.Text); with RefPessoa do begin

rg:=edtrg.Text; cpf:=edtcpf.Text; senha:=edtsenha.Text; end;end;

Repare que não precisamos nos preocupar em liberar RefPessoa, que é a variável que faz referên-cia a Pessoa porque como se trata de um Record, quando a função que instanciou o Record termina esse último é liberado de memória.

Se quiséssemos manter os dados de RefPes-soa poderíamos copiá-los para uma variável de escopo global que só seria liberada ao término da aplicação.

Vamos demonstrar isso. Declare uma variá-vel global RefPessoaGlobal do tipo Pessoa e no evento onclick que criamos a pouco, insira mais essa linha:

RefPessoaGlobal:=RefPessoa;

Com isso essa nova variável irá manter os da-dos que passamos a RefPessoa já que esta última será liberada ao final do evento.

Aproveitando essa nova variável, vamos fazer uso do método alterasenha do Record Pessoa. Insira mais um Button no formulário e em seu

evento on click faça:

procedure TForm1.Button2Click(Sender: TObject);var novasenha:string;begin novasenha:=InputBox(‘Nova Senha’,’Digite a nova senha’,’’); RefPessoaGlobal.alterasenha(novasenha); ShowMessage(‘A nova senha é: ‘+RefPessoaGlobal.senha);end;

Teste o aplicativo e salve as alterações.

Conclusão

Através desse artigo, o leitor pode ter contato com novas funcionalidades em um sistema que podem ser proporcionadas pelo uso dos records.

Se bem aproveitadas podem ser de grande utilidade para o dia a dia do desenvolvimento.

Espero que tenham gostado e até a próxima!

Outubro 200920

Uma das técnicas que mais chamou atenção desde o inicio da minha vida de pro-gramador é a herança visual de formulários. Chama atenção pelo fato de aproveitarmos o que a Programação Orientada a Objetos (POO) tem de melhor, usando herança, abstração, etc.

Uma aplicação Windows Forms comercial possui dezenas ou até centenas de formulá-rios, onde muitos possuem as mesmas ca-racterísticas para um formulário de cadastro, onde teremos, por exemplo, botões para novo registro, salvar, excluir etc.

Podemos então aproveitar essa técnica para criar um formulário base, com todas as funcionalidades comuns dos formulários de cadastros e assim, apenas herdar para os no-vos. Primeiramente, devemos analisar quais as funcionalidades comuns em um formulário de cadastro que devem ser implementadas no base.

Herança Visualde formulários em

Windows Forms

Criando o formulário base

Crie um novo projeto e no formulário dê o nome de “frmBase”. Todas as propriedades dos formulários de cadastro devem ser modificadas no frmBase. Altere as seguintes propriedades: KeyPre-view = true, MaximizeBox = false, MinimizeBox = false, StartPosition = CenterScreen.

Assim temos uma grande vantagem, pois não precisamos mudar as propriedades em cada formulário. Os formulários herdados do frmBase “recebem” as mesmas propriedades do formu-lário base.

Nota: todas as propriedades do formu-lário podem ser modificadas nos formulários herdados. Diferentes dos componentes, que para terem suas propriedades modificadas, devem ser configurados para isso. Veremos mais adiante essa configuração.

Agora precisamos adicionar os controles de tela que serão comuns em todos os formulários

de cadastro. Poderíamos usar botões, mas nesse exemplo, usarei um ToolStrip para adicionar as funcionalidades de cadastro: Novo, Salvar, Excluir etc.

No ToolStrip, adicione cinco botões e dê uma imagem a cada um, referente a sua funcionalidade (propriedade Image). Na propriedade DisplaySty-le mude para ImageAndText, para mostrar a imagem e o texto.

Dê também nomes suges-tivos aos botões, como “btn-Novo”, “btnSalvar”, etc. Adicione

Outubro 2009 21

também um StatusStrip no formulário. Veja na Figura 1 como deve ficar o formulário.

Figura 1. Formulário base da aplicação

Esses são controles comuns de todos os for-mulários de cadastro, ou seja, os controles para o cadastro de clientes (TextBox, Labels etc), por exemplo, devem ser adicionados no formulário herdado para esse cadastro especifico. Vamos agora criar os métodos comuns que podem ser usados em qualquer formulário herdado.

Criando código comum

Um exemplo bem simples e para fácil enten-dimento sobre a vantagem de usar formulários herdados é o código para fechamento do formu-lário usando a tecla ESC. Sem a herança, o código deveria ser colocado em todos os formulários. Com a herança, o código será adicionado somente no formulário base. Para isso, acesse o evento KeyDo-wn do formulário e adicione o seguinte código que será responsável por fechar o formulário quando o usuário apertar a tecla ESC:

if (e.KeyCode == Keys.Escape)this.Close();

Agora, todos os formulários herda-dos, não precisam codificar o mesmo

evento para adicionar essa funcionalidade.

C o n v e n h a -mos, muita produtivida-de e reapro-

veitamento de código, mesmo

em um exemplo simples. Outro

código bastante comum usado em

cadastros são os mé-todos que habilitam/

desabilitam controles de tela e o que “limpa” os controles.

O primeiro serve para indicar ao usuário, quando os controles

Figura 1. Formulário base da aplicação

de tela podem ficar disponíveis para o usuário e o segundo, para limpar, principalmente TextBox, depois de inserção ou atualização dos dados no banco. Adicione o seguinte código, que será o de habilitar/desabilitar controles:

private void HabilitaDesabilitaControles(bool Value){foreach (Control ctl in this.Controls){

if (ctl is ToolStrip)continue;ctl.Enabled = Value; }}

O código é bastante simples, onde possui um parâmetro do tipo bool para indicar se deseja habilitar ou desabilitar os controles, usando a propriedade Enabled dos controles de tela (this.Controls), configurados através de um foreach.

Fizemos uma verificação do ToolStrip para que os botões não sejam desabilitados, assim, se acharmos um controle do tipo, continuamos o laço, usando o continue. Já podemos usar o método no formulário base, pois após o usuário clicar no Novo, os controles de tela devem ser habilitados.

No botão adicione o código, passando como parâmetro true. Com esse código, os botões de cadastros do ToolStrip também estarão desabili-tados ou habilitados, então vamos criar um enum para indicarmos quando devemos habilitar ou desabilitar determinado botão, conforme o código a seguir:

public enum StatusCadastro{

scInsert, scBrowser, scEdit}

Crie também uma variável do tipo do enum chamada sStatus. No HabilitaDesabilitaControles vamos modificar o método, adicionando o código da Listagem 1, após o foreach.

Listagem 1. Alterando a configuração do botão, de acordo com o status do cadastro

//habilitado quando não estivermos inserindo ou editando, somente navegandobtnNovo.Enabled = (sStatus == StatusCadastro.scBrowser);//habilitado quando estiver inserindo ou editando

Outubro 200922

btnSalvar.Enabled = ((sStatus == StatusCadastro.scInsert) || (sStatus == StatusCadastro.scEdit));//habilitado quando estivermos editandobtnExcluir.Enabled = (sStatus == StatusCadastro.scEdit);

//habilitado quando não estivermos inserindo ou editando, somente navegandobtnLocalizar.Enabled = (sStatus == StatusCadastro.scBrowser);//sempre habilita o sairbtnSair.Enabled = true;

No código, estamos verificando o valor de sSta-tus, para habilitar/desabilitar os botões, então para que isso funcione corretamente, devemos atribuir o valor correto para a variável, em determinadas situações.

No botão Novo, antes do HabilitaDesabili-taControles, devemos configurar a variável para scInsert. Nos botões Salvar e Excluir, atribuía o valor scBrowser, seguido do HabilitaDesabilitaControles passando false. Já no Localizar, alteramos a variá-vel para scEdit e devemos habilitar os controles de tela.

Mais código comum

Como indicado anteriormente, outro código interessante a ser usado no formulário base, é para “limpar” controles de tela. Para isso implemente o código da Listagem 2.

Listagem 2. Método para limpar controles de tela

private void LimpaControles(){ foreach (Control ctl in this.Controls)

{ if (ctl is TextBox) (ctl as TextBox).Text = “”; if (ctl is ComboBox) (ctl as ComboBox).SelectedIndex = -1; if

(ctl is ListBox) (ctl as ListBox).SelectedIndex = -1; }}

O código é bastante semelhante ao anterior, onde fizemos um laço pelos controles de tela. A diferença fica por conta, que verificamos o tipo de controle utilizando a diretiva is para saber o tipo da classe. Sabendo o tipo, usamos o as para fazer um cast e acessar as propriedades da classe. Assim, podemos utilizar, por exemplo, o Text do TextBox, o SelectedIndex do ListBox e ComboBox.

Para outras classes, basta verificar seu tipo e fazer o cast na propriedade desejada. Bom, e onde vamos usar esse método? Devemos usar o mesmo quando o usuário quiser adicionar um novo regis-tro, portanto chame o método no botão Novo.

Nosso processo será o seguinte para um novo registro: usuário clica em Novo, limpamos e habilitamos os controles de tela, usuário adiciona os dados, salvamos o registro, desabilitamos os controles de tela.

Assim, colocamos o usuário em um processo onde os erros, têm menos possibilidade de ocorrer (claro, devemos ter as validações do cadastro em cada formulário herdado). Precisamos também deixar os controles limpos e desabilitados quando o usuário abrir pela primeira vez o formulário.

No evento Load do formulário, usaremos o seguinte código:

sStatus = StatusCadastro.scBrowser;

LimpaControles();HabilitaDesabilitaControles(false);

A idéia das funcionalidades do cadastro é que usaremos um cadastro parametrizado, ou seja, o usuário deve localizar um registro para poder editá-lo, assim quando abrir o formulário, as opções existentes são de inserir um registro (botão Novo) ou localizar para edição.

Métodos virtuais

Podemos declarar métodos no formulário base, que podem ser subscritos nos formulários herdados. A vantagem é que precisamos apenas subscrever, com o código necessário, não precisan-do chamar o mesmo em determinadas situações, claro se já o fizermos no formulário base.

Para um melhor entendimento dessa parte, imagine o método para salvar os dados. Com o método virtual, declaramos o mesmo no formulário base, e a implementação que será de acordo com o cadastro, deve ser feita no herdado.

A chamada do método será feita no formu-lário base, no botão de salvar os dados. Partindo para a prática, declare os métodos a seguir no formulário base:

public virtual bool Salvar(){ }public virtual bool Excluir(){ }public virtual bool Localizar(){ }

O método pode ter implementação de código e vamos subscrever o mesmo no formulário herdado (ou classe, caso fosse essa a intenção). Faça a cha-mada aos métodos nos respectivos botões. Como temos um retorno do método (bool), o código que já implementamos nos botões devem ser executa-dos, somente se o método retornou true.

Adicionamos uma mensagem ao bloco de código para que o usuário saiba que o método

Outubro 2009 23

foi executado com sucesso. Para o botão Salvar teríamos o código da Listagem 3.

Listagem 3. Alterando o código dos botões

if (Salvar()){sStatus = StatusCadastro.scBrowser;HabilitaDesabilitaControles

(false);MessageBox.Show(“Registro salvo com sucesso!”, “Salvar”, MessageBoxButtons.OK, MessageBoxIcon.Information);}

Podemos ainda implementar um código ou variável que retornasse o motivo do método ter retornado false, por exemplo, não salvando os registros. Lembrando, tudo isso pode e deve ser implementado no base, sem duplicar código em cada formulário. Execute de maneira semelhante, os outros métodos nos seus respectivos botões.

Criando o formulário herdado

Bom, podemos claro implementar mais código no formulário base, mas isso depende da necessi-dade do nosso projeto. Para criar um formulário herdado, primeiramente, dê um Build no seu projeto e em seguida, acesse o menu Project>Add Windows Forms.

Em Add New Item, na seção Windows Forms, escolha a opção Inherited Form, como podemos ver na Figura 2.

Figura 2. Criando um formulário baseado

em outro

Após colocar o nome do formulário e clicar em Add, teremos um novo editor, onde vamos escolher o formulário que será herdado. Veja na Figura 3 a tela onde escolhemos o formulário.

Figura 3. Escolhendo o formulário base

Figura 2. Criando um formulário baseado em outro

Figura 3. Escolhendo o formulário base

Outubro 200924

atualizará os dados do cliente, bem como o de excluir os dados, usando os métodos. Para efeitos de didática, imaginamos que temos o código para adicionar os dados, onde apenas vamos retornar true no método.

Vamos configurar para que o formulário de clientes seja o formulário inicial da aplicação. Ao abrir o formulário, clicamos em Novo e adiciona-mos os valores nos TextBox. Após clicamos em Salvar e temos a mensagem de confirmação que só é executada se o método salvou corretamente os dados.

Veja que com essa técnica, poupamos trabalho

Figura 4. Formulário herdado

Caso o formulário que você deseja herdar, não aparecer, experimente dar um Build na aplicação e tente novamente. Ao clicar em OK, teremos um formulário com os mesmos componentes do for-mulário base (Figura 4).

Figura 4. Formulário herdado

Nota: Os componentes adicionados no formulário base, não podem ser excluídos nos formulários herdados, portanto, como frisado anteriormente, é necessário fazer uma análise perfeita dos controles que devem ser mostrados no base.

Você pode alterar propriedades como Enabled e Visible para modificar o controle no formulário herdado, mas para isso, deverá alterar a proprie-dade Modifiers para Public do componente no formulário base.

Caso esteja utilizando o Visual C# (versão gratuita do Visual Studio para aplicações Windows Forms), a opção Inherited Form da Figura 2, pode não aparecer. Mas para contornar isso, é muito fácil. Abra o editor de código do formulário que deseja herdar (crio primeiramente) e na declaração do tipo, altere como o código a seguir:

Antespublic partial class Form1 : Form

Depoispublic partial class frmClientes : frmBase

Após, salve o formulário, feche o mesmo e dê um build na aplicação. Ao reabrir, o mesmo estará com os componentes do formulário base.

Codificando o formulário herdado

Após herdar o formulário, o que precisamos fazer? Primeiro, devemos adicionar os controles para mostrar os dados do cadastro que precisa-mos. Aqui, didaticamente, usaremos um cadastro de clientes. Então, adicione controles de tela, e precisamos codificar os métodos virtuais, criados no formulário base, salvando e excluindo os dados do cliente.

Veja que não precisamos nos preocupar com funcionalidades para fechar formulário, limpar e desabilitar controles de tela, tudo esta codificado no formulário base, trazendo produtividade e fácil manutenção dos cadastros. Declare os métodos da Listagem 4 no formulário de clientes.

Listagem 4. Subscrevendo os métodos da classe base (formulário)

public override bool Salvar(){ return base.Salvar(); }

public override bool Excluir(){ return base.Excluir(); }

public override bool Localizar(){ return base.Localizar(); }

Veja que temos o retorno do método criado no formulário base, usando base.NomedoMé-todo, isso indica que qualquer código que for implementado no método, será executado com essa chamada.

O trabalho que teremos no formulário de clientes será escrever o código que adicionará ou

Outubro 2009 25

Confira o video deste artigo no site do The Club na edição online da revista.

É Técnico em Processamento de Dados, desenvolvedor Delphi/C# para aplicações Web com ASP.NET e Windows com Win32 e Windows Forms. Palestrante da 4ª edição da Borland Conference (BorCon).

Autor de mais de 60 artigos e de mais de 300 vídeos aulas publicadas em revistas e sites especializados. É consultor da FP2 Tecnologia (www.fp2.com.br) onde ministra cursos de programação e banco de dados. É desenvolvedor da Paradigma Web Bussi-ness em Florianópolis-SC.

Sobre o autor

Luciano Pimenta

e código, ou seja, temos em apenas um método o código necessário, por exemplo, para excluir um registro, que varia de acordo com o cadastro. Veja na Figura 5 o cadastro de clientes em execução.

Veja a Figura 5. Exemplo do formulário em exe-

cução

Para a funcionalidade de Localizar, também podemos criar um formulário de pesquisa base, e, por exemplo, passar um DataTable ou DataSet para fazer a pesquisa dos dados. Deixo essa idéia

para o leitor implementar e mostrar o conhecimento adquirido com o artigo.

Conclusão

Vimos neste artigo, como criar formulários ba-ses, para serem usados de maneira produtiva em apli-cações Windows Forms. As

dicas apresentadas neste artigo podem e devem ser melhoradas e adaptadas a necessidade do

www.lucianopimenta.net

leitor, mas sempre tenha em mente que o tempo de análise é muito importante antes de começar a desenvolver seus projetos e no nosso exemplo, um formulário base.

Um grande abraço a todos e sucesso em seus projetos!

Figura 5. Exemplo do formulário em execução

Outubro 200926

Olá, chegamos ao final dos nossos 3 arti-gos sobre jQuery. Nesse artigo irei tratar sobre como acessar a funções (Handler) no Server site através de funções nativas do jQuery. Levando-se em consideração a prática do primeiro artigo vamos ao que interessa:

Primeiro vamos abrir o Visual Studio 2008 e criaremos uma aplicação Web (imagem 01). De-pois de criarmos a aplicação WEB adicionamos o jQuery a nossa aplicação e agora estamos prontos para começar a desenvolver nosso exemplo de utilização.

Veja a imagem 1.

Depois da aplicação criada, tecle com o botão direito sobre o projeto > depois Add > New Item (Imagem 02), abrirá a tela Add New Item, nessa tela iremos selecionar a Opção Web do lado esquerdo e a Opção Generic Handler (imagem 03) neste ponto nossa aplicação deverá ter os seguintes arquivos (Imagem 04), esse Generic Handler é uma espécie de WebService que fará a “ligação” entre o client-side ( jQuery ) e a camada de negócio ou o banco de dados, através dele que acessaremos as funções C#.

Veja a Imagem 2.Veja a imagem 3.

Acesso a dados com

jQuery

Imagem 1

Imagem 2

Imagem 3

Outubro 2009 27

Agora vamos começar a codificar: Primeiro vamos incluir o jQuery na nossa página Default.Aspx através da Listagem 01, nessa listagem referenciamos o jQuery, logo após esse códi-go referenciamos a nosso objeto de pesquisa conforme listagem 02, na listagem 02 temos a lista de categorias que podemos ter em nosso exemplo, que seria semelhante a uma loja virtual, observem que estamos criando links e nesses links apontamos para a própria página através do # e no evento onclick atribuímos a chamada de um método JavaScript que iremos implementar adiante, passamos para esse método o código da categoria que estamos procurando, exemplo a ca-tegoria Culinária é o código 1 Informática código 3 e assim sucessivamente. Agora vamos implementar nosso método para acessar o servidor e retornar os produtos da categoria sem a necessidade de fazer um postback de toda a página (listagem 03), observem que na listagem 03 eu criei primeiro um Bloco de text/JavaScript que deve ser criado dentro das tag <head> do nosso HTML, depois eu criei uma variável contendo o nome do nosso handler para facilitar a manutenção futuramente e depois implementei o nosso GetComunicacaoDados(e), onde é o código da categoria que estou pesqui-sando. Depois crio outra variável nomeada como detailArea contendo o nome do elemento HTML que vai receber os produtos de determinada ca-tegoria, depois implementamos o método $.get do jQuery que tem como seus parâmetros default a URL, DATA, CALLBACK onde que URL indica a página que temos nosso Handler o DATA indica o valor que queremos passar em nosso parâmetro, uma espécie de QueryString e o Callback é o que o Client-side vai processar quando o servidor responder a requisição, no campo URL passamos a nossa variável criada anteriormente com o cami-nho do nosso Handler depois no parâmetro DATA é no formato JSON indiquei um atributo nomeado como codCategoria e passei para ele o código da categoria que tínhamos colocado no onclick lá no link de categorias, e por último o CALLBACK que é o que será processado pelo client-side quando o servidor retornar da requisição, neste caso ele simplesmente vai colocar o retorno para dentro do nosso divProdutos onde estarão os produtos da nossa loja. Para criar o Div de produtos utiliza a listagem 04. Ok agora o nosso Client-Side está pronto, a nossa página Default.aspx está ok.

Agora vamos abrir o arquivo Handler1.ashx e implemente no método ProcessRequest a listagem 05, nessa listagem primeiro criamos uma variável

inteira que receberá o valor do JSON codCategoria que contém dentro dele a categoria que está sendo pesquisada, depois eu “escrevo” no context (pági-na) o retorno do meu método RetornarProdutos que é um método que pode estar em qualquer NameSpace da minha aplicação, assim consegui-mos interagir entre o HTML e o C#, mas retornando ao nosso exemplo o Método RetornarProdutos está dentro da mesma classe do Handler esse método está descrito na Listagem 06, fiz apenas um exemplo simples para retornar valores pois não é de intenção desse artigo entrar em questão o acesso a banco de dados. Agora vamos acessar a nossa aplicação (F5): Quando abrimos a nossa página vai estar no topo as categorias que foram listadas (Elétrodoméstico, Culinária, Etc.) e em baixo um FieldSet com o título Produtos da Cate-goria, quando clicamos em alguma das categorias o JavaScript do onClick daquele link é executado fazendo uma requisição ao servidor para que o mesmo retorne com os produtos referenciados para determinada categoria. Então é isso, espero que tenham gostado dessa série de artigos sobre jQuery e em breve estarei com novos artigos sobre novas tecnologias que estão sendo lançadas no VS2010 e Silverlight 3.

Listagem 01:

<asp:ScriptManager id=”sm1” runat=”server”> <Scripts> <asp:ScriptReference Path=”~/Scripts/jquery-1.3.2.js” /> </Scripts></asp:ScriptManager>

Listagem 02:

<ul id=”categories”> <li><a href=”#” onclick=”GetComunicacaoDados(0);return false;”>Eletrodomésticos</a></li>

<li><a href=”#” onclick=”GetComunicacaoDados(1);return false;”>Culinária</a></li> <li><a href=”#” onclick=”GetComunicacaoDados(2);return false;”>Informática</a></li> <li><a href=”#” onclick=”GetComunicacaoDados(3);return false;”>Jardinagem</a></li> </ul>

Listagem 03:

<script type=”text/javascript”>

// The handler url var handlerUrl = ‘Handler1.ashx’;

function GetComunicacaoDados(e) { var detailArea = ‘#divCategorias’; $.get(handlerUrl , { codCategoria: e.toString() } , function(data) { $(“#divprodutos”).html(data); }); } </script>

Listagem 04:

<br /> <fieldset> <legend> Produtos da Categoria </legend>

Outubro 200928

Trabalha a quase 7 anos com Delphi, trabalha na empresa Benner Sistemas (www.benner.com.br ) na área de tecnologia desenvolvendo fer-ramentas em Delphi e como hobby e visão de mercado está migrando seus conhecimentos para a plataforma .NET. Faz parte do grupo .NET Blumenau http://dotnetblumenau.ning.com/ . Possue certificação 70-536 (Microsoft .NET Framework 2.0 Application Development Foundation ) . Twitter: djonatastenfen - blog http://www.djonatastenfen.blogspot.com/

Sobre o autor

Djonatas Tenfen

[email protected]

<div id=”divprodutos”></div> </fieldset>

Listagem 05

public void ProcessRequest(HttpContext context) { int codCategoria = Int32.Parse(context.Request.QueryString[“codCategoria”]); context.Response.Write(RetornaProdutos(codCategoria)); }

Listagem 06

private string RetornaProdutos(int

Conclusão:

O objetivo dessa seqüência de artigos sobre jQuery era de passar um pouco de conhecimento aos desenvolvedores .net e web uma pequena par-te dessa fabulosa Framework que veio para firmar ainda mais a chamada WEB 2.0 com muitas mais interatividade, praticidade e performance.

CodCategoria) { // Aqui posso criar um acesso a banco de dados e // filtrar os produtos da cateogira indicada no parâmetro do método StringBuilder sb = new StringBuilder(); sb.Append(“produto 01 da cateogia “ + CodCategoria.ToString() + “<br/>”);

sb.Append(“produto 02 da cateogia “ + CodCategoria.ToString() + “<br/>”); sb.Append(“produto 03 da cateogia “ + CodCategoria.ToString() + “<br/>”); return

sb.ToString(); }

Outubro 2009 29

Dicas DELPHIAlterar propriedade buttonstyle das toolbars ligadas ao

actionmanager em tempo de execução:

TButtonProperties(ActionManager1.ActionBars[0].Items[0].CommandProperties).ButtonSize := bsLarge;

Esse typecast também serve para alterar outros subitens de command properties como buttontype, groupposition e textassociation

Criando uma caixa de mensagem personalizada

function mensagem(Texto: string; Botao: TMsgDlgButtons = [mbOk]; Rotulo:String = ‘Atenção’; Icon : TMsgDlgType = mtWarning): integer;var wl_mensagem: TForm;begin

wl_Mensagem := CreateMessageDialog(Texto, Icon, Botao);

(wl_mensagem.FindComponent(‘YES’) as TButton).Caption := ‘&Sim’; (wl_mensagem.FindComponent(‘NO’) as TButton).Caption := ‘&Não’; (wl_mensagem.FindComponent(‘OK’) as TButton).Caption := ‘&Ok’; (wl_mensagem.FindComponent(‘CANCEL’) as TButton).Caption := ‘&Cancela’;

wl_mensagem.Color := clBtnFace; wl_mensagem.BorderStyle := bsSingle; wl_mensagem.BorderIcons := [];

wl_mensagem.Caption := Rotulo;

result := wl_mensagem.ShowModal;end;

Mostrar jpg num grid

usesjpeg

no evento do onDrawColumnCell do grid.

varjpeg:tjpegimage;beginif column.Field is tgraphicfield thenbeginwith dbgrid1.Canvas dobeginfillrect(rect);jpeg:=tjpegimage.create;tryjpeg.Assign(column.Field);draw(rect.Left,rect.top,jpeg);finallyjpeg.Free;end;end;end;end;

Wav em sua aplicação

Na Unit do form vá até USES e acrescente lá: MMSystem, (coloque a vírgula).

Depois vá no evento OnShow do form e coloque o comando:

Begin PlaySound(‘C:caminho_da_musicanome_da_musica.wav’, 1, SND_ASYNC);End;End.

Outubro 200930

Outubro 2009

Outubro 2009