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(, , 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 := to PageControl1.PageCount - 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,多实例内嵌窗口服务的更多相关文章
- 013.Delphi插件之QPlugins,模块化代码示例
这个DEMO的是一个定义了一个窗体插件接口,把其他窗口注册到这个窗体插件接口中.主程序运行起来,就遍历一下窗体插件接口,把每个窗体内嵌到对话框中 运行效果如下 主窗口代码如下 unit Frm_Mai ...
- 015.Delphi插件之QPlugins,FMX插件窗口
内嵌FMX的插件窗口,效果还是很可以的.退出时,会报错,很诡异啊. 主窗口代码如下 unit Frm_Main; interface uses Winapi.Windows, Winapi.Messa ...
- 004.Delphi插件之QPlugins,参数传递
界面如下 插件框架中大量使用了接口的东西,看的眼花缭乱,很多地方只做了申明,具体的实现是在另外的子类. DLL的代码如下 unit ParamTest; interface uses classes, ...
- WPF内嵌WCF服务对外提供接口
要测试本帖子代码请记得管理员权限运行vs. 我写这个帖子的初衷是在我做surface小车的时候有类似的需求,感觉这个功能还挺有意思的,所以就分享给大家,网上有很多关于wcf的文章 我就不一一列举了.公 ...
- 014.Delphi插件之QPlugins,MDI窗口
不知道为什么,这个DEMO编译出来报错,运行不了,在QDAC群里问了一下也没人响应. 效果如下 主程序代码如下 unit Frm_Main; interface uses Winapi.Windows ...
- 011.Delphi插件之QPlugins,延时加载服务
这个DEMO是是把DLL插件的相关信息做成了一个配置文件,主程序加载这个配置文件,从而起到延时加载的作用 主程序代码如下 unit Frm_Main; interface uses Winapi.Wi ...
- 010.Delphi插件之QPlugins,遍历服务接口
这个DEMO注意是用来看一个DLL所拥有的全部服务接口 演示效果如下 代码如下: unit Frm_Main; interface uses Winapi.Windows, Winapi.Messag ...
- 009.Delphi插件之QPlugins,服务的热插拔
这个DEMO用来演示服务的替换,用起来总是怪怪的感觉,效果图如下 代码如下 unit Frm_Main; interface uses Winapi.Windows, Winapi.Messages, ...
- 007.Delphi插件之QPlugins,插件的卸载和重新加载
效果图如下,可以反复卸载和重新加载.QPlugins这个插件,还没弄明白,摸索着跟着DEMO写 主窗口代码如下 unit Frm_Main; interface uses Winapi.Windows ...
随机推荐
- 关于ubuntu挂载ntfs无法进行读写的解决方法
查看挂载信息 df -h 参看要挂载磁盘UUID sudo blkid 编辑/etc/fstab文件: sudo vim /etc/fstab 在最后一行添加如下一行信息: UUID=A248CF46 ...
- MySQL之约束
目录 约束(CONSTRAINT) mysql中的约束有哪些? 级联操作 产生的原因: 两种级联的定义方式 约束(CONSTRAINT) 什么是约束? 是一种限制,对某一个东西的限制.例如宪法规定 ...
- WPS 2019文档编辑 技巧
wps2019文档怎么设置粘贴时自动匹配当前的格式: 菜单栏 文件 -- 选项 -- 编辑 -- 默认粘贴方式 设置为 匹配当前格式. 在编辑文档左侧或右侧显示/隐藏 目录/书签: 视图 -- 导航窗 ...
- SpringBoot Controller找不到视图路径
在启动类加注解@ComponentScan("com.controller")即可,括号里表示Controller所在包名. 参考:https://blog.csdn.net/ji ...
- warning no match for this type name: entity.User [Xlint:invalidAbsoluteTypeName]
这个bug是由于在spring的配置文件中的错误 这是由于上述中的 这一句中的这里的类名的引用错了,我的正确类名引用是 所以只要将包引用的包名修改为User类的完全限定名就可以了
- Java 实现简单的人机猜拳游戏
import java.util.Scanner; import java.util.Random; public class TestGuess{ public static void main(S ...
- VMware安装CentOS操作系统详细步骤
目录 创建虚拟机(买电脑) 1. 创建新虚拟机 2. 自定义配置虚拟机 3. 选择虚拟机硬件兼容性 4. 安装虚拟机创建系统 5. 选择虚拟机操作系统 6. 设置虚拟机名字和存放位置 7. 设置虚拟机 ...
- 【转载】如何快速转载CSDN中的博客
前言 对于喜欢逛CSDN的人来说,看别人的博客确实能够对自己有不小的提高,有时候看到特别好的博客想转载下载,但是不能一个字一个字的敲了,这时候我们就想快速转载别人的博客,把别人的博客移到自己的空间 ...
- 新闻网大数据实时分析可视化系统项目——7、Kafka分布式集群部署
Kafka是由LinkedIn开发的一个分布式的消息系统,使用Scala编写,它以可水平扩展和高吞吐率而被广泛使用.目前越来越多的开源分布式处理系统如Cloudera.Apache Storm.Spa ...
- java虚拟机之内存分配
Java 的自动内存管理主要是针对对象内存的回收和对象内存的分配.同时,Java 自动内存管理最核心的功能是 堆 内存中对象的分配与回收. JDK1.8之前的堆内存示意图: 从上图可以看出堆内存分为新 ...