Executando vários métodos ao mesmo tempo.

Escrito em 29 de Janeiro de 2007 em Componentes por leosimas

Calma! É isso mesmo que você leu!
Puro mérito de uma unit chamada AsyncCalls:
Página do ASyncCalls
Download do arquivo

Após o download, nem é necessário instalar nada no delphi. Basta adicionar a unit ASyncCalls.pas no seu projeto.

Mostrarei agora um exemplo de como essa maravilha funciona:

1- Crie um projeto novo com uma tela assim:

Nosso exemplo consiste em pegar os números pares de cada memo e jogá-los ao memo3.
Para isso, faremos uma procedure chamada pegarpares que será assim:
 

  procedure PegarPares(MemoAtual, MemoResultado : TMemo);
  var x: Integer;
  begin
    for x := 0 to MemoAtual.Lines.count-1 do
      If strtoint(MemoAtual.Lines[x])mod 2 = 0 then
        MemoResultado.Lines.add(MemoAtual.Lines[x]);
  end;

 

Só que ao chamar um método seguidamente assim:
pegarpares(Memo1, Memo3);
pegarpares(Memo2, Memo3);

O conteúdo do memo3 ficaria assim:

2
6
10
14
18
4
8
12
16
20

Ou seja, logicamente ele faz primeiro para os números do memo1 e depois para o memo2.

Por incrível que pareça, o AsyncCalls fará nosso memo3 ficar dessa forma:

2
4
6
8
10
12
14
16
18
20

Ou seja, ele faz “ao mesmo tempo” para o memo1 e para o memo3.

Você já deve estar curioso com a infinidade de linhas de código que será preciso pra fazer isso né? Então fique impressionado com “tanta complexidade” :D

1- Com a unit AsyncCalls.pas adicionada ao projeto, coloque no uses AsyncCalls;

2-Crie a nossa função que será chamada várias vezes ao mesmo tempo:

  procedure PegarPares(MemoAtual, MemoResultado : TMemo);cdecl;
  var x: Integer;
  begin
    for x := 0 to MemoAtual.Lines.count-1 do
      If strtoint(MemoAtual.Lines[x])mod 2 = 0 then
        MemoResultado.Lines.add(MemoAtual.Lines[x]);
  end;

  Repare que, no fim da declaração da procedure, existe um keyword chamado “cdecl”. Esse keyword permite que o AsuncCall saiba a forma certa de passar os parâmetros da procedure.
Para que passar por um array? É que podemos ter várias procedures diferentes sendo executadas “ao mesmo tempo” e todas com seus parâmetros.

 

3-No onclick do botão vamos declarar 3 variáveis da interface ISyncCall:

  procedure TForm2.Button1Click(Sender: TObject);
  Var M1,M2 : IAsyncCall;
  begin

4-Carregaremos cada variável dessa maneira:

    M1 := Asynccall(@PegarPares, [Memo1, Memo3]);
    M2 := Asynccall(@PegarPares, [Memo2, Memo3]);

5-E por último. Sim, por último já :D ! Chamaremos as procedures com o AsyncMultiSync assim:

    while AsyncMultiSync([M1,M2],true, 10) < 0 do
      Application.ProcessMessages;
  end;

Dessa forma o Asynccalls sabe que tem que executar essas procedures ao mesmo tempo.
O primeiro parâmetro é seu array de IAsyncCall.
O segundo parâmetro é se vc quer esperar o fim de todas as procedures para continuar.
E por último, o tempo em milisegundos para atualizar a tela.

Por fim sua aplicação rodará assim:

Este foi um exemplo simples para entender como funciona o AsyncCalls. Mas preparem-se, porque artigos mais complexos estarão vindo aí.

Espero que tenham gostado.
Obrigado.

Se você é novo por aqui, não deixe de assinar o feed RSS ou notificações por email. Não perca novos artigos!

Quanto de memória estou utilizando?

É comum muitos programadores, inclusive eu, há algum tempo atrás, medirem o consumo de memória de uma aplicação pelo gerenciador de tarefas do windows, o que é, na melhor das hipóteses, uma maneira incompleta de realizar essa verificação. O gerenciador de tarefas na verdade mostra a quantidade de memória que ele alocou naquele momento e não o quanto de memória o programa utiliza, além do que, o Windows contabiliza a memória alocada que foi utilizada e liberada até que outro programa a utilize.

Exemplo: seu programa utilizou 4.569K e liberou 169K, esse valor é contabilizado pelo windows até que outro programa o utilize (o gerenciador continua mostrando os 4.569K).

A causa desse problema com o gerenciador de tarefas é o gerenciador de memória runtime do Delphi alocar memória indiretamente. Quando o programa solicita memória para o gerenciador, ele aloca blocos de memória para o programa. Os blocos tem tamanho fixo de modo que para cada pedido de memória o gerenciador aloca a quantidade necessária de blocos contínuos para satisfazer o pedido do programa.

Deste ponto de vista o bloco é a menor quantidade de bytes que o gerenciador aloca.

Exemplo: Um bloco tem 16 bytes; se o programa pede 4 bytes, o gerenciador irá alocar um bloco; se o programa pedir 18 bytes, o gerenciador irá alocar dois blocos.

Parece que o gerenciador está “torrando” memória a toa, mas isso é feito para evitar a fragmentação da memória. Quando o programa devolve memória ao gerenciador, este não a devolve para o Windows, pois ele deduz que o programa pode solicitar mais memória a qualquer momento e a reserva para otimizar o tempo de acesso a ela.

Entendendo melhor o funcionamento:

Imagine que você possui duas classes (TAlocaMemoriaAtoa e TAlocaMemoriaAVontade). Quando executamos um programa qualquer, por exemplo, vamos imaginar que o gerenciador aloque 10 blocos de memória. Após isso criamos a classe TAlocaMemoriaAtoa que solicita ao gerenciador mais 10 blocos. O tamanho total de memória utilizada é 20 blocos. Ao destruírmos a classe TAlocaMemoriaAtoa o sistema libera 10 blocos, mas o gerenciador os mantém disponíveis para a aplicação. Se nesse momento criarmos a classe TAlocaMemoriaAVontade e esta solicita 5 blocos de memória, o gerenciador buscará 5 blocos dos 10 reservados anteriormente, quando a classe TAlocaMemoriaAtoa fora destruída.

BINGO! Por isso que quando eu fazia debug da minha aplicação com o gerenciador de tarefas aberto os “Free” e “FreeAndNil” quase nunca funcionavam! :)

No meu próximo post falarei sobre gerenciadores de memória alternativos como o FastMM, adotado como gerenciador de memória padrão na versão 2006 do Delphi, e faremos alguns testes comparativos. Até a próxima.

Arquivos Gerados Pelo Compilador

Escrito em 24 de Janeiro de 2007 em IDE por Leonel Togniolli

Ao compilar um projeto Delphi, vários arquivos podem ser gerados pelo compilador. Alguns são bem conhecidos, outros nem tanto. Você conhece todos?

  • .dcu, .dpu, .dcuil

DCU, ou “Delphi Compiled Unit”, contém o código compilado de uma unit .pas, e, opcionalmente, informações de debug que podem ser usadas posteriormente pela IDE. O .dpu é o correspondente do Kylix, e .dcuil é o mesmo arquivo gerado pelo compilador de Delphi para .Net

  • .dcp, .dcpil

O arquivo .dcp é uma espécie de conjunto de todos os DCUs que formam uma package. O .dcpil é a versão .net desses dados, onde também é gerado pelo compilador Delphi ao importar assemblies escritos em outras linguagems, como C#.

  • .exe

Geralmente o que você espera que saia de uma compilação: o executável do seu projeto.

  • .dll, .bpl

DLLs são bem conhecidas de desenvolvedores windows: são bibliotecas que podem ser compartilhadas por vários executáveis, ou simplesmente servir para modularizar projetos. BPL é uma DLL com informações extras adicionadas pelo compilador Delphi, permitindo compartilhar tipos entre módulos e o executável de forma mais fácil.

  • .map, .rsm, .pdb

São arquivos opcionais, habilitados nas opções de projeto, contendo informações de debug. O primeiro contém informações sobre a relação do conteúdo do código fonte e o código gerado, o segundo possui dados específicos para o remote debugger. Arquivos .pdb são informações de debug externas geradas para aplicações .net

  • .xml

Se habilitado nas opções de projeto, o compilador também gera arquivos XML contendo documentação sobre as classes, extraídas das suas declarações e de comentários que se relacionam à elas.

  • .drc

Se for gerado um map file detalhado, também será gerado um arquivo .drc contendo uma lista de todos os recursos que o compilador incluiu no executável.

  • .hpp, .obj, .lib

Pra quem usa C++ Builder, se for habilitado a opção de gerar arquivos para o C++ nas opções de um projeto Delphi, o compilador também gera o .hpp, que é um header de C++ contendo as declarações do que estiver nos seus arquivos .pas. O .obj é o correspondente do .dcu para o C++, e o .lib, corresponde do .dcp. Útil para quem escreve componentes VCL para usar tanto no Delphi quanto no C++.

Sabendo pra que servem os arquivos gerados, e quando são gerados, fica mais fácil gerenciar os arquivos de um projeto, e decidir o que pode ser apagado e o quais devem estar no controle de versão.

Caos - Introdução

Escrito em 24 de Janeiro de 2007 em Infraestrutura, TI por Eduardo Tafner

Trabalho com infra-estrutura de TI a bastante tempo. Já vivi uma porção de situações que, em nenhum momento, equivalem ou somam mais do que qualquer ambiente: cada ambiente é quase a teoria do caos instaurada, de tantas variáveis que o componhem.

Já se deparou em um momento em que, para iniciar um serviço você precisa entrar em contato com uma porção de pessoas, iniciar uma diversidade de processos, workflows, acessar uma diversidade servidores, eventualmente em uma ordem específica e após o que parecia interminável você pára e diz para si: “Isso já foi mais simples…”? Ops! Caos detectado.

O artigo é apenas para reavivar a idéia e, se isso comovê-lo, fazer com que você tome uma atitude em prol da sua saúde. :]

Abaixo seguem os artigos e os respectivos tópicos para discussão futura. Os tópicos são guias para o conteúdo dos futuros artigos, mas exemplos de infra-estruturas diferentes podem instigar outro rumos. Fique à vontade para comentar!

O caos, em si:

  1. “N-vários”;
  2. Politicalha;
  3. One-man army;
  4. Nada é o que parece.

Fatores que geram o caos:

  1. O famoso “jeitinho”;
  2. “Pessoas”;
  3. SLAs.

Como evitar o caos:

  1. Fazendo direito;
  2. Infelizmente, você não está sozinho.

Desestruturando o caos já instalado:

  1. Filosofar;
  2. Centralizando;
  3. Simplificando;
  4. Sem jeito - refazendo.

Bom Programador é Preguiçoso

Escrito em 19 de Janeiro de 2007 em Programação por Leonel Togniolli

Uma vez li em algum lugar que um bom programador é preguiçoso. Concordo plenamente.

Calma, calma, já explico: é que, um programador que não tem preguiça de fazer todo dia a mesma coisa vai estar sempre cheio da mesma coisa pra fazer, todo dia, e não vai conseguir fazer mais nada. Quem é preguiçoso o suficiente pra achar que alguma coisa é muito chata de fazer, vai encontrar uma forma de automatizar isso pra não precisar fazer de novo.

Seja um programinha pra gerar forms seguindo o seu padrão, um expert na IDE pra automatizar alguma tarefa chata, uma macro pra facilitar a alteração naquele bloco de código, um arquivo de lotes pra copiar arquivos repetidamente, ou qualquer outra coisa que deixe o programador preguiçoso descansar por um tempo é bem vinda. Quem não tem paciência de seguir os diversos passos necessários toda vez que precisa liberar uma versão da sua aplicação, desde a compilação até a distribuição, vai automatizar seus builds. E isso é bom.

Você é um programador preguiçoso? Compartilhe com os outros as técnicas que você usa pra facilitar a sua vida.

Não é preguiçoso? Deveria ter vergonha de trabalhar tanto - faça computador trabalhar um pouco por você - ele é bom nisso.

Criando seu próprio "splash-screen" na inicialização da IDE do BDS

Escrito em 18 de Janeiro de 2007 em Delphi, IDE, Linguagem Delphi por Alexandre José

Olá pessoal, resolvi colocar uma dica bacana para quem desenvolve pacotes de componentes.

Quem utiliza o BDS já reparou que alguns packages, depois de carregados, exibem um pequeno bitmap de 24×24 px. com a descrição do pacote de ferramentas e a empresa desenvolvedora na tela de inicialização da IDE. Podemos citar entre eles o JediVCS, RemObjects, TMS Component Pack entre outros.

Neste pequeno artigo quero mostrar como é fácil e rápido personalizarmos nossos pacotes de componentes com este recurso que a IDE nos oferece.

Primeiramente devemos criar o nosso arquivo de recurso (.RES) com a imagem bitmap que irá ser apresentada na inicialização da IDE. Para isso você pode utilizar qualquer ferramenta de edição de recursos, até mesmo na linha de comando, compilando um arquivo texto com o aplicativo que a Code Gear nos disponibiliza, o BRCC32. Eu recomendo o XN Resource Editor(XRE), desenvolvido por Colin Wilson (Xana News), que além de ser muito bom é FREE. Para baixá-lo acesse o site: http://www.wilsonc.demon.co.uk/delphi.htm (vou utilizar ele como base para terminar este artigo mas você pode criar o arquivo da maneira que bem entender, desde que o recurso possua o mesmo nome deste exemplo ou você adapte este exemplo).

Criando o arquivo de recurso:

  1. Dentro do XRE clique no menu “Resource” e selecione a opção “Import Image Resource”. Escolha uma imagem Bitmap de 24×24 px;
  2. Após inserir esta imagem o XRE a adicionará no grupo “Bitmap” e o nome dela será “1″;
  3. Clique no nome “1″ e renomeie para “SPLASH_TECHTIPS”;
  4. Salve o arquivo com o nome SPLASH_TESTE.RES na pasta do seu projeto de componentes.

Criando a unit de registro do seu splash:

Crie uma unit em branco e adicione ao seu pacote de componentes com a seguinte estrutura:

unit SplashTeste;

interface

{$R SPLASH_TESTE.RES} 

implementation

uses
  Graphics, ToolsAPI;

procedure AddSplash;
var
  bmpAux : TBitmap;
begin
  bmpAux := TBitmap.Create;
  try
    bmpAux.LoadFromResourceName(HInstance, 'SPLASH_TECHTIPS');

    {$IFDEF VER180}
      SplashScreenServices.AddPluginBitmap('Meus componentes',
        bmpAux.Handle,
        False,
        'Licenciado para TechTips', '');
    {$ENDIF}

  finally
    bmpAux.Free;
  end;
end;

begin
  AddSplash;

end.

Agora recompile seu pacote de componentes e instale-o novamente.

Reinicie a sua IDE e veja o resultado!

Introdução ao ECO

Escrito em 18 de Janeiro de 2007 em .Net, Delphi, ECO, Linguagem Delphi, Orientação a Objetos, Programação por Zote

 

ECO - Enterprise Core Objects, é um framework para persistência de objetos.

Você já pensou em como seria bom se precupar com o negócio e não com a tecnologia, não precisar se preocupar com operações de banco de dados (select, insert, update, delete)?

Se marcarmos o tempo se investimos nesse tipo de operação, veremos que não é investimento, mas que depois de muito trabalho, é na verdade um pouco perda de tempo. Você poderia ter investido esse recurso numa nova funcionalidade do software.
Voltando ao assunto :) o ECO vem resolver esse tipo de coisa pra gente. Com ele, você se preocupa em resolver o problema do cliente desenvolvendo um software. Operações com banco de dados, você esquece! Do BD você so vai precisar na pior das hipóteses em 3 casos:

  1. Criação / configuração.
  2. Backup.
  3. Na pior hipótese, restore.

O ECO é uma evolução do bold. Bold era(é?) para Delphi/Win32. ECO é para .NET tanto para Delphi Language tanto para C#.

Em ECO, você trabalha com Classes e Objetos, fazendo a modelagem utilizando UML. Então basicamente, você faz o diagrama de classes, configura qual banco de dados será utlizado, e o ECO faz toda a mágica gerando o código dessas classes pro sistema funcionar! ;)

Estou preparando alguns materiais mostrando como trabalhar com ele, assine nosso RSS para receber novos artigos.

Um abraço e até a próxima!

Records no Turbo / Delphi 2006

Escrito em 17 de Janeiro de 2007 em Delphi, Linguagem Delphi, Programação por Alexandre José

Records na linguagem Delphi são, basicamente, um conjunto de vários elementos. Cada elemento é chamado de campo(field) e cada campo é formado por um nome(name) e tipo(datatype).

Exemplo:

type
  TTechTips = record
    Campo1 : Integer;
    Campo2 : string;
  end;

No Turbo/Delphi 2006 os records ficaram mais poderosos e espertos! Abaixo listei as suas novas características:

  • Podem possuir construtores, com pelo menos um parâmetro;
  • suportam propriedades e métodos estáticos;
  • suportam sobrecarga de operador;
  • não suportam métodos virtuais(virtual, dynamic e message);
  • não suportam destrutores.

Exemplo de uma estrutura no Turbo/Delphi 2006:

 

type
  TTechTips2006 = record
  strict private
    FValorNome : Integer;
    function getNome: string;
  public
    FPrefixo : string;
    constructor Create(const Nome: Integer);
    property Nome : string read getNome;
  end; 

implementation 

{ TTechTips2006 } 

constructor TTechTips2006.Create(const Nome: Integer);
begin
  FValorNome := Nome;
  FPrefixo := '"utilizando constructor"';
end;
function TTechTips2006.getNome: string;
begin
  Inc(FValorNome);
  Result := Format('%s %d', [FPrefixo, FValorNome]);
end;

Adicione um TMemo no formulário (name: mmo1):

procedure TForm1.FormShow(Sender: TObject);
var
  recAux1 : TTechTips2006;
  recAux2 : TTechTips2006;
begin
  // sem constructor [FValorNome = 0 por padrão]:
  recAux1.FPrefixo := 'D2006: ';
  mmo1.Lines.Add(recAux1.Nome);
  mmo1.Lines.Add(recAux1.Nome);
  // utilizando constructor:
  recAux1 := TTechTips2006.Create(2006);
  mmo1.Lines.Add(recAux1.Nome);
  mmo1.Lines.Add(recAux1.Nome);
  recAux2 := recAux1;
  recAux2.FPrefixo := 'Adicional';
  mmo1.Lines.Add(recAux2.Nome);
  mmo1.Lines.Add(recAux2.Nome);
  mmo1.Lines.Add(recAux1.Nome);
  mmo1.Lines.Add(recAux1.Nome);
  // não é necessário utilizar Free com Records.
end;

Para baixar o source deste artigo clique aqui.

Propriedades no Object Inspector para Forms

Escrito em 17 de Janeiro de 2007 em IDE por Leonel Togniolli

Um recurso que muita gente procura mas não é muito óbvio em primeira vista é como adicionar propriedades em um form que será herdado para que elas apareçam no Object Inspector. Vamos ver como fazer isso.

Primeiramente, um package e adicione um novo form nele. Crie uma seção published na declaração do form e adicione qualquer propriedade que quiser. No meu caso, a declaração ficou assim:

type
  TFormComPropriedades = class(TForm)
  private
    FMensagem: string;
  published
    property Mensagem: string read FMensagem write FMensagem;
  end;

Crie uma nova unit, adicione DesignIntf e DesignEditors no uses da implementação, e inclua uma função Register, ficando tudo assim assim:

unit FormPropReg;

interface

procedure Register;

implementation

uses UnitFormProp, DesignIntf, DesignEditors;

procedure Register;
begin
  RegisterCustomModule(TFormComPropriedades, TCustomModule);
end;

end.

Clique com o botão direito no designer do form e selecione Add To Repository. Preencha os dados pra ele aparecer na lista de forms que podem ser herdados. Compile o package, clique com o botão direito sobre ele no Project Manager e selecione Install.

Agora é só criar uma nova aplicação, ir em File/New/Other, escolher o formulário que foi adicionado anteriormente, selecionar inherit (e não copy!), e pronto. As propriedades devem então aparecer no object inspector:

Usando Frames na prática Parte 01/N

Escrito em 16 de Janeiro de 2007 em VCL/RTL por leosimas

Olá Pessoal, estou aqui para falar de sobre frames.
Frame é como se fosse uma form instanciada como um componente panel.
O Help do delphi o chama de container, mas ele não é um mero container, se aplicado de forma corretamente.

Situação:
No seu sistema você tem um listbox aonde seu analista(um cara muito criativo) quer que o usuário possa incluir, alterar e excluir items.
É um listbox de filtro de likes. Ex: O usuário pode pesquisar por produtos que começam com ‘Abac’ e ‘Lim’.

Problema:
Não convém criar uma tabela pra isso devido aos milhares de combinações diferentes já que sempre vai ser por algo específico.
Seu analista não te disse, mas tem centenas de telas de relatório que vc vai ter que alterar para mesma coisa.
Muitos podem pensar “Crio os 3 botões ali naquela tela e depois só copio e colo nas outras telas!”, mas o problema de fazer isso é a redundância de código.
Muitos podem pensar “Vamos criar uma classe e passamos os botões na criação” Mesmo assim o código vai ter que ter redundância.
Muitos podem pensar “Vamos criar um componente pra isso.”. Quase lá! O problema disso é ter q instalar o componente em cada máquina e sempre ter que recompilá-lo a cada alteração até ele estar pronto.
A solução é simples: Frames!
Você deve ter exclamado: “Ok. Ok Léo Simas! Como frames vai ser melhor que tudo isso aí?”
Para solucionarmos esse problema, nada melhor que um exemplo prático!
Mãos à obra!

*Crie uma nova aplicação.
*Com a Form vazia mesmo, vá em File->New->Frame.
Vai aparecer algo meio estranho. Parece um painel, mas tem botões de form.
Isso é o nosso frame.
*Chame-o de FmAddLista.
*Deixe o Frame com width como 280 e Height como 35.
*No public do nosso Frame declare isso:

  public
    Lista : TListbox;
  end;

Não coloque um listbox na tela. O Objeto Lista vai ser apenas um referencial depois.
*Adicione 3 botões com os captions respectivos como “I”,”A”,”X”.
Vai ficar parecido com isso:
frame01b.jpg
No primeiro botão vamos fazer ele incluir nesse objeto que chamamos Lista:

  procedure TFmAddLista.SpeedButton1Click(Sender: TObject);
  begin
    If not assigned(Lista) then exit;
    Lista.items.add(InputBox('Informe o items','Informe o item','item'));
  end;

No segundo botão vamos fazer ele alterar o item selecionado nesse objeto que chamamos Lista:

  procedure TFmAddLista.SpeedButton2Click(Sender: TObject);
  begin
    If not assigned(Lista) then exit;
    If Lista.itemindex < 0 then exit;
    Lista.items[Lista.itemindex] := InputBox('Informe o item',
                                             'Informe o item',
                                              Lista.items[Lista.itemindex]);
  end;

No terceiro botão vamos fazer ele excluir o item nesse objeto que chamamos Lista:

  procedure TFmAddLista.SpeedButton3Click(Sender: TObject);
  begin
    If not assigned(Lista) then exit;
    If Lista.itemindex < 0 then exit;
    Lista.items.delete(Lista.itemindex);
  end;

Se vc tentar compilar, vai compilar certinho. Mesmo não tendo um Listbox na tela.
Agora voltamos a tela principal do cliente.
Na aba Standard, o primeiro componente é o TFrame.
Clique nele e clique na form principal.
Uma janela aparecerá com todos os frames do seu projeto.
Escolha o FmAddLista.
Bingo!
Seu frame está na tela principal!
Assim:
frame01a.jpg
Agora a Ultima parte.(Mas já?)
No oncreate da form principal coloque:

  procedure TForm1.FormCreate(Sender: TObject);
  begin
    fmaddlista1.lista := Listbox1;
  end;

Pode botar seu programa pra rodar!
Você deve estar se perguntando: “Como isso????”
Simples. Declaramos nosso frame como um controlador de items de um listbox.
Que listbox? Qualquer um que vc carregue para objeto lista dele.
Experimente dar Ctrl+C e Ctrl+V no seu frame da tela principal!
Isso mesmo! Você pode ter quantos quiser. Usados na sua aplicação.
Coloque vários frames e vários listbox e ligue eles no oncreate.
Ligue um mesmo listbox a vários frames FmAddlista.
Agora é por sua imaginação… :)
Espero que tenham gostado.
Até a próxima!
Falowzzzzzzzzzzzzz

Próxima Página »