请教高手:动态载入DLL插件自动增加菜单的问题!!(150分)

  • 主题发起人 主题发起人 snowsky
  • 开始时间 开始时间
S

snowsky

Unregistered / Unconfirmed
GUEST, unregistred user!
DLL源代码如下:
--------------------Test2.dpr------------------------------
library Test2;
uses
ShareMem, SysUtils, Classes,
Unit1 in 'Unit1.pas' {Form1};

{$R *.res}
exports
AddTest2;
begin
end.

----------Unit.pas--------------------
unit Unit1;

interface

uses
ShareMem,Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs,Menus;

type
TForm1 = class(TForm)
private
{ Private declarations }
public
{ Public declarations }
end;

Type
TH = class
Public
Procedure Click(Sender:TObject);
end;

Function AddTest2(ParentMenu:TMenuItem):TMenuItem;export;stdcall;

var
Form1: TForm1;
H: TH;

implementation

{$R *.dfm}

Function AddTest2(ParentMenu:TMenuItem):TMenuItem;
var Menu:TMenuItem;
begin
Menu:=TMenuItem.Create(ParentMenu);
//Menu:=NewItem('测试二',scNone,false,true,H.Click,0,'mTest1');
Menu.Caption:='新测试二';
Menu.Name:='mTest2';
Menu.OnClick:=H.Click;
Menu.Hint:='222';
Result:=Menu;
end;

Procedure TH.Click(Sender:TObject);
begin
ShowMessage('测试二');
end;

initialization
H:=TH.Create;
finalization
H.Free;

end.


---------------------主程序如下-------------------------------
Procedure TForm1.LoadDll(Const FileName:String);
var LibHandle:integer;
PlugProc:TPlugInProc;
str:string;
Menu:TMenuItem;
begin
str:=ExtractFileName(FileName);
str:=Copy(str,1,Length(str)-4);
str:='Add'+str;
LibHandle:=LoadLibrary(PChar(Filename));
if LibHandle<>0 then
begin
PlugProc:=GetProcAddress(LibHandle,PChar(str));
if Assigned(PlugProc)then
begin
Menu:=TMenuItem.Create(Application);
Menu.OnClick:=Hol.Click;
Menu:=PlugProc(n111);
N111.Add(Menu);
end;
end;
end;

问题是:加载一个DLL插件时一切正常,会在主菜单中正常添加一个子菜单,也可以正常
执行DLL中的点击事件,但如果DLL插件为二个时,主菜单也会正常添加二个子菜单,且
Caption也正常,只是点击任意一个子菜单都只会响应第一个子菜单的点击事件。

请高手指点,我已经查过DFW上的几乎所有资料,那个开始用PHOTOSHOP举例的文章就请不要
贴到这了。
 
你把所有的子菜单的onclick都指向同一个处理函数,当然是执行同样的操作.
一般的做法都是把这个功能模板的所有操作都放在dll中.比如每个模板dll都有
统一名字的[取菜单caption, hint等信息的导出函数,onclick事件执行的导出函数等]
 
可是我事先并不知道有哪些插件,我不可能在主程序里面定义菜单的点击事件?

还有:在DLL中定义的onClick指向的难道不是它自己的onClick事件吗?难道不同的DLL指向
的onClick事件会一样吗?能给我举一个例子吗?

谢谢您的回答
 
各位老大,帮个忙呀。我已经折腾了好几天了。
 
有哪些插件:
这个你随便想个法都行,比如将所有插件dll放在指定目录,然后程序启动时搜索dll并逐个
载入.或者在程序中做一个导入插件的功能,将插件dll的文件名及其他信息写入ini或注册
表.....

菜单的onclick事件
onclick必须指向一个of object的函数地址.而dll的导出函数都是普通函数.所以你要
动点脑筋.
一种办法如下:[这有一个我写的函数
procedure SetEvenToProc(Sender:TObject;evenname:string;e:Pointer);
var
//将vcl对象的事件指向一个普通函数指针.
m:TMethod;
begin
m.Code:=e;
m.Data:=Sender;
try
typinfo.SetMethodProp(Sender,evenname,m);
except
end;
end;
{使用方法
procedure FormCloseQuery(Self,Sender: TObject; var CanClose: Boolean);
begin
if Sender<>nil then
begin
Showmess(TForm(Sender).Caption);
CanClose:=true;
end;
end;
SetEvenToProc(Self,'OnCloseQuery',@FormCloseQuery);
}
另外一种办法是普通一点,也可靠一点.定义一个TList,保存从各个dll中得到的函数指针,
然后做一个of object的函数,在这个函数中根据传入的参数(比如Caption,index)执行相应
的函数就可以了.我想你也不用我说得更详细吧.

 
谢谢您,我已经搞定了.
 
接受答案了.
 
后退
顶部