quinta-feira, 3 de março de 2011

Progresso de Transferência FTP com idFTP


Andei procurando muito pela web algum exemplo de como medir o progresso da transferência de um arquivo através do componente idFtp, no Delphi 6. Depois de muito procurar e nada encontrar, um pequeno exemplo que não funcionava muito bem me fez pensar um pouco e me levou, após alguns testes, a um medidor de progresso funcional, feito com um gauge.
Para fazer um exemplo, coloque um componente idFTP, um ListBox e um Button no seu formulário. Configure o seu componente de conexão de acordo com os dados do ftp que irá se conectar e declare uma variável global chamada bytesToTransfer

var
  Form1: TForm1;
  bytesToTransfer: integer;
em seguida, faremos a conexão e o download de todos os arquivos .exe que estiverem no ftp. No exemplo, o código foi implementado no evento onClick do botão:

procedure TForm1.Button1Click(Sender: TObject);
var
  indice: integer;
begin
  try
    //efetua a conexão ao FTP
    if IdFTP1.Connected then
      IdFTP1.Disconnect;
    IdFTP1.Connect();

    //lista todos os arquivos do tipo .exe do ftp no ListBox1
    IdFTP1.List(ListBox1.Items,'*.exe',false);

    //se não houverem arquivos, aborta
    if ListBox1.Items.Count = 0 then
      Abort;

    //para cada ítem do ListBox1
    for indice:=0 to ListBox1.Items.Count -1 do
    begin
      try
        //marca o ítem selecionado
        ListBox1.Selected[indice] := true;
        //captura o tamanho do arquivo para a varíavel global
        bytesToTransfer := IdFTP1.Size(ListBox1.Items.Strings[indice]);
        //inicia a transferência do arquivo
        IdFTP1.Get(ListBox1.Items.Strings[indice],
          '' + ListBox1.Items.Strings[indice],true);
      except
        on e:exception do
          showmessage(e.Message);
      end;
    end;

  finally
    //desconecta
    IdFTP1.Disconnect;
  end;
end;
No eventoWorkBegin do idFTP, que é disparado no momento em que o Download do arquivo é iniciado, faça:

procedure TForm1.IdFTP1WorkBegin(Sender: TObject; AWorkMode: TWorkMode;
   const AWorkCountMax: Integer);
begin
  //limpa a barra de progresso
  Gauge1.Progress := 0;
  //define o tamanho máximo para o Gauge
  if AWorkCountMax > 0 then
    Gauge1.MaxValue := AWorkCountMax
  else
    Gauge1.MaxValue := bytesToTransfer;
end;
E finalmente, a cada conjunto de bytes trazidos pelo componente, incrementamos o Gauge. Isso é feito no evento Work do idFTP:

procedure TForm1.IdFTP1Work(Sender: TObject; AWorkMode: TWorkMode;
   const AWorkCount: Integer);
begin
  //incrementa o Gauge
  Gauge1.Progress := AWorkCount;
end;

quarta-feira, 2 de março de 2011

Técnicas de depuração em Delphi e Prevenção de Bug


Muitas vezes pegamos um sistema legado de outro programador para realizarmos implementação de novas funcionalidades ou corrigir eventuais "bugs". Neste caso você vai precisar depurá-lo para encontrar os "bugs". O Delphi oferece ótimas ferramentas de depuração e quando você sabe como usá-las, você vai economizar muito tempo para corrigir o "bug" e chegar no resultado desejado
Neste caso quero indicar um tutorial que encontrei e ajudou quando o assunto era depuração de programas.
Aqui está o conteúdo:

Project options - antes que você possa começar a utilizar as ferramentas depurador do Delphi, você tem que certificar-se de todas as configurações necessárias são definidas opções depurador .

Breakpoints - Quando pressionar a tecla F5 ou clicando na barra esquerda do seu editor você pode adicionar uma linha vermelha para a sua fonte. Esta linha de origem terão um ponto de interrupção. Ao executar o programa, a execução irá parar quando ele passa a linha de origem. Agora você pode seguir em sua origem, usando algumas teclas de função.

Call stack - a janela Call Stack exibe as chamadas de função que o trouxe para a sua localização atual no programa e os argumentos passados para cada chamada de função.

Local variables - essa janela vai mostrar todas as variáveis locais e o seu valor atual no atual função ou procedimento.

Watches - você adicionar um Watches para controlar os valores das variáveis do programa ou expressões como você passar por cima ou em código de rastreamento.

Idéias para criar os seus próprios recursos de depuração Prevenção Bug Try-Finally Gotchas Try-Except Gotchas

Criando um gerador de senhas


Veja nesta dica um código simples mas bastante útil, que gera senhas aleatórias podendo conter somente numeros, somente letras ou letras e números. O autor também aborda um pouco do comando try..except. Confira!
Primeiramente, vamos ao tutorial: insira em um form um Edit, abaixo dele um RadioGroup e depois outro Edit. Nesse RadioGroup, procure pela propriedade Items no Object Inspector e adicione o seguinte:

Somente números Somente letras Letras e números

Após isso, adicione dois Buttons. No primeiro mude a propriedade Caption para "Gerar" e o segundo "Limpar". No OnClick do botao "Gerar" coloque o seguinte código:

procedure TForm1.Button1Click(Sender: TObject);
const
  letras = 'abcdefghijklmnopqrstuvxwyzABCDEFGHIJKLMNOPQRSTUVXWYZ';
  numeros = '1234567890';
  letrasnumeros = letras + numeros;
var
  i: integer;
begin
  try
    Edit2.Clear;
    for i := 1 to StrToInt(Edit1.Text) do
    begin
      if RadioGroup1.ItemIndex = 0 then
        Edit2.Text := Edit2.Text + numeros[random(length(numeros)) + 1]
      else if RadioGroup1.ItemIndex = 1 then
        Edit2.Text := Edit2.Text + letras[random(length(letras)) + 1]
      else if RadioGroup1.ItemIndex = 2 then
        Edit2.Text := Edit2.Text + letrasnumeros[random(length(letrasnumeros)) + 1];
    end;
  except
    showmessage('Insira somente números no primeiro Edit');
  end;
end;
Explicando

Criamos uma variavel i, do tipo inteira, que irá receber a quantidade de caracteres que o usuário quiser para a sua senha. Por isso convertemos o valor do Edit1.Text de String para Inteiro (StrToInt) dentro do for. Criamos também três constantes, adicionando a cada uma respectivamente as letras, números ou as duas juntas.

O comando "Try" funciona da seguinte maneira: falamos para o Delphi tentar executar esse código e, caso ele não conseguir, podemos utilizar o Except para apresentar, por exemplo, algumas mensagens de erro do que pôde acontecer. No exemplo, deve ser informado no Edit1 a quantidade de caracteres da senha e, caso a pessoa coloque letras ao invés de números, a função StrToInt não conseguirá ser executada. Com o Except, conseguimos informar ao usuário este problema e tiramos a mensagem de erro que o delphi emitiria, em inglês.

No segundo botão, coloque apenas:

procedure TForm1.Button2Click(Sender: TObject);
begin
  Edit2.Clear;
end;
Após isso efetue a seguinte alteração no seu Delphi : em Tool>Options, procure por Language Execeptions e desmarque "Notify on Language Execeptions". Isto fará com que o compilador do Delphi não interrompa o programa com as mensagens do depurador e deixe a mensagem ir diretamente ao programa.

Nesse momento, compile e rode sua aplicação, informe um número no primeiro edit, selecione um método de geração e veja a senha gerada no segundo edit. É o nosso código em funcionamento!

Pesquisa fonética no MySQL

Fonte: www.activedelphi.com.br

Olá pessoal! Há algum tempo atrás precisei fazer uma consulta por fonema em meu banco de dados e não achei muita coisa na internet, mas descobri que o MySQL a partir da versão 3 acrescentou uma função chamada soundex, que outros bancos até já utilizam, como o Oracle, por exemplo. Nesta dica mostrarei uma consulta simples, que pode ser implementada em qualquer linguagem de programação, pois é um código SQL.
Primeiramente vamos criar um banco no mysql:

shell>mysql –useuusario –psuasenha
mysql>create database fonema;
Query OK, 1 row affected (0.01 sec)
Agora vamos selecionar para uso o banco que acabamos de criar:

mysql>use fonema;
Database changed
Criando nossa tabela de teste:

mysql>create table fonetica (
cod INTEGER NOT NULL AUTO_INCREMENT,
nome VARCHAR(60) NOT NULL,
PRIMARY KEY (cod)
)
ENGINE = InnoDB;
Query OK, 0 rows affected (0.08 sec)
Vamos inserir alguns dados nesta tabela. No comando abaixo, dois nomes somente:

mysql>insert into fonetica (nome) values (“JAIME ADRIANO”),(“JAYME ADRIANO”);
Query OK, 2 rows affected (0.09 sec)
Records: 2 Duplicates: 0 Warnings: 0
Agora vamos a nossa consulta:

mysql>select * from fonetica where SOUNDEX(nome) like
    ->CONCAT(SOUNDEX(“JAIME ADRIANO”),”%”);
+-----+---------------+
 cod    nome
+-----+---------------+
 6      JAIME ADRIANO
 7      JAYME ADRIANO
+-----+---------------+
2 rows in set (0.00 sec)
Perceba que o banco retornou Jaime com i e com y, que foneticamente são pronunciados da mesma forma. Faça um teste ao contrario, colocando o nome JAYME na consulta, com y, e verá que ele também retornará os dois nomes com a mesma fonética.

Espero ter ajudado e daí por diante é com vocês! Façam as implementações e melhorias e postem aqui para ajudar outras pessoas. Esta dica foi extraida do meu blog, achei interessante postar aqui!

segunda-feira, 28 de fevereiro de 2011

Mudar a letra da unidade usando WMI e Delphi

Fonte: www.activedelphi.com.br

Veja nesta dica uma aplicação console com o código fonte de exemplo para se alterar a letra de unidade de disco (volume) através do WMI. A chave é usar a classe Win32_Volume e alterar a propriedade DriverLetter. Esta propriedade é de leitura e escrita, sendo assim, podemos atualiza-la diretamente e então chamar o método Put_ do objeto SWbemObject.
Para rodar o programa e fazer os testes, solicite no Delphi uma nova "Console Application", apague todo o seu conteúdo e coloque o código abaixo:

program ChangeVolumeLetter_WMI;
 
{$APPTYPE CONSOLE}
 
uses
  SysUtils,
  ActiveX,
  ComObj;
 
procedure  ChangeDriveLetter(OldDrive, NewDrive:Char);
var
  FSWbemLocator : OLEVariant;
  FWMIService   : OLEVariant;
  FWbemObjectSet: OLEVariant;
  FWbemObject   : OLEVariant;
  oEnum         : IEnumvariant;
  iValue        : LongWord;
begin;
  FSWbemLocator := CreateOleObject('WbemScripting.SWbemLocator');
  FWMIService   := FSWbemLocator.ConnectServer('localhost', 'root\CIMV2', '', '');
  FWbemObjectSet:= FWMIService.ExecQuery(
    Format('SELECT * FROM Win32_Volume Where DriveLetter=%s',
           [QuotedStr(OldDrive+':')]),
    'WQL',0);
  oEnum         := IUnknown(FWbemObjectSet._NewEnum) as IEnumVariant;
  if oEnum.Next(1, FWbemObject, iValue) = 0 then
  begin
    //Define a nova letra
    FWbemObject.DriveLetter:=NewDrive+':';
    //Aplica as mudanças
    FWbemObject.Put_();
  end;
end;
 
begin
 try
    CoInitialize(nil);
    try
      //Mudará a letra da unidade E para Z
      ChangeDriveLetter('E','Z');
      Readln;
    finally
      CoUninitialize;
    end;
 except
    on E:Exception do
    begin
        Writeln(E.Classname, ':', E.Message);
        Readln;
    end;
  end;
end.
Aí é só rodar e conferir a letra da unidade modificada, neste exemplo, alterando a unidade E para Z.

Algumas explicações na internet (em inglês):

WMI - Windows Management Instrumentation
Win32_Volume
Método Put_
SWbemObject