像VCL组件有很多的事件.
如TDataSet.AfterPost,
TDataSet.BeforePost等等
有没有什么方法可以一下子屏蔽所有的事件,
做了一些事后,
要可以还原.
相当以下的代码:
var
OnAfterPost: TDataSetNotifyEvent;
begin
OnAfterPost := ADataSet.AfterPost;
ADataSet.AfterPost := nil;
try
// do something
finally
ADataSet.AfterPost := OnAfterPost;
end;
end;如果这样的话, 事件多了, 就要写很多.
如TDataSet.AfterPost,
TDataSet.BeforePost等等
有没有什么方法可以一下子屏蔽所有的事件,
做了一些事后,
要可以还原.
相当以下的代码:
var
OnAfterPost: TDataSetNotifyEvent;
begin
OnAfterPost := ADataSet.AfterPost;
ADataSet.AfterPost := nil;
try
// do something
finally
ADataSet.AfterPost := OnAfterPost;
end;
end;如果这样的话, 事件多了, 就要写很多.
begin
if CanEvent then
......
end;
針對不同的組件,有不同的處理方法,比如一些組件可以disable。看你要處理的是哪些組件,找找這些組件的共性,以這個方向去尋找,應是可解決。
因为使用TypeInfo单元可以控制类的所有信息,比如说可以将所有的事件都屏蔽或接管。>to aiirii: 重载其winproc, 应该可以阻止一部分
应该叫 WindowProc,不过它并没有控制事件的所有部分(比如说人工分配的)。
下面是替换Button1OnClick事件的一个简单示例:
var
m_vMethod: TMethod;
begin
m_vMethod.Code := Self.MethodAddress('MyClick'); //MyClick是Publish出来的一个TNotifyEvent类型方法
m_VMethod.Data := Self; SetMethodProp(Button1, 'OnClick', m_VMethod);
end;2. 个人的见解:如果是继承自TWinControl的,子类化该控件,截获所有消息。//定义新的窗口消息处理函数
function NewWndProc(AHandle: THandle; AMsg: UINT; wPar, lPar: LongInt): LongInt; stdcall;
begin
Result:= 0;
if g_bHandled then exit; //可能有一些不妥当的地方,因为消息的返回值不一定正确了。
Result:= CallWindowProc(Pointer(g_OldWndProc), AHandle, AMsg, wPar, lPar);
end;//定义全局变量
var
g_OldWndProc: Integer; //保存旧的窗口处理函数地址
g_bHandled : boolean = false; //是否被禁止了消息处理OnCreate://在控件创建的时候SubClass
g_bHandled := true;
g_OldWndProc:= SetWindowLong(Button1.Handle, GWL_WNDPROC, Integer(@NewWndProc));OnDestroy: //销毁前记得还原
g_bHandled:= false;
SetWindowLong(Button1.Handle, GWL_WNDPROC, g_OldWndProc);//禁止所有消息或允许消息传递
procedure TForm1.Button1Click(Sender: TObject);
begin
g_bHandled:= not g_bHandled;
end;3. 重载WindowProc的话,就的重新写一个类了。不喜欢这种方法。
SetWindowsHookEx(WH_CALLWNDPROC, @NewHookProc, nil, GetCurrentThreadID);
这样在消息处理之前,Call Window Procedure,就可以截获所有的消息处理了,接下来你就看着办吧。这个方法不用处理特定的控件的消息了,而是整个线程的消息都在自己的掌握之中了。
机制,不在此列,因此它们不能完全覆盖。关于 TypInfo/RTTI 是一个值得深入的话题。