-
-
Save pernalin9/220d00016182acb7f13b96cd0506c0a9 to your computer and use it in GitHub Desktop.
| # 如果可以接受capslock作为输入法切换按键,强烈建议使用评论区脚本 | |
| # 如果可以接受capslock作为输入法切换按键,强烈建议使用评论区脚本 | |
| # 如果可以接受capslock作为输入法切换按键,强烈建议使用评论区脚本 | |
| #Include %A_ScriptDir% | |
| timeInterval := 500 | |
| ; +-------------------------+-------------------------+ | |
| ; | SubLanguage ID | Primary Language ID | | |
| ; +-------------------------+-------------------------+ | |
| ; 15 10 9 0 bit | |
| InChs(hWnd) { | |
| ThreadID:=DllCall("GetWindowThreadProcessId", "UInt", hWnd, "UInt", 0) | |
| ime_status := DllCall("GetKeyboardLayout", "int", ThreadID, "UInt") | |
| return (ime_status & 0xffff) = 0x804 ; LANGID(Chinese) = 0x804 | |
| } | |
| SwitchImeState(id) { | |
| SendMessage(0x283, ; WM_IME_CONTROL | |
| 0x002, ; wParam IMC_SETCONVERSIONMODE | |
| 1025, ; lParam (Chinese) | |
| , ; Control (Window) | |
| id) | |
| } | |
| DetectHiddenWindows True | |
| outer: | |
| Loop { | |
| try { | |
| hWnd := WinGetID("A") | |
| id := DllCall("imm32\ImmGetDefaultIMEWnd", "Uint", hWnd, "Uint") | |
| if (InChs(hWnd)) { | |
| SwitchImeState(id) | |
| } | |
| } catch as e { | |
| ; ^Esc 开始菜单弹窗,会卡死在找不到当前窗口 | |
| continue("outer") | |
| } | |
| Sleep(timeInterval) | |
| } |
@Lone101245 原本脚本在我的windows上确实可以运行,请再检查一下脚本是否一致。
不过原本版本的脚本确实存在很多小问题,我还发现这种连续调用SendMessage的方式在某些设备会造成cpu异常占用
我目前更改了一下脚本,如果可以接受的话建议使用这个版本(虽然还是会有一些偶发的小bug)
该版本特征:
- 使用capslock更改输入法,原本的大写锁定按键需要通过Shift+capslock使用 (模仿mac的中英文切换操作)
- shift不再有切换输入法功能
该版本需要的操作:
该版本运行逻辑
- 每隔指定时间更新一下窗口ID
- 当按下capslock时输入左Alt+Shift来切换输入法,并调用窗口检查,如果发生窗口变化就更改输入法语言为中文
使用两个月以来遇到的问题
- 很偶尔会出现切换之后还是英文的情况
具体代码
global LastActiveWindowID := "" ; 用于存储上一个活动窗口的标题
CheckActiveWindow() {
global LastActiveWindowID
try {
currentActive := WinGetID("A") ; 获取当前活动窗口的ID
} catch as e {
return
}
if (currentActive != LastActiveWindowID) { ; 如果当前窗口与上一个窗口不同
LastActiveWindowID := currentActive ; 更新最后一个活动窗口的ID
HandleIME(currentActive)
; ToolTip(currentActive) ; 显示当前活动窗口的标题
} else {
; ToolTip() ; 清除工具提示
}
}
SetTimer(CheckActiveWindow, 300) ; 每500毫秒检查一次当前窗口
timeInterval := 100
; +-------------------------+-------------------------+
; | SubLanguage ID | Primary Language ID |
; +-------------------------+-------------------------+
; 15 10 9 0 bit
InChs(hWnd) {
ThreadID:=DllCall("GetWindowThreadProcessId", "UInt", hWnd, "UInt", 0)
ime_status := DllCall("GetKeyboardLayout", "int", ThreadID, "UInt")
return (ime_status & 0xffff) = 0x804 ; LANGID(Chinese) = 0x804
}
SwitchImeState(id) {
SendMessage(0x283, ; WM_IME_CONTROL
0x002, ; wParam IMC_SETCONVERSIONMODE
1025, ; lParam (Chinese)
, ; Control (Window)
id)
}
HandleIME(hWnd)
{
try {
id := DllCall("imm32\ImmGetDefaultIMEWnd", "Uint", hWnd, "Uint")
if (InChs(hWnd)) {
SwitchImeState(id)
}
} catch as e {
return
; ^Esc 开始菜单弹窗,会卡死在找不到当前窗口
}
}
HandleIMEF()
{
try {
currentActive := WinGetID("A") ; 获取当前活动窗口的ID
HandleIME(currentActive)
} catch as e {
return
}
}
DetectHiddenWindows True
CapsLock::
{
Send "{Alt down}{Shift down}{Alt up}{Shift up}"
SetTimer(HandleIMEF, -timeInterval)
return
}
我琢磨出了一个新的办法,有兴趣可以试下,就是监听窗口切换事件,刚好有个现成的库(https://github.com/Descolada/AHK-v2-libraries/blob/main/Lib/WinEvent.ahk)可以用,然后代码就很简单了
`#include WinEvent.ahk
WinEvent.Active(ActiveWindowChanged)
Persistent()
ActiveWindowChanged(hook, hWnd, *) {
sleep 100
;ToolTip "激活窗口变了! "
wnd:=DllCall("imm32.dll\ImmGetDefaultIMEWnd", "Uint",WinExist("A"))
DllCall("SendMessage"
, "Ptr", wnd
, "UInt", 0x0283 ;Message : WM_IME_CONTROL
, "UPtr", 0x002 ;wParam : IMC_SETOPENSTATUS
, "Ptr", 1) ;lParam : 0 or 1
}`
其中sleep的时间可能需要根据实际情况调整,因为微软这个傻B切换机制也有一定的延时,在我的电脑上大致试了下,10是肯定切不过来,会被微软的覆盖,50一半一半,100刚好够用,刚好能看到我的设置把微软的给覆盖。
@silentmoooon 发现一个问题,记事本和系统设置无法切换到中文,资源管理器、任务管理器、浏览器都正常,系统 win11 24h2。
额,确实是,我也不知道为什么, 这两个怎么都不生效,不知道什么时候开始这样的.



Error at line 18.
Line Text:0x002,
Error: This line does not contain a recognized action.
The program will exit.
出现如上报错,请问如何解决