Q&A

  • 간접적으로 한글 입력....
메모 컴포넌트 같은 텍스트 입력이가능한 컴포넌트에 한글입력을

간접적으로 할수 있는 방법을 알고 싶습니다.

예를 들어'델파이'를 입력하는데...

먼저 메모장에 'ㄷ' 자가 출력되고 'ㅔ'를 보내면 '데' 이되고

그 다음에 'ㄹ'를 보내어 '델'자가 완성되도록 하고 싶은데..

가능한가요?

나머지 '파이'도 같은 형식으로 출력 되도록 하려하는데..

윈도우의 SendMessaga() 를 응용해 봤는데 쉽지 않더군요...

1  COMMENTS
  • Profile
    이정욱 1999.07.09 01:38
    민성기님의 글을 퍼왔습니다.



    화면 키보드 만들기.



    안녕하세요. 민성기 입니다.

    사진 자판기 같은 공중용 컴퓨터, “키오스크”에 조이스틱이 아닌 터치 스크린이 적용되는 예가 점차 늘어나고 있습니다. 이번 모임에서는 터치 스크린을 통해 사용자의 키 입력을 받아들일 수 있도록 화면 키보드를 구성하는 방법에 대해 살펴보도록 하겠습니다.



    키보드 갈구리를 이용한 키 값 얻기 유틸리티.

    예전 질/답란에는 가끔씩 화살표 키 등의 키 값이 무엇인지를 묻는 계시물들이 올라왔었습니다. 윈도우에는 ‘가상키’라는 상수들이 잘 정의되어 있으므로 이것을 사용해도 되겠지만, 저처럼 두뇌활동이 황혼기에 접어드는 사람들은 이 값들과 실제 키를 외우는 것 또한 보통 문제가 아닙니다.

    따라서 강좌란의 ‘갈구리질’에 대한 복습도 할 겸, 키보드 갈구리질을 이용해 눌려진 키 값을 알 수 있는 간단한 유틸리티를 만들어 보겠습니다.

    키보드의 갈구리 프로시저는 도움말에 다음과 같이 설명되어 있습니다.



    LRESULT CALLBACK KeyboardProc(

    int code, // hook code

    WPARAM wParam, // virtual-key code

    LPARAM lParam // keystroke-message information

    );



    키가 눌리면 wParam에 가상 키 값이, lParam에 기타 정보가 들어오게 됩니다. 다음은 키 값 알기 유틸리티가 사용하는 키보드 갈구리 프로시저 입니다. 키보드를 누를 때 마다 키 값과 기타 정보값을 화면에 표시하고 있습니다. 갈구리의 사용법에 대한 자세한 내용은 강좌란의 “민성기도 하는 훅킹” 강좌를 참고 하세요.



    var

    KeybdHook : HHook;



    function KeybdHookProc(Code : Integer; wParam: WPARAM; lParam: LPARAM)

    : LongInt; stdcall;

    begin

    if Code >= 0 then

    with KeyValueForm do

    begin

    Label1.Caption := Format('wParam : %d', [wParam]);

    Label2.Caption := Format('lParam : %d', [lParam]);

    ListBox1.Items.Add(Format('%d, %d', [wParam, lParam]));

    ListBox1.ItemIndex := ListBox1.Items.Count -1;

    end;

    Result := CallNexthookEx(KeybdHook, Code, wParam, lParam);

    end;



    procedure TKeyValueForm.FormCreate(Sender: TObject);

    begin

    KeybdHook :=

    SetWindowsHookEx(

    WH_KEYBOARD,

    KeybdHookProc,

    HInstance,

    GetCurrentThreadID

    );

    end;



    procedure TKeyValueForm.FormDestroy(Sender: TObject);

    begin

    UnHookWindowsHookEx(KeybdHook);

    end;





    키보드 이벤트 함수.

    윈도우에는 키보드의 동작을 에뮬레이트 하는 Keybd_Event() API가 준비되어 있습니다. 다음 함수는 이 API를 이용해 키값을 발생시키는 동작을 합니다.



    procedure SimulateKeyDown(VirtualKey : Byte); // 키의 down

    begin

    keybd_event(

    VirtualKey,

    MapVirtualkey(VirtualKey, 0),

    0, 0

    );

    end;



    procedure SimulateKeyUp(VirtualKey : Byte); // 키의 up

    begin

    keybd_event(

    VirtualKey,

    MapVirtualkey(VirtualKey, 0),

    KEYEVENTF_KEYUP,

    0

    );

    end;





    다음은 이 함수를 이용해 실제 'A'키를 발생시키는 예 입니다.



    procedure TForm1.SpeedButton1Click(Sender: TObject);

    begin

    SimulateKeyDown(Ord('A'));

    SimulateKeyUp(Ord('A'));

    end;



    쉬프트 키와 함께 누르는 경우는 다음과 같이 해 주면 됩니다.



    procedure TForm1.SpeedButton1Click(Sender: TObject);

    begin

    SimulateKeyDown(VK_SHIFT);

    SimulateKeyDown(Ord('A'));

    SimulateKeyUp(Ord('A'));

    SimulateKeyUp(VK_SHIFT);

    end;



    다음 화면은 위의 함수를 이용해 화면 키보드를 구성한 것 입니다. 각 버튼은 SpeedButton을 사용해 Tag프로퍼티에 적절한 키 값을 넣었고 Shift, Ctrl, Alt키는 토글 방식으로 구성하였습니다.



    procedure TForm1.KeyBtnClick(Sender: TObject);

    begin

    if ShiftBtn1.Down or ShiftBtn2.Down then

    SimulateKeyDown(VK_SHIFT);

    if CtrlBtn1.Down or CtrlBtn2.Down then

    SimulateKeyDown(VK_CONTROL);

    if AltBtn1.Down or AltBtn2.Down then

    SimulateKeyDown(VK_MENU);



    SimulateKeyDown(TSpeedButton(Sender).Tag);

    SimulateKeyUp(TSpeedButton(Sender).Tag);



    if ShiftBtn1.Down or ShiftBtn2.Down then

    SimulateKeyUp(VK_SHIFT);

    if CtrlBtn1.Down or CtrlBtn2.Down then

    SimulateKeyUp(VK_CONTROL);

    if AltBtn1.Down or AltBtn2.Down then

    SimulateKeyUp(VK_MENU);

    end;





    한글 깨짐 해결하기.

    위의 화면 키보드는 결정적인 결함을 가지고 있습니다. 한글 모드에서 자/모 조합이 끝나기도 전에 한글이 완성되어 버린다는 것 입니다. 다시 말해 ‘민’이라는 글자를 입력하기 위해 ‘A’, ‘L’, ‘S’키를 차례로 입력하면 결과는 ‘ㅁㅣㄴ’이 되어 버립니다.

    이 현상이 발생하는 원인과 해결 방법은 처음에 만들었던 키값 알기 유틸리티에서 찾을 수 있습니다. 눈 여겨 보신 분은 키값 유틸에서 마우스를 클릭할 때 조금 이상한 값이 발생 하는 것을 보셨을 텐데, wParam이 229이고 lParam이 –2147483647인 값이 그것 입니다. 이렇게 마우스가 눌릴 때 키값이 발생하는 것이 바로 한글 깨짐의 원인이 됩니다.

    글자가 완성되기 전에 다른 키가 눌림으로써 IME는 현재 조합중인 글자의 조합이 끝났다고 생각하게 되고 이 때문에 미완성 한글은 미완성인 채로 조합이 완료되는 것 입니다.

    따라서 키보드 갈구리를 설치하고 이 메시지를 잡아 채 묻어 버리면 한글 조합은 깨지지 않고 유지되게 됩니다.

    참고적으로 각 시스템에서 전역 훅을 걸어 확인해 본 결과, 윈 98용 어플리케이션 윈도우에서 마우스를 누르는 경우 lParam 값은 –2147483647이고 열기 대화상자 같은 공용 다이얼로그 박스에서는 –2013265919가 됩니다. NT에서는 –2147483648라는 값을 갖습니다.

    위의 경우 다음과 같은 키보드 갈구리를 설치하면 한글 깨짐이 사라지게 됩니다.



    function KeybdHookProc(Code : Integer; wParam: WPARAM; lParam: LPARAM)

    : LongInt; stdcall;

    begin

    if Code >= 0 then

    if ((wParam = 229) and (lParam = -2147483647)) then

    begin

    Result := Integer(True);

    Exit;

    end;

    Result := CallNexthookEx(KeybdHook, Code, wParam, lParam);

    end;





    안명호 께서 말씀하시기를...

    > 메모 컴포넌트 같은 텍스트 입력이가능한 컴포넌트에 한글입력을

    > 간접적으로 할수 있는 방법을 알고 싶습니다.

    > 예를 들어'델파이'를 입력하는데...

    > 먼저 메모장에 'ㄷ' 자가 출력되고 'ㅔ'를 보내면 '데' 이되고

    > 그 다음에 'ㄹ'를 보내어 '델'자가 완성되도록 하고 싶은데..

    > 가능한가요?

    > 나머지 '파이'도 같은 형식으로 출력 되도록 하려하는데..

    > 윈도우의 SendMessaga() 를 응용해 봤는데 쉽지 않더군요...