向窗口或者窗口控件发送消息,作者:Rajat


本页讨论 PostMessage 和 SendMessage 命令,并将回答这样一些问题:

“我如何按下已被最小化的窗口中的按钮?”
“当 WinMenuSelectItem 不起作用时,我如何选中一个菜单项?!”
“这是个可更换皮肤的窗口……如何保证我发送的命令每次都能生效?”
隐藏窗口的话该怎么办?!”


环境要求:AutoHotkey v1.0.09+ 以及 Winspector Spy (www.windows-spy.com)

例如第一个例子中,注意 WinMenuSelectItem 命令就对 Outlook Express 的"New Message"窗口上的菜单栏无效。换言之,该代码不起任何作用:

WinMenuSelectItem, New Message,, &Insert, &Picture...

 

PostMessage 命令就能完成这个工作:

PostMessage, 0x111, 40239, 0, , New Message

好神奇啊!但那是啥鬼东西?0x111 是 wm_command 消息 的十六进制代码,40239 是让这个特殊的窗口理解为选择 'Insert Picture' 菜单项的代码。现在让我来告诉你如何获得一个类似 40239 这样的值:

  1. 启动 Winspector Spy 软件,打开 "New Message" 窗口。
  2. 拖动 Winspector Spy 窗口中的十字光标到 "New Message" 窗口的标题栏上(未被 Winspector Spy 窗口的覆盖效果遮蔽的部分)。
  3. 在左边列表中被选中的窗口名称上点击右键,选择 'Messages'。
  4. 右键点击空白窗口并选择 'Edit message filter'。 
  5. 按 'filter all' 按钮,然后双击左边列表中的 'wm_command' 项。这样你将只监视此消息。
  6. 现在转到 "New Message" 窗口并从菜单栏选择:Insert > Picture 。
  7. 返回 Winspector Spy 并按下信号灯按钮来暂停监视。
  8. 展开收集到的 wm_command 消息(忽略其它消息)。
  9. 你想要找的(通常)是一个代码为 0 的消息。有时那里描述为 'win activated' 或者 'win destroyed' 以及其它等等……都是不需要的内容。你要是发现那有一个描述为 'Control ID: 40239' 的消息……那就是它了!
  10. 现在将它放入上面的命令中你就搞定了!它就是 wParam 参数的值。

在下一个例子中,我会用到画图,因为大概每个人都会有。现在,让我们假设你要使用 AutoHotkey 从一个程序的工具栏选择一个工具;假设选择的就是取色这个工具。

你会怎么做?很可能是在工具栏按钮上用鼠标点击,对吧?但是工具栏可以被移动或者隐藏!在画图中也可以。所以如果目标用户移动或隐藏了工具栏,那么你的脚本在那个点上将会失效。但是下面的命令仍将有效:

PostMessage, 0x111, 639,,,未命名 - 画图

PostMessage 的另一个好处是窗口可以处在后台;相比之下,发送鼠标击键需要窗口处于激活状态。


下面有更多的例子。注意:我用的是 WinXP Pro (SP1)……如果你使用的是不同的操作系统,那可能需要调整下参数(仅对于像写字板和记事本这种 windows 自带的应用程序;其它的程序而言参数应该不用改变)。

;写字板字体设为青色
PostMessage, 0x111, 32788, 0, ,文档 - 写字板

;在记事本打开关于对话框
PostMessage, 0x111, 65, 0, ,无标题 - 记事本

;在记事本切换自动换行
PostMessage, 0x111, 32, 0, ,无标题 - 记事本

;播放/暂停 Windows Media Player
PostMessage, 0x111, 32808, 0, , Windows Media Player

;挂起一个正在运行的AHK脚本的热键
DetectHiddenWindows, on
SetTitleMatchMode, 2
PostMessage, 0x111, 65305,,, MyScript.ahk - AutoHotkey ;对比挂起操作,使用 65306 来暂停脚本。


上文讲的是 PostMessage 命令。SendMessage 命令与之相同,此外还等待一个消息返回值。可以用作例如获取 Winamp 中当前播放的曲目(请看 Automating Winamp 里的例子)。

这里还有些注意事项:

注意:此技术对某些应用程序无效。我对 VB 和 Delphi 编写的应用程序用时只能侥幸。此技术最适于 C, C++ 编写的应用程序。对于 VB应用程序,同个命令的 'LParam' 参数在传递时总是变化。对于 Delphi 应用程序……一些程序的GUI (用户图形界面)甚至不使用 wm_command 。它大概使用了鼠标位置和点击。

去探索吧……要在 AutoHotkey 论坛分享你的经验哦。欢迎您反馈信息!

这个指南并不是为新手们准备的(没有冒犯的意思),因为这些命令被认为是高级专题。所以如果读完本文,你还是摸不着头脑的话,请忘了它吧。

-Rajat

翻译:lwjiee   修正:天堂之门 menk33@163.com 2008年8月24日