Autohotkey 将gui停靠到变量活动窗口

Autohotkey 将gui停靠到变量活动窗口,autohotkey,Autohotkey,我看到很多例子,允许我打开一个程序,然后使用winwait和winexist将gui对接到它 相反,我想做的是将gui停靠到任何活动窗口。我试过无数种方法,请帮忙 (另外,当我将其附加到窗口时,它不会完全居中生成,因为在主脚本中,当我尝试执行以下操作时: WinGetPos cX, cY, cW, cH, ahk_id %ChildhWnd% offset1 := (mw / 2) - (cw /2) 当我按下热键说xy无效时,它抛出一个错误 下面是一个我没有

我看到很多例子,允许我打开一个程序,然后使用winwait和winexist将gui对接到它

相反,我想做的是将gui停靠到任何活动窗口。我试过无数种方法,请帮忙

(另外,当我将其附加到窗口时,它不会完全居中生成,因为在主脚本中,当我尝试执行以下操作时:

        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) 
}