Autohotkey 将gui停靠到变量活动窗口
我看到很多例子,允许我打开一个程序,然后使用winwait和winexist将gui对接到它 相反,我想做的是将gui停靠到任何活动窗口。我试过无数种方法,请帮忙 (另外,当我将其附加到窗口时,它不会完全居中生成,因为在主脚本中,当我尝试执行以下操作时:Autohotkey 将gui停靠到变量活动窗口,autohotkey,Autohotkey,我看到很多例子,允许我打开一个程序,然后使用winwait和winexist将gui对接到它 相反,我想做的是将gui停靠到任何活动窗口。我试过无数种方法,请帮忙 (另外,当我将其附加到窗口时,它不会完全居中生成,因为在主脚本中,当我尝试执行以下操作时: WinGetPos cX, cY, cW, cH, ahk_id %ChildhWnd% offset1 := (mw / 2) - (cw /2) 当我按下热键说xy无效时,它抛出一个错误 下面是一个我没有
WinGetPos cX, cY, cW, cH, ahk_id %ChildhWnd%
offset1 := (mw / 2) - (cw /2)
当我按下热键说xy无效时,它抛出一个错误
下面是一个我没有完全自己制作的脚本。我自己算出了数学,但大量借用了我记不起来的资料。它几乎完成了我需要的,但不完全
; #Warn ; Enable warnings to assist with detecting common errors.
SendMode Input ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir% ; Ensures a consistent starting directory.
#SingleInstance, force
^T::
hookProcAdr := RegisterCallback("HookProc")
hHook := SetWinEventHook(0x800B,0x800B,0,hookProcAdr,0,0,0) ; EVENT_OBJECT_LOCATIONCHANGE
Gui, +hwndChildhWnd +AlwaysOnTop
Gui, add, text,,some text in a small gui that will move around with a notepad window
Gui, add, Button,,Button
MainhWnd := WinExist() ;<---------what do i do here?
;--------------------------------------------;
;-----i commented my second problem here-----;
;--------------------------------------------;
WinGetPos, mX, mY, mW, mH, ahk_id %MainhWnd%
;WinGetPos cX, cY, cW, cH, ahk_id %ChildhWnd% <--------{why cant i put child window here-+
; |
offset2 := (mw / 2) ; - (cw /2) <------------------------with offset subtraction here <-+
cX := mX + offset2
cY := mY
Gui, show, x%cX% y%cY%
return
;-------------------;
;-----functions-----;
;-------------------;
HookProc(hWinEventHook, event, hwnd)
{
global MainHwnd, ChildhWnd
if (hwnd = MainHwnd)
{
SetWinDelay, -1
WinGetPos hX, hY, hW, hH, ahk_id %MainhWnd%
WinGetPos cX, cY, cW, cH, ahk_id %ChildhWnd%
offset1 := (hw / 2) - (cw / 2)
X := hX + offset1
Y := hY
WinMove ahk_id %ChildhWnd%,,X,Y,w%cw%,h%ch%
}
}
SetWinEventHook(eventMin, eventMax, hmodWinEventProc, lpfnWinEventProc, idProcess, idThread, dwFlags) {
DllCall("CoInitialize", "uint", 0)
return DllCall("SetWinEventHook", "uint", eventMin, "uint", eventMax, "uint", hmodWinEventProc, "uint", lpfnWinEventProc, "uint", idProcess, "uint", idThread, "uint", dwFlags)
}```
#Warn;启用警告以帮助检测常见错误。
SendMode输入;由于其优越的速度和可靠性,建议用于新脚本。
SetWorkingDir%A_ScriptDir%;确保起始目录一致。
#单一实例,强制
^T::
hookProcAdr:=注册表回调(“HookProc”)
hHook:=SetWinEventHook(0x800B,0x800B,0,hookProcAdr,0,0,0);事件\对象\位置更改
Gui,+hwndChildhWnd+AlwaysOnTop
Gui,add,text,,小Gui中的一些文本将随记事本窗口移动
Gui,添加,按钮,按钮
MainhWnd:=WinExist();这里几乎没有错误,窗口切换部分必须添加一些额外的逻辑和魔力。
另外,我将把这个脚本从传统语法转换为现代表达式语法
首先,在这一行MainhWnd:=WinExist()
我们想从当前活动的窗口开始,所以让我们使用A
像这样:
MainhWnd:=WinExist(“A”)
那么这部分代码:
WinGetPos, mX, mY, mW, mH, ahk_id %MainhWnd%
;WinGetPos cX, cY, cW, cH, ahk_id %ChildhWnd% <--------{why cant i put child window here-+
; |
offset2 := (mw / 2) ; - (cw /2) <------------------------with offset subtraction here <-+
cX := mX + offset2
cY := mY
Gui, show, x%cX% y%cY%
在这里,您还可以看到我放弃传统语法并切换到的第一次出现,例如,在这里将字符串与变量连接起来:
ahk_id%MainhWnd%
→ <代码>%ahk_id“MainhWnd
基本上,一个带有空格的
%
强制命令的参数对表达式求值,而不是使用传统的文本参数。如果所有这些对您来说都是全新的,我建议您查看文档中的页面
然后讨论
HookProc
函数中的问题:
HookProc(hWinEventHook, event, hwnd)
{
global MainHwnd, ChildhWnd
if (hwnd = MainHwnd)
{
SetWinDelay, -1
WinGetPos hX, hY, hW, hH, ahk_id %MainhWnd%
WinGetPos cX, cY, cW, cH, ahk_id %ChildhWnd%
offset1 := (hw / 2) - (cw / 2)
X := hX + offset1
Y := hY
WinMove ahk_id %ChildhWnd%,,X,Y,w%cw%,h%ch%
}
}
首先在这里global MainHwnd,ChildhWnd
我们可以放弃变量
MainHwnd
,因为它对我们没有任何用处。我们希望MainHwnd
成为当前活动的窗口,而不是脚本开始时确定的一个窗口。还可以添加此变量
ChildWindowWidthHalf
if(hwnd=MainHwnd)
这张支票对我们来说也毫无意义。它应该被完全删除。
尽管如此,我还是强烈建议将其替换为if(hwnd=WinActive(“A”),这样可以过滤掉与当前活动窗口移动无关的消息 这个:
SetWinDelay,-1
没有理由每次都设置它,我们只需在脚本顶部设置一次即可 关于这一点:
WinGetPos hX, hY, hW, hH, ahk_id %MainhWnd%
WinGetPos cX, cY, cW, cH, ahk_id %ChildhWnd%
offset1 := (hw / 2) - (cw / 2)
我们对MainhWnd
不感兴趣,如上所述,让我们直接从windows消息中获取hwnd来替换它。传递到HookProc
函数第三个参数的hwnd。wingtpos,hX,hY,hW,%“ahk_id”hwnd
然后我们就可以不获取子窗口的位置。这没有用。
然后让我们也切换偏移以再次使用预定的子窗口宽度:
offset1:=(hW/2)-ChildWindowWidthHalf
然后转到:WinMove-ahk\u-id%ChildhWnd%,X,Y,w%cw%,h%ch%
它使用错误。宽度和高度参数前面没有
w
和h
字符。我们也没有理由更改窗口的宽度或高度。下面是它的外观:WinMove,%%“ahk_id”ChildhWnd,%X,%Y
现在您应该有一个工作脚本,如下所示: 但它只会在一个窗口移动时更新子窗口的位置,而不会在激活另一个窗口时更新子窗口的位置。
因此,您还需要捕捉一个窗口以获得焦点。
这可以通过一个壳钩很好地完成。
我将在代码中用注释解释这一点,下面是相关的文档链接:
,
现在你终于可以得到这样的成品了:
此外,我也不知道如何正确使用dock,所以我没有使用i lol。我主要想知道如何将gui附加到任何活动窗口,以及如何使其更新到新的活动窗口。您的代码运行良好,但我在发布代码后更改了代码。
WinGetPos hX, hY, hW, hH, ahk_id %MainhWnd%
WinGetPos cX, cY, cW, cH, ahk_id %ChildhWnd%
offset1 := (hw / 2) - (cw / 2)
SetWinDelay, -1
hookProcAdr := RegisterCallback("HookProc")
hHook := SetWinEventHook(0x800B,0x800B,0,hookProcAdr,0,0,0) ; EVENT_OBJECT_LOCATIONCHANGE
Gui, +hwndChildhWnd +AlwaysOnTop
Gui, add, text, , % "some text in a small gui that will move around with a notepad window"
Gui, add, Button, , Button
MainhWnd := WinExist("A")
ChildWindowWidthHalf := 349/2
WinGetPos, mX, mY, mW, , % "ahk_id " MainhWnd
offset2 := (mw / 2) - ChildWindowWidthHalf
cX := mX + offset2
cY := mY
Gui, show, % "x" cX " y" cY
return
HookProc(hWinEventHook, event, hwnd)
{
global ChildhWnd, ChildWindowWidthHalf
if (hwnd = WinActive("A"))
{
WinGetPos, hX, hY, hW, , % "ahk_id " hwnd
offset1 := (hW / 2) - ChildWindowWidthHalf
X := hX + offset1
Y := hY
WinMove, % "ahk_id " ChildhWnd, , % X, % Y
}
}
SetWinEventHook(eventMin, eventMax, hmodWinEventProc, lpfnWinEventProc, idProcess, idThread, dwFlags)
{
DllCall("CoInitialize", "uint", 0)
return DllCall("SetWinEventHook", "uint", eventMin, "uint", eventMax, "uint", hmodWinEventProc, "uint", lpfnWinEventProc, "uint", idProcess, "uint", idThread, "uint", dwFlags)
}
;register our script to receive shell messages
DllCall("RegisterShellHookWindow", UInt, ChildhWnd)
;define a unique message which we'll monitor
MsgId := DllCall("RegisterWindowMessage", Str, "SHELLHOOK")
;monitors the the message and fires the our
;user defined function "MsgMonitor"
OnMessage(MsgId, "MsgMonitor")
MsgMonitor(wParam, lParam) ;wParam = message, lParam = hwnd
{
;HSHELL_WINDOWACTIVATED = 0x04
;HSHELL_RUDEAPPACTIVATED = 0x8004
if (wParam = 0x8004 || wParam = 0x8004)
;we can borrow the HookProc function so we dont
;need to type the same code again
;first two parameters arent needed
HookProc("whatever", "whatever", lParam)
}
SetWinDelay, -1
hookProcAdr := RegisterCallback("HookProc")
hHook := SetWinEventHook(0x800B,0x800B,0,hookProcAdr,0,0,0) ; EVENT_OBJECT_LOCATIONCHANGE
Gui, +hwndChildhWnd +AlwaysOnTop
Gui, add, text, , % "some text in a small gui that will move around with a notepad window"
Gui, add, Button, , Button
;register our script to receive shell messages
DllCall("RegisterShellHookWindow", UInt, ChildhWnd)
;define a unique message which we'll monitor
MsgId := DllCall("RegisterWindowMessage", Str, "SHELLHOOK")
;monitors the the message and fires the our
;user defined function "MsgMonitor"
OnMessage(MsgId, "MsgMonitor")
MainhWnd := WinExist("A")
ChildWindowWidthHalf := 349/2
WinGetPos, mX, mY, mW, , % "ahk_id " MainhWnd
offset2 := (mw / 2) - ChildWindowWidthHalf
cX := mX + offset2
cY := mY
Gui, show, % "x" cX " y" cY
return
MsgMonitor(wParam, lParam) ;wParam = message, lParam = hwnd
{
;HSHELL_WINDOWACTIVATED = 0x04
;HSHELL_RUDEAPPACTIVATED = 0x8004
if (wParam = 0x8004 || wParam = 0x8004)
;we can borrow the HookProc function so we dont
;need to type the same code again
;first two parameters arent needed
HookProc("whatever", "whatever", lParam)
}
HookProc(hWinEventHook, event, hwnd)
{
global ChildhWnd, ChildWindowWidthHalf
if (hwnd = WinActive("A"))
{
WinGetPos, hX, hY, hW, , % "ahk_id " hwnd
offset1 := (hW / 2) - ChildWindowWidthHalf
X := hX + offset1
Y := hY
WinMove, % "ahk_id " ChildhWnd, , % X, % Y
}
}
SetWinEventHook(eventMin, eventMax, hmodWinEventProc, lpfnWinEventProc, idProcess, idThread, dwFlags)
{
DllCall("CoInitialize", "uint", 0)
return DllCall("SetWinEventHook", "uint", eventMin, "uint", eventMax, "uint", hmodWinEventProc, "uint", lpfnWinEventProc, "uint", idProcess, "uint", idThread, "uint", dwFlags)
}