消息使用简介

供新手入门和老手参考的教程和相关资料,包括中文帮助

Moderators: tmplinshi, arcticir

User avatar
amnesiac
Posts: 186
Joined: 22 Nov 2013, 03:08
Location: Egret Island, China
Contact:

消息使用简介

21 Aug 2014, 21:25

注:本文原计划为三个部分,目前后两个部分仍在整理中。

导言:许多新人、甚至一些使用不短时间脚本的用户对消息都比较陌生,看到使用消息的代码时总感觉玄而又玄,他们怎么知道可以用消息?消息中的那些参数是哪里来的?什么时候或什么场合可以考虑用消息?在自己的图形界面中如何自定义消息?本文尝试回答这些问题,让大家对消息有个大概的认识。
消息机制是 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
这里是赋值我们需要监视的系统消息,与许多高级语言可以通过加载头文件从而包含常量值 WM_COMMAND 不同,在 AutoHotkey 中并没有,所以要使用消息前需要先赋值(或者直接在后面使用相应的数值)。

Code: Select all

OnMessage(WM_COMMAND,"MsgHandler")
监视 WM_COMMAND 消息,接收到后使用 MsgHandler() 函数处理。如果我们这里没有监视系统消息,那么应用程序接收到消息后会进行默认的处理。除了 WM_COMMAND,还有许多其他的消息,例如 WM_NOTIFY,更多的请参阅帮助中“Windows 消息列表”页面。

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
在这个例子中,我们监视的是目标编辑控件取得和失去焦点时的系统消息,根据 MSDN 中 WM_COMMAND 消息页面可以看到,wParam 中的低字表示控件标识符,高字表示控件定义的通告码,lParam 表示发送此消息的控件句柄。这里摘取 MSDN 中 EN_SETFOCUS notification code 页面的关于 wParam 描述部分:
msdn.microsoft.com wrote:wParam
The LOWORD contains the identifier of the edit control. The HIWORD specifies the notification code.
所以,这个例子中如果完整的判断时(例如在含有多窗口的脚本中使用一个函数监视多种系统消息时),首先根据 hwnd 判断是否是我们需要监视的目标窗口,使用 msg 知道接收到的消息号,使用 lParam 判断发送消息的控件,然后检查 wParam 中的高字,如果高字的内容为 EN_SETFOCUS,说明目标编辑控件取得了焦点。
这里有两个地方要小心:
  • 从 wParam 中分离高字和低字时使用 NumGet() 得到的结果是错误的;
  • 应该使用 lParam 判断发送消息的控件而不用 wParam 中的低字,因为控件标识符不是唯一的(在函数中还可以使用 AutoHotkey 的一些内置变量进行辅助判断,例如 A_Gui 等)。
如何编写消息脚本
本部分待整理
在脚本 GUI 中自定义消息
本部分待整理
小结
Spoiler
扩展阅读:
AutoHotkey 学习指南(Beauty of AutoHotkey)
I do not make codes, and only a porter of AutoHotkey: from official to Chinese, from other languages to AutoHotkey, and show AutoHotkey to ordinary users sometimes.

Return to “教程资料”

Who is online

Users browsing this forum: No registered users and 6 guests