012.Delphi插件之QPlugins,多实例内嵌窗口服务

这个DEMO中主要是在DLL中建立了一个IDockableControl类,并在DLL的子类中写了具体的实现方法。

在主程序exe中,找到这个服务,然后调用DLL的内嵌方法,把DLL插件窗口内嵌到主程序中。

界面如下

DLL代码如下:

unit 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.

EXE代码如下

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.

原文地址:https://www.cnblogs.com/tianpan2019/p/11498642.html

时间: 2024-11-06 09:39:42

012.Delphi插件之QPlugins,多实例内嵌窗口服务的相关文章

009.Delphi插件之QPlugins,服务的热插拔

这个DEMO用来演示服务的替换,用起来总是怪怪的感觉,效果图如下 代码如下 unit Frm_Main; interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ExtCtrls, Vcl.StdCtrls, qplugins_base, QPlu

006.Delphi插件之QPlugins,多服务演示

演示效果如下 演示工程,全部就一个文件,代码如下 unit Frm_Main; interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, System.Rtti, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, qstring, QPlugins, qplugins_base,

Delphi插件创建、调试与使用应用程序扩展

Delphi插件创建.调试与使用应用程序扩展 翻译 : MiracleZ  有没有使用过Adobe Photoshop?如果用过,你就会对插件的概念比较熟悉.对外行人来说,插件仅仅是从外部提供给应用程序的代码块而已(举个例子来说,在一个DLL中).一个插件和一个普通DLL之间的差异在于插件具有扩展父应用程序功能的能力.例如,Photoshop本身并不具备进行大量的图像处理功能.插件的加入使其获得了产生诸如模糊.斑点,以及其他所有风格的奇怪效果,而其中任何一项功能都不是父应用程序自身所具有的.对于

C#开发奇技淫巧二:根据dll文件加载C++或者Delphi插件

原文:C#开发奇技淫巧二:根据dll文件加载C++或者Delphi插件 这两天忙着把框架改为支持加载C++和Delphi的插件,来不及更新blog了.      原来的写的框架只支持c#插件,这个好做,直接用c#的反射功能便可.但是公司不是所有人都搞C#,也不是所有的程序C#都能很好的完成,又或者其他公司提供的API不是C#的,这个时候,就需要这个框架能够支持多种语言了.      废话不多说,进入正题.     上网一搜,C#加载非托管的dll,无非就是使用 DllImportAttribut

jquery easyui+sparkline插件+jqplot插件实现数据表行内插入线形图

Jquery easyui : 实现前端数据包格式化输出,支持多种模块式定义,只需要添加相应的预设参数即可实现丰富的前端. 资料参考: http://www.jeasyui.com/ Jquery sparkline: 基于jQuery 的js插件,底层调用html5的canvas标签,并通过js动态实现在数据表行内画条形图或趋势图,操作简单,可实现不同类型的图形化,如线形图,饼状图,柱形图. 资料参考:http://omnipotent.net/jquery.sparkline/#s-docs

php中的插件机制原理和实例

PHP中的插件机制原理和实例 投稿:junjie 字体:[增加 减小] 类型:转载 这篇文章主要介绍了PHP中的插件机制原理和实例,文中例子主要借鉴了网上一些网友的方式做了稍微的改造,需要的朋友可以参考下 PHP项目中很多用到插件的地方,更尤其是基础程序写成之后很多功能由第三方完善开发的时候,更能用到插件机制,现在说一下插件的实现.特点是无论你是否激活,都不影响主程序的运行,即使是删除也不会影响. 从一个插件安装到运行过程的角度来说,主要是三个步骤: 1.插件安装(把插件信息收集进行采集和记忆的

Delphi ActiveX Form的使用实例

Delphi ActiveX Form的使用实例 By knityster 1. ActiveX控件简介 ActiveX控件也就是一般所说的OCX控件,它是ActiveX技术的一部分. ActiveX控件可以被集成到很多支持ActiveX的应用当中去,或者直接用来扩展应用的功能,这些支持ActiveX的应用包括C++ Builder.Delphi.Visual dBASE. Visual Basic.Visual C++.Internet Explorer.Netscape Navigator等

主窗体里面打开子窗体&amp;&amp;打印饼图《Delphi 6数据库开发典型实例》--图表的绘制

\Delphi 6数据库开发典型实例\图表的绘制 1.在主窗体里面打开子窗体:ShowForm(Tfrm_Print); procedure Tfrm_Main.ShowForm(AFormClass:TFormClass);begin with AFormClass.Create(Self) do try ShowModal;  // 阻塞或者模态窗口,只有你把当前窗口关闭后,才能去操作父亲窗口. finally Free; end;end; //这个例子打开有异常,提示单元chart 引用本

H5实例教学--微信内嵌视频2(素材来自腾讯孙尚香末日机甲皮肤宣传H5)

结合之前的两篇解析 微信内嵌视频1(案例浅析)https://segmentfault.com/a/11...从AnimateCC到CreateJS入门https://segmentfault.com/a/11... 这次是一篇createjs完成UI 结合内联视频实现的一个demo 因为忘了原地址所以大家只能自己下demo跑一下简单的效果了 需要简单搭建一个服务器来跑不然createjs对图片资源引用 稍微解析一下总结实现思路 主要是由两个标签实现 video标签实现在手机端内嵌视频播放 ca