キーボードの作り方(2)

2004/12/05 (最終更新:2005/08/28 15:27)

◎ SIP 版リモートキーボード

キーボードの作り方(1) で予告したとおり、リモートキーボードの SIP 版 NetKeySip を作ってみました。

PocketPC の入力パネル (SIP) として組み込みます。 実際に汎用の入力パネルとして機能します。 同時に SIP が開いている状態で リモートキーの入力を受け付けます。

キーボード送信側
WindowsPC, H/PC など
ppckeyClient
LAN
────→
シリアル
赤外線
キーボード受信側
PocketPC 2002/2003
NetKeySip

例えば WindowsPC (Win2000/XP) や他の H/PC, PocketPC 等で ppckeyClient を起動し、 キー入力するとそのまま NetKeySip の入力になります。 コネクション動作が不要で、同じ LAN 上にある場合相手を指定するだけで キー入力できます。 またはシリアルケーブルや赤外線でも同じように キー入力入力することができます。

ただ PocketPC 2003 では NetKeySip は動くものの、ppckeyClient は きちんと動作しないようです。同じように WindowsCE 4 ( .NET ) 系の H/PC でも動作しないかもしれません。

◎ 標準 SIP で Terminal Services Client が使えなかったわけ

入力パネルからシステム側に、押したキーを通知する手段は二通りあります。 仮想キーコードを直接渡す方法と、 仮想キーコードに加えてキーが押されたときに発する文字そのものを 渡すやり方です。

IIMCallback::SendVirtualKey( VKey, dwFlags );
IIMCallback::SendCharEvent( VKey, uKeyFlags, uChars, puShift, puChars );

仮想キーコードは物理的なキー1つ1つに割り振られた識別名で、 実際に押されたときにどの文字になるのかはまた別ものです。 なので日本語配列のキーボードを作ったり、 手書き認識などさまざまな文字入力手段を実装する場合は 文字コードを直接渡した方が便利です。

文字コードで送る場合でも、一緒に仮想キーコードを渡す必要があります。 これは、キー自体を仮想キーコードで識別するアプリケーションに対応するためです。 実際の文字入力には不要なので、無くてもたいていの場合困りません。

実は PocketPC 標準の入力パネル「ローマ字/かな」がこの値を省略しており、 「英数+半角」状態では 文字キーがすべて同じ仮想キーコードを返してきます。

以前 こちら のページに書きましたが、 PocketPC 用 Terminal Services Client のログイン時にキー入力できなかったのはこれが原因のようです。 かな モードにすると入力できるようになるのは、 その場合だけ仮想キーコードがきちんと実装されているのでしょう。

ちなみに ppckeyClient も 仮想キーコードを必要とします。 今回作成した NetKeySip は Terminal Services Client で使えるよう キーコードの再現と互換性を重視してみました。

なお日本語版 PocketPC 2002/2003 には Terminal Services Client が付属していませんが、 2002 にアップグレードした iPAQ 用に Microsoft のこちらからダウンロードできるようです。
Pocket PC Downloads - Terminal Services
http://www.microsoft.com/technet/prodtechnol/wce/downloads/ppctsrv.mspx

◎ 開発環境混在

PocketPC 用プログラム開発環境は OS のバージョンがあがり SDK の種類も増えて 少々複雑になりました。

WindowsCE の開発に使用する eMbedded Visual Tools/eMbedded Visual C++ は、 Microsoft のサイトからダウンロードすることができます。
Mobile Device - Download
http://www.microsoft.com/japan/windowsmobile/downloads/default.asp

ダウンロードできるこれらのツールは、 Visual C++ 6.0 と使い勝手やインターフェースが全く同じです。 PC の開発に慣れている方ならすぐ使いこなせると思います。

ただし最新の eMbedded Visual C++ 4.0 は WindowsCE 3.0 以前の SDK に 対応していないので、PocketPC 2002 用の バイナリも作る場合は古い eMbedded Visual Tools 3.0 も必要になります。

eMbedded Visual Tools 3.0
WindowsCE 2.11 H/PC Pro 3.0
WindowsCE 3.0 H/PC 2000
WindowsCE 3.0 PocketPC(2000), PocketPC 2002 など

eMbedded Visual C++ 4.0 (sp2/3)
WindowsCE 4.2 PocketPC 2003/2003 SE など

PC 用に Visual Studio も入れてあるため、互換性を保ちながら開発するには 3つツールが混在することになってしまいます。

ちなみに SDK には PocketPC はエミュレータがついてくるので、 ターゲット機器が無くても動作確認できるのは便利です。 とはいっても ARM 用バイナリが動くわけではありません。 PC 上で動作させるため CPU Type が x86 になります。 x86 用のバイナリは普段作成していないしまず見当たらないので、 エミュレータにツールをインストールしたり 他のソフトとの相性を調べたりするのは厄介です。

◎ SIP のインストーラー

WindowsCE 用のインストール用パッケージに使われる .CAB ファイルは、 Cabwiz というコマンドを使って作成します。 あらかじめ必要なファイルや転送先などのルールを .ini ファイルに記述しておけば、指定した CAB ファイルを生成してくれます。 CPU タイプ別、環境別などの条件を一緒に記述しておくこともできます。 この辺は、オンラインヘルプで Cabwiz を検索するといろいろとでてきます。

SIP の場合、インストールと同時にレジストリへの DLL 登録が必要になります。 もともと DLL の関数 DllRegisterServer() でレジストリ登録を行っているので、 インストール時に呼び出してもらう必要があります。 これは DefaultInstall へ CESelfRegister を追加することで実現できるようです。

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/devio/base/setcommstate.asp [DefaultInstall.ARM]
CopyFiles = Files.Common, Files.ARM
CESelfRegister = netkeysip.dll

アンインストール時も同様に DllUnregisterServer() が呼び出されるため、 こちらでは不要になったレジストリエントリを削除しておきます。 SIP のサンプル dvoraksip は DllUnregisterServer() の記述が無いので、 自分で追加しておく必要があります。

DLL ファイルの転送先は \Windows ですが、2002 では動くものの PocketPC 2003 でファイルが転送されない現象に悩みました。 コピー時にフラグ 0x80000000 を記述することでコピhttp://msdn.microsoft.com/library/default.asp?url=/library/en-us/devio/base/setcommstate.aspーされるようになりました。

[Files.ARM]
netkeysip.dll,,,0x80000000

◎ SIP のオプション画面

設定の「個人用」から「入力」を開くと 各 SIP のオプション画面を開くことができます。 このオプション画面選択時は IInputMethod の UserOptionsDlg() が呼び出されます。

注意点は、オプション画面が呼び出されたときのインスタンスは 実際にキー入力している SIP 本体と別であることです。 そのため実際に設定した内容は、レジストリなどを使って 受け渡しする必要があります。

◎ シリアル通信

NetKeySip をシリアル対応にするために、 久しぶりに RS-232C ケーブルなどを触りました。 買っておいた h3630 用シリアルケーブルが役に立ちました。

Windows ではシリアルデバイスに COM1: 〜 などの名前がつけられており、 ファイルとして Open して読み書きするだけで通信できます。 通信速度などの細かい条件は
SetCommState()
で設定できます。同様に Comm 系の API を使って Timeout 条件や現在のエラー状況取得など細かい操作もできるようです。

赤外線ポートも同じように、 IrCOMM によってシリアルポートの一種として扱うことができます。 iPAQ h3630 では赤外線ポートが COM2: に割り当てられていました。

初期状態では、システムが赤外線ポートを占有しています。 設定画面の「接続」タブから「ビーム」を選び「ビームを受信する」 部分のチェックをあらかじめはずしておく必要があります。

赤外線ポートを使って通信する場合もシリアルケーブルと全く同じ条件で 実行できます。 ただ通信途中に電源を切ってしまうと、 電源を入れてサスペンドから復帰しても通信状態が回復しません。 せめて API がエラーを返してくれれば再接続できるのですが、 なぜかエラーも返ってこないようです。

外部キーボードとして使う場合はできる限りコネクションレスにしたいし、 こまめに電源を ON/OFF しながら使うであろうことが考えられます。 なので電源 OFF を監視して、一度電源が切れたと思われるときは 自分から再接続しなおすようにします。

ところが今度は、電源 OFF の監視方法がわかりません。 適当にイベントを監視して、 ウィンドウに初期化がかかったら再接続するようにしてみました。 PocketPC 2003 では まだきちんと再接続できていません。残念ながら SIP の選択しなおしなど、自分でリセットする必要があります。 PocketPC 2002 の ppckeyClient ではうまくいっているようです。

[戻る]
[メニューに戻る] [ZAURUS総合] [Direct3D] [Ko-Window] [Win32] [WinCE] [携帯電話] [その他]
フルパワー全開 Hyperでんち

Hiroyuki Ogasawara <ho>