Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 7 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pernalin9/220d00016182acb7f13b96cd0506c0a9 to your computer and use it in GitHub Desktop.
Save pernalin9/220d00016182acb7f13b96cd0506c0a9 to your computer and use it in GitHub Desktop.
微软输入法自动跳转为中文Fix.ahk
# 如果可以接受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
Copy link

Error at line 18.
Line Text:0x002,
Error: This line does not contain a recognized action.

The program will exit.
出现如上报错,请问如何解决

@pernalin9
Copy link
Author

@Lone101245 原本脚本在我的windows上确实可以运行,请再检查一下脚本是否一致。
不过原本版本的脚本确实存在很多小问题,我还发现这种连续调用SendMessage的方式在某些设备会造成cpu异常占用
我目前更改了一下脚本,如果可以接受的话建议使用这个版本(虽然还是会有一些偶发的小bug)

该版本特征:

  • 使用capslock更改输入法,原本的大写锁定按键需要通过Shift+capslock使用 (模仿mac的中英文切换操作)
  • shift不再有切换输入法功能

该版本需要的操作:

  • 安装中文和英语两个语言包
    image
  • 需要调整微软拼音输入法按键设置,取消中英文模式切换
    image
  • 时间和语言 > 输入 > 高级键盘设置 > 输入语言热键 > 将 在输入语言之间 的热键调整为 左Alt+Shift
    image

该版本运行逻辑

  • 每隔指定时间更新一下窗口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
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment