今回の[さまれぼ!サロン管理]バージョンアップで、Windowsのデスクトップテーマに準拠したウィンドウ表示(ビジュアルスタイル使用)が行えるようになりました。ボタンやリストボックスなどのコントロール類の外観がデスクトップテーマに合わせて変わります(詳細は‘さまれぼ!’~デスクトップテーマ準拠表示サポートをご覧ください)。
実装にはリソースファイルで指定する方法もありますが、マニフェストファイルを用いることにしました。マニフェストファイルの有無で、デスクトップテーマ準拠表示するかクラシック表示にするかを切り替えられるためです。これには理由があるのですが、まずはリリースまでの経過をまとめます。
Windows上の調和を考えて、デスクトップテーマに準拠した表示(Windows XPのLunaスタイル)にすることを、およそ2年前に試みていました。この時は、「マニフェスト自動作成君」というマニフェストファイル自動作成やリソース化を行うフリーソフトを使用して用意しました。
そして試したところ、いくつかの問題が判明しました。
最初に気付いたのは、コントロール内の余白が広く取られることです。特にリストビューでは、横スクロールバーが表示されたり、見出しを表示しきれずに「...」だったりしました。これはウィンドウ上のレイアウトを変更すれば対応できます。
次の問題は、OWNERDRAWのプッシュボタンがクラシック表示のままだということです(当たり前のことですが)。‘さまれぼ!’では複数行ラベルのボタンやアイコン付きボタンをOWNERDRAWで描画しています。また、仮想キーボードではボタンコントロールを用いず全て自前で処理しています。これをデスクトップテーマに合わせて描画する必要があります。
色々調べた結果、OpenThemeData/CloseThemeData/DrawThemeBackground のAPIを使って実装しました。
こうして一見してわかる問題は解消できましたが、次にリストビューの動作に問題が見つかりました。フロント設定画面のリストビューを改ページした際に表示が乱れるのです。具体的には、改ページ後、横線の間隔が狭くなって、文字が読み辛くなります。これは、OWNERDRAWのリストビューでも同様で、間隔の指定が小さくなったのかと疑ってOWNERDRAWでの描画領域をデバッグログ出力しましたが、別に小さくはなっていませんでした。
また、一行ずつスクロールする場合には問題ありません。
結局原因はわからず、後回しにすることにしました。
ここまで確認してWindows XPでは問題ないようなので、Windows Vistaで動作確認を行いました。すると、フロント画面のカレンダーが指定したサイズに収まりきらないという問題が見つかりました。カレンダーはWindowsのコントロールを使っているようなのですが、文字の間隔が広く右端の土曜日が表示されません。念のためWindows 7でも確認すると、Vistaと同様でした。
おそらくカレンダーの最小サイズが、こちらで指定したサイズより大きいのでしょう。
Vista/7に合わせると非常に大きくなってしまうだけでなく、XPでは左右に隙間ができてしまいます。
この問題を解消する手段が見つからず正式リリースできませんでしたが、今回のバージョンアップで対応することにしました。
まずカレンダーの問題は、自前のカレンダーを用意することで解決しました。ただ移行するだけではなく、カレンダーサイズを変更できるようにしました。これはタッチパネルでの利用を考えてのことです。
また、店休日を黒色で表示するようにしました。これは以前より要望されていたことでした。
次にリストビューの改ページの問題です。
まず、Windows Vista/7では問題ありませんでした。どうも改ページの途中経過が残像として消え残っているらしいとわかりました。
SetWindowTheme APIでリストビューのテーマだけを解除してみたが、結果は変わりません。
ThinkPad T61入手後に確認すると問題なかったので、Windows XPの問題ではありません。PCの処理速度が遅く、描画が追いつかないような感じです。
「画面のプロパティ」-「デザイン」-「効果」で、「ドラッグ中にウィンドウの内容を表示する」のチェックを外しても、アニメーション効果を変更してもダメでした。スクリーンフォントの縁も、「メニューの下に影を表示する」も関係ありません。
結局、この問題は解消できませんでした。
そこで、デスクトップテーマに準拠しない表示も行えるように、マニフェストによる切り替えとしました。ただ、10年も前のXP機を使う人はそうないないでしょうから、この問題に当たる人は多くはないと思います。
一通り問題に対処して最終テストをしている最中、新たな問題が見つかりました。仮想キーボードで文字入力する際、こちらで指定した上限値を超えて入力できるのです。どうもエディットボックスの上限がバイト数ではなく文字数になっているようです。
調べてみると、これは仕様だということがわかりました(詳細はこちらのMicrosoftサポートページをご覧ください)。
毎度のことですが、マイクロソフトの傲慢さには呆れます。
エディットボックスをサブクラス化して自前でチェックするのはトラブルの元なので、仮想キーボード終了時にバイト数をチェックし、オーバーした分を除去することにしました。バイト数は多めに指定しているので、問題ないと判断しました。
既知の問題に対処して、晴れてリリースできる状態となりました。
インストーラを作成して動作確認したところ、新たな問題が判明しました。‘さまれぼ!’をバージョンアップすると、マニフェストファイルがあってもテーマ準拠表示しない場合があるのです。
1.63から2.00にバージョンアップして、フロント設定でテーマ準拠表示に切り替えます。‘さまれぼ!’を実行し直すとテーマ準拠表示になるはずですが、Windows 7ではクラシック表示のままです(XPでは切り替わりました)。
初めはマニフェストファイルに問題があるのではないか(publicKeyTokenなど)とも考えましたが、色々試すうちに、どうやらOS側でマニフェストファイルを参照したかどうか記憶しているようだということがわかりました。
- 最初にマニフェストなしで起動すると、それ以降マニフェストの有無とは関係なくクラシック表示になる。Windowsを再起動してもマニフェストは認識されない。
- テーマ準拠表示された後はマニフェストの有無に合わせて表示が切り替わる。
- マニフェストがある状態でEXEのタイムスタンプを変えた後に実行すると、テーマ準拠表示になる。
これらの事象から、WindowsがEXEごとにマニフェストの有無を記憶していて、EXEのタイムスタンプが変わった状態でチェックし直しているのではないか、という結論に達しました。
チェックの際にマニフェストがなければフラグがクリアされ、マニフェストの有無をチェックしなくなり、常にクラシック表示になります。
一方マニフェストがあればフラグが立ち、EXE実行時にマニフェストを参照します。ここでマニフェストがない場合はクラシック表示となりますが、フラグは立ったままです。そのため、次にマニフェストがあればテーマ準拠表示になります。
もしもテーマ準拠表示にならない利用者が頻発するようなら、タイムスタンプが1ミリ秒変わっただけでテーマ準拠表示になるので、タイムスタンプ変更ツールを用意しようと考えています。
こうしていくつもの問題を乗り越えて、やっとリリースに漕ぎ着けました。コントロールの余白やOWNERDRAWプッシュボタンの問題は予想していましたが、それ以外は思いがけないものでした。
いつもながら、Windowsでの開発は想定外との戦いです。
最近のコメント