在 Delphi 中动态使用包(dpk)实现项目模块化的问题 (100分)

  • 主题发起人 主题发起人 Ourland
  • 开始时间 开始时间
O

Ourland

Unregistered / Unconfirmed
GUEST, unregistred user!
我已经用动态调用包的形式做了一个系统,程序发布时遇到一个问题:
当不是把所有 BPL 文件给用户的情况下,主程序启动时会报错(无法找到动态连接库)。
我的想法是:能否只在调用这个包的时候(而不是主程序启动时)才报这个错呢?
 
在运行时装载就可以了,也就是动态装载
请参看 LoadPackage和UnloadPackage等Delphi函数
 
再给你一点示例代码
procedure TForm1.BtnChangeClick(Sender: TObject);
var
FormScroll: TForm;
FormClass: TFormClass;
HandlePack: HModule;
begin
// try to load the package
HandlePack := LoadPackage ('PackWithForm.bpl');
if HandlePack > 0 then
begin
FormClass := TFormClass(GetClass ('TFormScroll'));
if Assigned (FormClass) then
begin
FormScroll := FormClass.Create (Application);
try
// initialize the data
SetPropValue (FormScroll, 'SelectedColor', Color);
// show the form
if FormScroll.ShowModal = mrOK then
Color := GetPropValue (FormScroll, 'SelectedColor');
finally
FormScroll.Free;
end;
end
else
ShowMessage ('Form class not found');
UnloadPackage (HandlePack);
end
else
ShowMessage ('Package not found');
end;
 
哈哈,给分吧
 
不是吧 呵呵 来迟了
程序在启动的时候的确如此,我也给你一段代码
phm:=LoadPackage(spkg);
if phm<>0 then
try
frmparm.TITLE:=adoquery.fieldbyname('chuangkbt').asstring+adoquery.fieldbyname('chuangkid').asstring;
frmparm.TAG:=adoquery.fieldbyname('chuangkbq').asinteger;
{ frmparm.x:=adoquery.fieldbyname('chuangkhzb').asinteger;
frmparm.y:=adoquery.fieldbyname('chuangkzzb').asinteger;
frmparm.width:=adoquery.fieldbyname('chuangkkd').asinteger;
frmparm.height:=adoquery.fieldbyname('chuangkgd').asinteger;}
if adoquery.FieldByName('shifzdh').asstring='1' then
frmparm.WindowState:=wsMaximized;
frmparm.formname:=adoquery.fieldbyname('chuangklm').asstring;
frmparm.wparam:=adoquery.fieldbyname('chuangkcs').asstring;
frmparm.PGSYS:=gsys;
frmparm.parentform:=application.MainForm;
 
别为的代码,你看一下吧
procedure Tmainfrm.loadpkbyname(pkname:string);
var
pkobject:THandle;
CreateNewObject:TCreateNewObject;
begin
pkname:='PKlib/'+pkname;
// package dir
pkobject:=Loadpackage(pkname);
@CreateNewObject:=GetprocAddress(pkobject,'CreateObject');
if integer(@CreateNewObject)<0 then
application.messagebox('包加载失败!','Load Package',48)
else
createnewobject;
end;

2.动态释放Package比较麻烦,这里是李维的一个例子,应该可以:
procedure UnLoadAddInPackage(Module: THandle);
var
i: Integer;
M: TMemoryBasicInformation;
begin
{ Make sure there aren't any instances of any of the classes from Module
instantiated, if so then
free them. (this assumes that the classes are
owned by the application) }
for i := Application.ComponentCount - 1do
wnto 0do
begin
VirtualQuery(GetClass(Application.Components.ClassName), M, SizeOf(M));
if (Module = 0) or (HMODULE(M.AllocationBase) = Module) then
begin
ShowMessage(Application.Components.ClassName);
Application.Components.Free;
end;
end;
UnRegisterModuleClasses(Module);
UnLoadPackage(Module);
end;
 
诸位:
  我情况是这样的,我在主程序的选项的包那页选定了"Build with runtime Packages",在编辑框中输入了我要引用的包文件,这样我的主程序的大小不到30K,但就是在主程序启动时,要是缺少某个包文件,就报找不到动态连接库,我想问的是如何在主程序运行前捕捉到这个错误。
  各位的做法好象没有这样处理,结果,主程序的大小比较大。而且上述所列方法我都知道!
 
----在编辑框中输入了我要引用的包文件
你不要在编辑框中输入要引用的包文件,而是用上面很多人介绍的LoadPackage方法,程序启动时就不会报错,而是在执行LoadPackage时才报错。
 
那象我那种方法出现的问题,有没有解决方案呢?
 
我看没有什么方法,要不你有耐心去找你到底缺了什么,要不只好不带包编译,大点儿就大点吧,我也碰到过这个问题
 
后退
顶部