脚本在AutoHotkey同时按Windows按钮和左箭头



我想在autohotkey中编写一个脚本,以便每次我在PC上打开我的字典应用程序时,键Windows+LeftArrow同时被按下,结果,它会在监视器的左侧捕获窗口。

我试过了:

#IfWinActive Oxford Advanced Learner's Dictionary
Send, #{Left}
return

还有这个:

#IfWinActive Oxford Advanced Learner's Dictionary
Send, {LWinDown}{Left}{LWinup}
return

但是当我打开应用程序时,他们都没有任何反应。

编辑:

正如@Charlie Armstrong建议的那样,真正的问题是:我如何在每次启动某个程序时使代码块运行?所以#IfWinActive可能对。

一种方法是定期检查是否创建了新的进程/窗口,并检查这是否是我们想要交互的进程/窗口。

第一个例子是基于COM通知,当一个进程被创建/销毁。

; help for question: https://stackoverflow.com/q/66394326/883015
; by joedf (16:04 2021/02/28)
MyWatchedWindowTitle := "Oxford Advanced Learner's Dictionary"
NewProcess_CheckInterval := 1 ; in seconds
SetTitleMatchMode, 2 ;this might not be needed, makes the check for "contains" instead of "same" winTitle
hWnds := []
gosub, initialize_NewProcessNotification
return
; Called when a new process is detected
On_NewProcess(proc) {
global hWnds
global MyWatchedWindowTitle

; get the window handle, if possible
if (hwnd:=WinExist("ahk_pid " proc.ProcessID)) {
WinGetTitle, wTitle, ahk_id %hwnd%

; check if there is a visible window
if (wTitle)
{
; if so, check if it's a window we want to interact with
if (InStr(wTitle,MyWatchedWindowTitle))
{
; check if we've interacted with this specific window before
if (!ArrayContains(hWnds, hwnd)) {
; we havent, so we do something with it
hWnds.push(hwnd) ; keep in memory that we have interacted with this window ID before.
DoSomething(hwnd) ; the keys we want to send to it
}
}
}
}
}
DoSomething(hwnd) {
; size and move window to the left
SysGet, MonitorWorkArea, MonitorWorkArea
posY := 0
posX  := 0
width := A_ScreenWidth // 2
height := MonitorWorkAreaBottom
WinMove, ahk_id %hwnd% ,,%posX%,%posY%,%width%,%height%

; multi-montitor support, more examples, and more complete snapping functions can be found here:
; https://gist.github.com/AWMooreCO/1ef708055a11862ca9dc
}
ArrayContains(haystack, needle) {
for k, v in haystack
{
if (v == needle)
return true
}
return false
}

initialize_NewProcessNotification:
;////////////////////////////// New Process notificaton ////////////////////////
; from Lexikos' example
; https://autohotkey.com/board/topic/56984-new-process-notifier/#entry358038
; Get WMI service object.
winmgmts := ComObjGet("winmgmts:")
; Create sink objects for receiving event noficiations.
ComObjConnect(createSink := ComObjCreate("WbemScripting.SWbemSink"), "ProcessCreate_")
ComObjConnect(deleteSink := ComObjCreate("WbemScripting.SWbemSink"), "ProcessDelete_")
; Set event polling interval, in seconds.
interval := NewProcess_CheckInterval
; Register for process creation notifications:
winmgmts.ExecNotificationQueryAsync(createSink
, "Select * from __InstanceCreationEvent"
. " within " interval
. " where TargetInstance isa 'Win32_Process'")
; Register for process deletion notifications:
winmgmts.ExecNotificationQueryAsync(deleteSink
, "Select * from __InstanceDeletionEvent"
. " within " interval
. " where TargetInstance isa 'Win32_Process'")
; Don't exit automatically.
#Persistent
return
; Called when a new process is detected:
ProcessCreate_OnObjectReady(obj) {
proc := obj.TargetInstance
/*
TrayTip New Process Detected, % "
(LTrim
ID:`t" proc.ProcessID "
Parent:`t" proc.ParentProcessID "
Name:`t" proc.Name "
Path:`t" proc.ExecutablePath "

Command line (requires XP or later):

" proc.CommandLine
)
*/
On_NewProcess(proc)
}
; Called when a process terminates:
ProcessDelete_OnObjectReady(prm) {
/*
obj := COM_DispGetParam(prm, 0, 9)
proc := COM_Invoke(obj, "TargetInstance")
COM_Release(obj)
TrayTip Process Terminated, % "
(LTrim
ID:`t" COM_Invoke(proc, "Handle") "
Name:`t" COM_Invoke(proc, "Name")
)
COM_Release(proc)
*/
}

第二个例子可能更简单一些,它定期检查与搜索的WinTitle匹配的新窗口。

; help for question: https://stackoverflow.com/q/66394326/883015
; by joedf (16:17 2021/02/28)
#Persistent
MyWatchedWindowTitle := "Oxford Advanced Learner's Dictionary"
SetTitleMatchMode, 2 ;this might not be needed, makes the check for "contains" instead of "same" winTitle
SetTimer, checkForNewWindow, 1000 ;ms
hWnds := []
return
checkForNewWindow() {
global hWnds
global MyWatchedWindowTitle

; first check if there is at least one window that matches our winTitle
if (hwnd:=WinExist(MyWatchedWindowTitle)) {
; get all window matches
WinGet, wArray, List , %MyWatchedWindowTitle%

; loop through all windows that matched
loop % wArray
{
hWnd := wArray%A_Index%
; check if we've interacted with this specific window before
if (!ArrayContains(hWnds, hwnd)) {
; we havent, so we do something with it
hWnds.push(hwnd) ; keep in memory that we have interacted with this window ID before.
DoSomething(hwnd) ; the keys we want to send to it
}
}
}
}
DoSomething(hwnd) {
; size and move window to the left
SysGet, MonitorWorkArea, MonitorWorkArea
posY := 0
posX  := 0
width := A_ScreenWidth // 2
height := MonitorWorkAreaBottom
WinMove, ahk_id %hwnd% ,,%posX%,%posY%,%width%,%height%

; multi-montitor support, more examples, and more complete snapping functions can be found here:
; https://gist.github.com/AWMooreCO/1ef708055a11862ca9dc
}
ArrayContains(haystack, needle) {
for k, v in haystack
{
if (v == needle)
return true
}
return false
}

我认为你最大的问题是AHK似乎不能很好地用于抓拍窗口(根据我的快速研究和测试)。不过,运行良好的是WinMove。

我假设您从快捷图标启动程序,但我建议使用键盘快捷键启动程序,然后从脚本定位窗口。下面是一些示例代码,打开Notepad2.exe,等待200毫秒,然后移动窗口并调整其大小:

^+!n:: ; Control+Shift+Alt+N to Open Notepad
Run C:Program FilesNotepad2Notepad2.exe
sleep, 200
WinMove, Notepad2,, 10, 20, 800, 600
return

最新更新