Autohotkey,切换布尔变量不能正常工作
Autohotkey, toggle boolean variable not work properly
我编写了一个 Autohotkey 程序来切换 Windows 内置放大镜的缩放级别。这很简单。当您将鼠标移动到左上角时,它会放大,下次您移动到左上角时它会缩小。下面是我的代码。问题是老是放大,不知道哪里出了问题。谁能帮忙看看?
; Timer to check mouse position
SetTimer, CheckMouse, 300
#Persistent
#SingleInstance force
WinGetPos,,,Xmax,Ymax,ahk_class Progman ; get desktop size
T = 4 ; adjust tolerance value if desired
Xmax := Xmax - T ; allow tolerance to mouse corner activation position
Ymax := Ymax - T
CheckMouse: ; check mouse position
CoordMode, Mouse, Screen
MouseGetPos, MouseX, MouseY
GetKeyState, SState, Shift
GetKeyState, AState, Alt
GetKeyState, CState, Control
zoom_toggle := True
if (MouseY < T and MouseX < T and CState = "U" and AState = "U" and SState = "U")
{
if(zoom_toggle)
{
Send #{+}
zoom_toggle := False
}
else
{
Send #{-}
zoom_toggle := True
}
}
Return
fix/improve.
的事情很少
我将从实际问题开始,然后再讨论您 should/could 改进的内容。
所以实际的问题是,每次你 运行 你的计时器,你都将 zoom_toggle
变量设置为 true
。所以是的,每次重置值时尝试进行任何切换都没有多大帮助。
将定义移动到脚本的顶部,或者由于 ahk 的宽容程度,您实际上可以完全跳过声明变量。这样,当它首次使用时,它是使用默认值 nothing 创建的,计算结果为 false
.
现在转到其他 fixes/improvements。
#directives 的位置。
Good/common 实践是在脚本的最顶部定义这些类型的#directives。
使用 WinGetPos
获取屏幕 width/height。
您可以使用 A_ScreenWidth
and A_ScreenHeight
变量轻松获取屏幕宽度和高度。
缺少 return
that should end your auto-execute section。
当您第一次启动脚本时,没有什么可以阻止代码执行一直下降到计时器的回调标签。
在您的情况下,这不会造成任何不良结果,但为了将来参考,您不希望这种情况发生。使用 return
停止代码执行并结束自动执行部分。
冗余代码
无需每次 运行 定时器都设置 CoordMode
。将此命令移动到脚本的顶部。
在您的发送命令中,无需将 -
包裹在 { }
中。这样做只是为了转义发送命令中具有特殊含义的字符,-
有 none。在特殊情况下,这样做甚至可能会遇到不需要的行为。 documentation.
中有更多相关信息
为什么要创建 Xmax
和 Ymax
?他们什么都不为我们做?
Send
instead of SendInput
的用法
SendInput
更快更可靠。应该几乎总是用于 Send
.
您可以在脚本顶部指定 SendMode, Input
以将所有 Send
命令转换为 SendInput
。我个人更喜欢只写 SendInput
.
遗留代码
从技术上讲,使用遗留代码没有错,但绝对不推荐这样做。
与未来 AHK 版本的兼容性也不存在。表达式语法是现在应该始终使用的语法。
使用函数 GetKeyState()
而不是旧命令。
使用非旧版 operators(&&
、||
等)而不是旧版 AND
、OR
等。
始终使用 :=
而不是 =
。从未使用过旧分配。
标签的使用也几乎是遗留的。应该替换为一个函数,但我应该确保你也理解函数范围。如果你愿意,我可以。
这是您修改后的代码:
#Persistent
#SingleInstance, Force
CoordMode, Mouse, Screen ;move this to the top, needs to be executed only once
; Timer to check mouse position
SetTimer, CheckMouse, 1000
T := 4 ; adjust tolerance value if desired
Xmax := A_ScreenWidth - T ; allow tolerance to mouse corner activation position
Ymax := A_ScreenHeight - T
;not sure why we're creating these two variables though, they're doing absolutely nothing for us?
return ;end auto-execute section
CheckMouse: ; check mouse position
MouseGetPos, MouseX, MouseY
SState := GetKeyState("Shift", "P")
AState := GetKeyState("Alt", "P")
CState := GetKeyState("Control", "P")
;returns true/false (1/0)
;true meaning the key is down
if (MouseY < T && MouseX < T && !SState && !AState && !CState)
{
;I skipped definin the zoom_toggle variable so it's created for us
;with the default value of nothing, which evaluates to false
;had to flip around the if statement to account for this as well
if(!zoom_toggle)
{
SendInput, #{+}
zoom_toggle := true
}
else
{
SendInput, #-
zoom_toggle := false
}
}
return ;ends the label
最后,我想说这不是一个很好的实现。为了使其至少可用,请将计时器更改为 运行 更慢。我在修改后的代码中做到了 1 秒。
如果你想让它变得更好,我可以提到一个超级简单的方法,就是当鼠标在该区域时只运行编码一次。为鼠标是否已退出该区域添加另一个开关即可。
此外,如果您在 Windows 中的主显示器左侧有第二台显示器,事情会变得很糟糕哈哈。
我编写了一个 Autohotkey 程序来切换 Windows 内置放大镜的缩放级别。这很简单。当您将鼠标移动到左上角时,它会放大,下次您移动到左上角时它会缩小。下面是我的代码。问题是老是放大,不知道哪里出了问题。谁能帮忙看看?
; Timer to check mouse position
SetTimer, CheckMouse, 300
#Persistent
#SingleInstance force
WinGetPos,,,Xmax,Ymax,ahk_class Progman ; get desktop size
T = 4 ; adjust tolerance value if desired
Xmax := Xmax - T ; allow tolerance to mouse corner activation position
Ymax := Ymax - T
CheckMouse: ; check mouse position
CoordMode, Mouse, Screen
MouseGetPos, MouseX, MouseY
GetKeyState, SState, Shift
GetKeyState, AState, Alt
GetKeyState, CState, Control
zoom_toggle := True
if (MouseY < T and MouseX < T and CState = "U" and AState = "U" and SState = "U")
{
if(zoom_toggle)
{
Send #{+}
zoom_toggle := False
}
else
{
Send #{-}
zoom_toggle := True
}
}
Return
fix/improve.
的事情很少
我将从实际问题开始,然后再讨论您 should/could 改进的内容。
所以实际的问题是,每次你 运行 你的计时器,你都将 zoom_toggle
变量设置为 true
。所以是的,每次重置值时尝试进行任何切换都没有多大帮助。
将定义移动到脚本的顶部,或者由于 ahk 的宽容程度,您实际上可以完全跳过声明变量。这样,当它首次使用时,它是使用默认值 nothing 创建的,计算结果为 false
.
现在转到其他 fixes/improvements。
#directives 的位置。
Good/common 实践是在脚本的最顶部定义这些类型的#directives。
使用 WinGetPos
获取屏幕 width/height。
您可以使用 A_ScreenWidth
and A_ScreenHeight
变量轻松获取屏幕宽度和高度。
缺少 return
that should end your auto-execute section。
当您第一次启动脚本时,没有什么可以阻止代码执行一直下降到计时器的回调标签。
在您的情况下,这不会造成任何不良结果,但为了将来参考,您不希望这种情况发生。使用 return
停止代码执行并结束自动执行部分。
冗余代码
无需每次 运行 定时器都设置 CoordMode
。将此命令移动到脚本的顶部。
在您的发送命令中,无需将 -
包裹在 { }
中。这样做只是为了转义发送命令中具有特殊含义的字符,-
有 none。在特殊情况下,这样做甚至可能会遇到不需要的行为。 documentation.
中有更多相关信息
为什么要创建 Xmax
和 Ymax
?他们什么都不为我们做?
Send
instead of SendInput
的用法
SendInput
更快更可靠。应该几乎总是用于 Send
.
您可以在脚本顶部指定 SendMode, Input
以将所有 Send
命令转换为 SendInput
。我个人更喜欢只写 SendInput
.
遗留代码
从技术上讲,使用遗留代码没有错,但绝对不推荐这样做。
与未来 AHK 版本的兼容性也不存在。表达式语法是现在应该始终使用的语法。
使用函数 GetKeyState()
而不是旧命令。
使用非旧版 operators(&&
、||
等)而不是旧版 AND
、OR
等。
始终使用 :=
而不是 =
。从未使用过旧分配。
标签的使用也几乎是遗留的。应该替换为一个函数,但我应该确保你也理解函数范围。如果你愿意,我可以。
这是您修改后的代码:
#Persistent
#SingleInstance, Force
CoordMode, Mouse, Screen ;move this to the top, needs to be executed only once
; Timer to check mouse position
SetTimer, CheckMouse, 1000
T := 4 ; adjust tolerance value if desired
Xmax := A_ScreenWidth - T ; allow tolerance to mouse corner activation position
Ymax := A_ScreenHeight - T
;not sure why we're creating these two variables though, they're doing absolutely nothing for us?
return ;end auto-execute section
CheckMouse: ; check mouse position
MouseGetPos, MouseX, MouseY
SState := GetKeyState("Shift", "P")
AState := GetKeyState("Alt", "P")
CState := GetKeyState("Control", "P")
;returns true/false (1/0)
;true meaning the key is down
if (MouseY < T && MouseX < T && !SState && !AState && !CState)
{
;I skipped definin the zoom_toggle variable so it's created for us
;with the default value of nothing, which evaluates to false
;had to flip around the if statement to account for this as well
if(!zoom_toggle)
{
SendInput, #{+}
zoom_toggle := true
}
else
{
SendInput, #-
zoom_toggle := false
}
}
return ;ends the label
最后,我想说这不是一个很好的实现。为了使其至少可用,请将计时器更改为 运行 更慢。我在修改后的代码中做到了 1 秒。
如果你想让它变得更好,我可以提到一个超级简单的方法,就是当鼠标在该区域时只运行编码一次。为鼠标是否已退出该区域添加另一个开关即可。
此外,如果您在 Windows 中的主显示器左侧有第二台显示器,事情会变得很糟糕哈哈。