タッチ操作用ソフトキーボード(カナ漢字変換)を作成するには


60の手習い  2012-04-14 10:05:38  No: 41907

MrXrayさんの「ソフトキーボードもどき」を参考にして、タッチ操作用カナ漢字変換キーボードを作成していますが、タッチ操作をするには変換候補の表示が小さくて使えません。変換候補をListBox等に取込み、大きく表示させる方法を教えてください。OS:Windows7 HomePremium,、Delphi2007です。よろしくお願いします。


Mr.XRAY  2012-04-17 03:17:19  No: 41908

こんにちは,Mr.XRAYです.

IMEの漢字変換で,TListBoxに候補の漢字を表示するサンプルです.

コードの通りで,以下の手順に実行します.

(1) 新規プロジェクトに,TEditとTListboxを1つづつ配置
(2) Edit1のサブクラス化関数を定義して,Form1のOnCreateイベントで指定
(3) Edit1にフォーカスを移動し,何か入寮して,[変換]キーを押す.

ただし,このままですと,ListBoxにフォーカス移動すると,
少々不可思議な挙動となります.
MN_CHANGECANDIDATEメッセージも処理した方がいいと思われます.

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, Buttons;

type
  TForm1 = class(TForm)
    Edit1: TEdit;
    ListBox1: TListBox;
    procedure FormCreate(Sender: TObject);
  private
    { Private 宣言 }
    OriginalProc : TWndMethod;
    procedure ControlSubclassProc(var Msg:TMessage);
  public
    { Public 宣言 }
  end;

var
  Form1: TForm1;

implementation

uses IMM;

{$R *.DFM}

//=============================================================================
//  IMEの変換候補のウィンドウを表示するかわりに,TListBoxに候補リストを表示
//
//  選択候補を取得するにはImmGetCandidateList関数を使用する
//  これは,IMEが選択候補ウィンドウを開いた時,これはWM_IME_NOTIFYメッセージで
//  wParam値がIMN_OPENCANDIDATE の時になる
//  ここでは,Edit1の漢字入力の際にこの動作を行う
//  TApplcationEventsを使用してもよいが,Edit1専用とするために,Edit1のサブクラ
//  ス化関数で対応
//
//  選択した候補は,IMN_CHANGECANDIDATEメッセージの時に,ImmGetCandidateList
//  で取得できる.この処理も必要だろう
//
//  動作確認環境
//  Windows XP(SP3) + Delphi 2007 Pro + Delphi XE
//  Microsoft Office IME 2007
//=============================================================================
procedure TForm1.FormCreate(Sender: TObject);
begin
  OriginalProc     := Edit1.WindowProc;
  Edit1.WindowProc := ControlSubclassProc;

  SetImeMode(Edit1.Handle, imHira);
end;

//-----------------------------------------------------------------------------
//  Edit1のサブクラス関数
//-----------------------------------------------------------------------------
procedure TForm1.ControlSubclassProc(var Msg: TMessage);
var
  IMC        : HIMC;
  dwSize     : Cardinal;
  CandiList  : PCandidateList;
  hImWnd     : Cardinal;
  i          : Integer;
  StrText    : String;
begin
  if Msg.Msg = WM_IME_NOTIFY then begin

    if Msg.WParam = IMN_OPENCANDIDATE then begin
      Form1.ListBox1.Clear;
      IMC := ImmGetContext(Edit1.Handle);

      //ImmGetCandidateList関数の処理に必要なサイズを取得
      dwSize := ImmGetCandidateList(IMC, 0, nil, 0);

      hImWnd := GlobalAlloc(GHND, dwSize);
      try
        //PCandidateListレコード型(構造体)のポインタを取得
        //GetMem(CandiList, dwSize); と FreeMem(CandiList);の組み合わせでもOK
        CandiList := GlobalLock(hImWnd);
        try
          //候補リストを作成
          ImmGetCandidateList(IMC, 0, CandiList, dwSize);

          //順番に取出していく
          for i := 1 to CandiList.dwCount do begin

             //CandiList.dwOffset[i]にi番目の文字列のオフセット値が入っている
             //そのため,構造体の先頭アドレスのポインタを加算
             StrText := PChar(Integer(CandiList) + CandiList.dwOffset[i]);

             //表示する
             Form1.ListBox1.Items.Add(IntToStr(i) + '.  ' + StrText);
          end;
          //IMEの候補ウィンドウは表示しない
          //Msg.Result := 0;
          //exit;
        finally
          //FreeMem(CandiList);
        end;
      finally
        ImmReleaseContext(Edit1.Handle, IMC);
        GlobalUnlock(hImWnd);
      end;
    end;
  end;

  OriginalProc(Msg);
end;

end.


Mr.XRAY  2012-04-17 03:57:23  No: 41909

こんにちは.
失礼しました.Windows 7でしたね.
やってみたら,残念ながら,

dwSize := ImmGetCandidateList(IMC, 0, nil, 0);

のdwSizeにとんでもない値が戻ってきてしまいます.
さきほどのコードは,処理の流れということで(汗)


Mr.XRAY  2012-04-17 04:14:27  No: 41910

>のdwSizeにとんでもない値が戻ってきてしまいます.

Vista以降のTSFがらみのようですね.
「アプリケーション互換性情報パック」の中の
「IMM32互換性情報.doc」に記述があります.
さて,....


60の手習い  2012-04-17 16:56:30  No: 41911

Mr.XRAY様,
有難うございました。


Mr.XRAY  2012-04-17 21:36:46  No: 41912

こんにちは.

参考までに,
[ImmDisableTextFrameService function]
http://msdn.microsoft.com/en-us/library/windows/desktop/dd318537%28v=vs.85%29.aspx

というTSFを無効にする関数がありますが,これは,Vist以降では無視されます.
実行しても常にFalseを返します.
皆さんの使用している言葉で言うなら,「上手くいきません」「ダメです」
ということになります.


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

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






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