Hatena::ブログ(Diary)

Webと文字

よければ、はてブしてください。( ´∀`) George.Nagaoka@gmail.com

JavaScript IME:海外からブラウザで日本語を変換 新URL 旧URL:
多言語入力ブックマークレット:ブラウザでロシア語、中国語、アラビア語・・・
【軍曹が】携帯電話開発の現状【語る】をAA化した
AAのデータベース
趣味のページ

2009-03-27

C++でWindowsのIMEを作ろう( ゚∀゚) その1

1.目標

 JavaScriptで日本語IMEを作ろう( ゚∀゚) - Webと文字で作ったJavaScriptIMEをWindowsに移植する。

2.必要な実装

  • 文字列の挿入と一時的な入力エリアの挿入
  • 一時的な入力エリアにおけるテキストの変更とキャレット位置の取得とキャレット位置の設定と書式変更
  • 一時的な入力エリアの下に出すWindowとその書式設定
  • キーイベントの取得
  • WwbAPIより変換候補を取得する

3.準備

 今までに以下に示す関連するエントリを書きました。

 TSFの説明が日本語資料としてMSDNにあります。

4.サンプルを改造する

 アイコンの変更を行います。rcファイルをいじると、なぜかコンパイルできなくなります。また、VC++ExpressEdisionにはリソースエディタが入っていないので不便です。参考資料1のResEditをダウンロードして、参考資料2を参考にしてResEditをRCファイルに関連づけます。元の"resource.h"とcase.rcは削除します。

f:id:project_the_tower2:20090328005129p:image

 言語バー用に16*16の拡張子icoアイコンファイルを用意します。テキストサービスを表すアイコンを一つ、ボタン用のが一つで二つ用意します。今回は参考資料3のminiアイコンを使用しました*1。ResEditを開いて新規プロジェクトで適当な場所にrcファイルを作成し、先ほどの二つのアイコンを追加します。保存すると、rcファイルとresource.hファイルができているのでVC+EEのプロジェクトに両方追加します。

 テキストサービスを表すアイコンはregister.cppのCCaseTextService::RegisterProfilesのpInputProcessProfiles->AddLanguageProfileの最後の引数によって決定されます。この引数リソースアイコンの通し番号です。0だと初めの一個目のアイコンになります。ボタン用のアイコンはlangbar.cppのCLangBarItemButton::GetIconのLoadImageによって決定されます。参考資料4を参考にして以下の用に書き換えました。

(HICON)LoadImage(g_hInst, MAKEINTRESOURCE(IDI_ICON2), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);

ここでIDI_ICON2はResEditによって自動的に決定されたアイコンの名前です。g_hInstはDLLのヒンスタンスです。


 hello.cppを変更して挿入するテキストの変更を行います。言語バーからテキストサービスを選ぶとITfTextInputProcessorを実装したオブジェクトのActivateメソッドが呼ばれます。その際に言語バーにボタンを追加する処理をします。ボタンはトグル、ポップアップメニュー、普通のボタンの3種類選べます。サンプルではメニューを出すものに設定されています。追加されたボタンをクリックするとそのボタンのInitMenuが呼ばれ、メニューの項目をクリックするとOnMenuSelectが呼ばれ、c_rgMenuItemsの二つの目の引数関数が呼ばれます。hello.cppではCCaseTextService::_Menu_Helloが呼ばれて、その中でITfEditSessionを継承したインスタンスを作成しています。インスタンスからコンテクストを取得し、RequestEditSessionを呼ぶと、インスタンスのDoEditSessionが呼び出されます。実際の処理はこの中で行います。エディットセッションについては参考資料5を参考にしてください。

 DoEditSessionの処理を以下の用に変更しました。

static WCHAR s[] = L"         ∧ ∧\n       ヽ(・∀ ・)ノ <\n       (( ノ(  )ヽ ))\n         <  >";
InsertTextAtSelection(ec, _pContext, s, (ULONG)wcslen(s));

\nが改行コードであることを考慮すると上の処理は以下のような結果になることを期待しています。

         ∧ ∧
       ヽ(・∀ ・)ノ
       (( ノ(  )ヽ ))
         <  >|←キャレット

GUIDの変更を行います。参考資料6を使用してglobal.cppの全てのGUIDを変更します。

5.テキストサービスをアンレジストする

 regsvr32で登録したDLLを登録除去するにはregsvr32に-uオプションをつけてDLLを指定するだけです。これは実際にはDLLにあるDllUnregisterServer関数を読んでいるだけなので、レジストリの除去及びTSFからの除去の処理は登録の時と同じように処理を書く必要があります。

6.試す

できたDLLビルドし、regsvr32して登録して試してみました。アイコンの変更は行われていました。

f:id:project_the_tower2:20090328020447p:image

テキストの挿入は幾つかのソフトウェアで動作が異なりました。

  • ワードパット:意図した結果になりました。
  • (´д`)Edit (参考資料7):一行になってしまいました。
  • terapad:複数行になりましたが、キャレットの位置がずれました。

7.次回

 一時的なテキスト入力エリア(Composition)とその中でのキャレット位置取得と設定

8.わからないとこ

TSFのサンプルのTSFmarkのコンポジションがwordpadやWordなどのTSF対応アプリケーションでしか動作しない。その2を参照のこと

9.参考資料

*1gifで用意されているので適当なファイルでicoに変換する必要があります。

programtipsprogramtips 2016/08/07 19:39 こんにちは、IME作成に関して大変参考にさせていただきました。

programtipsprogramtips 2016/08/07 19:42 こんにちわ、IME作成に関して大変参考にさせていただきました。

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証