像VCL组件有很多的事件.
如TDataSet.AfterPost,
  TDataSet.BeforePost等等
有没有什么方法可以一下子屏蔽所有的事件, 
做了一些事后,
要可以还原.
相当以下的代码:
var
  OnAfterPost: TDataSetNotifyEvent;
begin
  OnAfterPost := ADataSet.AfterPost;
  ADataSet.AfterPost := nil;
  try
    // do something
  finally
    ADataSet.AfterPost := OnAfterPost;  
  end;
end;如果这样的话, 事件多了, 就要写很多.

解决方案 »

  1.   

    楼主的要求太理想化,不过,可以设一个变量,如CanEvent: Boolean,需要响应时设置为True,否则False,在响应事件的时候判断一下,如:procedure TForm1.Button1Click(Sender: TObject)
    begin
      if CanEvent then
        ......
    end;
      
      

  2.   

    需要用到运行时类型信息(RTTI, Runtime Type Information),你找相关的资料看一看,具体关注 TypInfo 单元。
      

  3.   

    重载其winproc, 应该可以阻止一部分,具体要测试下
      

  4.   

    圍繞屏蔽消息這個方向去處理,因為一切窗口行為都是事件驅動型的。
    針對不同的組件,有不同的處理方法,比如一些組件可以disable。看你要處理的是哪些組件,找找這些組件的共性,以這個方向去尋找,應是可解決。
      

  5.   

    >为什么用TypInfo 单元
    因为使用TypeInfo单元可以控制类的所有信息,比如说可以将所有的事件都屏蔽或接管。>to aiirii: 重载其winproc, 应该可以阻止一部分
    应该叫 WindowProc,不过它并没有控制事件的所有部分(比如说人工分配的)。
      

  6.   

    因为使用TypeInfo单元可以控制类的所有信息,比如说可以将所有的事件都屏蔽或接管。 怎么我没有看到?
      

  7.   

    1. 可以使用TypInfo来控制,不过我试验了一下,比较麻烦,不知道是不是处理的不好。基本原理替换原来的虚拟方法.
    下面是替换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的话,就的重新写一个类了。不喜欢这种方法。
      

  8.   

    发完了想到一个更好的,Hook消息处理,
      SetWindowsHookEx(WH_CALLWNDPROC, @NewHookProc, nil, GetCurrentThreadID);
    这样在消息处理之前,Call Window Procedure,就可以截获所有的消息处理了,接下来你就看着办吧。这个方法不用处理特定的控件的消息了,而是整个线程的消息都在自己的掌握之中了。
      

  9.   

    WindowProc 或 Windows Hook (SetWindowsHookEx) 都只能截获属于Windows的消息,但 Delphi 有自己的事件
    机制,不在此列,因此它们不能完全覆盖。关于 TypInfo/RTTI 是一个值得深入的话题。
      

  10.   

    嗯,RTTI也许是个不错的选择,但是也不是最完美的,Delphi的不同版本,RTTI也不一定一样。兼容也是个问题...