http://blog.163.com/muhx1981@126/blog/static/81459489200610305170213/

    一直以来都弄不清楚Delphi的事件驱动机制,今天看Delphi源代码,似乎有些明白了。
    问题:用鼠标单击按钮,为什么能执行我写的代码?
    环境:创建一个工程并保存,窗体上放置一个Button,在Button上双击鼠标左键,在Button1Click中写入一行代码,保存,所有控件的名字都保持默认的命名。
    现象:
      1.在Unit1.dfm中有一行语句
          OnClick = Button1Click
      2.TButton类中有published限制的属性
          property OnClick;
        从声明方式可知是继承而来的属性。
      3.TButton的父类和祖先类TButtonControl, TWinControl中没有关于OnClick的信息。
      4.TWinControl的父类TControl中有Published限制的属性
          property OnClick: TNotifyEvent read FOnClick write FOnClick stored IsOnClickStored;
      5.TNotifyEvent = procedure(Sender: TObject) of Object;
        这是一个方法指针的定义。
      6.跟踪FOnClick,发现只有在下面过程中使用到FOnClick:
          procedure TControl.Click;
          begin
            { Call OnClick if assigned and not equal to associated action's OnExecute.
              If associated action's OnExecute assigned then call it, otherwise, call
              OnClick. }
            if Assigned(FOnClick) and (Action <> nil) and (@FOnClick <> @Action.OnExecute) then
              FOnClick(Self)
            else if not (csDesigning in ComponentState) and (ActionLink <> nil) then
              ActionLink.Execute(Self)
            else if Assigned(FOnClick) then
              FOnClick(Self);
          end;
        这段代码有一条注释。
      7.跟踪过程Click,发现只存在以下过程:
          procedure TControl.WMLButtonUp(var Message: TWMLButtonUp);
          begin
            inherited;
            if csCaptureMouse in ControlStyle then MouseCapture := False;
            if csClicked in ControlState then
            begin
              Exclude(FControlState, csClicked);
              if PtInRect(ClientRect, SmallPointToPoint(Message.Pos)) then Click;
            end;
            DoMouseUp(Message, mbLeft);
          end;
        即,当鼠标左键送开并且满足一定条件时,执行Click过程。
        需要注意的是当执行Click过程之后依然需要执行DoMouseUp过程。
      8.找到这个过程的定义处,发现类接口中如下定义:
          procedure WMLButtonUp(var Message: TWMLButtonUp); message WM_LBUTTONUP;
        而消息常量:
          {$EXTERNALSYM WM_LBUTTONUP}
          WM_LBUTTONUP = $0202;
          
    至此,已经和Wondows消息机制联系起来了。
    
    结论:控件的事件实际上是响应Windows消息的过程。事件用方法指针实现,当将过程赋值给方法指针,而Wondows发出了对应的消息,则通过事件(方法指针)指向的实际过程来使得对应的消息得到响应。 

相关文章:

  • 2021-09-30
  • 2021-11-08
  • 2021-11-30
  • 2021-07-05
  • 2021-06-25
  • 2021-05-23
  • 2022-02-08
猜你喜欢
  • 2022-12-23
  • 2021-07-10
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2021-11-29
  • 2022-12-23
相关资源
相似解决方案