AutoHotkey 한영 상태 감지하기

오토핫키에서 키보드 매크로(hot string)는 키보드의 한/영 상태를 고려하지 않고 작동하기 때문에, 한/영 상태에 따라서 다른 핫스트링을 정의해야 하는 경우가 있다. 이를 위한 함수 코드가 여러 커뮤니티나 블로그를 통해서 공유되고 있는 걸 줏어서 소개한다. (물론 구글에서 검색해보면 이 글보다는 다른 글들이 먼저 보이니까, 이 글을 보시는 분들은 아마 보셨던 코드일 것이다.)

원리는 대충 윈도 API를 통해 어떤 응용 프로그램 내의 컨트롤에 ‘메시지’를 보내어 원격으로 어떤 기능을 실행할 수 있게 하는 것이 기본적인 아이디어이다. 현재 활성화된 창에서 기본 IME의 상태창을 열도록, 응용 프로그램의 기본 IME 창에게 메시지를 보낸다. 만약 현재 한글 IME가 선택된 경우에는, 이 요청을 처리하지 못하고 에러가 반환되기 때문에 이 메시지의 결과가 실패라면 한글로 선택되어 있다고 상정할 수 있는 것이다.

따라서 이 함수는 크게 두 개의 동작으로 나눠진다.

  1. 현재 창에서 사용하는 기본 IME창의 핸들을 획득한다. (여기에 메시지를 보내야 하므로)
  2. 1에서 획득한 창에 메시지를 보낸다.

코드는 다음과 같다. 원본은 2개의 함수로 나뉘어 있었는데, 사실 간단하게 하나로 합칠 수 있다.

[UPDATE] 윈도11의 22H2 업데이트에서 Microsoft IME가 새로운 버전으로 업그레이드 되었고, 이제 이 함수에서 소개하는 방법으로는 더 이상 정상적으로 한/영 상태를 구분할 수 없다 IMC_OPENSTATUSWINDOW 명령은 최초 영문 상태일 때에만 0을 리턴하며, 한 번이라도 한글로 전환한 이후부터는 한/영 상태에 상관없이 1을 리턴한다. 현재 유일한 대안은 날개셋 IME를 사용하는 것이다.

; for AHK v1.1

IMECheckHangul()
{
  WinGet hWnd, ID, A
  hIME := DllCall("imm32\ImmGetDefaultIMEWnd", "UInt", hWnd, "UInt")
  Temp := A_DetectHiddenWindows
  DetectHiddenWindows ON
  SendMessage 0x283, 0x005, 0, ,ahk_id %IMEWnd%
  Res := ErrorLevel
  if (Temp <> A_DetectHiddenWindows)
    DetectHiddenWindows %Temp%
  return Res <> 0
}

+F1::MsgBox % IMECheckHangul()

이렇게 만든 스크립트를 실행하고 <shift>F1 키를 누르면 한영 상태에 따라서 값이 메시지 박스로 표시된다. 영어일 때 0, 한글일 때 1이면 성공이다.

AHK V2 용 코드

AHK V2가 정식으로 릴리즈 되었다. 많은 분들이 관심을 갖고 보시는 것 같아서, V2용 코드를 추가한다. 이 코드와 관련하여 AHK V2의 변경사항은 다음과 같다.

  1. 모든 “명령”은 함수로 대체되었다. 단, 인자가 없을 때에 괄호는 생략할 수 있다.
  2. 할당 구문은 := 연산자만 사용한다.
  3. 대부분의 구문은 이제 “표현식”으로 인식한다. 문자열은 식별자와 구별하기 위해 따옴표로 감싼다.
  4. WinGet 명령에 1:1로 대응하는 함수는 없다. WinGetID() 를 사용하여 창의 핸들을 얻는다.
  5. SendMessage() 함수는 메시지에서 리턴하는 결과값을 리턴한다.
  6. 예외처리는 try { .. } catch ... { .. } 구문을 통해 처리한다. A_ErrorLevel 내장 변수는 제거되었다.

참고로 함수는 입력방식 관리자(Input Method Manager) 관련한 윈도 API를 사용하는 부분이 있기 때문에, 호출 시마다 내부적으로 imm32.dll 파일을 로드한다. 스크립트의 수명 주기에서 같은 dll을 반복적으로 사용한다면 매번 함수에서 로드하기 보다는 미리 로드했다가, 스크립트가 종료되는 시점에 언로드하는 것이 성능면에서 크게 도움이 된다고 한다.

  1. kernel32.dll 의 LoadLibrary() 를 사용하여 dll 파일을 로드해둔다.
  2. OnExit()를 사용하여 스크립트가 종료되기 직전에 FreeLibrary() 를 사용하여 로드해둔 dll을 언로드한다.

OnExit 명령을 사용하면, 종료 시점에 호출할 함수를 지정할 수 있다. 이 함수에서 “FreeLibrary” 함수를 호출하도록 하여 로드해놓은 dll 파일을 해제해준다.

imm32 := DllCall("LoadLibrary", "Str", "imm32.dll", "Ptr")

IMECheckHangul()  ; 0: 영어, 1: 한글
{
  hWnd := WinGetID("A")   
  ; WinGet 명령은 제거되었고, 창의 핸들을 얻기위해서는 WinGet("A")를 사용한다.
  hIME := DllCall("imm32\ImmGetDefaultIMEWnd", "UInt", hWnd, "UInt")
  temp := A_DetectHiddenWindows
  DetectHiddenWinows(True)
  res := SendMessage(0x0283, 0x0005, 0x0000, , "ahk_id " hIME)
  DetectHiddenWindows(temp)
  return res
}

ExitFunc(ExitReason, ExitCode)
{
  DllCall("FreeLibary", "Ptr", imm32)
}

OnExit("ExitFunc")

Read more

워드프레스에서 고스트로 이전

워드프레스에서 고스트로 이전

이 글을 쓰면서도 믿기 힘든 사실인데, 블로그라는 걸 처음 시작한지가 20년이 되었습니다. 이글루스에서 처음 시작했다가, SK컴즈가 인수한다고 발표함과 동시에 워드프레스로 플랫폼을 옮겼죠. 워드프레스오 옮긴 이후에는 호스팅 환경을 이리 저리 옮기긴 했지만 거의 18년 가까이 워드프레스를 사용해온 것 같습니다. 그 동안 워드프레스는 블로깅 툴에서 명실상부한 범용CMS로 발전했습니다. 사실 웬만한 홈페이지들은 이제

By sooop
띄어쓰기에 대한 생각

띄어쓰기에 대한 생각

업무 메일을 쓸 때 가장 많이 쓰는 말 중에 하나가 메일 말미에 ‘업무에 참고 부탁 드립니다.‘인데요, 어느 날부터 아웃룩에서 이 ‘부탁 드립니다’가 틀렸다고 맞춤법 지적을 하기 시작했습니다. 맞는 말은 ‘부탁드립니다’라고 붙여 쓰는 거라고. 사실 아래아한글 시절부터 이전의 MS워드까지, 워드프로세서들의 한국어 맞춤법 검사 실력은 거의 있으나 마나 한

By sooop

구글 포토에서 아이클라우드로 탈출한 후기

한 때 구글 포토가 백업 용량을 무제한으로 제공해 주겠다고해서, 구글 포토를 사용해서 사진을 백업해왔습니다. 물론 이 이야기의 결말은 저나 이 글을 읽고 있는 여러분이나 모두 알고 있습니다. 사실 AI에게 학습 시킬 이미지 데이터를 모으기 위한 것일 뿐이라거나 하는 이야기는 그 당시에도 있었습니다만, 에이 그래도 구글인데 용량은 넉넉하게 주겠지…하는 순진한

By sooop

Julia의 함수 사용팁

연산자의 함수적 표기 Julia의 연산자는 기본적으로 함수이며, 함수 호출 표기와 같은 방식으로 호출하는 것이 가능합니다. 또한 그 자체로 함수이기 때문에 filter(), map() 과 같이 함수를 인자로 받는 함수에도 연산자를 그대로 적용하는 것이 가능합니다. 특히 + 연산자는 sum() 함수와 같이 여러 인자를 받아 인자들의 합을 구할 수 있습니다. 2 + 3 # = 5 +(2,

By sooop