MrXrayさんの「ソフトキーボードもどき」を参考にして、タッチ操作用カナ漢字変換キーボードを作成していますが、タッチ操作をするには変換候補の表示が小さくて使えません。変換候補をListBox等に取込み、大きく表示させる方法を教えてください。OS:Windows7 HomePremium,、Delphi2007です。よろしくお願いします。
こんにちは,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.
こんにちは.
失礼しました.Windows 7でしたね.
やってみたら,残念ながら,
dwSize := ImmGetCandidateList(IMC, 0, nil, 0);
のdwSizeにとんでもない値が戻ってきてしまいます.
さきほどのコードは,処理の流れということで(汗)
>のdwSizeにとんでもない値が戻ってきてしまいます.
Vista以降のTSFがらみのようですね.
「アプリケーション互換性情報パック」の中の
「IMM32互換性情報.doc」に記述があります.
さて,....
Mr.XRAY様,
有難うございました。
こんにちは.
参考までに,
[ImmDisableTextFrameService function]
http://msdn.microsoft.com/en-us/library/windows/desktop/dd318537%28v=vs.85%29.aspx
というTSFを無効にする関数がありますが,これは,Vist以降では無視されます.
実行しても常にFalseを返します.
皆さんの使用している言葉で言うなら,「上手くいきません」「ダメです」
ということになります.
ツイート | ![]() |