首页 > 代码库 > 点击TButton后的执行过程

点击TButton后的执行过程

问题的来源:在李维的《深入浅出VCL》一书中提到了点击TButton会触发WM_COMMAND消息,正是它真正执行了程序员的代码。也许是我比较笨,没有理解他说的含义。但是后来经过追踪代码和仔细分析,终于明白了整个过程。结论是,自己对Win32的不够了解,其实触发按钮就是靠这个WM_COMMAND消息,VC里也是这样做的。

现象:有没有发现TButton既有OnClick,又有OnMouseDown,它们之间是什么区别和联系是什么呢?普通的按钮点击到底是哪个事件执行了程序员的代码,又是如何执行的呢?且看我的分析过程:

type  TForm1 = class(TForm)    Button1: TButton;    Button2: TButton;    procedure Button1Click(Sender: TObject);    procedure Button1MouseDown(Sender: TObject; Button: TMouseButton;      Shift: TShiftState; X, Y: Integer);    procedure Button2Click(Sender: TObject);  private    { Private declarations }  public    { Public declarations }    m_tag: integer;  end;var  Form1: TForm1;implementation{$R *.dfm}procedure TForm1.Button1Click(Sender: TObject);begin  tag:=100;end;procedure TForm1.Button1MouseDown(Sender: TObject; Button: TMouseButton;  Shift: TShiftState; X, Y: Integer);begin  m_tag:=200;end;procedure TForm1.Button2Click(Sender: TObject);begin  ShowMessage(intToStr(tag));  ShowMessage(intToStr(m_tag));end;

点击Button1后,再点击Button2,发现tag和m_tag两个值都被赋值了。看来用鼠标点击Button是一箭双雕啊,会同时触发OnClick和OnMouseDown事件。至于这两个事件哪个会先执行,则要看产生消息的先后顺序。至于到底谁先谁后,我想了好多办法:用SPY++观察不行,因为Button1和Form1是两个不同的句柄;在Application.Run里观察消息也不行,因为实在Application运行以后是太多消息了,没法调试。也许修改VCL源代码并同时加上case WM_COMMAND和case WM_LBUTTONDOWN后看先截住谁。不过后来我想了一个好办法,就是在这两个事件里加上记录时间的选项,这样简单方便,实在是不用什么高深技术。通过如下代码,我发现还是OnClick会被先执行:

  TForm1 = class(TForm)    Button1: TButton;    Button2: TButton;    procedure Button1Click(Sender: TObject);    procedure Button1MouseDown(Sender: TObject; Button: TMouseButton;      Shift: TShiftState; X, Y: Integer);    procedure Button2Click(Sender: TObject);  private    { Private declarations }  public    { Public declarations }    m_tag: integer;    m_time_click: TTime;    m_time_mousedown: TTime;  end;var  Form1: TForm1;implementation{$R *.dfm}procedure TForm1.Button1Click(Sender: TObject);begin  tag:=100;  m_time_click:=now;end;procedure TForm1.Button1MouseDown(Sender: TObject; Button: TMouseButton;  Shift: TShiftState; X, Y: Integer);begin  m_tag:=200;  m_time_mousedown:=now;end;procedure TForm1.Button2Click(Sender: TObject);begin  ShowMessage(intToStr(tag));  ShowMessage(intToStr(m_tag));  if m_time_click>m_time_mousedown then ShowMessage(m_time_click is first);end;

 

点击TButton后的执行过程