0 リソースから読み出す ■ワタソン「それじゃあ , この質問にも答えてくれよ。なんでリソースに入れた BMP フ ァイルを読み出すと , DDB のハンドルになってしまうんだい ? 」 マホラムズ「サービスと考えていいんじゃないかな。 DDB のほうが高速だし処理が楽だ」 ・ワタソン「でも , それじゃあ困ることもあるよ。それを BMP ファイルとして書き込み たかったりすることもあるだろうし。それに , DIB 機能を測定するべンチマ ークテストも作れなくなってしまうじゃないか」 マホラムズ「ふむ。つまり , L 。 adBitmapAP1 が勝手に変換してしまうのが困る場合もあ るというわけだね」 ■ワタソン「そうだよ。できればそのまんま DIB 形式で参照できないかと思ってね」 「少々ややこしい注文だなあ」 マホラムズ ■ワタソン「不可能かい ? 」 マホラムズ「いや , そんなことはないよ。今度はリソース関係の API の説明になるけど , いいかな ? 」 ■ワタソン「よしきた。 LoadDIBitmap とか , そういう API があるのかい ? 」 マホラムズ「残念でした。そんな API はありません」 ■ワタソン「じゃあ , どうやるんだい ? 」 マホラムズ「リソースの種類は , ビットマップやアイコンやメニューやストリングだけ じゃないってことは知っているかな ? 」 ■ワタソン「え ? あとはアクセラレータとか ? 」 ▽ホラムズ「そういう , マニュアルに書いてあるもの以外にあると思うかい ? 」 ■ワタソン「わかった。隠しリソースだね ? 」 ホラムズ「残念。そうじゃなくてユーザー定義のリソースさ」 ■ワタソン「ユーザー定義 ? 」 マホラムズ「つまり , プログラマが自分で , リソースの新しい型を定義して使うことが できるんだよ」 ワタソン「それは知らなかったなあ。でも , 自分で作ったリソース型なんてリソース コンパイラがエラーになってしまうんじゃないか ? 」 マホラムズ「だから文法的には , データを記述するのではなくファイル名を指定するよ うになっているんだ。自分で定義したリソースはファイル名だけ書いて , そ のファイルの中にデータを書き込むわけだ」 ■ワタソン「ふむふむ。それは , 知っていると利用できそうなテクニックだなあ」 マホラムズ「例えば , ビットマップをリソースに取り込むときは , よく TIDB BITMAP 7-
い 第 14 章 A 円スへシャル・ Wi nd ows 殺人事件 どがあるから , EXE ファイルのままリソースを書き換えるのも簡単にできるんだ」 「いまは , ポーランドのリソースワークショップや , マイクロソフトの AppStudio な 換えて , リソースコンパイラを通して・・・・・・」 「でも , そう簡単にリソースは書き換えられないだろう ? リソーススクリプトを書き 「 Macintosh なんかでは , リソースはウイルスの巣とまでいう人がいるらしい」 放題じゃないか」 「そうか」僕はようやく理解した。「それじゃあ , リソースにはなんでもデータを入れ 「アプリケーションから参照されることはないから , 別に問題を起こしたりはしない 以外のデータはどうなるんだろう」 「アプリケーションの実行に必要なデータは全部リソースに残っているんだよね。それ タには手を触れず , 未使用の ID 名でデータを追加したらどうなると思う ? 」 「既存のデータを置き換えたらね」ホラムズは首を横に振った。「しかし , 既存のデー うじゃないか」僕は反論した。 「でも必要なデータがなくなったら , アプリケーションが正常に動作しなくなってしま リソースなんかはどんなデータでも格納できる」 「いくつか考えられる」ホラムズは真顔でうなずいた。「例えば , EXE ファイルの中の 隠せる場所があるのかい ? 」 「 Windows ならではね・・・・・・」僕はため息をついた。「でも , そんなに都合よく , 情報を かない場所だろうね。 Windows ならではの隠し場所だ」 「とすれば , なにかのメッセージが隠されているとしたら , MS -DOS の知識の手が届 はうなずいた。「 x. T というやつだ」 「しかし , MS-DOS レベルの技術に関しては , エキスパートがいたってことだね」僕 Windows に絡んだ仕事だった。そういうことだな」 な情報が得られた。斉藤氏は , なにかの組織に , なにかの仕事をさせられていた。それは 「さてと」ホラムズはふたたび , ノートパソコンに向き直った。「ともかく , いろいろ 「もういい。近くの公衆電話でかける」レストラン警部はそういい残して出ていった。 「レストラン警部 ? 」僕は呼びかけた。 レストラン警部は , 立ち上がりかけた体を途中で凝固させた。 れた 10 キーをマウスでクリックしてダイヤルすれば通常の音声回線につながる」 ージャの電話のアイコンをダブルクリックして , 電話マネージャを開いて , そこで表示さ 「どうぞ。そのパソコンにつながっているヘッドセットを頭につけて , プログラムマネ レストラン警部はうなずいた。「わかった。電話を借りるぞ」 「一応 , 該当する犯罪者などを調べてくれませんか ? 」 「とはいっても , せつかくの手がかりだ。調べない手はない」ホラムズは平然と続けた。
固定されたデータテープルなどは , 拡張された D 旧を この方法を使って全部リソースに入れて しまうべきだと思う。 MS-DOS べースでは , 実際に実行する EXE ファイル のほかにいろいろなデータファイルを要求されることがあるけど , これは美 しくない。だいたい , ユーザーから見て削除していいファイルなのかどうか , はっきりと区別がつかない。だから , せつかくリソースが使えるんだから固 定されたデータはリソースに取り込んでしまい , 設定値などは INI ファイル などに書き出すように統一したいものだね」 ーワタソン「でも , Windows でもなかなかそれは実現できていないんじゃないかな。ア プリをインストールすると , 結構いろんなファイルがいっしょに入ってくる し。それが全部必要なのか , はっきりしないしね」 マホラムズ「まあ , 全部が全部そうでなければならないというものでもないしね。固定 されたデータテープルであっても , あとで簡単に差し替えられたほうがいい 場合もあるし。でも , Windows ならファイル数を減らせる方法があるってこ とを , 知っておくのも悪くないだろう ? 」 ■ワタソン「うん。僕もそう思うよ」 マホラムズ「あとは余談だけれど , WindowsNT では , リソースに書き込まれる文字は 全部 Unicode になる」 ■ワタソン「え ? それじゃあ , シフト JIS を前提にして書いたアプリは全部書き換えだ マホラムズ「そうじゃないよ。 LoadString を使って読み込んでいれば自動的に文字コー ド変換が入るらしい」 ■ワタソン「ふうん」 ホラムズ「つまりね , L 。 adBitmap で DIB から DDB に勝手に変換してくれるのと , 同 じようなことなんだ」 ■ワタソン「え ? どこが ? 」 マホラムズ「つまり , DIB のことをなにも知らない Windows2. x のアプリケーションが , ソースを書き替えなくても Windows3.0 に対応できたってこと。リソースを 活用していると , そういうメリットもあるんだよ」 ■ワタソン「なあるほど。わざわざリソースを使うのは面倒だと思っていたけれど , そ んな価値もあるんだね」 ■ワタソン「なんだい ? 」 マホラムズ「最後の補足をしておこう」
。、第第 7 章 BMP ファイルと D 旧 マホラムズ「そうだ。それに重要な機能でもあるよ。ちょっと DIB から話はそれるけど。 ■ワタソン「でも , 結構面白そうな機能じゃないか」 平ホラムズ「ステップが多いだけで , 迷うようなことはそれほどないはずだよ」 ■ワタソン「うわ。すごく面倒くさそう」 のが決まりだ」 ら UnlockResource API と FreeResouce API を呼び出して , あと始末をする ルの中身そのまんまだ。あとは自由に参照してかまわない。参照が終わった インタが返ってくる。そのポインタが示しているのは , まさに BMP ファイ てくる。そして , LockResourceAPI を呼び出して , それをロックするとポ 情報をもとにリソース本体を読み込んでくれて , リソースのハンドルが返っ のハンドルを引数として LoadResource API を呼び出す。すると , リソース ソースを検索する。その結果 , リソース情報のハンドルが返ってくるからこ ▽ホラムズ「まず , FindResource APIO これは , 指定したデータ型で指定した名前のリ ワタソン「どんなの ? 」 教えよう」 マホラムズ「もちろん , いわないさ。そのためには , うってつけの API がある。これを 読み出すなんてこと , いわないよな」 LoadString も LoadMenu も使えないし。まさか EXE ファイルをオープンして ■ワタソン「あ , そうか。でも , それは困ったぞ。 LoadB itmap が使えないとすると , ビットマッブハンドルしか返せない仕様だしね」 んだから LoadBitmap ではエラーになるよ。それに , LoadBitmap は DDB の マホラムズ「それはダメだよ。だって , システムはビットマップじゃないと思っている ■ワタソン「そこで LoadBitmap をすればいいのか」 けだ」 マホラムズ「そう。そうなると勝手に DDB に変換してしまうような機構は動作しないわ ータだと思い込むんじゃないか ? 」 第ワタソン「もしかして , システムはビットマップじゃなくてなにかユーザー定義のデ と思う ? 」 マホラムズ「ともかく , BMP ファイルをこの方法でリソースの中に記述したらどうなる ■ワタソン「いつも , 宣言や定義を要求する Windows にしては珍しいなあ」 マホラムズ「いや , 宣言とか定義は不要で , いきなり書いても大丈夫だ」 ■ワタソン「それで , その MYDATA はどこで宣言するんだい ? 」 るんだ。 MYDATA が , 自分で定義したデータ型の名前だよ」 様に「 IDMY_DATANAME MYDATA FiIeName. MYDJ というように書け NAME BITMAP FiIeName. BMP 』なんていうふうに書くよね。それと同
ノ宿第 14 章 A 円スへシャル・ Windows 殺人事件 「まあ待て」ホラムズはゆっくりと首を横に振った。「 x. T がリソースをのぞく能力を 「じゃあ , もっと探そう」僕は手伝おうとして身を乗り出した。 た。「探せば , ほかにもあるかもしれない」 「ファイルマネージャ winfile. exe の文字列型リソースの中にあった」ホラムズは説明し 「これは , どうやって入っていたんだい ? 」僕は質問した。 Windows. 』とか , 「このプログラムを実行するには Windows が必要です』というメッセー く。このダンプは 200 番地から始まっているね。これは , TThis program requires Microsoft をもっている。そして , スタブプログラムと呼ばれる小さなプログラムがそのあとに続 MZ で始まる最初のヘッダは , 基本的に DOS アプリケーションの EXE ヘッダと同じ構造 EXE ヘッダ十スタブプログラム十ニュー EXE ヘッダの 3 つのパートが先頭に存在する。 いのにダンプリストを表示させて説明を始めた。「 Windows の EXE ファイルは , DOS の 「では , EXE ファイルの構造について , 少し説明をしよう」ホラムズは , 頼みもしな 「いやないが・・・・・・」 「もちろん。君は Windows の EXE ファイルを 16 進ダンプしたことがあるかい ? 」 「ほかにも , 情報を隠せるような場所があるのかい ? 」 「もっとほかの場所を探そう」ホラムズはうなずいた。 「じゃあ , どうするんだい ? 」 すというのは , 考えられないんじゃないかな」 もっているということを斉藤氏が知ったとすれば , 斉藤氏がなにかの情報をリソースに残 ジを表示させる DOS のプログラムだ。 こまでは , 古い DOS で起動すると , 通常の DOS 用の EXE ファイルとして認識される。だから , DOS で Windows のプログラムを起動して も , 暴走せずに警告メッセージを表示して DOS に戻るわけだ」 ふむふむ , なるほどと思っていると , レストラン警部が口をはさんできた。「おまえら , いったい , なにを話しているんだ ? 」 「すいません」僕は , 思わずホラムズの話につり込まれてしまったことを後悔した。普 通の人には , 理解できるはずもない。僕は , なるべくわかりやすいように , レストラン警 部に説明した。 説明が終わると , 「そうか , わかったよ」レストラン警部はゆっくりうなずいた。 「よかった」僕はほっとした。 「機械オンチの俺には , 絶対にわからんということが , よくわかった。勝手に話を進め てくれ」レストラン警部は , そういった。僕はやつばり , レストラン警部が嫌いだ。 「では続きをやるぞ」ホラムズが話を続けた。「 400 番地から Windows 専用のヘッダが 始まっている。 NE で始まる NE ヘッダだ 、から , セグメントに関する情報や , リソ ースに関する情報などが並ぶことになる」
・物第 5 章 MDI の作り方 ワタソン ワタソン「おお。そいつはうつかりしていたな。やつばり , リソースは大事にしなく を使う必要がある」 マホラムズ「いや , ダメだ。使われなくなったメニューを破棄するために , DestroyMenu ムズ ? 」 するとメニューが差し替わるから , それで完了か。これで完璧だろう , ホラ ってこられるから , それを引数にして WM_MDISETMENU を送って , そう ワタソン「よし , 僕も考えてみよう。ええと , メニューのハンドルは LoadMenu で取 やこしい」 v ホラムズ「そのとおり。だが , 引数に渡すべき新しいメニューのハンドルの扱いがや て , 差し替えさせるんだったよな」 「ああ。 WM_MDISETMENU メッセージを MDICLIENT ウインドウに送っ たときに , メニューの差し替えができるという話はしたよね」 マホラムズ「次は , メニュー差し替えの問題だ。 WM_MDIACTIVATE メッセージがき ちゃいけないものな」 マホラムズ「ところが , 問題はこれだけじゃない」 ■ワタソン「まだあるの ? 」 マホラムズ「勝手にメニューを LoadMenu する API と , 勝手にメニ する API があるんだ」 ■ワタソン「ええっ ! ? 」 マホラムズ「 LoadMenu してないメニューを DestroyMenu したり , ューを DestroyMenu LoadMenu したメ ューを DestroyMenu しないでおくと , Wind 。 ws のシステム全体の動作がお かしくなってしまう。だから , そのへんにも注意を払っておかないと , とん でもないバグをはらんだプログラムになる可能性がある」 をワタソン「いったい , その API ってなんだい ? 」 マホラムズ「 CreateWindow と DestroyWindow だよ」 ■ワタソン「そんな馬鹿な」 マホラムズ「本当だよ。 CreateWindow は引数でメニューハンドルが指定されず , クラス 登録時にメニューのリソース名が指定されていると自動的にメニューをロー ドする。それとは逆に DestroyWindow は , そのウインドウに付属している メニューを自動的に破棄しているんだ」 ■ワタソン「それは知らなかったな。メニューはいつも使っているのに」 ▽ホラムズ「 WM_MDISETMENU メッセージを使うときには , 注意しなければならな い。 WM MDISETMENU で MDICLIENT ウインドウに送ったメニューハン ドルは , 最終的に DestroyWindow のときに破棄されるはずのハンドルなの で , DestroyMenu を呼び出してはならない。そして , WM—MDISETMENU
直前のインスタンスー してしまうことになる。同じウインドウの設計図をいくつも登録するのは , メモリの無駄だとは思わないかい ? 」 「確かに・ マホラムズ「しかも , RegisterClass が消費するのは貴重なシステムリソースだ。消費量 を減らせるものならできるだけ減らしたいのが人情だろう」 「じゃあ , それを節約するために hPrevInstance によって , RegisterCIass した りしなかったりするわけなんですか ? 」 マホラムズ「そうだ。 hPrevInstance を調べて , NULL だったら最初の起動だから RegisterClass してやる。しかし , hPrevInstance が NULL でないなら , 同じ プログラムがすでに起動され設計図の登録がすんでいるから , RegisterCIass は行わない。そういう仕組みになっているわけだ」 「それは , ずいぶん賢い仕組みなんですね」 ▽ホラムズ「 Windows は , システム資源節約のための仕組みがいつばい詰まったシステ ムさ。 DOS なんかよりもはるかに少ないメモリで効率よく動くよ」 「でも , Windows って DOS よりも要求メモリ量が多いですよ」 マホラムズ「それは DOS がやっていない多くの仕事をこなしているからさ。 Windows が システム資源の無駄遣いをしていると思ったら大間違いだ。これだけのシス テムを , この程度のメモリで動かすというのはやつばりすごいことだと思う よ」 「わかりました。頑張って , また取り組んでみます ! 」 マホラムズ「うんうん。わからないことがあったらまたいつでも来なさい」 ☆パステル「はい ! ありがとうございましたつ。ホラムズ先生 ! 」 ■ワタソン「僕のことは忘れられているのね。しくしく」 「あ , ワタソン先輩もありがとう。頼りなかったけど質問に答えてくれてあ りがとうございまーす」 ・ワタソン「頼りないは余計だよ」 ☆ / ヾステル ☆ / ヾステ丿レ ☆ / ヾステル ☆ノヾステル ☆ノヾステ丿レ ☆ / ヾステル
第 5 章 MDI の作り方 OM のメニュー のメニューを設定するといいね」 マホラムズ「そのとおり。そういうときには , [ 新規作成 ] と [ 開く ] と [ 終了 ] だけ んだね ? 」 ワタソン「だけどひとつでも MDI 子ウインドウがあれば , 決して NULL にはならない り値が , いつも有効なウインドウハンドルを示していると考えてはいけない ■ワタソン「そういえば , そのへんの処理をやるための A 円の説明はまだ聞いてないな」 ックスが出る」 なんて項目もできて , これを選ぶと , MDI 子ウインドウを選ぶダイアログボ るだろう ? それに , ウインドウが増えると , [ そのほかのウインドウ… ] インドウを作ったり消したりすると , [ ウインドウ ] メニューの中身が変わ マホラムズ「 [ ウインドウ ] メニューの中の , MDI 子ウインドウのリストさ。 MDI 子ウ 第ワタソン「自動的って , なにを作ってくれるんだい ? 」 について」 マホラムズ「まず最初に , MDICLIENT がメニューの一部を自動的に作ってくれる機能 ■ワタソン「順番に聞かせてくれよ」 マホラムズ「そう。それにも問題があるし , ほかにもいろいろと問題がある」 メなのかい ? 」 それを WM_ACTIVATE メッセージで切り替えるんだよね。それだけじやダ ■ワタソン「 MDI 子ウインドウの種類の数だけメニューをリソースに記述しておいて , マホラムズ「こいつが難しいんだ」 ーワタソン「メニューがどうかしたのかい ? 」 マホラムズ「さて , 最大の難関がメニューだ」 マホラムズ「実は , ないんだ」 ■ワタソン「なんだって ! じゃあ , もっといろいろな A 円を組み合わせて , くのかい ? 」 マホラムズ「その反対さ。全部 MDICLIENT ウインドウがやってくれるので , 自分で書 なにも書 かなくていいんだ」 ■ワタソン「なんだか得した気分」 ホラムズ「ただし , 何番目のメニューに追加するのか , ない」 ■ワタソン「どうやって指定するんだい ? 」 それだけは指定しないとなら
M 団のメニ ュ、 マホラムズ「まだ説明していなかったが , MDICLIENT ウインドウを CreateWindow す るとき , CLIENTCREATESTRUCT という構造体を準備して , これへのポイ ンタを引数 lParam に入れて渡す。この CLIENTCREATESTRU.CT には 2 つ のメンバーがある。ひとつは hWindowMenu で , メニューの中の [ ウインド ウ ] メニューのハンドルを入れる。もうひとつは idFirstChild で , こちらは アプリのほうに通知してくるときの ID 番号の最低値を入れる。これが 5000 なら , メニュー中で 1 番目の MDI 子ウインドウを選んだとき , ID = 5000 の WM_COMMAND メッセージがくる。メニュー中で 2 番目なら ID = 5001 だ」 ■ワタソン「ちょっと待ってくれ。その前に [ ウインドウ ] メニューのハンドルってな んだい ? 」 マホラムズ「メニューというのは , 一種のリソースだね。 LoadMenu なんかで , 読み込 めるわけだ」 ■ワタソン「それくらいは知っているよ」 ▽ホラムズ「 LoadMenu したメニューは , さらにいくつかのメニューから成り立ってい る。これがサプメニューだね。例えば [ ファイル ] , [ 編集 ] , [ ウインドウ ] , [ ヘルプ ] というメニューがメインメニュー。ファイルメニューの中の [ 新 規作成 ] , [ 開く ] , [ 終了 ] というのがサプメニュー。サプメニューの中に さらにサプメニューがあることもある」 ■ワタソン「なるほど」 マホラムズ「で , [ ウインドウ ] メニューのハンドルというのは , メニューの [ ウイン ドウ ] をクリックしたときに出てくるサプメニューのハンドルだ。 API を使 ってこんなふうにすると得られる ( リスト 2 ) 」 「ウインドウ」メニューのハンドル ュー中の順番 ) : GetSubMenu( メインメニューのハンドル , メインメニ リスト 2 自動的に作ってくれる ■ワタソン「なるほど。これで得られるサプメニューの中身を , というわけだな」 このことは忘れてしま マホラムズ「そのとおり。機能がデフォルトのままでよければ , ってもかまわないよ」 ■ワタソン「よし。これでメニューは完璧だ」 マホラムズ「いいや , まだまだ」 ■ワタソン「まだあるの ? 」
第 7 章 BMP ファイルと D 旧 マホラムズ V ホラムズ ■ワタソン「 DIB ? 」 ワタソン「証明といっても , ここには SDK のマニュアルもなにもないじゃないか」 マホラムズ「それじゃあ , この場で証明してあげようじゃないか」 ■ワタソン「うそだろう ? 」 ▽ホラムズ「そんなことはないよ」 ■ワタソン「でも , SDK のマニュアルとかには載ってない知識がいるんだろう ? 」 「できるとも」 ■ワタソン「じゃあ , 公開 API だけでもできるのかい ? 」 API とか , まあそんなものだね」 ようなクズ API とか , 単に過去のバージョンとの互換性のためについている ちょっと特殊な処理をやるときに必要な API とか , 箸にも棒にもかからない マホラムズ「そりゃ , 隠し API くらいあるよ。だけど , そんなにたいした API はないよ。 いてあるよ」 住ワタソン「だって , やつばり Wind 。 ws に隠し API があった ! とか , 雑誌なんかに書 「ない」 の ? 」 ■ワタソン「もしかして隠し API 一発で , どーんといけるとか , そういう楽な手はない んあるね」 マホラムズ「確かに , これを実現するためには乗り越えなければならない障害がたくさ いわけだね ? 」 Y ホラムズ「ふむふむ。要は BMP ファイルを読み込んで , これを画面に表示できればい いてあるが , さつばりわからん。ホラムズ , なんとかしてくれよ」 きないよ。サンプルソースや解説を見ているとあたりまえのことのように書 出力機器に依存するビットマップ ) になってしまうんだな。さつばり理解で API でそれを読みにいくと , なぜかこれが DDB (Device Dependent Bitmap わからない。ついでにリソースに B MP ファイルを入れて , LoadB itmap の ない。それから , それを読み込んでからどうやって表示させたらいいのかも ■ワタソン「いろいろだよ。まず , BMP ファイルのファイルフォーマットがよくわから マホラムズ「具体的には , なにがわからなくてつまずいたんだい ? 」 ・ワタソン「そのマニュアルが理解不能なんだもの。困ってしまうよ」 マホラムズ「ちゃんとマニュアルを読んだかい ? 」 いんだよ。いったい , どういう意味 ? 」 ■ワタソン「それくらい知っているよ。でも , それもなにがなんだか意味が理解できな マホラムズ「出力機器に依存しないビットマップだよ」 臨ワタソン「そうそう」