Delphi2009、Win7でImeMode制御が?

解決


サトウ  2011-05-30 01:16:30  No: 40562

delphi2009のIME制御についで教えてください。

Win Xp-Pro上でDelphi2009によりFormにEdit1、Edit2を作ります。
Edit1は、英数字のみを入力するため、ImeModeをimDisableに、
Edit2は、全ての文字種を受け入れる為、ImeModeをimDontCareに設定します。

IMEはMsのNatural Input 2002 ver2.1です。
このとき、Edit2でのImeの入力モードがなんであっても、Kanaキーロックがいずれでも
Edit2からEdit1へFocusgが移ると、Edit1でのIMEは、半角英数入力になります。
これは、望んでいる動作です。

ところが、このEXEをWin7のPCへインストールすると
Edit2からEdit1へFocusが移ったときのIMEの入力モードはWin Xpと動作が異なります。

たとえば、
Edit2が、ひらがな入力で、Kanaキーロックが外れているときにEdit1へFocusが移動するとIMEはひらがな入力のままですが、入力は半角英数になります。
また、Edit2が、ひらがな入力で、Kanaキーロックが外れていないときにEdit1へFocusが移動するとIMEはひらがな入力のままで、入力は半角カタカナになってしまいます。

納得いかないのは、Edit1での入力モードの表示が入力値と合っていない。
Kanaキーロックの状態のかかわらず、英数入力にならないの2点です。

これは、自分のPCだけではなく、友人のPCのWin7でも同じになります。

これを、Win Xpと同じように動作するようにするにはどのようにすればよいでしょうか。
よろしくお願いいたします。

                                              サトウ


かず  2011-06-01 05:01:29  No: 40563

私なら
Edit1は、英数字のみを入力するため、ImeModeをimCloseに、
Edit2は、全ての文字種を受け入れる為、ImeModeをimHiraなど頻度の多い状態に設定します。


サトウ  2011-06-01 05:52:34  No: 40564

かずさん  こんばんは

見ていただいてありがとうございます。

でも、ちょっと私が問題としている点とちょっと違っているようです。
ImeModeをimCloseにすると、ユーザーは自分でIMEをOpenできてしまいます。
また、Edit2は、ユーザの好みにによって漢字で入力したり、かなで入力したりと、その人の好みに任せたいと考えていますので、imHiraに決め付けたくないのでimDontCareを選んでいます。

いろいろ、自分でも調べていますが、Keybd_eventコマンドでできるかなと確かめてみましたが、WinXPでは動いてくれますがWin7ではやっぱり望んだようにうごいてくれません。

メーカのHPを見ると、Delphi2010がWin7対応と出ていましたが、そのためでしょうか?

もう少し、自分でも確かめたいと思っています。

                                        サトウ


au  2011-06-01 07:08:18  No: 40565

フォームの変数に
FPrevIME: HIMC;
を追加して、FormのOnCreate辺りで
FPrevIME := ImmAssociateContext(Edit1.Handle, 0);
OnDestroyで
ImmAssociateContext(Edit1.Handle, FPrevIME);

てやれば、とりあえずIMEを無効には出来ますね。ただカナロックに関しては変わらないです。

で、このIMEの挙動に関してはXEでも一緒ですね。


au  2011-06-01 18:52:31  No: 40566

先のやり方だとEditが作り直された時なんかに対応出来ないのと、入れ替えた入力コンテキストが中に浮いちゃうのでまずい気がします。

ちゃんとやるなら、Editを継承したのを作るしかないのかも。SetIMEとResetIMEがvirtualなら良かったんですがね


Quest  2011-06-02 05:30:46  No: 40567

私の場合は、漢字入力を行う可能性があるEdit等からフォーカスが外れる時に
強制的にIMEをオフにしてしまっています。
私もかずさんの様に漢字入力を行う項目ではImeModeをimHiraにしてしまうので
これでも問題はありませんが、サトウさんの場合はEdit2でIMEをオンにした後
Edit1に移動し、さらにEdit2に戻った時にIMEがオンに戻って欲しいのならば
ちょっと工夫がいるかもしれません。
ちなみにIMEをオフにするには下記のイベントをOnExitに割り当てています。
usesにImmの追加が必要です。

  TForm1 = class(TForm)
    Edit1: TEdit;
    Edit2: TEdit;
    procedure CustomEditExit(Sender: TObject);
  private
    { Private 宣言 }
  public
    { Public 宣言 }
  end;

procedure TForm1.CustomEditExit(Sender: TObject);
var
  imc: HIMC;
begin
  imc := ImmGetContext((Sender as TWinControl).Handle);
  if imc <> 0 then
  begin
    if ImmGetOpenStatus(imc) then
      ImmSetOpenStatus(imc, False);
    ImmReleaseContext((Sender as TWinControl).Handle, imc);
  end;
end;


au  2011-06-02 06:30:35  No: 40568

かなり無理矢理ですけど下みたいな感じかな。
TFormの宣言の前に追加してください。

  TEdit = class(StdCtrls.TEdit)
  private
    FOldIMC: HIMC;
    FKanaMode: Boolean;
    procedure WMSetFocus(var Message: TWMSetFocus); message WM_SETFOCUS;
    procedure WMKillFocus(var Message: TWMKillFocus); message WM_KILLFOCUS;
  public
    destructor Destroy; override;
  end;

destructor TEdit.Destroy;
begin
  if FOldIMC <> 0 then
    ImmAssociateContext(Handle, FOldIMC);
  inherited;
end;

procedure TEdit.WMKillFocus(var Message: TWMKillFocus);
begin
  inherited;
  if ImeMode=imDisable then
  begin
    if FOldIMC <> 0 then
    begin
      ImmAssociateContext(Handle, FOldIMC);
      FOldIMC := 0;
      if FKanaMode And ((GetKeyState(VK_KANA) And 1) = 0) then
      begin
        keybd_event(VK_KANA, 0, 0, 0);
        keybd_event(VK_KANA, 0, KEYEVENTF_KEYUP, 0);
      end;
    end;
  end;
end;

procedure TEdit.WMSetFocus(var Message: TWMSetFocus);
begin
  inherited;
  if ImeMode = imDisable then
  begin
    FOldIMC := ImmAssociateContext(Handle, 0);
    FKanaMode := (GetKeyState(VK_KANA) And 1) = 1;
    if FKanaMode then
    begin
      keybd_event(VK_KANA, 0, 0, 0);
      keybd_event(VK_KANA, 0, KEYEVENTF_KEYUP, 0);
    end;
  end else begin
    if FOldIMC <> 0 then
    begin
      ImmAssociateContext(Handle, FOldIMC);
      FOldIMC := 0;
    end;
  end;
end;


サトウ  2011-06-02 07:16:58  No: 40569

AUさん、QUESTさん  ありがとうございます。

今会社から帰ってきたばかりで、確認は明日の晩に行います。
ただ、日曜素人プログラマーには少し難しそうですね。


サトウ  2011-06-03 08:32:31  No: 40570

今日、動きを確認してみました

IMEのOn/Off、Kanaロックとも望んだ動きをしました。ただ、なぜそのように動くかが理解できていませんので、これからHelp等をあさって見ます。

AUさん、QUESTさんありがとうございます。


サトウ  2011-06-04 07:47:46  No: 40571

なんとかAUさんのコードを読み解きました。
しかし、ImmAsociateContextが理解できません。多分IMEの制御情報だろうとおもい、ネットで検索してみましたが、私の理解の範囲を明らかに超えています。これ以上追わないことにします。(笑)

それと、AUさんのコードからコンポーネントを新たに作成しないで、一時的にカスタマイズする方法を知りました。これは私にとって非常に使いでのある手法です。今後使わせていただきます。

AUさん、QUESTさん  ありがとうございます。


au  2011-06-04 08:15:08  No: 40572

一応IMEの表示が変わらない件についてQCに登録しておきました。
http://qc.embarcadero.com/wc/qcmain.aspx?d=94701

Delphi2009はWin7対応してないよって言われちゃったので修正はされないでしょうけど、XEの方は修正して欲しいですねぇ。
カナロックに関しては、XPでもATOKだとロック効いたままになったりしたのでIMEによって動作が違うのかもしれません。


サトウ  2011-06-06 05:28:02  No: 40573

XEとWin7との環境だけでチェックしてくれるようですね。
まあ  しょうがないですね。

でも、ここ数年毎年のようにUpgradeがあると、仕事で使っている人はいいとしても個人的使っている人にはつらいものがあります。
Delphiを使っている人は、Delphiに惚れて使っていることと思われます。Delphiから離れていく人がでないような施策を打ってほしいですね。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加