导言:许多新人、甚至一些使用不短时间脚本的用户对消息都比较陌生,看到使用消息的代码时总感觉玄而又玄,他们怎么知道可以用消息?消息中的那些参数是哪里来的?什么时候或什么场合可以考虑用消息?在自己的图形界面中如何自定义消息?本文尝试回答这些问题,让大家对消息有个大概的认识。
消息机制是 Windows 系统中的一种通讯方式,简单的说就像人与人之间使用的短信。它是 Windows 发出的一个通知,告诉应用程序某个事情发生了。例如,单击鼠标、改变窗口尺寸、按下键盘上的一个键都会使 Windows 发送一个消息给应用程序。
帮助中相关内容:
SendMessage/PostMessage
OnMessage()
Windows 消息列表
处理系统消息
消息本身是作为一个记录传递给应用程序的,这个记录中包含了消息的类型及其他相关信息。在 AutoHotkey 中我们可以使用 OnMessage() 捕捉系统消息,这样可以实现对右击、双击、获取焦点等行为的判断,从而进行进一步的响应。这里将探讨如何监视系统消息并根据需要进行处理。
从示例开始
我们先来看看下面这个例子,这里实现了当编辑控件取得焦点(可以通过点击鼠标或键盘导航)时清除提示,若失去焦点前没有输入新内容则恢复提示。
Code: Select all
SetFormat, integer, hex
WM_COMMAND := 0x111 ; http://msdn.microsoft.com/en-us/library/ms647591.aspx
TestStr := "请输入测试字符串!"
Gui, +Border +LastFound +AlwaysOnTop +ToolWindow
hWin := WinExist()
Gui, Add, Edit
Gui, Font, italic s15
Gui, Add, Edit, vEditVar HwndhEdit, %TestStr%
Gui, Font, norm
Gui, Add, Button, Default, 确定
Gui, Show, AutoSize, 测试 GUI
OnMessage(WM_COMMAND,"MsgHandler")
Return
GuiClose:
ExitApp
MsgHandler(wParam, lParam, msg, hwnd)
{
global hEdit, TestStr, EditVar
EN_SETFOCUS := 0x100 ; http://msdn.microsoft.com/en-us/library/bb761685
EN_KILLFOCUS := 0x200
;~ xn := NumGet(wParam, 0, "short")
;~ yn := NumGet(wParam, 2, "short")
Transform, loword, BitAnd, wParam, 0xffff
Transform, hiword, BitShiftRight, wParam, 16
if (hEdit <> lParam) ; 发送此通告的不是目标编辑控件
return
ControlGetText, EditContent, , ahk_id %hEdit% ; 获取控件现在的内容
if (EditContent <> "" and EditContent <> TestStr) ; 控件的内容不为空,说明已经输入了新内容或者为第一次获取焦点前的原始内容。
return
if (hiword = EN_SETFOCUS) ; 编辑控件获得焦点
{
Gui, Font, norm
GuiControl, Font, EditVar
GuiControl, , EditVar
}
if (hiword = EN_KILLFOCUS) ; 编辑控件失去焦点
{
Gui, Font, italic
GuiControl, Font, EditVar
GuiControl, , EditVar, %TestStr%
}
return, 0
}
下面我们对这段代码进行简单的分析:
Code: Select all
WM_COMMAND := 0x111
Code: Select all
OnMessage(WM_COMMAND,"MsgHandler")
Code: Select all
MsgHandler(wParam, lParam, msg, hwnd){}
- wParam:消息的首个参数,表示的含义与具体的系统消息有关。
- lParam:消息的第二个参数,表示的含义与具体的系统消息有关。
- msg:接收到的消息号,如果我们使用一个函数监视多种系统消息例如 WM_COMMAND 和 WM_NOTIFY,在函数中可以根据这个判断接收到的是哪种消息。
- hwnd:接收到消息的窗口句柄,当我们写的脚本中含有多个窗口时可以根据此参数判断接收到消息的是哪个窗口。
Code: Select all
EN_SETFOCUS := 0x100
EN_KILLFOCUS := 0x200
Code: Select all
Transform, loword, BitAnd, wParam, 0xffff
Transform, hiword, BitShiftRight, wParam, 16
所以,这个例子中如果完整的判断时(例如在含有多窗口的脚本中使用一个函数监视多种系统消息时),首先根据 hwnd 判断是否是我们需要监视的目标窗口,使用 msg 知道接收到的消息号,使用 lParam 判断发送消息的控件,然后检查 wParam 中的高字,如果高字的内容为 EN_SETFOCUS,说明目标编辑控件取得了焦点。msdn.microsoft.com wrote:wParam
The LOWORD contains the identifier of the edit control. The HIWORD specifies the notification code.
这里有两个地方要小心:
- 从 wParam 中分离高字和低字时使用 NumGet() 得到的结果是错误的;
- 应该使用 lParam 判断发送消息的控件而不用 wParam 中的低字,因为控件标识符不是唯一的(在函数中还可以使用 AutoHotkey 的一些内置变量进行辅助判断,例如 A_Gui 等)。
本部分待整理
在脚本 GUI 中自定义消息
本部分待整理
小结
Spoiler
扩展阅读: