gpt4 book ai didi

autohotkey - 每次目标窗口在 AutoHotkey 中激活时如何激活功能

转载 作者:行者123 更新时间:2023-12-03 13:12:17 28 4
gpt4 key购买 nike

我想在每次切换到特定程序时激活声音配置文件,并在每次离开时更改回默认配置文件。
此操作在 GUI 中通过单选按钮打开。

我创建的解决方法是:

Auto_Ftsps:
gui, Submit, NoHide
While (Rad3==1)
{
Previous_window:= WinActive("A")
Sleep,1000
Current_window:= WinActive("A")
If (Previous_window =Current_window)
{}
Else If (Previous_window !=Current_window)
{
If(WinActive("Fortnite"))
Run_Peace_Profile("Ftsps")
Else
Run_Peace_Profile("Graphic EQ")
}
Sleep,2000
}
return

有一个更好的方法吗?我查看了论坛和教程,但没有成功。

最佳答案

OnWin.ahk 与您的方法有些相似;它使用 SetTimer 定期检查您向其注册的事件,因此与您的方法不同,它在 AHK 线程方面是异步的。不要引用我的话,但我在内部认为 WinWaitActive 也是类似的。

然而,还有另一种方法不涉及定期检查事件窗口,而是允许我们对 Windows 的“事件窗口更改”事件使用react - 外壳 Hook 。通常为 SetWindowsHookEx WH_SHELL将用于此,但我认为它甚至不可能单独与 AHK 一起使用(你必须制作一个 DLL),而且把一切都做好有点复杂。幸运的是有 RegisterShellHookWindow ,它允许我们以 Windows 消息的形式接收 shell 事件,而不是将 DLL 注入(inject)其他线程。然后我们可以使用 AHK 的 OnMessage 对这些消息使用react,在您的情况下,这意味着具有测试 wParam 的功能正在 HSHELL_WINDOWACTIVATEDHSHELL_RUDEAPPACTIVATED (即第 3 位已设置)并相应地更改声音配置文件。至于打开/关闭此功能,我们可以让单选按钮的 g-label 包含用于控制是否要通过 (De)RegisterShellHookWindow 接收 shell 消息的逻辑。 .

#SingleInstance Force

Gui +AlwaysOnTop +HwndhWnd
Gui Add, Text,, Automatic sound profile change
Gui Add, Radio, gHookRadioHandler Checked, On
Gui Add, Radio, gHookRadioHandler X+, Off
Gui Font,, Consolas
Gui Add, Edit, HwndhLog xm w800 r30 ReadOnly -Wrap -WantReturn

ftspsActive := false

; Get the dynamic identifier for shell messages and assign our callback to handle these messages
SHELL_MSG := DllCall("RegisterWindowMessage", "Str", "SHELLHOOK", "UInt")
OnMessage(SHELL_MSG, Func("ShellCallback"))

if (!SetHook(true)) {
GuiControl,, Off, 1
}

Gui Show


GuiClose() {
ExitApp
}

; Dummy implementation that logs the changes to an edit control for demonstration purposes
Run_Peace_Profile(profile) {
Println("Switched to " profile)
}

; Sets whether the shell hook is registered
SetHook(state) {
global hWnd
static shellHookInstalled := false
if (!shellHookInstalled and state) {
if (!DllCall("RegisterShellHookWindow", "Ptr", hWnd)) {
Println("Failed to register shell hook")
return false
}
Println("Registered shell hook")
shellHookInstalled := true
}
else if (shellHookInstalled and !state) {
if (!DllCall("DeregisterShellHookWindow", "Ptr", hWnd)) {
Println("Failed to deregister shell hook")
return false
}
Println("Deregistered shell hook")
shellHookInstalled := false
}

return true
}

; Radio button handler that controls registration of the sound profile hook
HookRadioHandler() {
state := A_GuiControl == "On"
if (!SetHook(state)) {
GuiControl,, % (state ? "Off" : "On"), 1
}
}

; Shell messages callback
ShellCallback(wParam, lParam) {
; HSHELL_WINDOWACTIVATED = 4, HSHELL_RUDEAPPACTIVATED = 0x8004
if (wParam & 4) {
; lParam = hWnd of activated window
global ftspsActive
WinGet fnHWnd, ID, Fortnite

WinGetTitle t, ahk_id %lParam%
Println("active window: " t)

if (!ftspsActive and fnHWnd = lParam) {
Run_Peace_Profile("Ftsps")
ftspsActive := true
}
else if (ftspsActive and fnHWnd != lParam) {
Run_Peace_Profile("Graphic EQ")
ftspsActive := false
}
}
}

; Prints a line to the logging edit box
Println(s) {
global hLog
static MAX_LINES := 1000, LINE_ADJUST := 200, nLines := 0
; EM_SETSEL = 0xB1, EM_REPLACESEL = 0xC2, EM_LINEINDEX = 0xBB
if (nLines = MAX_LINES) {
; Delete the oldest LINE_ADJUST lines
SendMessage 0xBB, LINE_ADJUST,,, ahk_id %hLog%
SendMessage 0xB1, 0, ErrorLevel,, ahk_id %hLog%
SendMessage 0xC2, 0, 0,, ahk_id %hLog%
nLines -= LINE_ADJUST
}
++nLines
; Move to the end by selecting all and deselecting
SendMessage 0xB1, 0, -1,, ahk_id %hLog%
SendMessage 0xB1, -1, -1,, ahk_id %hLog%
; Add the line
str := "[" A_Hour ":" A_Min "] " s "`r`n"
SendMessage 0xC2, 0, &str,, ahk_id %hLog%
}

请注意,我以编辑控件的形式添加了一些反馈消息,以便该脚本可以用作小型独立演示。

这种方法的一个可能的缺点来自 RegisterShellHookWindow 的顶部。文档:

This function is not intended for general use. It may be altered or unavailable in subsequent versions of Windows.



此外,我不知道什么是“粗鲁的应用程序”,也不知道为什么它们有自己的常数。 This question说它与全屏应用程序有关,但提问者和我收到 HSHELL_RUDEAPPACTIVATED对于似乎每个程序。

作为替代方案,还有 SetWinEventHook , 可以用 EVENT_SYSTEM_FOREGROUND 调用和 WINEVENT_OUTOFCONTEXT安装来自 AHK 的回调,每次前景窗口更改时都会调用该回调。请注意,与 RegisterShellHookWindow 不同,这将在子窗口进入前台时调用。方法。
#SingleInstance Force

Gui +AlwaysOnTop
Gui Add, Text,, Automatic sound profile change
Gui Add, Radio, gHookRadioHandler Checked, On
Gui Add, Radio, gHookRadioHandler X+, Off
Gui Font,, Consolas
Gui Add, Edit, HwndhLog xm w800 r30 ReadOnly -Wrap -WantReturn

ftspsActive := false

fcAddr := RegisterCallback(Func("FgCallback"))

if (!SetHook(true)) {
GuiControl,, Off, 1
}

Gui Show


GuiClose() {
ExitApp
}

; Dummy implementation that logs the changes to an edit control for demonstration purposes
Run_Peace_Profile(profile) {
Println("Switched to " profile)
}

; Sets whether the foreground hook is installed
SetHook(state) {
global fcAddr
static hook, fgHookInstalled := false

if (!fgHookInstalled and state) {
; EVENT_SYSTEM_FOREGROUND = 3, WINEVENT_OUTOFCONTEXT = 0
hook := DllCall("SetWinEventHook", "UInt", 3, "UInt", 3, "Ptr", 0, "Ptr", fcAddr, "Int", 0, "Int", 0, "UInt", 0, "Ptr")
if (!hook) {
Println("Failed to set foreground hook")
return false
}
Println("Set foreground hook")
fgHookInstalled := true
}
else if (fgHookInstalled and !state) {
if (!DllCall("UnhookWinEvent", "Ptr", hook)) {
Println("Failed to unset foreground hook")
return false
}
Println("Unset foreground hook")
fgHookInstalled := false
}

return true
}

; Radio button handler that controls installation of the sound profile hook
HookRadioHandler() {
state := A_GuiControl == "On"
if (!SetHook(state)) {
GuiControl,, % (state ? "Off" : "On"), 1
}
}

; Foreground window change callback
FgCallback(hWinEventHook, event, hWnd, idObject, idChild, dwEventThread, dwmsEventTime) {
global ftspsActive
WinGet fnHWnd, ID, Fortnite

WinGetTitle t, ahk_id %hWnd%
Println("fg window: " t)

if (!ftspsActive and fnHWnd = hWnd) {
Run_Peace_Profile("Ftsps")
ftspsActive := true
}
else if (ftspsActive and fnHWnd != hWnd) {
Run_Peace_Profile("Graphic EQ")
ftspsActive := false
}
}

; Prints a line to the logging edit box
Println(s) {
global hLog
static MAX_LINES := 1000, LINE_ADJUST := 200, nLines := 0
; EM_SETSEL = 0xB1, EM_REPLACESEL = 0xC2, EM_LINEINDEX = 0xBB
if (nLines = MAX_LINES) {
; Delete the oldest LINE_ADJUST lines
SendMessage 0xBB, LINE_ADJUST,,, ahk_id %hLog%
SendMessage 0xB1, 0, ErrorLevel,, ahk_id %hLog%
SendMessage 0xC2, 0, 0,, ahk_id %hLog%
nLines -= LINE_ADJUST
}
++nLines
; Move to the end by selecting all and deselecting
SendMessage 0xB1, 0, -1,, ahk_id %hLog%
SendMessage 0xB1, -1, -1,, ahk_id %hLog%
; Add the line
str := "[" A_Hour ":" A_Min "] " s "`r`n"
SendMessage 0xC2, 0, &str,, ahk_id %hLog%
}

关于autohotkey - 每次目标窗口在 AutoHotkey 中激活时如何激活功能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49610663/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com