关于DLL事件模型的应用?(200分)

  • 主题发起人 主题发起人 bbscom
  • 开始时间 开始时间
B

bbscom

Unregistered / Unconfirmed
GUEST, unregistred user!
在开发过程中会使用很多同样的控件,这些控件有些事件触发的业务规则是一样的,如果把这些同规律的东西放到DLL里,然后让主程序从DLL里调用,可以达到同样的效果,这有益于开发和管理。不过如何将DLL里的事件让主程序调用后触发,请你帮助?
 
关注一下!我也对此感兴趣
 
用回调函数喽
 
很简单嘛,用回调函数,或者在DLL中导出一个函数赋给你的对象事件就可以了,不过要注意下,假如给一个对象添加一个不在类里面的方法,那么方法需要多一个TOBJECT类型的参数:
procedure (Obj: TObject;
Sender: TObject....);
 
坐下,,学习学习
 
朋友请详细,有小实例发到我的邮箱里:delphi2005@163.com
小实例:
procedure TForm1.Edit1KeyDown(Sender: TObject;
var Key: Word;
Shift: TShiftState);
begin
// 将这里代码移到DLL里,然后让EXE主程序调用DLL这个事件。
end;
我主要是想建立DLL事件模型库,方便维护或升级。回调函数在网上找的资料不够详细。
 
bahamut8348说的对
在Dll中声明好这个方法,然后在程序中加载,利用回调就可以实现
你可以看一下关于控件编写方面的代码,会找到你想要的答案
 
请大家谈DLL的事件模型问题。
 
在DLL做个这样的form,让主程序加载这个form,不就可以吗.
msn:longeremaq@hotmail.com
 
朋友请详细,有小实例发到我的邮箱里:delphi2005@163.com
我的小实例
1.1、在DLL里过程声明:
[red] procedure DLLDrawColumnCell(Sender: TObject;
const Rect: TRect;
DataCol: Integer;
Column: TColumnEh;
State: TGridDrawState);
Stdcall;[/red]
1.2、在DLL里过程实际业务处理:
[blue]procedure DLLDrawColumnCell(Sender: TObject;const Rect: TRect;
DataCol: Integer;
Column: TColumnEh;
State: TGridDrawState);
begin
if (Sender as TDBGridEh).DataSource.DataSet.RecNo mod 2 = 0 then
(Sender as TDBGridEh).Canvas.Brush.Color := $00FFF7EE;
(Sender as TDBGridEh).Canvas.Font.Color := clWindowText;
if gdSelected in State then
(Sender as TDBGridEh).Canvas.Brush.Color:=clYellow;
(Sender as TDBGridEh).DefaultDrawColumnCell(Rect, DataCol, Column, State);
end;
[/blue]
1.3、在DLL里输出Exports
DLLDrawColumnCell;
2.1、在EXE主程序中声明:
type
[red] TDLLDrawColumnCell = procedure(Sender: TObject;
const Rect: TRect;
DataCol: Integer;
Column: TColumnEh;
State: TGridDrawState);
Stdcall;[/red]
2.2、在DBGridEh1添加事件:
[blue]procedure TForm1.DBGridEh1DrawColumnCell(Sender: TObject;
const Rect: TRect;
DataCol: Integer;
Column: TColumnEh;
State: TGridDrawState);
var
LibHandle: THandle;
DLLDrawColumnCell: TDLLDrawColumnCell;
begin
LibHandle := LoadLibrary('../PubLib.dll');
if LibHandle = HINSTANCE_ERROR then
raise EDLLLoadError.Create('Unable to Load DLL');
@DLLDrawColumnCell := GetProcAddress(LibHandle, 'DLLDrawColumnCell');
if not (@DLLDrawColumnCell = nil) then
DLLDrawColumnCell(Sender,Rect,DataCol,Column,State);
end;
[/blue]当程序运行后出错,到底是哪里出现问题???
 
路过。。。帮顶
 
我的代码都粘出来了,请帮助修改呀。
DLL部份应该没有问题,关键是EXE主程序部份的声明或调用出现问题。
 
DLL里的部分:
Function IIWControl_ExecuteEx(command:Integer;p:Pointer):Boolean;export;stdcall;
proImageListRightMouseUp:procedure (FileName,LabelValue:string);stdcall;
//
Function IIWControl_ExecuteEx(command:Integer;p:Pointer):Boolean;
begin
proImageListRightMouseUp:=p;
end;
直接调用 proImageListRightMouseUp
//主程序部分
procedure ImageListRightMouseUp(FileName,LabelValue:string);stdcall;
//
IIWControl_ExecuteEx(0,@ImageListRightMouseUp);
 
康凌,你好!
我按你的意思测试一下.
 
如果只是为了加载执行一些公用的逻辑,是否可以考虑写公用的一个类,然后动态绑定到你需要替换使用的一些对象里面.这样方便以后遇到同样的其他需求时,再这个基础上进行扩展,或移植到其他项目当中去.
 
这种方法不可取,当系统大的时候或团队开发时,要安装太多的类。
 
以上的方法大部分情况回死锁,一般应该这样:
1.在dll中建立内存影射区放置事件变量地址
2.调用实践变量地址
千万不要直接调用Form的事件!
 
对于其它的事件模型已经解决,
但对于上面的实例请大家帮助,
查明原因。
 
我想,先更正一个说法,到目前为止,上面所说的全部内容,还没有涉及事件模型,这就是一个简单的函数调用。
其实,假如换一个编译器(比如 Delphi 2007),这个问题大概就没有。大致的原因与帖子:
http://www.delphibbs.com/delphibbs/dispq.asp?lid=3870571
上描述是一致的,都是由于 TCanvas 导致的。
3870571 帖子上说的方法还不够好,尝试以下方法:
1) 在 DLL 单元最下面的 begin
..end 之间加入 RegisterClasses(TCanvas, TDBGridEh, DataSource, TDataSet);
2) 在函数里重新定义一个 TCanvas 变量并创建它:
procedure DLLDrawColumnCell(Sender: TObject;
const Rect: TRect;
DataCol: Integer;
Column: TColumnEh;
State: TGridDrawState);
stdcall;
var
Canvas: TCanvas;
begin
Canvas := TCanvas.Create;
Canvas.Handle := (Sender as TDBGridEh).Canvas.Handle;
....
Canvas.Handle := 0;
Canvas.Free;
end;

不知道这样是否就可以了。
不管是好了还是没有最终解决,我反对这样粗糙的导出函数。我觉得这样的导出函数是没有意义的,要是这样导出,那还不如直接写在代码里面,或者用一个公共单元存放这些通用函数,什么毛病都没有。
既然考虑了 DLL 导出,最起码做到参数类型简单化,这种传递对象、传递复杂类型(甚至某些类型还是语言或者编译器版本相关的)的 DLL 函数,有导出的必要吗?请思考
 
后退
顶部