画餅展覧会

2009 年 4 月 6 日

破壊の春

カテゴリー: W-ZERO3, 妄言 — jk78 @ 4:33 PM

W-ZERO3[es] (WS007SH) のminiSDスロットが壊れた。カードを差し込んでも奥でロックされず、べろんと吐き出してしまう。現役だった時は、2GBのカードを刺しっぱなしだったが、現役を外れてから、頻繁に無線LANカードを抜き差ししていたから壊れたのか。たかだか数百回程度の抜き差ししかしていないと思うのだが。W-ZERO3にかぎらず、SDスロットは、ちゃちで、壊れやすいように感じるがどうなのだろう。

などといっていたら、今度は9年間使い続けたAcerのノートブックが起ち上がらなくなった。唯一のWindowsマシンを失ったのでしばらくは開発も出来ない。失われたデータは無いが、精神的ショックが大きい。

私の周りに宇宙線が大量に放射されたのかな。明日目覚めたら私も進化して羽でも生えているといいのだが。

2009 年 4 月 3 日

二重起動防止考

カテゴリー: KanaInput, Programming, Windows Mobile — jk78 @ 6:35 PM

いつのころからか、Microsoftはアプリケーションの二重起動防止コードサンプルとして、MutexとFindWindow()を組み合わせた方法を推奨するようになった。

なんでアプリケーションの起動ごときにMutexとWindowという二つの仕組みを併用せねばならんのか、と不満だったのだが、今まで深く考えたことが無かったので、見直してみた。

FindWindow

自分のウィンドウをFindWindowして、見つからなかった場合は新規作成。見つかった場合は、既存のウィンドウをSetForegroundWindowする。昔のアプリケーションは皆こうしていた。簡単で非常に結構なのだが、少し考えればまずい点は明らかだ。FindWindowからCreateWindowの流れはアトミックな操作ではないので、どう頑張っても二重起動する可能性を消しきれない。単なるアプリケーションウィンドウの二重起動ならば、それほど神経質にならなくても良かろうが、KanaInputのようにシステムの動作にかかわるアプリケーションは、カーネルオブジェクトを使って、確実に二重起動を制御すべきである。(KanaInput 1.0.1 ではやってません。次のバージョンで対応します )

Mutex

で、カーネルオブジェクトの登場となるわけだが、CreateMutexを使って、自分が作成者かどうかだけを判断の材料にする。自分が作成者であれば、おもむろにウィンドウを作成する。自分が作成者でなければ、既存のウィンドウをFindWindowしにいく。同期オブジェクトとしてMutexを使っているにもかかわらず、FindWindowなどという、どちらかといえば不確かな手段を使わなければならないのが気に入らない。同期オブジェクトを使っているのだから、既存ウィンドウのForeground化も同期オブジェクトを使って行えないものか、と考えてしまう。

Event

Mutexは、所有/非所有の判断しかできないので、Eventを使うことを考えてみた。CreateEventして、自分が作成者ならば、ウィンドウを作成し、メッセージループでEvent待ちを併用する。自分が作成者でなければ、既存のEventオブジェクトに対してSetEventする。既存プロセスが、Eventを受け取ったら、SetForegroundWindowを実行する。きれいではないか。ところが実際にやってみると、難がある。まず、デスクトップでは、Windows 2000以降、SetForegourndWindowの実行に制限がかかっているので、バックグラウンドにくすぶっているプロセスが、自分のウィンドウに対してSetForegourndWindowしても、Foregroundになってくれない。Windows Mobileでは今のところそのような制限は無いが、メッセージループが回っていないと、Eventが取れない。つまり、モーダルループが回っている間は、使えない。モーダルウィンドウを出さないアプリケーションならば、使えるかもしれない。(ChooseIM 1.0.1 がこの方法を使っています)

Semaphore + File Mapping (Shared Memory)

つまり、後から起動したほうが、既存ウィンドウに対してSetForegroundWindowを実行しなければならないわけだが、そのためには、ウィンドウハンドルが必要になる。Windowsでは、特にWindows Mobileでは、プロセス間のデータ共有方法はFile Mappingしかない。で、Semaphoreを使って制御しながら、File Mappingでウィンドウハンドルを後続プロセスに渡す方法で組んでみた。問題なく動作する。FindWindowのような不確かな要素も入らない。しかし、受け渡すデータが4バイトなのに対して、共有メモリーの最小単位が64KBと大きいのである。65532バイトが丸々無駄になる。メモリの潤沢なデスクトップ環境ならばいざ知らず、Windows Mobileでは、このような無駄は極力避けたい。

以上のような理由から、結局、Mutex+FindWindowが落しどころと言うことになるのだろう。Microsoftの推奨にも理由はあるのだろうが、やはり自分で考えてみないと納得がいかない。

もう一度FindWindow

FindWindowは、ウィンドウ名とウィンドウクラス名で検索する。ウィンドウ名というのは、ユーザーに見せるものだから、その表現内容は自ずと限られる。ウィンドウクラス名はユーザーに見えないので、長くて醜い名前、特にURLを利用した一意的な名前を使えば、他アプリケーションとの衝突は事実上避けられる。しかし、ダイアログアプリケーションでは、そうはいかない。ダイアログクラスは、システムが用意するものだから、クラス名は選べない。ダイアログウィンドウの検索は、実質ウィンドウ名だけで行われることになる。これは避けたい。「KanaInput」と言う名前のダイアログを他人が悪意なく作成することなど、いくらでもありえるではないか。これを避けるために、KanaInputや、ChooseIM 1.0.0 などは、表示されないフレームウィンドウを、FindWindowのために持たせていたのである。ところが、この構成は、SetForegroundWindowに難がある

ダイアログを子ウィンドウに

最近、ダイアログウィンドウを他のウィンドウの子ウィンドウとして貼り付けることができるということを知った(知りませんでした)。この方法を使えば、ダイアログを利用しながら、独自のクラス名を持ったウィンドウを作成することができる。単独のウィンドウだからSetForegroundWindowによるフォーカスの問題も起きにくい。PropertySheetだと、多少厄介なのだが、やり方はここに書いてある。ChooseIMとKanaInputの次バージョンは、この方法を採用する予定である。

2009 年 3 月 23 日

ChooseIMのアップデート

カテゴリー: JISかな入力パネル, Programming, Windows Mobile — jk78 @ 9:39 PM

ChooseIMの1.0.1を公開しました。こちらから。

機能的な差はありません。バックグラウンドから呼び出したときに、クリックするまでキーボードが使えない問題などが修正されてます。

「影のフレームウィンドウ」をやめて、ノン・モーダル・ダイアログにしてみました。[メモリ]コントロールパネルから終了できるようになったのはうれしいのですが、なぜかTodayの[実行中のプログラム]にカウントされなくなってしまいました。謎だらけ。

古い投稿 »

Powered by WordPress