From c4784d460f2661002ca58c52fa06641c165add20 Mon Sep 17 00:00:00 2001 From: codepage949 Date: Sat, 11 Jun 2022 16:17:34 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20locale=20=EC=8B=9D=EB=B3=84=EC=9E=90?= =?UTF-8?q?=EA=B0=80=20ko-KR=EC=9D=BC=20=EA=B2=BD=EC=9A=B0=EC=97=90?= =?UTF-8?q?=EB=A7=8C=20=EC=96=B8=EC=96=B4=20=EB=B3=80=EA=B2=BD=20=EC=9E=91?= =?UTF-8?q?=EC=97=85=20=EC=A7=84=ED=96=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib.go | 23 +++++++++++++++-------- winapi/const.go | 30 +++++++++++++++--------------- winapi/winapi.go | 45 +++++++++++++++++++++++++++++++++++---------- 3 files changed, 65 insertions(+), 33 deletions(-) diff --git a/lib.go b/lib.go index d967197..e613d9c 100644 --- a/lib.go +++ b/lib.go @@ -20,23 +20,30 @@ func keyboardHook(nCode int32, wParam uintptr, lParam unsafe.Pointer) uintptr { } } else if wParam == winapi.WM_KEYUP { if lShiftAlone { - // https://stackoverflow.com/questions/64280975/immgetcontext-returns-zero-always + // NOTE: https://stackoverflow.com/questions/64280975/immgetcontext-returns-zero-always hwnd := winapi.ImmGetDefaultIMEWnd(winapi.GetForegroundWindow()) - // COMPOSITIONFORM에 사용하는 CFS_EXCLUDE에 대한 참고 자료가 없으나 실제로 해보면 composition window가 나타나지 않음 - cf := winapi.COMPOSITIONFORM{Style: winapi.CFS_EXCLUDE} - _ = winapi.SendMessage(hwnd, winapi.WM_IME_CONTROL, winapi.IMC_SETCOMPOSITIONWINDOW, uintptr(unsafe.Pointer(&cf))) - mode := 1 ^ winapi.SendMessage(hwnd, winapi.WM_IME_CONTROL, winapi.IMC_GETCONVERSIONMODE, 0) - _ = winapi.SendMessage(hwnd, winapi.WM_IME_CONTROL, winapi.IMC_SETCONVERSIONMODE, mode) + tid := uint32(winapi.GetWindowThreadProcessId(hwnd, 0)) + lid := winapi.GetKeyboardLayout(tid) + + // NOTE: https://docs.microsoft.com/ko-kr/windows/win32/api/winuser/nf-winuser-getkeyboardlayout?redirectedfrom=MSDN#return-value + // locale 식별자가 ko-KR일 경우에만 언어 변경 작업 진행 + if lid&0xFFFF == 0x0412 { + // NOTE: COMPOSITIONFORM에 사용하는 CFS_EXCLUDE에 대한 참고 자료가 없으나 실제로 해보면 composition window가 나타나지 않음 + cf := winapi.COMPOSITIONFORM{Style: winapi.CFS_EXCLUDE} + _ = winapi.SendMessage(hwnd, winapi.WM_IME_CONTROL, winapi.IMC_SETCOMPOSITIONWINDOW, uintptr(unsafe.Pointer(&cf))) + mode := 1 ^ winapi.SendMessage(hwnd, winapi.WM_IME_CONTROL, winapi.IMC_GETCONVERSIONMODE, 0) + _ = winapi.SendMessage(hwnd, winapi.WM_IME_CONTROL, winapi.IMC_SETCONVERSIONMODE, mode) + } } } } else { - if wParam&0x1 == 0 { // WM_*DOWN + if wParam&0x1 == 0 { // NOTE: WM_*DOWN if !otherPressedMap[kb.VkCode] { lShiftAlone = false otherPressedCount += 1 otherPressedMap[kb.VkCode] = true } - } else { // WM_*UP + } else { // NOTE: WM_*UP if otherPressedMap[kb.VkCode] { otherPressedCount -= 1 otherPressedMap[kb.VkCode] = false diff --git a/winapi/const.go b/winapi/const.go index 639e1d9..6e1ff29 100644 --- a/winapi/const.go +++ b/winapi/const.go @@ -15,8 +15,8 @@ type MSG struct { } type INPUTUNION struct { - _ [20]byte // fixed - _ uintptr // non-fixed + _ [20]byte // NOTE: fixed + _ uintptr // NOTE: non-fixed } type INPUT struct { @@ -36,24 +36,24 @@ type KBDLLHOOKSTRUCT struct { } type COMPOSITIONFORM struct { - Style uint8 - _ [192]byte + Style uint8 + _ [192]byte } type Hookproc func(int32, uintptr, unsafe.Pointer) uintptr const ( - INPUT_KEYBOARD = 1 - WH_KEYBOARD_LL = 13 - VK_LSHIFT = 0xA0 - VK_HANGUL = 0x15 - KEYEVENTF_KEYUP = 0x2 - WM_KEYDOWN = 0x100 - WM_KEYUP = 0x101 - WM_IME_CONTROL = 0x283 + INPUT_KEYBOARD = 1 + WH_KEYBOARD_LL = 13 + VK_LSHIFT = 0xA0 + VK_HANGUL = 0x15 + KEYEVENTF_KEYUP = 0x2 + WM_KEYDOWN = 0x100 + WM_KEYUP = 0x101 + WM_IME_CONTROL = 0x283 IMC_GETCOMPOSITIONWINDOW = 0xB IMC_SETCOMPOSITIONWINDOW = 0xC - IMC_GETCONVERSIONMODE = 1 - IMC_SETCONVERSIONMODE = 2 - CFS_EXCLUDE = 0x80 + IMC_GETCONVERSIONMODE = 1 + IMC_SETCONVERSIONMODE = 2 + CFS_EXCLUDE = 0x80 ) diff --git a/winapi/winapi.go b/winapi/winapi.go index 1b1ec63..cae7b38 100644 --- a/winapi/winapi.go +++ b/winapi/winapi.go @@ -1,4 +1,4 @@ -// ref https://play.golang.org/p/2JzHDalGN7Q +// NOTE: https://play.golang.org/p/2JzHDalGN7Q package winapi import ( @@ -7,12 +7,14 @@ import ( ) var ( - user32 = syscall.NewLazyDLL("user32.dll") - _GetMessage = user32.NewProc("GetMessageA") - _SetWindowsHookExA = user32.NewProc("SetWindowsHookExA") - _CallNextHookEx = user32.NewProc("CallNextHookEx") - _GetForegroundWindow = user32.NewProc("GetForegroundWindow") - _SendMessage = user32.NewProc("SendMessageW") + user32 = syscall.NewLazyDLL("user32.dll") + _GetMessage = user32.NewProc("GetMessageA") + _SetWindowsHookExA = user32.NewProc("SetWindowsHookExA") + _CallNextHookEx = user32.NewProc("CallNextHookEx") + _GetForegroundWindow = user32.NewProc("GetForegroundWindow") + _SendMessage = user32.NewProc("SendMessageW") + _GetKeyboardLayout = user32.NewProc("GetKeyboardLayout") + _GetWindowThreadProcessId = user32.NewProc("GetWindowThreadProcessId") ) func GetMessage(m *MSG, hwnd uintptr, wMsgFilterMin, wMsgFilterMax uint32) int32 { @@ -48,13 +50,36 @@ func SendMessage(hwnd uintptr, msg uint32, wparam, lparam uintptr) uintptr { return r } +func GetKeyboardLayout(idThread uint32) uintptr { + r, _, _ := _GetKeyboardLayout.Call(uintptr(idThread)) + + return r +} + +func GetWindowThreadProcessId(hwnd uintptr, processId uintptr) uintptr { + r, _, _ := _GetWindowThreadProcessId.Call(hwnd, processId) + + return r +} + var ( - imm32 = syscall.NewLazyDLL("imm32.dll") - _ImmGetDefaultIMEWnd = imm32.NewProc("ImmGetDefaultIMEWnd") + imm32 = syscall.NewLazyDLL("imm32.dll") + _ImmGetDefaultIMEWnd = imm32.NewProc("ImmGetDefaultIMEWnd") ) func ImmGetDefaultIMEWnd(hwnd uintptr) uintptr { r, _, _ := _ImmGetDefaultIMEWnd.Call(hwnd) return r -} \ No newline at end of file +} + +var ( + kernel32 = syscall.NewLazyDLL("kernel32.dll") + _GetCurrentThreadId = kernel32.NewProc("GetCurrentThreadId") +) + +func GetCurrentThreadId() uintptr { + r, _, _ := _GetCurrentThreadId.Call() + + return r +}