delphi中的事件和消息
windows事件和消息机制
Delphi消息处理机制
键盘事件
鼠标事件
1、 windows事件和事件驱动程序编程
处理windows发往应用程序的消息一直是传统windows编程的关键内容之一,深刻理解windows的消息机制是编写出优秀windows应用程序的基础。
事件是组件的重要组成部分,它是连接对应的系统事件和为此而编写的代码。
不需要大量编程,这个时候组件封装了系统事件。
2、 windows的消息处理机制
消息是win发出的通知,它告诉应用程序某个事件发生了,win并不通知应用程序完成什么工作,而只是通知应用程序发生了什么。
一个应用程序一旦启动,Windows便为该应用程序建立一个消息队列(message queue),开始且陆续地将与该应用程序有关的消息加入它的队尾。应用程序则要逐个地将其消息队列中的队头消息取出,筛选出有用的消息,再指派给某个窗口过程,由其对消息进行处理和做出响应。从某种意义上讲,Windows的应用程序不过是一个消息处理器。事件就是被消息所驱动的。每个应用程序内部必定有一段循环程序,负责检索其消息队列,这段特殊的程序称为消息循环(message loop)。
windows消息系统的组成
消息队列(卖家):Windows为每个应用程序维护一个消息队列。应用程序从消息队列中获取消息,然后分派给某个窗口。
消息循环(中介):应用程序循环地从消息队列中检索消息,再把它分派给适当的窗口,然后继续从消息队列中检索下一条消息,再分派给适当的窗口,循环进行。
窗口过程(消费者):每个窗口都有一个窗口过程来接收传递给它的消息,它的任务就是获取消息然后响应它。窗口过程是一个回调函数,处理了一个消息后,它通常要返回一个值给Windows。
windows中消息的数据结构
消息的数据结构在Windows中被定义为如下的记录类型:
TMessage = record
Msg: Cardinal;
WParam:Word;
LParam: Longint;
Result: Longint;
end;
消息定义为如下的TMsg记录类型:
TMsg = packed record
hwnd: HWND;
message: UINT;
wParam: WPARAM;
lParam: LPARAM;
time: DWORD;
pt: TPoint;
end;
Delphi消息处理机制
1、 delphi的消息处理机制
所有Delphi提供的对象都有内建的消息处理机制。其基本思想是:对象接收某些类型的消息,并发送出去,继而调用一组与该消息相关的消息处理方法。若调用消息的特定方法不存在,则Delphi调用缺省处理。
当某个事件满足触发条件时,就会发送特定的消息到Windows系统消息队列。Delphi为应用程序中每种类型的组件注册了名为WinWndProc的方法作为窗口过程。窗口过程同时包含了异常处理模块、完成从Windows到名为WndProc的虚方法的消息记录传送、并调用应用程序对象的HandleException方法处理异常。
2、 发送消息
function SendMessage(hWnd:HWND; Msg:UINT;
wParam:WPARAM; lParam:LPARAM):LRESULT; stdcall;
function PostMessage(hWnd:HWND; Msg:UINT;
wParam:WPARAM; lParam:LPARAM): BOOL; stdcall;
3、 响应消息
方法1. 覆盖组件继承的虚拟方法WndProc
procedure TNewComponent.WndProc(varmessage:TMessage);
begin
if message.Msg = 需要过滤的消息then
begin
// 此处编写处理过滤消息代码
exit;
end;
inheritedWndProc(message);
dispatch(message);
end;
方法2. 覆盖组件继承的虚拟方法
DefaultHandler
在继承类中对DefaultHandler过程进行覆盖,同样可以实现类似于前一种方法的消息过滤。
方法3. 自定义消息和消息处理方法
Windows预定义了1024个编码从$0000到$03FF的消息常量标识符,留出从$0400到$7FFF的编码空间用于用户自定义消息。其中的$0400已定义为WM_USER。因此,自定义消息常量标识符的形式如下:
const
WM_UserMsgName = WM_USER + N; // 其中,
0<=N<=31743
方法4. TApplication的OnMessage事件
每当应用程序从消息队列中检索到一个消息时,便触发Application的OnMessage事件。由此,在消息被派送到对其响应和处理的目标对象之前,有机会处理该消息。
键盘事件
关于键盘
在计算机发展过程中,一开始是就使用键盘作为输入方式,在DOS环境中,大多只有判断键盘是否单击,以及单击的是哪个键,在Windows之中,可以判断键盘单击的事件有三种如下图所示:
在这些事件中,OnKeyDown和OnKeyUp都会传入用户单击的Key值(word值),可以利用这些值,来判断用户按了哪些键,而这些值代表了Windows中的Virtual Key Code。而OnKeyPress所返回的是一个Char值,代表一个ASCII字符。ASCII字符和Virtual Key Code是不相同的,因为Virtual Key Code中有代表ASCII的字符,但ASCII字符不包含全部的Virtual Key Code,因为Virtual Key Code中内含了很多功能键。
1.OnKeyDown
当按下键盘上的任一个键时,就会触发此事件。如字母键、数字键、功能键(F1~F12)、Ctrl键、Shift键或Alt键等,都将产生一个OnKeyDown事件。
2.OnKeyPress
当用户单击ASCII字符的键盘时,就是说当按下键盘上的一个字符键,如字母键、数字键等会产生一个OnKeyPress事件,但是单独按下功能键(F1~F12)、Ctrl键、Shift键或Alt键等,不会产生OnKeyPress事件。
3.OnKeyUp
当按下键盘上的任一个键后松开时,都会产生一个OnKeyUp事件。对于功能键(F1~F12)、Ctrl键、Shift键或Alt键等,也会产生一个OnKeyUp事件。
4.检测功能键
在组件的OnKeyDown、OnKeyUp、OnMouseDown和OnMouseUp等事件的处理过程中,有一个TShiftState类型的变量Shift,TShiftState类型定义如下:
Type
TShiftState=setof(ssShift,ssAlt,ssCtrl,ssLeft,ssRight,ssMiddle,ssDouble);
根据Shift的值就可以判断当键盘上的键按下时Shift、Alt和Ctrl键的状态,或者按下鼠标左键、中键时的状态或者是否双击了按键。当然,如果有OnMouseDown事件发生了,而又不是按下左键和中键,则按下的一定是右键。
1.常用鼠标事件
(1)OnClick:当用户单击鼠标任何一个键时,就会触发此事件。
(2)OnMouseDown:当用户单击鼠标时,就会触发此事件。
(3)OnMouseMove:当用户单击鼠标在对象上移动时,就会触发此事件,但停止就不触发了。
(4)OnMouseUp:当鼠标的某个按键按下,然后松开后会产生一个此事件。
在这些事件中,OnMouseDown和OnMouseUp都会触发事件,但是在用户单击时,可能会移动鼠标位置,使得两者被触发的对象不同的,但OnClick和OnMouseDown是会触发在同一个对象上的。当用户在对象A按一下时,A会同时触发OnMouseDown OnClick OnMouseUp OnMouseMove当用户在对象A单击但在对象B放开时,A会触发OnMouseDown OnMouseMove OnMouseUpB会触发OnMouseMove因此如果要触发OnClick事件,就必须要在一个对象按一下才行,否则只会有OnMouseDown、OnMouseMove、OnMouseUp这些事件。
2.拖放事件
(1)OnDragDrop:在拖曳事件开始时会触发此事件。
(2)OnDragOver:当拖曳对象跨过一个组件时会触发此事件。
(3)OnEndDrag:当拖曳事件结束后会产生触发此事件。
具体过程如下:
(1) 拖曳操作开始
大多数的组件具有DragMode属性,表示开始拖曳操作的方式。DragMode属性的缺省值为dmManual,也就是要在被拖动组件的OnMouseDown事件的处理过程中调用BeginDrag过
程才开始拖曳操作。如果将DragMode属性设置为dmAutomation,则鼠标左键在被拖动组件上按下后就自动开始拖曳操作。
(2)接受拖曳操作
当拖动一个组件经过第二个组件的时候,第二个组件会产生一个OnDragOver事件。在该事件的处理过程中有一个布尔类型的参数,该参数的设置直接影响是否产生OnDragDrop事件。一般情况下,在OnDragOver事件的处理过程中,根据参数Source判断拖曳操作的源。如果是可以接受的源,则将Accept参数设置为True;否则,将其设置为False。
(3)处理拖曳操作
在第二个组件OnDragDrop事件处理过程中,根据拖曳操作的源做一些相应的处理。
(4)拖曳操作结束
拖曳操作完成后释放鼠标左键,会在第一个组件中产生一个OnEndDrag事件,可以根据参数Target的数值进行相应的处理。如果参数Target的值为nil,则表示拖曳操作没有被接受如果Target的值不为nil,则Target的值就是接受拖曳操作的组件。
3.滚轮事件
(1) OnMouseWheel:当用户单击滚轮按钮时,就会触发此事件。
(2) OnMouseWheelDown:当用户用滚轮按钮向下转动时,就会触发。
(3) OnMouseWheelUp:当用户滚轮按钮向上转动时,就会触发。