2009-09-21 조합중인 한글 표시. 대소문자 구분. 커서키 입력처리.
(여기서부턴 반말이예용)
우
선 생각은 아침에 문득 , 키보드 후킹을 통한 입력을 이용해서 지금의 Copy&Paste작업을 없엘 수 있지 않을까에서
였다. 3년쯤전에 Trader를 만들어볼까 하고 Socket Hooking이랑 Keyboard Hooking자료를 좀 구해놓고
테스트까진 했었는데.. 그 예제를 다시꺼내서 우선 매온에서 키보드 입력을 받을 수 있는지 부터 확인했다.
키보드 후킹 예제 (
http://guyya.tistory.com/10)
하지만 키보드 후킹은 매온에서 막혀있는듯하다. 후킹은 성공하지만 어떤 메시지도 오지 않는다. 그래서 일단 방향을 선회해서 직접적인 윈도우 메시지를 받는 법을 사용했다.
DLL
Injection으로 , 매직클라이언트의 프로세스 내로 침투해서 , FindWindow로 윈도우 핸들 얻은다음에 ,
GetWindowLong & SetWindowLong 으로 WndProc를 바꿔치기 , 윈도우가 받는 모든 메시지를
중앙통솔할수있게 되기 땜에. 거기서 직접 클라이언트로 Paste메시지를 보낼 수 있으면 외부에서 클립보드를 세팅해서 원하는
스트링을 집어넣는게 가능할거란 생각이 들었다.
그래서 클립보드 예제를 뒤져보니까. Paste할때 WM_PASTE메시지가 간다는데.. 그래서 PostMessage해보니....니미 - -... 왜 안돼
결국 삽질끝에 WM_CHAR메시지에 22 ( 0x16 )키의 정보가 가면 클라이언트 내부에서 Paste를 수행하는것을 발견. 클립보드에 데이타 세팅하고 클라이언트로 페이스트 메시지 보내는 것에 일단 성공.
템플릿으로 와이드버젼을 만들었음.
HANDLE _setclipboardData( const char * pStr , HGLOBAL hMem ){ return SetClipboardData( CF_TEXT , hMem );}
HANDLE _setclipboardData( const wchar_t * pStr , HGLOBAL hMem ){ return SetClipboardData( CF_UNICODETEXT , hMem );}
template< class WCHAR >
void SendStringToClient( HWND hWnd , const WCHAR * pStr )
{
OpenClipboard( NULL );
HGLOBAL hMem;
WCHAR* pMem = NULL;
int nLen= 0;
// wcslen
const WCHAR * p = pStr;
while( *p++ )nLen ++;
hMem = GlobalAlloc( GHND | GMEM_DDESHARE | GMEM_MOVEABLE | GMEM_ZEROINIT
, sizeof( WCHAR ) * ( nLen + 1 ) );
pMem = static_cast<WCHAR *>( GlobalLock(hMem) );
//wcscpy(pMem,pStr);
for( int i = 0 ; i < nLen + 1 ; i ++ )
{
pMem[ i ] = pStr [ i ];
}
GlobalUnlock(hMem);
EmptyClipboard();
HANDLE handle = _setclipboardData( pStr , hMem);
if( handle )
{
// Paste....
::PostMessage( hWnd , WM_CHAR , 22 , 0 );
}
else
{
::MessageBox( NULL , L"클립보드 올리기 실패!" , L"-_-", MB_OK );
}
CloseClipboard();
}
인자들 몰라서 대충넣은것들은 넘어가주시고. 여튼 보낼 수 있는건 알았는데. 문제는 한글 입력을 어떻게 받지 -_- 였다. 이걸 어쩌나..
그전에 뭔가 좀 이쁘게 보여주기 위해서 윈도우에 붙은 기생 윈도우로 현새 글자 조합되는걸 보여주고 싶었는데, Create는 되는데 금방 펑하고 사라지는게 -_- 뭐가 문젠지 모르겠어서 조금 하다가 포기.. IME로 넘아감.
고
민하다가... 일단 클라이언트에서 IME메시지를 처리할수 있는지부터 확인했다. 각종 IME 메시지프로시져에 등록하고
확인했으나.. 낑.. 전혀 안온다. 하지만 WM_KEYDOWN에서 한영전환 정도는 확인이 가능했다. 이게 어디냐.
한영전환 상태확인 + 키입력 정보 알수 있음 ---> 이걸로 한글변환 가능하냐의 문제다.
이건 고전적인 문제로 한글 오토마타를 구현해서 직접 한글을 조합하는 방법으로 해결이 가능하다. 여기서 한글오토마타 구현한 예제를 찾아 인터넷 서핑.
딱
적당한 파이선 예제를 발견
(
http://totala.info/?module=file&act=procFileDownload&file_srl=6474&sid=73413a7e0f5bfd63659ea21cd9acbd51)
한시간쯤 노가다로 파이썬을 C++로 전환 ( 전에 파이썬 공부해두길 잘했어 ).
사소한 버그를 수정하고 테스트
니미 ;;
왜 안나오는거지 한참 뒤져보니. 소스자체가 조합형 한글을 조합하는거라 완성형으로 변환이 필요함을 발견.
웹서핑..
http://lucene.egloos.com/1499281
딱 좋은 조합형->완성형 테이블을 발견.. (감사)
해서 기술적인 문제는 다 해결함..
그뒤론 사소한 노가다들 -_-;;;;
특히 저 완성형 변환 테이블이 완전한게 아니라서.. 안나오는 글자를 발견할때 마다 Case by Case로 코드를 추가했다.
여튼 필요로하던 유틸을 직접 만들어서 기분이 좋음.
아쉬운점은 IME_COMPOSIONG을 보여주질 못한다는건데.. 이것도 기술적인건 다 알고 있으니까 조금만 노가다 하면 될거 같은데.. 담에 시간나면 하지 뭐.. (기부하는 사람있으면 좀더 생각해보고 - -;; )..
개발 시간은 한 5~6시간 정도 -_-;;
추가로 조합형 출력을 위해서 퍼온 한글 라이브러리를 개조해서 , 완성된 글자가 나오면 그만큼 키보드 버퍼를 날리는 방식으로 개조하고 , 화면에 출력되는건 그냥 찍은다음에 조합글자를 지우는 방식으로 구현.. (완존 꼼수)
2009/09/25
패치되면서 하드코딩된 윈도우 네임때문에 못찾던 버그수정.."Magic Online v3" 까지만 검색해야하는데 런쳐에서는 그렇게 해놓고 DLL안에서 안하는 -_-.. 정신줄 놓은 시츄에이션.
어차피 안되니까 다들 새로받아야할테니 이기회에 입력 오류생기던걸 좀 손봤는데..
매온 클라이언트에 케릭터메시지가 버퍼링되면 무시해버리는 기능이 있는지 , 연속으로 보내면 처리가 안된다. 그래서 블러킹되는 메시지는 큐잉해서 순차적으로 처리하게 하긴 했는데... 문제는 순차적으로 해서 글자를 보내도 빠지는게 가끔 생김.. 그냥 좀 불편하지만 고고싱 해야하지 않을까함..지금 구조상은 이정도 까지가 한계인듯.
클라이언트 내부에서 글자를 렌더링 하는 루틴을 찾아서 개조하는 방법도 있는데 , 이건 좀 노가다가 심해서 안할듯..
2009/10/17
Zendikar 나왔는데 , 돈없어서 손가락만 빨다가 .. 문득 기존부터 계속 속썩이던 글자 빠지거나 겹치는 문제가 떠올랐는데.. 그 구조 자체가 클립보드를 이용한 전송이었기때문에 생기는 구조적인 문제임을 발견..
그럼 다른데선 어떻게하지?.. 그냥 WM_CHAR로 못보내나?
Spy를 사용해서 메시지를 들어가는걸 보니 , 멀티바이트를 순서대로 보내면 알아서 조합이 되나보다. 니미 ;; . 코드 테스트 해보니까 확실. 그래 이거다.
void SendStringWithWM_CHAR( HWND hWnd , const char * p )
{
int nLen = strlen( p );
for( int i = 0 ; i < nLen ; i ++ )
{
char nChar = p[ i ];
DWORD dw = 0;
char *pDW = ( char * ) &dw;
pDW[ 0 ] = nChar;
::PostMessage( hWnd , WM_MAGOJA , dw , 0x00000001 );
}
}
근데 글자가 깨진다. 왜이런지 해결하는데 5시간 걸림.
결국, Unicode모드에서 MBC모드간에 차이로 결론이 났다. PostMessage에서 WM_CHAR로 넘어가는 메시지는 그 코드셋에 따라서 변경이 생긴다는 사실을 아는데 5시간이 .. 털썩..
이거 해결할려고 따로 메지시 만들어서 포워딩하는것까지 하는 삽질을 했었음..
단지 프로젝트 설정문제임이 밝혀져서.. 2시간에 끝날일이 7시간걸려버렸음.. 젠장;;
어쨌든,, 가끔 있을 업데이트를 위한 버젼 확인 기능 추가..
homepage 위에다가 주석으로 버젼 기입해놓고 그걸 읽는 방식을 사용함.
그나저나 이거 만들고보니 위에 클립보드 로 보내는 삽질한게 무척 부끄럽군 -_-;;;