티스토리 뷰


이번에 환이매크로를 만들면서 고민햇던것이, 게임이 아닌 단순한 글을 쓸 수 있는 에딧박스라면 keybd_event함수를 이용하지않고서 SendMessageWM_CHARWM_IME_CHAR메세지만 날려주면 문자열을 입력하는 효과를 줄 수 있다. 하지만 게임에서 SendMessagePostMessage같은 함수들은 엔프로텍트나 각종 가드프로그램에서 막아버린다.
또한 막지 않는다고 해도 게임속 에딧박스의 핸들을 얻을 수 있는 방법을 찾을수가 없엇다.

따라서 게임을 창모드로 하고서 keybd_event함수를 이용하면 키입력이 가능하다는것을 알아냇다.
그래서 keybd_event 함수를 이용하여 타이핑하는 효과를 주엇더니 원하는 결과가 나왔다.
하지만 여기서 문제가 하나 발생햇는데, 영문을 타이핑할때는
keybd_event(영문의 가상키코드, 0, 0, 0); 하면 키다운메세지가 잘 전달되고 영문도 잘 찍히는데 문제는 한글에 있었다.
한글에서 "환" 이라는 글자를 보자. 저 글자를 치기위해서는 "ㅎㅗㅏㄴ"이라는 4개의 키 입력이 필요하다.
한마디로 keybd_event함수를 4번 호출해야(키업함수까지 8개) "환" 이라는 한글자가 화면에 타이핑 된다는 이야기다.

그래서 여기저기 알아본결과 한글의 자모를 유니코드상에서 분리할 수 있는 방법을 찾아냇다.
일단 알아야할것은 완성형 한글 유니코드값을 만드는 방법이다. 완성형을 만드는 방법을 알면 도식에서 초성 중성 종성을 알아내는 도식을 도출해내는것은 간단하다.

유니코드 완성형 코드
유니코드 완성형 값 = ( ( ( 초성 * 21 ) + 중성 ) * 28 ) + 종성 + 0xAC00

여기서 초성, 중성, 종성에 들어갈 값들은 다음과 같다.

초성[0~19] =
{L'ㄱ', L'ㄲ', L'ㄴ', L'ㄷ', L'ㄸ', L'ㄹ', L'ㅁ', L'ㅂ', L'ㅃ', L'ㅅ', L'ㅆ', L'ㅇ', L'ㅈ', L'ㅉ', L'ㅊ', L'ㅋ', L'ㅌ', L'ㅍ', L'ㅎ'};

중성[0~21] =
{L'ㅏ', L'ㅐ', L'ㅑ', L'ㅒ', L'ㅓ', L'ㅔ', L'ㅕ', L'ㅖ', L'ㅗ', L'ㅘ', L'ㅙ', L'ㅚ', L'ㅛ', L'ㅜ', L'ㅝ', L'ㅞ', L'ㅟ', L'ㅠ', L'ㅡ', L'ㅢ', L'ㅣ'};

종성[0~28] =
{L'x', L'ㄱ', L'ㄲ', L'ㄳ', L'ㄴ', L'ㄵ', L'ㄶ', L'ㄷ', L'ㄹ', L'ㄺ', L'ㄻ', L'ㄼ', L'ㄽ', L'ㄾ', L'ㄿ', L'ㅀ', L'ㅁ', L'ㅂ', L'ㅄ', L'ㅅ', L'ㅆ', L'ㅇ', L'ㅈ', L'ㅊ', L'ㅋ', L'ㅌ', L'ㅍ', L'ㅎ'};

여기서 종성 0번째 'x'는 종성이 존재하지 않는것을 뜻한다.

초성 중성 종성의 코드값을 알아내는 방법은 다음과 같다.

(초성인덱스) = ((유니코드 완성형 값)-0xAC00)/(28*21)
(중성인덱스) = ((유니코드 완성형 값)-0xAC00%(28*21))/28)
(종성인덱스) = ((유니코드 완성형 값)-0xAC00)%28


이것과 같은방법으로 한글유니코드의 한글자를 넣으면 자모로 분리하여 최대 3개의 값을 가지는 배열로 리턴하는 함수를 만들어 봣다.


이 함수는 HangulDisassemble(L'환');
이렇게 호출하면 {ㅎ, ㅘ, ㄴ} 이렇게 총 3의 길이를 가지는 문자열로 리턴한다.

그런데 궁극적인 목표인 keybd_event함수로 저 한글을 쓰려면 저것만으로는 할 수 없다.
저렇게 분해된 자모를 다시 키보드의 배열에 맞는 영문자로 치환해야 한다.
유니코드 한글 한글자를 인수로 주면 키보드에 있는 자모와 매칭되는 영문자문자열을 리턴하는 함수를 만들었다.




이 함수는 ReplacementHangulFragment(L'환');
이렇게 호출하면 {g, hk, s} 이렇게 총 4의 길이를 가지는 문자열로 리턴한다.
이 함수에서 중요한 부분은 ㅒ나 ㅖ와 같이 쉬프트를 누르고 써야하는 문자들은 대문자영문자로 치환하여 보여준다.

이제 한글을 영문자로 치환하는 단계까지 완료 했으니, 영문자 문자열을 인수로 주면 그 값들을 keybd_event해주는 함수를 만들어야한다.

나는 다음과 같이 만들엇는데, 내가 생각해도 많이 조잡하다.
여기서 핵심은 대문자 A~Z는 쉬프트를 누른상태에서 입력이 이루어진다는 부분이다. 한글에서도 이 부분이 없으면 원하는 결과를 얻을 수 없기때문에 꼭 필요하다. CAPSLOCK를 누르는 방법도 생각해 봣으나, 한글에서는 작동을 하지 않기 때문에 패스햇다.

소스는 다음과 같다. 인수로 영문자열 + 특수문자 + 숫자 등을 주면 그 문자열들을 그대로 타이핑 해주는 함수다.



이제 지금까지 만든 함수들을 이용하여 (영문자 + 한글 + 특수문자 + 숫자) 가 섞인 문자열을 인수로 줘도 문제없이 타이핑하는 함수를 만들어보자.
여기서 처음에 만든 한글 자모를 분리하여 리턴하는 함수는 필요가 없다. 타이핑을 하기 위해서는 영문자로 치환된값만 필요하기 때문..


이 소스에서 if( Message[i] >= 0xAC00 && Message[i] <= 0xD7A3 ) 이부분은 한글인지 검사하는 부분이다.
대충 검색해보니까 유니코드 한글범위가 저거라고 해서 걍 해봣는데 잘 되길래 놔둿다.

근데 이 함수를 만들면서 아쉬웟던점이 keybd_event 함수의 한/영키는 그때그때 상황에 따라 달라진다는 것이엇다.
그래서 imm32.lib를 추가하고 imm관련 함수들을 이용하여 조작하려 햇지만 현재 자신윈도우의 한/영 상태의 조사, 조작이 가능햇지만 다른 윈도우는 불가능했다...

그래서 임시방편으로 현재 한/영키의 상태가 [한글]상태인것으로 가정하고 영타를 쓸때는 한영키를 한번 눌러주고 쓰게 만들어 놧다.

매크로기능 하나를 추가하려고 하면 정말 힘들다.. 그런데 이러면서 많은 공부가 되는것 같다..

댓글
  • 프로필사진 궁금 static const int CommonNumber = Character - 0xAC00;
    여기 라인에서 Character은 뭔가요? 정의되는 부분이 없어서 에러가 발생하는데요 ㅠㅠ
    2014.03.28 18:39
  • 프로필사진 Favicon of https://wmmu.tistory.com BlogIcon 모카쨩 정말 소름끼치는 노가다네요;; 한글이 컴퓨터쪽에서는 골칫덩어리 언어죠 많은 공부하고 갑니다 2016.02.18 16:28 신고
  • 프로필사진 엑셀 어려버 vba 껀가요? 아님 c언어인가요?
    vba 로 이걸 쓰고 싶은데 혹시 이 코드를 vba용으로 변환할수 있을까요?
    2017.08.24 14:00
  • 프로필사진 두리안 저도 vba로 한글을 다른 프로그램에 타이핑 하고 싶은데 어렵네요 2018.02.02 15:01
댓글쓰기 폼