dll mdi

原创 2007年09月22日 17:55:00
   很多人认为,在Delphi的DLL中加载MDI子窗体时,需要注意保存并恢复Delphi全局变量(Application和Screen)对象。其实,根本没有办法在DLL中加载MDI子窗体。

原文出处:http://delphi.about.com/library/weekly/aa020805a.htm

    在开发复杂的应用系统时,把系统分为各个模块分而制之是一种很平常的策略,这样就可以使得每个模块负责一套业务逻辑。模块可以是一个DLL,在需要的时候,主程序可以调用这个DLL以使用该模块。
    当你开发一个MDI应用程序,并希望把该应用程序分割成各个模块时,自然会有这样的疑问:“如何将MDI子窗体创建在DLL中,以使得在必要的时候能够被主程序调用?”
    如果你已经知道如何在DLL中创建非MDI子窗体的窗体,并且也知道如何从主程序调用这个DLL中的窗体时,你或许会认为问题已经得到了解决,但事实并非如此。
    如何让DLL中的MDI子窗体得知哪个窗体是它的父窗体(以便让其能够以子窗体的形式展现出来)?用于创建该子窗体的Application对象(位于父窗体所在的应用程序中)与你在DLL中获得的Application对象根本就是两回事情,不仅如此,两者的Screen对象也不相同。
 
想要在DLL中保存并创建MDI子窗体?没门!
    就如你所看到的这个标题所说的一样,根本就没有办法在DLL中保存并创建MDI子窗体,然后让MDI应用程序去调用它。或者你会说,你已经在网上找到一些资料,上面显示如何保存并传递Application对象,以使得DLL中的MDI子窗体能够被创建于正确的MDI父窗体中,其实这种做法并不奏效,至少在Delphi 5以上的版本中不会奏效。
 
那么解决方案是什么呢?
    如果你非要在DLL中保存并创建MDI子窗体,那么你需要在主程序(MDI应用程序)和DLL生成的时候,与运行时包(runtime package)一起生成。这样做就确保了主程序和DLL使用了共同的Application和Screen对象,并使用了相同的RTL与VCL实例。为了100%确保“安全”,你应该使用包,而不是DLL。
 
包中的MDI子窗体:唯一正确的解决方案
    Delphi的包是一种特殊的DLL,它仅用于Delphi的应用程序。如果你的应用程序模块是使用包的形式开发而不是DLL,那么所有的模块都会共享同一个内存管理机制,包括了VCL全局对象(例如Application和Screen)以及RTL与VCL在内存中的同一代码拷贝。
 
包中的MDI子窗体:实例
    现在来看一个实例,首先,我们将创建一个MDI应用程序:
1、 创建一个新的MDI应用程序。你可以使用MDI应用程序创建向导(File - New - Other - Projects - MDI Application)
2、 确保主窗体的FormStyle属性已经设置为fsMDIForm
3、 添加一个MainMenu控件,使其只有一个用于从包中加载子窗体的菜单项
4、 确保在生成应用程序的时候,是和运行时包一起生成的。在Project – Options菜单中,选择Packages选项卡,然后选中“Build with run-time packages”选项。你至少要选中rtl包和vcl包
在真正编码前,首先生成该包,并且向其添加一个MDI子窗体
1、 创建一个新的运行时包
2、 向包添加一个TForm对象,确保该对象的FormStyle属性已经设置为fsMDIChild
3、 添加一个导出过程,用于创建子窗体的实例:
procedure TPackageMDIChildForm.FormClose
 (Sender: TObject; 
   var Action: TCloseAction);
begin
 //since this is an MDI child, make sure 
  //it gets closed when the user 
  //clicks the x button.
 Action := caFree;
end;
 
procedure ExecuteChild;
begin
 TPackageMDIChildForm.Create(Application);
end;
 
exports
 //NOTE!! The export name 
  //is CASE SENSITIVE
 ExecuteChild;
 
end.
 
    重新回到MDI主程序,以下是MDI主窗体的所有代码:
type
 //signature of the "ExecuteChild"
 //procedure from the Package
 TExecuteChild = procedure;
 
 TMainForm = class(TForm)
   ...
 private
    PackageModule : HModule;
    ExecuteChild : TExecuteChild;
    procedure PackageLoad;
 end;
 
var
 MainForm: TMainForm;
 
implementation
{$R *.dfm}
 
procedure TMainForm.PackageLoad;
begin
 //try loading the package
 //(let's presume it's in the same
 //folder, where the main app. exe is)
 PackageModule := LoadPackage('MDIPackage.bpl');
 
 //if loaded, try locating
 //the ExecuteChild procedure
 if PackageModule <> 0 then
 try
    @ExecuteChild := GetProcAddress(PackageModule,
                                    'ExecuteChild');
 except
    //display an error message if we fail
    ShowMessage ('Package not found');
 end;
end;
 
//menu click
procedure TMainForm.mnuCallFromDLLClick
(Sender: TObject);
begin
 //lazzy load package
 if PackageModule = 0 then PackageLoad;
 
 //if the ExecuteChild procedure
 //was found in the package, call it
 if Assigned(ExecuteChild) then ExecuteChild;
end;
 
procedure TMainForm.FormDestroy(Sender: TObject);
begin
 //if the package was loaded,
 //make sure to free the resources
 if PackageModule <> 0 then
    UnloadPackage(PackageModule);
end;
 
    上面的代码中,选中菜单项时,主程序动态地加载了所需的包(使用PackageLoad过程),并且在应用程序终止的时候卸载了已经加载的包。最后,在运行时,我们得到了一个能够正确加载并运行包中MDI子窗体的应用程序。
    最后需要说明的是,在使用runtime package模块化应用程序时,你必须将所需的包与应用程序的exe文件一起发布。 

用AlphaControls皮肤控件来美化用Dll制作的MDI子窗体程序

AlphaControls控件是目前效果比较好的皮肤控件,专业和细致。 有朋友咨询用Dll制作的MDI子窗体程序被调用后,没有被美化,如何处理? 其实即使正常的窗体被放在dll中,再用主程序来调用...
  • wozengcong
  • wozengcong
  • 2014年01月03日 15:58
  • 1626

C# SetParent将其他程序嵌入自己的程序

模块化的开发,将模块合并到一起的时候,遇到了Mdi不能添加到其它窗口下的问题。 分两种情况: 将mdi窗口A设成普通窗口B的子控件,需要将A的TopLevel设置成false,但是Mdi窗口的To...
  • xtfnpgy
  • xtfnpgy
  • 2014年07月13日 17:33
  • 3154

MFC中MDI方式下如何自由生成自定义的子窗口

本文介绍如何删除由MFC AppWinzard工程中产生的文档/视图结构,同时根据自己的实际需要创建子窗口界面。 Visual C++ 开发系统中应用程序向导的标准设置允许应用程序开发者方便简单...
  • dearm23
  • dearm23
  • 2015年10月28日 23:54
  • 1256

Delphi封装Mdi窗体到Dll并使用插件管理,tabControl制作多页面

源码下载地址 1.ShareMem的引用要放在各单元的第一位置,否则会报错 2.dll中mdi子窗体关闭时要,      Action:=caFree;     TestForm2...
  • spd260
  • spd260
  • 2013年01月27日 16:00
  • 2236

delphi的DLL封装MDI子窗体

转自http://www.cnblogs.com/kfarvid/archive/2010/06/23/1763753.html 前天遇到一个疑问:主窗体是fsMDIForm时,调用DLL的窗体不可...
  • aTian2009
  • aTian2009
  • 2012年04月23日 09:31
  • 2564

C++ Builde 2010 MDI 调用 DLL 子窗体

MDI 封装DLL 子窗体,要注意的问题:   1) 传递
  • artsmart
  • artsmart
  • 2014年11月13日 15:06
  • 424

VC++MDI框架的dll简单源码

  • 2011年02月14日 10:59
  • 32KB
  • 下载

用dll实现MDI窗口

  • 2012年04月28日 10:00
  • 351KB
  • 下载

C++ Builder MDI 调用 DLL 子窗体(基于 BCB2010)

  • 2014年11月13日 15:33
  • 26KB
  • 下载

Dll Form MDI 的TAB问题的解决方法!

  • 2006年02月23日 09:05
  • 516KB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:dll mdi
举报原因:
原因补充:

(最多只允许输入30个字)