求教Delphi事件机制,如果将Windows消息转换为Delphi的事件? (100分)

  • 主题发起人 主题发起人 NoSwing
  • 开始时间 开始时间
N

NoSwing

Unregistered / Unconfirmed
GUEST, unregistred user!
我想弄明白,Window消息如何成为Delphi事件的!出价100分,要详细的,而且不要给我指定看什么书,
别想蒙我,我都追到源代码的超汇编代码了,就是将机器指令写的整数数组里,再强制转换成函数.
谢谢.
 
如果了解Window消息机制,理解Delphi事件就好多啦
 
hehe,不会追这么远吧。
windows的消息在delphi中处理顺序依次为:wndproc,messagemap和defaultmap.
在消息处理函数中调用事件处理函数就得了。
比如你定义了一个消息,WM_MyMessage;其处理函数为HandleMyMessage,驱动的事件为
MyMessageEvent,对就的内部变量为FMyMessageEvent.
再HandleMyMessage的形式必如:
procedure HandleMyMessage(var Message);
begin
; ..........
; if Assigned(FMyMessageEvent) then FMyMessageEvent;
end;

hehe
 
真的没人回答吗?
 
我好失望啊,居然没人回答!我只是想找一个可以值得给分的人啊!
 
给你一个例子(给TSpeedButton添加OnMouseEnter和OnMouseLeave事件)
unit EnhSpeedButton;
interface
uses
; Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
; Buttons;
type
; TEnhSpeedButton = class(TSpeedButton)
; private
; ; FOnMouseEnter: TNotifyEvent; //Make the Mouse Enter and Leave available
; ; FOnMouseLeave: TNotifyEvent;
; ; procedure CMMouseEnter(var Message: TMessage); message CM_MOUSEENTER;
; ; procedure CMMouseLeave(var Message: TMessage); message CM_MOUSELEAVE;
; ; { Private declarations }
; protected
; ; { Protected declarations }
; public
; ; procedure Click; override;
; ; { Public declarations }
; published
; ; property OnMouseEnter: TNotifyEvent read FOnMouseEnter write FOnMouseEnter; //These show up in events
; ; property OnMouseLeave: TNotifyEvent read FOnMouseLeave write FOnMouseLeave;
; ; { Published declarations }
; end;

procedure Register;

implementation

procedure Register;
begin
; RegisterComponents('Samples', [TEnhSpeedButton]);
end;

{ TEnhSpeedButton }

procedure TEnhSpeedButton.CMMouseEnter(var Message: TMessage);
begin
; inherited;
; if Assigned(FOnMouseEnter) then FOnMouseEnter(Self);
end;

procedure TEnhSpeedButton.CMMouseLeave(var Message: TMessage);
begin
; inherited;
; if Assigned(FOnMouseLeave) then FOnMouseLeave(Self);
end;
end.

够简单吧。
 
我想我知道了,每个有窗口句柄的组件都自己处理窗口消息,这是通过字类化窗口函数实现的
关键是MakeInstanceObject 函数,这个函数在运行时可以生成一个新的函数过程,这个函数生成
一个窗口处理过程。每个组件(有窗口句柄)的初始的窗口处理函数都是InitProc;这个函数在
窗口的第一次窗口消息发送时被执行,其中就有调用MakeInstanceObject然后字类化窗口的代码,紧接着通过
汇编的粗暴方法补充一次对新的窗口处理函数的调用。MakeInstanceObject就是在运行时生成一个新
的窗口处理函数,函数中保存了组件类实例的地址,再通过这个地址调用WndProc方法,WndProc方法中
对Windows消息进行映射,然后就看到了事件了。最后还是要调用缺省的窗口处理函数以提供缺省的窗口行为。
这是部分的关键代码:
function MakeObjectInstance(Method: TWndMethod): Pointer;
const
; BlockCode: array[1..2] of Byte = (
; ; $59, ; ; ; { POP ECX }
; ; $E9); ; ; ;{ JMP StdWndProc }
; PageSize = 4096;
var
; Block: PInstanceBlock;
; Instance: PObjectInstance;
begin
; if InstFreeList = nil then
; begin
; ; Block := VirtualAlloc(nil, PageSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
; ; Block^.Next := InstBlockList;
; ; Move(BlockCode, Block^.Code, SizeOf(BlockCode));
; ; Block^.WndProcPtr := Pointer(CalcJmpOffset(@Block^.Code[2], @StdWndProc));
; ; Instance := @Block^.Instances;
; ; repeat
; ; ; Instance^.Code := $E8; ;{ CALL NEAR PTR Offset }
; ; ; Instance^.Offset := CalcJmpOffset(Instance, @Block^.Code);
; ; ; Instance^.Next := InstFreeList;
; ; ; InstFreeList := Instance;
; ; ; Inc(Longint(Instance), SizeOf(TObjectInstance));
; ; until Longint(Instance) - Longint(Block) >= SizeOf(TInstanceBlock);
; ; InstBlockList := Block;
; end;
; Result := InstFreeList;
; Instance := InstFreeList;
; InstFreeList := Instance^.Next;
; Instance^.Method := Method;
end;
那位大侠告诉小弟这是什么意思。
 
MakeObjectInstance creates a wrapper function that windows can call which in turn calls the object method.
 
后退
顶部