본문 바로가기

프로그래밍/Delphi

[팁] ActiveX XP에서 한영 전환 안되는 문제 해결책.


[원본]http://www.delphi.co.kr/?mid=lecture&page=24&document_srl=156160

델파이 activeX를 다른 os(win98, win 2k)에서 개발 하면
imeName이 제대로 설정되지 않아서 한영 전환이 안됩니다.

문제는 Screen의 ImeName이 thread기동시에 제대로 설정되지
않아서 이며, 일반적인 프로그램의 경우에는 바르게 작동하는 것으로
보입니다. 이것을 델파이의 문제라 할지 win xp의 문제라 할지
의문입니다.

양쪽다 조금씩 문제점이 존재 한다고 생각됩니다.

가장 쉬운 해결책은 ImeName 속성을 모두다 공백으로 설정하는 것입니다만
이전에 개발한 프로그램의 속성을 모두다 바꾸는 것이 귀찮기도하죠.

다음은 해결 방법입니다.

forms.pas

implementation 앞부분에 다음과 같이 선언합니다.


// bug-fix
procedure RefreshDefaultIme(scr : TScreen);


구현부에는

// bug-fix
procedure RefreshDefaultIme(scr : TScreen);
begin
  if (SysLocale.PriLangID=LANG_KOREAN) and (scr.FDefaultIme='') then
  begin
    scr.FImes.Free;
    scr.FImes := nil;

    scr.FDefaultKbLayout := GetKeyboardLayout(0);
    scr.GetDefaultIme;
  end;
end;


controls.pas에는 다음의 함수에 bug-fix 부분을 추가합니다.


procedure TWinControl.SetIme;
var
  I: Integer;
  HandleToSet: HKL;
begin
  if not SysLocale.FarEast then Exit;
  if FImeName <> '' then
  begin
    RefreshDefaultIme(Screen); // bug-fix
    if (AnsiCompareText(FImeName, Screen.DefaultIme) <> 0) and (Screen.Imes.Count <> 0) then
    begin
      HandleToSet := Screen.DefaultKbLayout;
      if FImeMode <> imDisable then
      begin
        I := Screen.Imes.IndexOf(FImeName);
        if I >= 0 then
          HandleToSet := HKL(Screen.Imes.Objects[I]);
      end;
      ActivateKeyboardLayout(HandleToSet, KLF_ACTIVATE);
    end;
  end;
  SetImeMode(Handle, FImeMode);
end;


procedure TWinControl.ResetIme;
begin
  if not SysLocale.FarEast then Exit;
  if FImeName <> '' then
  begin
    RefreshDefaultIme(Screen); // bug-fix
    if AnsiCompareText(FImeName, Screen.DefaultIme) <> 0 then
      ActivateKeyboardLayout(Screen.DefaultKbLayout, KLF_ACTIVATE);
  end;
  if FImeMode = imDisable then Win32NLSEnableIME(Handle, TRUE);
end;

procedure SetImeName(Name: TImeName);
var
  I: Integer;
  HandleToSet: HKL;
begin
  if not SysLocale.FarEast then Exit;
  RefreshDefaultIme(Screen); // bug-fix
  if (Name <> '') and (Screen.Imes.Count <> 0) then
  begin
    HandleToSet := Screen.DefaultKbLayout;
    I := Screen.Imes.IndexOf(Name);
    if I >= 0 then HandleToSet := HKL(Screen.Imes.Objects[I]);
    ActivateKeyboardLayout(HandleToSet, KLF_ACTIVATE);
  end;
end;


DefaultIme명이 제대로 설정되었는가 확인해보는 작업을 하는 것입니다.
언어 설정이 한글 인 경우만 동작하게 되어있습니다.
다른 언어는 어떻게 될지 몰라서요.

---------------------------------------------------------------
추가적으로 ImeMode를 변경하면 Focus를 다시 얻을때만 ImeMode를 설정하게 되어있습니다.
이것을 포커스를 가진 상황에서 변경하려면 다음 것을 Controls.pas에 넣고
ImeMode를 바꾼다음 불러 주시면 됩니다.

이것은 ActiveX 만의 문제가 아니고 델파이가 그렇게 되어있습니다
참고 하시길 바랍니다.

//선언부에 넣습니다.
// bug-fix
procedure RefreshImeMode(AControl : TWinControl);

// 구현 부에 넣습니다.

// bug-fix
procedure RefreshImeMode(AControl : TWinControl);
begin
  if(AControl.Focused = true) then
          SetImeMode(AControl.Handle, AControl.ImeMode);
end;


-----------------------------------------------------------------
문의 메일이 온 내용에 대한 답변을 추가 합니다.

---------[ 받은 메일 내용 ]----------
> Title : ActiveX에서 한영전환문제 조언 요청
>
> 윈도우XP에서 Delphi6로 ActiveX를 만들었는데 DBEdit나 Edit콤포넌트에서는
> 한델의 팁과 같이 해도 안되는군요.
> 그런데 다른 콤포넌트로 Focus를 옮겼다가 해당 콤포넌트로 다시 오면 한영전환이 됩니다.
> 그래서 DBEdit의 Enter이벤트에서 RefreshImeMode(DBEdit1) 프로시져를 호출해도 안되는군요.
> DB는 PARADOX를 사용했구요 해결방법을 아시면 멜 부탁드립니다.

----------------------------------------------------------------------------------

결국은 타이밍의 문제로 보입니다.
activex가 기동시에 tscreen의 ime를 제대로 지정해야 하는데.
이게 시간적인 여유가 없으면 기동이 완료된 후에 제대로 돌아갑니다.

방법은 3가지가 있다고 보는데요.

1.일단 폼이 뜰때 기본적으로 포커스를 가지는
콘트롤에 imename을 없애주시길 바랍니다.

주의 : 디자인시에 없애 주셔야 합니다.
FormCreate에 넣거나 하면 동작 안하게 됩니다.

(문제가 되는 폼에 콘트롤에 imename을 전체를 다 없애는 것도 괜찮습니다.
귀찮으면 놔두시고요. 어찌히였든 처음 포커스 가지는 콘트롤에 imename을 없애십시요.
버튼 같이 imename이 없는 콘트롤은 당연히 상관없습니다.)

이 경우는 반드시 해결이 되어야 하는 것으로 압니다.

2. 더 극단적인 방법은 소스에서 아예 키보드 레이아웃을 변경하지 않도록하는 것입니다.
VC++의 경우는 키보드 레이아웃을 변경하는 소스 자체가 없습니다.

즉 axctrls.pas 에

ActivateKeyboardLayout

부분을 전체다 코멘트 처리하시면 해결이 됩니다.

3. xp에서 screen에 imemode가 제대로 설정되려면 FormCreate부분에서는
작동되지 않습니다. 따라서 FormCreate에서 PostMessage를 해서
메시지 받는 부분에서 다음 펑션을 불러주면 됩니다.

RefreshDefaultIme(screen);

문제는 포커스를 받은 콘트롤이 ime가 안바뀐다는 건데요.
이건 다른데로 포커스를 주었다가 다시 얻으면 되겠습니다.
입력창이 없는 콘트롤은 그냥 두셔도 됩니다.

권하기로는 1번을 권합니다만.. 문제가 생기면 3번 방법도 병행하시길 바랍니다.

제가 생각하기로는 1번만 적용하셔도 될걸로 압니다.

2번은 극단적이지만 영구적인 해결책이기도 합니다. 다만 원래 델파이 소스를 너무 건드리는 것이
아닌가 하고 권장하지 않습니다.

참고로 말씀드리면 정확치는 않습니다만
이 한영전환 문제는 우습게도 한글 xp에서 나타나는 현상입니다.
즉 영문 xp에 한글 ime를 깔고,한글 환경으로 바꾸는 것 깔고하면
한영전환 잘되는 것으로 기억합니다.