プログラミングの最近のブログ記事

タブキーで確定同時タブ入力

| コメント(0) | トラックバック(0)
DFJ2を真似したキー設定で使い続けること14年、流れ流れてATOK。

DFJ2/WINがどうだったかは記憶の彼方ですが、VJE-Deltaでは確定前にタブキーを押すと、確定と同時にタブが入力されました。2.0/2.5/4.0共通の仕様だったはずです。

どうなるかというと、Webブラウザのフォームで日本語入力している時に便利なのです。例えば姓を変換してタブを押すと、姓を確定しつつ名の欄に移動する具合になります。

しかしATOK2008では、どう設定してもこれは実現できないようでした。

この場合、とりあえずタブに全文確定を割り当て、確定を検出してVK_TABを発行すれば良いわけです。

Spy++を眺めたところ、確定すると下記のようなメッセージが来ていました。

WM_IME_NOTIFY / IMN_PRIVATE / lParam:0x04
WM_IME_NOTIFY / IMN_PRIVATE / lParam:0x13
WM_IME_ENDCOMPOSITION

IMN_PRIVATEは必ず0x04~0x13の順ですが、変換してから確定するとWM_IME_ENDCOMPOSITIONが二つのIMN_PRIVATEより後(上記のままの順序)、変換前に確定するとWM_IME_ENDCOMPOSITIONが先になります。

Vista/7上のATOK2008とFirefoxの組み合わせではWM_IME_ENDCOMPOSITIONが来ず、また二度目以降の確定の場合は0x13のIMN_PRIVATEも来ませんでした。ということで、0x04のIMN_PRIVATEを処理すれば良いことになります。
XP上でVJE-Delta4.0とFirefoxの組み合わせだとWM_IME_ENDCOMPOSITIONは普通に来るのですが。

DeltaEndにこの仕組みを入れたテスト版で動作を確認できましたが、現在のメイン環境は64ビットです。64ビットEXEとDLLも用意しないと、64ビットアプリにフックが届きませんし、その場合はそれぞれDLLを別名にしなければならないということでした。

# Webブラウザぐらいでしか使わない機能だと割り切る選択肢もあり

32ビットをメインとし、64ビット動作用の子プロセスを呼ぶとして、設定の同期が課題です。まずは32ビットEXE~32ビットDLL間を共有メモリにしてみましょうか。

キーボードフィルタ

| コメント(0) | トラックバック(0)
キーボードフィルタドライバの使い方がわかってきました。いくらでも試して操作不能にできる仮想PC環境のおかげです。

例えば無変換キーを
  • KEYDOWNでKEYUPも発行
  • KEYUPは無視
  • リピート却下
とする場合、後述のようなコードになっています。

ベースのkbfiltrはWDK 6001.18002です。スキャンコード一覧はこちらにあります。その他、ここここここを参考にしまし た。

レイアウトドライバで無変換にVK_KANAを割り当てれば、遜色ないカナキーにすることができるわけです。

ローレベルの制御をドライバで完了できれば、管理者権限のユーティリティが不要になります。一般権限では管理者権限アプリをフックできませんが、カナインジケータ程度の監視ならポーリングのような、より普通の実装にすべきなのでしょう。

VOID
KbFilter_ServiceCallback(
  IN PDEVICE_OBJECT DeviceObject,
  IN PKEYBOARD_INPUT_DATA InputDataStart,
  IN PKEYBOARD_INPUT_DATA InputDataEnd,
  IN OUT PULONG InputDataConsumed
  )
{
  PDEVICE_EXTENSION  devExt;
  KEYBOARD_INPUT_DATA kana[1] = {0};
  PKEYBOARD_INPUT_DATA curInputData = InputDataStart;
  ULONG tempConsumed = 0;
  static int bInKana = 0;

  devExt = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension;

  while( curInputData < InputDataEnd )
  {
    switch ( curInputData->MakeCode )
    {
    case 0x7b:
      if ( ( InputDataStart->Flags & KEY_BREAK ) == 0 ) {
        if ( bInKana == 0 ) {
          bInKana = 1;

          kana[0].MakeCode = 0x7b;
          kana[0].Flags = KEY_MAKE;
          tempConsumed = 0;

          (*(PSERVICE_CALLBACK_ROUTINE) devExt->UpperConnectData.ClassService)(
            devExt->UpperConnectData.ClassDeviceObject,
            &kana[0],
            &kana[1],
            &tempConsumed);

          kana[0].Flags = KEY_BREAK;
          tempConsumed = 0;

          (*(PSERVICE_CALLBACK_ROUTINE) devExt->UpperConnectData.ClassService)(
            devExt->UpperConnectData.ClassDeviceObject,
            &kana[0],
            &kana[1],
            &tempConsumed );
        }
        else {
          curInputData++;
          continue;
        }
      }
      else {
        bInKana = 0;

        curInputData++;
        continue;
      }
      break;
    
    default:
      tempConsumed = 0;
      (*(PSERVICE_CALLBACK_ROUTINE) devExt->UpperConnectData.ClassService)(
        devExt->UpperConnectData.ClassDeviceObject,
        curInputData,
        curInputData + 1,
        &tempConsumed );
    }
    curInputData++;
  }

  *InputDataConsumed = ( InputDataEnd - InputDataStart );
}

デバッグシンボル

| コメント(0) | トラックバック(0)
何となく、ドライバ類からデバッグ用シンボル情報を削除する話をまとめます。

まず、rebaseする方法。Windows 2000 DDKぐらいまではこれ。Free Buildでも入るのでこうしたKBがあります。
[NT DDK] デバイス ドライバからシンボルを削除する方法

Server 2003 SP1 DDKはmakefile.newの修正が必要です。
LINKER_FLAGSにLINKER_DBG_SECTIONを追加している部分をFree Buildの場合に除外します。

LINKER_FLAGS = $(LINKER_FLAGS) $(LINKER_DBG_SECTION) -debugtype:cv $(LINK_OS_VERSIONS)
これを
!if $(FREEBUILD)
LINKER_FLAGS = $(LINKER_FLAGS) $(LINK_OS_VERSIONS)
!else
LINKER_FLAGS = $(LINKER_FLAGS) $(LINKER_DBG_SECTION) -debugtype:cv $(LINK_OS_VERSIONS)
!endif
こう。

WDKもmakefile.new修正ですが少し変わりました。6001.18002と7600.16385.1で共通です。

LINKER_FLAGS = $(LINKER_FLAGS) $(LINKER_DBG_SECTION) $(LINK_OS_VERSIONS)
これを
!if $(FREEBUILD)
LINKER_FLAGS = $(LINKER_FLAGS) $(LINK_OS_VERSIONS)
!else
LINKER_FLAGS = $(LINKER_FLAGS) $(LINKER_DBG_SECTION) $(LINK_OS_VERSIONS)
!endif
こんな感じに。

ただし2003 DDK以降は派手には残らず、pdbファイルへのフルパスが残る程度のものとなっています。ちょうどVisual C++でデフォルト設定のままReleaseビルドした状態に相当ですので、気にしない人には問題ありません。

VK_F

| コメント(0) | トラックバック(0)
時々Windowsのキーボードレイアウトドライバを弄っていますが、VK_F構造体(タグ名_VK_TO_FUNCTION_TABLE)の意味が何となくわかってきました。

# MSDNででも聞けば教えてくれるのでしょうが

NLSFEProcTypeがKBDNLS_TYPE_TOGGLEの場合、NLSFEProcSwitchが8ビットのフラグとしてNLSFEProc[8]の各状態に対応し、その組み合わせでキーが押されると、ビットが立っている状態に関してのみNLSFEProcAltと切り替わるようです。

NLSFEProcCurrentは初期状態をNLSFEProcかNLSFEProcAltのどちらにするか、でしょう。試していませんが2択なので変更する必要性もありません。

WDKのkbd106サンプルの場合、「英数」のNLSFEProcSwitchは2ですから、Shift同時押しでトグル動作です。
このShift同時押しでKBDNLS_SEND_PARAM_VKに従いVK_CAPITALを発行し、同時にNLSFEProcAlt側に切り替わります。次のShift同時押しはNLSFEProcAlt側が参照され、VK_CAPITAL発行と同時にNLSFEProcに戻ってくる、と。
NLSFEProcAltには同時押しのない単体(Base)にもVK_CAPITALが書かれていますが、発行されないことから、Shift同時押しだけが切り替わったものと考えられます。

「ひらがな」はNLSFEProcSwitchが8なのでShift+Ctrl同時押しが対応。VK_KANAと同時にNLSFEProcAltに切り替わり、同様に次にShift+Ctrl同時押しで戻ってきます。

ということに気付いたのは、無変換VK_KANAをKBDNLS_TYPE_TOGGLEで試している途中、NLSFEProcAlt側を全部KBDNLS_NULLのままにしていたら、戻って来られなくなったためですが(汗)。

しかしKBDNLS_TYPE_TOGGLEにしても、少なくともVK_KANAに関して御利益はないようで、相変わらずKEYUPまでON/OFFが変化しません。KEYDOWNで変化するのはCapsLock、NumLock、ScrollLockの特権のようです。

98配列USBキーボードでは、KEYDOWNで切り替えるためのフィルタドライバを別途用意していますが、この部分の書き方についてはまだ理解できていません。

Core Textに手をつけてみる

| コメント(0) | トラックバック(0)
XCodeのCoreTextTestサンプルが文字化けして動作しませんでした。MacBook、Mac OS X 10.5.8、XCode 3.1.3にて。

文字列が入ったutxtファイルをmiでLittle Endian(UTF-16LE)で保存し直したら表示されました。

CFStringオブジェクトの中にファイルから直接バイナリで読み込んでいるので、BOM無しのアーキテクチャ依存なエンディアンでしか正常に読み込めないように見えます。

AnyDVDとプログレスバー

| コメント(0) | トラックバック(0)
面倒くさがり屋なのでBuffaloのLinkTheaterを導入しました。LT-H91DTV
LT-H91LANでも良かったのですが、価格差も小さく、あまり店頭で見かけないのでこちらに。

HDDにDVDを丸ごと放り込んで、見たい時にどれでも見られる、ズボラ人間にはたまらないアイテムです。
同種のものは他にもありますが、DVDのメニューが使える素敵な代物。

せっせとHDDに放り込むわけですが、永代更新の滑り込みで購入したAnyDVDが、Windows 7のタスクバー上プログレスバーに対応していないので、フルスクリーンの使用頻度が高いノートでは少し不便です。

AnyDVD.pngということで、進捗をタスクバーに表示するランチャーを作ってみました。
Program Files以下のデフォルト位置でインストールされたAnyDVDの、isoイメージ作成を起動し、プログレスバーをタスクバー上に重ね、閉じると同時に自分も終了します。

TaskBarProgress.zip

ウィンドウハンドルがわかっていれば、他のプロセスのタスクバーを操作することは禁止されていないようです。

CERTUMでコード署名

| コメント(0) | トラックバック(0)
UAC.png無料でexe等へのコード署名ができないものかと思ったら、Thawteが個人向け無料サービスを昨年10月に終了してしまっていました。

何とかならないかと探したところ、オープンソース開発者向けに、ポーランドUnizeto社のCERTUMが無料サービスをしていることがわかりましたので、申し込んでみました。詳しくはこちら

Code SigningからMicrosoft Authenticodeを選択、Issueを購入します。アカウントを作成して個人情報を入力。Companyは"Open Source Developer"とします。なお電子メールアドレスは必須で、これはexeファイルの署名にも入ります。

支払いをSpecial Offerとし、その右のOffer Codeに"Open Source Developer"と入力して手続きを進めます。

翌営業日にでしょうか、向こうからメールが来るので、身分を証明できる書類をJPEGででも添付して返事をします。
日本語がわかる人がいないとのことで、運転免許はダメでした。パスポートは使えます。

書類が受け付けられるとIDが送られてくるので、指定されたURLで入力すると証明書ファイルを受け取ることができます。
あとはこれをVisualStudioのSignTool等に渡してやれば署名できます。

signtool sign /v /ac (証明書ファイル名) /s my /n "(名前)" /t http://time.certum.pl (実行ファイル名)

この辺に書いてある例の改変ですが、タイムスタンプ取得はVeriSignのままで通ったりしますが、各証明書の発行元が用意しているものを使います。

自分のプログラムが出すUACダイアログが黄色から標準のものに変わるのは妙に嬉しいですが、上記の通り電子メールアドレスが晒されることになるため、spamが多い昨今ですのでソフト配布の際にはご注意ください。

ルート証明書を諦めてよいならCAcertを利用するのがよいのでしょう。
<<前のページへ 12345678

アーカイブ

ウェブページ

Powered by Movable Type 5.2.13

ホームページ