Source of the problem: Li Wei's book deep dive into VCL mentioned that clicking tbutton triggers the wm_command message, which actually executes the programmer's code. Maybe I was stupid and didn't understand what he meant. However, after tracing code and careful analysis, I finally understood the entire process. The conclusion is that I don't know much about Win32. In fact, the trigger button relies on the wm_command message, which is also done in VC.
Symptom: Have you found that tbutton has both onclick and onmousedown? What are the differences and connections between them? Which event does a normal button click to execute the programmer's code? View my analysis process:
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;
Click button1 and then click button2. Both the tag and m_tag are assigned values. It seems that clicking the button with the mouse is an arrow that triggers both The onclick and onmousedown events. Which of the two events will be executed first depends on the order in which messages are generated. As for who is the first, I have thought of a lot of ways: use Spy ++ to observe, because button1 and form1 are two different handles; in application. it is not acceptable to observe messages in run, because there are too many messages after the application runs and debugging is not feasible. You may modify the VCL source code and add case wm_command and case wm_lbuttondown to check who is intercepted first. However, I thought of a good way to add the record time option in these two events. This is simple and convenient, so there is no need for advanced technology. Through the following code, I found that onclick will be executed first:
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;
Execution Process after clicking tbutton