住所録を登録する画面で名前を入力すると自動的に名前のよみがなを編集したい。
IMEの入力値がとる方法がしりたい。
名前:松山 名前のふりがな:まつやま
Delphi6Pro
immユニットを使います。
Form1に、Edit1とButton1とListBox1をおき、Button1のOnClickに次のような定義をすれば、とり方はわかると思います。
procedure TForm1.Button1Click(Sender: TObject);
var
i: integer;
imc: HIMC;
kl: HKL; // キーボードレイアウト
Dst: PCandidateList;
sz: integer; // サイズ
tmppchar: PChar;
begin
Edit1.SetFocus;
ListBox1.Clear;
imc := ImmGetContext(Handle);
kl := GetKeyboardLayout(0);
sz := ImmGetConversionList(kl, imc, PChar(Edit1.Text), nil, 0, GCL_REVERSECONVERSION);
GetMem(Dst, sz);
ImmGetConversionList(kl, imc, PChar(Edit1.Text), Dst, sz, GCL_REVERSECONVERSION);
for i := 0 to Dst.dwCount - 1 do
begin
tmppchar := PChar(DWORD(Dst) + Dst.dwOffset[i]);
ListBox1.Items.Add(String(tmppchar));
end;
FreeMem(Dst);
ImmReleaseContext(Handle, imc);
end;
にしのさん お返事ありがとうございます。
早速、試してみましたがうまくいきません。教えてください。
Edit1とButton1とListBox1を配置して
お返事のコードをButton1.OnClickに貼り付けで実行しました。
エラーになったのでUses に immを追加して実行しました。
これで動作はするのですがListBoxにはなにも表示されなかったり
ゴミのようなものが出たりです。
操作はEDIT1に松山(まつやまで変換して確定後)と入力して
Button1をクリックしています。
あとEDIT1になにも入力がないときは異常のようです。
今はDelphi4ですが、まずいですか?
よろしくお願いします。
うちの環境はDelphi5です。
予想ですが、HandleをApplication.Handleにしてはどうですか?
僕も、最初これを作るときにEdit1.SetFocusしないでIMEコンテキストを取得したらエラーになりましたから。
ちなみに、手元の資料(Windows98 APIバイブル)では、Editからメッセージを飛ばして、そのメッセージの処理内で取得しているようです。
imc(IMEコンテキスト)がきちんと取得できているか、kl(キーボードレイアウト)が取得できているか、ImmGetConversionListの戻り値(CandidateListのサイズ)が正常か、確かめてみてください。
間違えてました。
dwOffsetは、[1..1]と定義されているので、[0]や[2]以降を参照しても意味がありません。
# [2]以降は意味があるかもしれませんが、どうせ#0区切りの文字列なので。
それと、Dstはポインタで、内部を参照するには逆参照しなければならないですね。
# Delphi5ではもしかしたら勝手にやってくれてたのかも
なので、var に offset:DWORD;と、idx: integer;を用意して、for文以下を
tmppchar := PChar(DWORD(Dst) + Dst^.dwOffset[1]);
offset := 0;
for i := 0 to Dst^.dwCount - 1 do
begin
tmppchar := PChar(DWORD(tmppchar) + offset);
idx := ListBox1.Items.Add(String(tmppchar));
offset := Length(ListBox1.Items[idx]) + 1;
end;
FreeMem(Dst);
のように変えてください。
にしのさんお返事ありがとうございます。
指示とおり、修正したのですがLISTBOXには意味不明の文字が
表示されます。
コーディングは以下のとおり。(Delphi4.0j Pro)
procedure TForm1.Button1Click(Sender: TObject);
var
i: integer;
imc: HIMC;
kl: HKL; // キーボードレイアウト
Dst: PCandidateList;
sz: integer; // サイズ
tmppchar: PChar;
offset:DWORD;
idx: integer;
begin
Edit1.SetFocus;
ListBox1.Clear;
imc := ImmGetContext(Handle);
kl := GetKeyboardLayout(0);
sz := ImmGetConversionList(kl, imc, PChar(Edit1.Text), nil, 0, GCL_REVERSECONVERSION);
GetMem(Dst, sz);
ImmGetConversionList(kl, imc, PChar(Edit1.Text), Dst, sz, GCL_REVERSECONVERSION);
// showmessage(inttostr(Dst.dwCount));
tmppchar := PChar(DWORD(Dst) + Dst^.dwOffset[1]);
offset := 0;
for i := 0 to Dst^.dwCount - 1 do
begin
tmppchar := PChar(DWORD(tmppchar) + offset);
idx := ListBox1.Items.Add(String(tmppchar));
offset := Length(ListBox1.Items[idx]) + 1;
end;
FreeMem(Dst);
ImmReleaseContext(Handle, imc);
end;
今の環境にDelphiがないため、確かめられません。
家に帰ったら確かめますね。
一応念のため、OSとIMEは何をお使いですか?
うちは、WindowsXP Pro+IME2002です。
それと、HandleはEdit1.Handleかもしれません。
うちだと、HandleでもEdit1.Handleでもうまくいきました。
# SetFocusしないとエラーになりました
動きましたよ。
やはり、OS、IMEの組み合わせでしょうか。
それともD4とD5の違いでしょうか。
これ以上はちょっとわかりません。
Delphi6、Win98、IME98 では、
Edit1が「松山」で、
ListBox1の表示は
「"gq¥」の1行です。
Edit1が「1」(半角)の場合、
ListBox1の表示は、
1
いっ
ひと
の3行です。
WindowsXP Pro+IME2002では、
Edit1が「松山」の場合、ListBox1の表示は
何と表示されるんでしょうか?
Delphi5,WindowsXP Pro+IME2002では、
ListBox1の表示は
まつやま
が8行表示されます。
半角の1の場合、
ListBox1の表示は
1
だけです。
空欄ではエラーが発生します。
ListBox1には「〜gq\」と表示されます。
今の環境はWinMe+IME2000+Delphi6.0Proです。
IME周りで参考になる本をご存知なら教えてください。
IMEの違いではなくて、OS(Win9XかNT系か)の違いが
影響するんですかね〜(@_@)
AnsistringとUnicodeの問題かな〜でも、
ImmGetConversionListA()
ImmGetConversionListW()
でやってもうまくいかないし…
参考になるかどうかわかりませんが、
Windows98 APIバイブル
シェル/シェルユーティリティ/印刷/IME/追加関数 編
有限会社ガリバー著
長谷川勝規 監修
販売元 翔泳社
ISBN4-88135-734-4
定価5800円+税
これに、IME関連の関数や定数(値は出ていません)、構造体などが出ています。
サンプルはVisualC++で書かれています。
UnicodeかSJISかですが、特に記述はありませんでした。
ここに解説がありました。
ナントIME98、IME2000のバグだったとは(-_-;)
いまだ未解決のようですね。困ったもんだ。(-_-メ)
http://www.microsoft.com/japan/support/kb/articles/J059/3/78.asp
http://hp.vector.co.jp/authors/VA009883/
の、Yomiというツールだとうまく変換できますよね?
# 対応がIME98以降となっているので
これにはDLLが含まれていて、.htaファイル(WSHすぷりぷと)で読み込んでDLLを呼び出しているので、このDLLの使用許可が出れば読み仮名取得が簡単にできそうです。
たしか、IME97以降には、別の方法で読み仮名を取得する方法があったはずなんですが、思い出せません。
「Yomi」というツールでは確かにIME98でも漢字の読みが表示されますね。
う〜ん、どうやっているんだろう。
中に入っている'comuni.Yomi.dll'を
次のように呼び出してみましたが、
「欠陥エクスポートにリンクされています」という
エラーが出てしまいます。
このDLLは Delphiでは使えないんでしょうか。(T_T)
const comuniYomi = 'comuni.Yomi.dll';
function getYomi(inStr: LPSTR): LPSTR; stdcall;
external comuniYomi name 'getYomi';
procedure TForm1.Button1Click(Sender: TObject);
begin
Edit1.Text := getYomi('明日');
end;
TLIBIMPで、
tlibimp comuni.Yomi.dll
とすると、
YOMILib_TLB.pas
YOMILib_TLB.dcr
が吐かれます。
これを使えばたぶんできると思います。
# 要はCOMオブジェクトです
それで、uses節にYOMILib_TLBを加えて、次のようにすれば取れます。
procedure TForm1.Button3Click(Sender: TObject);
var
yomi: IYomiImpl;
tmpstr : string;
begin
yomi := CoYomiImpl.Create;
tmpstr := yomi.getYomi(WideString(Edit1.Text));
ListBox1.Items.Clear;
ListBox1.Items.Add(tmpstr);
end;
CreateComObjectしたオブジェクトの廃棄の仕方はわかりませんでした。
ヘルプを見ると、複数作るときはクラスファクトリを使用したほうがよいと勝てあるので、実際には、単一のオブジェクトにするかクラスファクトリを使うとよいです。
もう少しじっくりテストします。
みなさま、ご協力ありがとうございました。
Delphi6Personal には TLIBIMP.exe がありません。(T_T)
これはお手上げですね。
tlibimp、ありませんか。
これで動きませんか?
Delphi5で通ります。
http://www.geocities.co.jp/AnimalPark/1770/YOMILib_TLB.lzh
どうでしょうか。
.dcrはいらないと思いますが。
コンポーネントと同じように、パッケージを作成してインストールしてみてください。
解凍したYOMILib_TLB.pasをプロジェクトのフォルダに入れて、
uses節にYOMILib_TLBを加えると動きました。\(^○^)/
WideStringのキャストは無くても問題ないようです。
色々な人名の読みテストしてみると、妙な変換がされましたが、
IMEのプロパティで初期変換モードを「人名/地名」にすることで
ほぼ的確な読み変換が出てきました。
ありがとうございました。m(__)m
ツイート | ![]() |