├── AIMSwitcher ├── AIMSwitcher.vcxproj.user ├── AIMSwitcher.vcxproj.filters ├── main.cpp └── AIMSwitcher.vcxproj ├── LICENSE ├── AIMSwitcher.sln └── README.md /AIMSwitcher/AIMSwitcher.vcxproj.user: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /AIMSwitcher/AIMSwitcher.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | 源文件 20 | 21 | 22 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 A23187 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /AIMSwitcher.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.3.32929.385 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AIMSwitcher", "AIMSwitcher\AIMSwitcher.vcxproj", "{A452978C-668D-488B-9DAE-6FCD3B175859}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Debug|x86 = Debug|x86 12 | Release|x64 = Release|x64 13 | Release|x86 = Release|x86 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {A452978C-668D-488B-9DAE-6FCD3B175859}.Debug|x64.ActiveCfg = Debug|x64 17 | {A452978C-668D-488B-9DAE-6FCD3B175859}.Debug|x64.Build.0 = Debug|x64 18 | {A452978C-668D-488B-9DAE-6FCD3B175859}.Debug|x86.ActiveCfg = Debug|Win32 19 | {A452978C-668D-488B-9DAE-6FCD3B175859}.Debug|x86.Build.0 = Debug|Win32 20 | {A452978C-668D-488B-9DAE-6FCD3B175859}.Release|x64.ActiveCfg = Release|x64 21 | {A452978C-668D-488B-9DAE-6FCD3B175859}.Release|x64.Build.0 = Release|x64 22 | {A452978C-668D-488B-9DAE-6FCD3B175859}.Release|x86.ActiveCfg = Release|Win32 23 | {A452978C-668D-488B-9DAE-6FCD3B175859}.Release|x86.Build.0 = Release|Win32 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {2456C611-4886-40EF-A6BA-98508EDF117B} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /AIMSwitcher/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | 6 | #pragma comment(lib, "imm32.lib") 7 | 8 | #define IMC_GETCONVERSIONMODE 0x01 9 | #define IMC_SETCONVERSIONMODE 0x02 10 | 11 | int GetCurrentInputMethod() { 12 | HWND hWnd = GetForegroundWindow(); 13 | DWORD threadId = GetWindowThreadProcessId(hWnd, nullptr); 14 | HKL hKL = GetKeyboardLayout(threadId); 15 | uintptr_t langId = reinterpret_cast(hKL) & 0xFFFF; 16 | return static_cast(langId); 17 | } 18 | 19 | void SwitchInputMethod(int langId) { 20 | HWND hWnd = GetForegroundWindow(); 21 | PostMessage(hWnd, WM_INPUTLANGCHANGEREQUEST, 0, static_cast(langId)); 22 | } 23 | 24 | int GetCurrentInputMethodMode() { 25 | HWND hWnd = GetForegroundWindow(); 26 | HWND hIMEWnd = ImmGetDefaultIMEWnd(hWnd); 27 | LRESULT mode = SendMessage(hIMEWnd, WM_IME_CONTROL, IMC_GETCONVERSIONMODE, 0); 28 | return static_cast(mode); 29 | } 30 | 31 | void SwitchInputMethodMode(int mode) { 32 | HWND hWnd = GetForegroundWindow(); 33 | HWND hIMEWnd = ImmGetDefaultIMEWnd(hWnd); 34 | SendMessage(hIMEWnd, WM_IME_CONTROL, IMC_SETCONVERSIONMODE, static_cast(mode)); 35 | } 36 | 37 | void ShowUsage() { 38 | std::cout 39 | << "AIMSwitcher, An Input Method Switcher\n" 40 | << "Usage: AIMSwitcher [OPTION]... [ARG]...\n" 41 | << "\n" 42 | << " --im [INPUTMETHOD] show the current input method if INPUTMETHOD is omitted,\n" 43 | << " otherwise switch to the specified input method\n" 44 | << " --imm [INPUTMETHODMODE] show the current input method mode if INPUTMETHODMODE is omitted,\n" 45 | << " otherwise switch to the specified input method mode\n" 46 | << std::endl; 47 | } 48 | 49 | int main(int argc, char** argv) { 50 | if (argc == 1) { 51 | ShowUsage(); 52 | } 53 | else if (strcmp(argv[1], "--im") == 0) { 54 | if (argc == 2) 55 | std::cout << GetCurrentInputMethod() << std::endl; 56 | else 57 | SwitchInputMethod(atoi(argv[2])); 58 | } 59 | else if (strcmp(argv[1], "--imm") == 0) { 60 | if (argc == 2) 61 | std::cout << GetCurrentInputMethodMode() << std::endl; 62 | else 63 | SwitchInputMethodMode(atoi(argv[2])); 64 | } 65 | else { 66 | ShowUsage(); 67 | } 68 | return 0; 69 | } 70 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # **AIMS**witcher 2 | **AIMS**witcher, **A**n **I**nput **M**ethod **S**witcher that **AIMS** to support switching between Chinese and English input methods or between Chinese and English modes in one input method when switching between Vim's insert and normal modes 3 | 4 | > Note: This tool is only available for Windows 5 | 6 | ## Installation 7 | Just download the executable file from the [releases page](https://github.com/A-23187/AIMSwitcher/releases/latest) 8 | 9 | ## Usage 10 | ``` 11 | AIMSwitcher, An Input Method Switcher 12 | Usage: AIMSwitcher [OPTION]... [ARG]... 13 | 14 | --im [INPUTMETHOD] show the current input method if INPUTMETHOD is omitted, 15 | otherwise switch to the specified input method 16 | --imm [INPUTMETHODMODE] show the current input method mode if INPUTMETHODMODE is omitted, 17 | otherwise switch to the specified input method mode 18 | ``` 19 | 20 | ### Examples 21 | AIMSwitcher uses the language identifier (i.e., the locale ID) to switch to the corresponding input method. And the locale ID of Simplified Chinese (zh_CN) is 2052, the locale ID of American English (en_US) is 1033. You can use the option `--im` without argument to discover the locale ID of your current input method 22 | ```sh 23 | # show the locale ID of the current input method 24 | AIMSwitcher.exe --im 25 | ``` 26 | 27 | For me, I installed Microsoft Pinyin input method for Simplified Chinese (2052), and US Keyboard input method for American English (1033). So for switching between these two input methods: 28 | ```sh 29 | # switch to Microsoft Pinyin IM 30 | AIMSwitcher.exe --im 2052 31 | # switch to US Keyboard IM 32 | AIMSwitcher.exe --im 1033 33 | ``` 34 | 35 | Microsoft Pinyin IM supports two language modes: Chinese and English. AIMSwitcher can switch between these two modes like below: 36 | ```sh 37 | # switch to Chinese mode 38 | AIMSwitcher.exe --imm 1025 39 | # switch to English mode 40 | AIMSwitcher.exe --imm 0 41 | 42 | # you can use this option without argument to find the key of your current mode 43 | AIMSwitcher.exe --imm 44 | ``` 45 | > Note: The functionality of switching input method mode has only been tested with Microsoft Pinyin IM, and contributions for testing with other input methods are welcome. 46 | 47 | ### AIMSwitcher + Vim 48 | - Switch to English input method when leaving insert mode to normal mode 49 | ```vim 50 | autocmd InsertLeave * silent !AIMSwitcher.exe --im 1033 51 | ``` 52 | - Switch to English mode of Chinese input method instead of switching input method when leaving insert mode to normal mode 53 | ```vim 54 | autocmd InsertLeave * silent !AIMSwitcher.exe --imm 0 55 | ``` 56 | 57 | ### AIMSwitcher + [VSCodeVim](https://github.com/VSCodeVim/Vim) 58 | - Switch input method 59 | ```json 60 | "vim.autoSwitchInputMethod.enable": true, 61 | // Use English input method by default 62 | "vim.autoSwitchInputMethod.defaultIM": "1033", 63 | "vim.autoSwitchInputMethod.obtainIMCmd": "AIMSwitcher.exe --im", 64 | // Switch to English input method when leaving insert mode to normal mode, 65 | // And the additional argument {im} is just a placeholder, as required by VSCodeVim 66 | "vim.autoSwitchInputMethod.switchIMCmd": "AIMSwitcher.exe --im 1033 {im}" 67 | ``` 68 | - Switch input method mode 69 | ```json 70 | "vim.autoSwitchInputMethod.enable": true, 71 | // Use Chinese input method by default (for me, I use Microsoft Pinyin IM) 72 | "vim.autoSwitchInputMethod.defaultIM": "2052", 73 | "vim.autoSwitchInputMethod.obtainIMCmd": "AIMSwitcher.exe --imm", 74 | // Switch to English mode of the Chinese input method when leaving insert mode to normal mode, 75 | // And the additional argument {im} is just a placeholder, as required by VSCodeVim 76 | "vim.autoSwitchInputMethod.switchIMCmd": "AIMSwitcher.exe --imm 0 {im}" 77 | ``` 78 | About VSCodeVim's `autoSwitchInputMethod` feature, find more information [here](https://github.com/VSCodeVim/Vim#input-method) 79 | 80 | ## Credits 81 | - [daipeihust/im-select](https://github.com/daipeihust/im-select) 82 | - [yfzhao20/Shift-IM-for-VSCode](https://github.com/yfzhao20/Shift-IM-for-VSCode) 83 | - [how to change input method when press in vim? - Stack Overflow](https://stackoverflow.com/a/71523260) 84 | 85 | ## License 86 | [MIT License](https://github.com/A-23187/AIMSwitcher/blob/master/LICENSE) -------------------------------------------------------------------------------- /AIMSwitcher/AIMSwitcher.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 16.0 23 | Win32Proj 24 | {a452978c-668d-488b-9dae-6fcd3b175859} 25 | AIMSwitcher 26 | 10.0 27 | 28 | 29 | 30 | Application 31 | true 32 | v143 33 | Unicode 34 | 35 | 36 | Application 37 | false 38 | v143 39 | true 40 | Unicode 41 | 42 | 43 | Application 44 | true 45 | v143 46 | Unicode 47 | 48 | 49 | Application 50 | false 51 | v143 52 | true 53 | Unicode 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | Level3 76 | true 77 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 78 | true 79 | 80 | 81 | Console 82 | true 83 | 84 | 85 | 86 | 87 | Level3 88 | true 89 | true 90 | true 91 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 92 | true 93 | 94 | 95 | Console 96 | true 97 | true 98 | true 99 | 100 | 101 | 102 | 103 | Level3 104 | true 105 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 106 | true 107 | 108 | 109 | Console 110 | true 111 | 112 | 113 | 114 | 115 | Level3 116 | true 117 | true 118 | true 119 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 120 | true 121 | 122 | 123 | Console 124 | true 125 | true 126 | true 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | --------------------------------------------------------------------------------