我想用插件开发GUI应用程序。插件包含VCL表单,这些表单继承自Plugin-Core库中的Base Forms。主应用程序可以选择动态加载哪个插件,然后选择要显示的Form子类。
在用户方面,我想为不同的模型部署主 .EXE ,Plugin-Core库和许多插件库。我可以向用户发布新的或修改现有的插件库,以便在不修改主 .EXE 和插件核心库的情况下为新设备显示新的表单。
我开发的第一个版本使用DLL方法,即Plugin-Core库和插件都是DLL形式。在用户方面一切都很好。但是,在开发人员方面,如果没有Plugin-Core DLL项目中定义的Base Forms,则无法链接插件DLL项目。这意味着Base Forms实际上是静态链接在每个插件DLL项目中,如果有一天我修改了Base Forms并重建了Plugin-Core DLL项目,我必须重建所有插件DLL项目并重新发布插件 < em> .DLL 也是用户。
在StackOverflow中搜索并询问之后,我意识到VCL Forms不能跨DLL边界继承的限制是由于RTTI冲突(?)。建议的解决方案是将库从DLL修改为BPL格式,这是我开发的第二个版本。一切都很好,除了以下两个:
插件BPL中的动态加载表单与Windows任务栏中的主 .EXE 分开。这不是我想要的。解决方案是我在 .EXE 项目中启用了“使用运行时包构建”。
在 .EXE 项目中启用“使用运行时包构建”后,我必须向用户发布其他.BPL,例如 vcl.bpl 和 rtl.bpl 。这不是我想要的完美。
我想知道上述两个问题可以同时解决吗?在我的想法中,如果我:
,我可以解决这两个问题通过这种方式, .EXE 可以在没有 vcl.bpl 和 rtl.bpl ,并且插件 .BPL 可以成功加载,因为依赖单元已经是主 .EXE ?我对么?但是,在所有 .BPL 项目选项中禁用了“使用运行时包构建”复选框。因此,我没有机会检查解决方案是否有效。对于冗长的描述我很抱歉,由于公司的互联网安全政策,我无法附上图片。
答案 0 :(得分:1)
插件BPL中的动态加载表单与Windows任务栏中的主.EXE分开。这不是我想要的。解决方案是我在.EXE项目中启用了“使用运行时包构建”。
加载BPL后,将EXE的Application.Handle
传递给BPL,并在创建任何Form实例之前将其分配给BPL自己的Application.Handle
。
或者,在Windows 7+上,您可以让EXE调用SetCurrentProcessExplicitAppUserModelID()
为其任务栏按钮建立应用ID。然后,BPL中的每个表单都可以使用SHGetPropertyStoreForWindow()
和IPropertyStore.SetValue(PKEY_AppUserModel_ID)
为其窗口设置相同的App ID。具有相同App ID的多个窗口在一个任务栏按钮下组合在一起。
有关详细信息,请参阅MSDN:Application User Model IDs (AppUserModelIDs)
我想知道上述两个问题可以同时解决吗?在我的想法中,如果我:
,我可以解决这两个问题
在.EXE项目中禁用“使用运行时包构建”。
- 醇>
在所有.BPL项目中启用“使用运行时包构建”。
通过这种方式,.EXE可以在没有捆绑vcl.bpl和rtl.bpl的情况下运行,并且插件.BPL可以成功加载,因为依赖单元已经是主.EXE的一部分了?我是对的吗?
没有。 BPL不能像这样使用EXE的内置单元。
如果禁用“使用运行时软件包构建”,则RTL / VCL单元将静态链接到可执行文件中。这样做的问题是给定单元的多个副本不能同时加载到内存中,因此如果相同的RTL / VCL单元静态链接,您将无法将多个BPL加载到一起(甚至根本不加载)多个BPL,甚至是EXE本身。
如果启用“使用运行时软件包构建”,则可执行文件将依赖于RTL / VCL BPL,然后必须部署这些文件。
因此,如果您的EXE和BPL共享公共单位,那么必须的单位必须通过共享BPL加载,因此内存中只存在一个单位副本。编写自定义BPL时无法避免。这意味着在 minimum ,如果您使用的是基本的RTL功能,则通常需要部署RTL.BPL,而使用VCL.BPL则需要部署。