我现在在看以前的一个老程序,除了主界面外,全部都是动态加载包,调用里面的窗体。主程序中菜单项对应的窗体类,是从数据库表中得到的,当我点击菜单时,首先判断这个窗体类是不是已经存在,如果不存在,则加载这个窗体类对应的包(包和窗体类的对应关系也是存储在数据库表中),然后在获得这个窗体类,在显示这个窗体。菜单对应窗体类,没办法,只能手工加入到数据库表中。
包和窗体类的对应,是通过一个exe文件执行的,而这个exe文件,则没有源代码。但执行效果可以看得到。当选择了一个bpl文件后,列表框中显示这个包中有哪些窗体类。我现在就比较困惑,这个功能是怎么实现的。
因为我查找了很多资料,说如果要超找包中的类,必须首先要对类进行注册,执行诸如下面的代码:
initialization
  RegisterClass(TForm2);
finalization
  UnRegisterClass(TForm2);
才能用FindClass或者GetClass根据类名得到相应的类。procedure TForm1.Button1Click(Sender: TObject);
var
  PackageModule : HModule;
  AClass : TPersistentClass;
begin
  PackageModule := LoadPackage('Package1.bpl');
  if PackageModule <> 0 then
  begin
    //AClass := GetClass('TForm2');
    AClass := FindClass('TForm2');
    if AClass <> nil then
      with TComponentClass(AClass).Create(Application) as TCustomForm do
      begin
        ShowModal;
        Free;
      end;  
    UnLoadPackage(PackageModule);
  end;
end;
以上代码测试过,如果注释掉Form2中的那4行代码,以上代码根本无法找到TForm2。
而以前老程序留下的包中的窗体的源代码,根本就没有关于注册的那部分代码,
那他是如何得到bpl中的窗体类呢?

解决方案 »

  1.   

    创建窗体肯定是在bpl中实现的,那也就不需要注册了啊~把主窗体的Application作为参数传递给bpl,然后在bpl中直接
    Application.CreateForm(窗体类, 窗体名);就可以了
      

  2.   

    谢谢楼上的,这个我知道。
    我想知道的是,给你一个bpl文件,如何得到这个文件中包含的窗体类。而这个bpl中窗体中的pas文件中,没有类似如下的代码:
    initialization 
      RegisterClass(TForm2); 
    finalization 
      UnRegisterClass(TForm2); 
      

  3.   

    这方面问题我比较清楚,最近在做一个关于这方面的项目。initialization 
      RegisterClass(TForm2); 
    finalization 
      UnRegisterClass(TForm2);
    以上代码是放在你的BPL里的,使用loadpackage('Package1.bpl')函数的时候,会自动执行
    Package1这个BPL中的
    initialization 
      RegisterClass(TForm2);在调用unloadpackage('Package1.bpl')函数时会执行BPL中的
    finalization 
      UnRegisterClass(TForm2);用兴趣的话你可以看一下RegisterClass()函数和UnregisterClass()的源代码。另外注意在build的时候要把option里的勾打上,这样才能够动态的加载。
      

  4.   

    to  netfirstman 
    bpl文件是编译后生成的吧,而关于注册代码,是写到pas文件里的吧?
      

  5.   

    嗯,要回答這個問題,先説明一下delphi自帶的RegisterClass和UnRegisterClass。這個有別于windows自帶的窗體類註冊用api-registerclass,UnRegisterClass。以RegisterClass為例,delphi自帶的RegisterClass,目的是記錄類信息,放到delphi的一個全局list裏面,可供調用者查詢。那麽當我們在loadpackage或者loadlibrary時,其實delphi的流機制已經幫我們註冊了窗口類,我們就不需要再顯式地去調用api註冊窗口。之所以在包模式下編程時,需要調用delphi自帶的RegisterClass,是為了能夠正確執行裏面的代碼。根據你的情況,你的程序必定是用自己list或者類似d方式來記錄類信息。