[Delphi] Criando um visualizador de DataSets com o Open Tools API – Parte 1

[Delphi] Criando um visualizador de DataSets com o ToolsAPI - Parte 1

Leitores, hoje é dia de assunto inédito no blog!
Você sabiam que é possível programar ações personalizadas na IDE do Delphi? Com algumas Interfaces especiais, chamadas de Open Tools API, podemos adicionar novos menus na IDE para executar ações específicas, codificadas por nós mesmos.
Para exemplificar este recurso, desenvolveremos um visualizador de DataSets em runtime que ficará disponível no menu Help do Delphi.

 

Você provavelmente utiliza – ou já utilizou – add-ins no Delphi para aprimorar a produtividade, como o GExperts, MMX, CnPack ou o DDevExtensions, certo? Essas extensões são tecnicamente conhecidas como “wizards” no RAD Studio e geralmente adicionam um novo menu na IDE do Delphi com várias opções para auxiliar nas atividades de programação. Porém, alguma vez você já se perguntou como estes wizards foram criados?

A resposta é simples. A Embarcadero disponibiliza um conjunto de Interfaces para trabalhar com as propriedades internas da IDE, chamadas de Open Tools API. Através dessas Interfaces, podemos, por exemplo, acessar o menu da IDE, o Project Manager, o editor de códigos ou a paleta de componentes. Com essa liberdade, é possível “estender” a IDE, adicionando ações personalizadas conforme desejamos. O uso dessas Interfaces é extremamente útil, por exemplo, para desenvolver add-ins que aprimorem a produtividade dos desenvolvedores de uma equipe.

Para este artigo, faremos um wizard bem simples, mas muito útil, para visualizar os dados de um DataSet em tempo de execução (runtime). Essa funcionalidade pode nos ajudar bastante no rastreamento de erros e na análise da execução de rotinas. Imagine, por exemplo, que uma exceção esteja ocorrendo na iteração dos registros de um DataSet em uma classe não-visual. A princípio, não conseguimos verificar os dados que estão carregados naquele momento de maneira fácil. Seria interessante, portanto, se houvesse uma forma de exibir esses dados em uma Grid, não acham? 🙂

Bom, vamos partir para o hands-on!

 

1) Criar um pacote para adicionar o wizard
Existem basicamente dois meios de distribuir um wizard: por pacote ou por DLL. Neste artigo, abordaremos a primeira modalidade por ser mais didático.
Acesse o menu File > New > Other e selecione Package na janela New Items. O nome e diretório do pacote é de sua preferência.

 

2) Adicionar a referência ao “designide.dcp” na seção Requires
Essa inclusão nos permitirá ter acesso às bibliotecas do Open Tools API em design-time. O arquivo “designide.dcp” está localizado na pasta “..lib\win32\release\” do RAD Studio. Para adicioná-lo, clique com o botão direito na seção Requires e acione a opção Add Reference, informando-o no campo Package Name.

Inclusão da referência ao arquivo "designide.dcp" na seção Requires

 

3) Adicionar uma nova unit no pacote
Só precisaremos de uma única unit para criar o nosso wizard. Clique com o botão direito no pacote e acesse o menu Add New > Unit, nomeando-a com o nome que desejar. A nova unit será anexada à seção Contains do pacote.

Inclusão de uma nova unit na seção Contains

 

4) Escrever a classe
Antes de iniciar, adicione a unit ToolsAPI na uses da unit para utilizarmos as Interfaces.
Pois bem, para que o Delphi reconheça o nosso pacote como um wizard, a classe deverá implementar a Interface IOTAWizard, na qual exige a implementação dos oito métodos descritos abaixo:

uses
  ToolsAPI;
 
type
  TVisualizadorDataSets = class(TInterfacedObject, IOTAWizard)
  private
    { Assinaturas do IOTAWizard }
    function GetState: TWizardState;
    function GetIDString: string;
    function GetName: string;
    procedure AfterSave;
    procedure BeforeSave;
    procedure Destroyed;
    procedure Execute;
    procedure Modified;
  end;

No nosso exemplo, implementaremos somente os quatro métodos a seguir:

  • GetState: para indicar se o wizard está habilitado;
  • GetIDString: para informar o identificador do wizard;
  • GetName: para informar o nome do wizard;
  • Execute: ação que o wizard irá executar.

uses
   Vcl.Dialogs;
 
function TVisualizadorDataSets.GetIDString: string;
begin
  // Texto de identificação do wizard
  result := 'Visualizador de DataSets';
end;
 
function TVisualizadorDataSets.GetName: string;
begin
  // Nome do wizard, exigido pela IDE
  result := 'Visualizador de DataSets';
end;
 
function TVisualizadorDataSets.GetState: TWizardState;
begin
  // Indica que o wizard está habilitado na IDE
  result := [wsEnabled];
end;
 
procedure TVisualizadorDataSets.Execute;
begin
  // Executa a ação do wizard
  ShowMessage('Visualizador de DataSets acionado!');
end;

Os outros métodos podem ficar vazios.

 

Uma vez que a nossa classe implementa a Interface IOTAWizard, podemos registrá-la com o método RegisterPackageWizard, informando uma instância da classe como parâmetro. A chamada deste método deve ser declarada dentro do procedimento padrão de registro de componentes do Delphi, ou seja, com o método Register. Na verdade, essa etapa é semelhante ao registro de componentes do Delphi, quando usamos o RegisterComponents.

type
  TVisualizadorDataSets = class(TInterfacedObject, IOTAWizard)
  private
    { Assinaturas do IOTAWizard }
    function GetState: TWizardState;
    function GetIDString: string;
    function GetName: string;
    procedure AfterSave;
    procedure BeforeSave;
    procedure Destroyed;
    procedure Execute;
    procedure Modified;
  end;
 
procedure Register;
 
implementation
 
procedure Register;
begin
  // Registra o Wizard
  RegisterPackageWizard(TVisualizadorDataSets.Create);
end;

Neste momento, ao instalar o pacote (botão direito > Install), o wizard já será automaticamente registrado na IDE. Porém, se você navegar pelos menus do Delphi, não irá encontrá-lo. O motivo é que ainda não programamos o código para que ele fique visível. Avançaremos, então, para o próximo passo.

 

5) Implementar a Interface IOTAMenuWizard
Já sabemos que, no Delphi, uma classe pode implementar várias Interfaces, correto? Bom, este será o nosso caso. Além de IOTAWizard, a classe também implementará a Interface IOTAMenuWizard, que exige apenas a implementação do método GetMenuText. Este método, conforme já podemos presumir, é o texto do menu que aparecerá na IDE do Delphi:

type
  TVisualizadorDataSets = class(TInterfacedObject, IOTAWizard, IOTAMenuWizard)
  private
    { Assinaturas da Interface IOTAWizard }
    function GetState: TWizardState;
    function GetIDString: string;
    function GetName: string;
    procedure AfterSave;
    procedure BeforeSave;
    procedure Destroyed;
    procedure Execute;
    procedure Modified;
 
    { Assinatura da Interface IOTAMenuWizard }
    function GetMenuText: string;    
  end;
 
implementation
 
{ ... }
 
function TVisualizadorDataSets.GetMenuText: string;
begin
  // Texto que aparecerá no menu Help > Help Wizards
  result := 'Visualizar DataSet';
end;

Opa, agora, sim!
Quando instalarmos novamente o nosso pacote, um novo submenu será adicionado no menu Help > Help Wizards do Delphi, conforme ilustrado na imagem abaixo.

Menu do wizard visível na IDE do Delphi

Por fim, ao clicarmos no menu, a mensagem que codificamos no método Execute será exibida:

Ação do wizard ao clicar no menu

 

Interessante, não? 🙂
Nota: caso você receba uma mensagem informando que não foi possível instalar o pacote, desinstale-o primeiro (botão direito > Uninstall) antes de instalá-lo novamente. Na verdade, ao realizar as alterações na unit, não é necessário reinstalar o pacote. A operação de Build, por si só, já atualiza o binário gerado, refletindo as alterações no wizard.

 

Na próxima parte do artigo, trabalharemos exclusivamente no método Execute, que ficará responsável por salvar os dados do DataSet.
Até amanhã, pessoal!


[Delphi] Criando um visualizador de DataSets na IDE com o ToolsAPI – Parte 1
[Delphi] Criando um visualizador de DataSets na IDE com o ToolsAPI – Parte 2
[Delphi] Criando um visualizador de DataSets na IDE com o ToolsAPI – Parte 3
[Delphi] Criando um visualizador de DataSets na IDE com o ToolsAPI – Parte 4


 

Compartilhe!
Share on FacebookTweet about this on TwitterShare on LinkedInShare on Google+Pin on PinterestEmail this to someone

8 comentários

  1. Bom dia!
    Vou acompanhar essa série!
    Excelente trabalho meu amigo(acho que já posso chamar assim né kkkkkk)
    Abraço

  2. Olá André, tudo bem?
    Sei que minha questão não está relacionada com o post, portanto, desde já me perdoe.

    Então, recentemente, migrei meu projeto do Delphi XE6 para o Berlin, até aí nada demais no entanto. O problema começou a surgir sempre que eu dava um click em um componente (do próprio Delphi) como o Combobox, ou um Edit por exemplo. A aplicação simplesmente trava e o Windows dá mensagem que o programa parou de funcionar, então a aplicação é fechada. Como eu não consegui resolver este problema, testei em uma nova aplicação feita do zero no Delphi Berlim 10.1 Update 2. O problema continuou. Então fiz outro teste para tentar compreender melhor onde poderia estar contido o erro: Criei uma nova aplicação, com apenas o formulário principal, sem código algum e coloquei nesse formulário um combobox e um edit, mais nada. Somente um formulário, um combobox e um edit, sem código algum, e a aplicação continua parando de funcionar ao clicar no combobox ou no edit.
    Há explicação aparente para isso? É um bug no Delphi Berlin?

    Agradeço desde já André.
    Muito obrigado.
    Adriano.

    1. Olá, Adriano.
      Sinto muito por estar experienciando estes problemas com o RAD Studio Berlin. Acredito que não seja um problema da versão, já que a utilizo desde o primeiro Update e não tive complicações. De qualquer forma, vou entrar em contato para tentar ajudá-lo.
      Abraço!

  3. mto bom seu artigo
    e a funcionalidade q vc desenvolveu ao longo dessa serie é brilhante! 😀
    n tenho comentado mto, mas sempre acompanho seus posts! 😛
    MMX eu nao conhecia, me parece ser pago, estou correto?
    DDevExtensions eu tb n conhecia

    sobre esses 2, saberia dizer de alguma funcionalidade q eu deveria conhecer?
    estou instalando pra testar, mas se tiver algo para me direcionar…

    atualmente uso CnPack, o fato dele sugerir prefixos nos nomes e colorir BEGINs e ENDs é o principal motivo de eu o usar, GExperts me pareceu um pouco redundante com CnPack, nao teve nenhuma opção q me chamou a atenção a ponto de ter ele instalado.

    Abs

    1. Fala, Conde, quanto tempo! 🙂
      Isso mesmo, o MMX é pago, mas é bem produtivo.
      O DDevExtensions incrementa algumas funcionalidades principalmente relacionadas à compilação como, por exemplo, mostrar o tempo dispendido.
      O CnPack e o GExperts realmente possuem muitas funcionalidades semelhantes. Geralmente os desenvolvedores optam por apenas um deles. Acredito que o CnPack é mais utilizado, mas o GExperts traz algumas particularidades, como o Code Librarian (biblioteca de códigos), Code Proofreader (corretor de códigos) e o Grep Search (pesquisador de arquivos).
      Nada impede que o desenvolvedor tenha 2 ou 3 desses add-ins instalados ao mesmo tempo, mas deve ter consciência de que eles deixam a IDE um pouco mais carregada.

      Abraço!

  4. Bom dia, parabéns pelo artigo.
    Ao declarar a uses ToolsAPI, meu Delphi não a localiza: File not found: ‘ToolsAPI.dcu’
    Adicionei no Library Path do Delphi: $(Delphi)\Source\ToolsAPI
    Mas agora esta unit não está encontrando o arquivo: ‘DockForm.dcu’

    Qual erro será que estou cometendo?

    1. Olá, Paulo, tudo bem?
      Peço desculpas pela demora. Por algum motivo, o seu comentário foi motivo para a caixa de spams.
      Vou entrar em contato por e-mail. Abraço!

Deixe uma resposta

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *

Preencha o campo abaixo * Time limit is exhausted. Please reload CAPTCHA.