<strong><span>三、窗口操作</span></strong><strong><span> <p></p></span></strong><span>注意:窗口标题和窗口文本参数总是对大小写敏感的。</span><span> <p></p></span><span>1</span><span>、等待窗口系列命令</span><span>/</span><span>函数</span><span> <p></p></span><span>AHK</span><span>和</span><span>AU3</span><span>都提供了用法类似的一组窗口等待命令</span><span>/</span><span>函数:</span><span>WinWait/WinWaitActive/WinWaitClose</span><span>。</span><span> <p></p></span><span>它们分别用于等待窗口出现、等待窗口被激活、等待窗口被关闭。由于这些命令</span><span>/</span><span>函数的参数类似,现仅以</span><span>WinWait</span><span>为例说明。</span><span> <p></p></span><span>AHK</span><span>:</span><span> <p></p></span><span>WinWait [, </span><span>窗口标题</span><span>, </span><span>窗口文本</span><span>, </span><span>超时时间</span><span>, </span><span>排除标题</span><span>, </span><span>排除文本</span><span>] <p></p></span><span>AU3</span><span>:</span><span> <p></p></span><span>WinWait ( "</span><span>窗口标题</span><span>" [, "</span><span>窗口文本</span><span>" [, </span><span>超时时间</span><span>]] ) <p></p></span><span>WinWait </span><span>的作用是<strong>在目标窗口出现之前不再执行后面的所有语句</strong>。</span><span> <p></p></span><span>假设我们要运行记事本程序,并在其窗口出现时提示用户:</span><span> <p></p></span><span>【示例</span> <span>3.1.1</span> <span>】</span><span> <p></p></span><span><span> </span>AHK</span><span>:</span><span> <p></p></span><span>Run Notepad <p></p></span><span>WinWait, </span><span>无标题</span><span> - </span><span>记事本</span><span> <p></p></span><span>MsgBox </span><span>记事本窗口已被打开!</span><span> <p></p></span><span>AU3</span><span>:</span><span> <p></p></span><span>Run("Notepad") <p></p></span><span>WinWait("</span><span>无标题</span><span> - </span><span>记事本</span><span>") <p></p></span><span>MsgBox(0, "", "</span><span>记事本窗口已被打开!</span><span>") <p></p></span><span><br /></span><span>2</span><span>、激活窗口相关命令</span><span>/</span><span>函数</span><span><br /></span><span>让目标窗口成为活动窗口的办法就是激活它,可用的命令</span><span>/</span><span>函数是</span><span>WinActivate</span><span>:</span><span> <p></p></span><span>AHK</span><span>:</span><span> <p></p></span><span>WinActivate [,</span><span>窗口标题</span><span>, </span><span>窗口文本</span><span>, </span><span>排除标题</span><span>, </span><span>排除文本</span><span>] <p></p></span><span>AU3</span><span>:</span><span> <p></p></span><span>WinActivate ( "</span><span>窗口标题</span><span>" [, "</span><span>窗口文本</span><span>"] ) <p></p></span><span><br /> </span><span>3</span><span>、关闭窗口</span><span> <p></p></span><span>关闭窗口有两种方式,一种是正常的关闭窗口(</span><span>WinClose</span><span>),另一种则是强行关闭窗口(</span><span>WinKill</span><span>):</span><span> <p></p></span><span>AHK</span><span>:</span><span> <p></p></span><span>WinClose/WinKill [,</span><span>窗口标题</span><span>, </span><span>窗口文本</span><span>, </span><span>超时时间</span><span>,, </span><span>排除标题</span><span>, </span><span>排除文本</span><span>] <p></p></span><span>AU3</span><span>:</span><span> <p></p></span><span>WinClose/WinKill ( "</span><span>窗口标题</span><span>" [, "</span><span>窗口文本</span><span>"] ) <p></p></span><span><br /> </span><span>现在我们已经可以实现一个比较简单的功能了,比如我们可以打开系统属性窗口并等待其出现,窗口出现后激活它,接着等待</span><span>3</span><span>秒再关闭它:</span><span> <p></p></span><span>【示例</span> <span>3.1.2</span> <span>】</span><span> <p></p></span><span><span> </span>AHK</span><span>:</span><span> <p></p></span><span>Run, Sysdm.cpl <p></p></span><span>WinWait, </span><span>系统属性</span><span> <p></p></span><span>WinActivate, </span><span>系统属性</span><span> <p></p></span><span>WinWaitActive, </span><span>系统属性</span><span> <p></p></span><span>Sleep, 3000 <p></p></span><span>WinClose, </span><span>系统属性</span><span> <p></p></span><span>WinWaitClose, </span><span>系统属性</span><span> <p></p></span><span>AU3</span><span>:</span><span> <p></p></span><span>Run("Control Sysdm.cpl") <p></p></span><span>WinWait("</span><span>系统属性</span><span>") <p></p></span><span>WinActivate("</span><span>系统属性</span><span>") <p></p></span><span>WinWaitActive("</span><span>系统属性</span><span>") <p></p></span><span>Sleep(3000) <p></p></span><span>WinClose("</span><span>系统属性</span><span>") <p></p></span><span>WinWaitClose("</span><span>系统属性</span><span>") <p></p></span><span><br /> </span><p><span>建议:如果程序中频繁地出现要用到这些窗口标题的地方,会带来一个问题:脚本的可读性,也许你会想,这不是很直观吗?可问题是如果这个重复出现的窗口标题是个很长的字符串呢?这将严重影响整个代码的排版美观。而且我们也无从了解这些窗口标题的“来头”,不知道这个窗口标题究竟是怎么来的。而如果我们定义一个变量(假设变量名是“</span><span>AppWindow1</span><span>”)保存这个窗口标题,我们就能在命令</span><span>/</span><span>函数中用变量来表示它,这样就达到了让代码用意更清晰一点的目的。另外,就算目标软件因某些原因(比如升级)而改变了它的窗口标题,我们也能很方便地作出修改。</span></p><span><br /> </span><span>4</span><span>、更准确的标识窗口的方法(主要针对</span><span>AHK</span><span>脚本)</span><span> <p></p></span><span>程序在运行时起码会有一个进程,如果能获得这个进程</span><span>ID</span><span>就能在一定程度上保证对窗口的准确标识。另外,每个窗口都有定义窗口类名(</span><span>Class</span><span>,比如说记事本窗口的类名就是</span><span>Notepad</span><span>),所以我们可以以此排除与目标窗口不同的其它窗口类。其实,我们还有一个更准确的方法:</span><span> <p></p></span><span>每个窗口(包括控件在内)都被</span><span>Windows</span><span>指派了一个可区别于其它窗口的唯一的标识符(</span><span>ID</span><span>),我们称之为窗口句柄(</span><span>HWND</span><span>)。</span><span> <p></p></span><p><span>直接给定窗口标题来表示窗口的一个缺点就是无法保证在脚本运行的过程中始终以该窗口为操作目标,因为在这个过程中很有可能会有其它“同名”窗口(或者说满足匹配条件的窗口)出现,而如果我们使用这个标识符来表示窗口自然就能保证命令</span><span>/</span><span>函数的操作窗口总是<strong>同一个</strong>窗口了。</span></p><p><span>我们先来了解一下获得窗口句柄的命令</span><span>/</span><span>函数:</span></p><span>AHK</span><span>:</span><span> <p></p></span><span>WinGet[, </span><span>输出变量</span><span>, ID, </span><span>窗口标题</span><span>, </span><span>窗口文本</span><span>, </span><span>排除标题</span><span>, </span><span>排除文本</span><span>] <p></p></span><span>AU3</span><span>:</span><span> <p></p></span><span>WinGetHandle ( "</span><span>窗口标题</span><span>" [, "</span><span>窗口文本</span><span>"] ) <p></p></span><span>其中</span><span>WinGet</span><span>获得的窗口</span><span>ID</span><span>将通过“输出变量”返回,而</span><span>WinGetHandle</span><span>的返回值就是获得的窗口</span><span>ID</span><span>。</span><span> <p></p></span><span><br /> </span><span>我们在进行自动化操作时是要先运行某个程序,如何获得这个程序成功运行后显示的窗口句柄?一个比较保险的办法是先获得这个程序的进程</span><span>ID</span><span>,然后根据这个进程</span><span>ID</span><span>获得它的窗口句柄,</span><span>AHK</span><span>支持使用进程</span><span>ID</span><span>作为窗口标题使用;但</span><span>AU3</span><span>不支持这样使用,只能先获得该窗口的类名再根据该类名来获得窗口句柄(不够保险):</span><span> <p></p></span><span>【示例</span> <span>3.1.3</span> <span>】</span><span> <p></p></span><span>AHK</span><span>:</span><span> <p></p></span><span>Run, NotePad, , , ThisPID <p></p></span><span>WinWait, ahk_pid %ThisPID%</span><span><span> </span><span> </span></span><span>;</span><span>这里的</span><span>ahk_pid</span><span>表明跟在后面的变量是进程</span><span>ID<span> <p></p></span></span><span>WinGet, ThisID, ID, ahk_pid %ThisPID%</span><span><span> </span><span> </span></span><span>;ThisID</span><span>将保存获得的窗口句柄</span><span> <p></p></span><span>AU3</span><span>:</span><span> <p></p></span><span><span> </span><span>Opt("WinTitleMatchMode", 4) <p></p></span></span><span>Run("Notepad") <p></p></span><span>$handle = WinGetHandle("class></span><span>现在暂且先忘记了</span><span>AU3</span><span>吧,因为它的窗口函数一般都不支持使用窗口句柄作为(窗口标题)参数。</span><span> <p></p></span><span>至于如何在</span><span>AHK</span><span>中使用窗口句柄,简单的说,凡是有“窗口标题”参数的命令就可以用窗口句柄来代替,比如:</span><span> <p></p></span><span>【示例</span> <span>3.1.4</span> <span>】</span><span> <p></p></span><span>AHK</span><span>:</span><span> <p></p></span><span>Run, Notepad, , , ThisPID</span><span><span> </span></span><span><span> </span>;</span><span>先获得运行的记事本程序的进程</span><span>ID</span><span> <p></p></span><span>WinWait, </span><span>无标题</span><span> - </span><span>记事本</span><span> <span>ahk_pid %ThisPID%</span></span><span><span> </span><span> </span></span><span>;</span><span>等待该进程窗口的出现</span><span> <p></p></span><span>WinGet, ThisHWND, ID, </span><span>无标题</span><span> - </span><span>记事本</span><span> <span>ahk_pid %ThisPID%</span></span><span><span> </span><span> </span></span><span>;</span><span>获得窗口句柄</span><span> <p></p></span><span>WinActivate, ahk_id %ThisHWND%</span><span><span> </span></span><span>;</span><span>这里的</span><span>ahk_id</span><span>表明跟在后面的变量是窗口句柄</span><span> <p></p></span><span>WinWaitActive, ahk_id %ThisHWND% <p></p></span><span>Sleep, 3000 <p></p></span><span>WinClose, ahk_id %ThisHWND% <p></p></span><p><span>WinWaitClose, ahk_id %ThisHWND%</span></p> |