读书人

关于类成员函数转 Windows 回调函数,该

发布时间: 2012-02-19 19:43:38 作者: rapoo

关于类成员函数转 Windows 回调函数
百度到关于类成员函数的代码如下:
unit ClassCallback;

interface

type
TCallbackInstance = array [1..18] of Byte;
PInteger=^Integer;
procedure MakeCallbackInstance(var Instance: TCallbackInstance;
ObjectAddr: Pointer; FunctionAddr: Pointer);

implementation

{----------------------------}
{ CallbackCode DASM }
{----------------------------}
{ MOV EAX, [ESP]; }
{ PUSH EAX; } //<========呵呵,这就是壳的汇编码哦
{ MOV EAX, ObjectAddr; }
{ MOV [ESP+4], EAX; }
{ JMP FunctionAddr; }
{----------------------------}
procedure MakeCallbackInstance(var Instance: TCallbackInstance;
ObjectAddr: Pointer; FunctionAddr: Pointer);
const CallbackCode: TCallbackInstance =
($8B,$04,$24,$50,$B8,$00,$00,$00,$00,$89,$44,$24,$04,$E9,$00,$00,$00,$00);
begin
Move(CallbackCode, Instance, SizeOf(TCallbackInstance));
PInteger(@Instance[6])^ := Integer(ObjectAddr);
PInteger(@Instance[15])^ := Integer(Integer(FunctionAddr) - Integer(@Instance) - 18);
end;
end.

调用过程:
MakeCallbackInstance(FCallbackInstance, Self, @TTest.MsgProc);
OldWndProc := Pointer(GetWindowLong(AWindow.Handle, GWL_WNDPROC));
SetWindowLong(AWindow.Handle, GWL_WNDPROC, Longint(@FCallbackInstance));
注:以上是用delphi5写的activeform控件里的代码。

问题:
生成的ocx在winxp下正常使用,在win2003server上ie出错:“address.....”,这是什么原因?怎样解决?




[解决办法]
呵呵。。winxp下正常使用而在win2003server上ie出错:“address.....”,
我有遇到过。我当时是这样处理的:在WIN2003我的电脑-属性-高级-性能(数据执行保护)里,添加你的应用程序就可以正常执行了。。
[解决办法]
这是一个完整的单元:
01 unit CallBackToMethod;
02
03 {*******************************************
04 * brief: 回调函数转对象方法的实现
05 * autor: linzhenqun
06 * date: 2006-12-18
07 * email: linzhengqun@163.com
08 ********************************************}
09 {
10 说明:本单元的实现方法是一种比较安全的方式,其中不破坏任何寄存器的值,并且
11 指令的大小只有16字节。
12 使用:下面是推荐的使用方法
13 1. 在类中保存一个指针成员 P: Pointer
14 2. 在类的构造函数中创建指令块:
15 var
16 M: TMethod;
17 begin
18 M.Code := @MyMethod;
19 M.Data := Self;
20 P := MakeInstruction(M);
21 end;
22 3. 调用需要回调函数的API时,直接传进P即可,如:
23 HHK := SetWindowsHookEx(WH_KEYBOARD, P, HInstance, 0);
24 4. 在类的析构函数中释放指令块
25 FreeInstruction(P);
26 注意:作为回调函数的对象方法必须是StdCall调用规则
27 }
28
29 interface
30
31 (* 创建回调函数转对象方法的指令块 *)
32 function MakeInstruction(Method: TMethod): Pointer;
33 (* 消毁指令块 *)
34 procedure FreeInstruction(P: Pointer);
35
36 implementation
37
38 uses SysUtils;
39
40 type
41 {
42 指令块中的内容相当于下面的汇编代码:
43 ----------------------------------
44 push [ESP]
45 mov [ESP+4], ObjectAddr
46 jmp MethodAddr
47 ----------------------------------
48 }
49 PInstruction = ^TInstruction;
50 TInstruction = packed record
51 Code1: array [0..6] of byte;
52 Self: Pointer;
53 Code2: byte;
54 Method: Pointer;
55 end;
56
57 function MakeInstruction(Method: TMethod): Pointer;
58 const
59 Code: array[0..15] of byte =
60 ($FF,$34,$24,$C7,$44,$24,$04,$00,$00,$00,$00,$E9,$00,$00,$00,$00);
61 var
62 P: PInstruction;
63 begin
64 New(P);
65 Move(Code, P^, SizeOf(Code));


66 P^.Self := Method.Data;
67 P^.Method := Pointer(Longint(Method.Code)-(Longint(P)+SizeOf(Code)));
68 Result := P;
69 end;
70
71 procedure FreeInstruction(P: Pointer);
72 begin
73 Dispose(P);
74 end;
75
76 end.

这里有更详细的描述:
http://blog.csdn.net/linzhengqun/archive/2006/12/20/1451088.aspx

但不知在2003下有没有问题,没有试过。

读书人网 >.NET

热点推荐