ナビゲーションバーの高さ取得とタッチUIの判定

「誰か知りませんか?」などと言ってたわりに、結局自分で思いつきました。ええ。ヒントは先日の改造版だったりします。
まずその改造版ですが、ツールバーの欠けを修正するのにSIPINFO構造体のrcVisibleDesktopを利用していたんですね。これで一体何が判るのかと思って数値を調べてみたんですが、要するに「タスクバー(画面最上部のアンテナマーク等が表示されるエリア)とSIPを除いた領域」が入っていました。
残念ながらこの領域はナビゲーションバーが無い状態を想定したものなので、ナビゲーションバーの高さを得ることは出来ませんが、別の要素は知ることができます。それが改造版が利用しているrcVisibleDesktop.topで、これにはタスクバーのすぐ下の座標、すなわち「タスクバーの高さ」が入っています。改造版ではタスクバーの高さが減った分、GSFinderのウインドウを上に縮めるという方法でツールバーの欠けを修正したのでしょう。ただし、私が勘違いして変なコードを書いていたので*1、ちょっとおかしな事になっていますが。
でも、これだけではナビゲーションバーの高さが求まりません。そこで注目したのが、タスクバーとナビゲーションバーの高さの合計値です。色々と調査した結果、実はこの値がPocketPC2003以降、解像度(厳密にはdpi値)が同じならずっと同じ値だということに気づきました。ちなみに、PocketPC2003からWM6.5まではタスクバーもナビゲーションバーも26ドット(96dpiの場合・以下同様)なので26+26=52ドットです。WM6.5.3のタッチUIではタスクバーが18ドットにナビゲーションバーが34ドットなので18+34=52ドットになります。
なんでこんな所の数値がずっと変わってないのかといえば、おそらくは互換性維持のため。同じ解像度のデバイスにおいて、タスクバーとナビゲーションバーを除いた有効なウインドウの面積が変化することで、表示領域が欠けたりする(経緯は違うがちょうど今回のGSFinderのツールバー欠けのようなことになる)のを防いでいるつもりなのでしょう*2
将来的な互換性は今は考えないことにして(考えても意味が無さそうなので(苦笑))、とりあえずタスクバーとナビゲーションバーの高さの合計値が52ドットだとするなら、ここからタスクバーの高さであるrcVisibleDesktop.topを減算してやれば、それがそのままナビゲーションバーの高さになります。実際には192dpi環境向けに補正をかける必要があるのでこのままでは使えませんが、GSFinder+ for W-ZERO3にはその補正用の数値としてm_fpHighResolutionScaleがあるので、これを利用すれば一発です。コードだとこんな感じですね。

SIPINFO si = {sizeof(SIPINFO)};
SipGetInfo(&si);
int navibar_height = (int)(52.0 * m_fpHighResolutionScale - (float)si.rcVisibleDesktop.top);

そしてもう一つのお題である「タッチUIの判定」もコレを利用していますが、もうちょっと単純です。WM6.5以前であればタスクバーは26ドットなので、rcVisibleDesktop.topが26未満だったらタッチUIだと判断できます。ただし、この判定方法だと俗に言うリアルVGAな環境では誤判定しますが、GSFinder+ for W-ZERO3では元々リアルVGAをサポートしていない(今後サポートする予定もない)ので無問題です。

SIPINFO si = {sizeof(SIPINFO)};
SipGetInfo(&si);
if (((float)si.rcVisibleDesktop.top / m_fpHighResolutionScale) < 26.0)
	m_bTouchUI = TRUE;

さて、これで問題が1つ解決したわけで、さっさと最新版を出さないとイカンでしょうね。チクチクと弄ってますので、もうしばらくお待ちください。

*1:タスクバーの高さ=ナビゲーションバーの高さ=(GetSystemMetrics(SM_CYMENU)+4)*m_fpHighResolutionScaleというのが勘違いで、改造版もこれを引きずっています

*2:そんなところで互換性を気にするなら、APIの挙動の方こそ互換性を持たせて欲しいところではありますが