012.Delphi插件之QPlugins,多实例内嵌窗口服务
2021-02-03 18:18
标签:dct ice RoCE ted nts dock rtm sse signed 这个DEMO中主要是在DLL中建立了一个IDockableControl类,并在DLL的子类中写了具体的实现方法。 在主程序exe中,找到这个服务,然后调用DLL的内嵌方法,把DLL插件窗口内嵌到主程序中。 界面如下 DLL代码如下: EXE代码如下 012.Delphi插件之QPlugins,多实例内嵌窗口服务 标签:dct ice RoCE ted nts dock rtm sse signed 原文地址:https://www.cnblogs.com/tianpan2019/p/11498642.htmlunit Frm_Dll;
interface
uses
Winapi.Windows,
Winapi.Messages,
System.SysUtils,
System.Variants,
System.Classes,
Vcl.Graphics,
Vcl.Controls,
Vcl.Forms,
Vcl.Dialogs,
qstring,
QPlugins,
Vcl.Imaging.jpeg,
Vcl.ExtCtrls,
Vcl.StdCtrls,
Vcl.AxCtrls,
qplugins_base,
qplugins_vcl_messages;
type
TForm_Dll = class(TForm)
Panel1: TPanel;
Button1: TButton;
CheckBox1: TCheckBox;
Edit1: TEdit;
Edit2: TEdit;
Image1: TImage;
Label1: TLabel;
private
{ Private declarations }
protected
procedure CreateParams(var Params: TCreateParams); override;
public
{ Public declarations }
end;
// 创建一个接口,方法都由子类来实现
IDockableControl = interface
[‘{D0A4BDFA-CB29-4725-9158-C199B9C373C9}‘]
procedure DockTo(AHandle: HWND); stdcall;
procedure HostSizeChanged; stdcall;
end;
// 接口方法的类
TDockableService = class(TQService, IDockableControl)
protected
FForm: TForm;
procedure DockTo(AHandle: HWND); stdcall;
procedure HostSizeChanged; stdcall;
public
constructor Create(const AId: TGuid; AName: QStringW); overload; override;
destructor Destroy; override;
end;
TDockInstanceService = class(TQService)
public
function GetInstance: IQService; override; stdcall;
end;
var
Form_Dll: TForm_Dll;
implementation
{$R *.dfm}
{ TDockableService }
constructor TDockableService.Create(const AId: TGuid; AName: QStringW);
begin
// 继承
inherited Create(AId, AName);
end;
// 销毁
destructor TDockableService.Destroy;
begin
FreeAndNil(FForm);
inherited;
end;
// 内嵌窗口
procedure TDockableService.DockTo(AHandle: HWND);
begin
// 创建窗体
FForm := TForm_Dll.Create(nil);
FForm.BorderStyle := bsNone;
FForm.ParentWindow := AHandle;
FForm.DoubleBuffered := True;
FForm.Show;
// 设置窗口大小
HostSizeChanged;
end;
procedure TDockableService.HostSizeChanged;
var
R: TRect;
begin
// 取父窗口大小
GetClientRect(Winapi.Windows.GetParent(FForm.Handle), R);
// 设置子窗口大小
FForm.SetBounds(0, 0, R.Width, R.Height);
end;
{ TDockInstanceService }
function TDockInstanceService.GetInstance: IQService;
begin
Result := TDockableService.Create(NewId, ‘DockableService‘);
end;
{ TForm2 }
procedure TForm_Dll.CreateParams(var Params: TCreateParams);
begin
inherited;
Params.Style := Params.Style and (not(WS_CAPTION or WS_THICKFRAME));
// 不要标题和边框,实际上就是 BorderStyle 为 bsNone 的效果
end;
initialization
// 注册 /Services/Docks/Frame 服务
RegisterServices(‘Services/Docks‘, [TDockInstanceService.Create(IDockableControl, ‘Frame‘)]);
finalization
// 取消服务注册
UnregisterServices(‘Services/Docks‘, [‘Frame‘]);
end.
unit Frm_Main;
interface
{
VCL DLL或主程序需要引用 QPlugins.VCL 单元,该单元实现了替代的消息处理和派发
}
uses
Winapi.Windows,
Winapi.Messages,
System.SysUtils,
System.Variants,
System.Classes,
Vcl.Graphics,
Vcl.Controls,
Vcl.Forms,
Vcl.Dialogs,
Vcl.ComCtrls,
Vcl.StdCtrls,
Vcl.ExtCtrls,
QPlugins,
QPlugins_loader_lib,
QPlugins_Vcl_Messages;
type
TForm1 = class(TForm)
Panel1: TPanel;
Button1: TButton;
PageControl1: TPageControl;
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure PageControl1Resize(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
// DLL中的接口,方法都由DLL的子类来实现
IDockableControl = interface
[‘{D0A4BDFA-CB29-4725-9158-C199B9C373C9}‘]
procedure DockTo(AHandle: HWND); stdcall;
procedure HostSizeChanged; stdcall;
end;
// 加强的Tabsheet
TDockHostPage = class(TTabSheet)
private
procedure SetDockedControl(const Value: IDockableControl);
protected
FDockedControl: IDockableControl;
public
property DockedControl: IDockableControl read FDockedControl write SetDockedControl;
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
// 按钮_新页
procedure TForm1.Button1Click(Sender: TObject);
var
ACtrl: IDockableControl;
ATabSheet: TDockHostPage;
begin
// 根据‘Services/Docks/Frame‘找到DLL中的TDockInstanceService服务
ACtrl := PluginsManager.ByPath(‘Services/Docks/Frame‘) as IDockableControl;
// 如果这个服务存在
if Assigned(ACtrl) then
begin
// 创建一个加强的Tabsheet,并把DLL中的TDockInstanceService服务内嵌进去
ATabSheet := TDockHostPage.Create(PageControl1);
ATabSheet.PageControl := PageControl1;
ATabSheet.Caption := ‘第 ‘ + IntToStr(PageControl1.PageCount) + ‘ 页‘;
ATabSheet.DockedControl := ACtrl;
// 激活
PageControl1.ActivePage := ATabSheet;
end
else
begin
Application.MessageBox(‘Services/Docks/Frame 服务未注册,请编译DLL先。‘, ‘服务未注册‘, MB_OK or MB_ICONSTOP);
end;
end;
// 创建
procedure TForm1.FormCreate(Sender: TObject);
var
APath: string;
begin
ReportMemoryLeaksOnShutdown := True;
APath := ExtractFilePath(Application.ExeName);
// 注册默认的 DLL 加载器,扩展名可以根据实际的情况随意修改,多个扩展名之间用逗号或分号分隔
PluginsManager.Loaders.Add(TQDLLLoader.Create(APath, ‘.dll‘));
// 启动插件注册,如果要显示加载进度,可以注册IQNotify响应函数响应进度通知
PluginsManager.Start;
end;
// 窗口大小调整
procedure TForm1.PageControl1Resize(Sender: TObject);
var
I: Integer;
APage: TDockHostPage;
begin
// 遍历窗体
for I := 0 to PageControl1.PageCount - 1 do
begin
APage := PageControl1.Pages[I] as TDockHostPage;
if APage.DockedControl nil then
begin
APage.DockedControl.HostSizeChanged;
end;
end;
end;
{ TDockHostPage }
// 接口作为参数传过来就内嵌到加强的Tabsheet中
procedure TDockHostPage.SetDockedControl(const Value: IDockableControl);
begin
if FDockedControl Value then
begin
FDockedControl := Value;
if Assigned(Value) then
begin
// DLl中的内嵌窗口函数
Value.DockTo(Handle);
end;
end;
end;
end.
文章标题:012.Delphi插件之QPlugins,多实例内嵌窗口服务
文章链接:http://soscw.com/index.php/essay/50538.html