Parte 1 – Criando o Host | Parte 2 – Criando o Plugin | Parte 3 – Item de Menu

Os artigos anteriores mostrei como o plugin assina à um item de menu do aplicativo host.  Agora é a vez de um plugin que assina ao serviço de janela, permitindo que seja embutido (embedded) como um componente da janela.

embedded

Criar o Plugin

  1. Criar um projeto DLL em branco;
  2. Adicionar ao projeto um FORM a ser inserido no formulário do aplicativo HOST;
  3. Incluir as UNITs: plugin.Service, plugin.Control no FORM;
  4. na Seção Initialization registrar o Plugin na lista de plugins disponíveis na DLL:
    RegisterPlugin(TPluginControlService.create(TForm1,1,0,'my control embedded'));
  5. Copiar a DLL do projeto para a pasta de “Plugins” do aplicativo HOST;

Exemplo:

[code lang=”pascal”]

{$R *.dfm}

uses plugin.Service, plugin.Control;

……..

initialization

RegisterPlugin(TPluginControlService.create(TForm1,9999,1,’my control embedded’));

finalization

end.
[/code]

 

Inserindo o Plugin em uma janela do HOST

  1.  Se o projeto HOST ainda não tem recurso para suportar plugin – arrastar o componente  TPluginManager para o formulário principal;TPluginManager
  2. Escolher um formulário onde deseja inserir o plugin controle (embedded) – arrastar um TPanel para o local onde o plugin será inserido, para estabelecer a área a ser ocupada pelo plugin (interno no plugins ele executa Align=alClient no formulário);
  3. Incluir na uses a UNIT no formulário: plugin.Manager (a mesma utilizada pelo component TPluginManager);
  4. No evento OnShow do formulário fazer chamada ao Manager do plugin para encontrar o plugin ser incorporado:
      GetPluginManager.EmbedControl(Panel1.Handle,9999,1);

Observando os parâmetros da procedure

TPluginManager.EmbedControl(AParentHandle: THandle;
AControlID, AControlType: Int64);

cabe considerar:

  • AParentHandle -> é o handle do TPanel onde o plugin será incorporado;
  • AControlID -> é um identificador para carregar um determinado plugin em específico – identifica o ID da janela que irá consumir o plugin (valor fixo nos dois lados);
  • AControlType -> um ID para separar os vários plugins que uma mesma janela pode consumir;

Quando chama

GetPluginManager.EmbedControl(Panel1.Handle,9999,1); 
deve inserir no Panel1 um plugin de controle identificado por 9999 que contenha serviços do tipo 1;

<a href="https://github.com/amarildolacerda/helpers/tree/master/plugin">Ver código de exemplo</a>

 

Parte 1 – Criando o Host | Parte 2 – Criando o Plugin

Registrando MenuItem no Host

No artigo anterior foi apresentado o exemplo de um plugin que assina o serviço de Menu do Host chamando o método:

[code]
PluginApplication.RegisterMenuItem(‘mnPlugins’, ‘Meu menu que adiciona um plugin’, self as IPluginMenuItem);
[/code]

 

Ao receber a chamada ao método do PluginApplication.RegisterMenuItem o host deverá coletar informações sobre o plugin bem como executar ações para disponibilizar o recurso solicitado.

Tratando-se de MenuItem, a implementação do host será criar o item de menu no local adequado para que seja visível ao usuário.

Um exemplo de como criar o item de menu no host:

 

[code lang=”pascal”]

// um item de menu para guardar a interface que o plugin assina
TPluginMenuItemInterf = class(TMenuItem)
protected
FProc: TProc<TObject>; // anonimous
procedure DoClick(Sender: TObject);
public
PluginMenuItem: IPluginMenuItem;
constructor Create(AOwner: TComponent; AProc: TProc<TObject>); overload;
end;

// implementação no TPluginManager -> para criar um item de menu no host
procedure TPluginManager.NewMenuItem(AMainMenu: TMainMenu;
ADefaultMenu: TMenuItem; const APath, ACaption: string;
ADoExecute: IPluginMenuItem; AProc: TProc<TObject>);
var
it: TPluginMenuItemInterf;
itClient: TMenuItem;
begin
inc(itCount);
// procura o menu para mostrar
itClient := AMainMenu.FindItem(APath);
if itClient = nil then
itClient := ADefaultMenu; // se nao encontrou pega um padrao

if not assigned(AProc) then
AProc := (
procedure(Sender: TObject)
begin
with TPluginMenuItemInterf(Sender) do
PluginMenuItem.DoClick(0);
end);

// cria o menu
it := TPluginMenuItemInterf.Create(AMainMenu, AProc);
it.Name := ‘mnPlugin_’ + formatDatetime
(‘hhmmsszzz_’ + intToStr(itCount), now);
it.PluginMenuItem := ADoExecute;
it.Caption := (it.PluginMenuItem as IPluginMenuItem).GetCaption;
// adiciona o menu na lista
itClient.Add(it);

end;

[/code]

 

Pensando em facilitar a integração no HOST é possível registrar o componente na aba do Delphi – Arrastar e soltar o componente TPluginManager no formulário principal do HOST.

PluginManager

Explorando código padrão para o evento do TPluginManager.RegisterMenuItem  irá notar que já foi implementado as funcionalidades para inserir o plugin no menu do aplicativo. Caso deseje mudar o comportamento do evento padrão, basta implementar o evento do componente com funcionalidade personalizadas…

 

Fontes: Código base para o Plugin

Parte 1 – Criando o Host

Na parte 1 deste artigo tracei as linhas básicas para a implementação do Aplicativo Principal HOST – se ainda não o leu, será mais produtivo fazê-lo antes de continuar.

Criando um Plugin
O Plugin em si consiste em uma DLL que “exports” 2 entradas:

  1. function LoadPlugin(AAplication: IPluginApplication): IPluginItems;
  2. procedure UnloadPlugin;

A base para a criação do plugin é a unit: plugin.Service

LoadPlugin
“LoadPlugin” é utilizado quando o HOST inicia o plugin; O parâmetro IPluginApplication representa os serviços publicados no HOST disponíveis para assinatura pelos plugins. Assim todos os serviços que o HOST implementar deve se publicada para que sejam visíveis aos plugins.

Nos casos em que houver necessidades de estender os serviços publicados pelo HOST, IPluginApplication será a interface base publicada adicionada de novos serviços…   IMyPluginApplication = interface( IPluginInterface) …

O Plugin registra-se à lista de plugins 

IPluginItems – é uma lista de plugins disponíveis na DLL;

Para que IPluginItems seja populada o plugin poderá escolher entre os serviços padrões, aquele a que deseja assinar.

[code lang=”pascal”]
initialization
RegisterPlugin(TPluginMenuItemService.Create(TForm1,”,1, ‘Menu base de sample’));

[/code]

DoStart
Após a inicialização do LoadPlugin, ocorrerá um evento “DoStart” que inicializa cada um dos plugins da lista registrada. É neste momento que o plugin fará o pedido de assinatura  no HOST… Tudo isto é feito internamente pelo objeto “TPluginMenuItemService” do exemplo.

[code lang=”pascal”]
procedure TPluginMenuItemService.DoStart;
begin
inherited;
PluginApplication.RegisterMenuItem(FMenuItemName, GetCaption, self);
end;
[/code]

Um esqueleto para um plugin de MenuItem

[code lang=”pascal”]
unit uMenuItemSimple;

interface

uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
System.Classes, Vcl.Graphics,
plugin.Interf, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls,
Vcl.ExtCtrls;

type
TForm1 = class(TForm)
Button1: TButton;
LabeledEdit1: TLabeledEdit;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }

public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

uses plugin.Service, plugin.MenuItem, plugin.Control;

procedure TForm1.Button1Click(Sender: TObject);
begin
close;
end;

initialization

RegisterPlugin(TPluginMenuItemService.Create(TForm1,”,1, ‘Menu base de sample’));

finalization

end.
[/code]