<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-1632085368384154" crossorigin="anonymous"></script><script src="https://autohotkey.top/gtag.js"></script></head> <body> <h1>PostMessage / SendMessage 教程 <span class="headnote">作者: Rajat</span></h1> <p>本页解释如何通过 <a href="../lib/PostMessage.htm">PostMessage</a> 或 <a href="../lib/SendMessage.htm">SendMessage</a> 向窗口或窗口控件发送消息, 并将回答如下问题:</p> <ul> <li>"如何按下已最小化窗口中的按钮?"</li> <li>"当 <a href="../lib/MenuSelect.htm">MenuSelect</a> 不起作用时, 我如何选择一个菜单项?!"</li> <li>"这是个可更换皮肤的窗口....如何确保我每次发送的函数都有效?"</li> <li>"如果是 <strong>隐藏</strong> 窗口呢?!"</li> </ul> <p>需要: Winspector Spy(<a href="https://www.softpedia.com/get/Security/Security-Related/Winspector.shtml">可在此处下载</a>)</p> <p>像第一个例子那样, 请注意 <a href="../lib/MenuSelect.htm">MenuSelect</a> 对 Outlook Express 的 "New Message" 窗口中的菜单栏无效. 换句话说, 这代码不起作用:</p> <pre> MenuSelect "New Message",, "&amp;Insert", "&amp;Picture..."</pre> <p>但 <a href="../lib/PostMessage.htm">PostMessage</a> 能实现这个操作:</p> <pre>PostMessage 0x111, 40239, 0, , "New Message"</pre> <p>太神奇了!但那个是什么? 0x111 是 <a href="SendMessageList.htm">wm_command 消息</a>的十六进制代码, 而 40239 是这个特殊窗口理解为选择 'Insert Picture' 菜单项的代码. 现在让我告诉您如何找到类似 40239 这样的值:</p> <ol> <li>启动 Winspector Spy, 打开 "New Message" 窗口.</li> <li>拖动 Winspector Spy 窗口中的十字线到 "New Message" 窗口的标题栏(没有被 Winspector Spy 覆盖的部分).</li> <li>在左边的列表中右键点击所选窗口并选择 'Messages'.</li> <li>右键点击空白窗口并选择 'Edit message filter'.</li> <li>点击 'filter all' 按钮, 然后双击左边列表中的 'wm_command'. 这样您将只监视此消息.</li> <li>现在转到 "New Message" 窗口并在菜单栏中选择: Insert &gt; Picture.</li> <li>返回 Winspector Spy 并按下信号灯按钮来停止监视.</li> <li>展开收集到的 wm_command 消息(忽略其他的).</li> <li>您想要找的(通常) 是代码为 0 的消息. 有时会有一些描述为 'win activated' 或 'win destroyed' 以及其他的 wm_command 消息..这些都是不需要的内容. 您会发现描述为 'Control ID: 40239' 的消息...就是它了!</li> <li>现在把它放入上面的函数中您就完成了! 它就是 wParam 值.</li> </ol> <p>在下一个例子中我会使用画图程序, 因为很可能每个人都会有. 现在假设我们要使用 AutoHotkey 从工具栏中选择一个工具; 假设要选择取色工具.</p> <p>您会怎么做? 很可能是使用鼠标点击工具栏, 对吗? 但是按钮可能被移动且隐藏了! 这个画图程序的工具栏也可能被移动/隐藏. 所以如果目标用户这么做了, 那么您的脚本在这个点上会失效. 但是下面的函数仍然有效:</p> <pre>PostMessage 0x111, 639,,, "Untitled - Paint"</pre> <p><a href="../lib/PostMessage.htm">PostMessage</a> 的另一个好处是窗口可以在后台; 与之相比, 发送鼠标点击要求目标窗口必须是活动的.</p> <p>这里有其他的例子. 请注意: 我使用的是 WinXP Pro(SP1) ... 如果您使用不同的操作系统, 那么您的参数可能要改变(仅适用于像写字板和记事本这类 windows 自带的应用程序; 其他的程序应该不用改变):</p> <pre><em>;设置写字板(Wordpad) 字体为青色</em> <a href="../lib/PostMessage.htm">PostMessage</a> 0x111, 32788, 0, , "Document - WordPad"</pre> <pre><em>;打开记事本(Notepad) 的关于对话框</em> <a href="../lib/PostMessage.htm">PostMessage</a> 0x111, 65, 0, , "Untitled - Notepad"</pre> <pre><em>;切换记事本的自动换行属性</em> <a href="../lib/PostMessage.htm">PostMessage</a> 0x111, 32, 0, , "Untitled - Notepad"</pre> <pre><em>;在 Windows Media Player 中播放/暂停</em> <a href="../lib/PostMessage.htm">PostMessage</a> 0x111, 32808, 0, , "Windows Media Player"</pre> <pre><em>;使用 65306 来 Pause, 而 65303 来 Reload, 从而代替下面的 Suspend. (请参阅 <a href="../FAQ.htm#close">FAQ</a>)</em> <a href="../lib/PostMessage.htm">PostMessage</a> 0x111, 65305,,, "MyScript.ahk - AutoHotkey" </pre> <pre><em>; 按下 CapsLock 和 Numpad2 重新加载所有 AutoHotkey 脚本</em> CapsLock &amp; Numpad2:: ReloadAllAhkScripts(ThisHotkey) { DetectHiddenWindows True for hwnd in WinGetList("ahk_class AutoHotkey") { if (hwnd = A_ScriptHwnd) <em>; 重新加载时忽略当前窗口</em> continue PostMessage 0x111, 65303,,, hwnd } Reload } </pre> <p>上面这个示例针对 PostMessage. <a href="../lib/SendMessage.htm">SendMessage</a> 的工作方式是一样的, 但另外会等待一个返回值, 这可以用于诸如在 Winamp 中获取当前正在播放的曲目(请参阅<a href="Winamp.htm">自动化 Winamp</a> 的例子).</p> <p>这里是一些注意事项:</p> <ul> <li>上文也提到了操作系统是 XP 且需要注意消息值随着不同的操作系统而改变. 如果您发现一个消息在您的系统上有效(对于一个软件的某个版本), 那么在其他系统上它对于这个软件的相同版本仍然是有效的. 此外, 大多数应用程序甚至会在它们的不同版本中使用相同的消息值(例如 Windows Media Player 和 Winamp).</li> <li>如果您已经在 Winspector Spy 中设置了过滤器来只显示 wm_command 消息, 却仍然得到大量的消息时, 请右键点击那些不需要的消息并选择隐藏(消息名)... 这些消息一般是不是由于您和目标软件交互所产生的消息.</li> <li>在 Winspector Spy 中, 右指向的箭头显示 msg 值, 左指向的模糊箭头显示返回值. 默认情况下, 0 值可以安全地认为是 '没有错误'(与 SendMessage 一起使用).</li> <li>要传递消息到隐藏窗口, 请添加此行到脚本: <code>DetectHiddenWindows True</code></li> </ul> <p>注: 此技术对某些应用程序无效. 我对 VB 和 Delphi 编写的应用程序只能侥幸. 此技术最适用于 C, C++ 编写的应用程序. 对于 VB 应用程序相同函数的 'LParam' 参数在传递时总是变化的. 对于 Delphi 应用程序... 一些程序的 GUI 甚至不使用 wm_command. 它或许使用鼠标位置和点击吧.</p> <p>去探索吧.... 并且记得在 AutoHotkey 论坛分享您的经验. 欢迎反馈!</p> <p>这个指南并不是为新手们准备的(没有冒犯的意思), 因为这些函数被认为是高级功能. 所以如果读完本文, 您还是摸不着头脑, 请忘了它吧.</p> <p>-Rajat</p> <a href="https://dftg.net">dftg</a><!-- Cloudflare Pages Analytics --><script defer src='https://static.cloudflareinsights.com/beacon.min.js' data-cf-beacon='{"token": "d5a9c4fcb9b6482fa53ce820d892f969"}'></script><!-- Cloudflare Pages Analytics --><script defer src="https://static.cloudflareinsights.com/beacon.min.js/vcd15cbe7772f49c399c6a5babf22c1241717689176015" integrity="sha512-ZpsOmlRQV6y907TI0dKBHq9Md29nnaEIPlkf84rnaERnq6zvWvPUqr2ft8M1aS28oN72PdrCzSjY4U6VaAw1EQ==" data-cf-beacon='{"rayId":"94f3b0762f8f6172","version":"2025.6.2","r":1,"serverTiming":{"name":{"cfExtPri":true,"cfEdge":true,"cfOrigin":true,"cfL4":true,"cfSpeedBrain":true,"cfCacheStatus":true}},"token":"51750bb5dc4f40cc91a5ec55c63bbc01","b":1}' crossorigin="anonymous"></script> </body> </html>