作为一个程序员,尤其是干什么都离不开vim的老码农,输入法的“中文时使用英文标点”功能是必不可少的。它可以让你在编写代码时避免了非常多不必要的中英文切换操作。不过这个功能在编写文档的时候就是个累赘了,中文文档中充斥着英文标点,我想稍微有点要求的公司怕是都是不允许的。于是开启或关闭这个“中文时使用英文标点”的操作就变得有点频繁了。
可惜的是无论是的经典的搜狗输入法还是微软自带的微软输入法都没有实现一个快捷键来实现这个功能的开关操作。最终导致每次在编写文档前我总是需要打开输入法的设置界面,找到“中文件时使用英文标点”的位置,点记那个可恶的开关将其关闭,等到编写代码时又不得不先跑去反向操作一波以重新将这个功能开启。啊~~~,多么反人类的设计!我在忍受了数年这种毫无价值的冗余操作后,终于在一个夜晚实在受不了这个垃圾操作,下定决定要把这个功能给快捷键化。
方法一:
解决的第一个方法自然是尝试找到该功能对应的配置项位置并尝试直接修改该配置来实现这功能的开启和关闭操作,然后尝试使用autohotkey来实现自动化的操作并最终映射到一个快捷键上来完成目标。
经过一番摸索,发现搜狗输入法该配置对应于C:\Users\Administrator\AppData\LocalLow\SogouPY.users\00000001\env.ini中的DefaultSymbol字段,可惜通过手动修改DefaultSymbol值并不能实现的输入法配置的自动更新。
微软输入法该配置记录与注册表的HKEY_CURRENT_USER\SOFTWARE\Microsoft\InputMethod\Settings\CHS\UseEnglishPunctuationsInChineseInputMode项中,通过测试发现使用regedit.exe编辑该值可以实现实时配置更新。但如果使用autohotkey的regWrite函数来操作该值则不会实现配置的实时更新效果。最终测试结果是微软输入法可以通过在autohotkey中前端显示使用cmd调用regedit导入reg文件的方式来完成实时切换, 封装函数类似如下:
SwitchUseEnPunctuation() ; {{{1
{
RegRead, val, HKEY_CURRENT_USER\SOFTWARE\Microsoft\InputMethod\Settings\CHS, UseEnglishPunctuationsInChineseInputMode
if (val)
Run %comSpec% /c "regedit -s d:\home\vimd\include\enp0.reg"
else
Run %comSpec% /c "regedit -s d:\home\vimd\include\enp1.reg"
}
enp0.reg的内容为:
Windows Registry Editor Version 5.00
[HKEY_CURRENT_USER\SOFTWARE\Microsoft\InputMethod\Settings\CHS]
"UseEnglishPunctuationsInChineseInputMode"=dword:00000001
enp1.reg的内容为:
Windows Registry Editor Version 5.00
[HKEY_CURRENT_USER\SOFTWARE\Microsoft\InputMethod\Settings\CHS]
"UseEnglishPunctuationsInChineseInputMode"=dword:00000000
该方法奇葩的地方在于cmd的调用必须使用显示前端方法调用(最终结果就是一个黑框一闪而过),如果使用hide参数来尝试影藏cmd执行期间的弹窗,则实时配置更新效果失效。由于该方法每次切换会有黑框一闪而过(比较恶心)外加日常更加喜欢使用搜狗输入法因最终放弃了该方案。
方法二:
经过一番思索,突然发现可以使用另一个更加通用且取巧的方法来实现这个需求。首先我们知道不管是搜狗还是微软输入法,都有一个切换中英文标点的快捷键,这个快捷键默认基本都是Ctrl+. ,其实这个快捷键在日常使用中也是有点用的,比如你开启了“中文时使用英文标点”的功能。如果偶尔需要输入中文标点,则可以使用Ctrl+.来一次性切换输入的标点类型到中文上。这个快捷键的问题在于它没有持续性,当你切换了一次输入法到英文状态后再切换回来,它总是会将输入的标点类型还原到英文状态(如果开启了“中文时使用英文标点”的功能的话)。
既然问题只是在于没有持续性,那如果每次切换到中文时总是根据是否开启了”中文时使用英文标点“的配置来决定是否额外的多自动输入一个Ctrl+.快捷键操作不就可以实现持续性了吗,事实上,的确可以这么干的。实现流程记录如下:
- 为了方便autohotkey管理输入法,我们需要在语言列表中额外添加“英语(美国)”:

2. 保证中文(简体,中国)语言中的输入法只有搜狗输入法:

3. 搜输入法配置:
a) 保持搜狗输入法默认状态为中文

b) 默认开启“中文时使用英文标点”:

c) 关闭搜狗输入法内部切换到英文状态的shift快捷键以避免切换到中文时意外的切换到了搜狗输入法的英文状态
d) 保证开启了默认的“中英标点切换:Ctrl+句号”:

4. 建立autohotkey脚本,添加中英文输入法切换函数封装,并添加快捷键映射。内容如下:
; 全局坏境设置 ; {{{1
; 以下环境参数必须设置, 否则快捷键设置失效
#UseHook On
Setkeydelay, -1
; 用于记录搜狗输入法中文状态下是否使用中文标点, 默认不使用
ime_us_cn_point := 0
GetIME() ; {{{1
{ ; 获取当前窗口的活动输入法语言布局ID接口, 该接口是为数不多能个正确的查询到输入法语言状态的接口
return DllCall("GetKeyboardLayout", "UInt", DllCall("GetWindowThreadProcessId", "UInt", WinActive("A"), "UInt", 0), "UInt")
}
SwitchIME() ; {{{1
{
global ime_us_cn_point
if (GetIME() = 0x8040804) ; = 0x8040804 = 中文
SendMessage, 0x50, 0, 0x00000409, , A
else
{
SendMessage, 0x50, 0, 0x00000804, , A
if (ime_us_cn_point)
{
sleep 50 ; 休眠50ms以保证100%成功率
Send ^.
}
}
}
SetIMEtoEn() ; {{{1
{ ; SendMessage比发送输入法切换快捷键更加的快速稳定, 0x50=WM_INPUTLANGCHANGEREQUEST
SendMessage, 0x50, 0, 0x00000409, , A
}
SetIMEtoCn() ; {{{1
{ ; SendMessage比发送输入法切换快捷键更加的快速稳定, 0x50=WM_INPUTLANGCHANGEREQUEST
global ime_us_cn_point
SendMessage, 0x50, 0, 0x00000804, , A
if (ime_us_cn_point)
{
sleep 50 ; 休眠50ms以保证100%成功率
Send ^.
}
}
SwitchUseEnPoint() ; {{{1
{
global ime_us_cn_point
if (ime_us_cn_point)
ime_us_cn_point = 0
else
ime_us_cn_point = 1
; msgbox % ime_us_cn_point
Send ^.
}
Shift::SwitchIME() ; 实现Shift按键切换中英输入法
^.::SwitchUseEnPoint() ; 实现 Ctrl+. 切换“中文时使用英文标点”开关效果
至此 autohotkey就实现了使用shift切换中英文输入法,使用 Ctrl+. 切换“中文时使用英文标点”开关效果的功能。之后你只需要让这个autohotkey脚本开机自启动即可(该方法同样适用于微软输入法)。
注意:以上配置的效果是默认总是开启了“中文时使用英文标点”,当需要编写文档时使用 Ctrl+. 关闭“中文时使用英文标点”功能,文档编写完毕后使用 Ctrl+. 切回默认配置。很明显该配置是以编写代码为主的场景中使用的,如果以编写文档为主并希望默认关闭“中文时使用英文标点”则需要做一些相应的修改即可。
本文介绍如何使用autohotkey自动化切换输入法的‘中文时使用英文标点’功能,解决编程时频繁切换的问题。分别探讨了通过修改注册表和利用输入法自带快捷键实现的方法,最终提供了一个适用于编程场景的解决方案。





