TControl与Windows消息

TControl将系统消息转换成VCL事件,以将系统消息融入VCL中。鼠标的事件就是一个很好的例子,当我们单击鼠标时会产生鼠标的单击消息,而这个单击消息是怎么被处理并执行的呢?

在Control单元中有这样的一段代码:

 1 TControl = class(TComponent)
 2 private
 3     ...
 4     FControlState: TControlState;    //状态    //TControlState = set of (csLButtonDown, csClicked,  .... , );
 5     ...
 6     FOnMouseDown: TMouseEvent;    //用以接受用户的定义的方法。
 7     ...
 8     procedure DoMouseDown(var Message: TWMMouse; Button: TMouseButton; Shift: TShiftState);
 9     ...
10     procedure WMLButtonDown(var Message: TWMLButtonDown); message WM_LBUTTONDOWN;    //鼠标左键
11     procedure WMRButtonDown(var Message: TWMRButtonDown); message WM_RBUTTONDOWN;    //鼠标右键
12     procedure WMMButtonDown(var Message: TWMMButtonDown); message WM_MBUTTONDOWN;   //鼠标中间键
13  protected
14     procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); dynamic;
15     ...
16     property OnMouseDown: TMouseEvent read FOnMouseDown write FOnMouseDown;
17 end;

TControl声明了一个OnMouseDown属性,该属性读写一个称为FOnMouseDown的事件指针。当我们需要处理一个按钮被按下的情况时,我们便会定义一个按钮按下的方法,并赋值给按钮OnMouseDown属性。此时,FOnMouseDown就会指向这个用户定义的方法。

当我们左键按下鼠标时候,TObject会调用Dispatch()方法会分发WM_LBUTTIONDOWN消息分发,然后进入相应的消息处理函数。如下:

1 procedure TControl.WMLButtonDown(var Message: TWMLButtonDown);
2 begin
3   SendCancelMode(Self);
4   inherited;
5   if csCaptureMouse in ControlStyle then MouseCapture := True;
6   if csClickEvents in ControlStyle then Include(FControlState, csClicked);
7   DoMouseDown(Message, mbLeft, []);
8 end;

如果是单击事件,则在FControlState中添加csClicked。并且跳转到DoMouseDown()方法中。

 1 procedure TControl.DoMouseDown(var Message: TWMMouse; Button: TMouseButton;
 2   Shift: TShiftState);
 3 begin
 4   if not (csNoStdEvents in ControlStyle) then
 5     with Message do
 6       if (Width > 32768) or (Height > 32768) then
 7         with CalcCursorPos do
 8           MouseDown(Button, KeysToShiftState(Keys) + Shift, X, Y)
 9       else
10         MouseDown(Button, KeysToShiftState(Keys) + Shift, Message.XPos, Message.YPos);
11 end;

在DoMouseDown()中进行一些必要的处理工作后,就会调用MouseDown();

1 procedure TControl.MouseDown(Button: TMouseButton;
2   Shift: TShiftState; X, Y: Integer);
3 begin
4   if Assigned(FOnMouseDown) then FOnMouseDown(Self, Button, Shift, X, Y);
5 end;

在MouseDown()中,就会通过FOnMouseDown事件指针去执行用户定义的代码。此时就完成了从一个WM_LBUTTIONDOWN消息转换成相应的代码过程。

另外,值得注意的是,鼠标的Click事件是没有相应的消息的,鼠标的单击事件被包含在WM_LBUTTIONDOWN消息中,而鼠标的双击事件的消息是WM_LBUTTONDBLCLK消息。而,我们如果要单击鼠标,会先处理OnMouseDown()事件,然后再处理OnClick()事件。并且,如果我们双击鼠标,首先先处理OnMouseDown()事件,然后再处理OnDblClick()事件。这一点很好被验证:

 1 procedure TForm1.FormClick(Sender: TObject);
 2 begin
 3   ShowMessage(‘click‘);
 4 end;
 5
 6 procedure TForm1.FormDblClick(Sender: TObject);
 7 begin
 8   ShowMessage(‘dblclick‘);
 9 end;
10
11 procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton;
12   Shift: TShiftState; X, Y: Integer);
13 begin
14   ShowMessage(‘Down‘);
15 end;

如果我们不注释第14行,那么无论我们如何点击鼠标,都只能处理OnMouseDown()事件,然后ShowMessage()并得到焦点,OnClick()或OnDblCLick事件就不会被执行到。同样,当我们双击鼠标的时候,首先会ShowMessage(‘click‘)。

时间: 2024-12-25 10:15:28

TControl与Windows消息的相关文章

Windows消息队列

一 Windows中有一个系统消息队列,对于每一个正在执行的Windows应用程序,系统为其建立一个"消息队列",即应用程序队列,用来存放该程序可能 创建的各种窗口的消息.应用程序中含有一段称作"消息循环"的代码,用来从消息队列中检索这些消息并把它们分发到相应的窗口函数中.  二 Windows为当前执行的每个Windows程序维护一个「消息队列」.在发生输入事件之后,Windows将事件转换为一个「消息」并将消息放入程序的消息队列中.程序通过执行一块称之为「消息循

(转载)Windows消息机制

文章出处:http://www.cnblogs.com/watsonyin/archive/2005/12/12/295536.html Windows消息机制 Windows操作系统最大的特点就是其图形化的操作界面,其图形化界面是建立在其消息处理机制这个基础之上的.如果不理解Windows消息处理机制,肯定无法深入的理解Windows编程.可惜很多程序员对Windows消息只是略有所闻,对其使用知之甚少,更不了解其内部实现原理,本文试着一步一步向大家披露我理解的Windows消息机制.可以说,

细说UI线程和Windows消息队列

在 Windows应用程序中,窗体是由一种称为" UI线程( User Interface Thread)"的特殊类型的线程创建的. 首先, UI线程是一种"线程",所以它具有一个线程应该具有的所有特征,比如有一个线程函数和一个线程 ID. 其次," UI线程"又是"特殊"的,这是因为 UI线程的线程函数中会创建一种特殊的对象--窗体,同时,还一并负责创建窗体上的各种控件. 窗体和控件大家都很熟悉了,这些对象具有接收用户操作的

全部的Windows消息对应值

以下是全部的Windows消息,   对于未在MSDN上的消息的WPARAM,   LPARAM参数解释正确的给分 [已知   :0x0313,   0x01e2,   0x01e5,   0x01eb,   0x006a] WM_NULL                                     0x0000 WM_CREATE                                 0x0001 WM_DESTROY                           

Windows 消息机制

Windows 消息机制 Windows是一个消息驱动的操作系统. 如绘制窗体的消息 WM_PAINT. 结构体定义: 消息分类-发送途径 队列消息. Windows为每一个执行中的程序维护一个消息队列.由应用程序自己取出,如WM_TIMER. 非队列消息. 此类消息来自特定的Windows函数,如UpdateWindow()函数直接向窗体处理函数发送WM_PAINT重绘消息. 消息分类-发送者 系统消息.是提前定义的UINT常量. 用户消息. 通过RegisterWindowMessage()

Windows 消息

Windows是一消息(Message)驱动式系统,Windows消息提供了应用程序与应用程序之间.应用程序与Windows系统之间进行通讯的手段.应用程序要实现的功能由消息来触发,并靠对消息的响应和处理来完成.Windows系统中有两种消息队列,一种是系统消息队列,另一种是应用程序消息队列.计算机的所有输入设备由 Windows监控,当一个事件发生时,Windows先将输入的消息放入系统消息队列中,然后再将输入的消息拷贝到相应的应用程序队列中,应用程序中的消息循环从它的消息队列中检索每一个消息

结合windows消息系统理解C#中WndProc函数和DefWndProc函数

Windows消息系统由3部分组成: 1.消息队列.Windows应用程序的消息是由Windows统一在一个消息队列中管理的. 2.消息循环.应用程序从Windows消息队列中获得自己的消息,并将其分配给窗体函数进行处理. 3.窗口过程.负责处理接收到的消息,每个窗口都有对应的窗口过程,负责截获消息并响应.WndProc是窗口过程函数,负责处理接收到的消息,在我们写代码时,不会注意到有这个函数,这是因为开发环境自动为我们生成了.WndProc函数通过switch...case...判断并处理消息

windows消息机制(MFC)

windows消息机制(MFC) 消息分类与消息队列 Windows中,消息使用统一的结构体(MSG)来存放信息,其中message表明消息的具体的类型, 而wParam,lParam是其最灵活的两个变量,为不同的消息类型时,存放数据的含义也不一样. time表示产生消息的时间,pt表示产生消息时鼠标的位置. 按照类型,Windows将消息分为: (0) 消息ID范围 系统定义消息ID范围:[0x0000, 0x03ff]用户自定义的消息ID范围: WM_USER: 0x0400-0x7FFF 

正则表达式实例 -- 匹配Windows消息宏

Windows消息宏,定义在winuser.h里,消息编号从 0x0000 到 0x0400,下面给出一部分: 1 #define WM_NULL 0x0000 2 #define WM_CREATE 0x0001 3 #define WM_DESTROY 0x0002 4 #define WM_MOVE 0x0003 5 #define WM_SIZE 0x0005 正则表达式: 1 #define (.+?) (0x[0-9a-fA-F]{1,4}) 在线测试工具: http://tool.