川俣 晶(かわまた あきら)
1964年4月生まれの東京出身。東京農工大化学工学科を卒業後,マイクロソフトでMicrosoft Windows 2.1~3.0の日本語化に従事。現在はピーデー 代表取締役。日本XMLユーザーグループ代表。Microsoft Most Valuable Professional(MVP)。

 Windows Mobileでは,C標準ライブラリ,Win32 APIともにサブセットしか使うことができない。漠然とした先入観でプログラミングを始めると,あって当たり前だと思った基本的な関数やAPIが存在しなかったり,無いと思った関数やAPIが存在する場合もある。

 ワンべぇWM開発中に遭遇した事例を中心に,このような例をいくつか見てみよう。それがコーディングに与える影響も考えてみる。

ScrollWindowは無い

 まず簡単な事例から見ていこう。ウィンドウをスクロールさせるAPIである。

 16ビット時代にWindowsプログラミングを身体に染みつかせた立場からすれば,無意識的にScrollWindowというAPI名を打ってしまうのは避けられない。しかし,このAPIはWindows Mobileでは提供されていない。

 ではどうすれば良いのかと言えば,ScrollWindow APIの強化版であるScrollWindowExを使えば良いのである。より強力な版が提供されていれば,実質的に困ることはない。引数の数が増えて書くのが面倒になるが,スクロールの処理はソースコード上に何回も書くものではないので,さほど大きな問題ではない。

 さらに言えば,ScrollWindowは後方互換のために用意されたAPIという位置付けなので,むしろ積極的に使わないほうが適切といえる。もし,ScrollWindow APIがあったとしても,ソースコード上にScrollWindowと打った後でF1を押し,APIの説明を読んで「後方互換のためのAPI」だと気づいてあらためてExを書き足すことになる。

 この事例は,ScrollWindow APIが存在しないことは正しく,それによって損をするのは16ビット時代が身体に染みついたロートルだけであることを示す。

TextOutも無い

 TextOutは,最もシンプルな文字列描画APIである。

 これに対して,背景の塗りつぶし,クリッピング矩形の指定,文字間隔の1文字単位の指定などのリッチな機能を持つのがExtTextOut APIである。つまり,ExtTextOutはTextOutの機能強化版として位置付けられる。

 しかし,ScrollWindowが後方互換のために用意されたに過ぎないAPIであるのに対して,TextOutは特にそのような位置付けもなく,一般のAPIとして提供され続けている。なぜ「TextOutはやめてExtTextOutを使おう」と言われないのだろうか。

 その理由は,おそらく文字列描画機能は頻繁に呼び出される可能性があるため,引数が少ないシンプルな版があると便利だからだろう。また,好ましくない挙動や副作用も存在しない。利用を取りやめる理由はない,ということである。

 しかし,それにもかかわらず,Windows MobileではTextOutはサポートされていない。ExtTextOutを使えということだろう…。多少引数は増えるが,増えた引数に0やNULLを書き込めば,TextOut相当の動作は容易に得られる。

 もしかしたら,画面が狭いWindows Mobileの世界では,文字列描画APIの呼び出しを記述する回数も少なくなり,引数が増えても大した問題ではない…ということかもしれない。

なぜExtTextOutはTextOutExではない?

 余談だが,APIの拡張版には末尾にExを付けて区別するのがWindows APIの流儀である。しかし,ExtTextOutはその例外として,先頭に“Ext”を付けて区別している。その理由は,おそらくExtTextOutだけ極めて歴史が長いためだろう。Exを付ける流儀は,おそらくWindows 3.0か3.1のあたりから始まったと思うのだが,ExtTextOutはWindows 2.xの時代にすでに存在していた。


ExtTextOutはなぜ矩形の塗りつぶし機能を持つ?

 ExtTextOutは,クリッピングの指定や矩形の塗りつぶし機能を持ち,非常に強力である。このように複数の機能を詰め込んだAPIは,KISS(Keep It Simple, Stupid)の原則に反するように見えるかもしれない。単純な機能の組み合わせで実現されるものは単純なままにしておくべき,という原則通りに設計するなら,このような複合機能APIを作るべきではないことになる。つまり,TextOutを残し,ExtTextOutを取り除くほうが良いという考え方もあり得るわけである。

 だが,その考え方は誤っている。なぜかといえば,ExtTextOutは要求される機能性を実現する最低限の機能しか持っておらず,無駄な贅肉など無く,最もシンプルな姿だと考えられるからである。

 なぜ,よりシンプルな機能を持った複数のAPIの組み合わせで代用できないのかといえば,「描画の素早さ=ちらつき防止」という要求を実現するためである。非力なマシンでのちらつきを防止するためには,背景を塗りつぶしてからその上に文字を描画するまでのタイムラグを最小に抑える必要がある。

 低レベルの知識はうろ覚えで,しかもWindows Mobileでも同じかどうかわからないが,1回のExtTextOutの呼び出しで行われる描画は,(基本的には)1回のデバイスドライバ呼び出して実行されると思う。つまり,デバイスドライバのレベルで,背景を描いた直後に文字を描くのである。これで,タイムラグは最小となる。

 ちなみに,塗りつぶす背景がブラシではなく,純色(単色)指定であることにも注意を払ってみよう。ブラシで塗るよりも,単色で塗りつぶすほうが高速に処理できる可能性がある。

 他の機能にも同様の理由がある。例えば,クリッピング領域を指定できることは,進行状況を示す数字入り棒グラフなどを描くときに役立つ(実際の事例を紹介しながら説明するとわかりやすいと思うが,本論から離れすぎるのでより突っ込んだ説明は省略する)。

 そのようなわけで,TextOutとExtTextOutの2択であれば,ExtTextOutをサポートするのは正しい選択と言える。