メッセージ - みる会図書館


検索対象: 月刊 C MAGAZINE 1990年6月号
28件見つかりました。

1. 月刊 C MAGAZINE 1990年6月号

最新 ウシステム 入門 ウイン、 数は読み出すメッセージの種類を限定する インスタンス変数に似ています。 いるのて、す。それが可能な理由は Fig. 4 の ためのマスクの役割をしますが , ふつうは MSG 構造体のメンバを見れば理解していた Windows や PM において , ウインドウは どちらも 0 にして , すべてのタイプのメッセ だけます。 Windows にはウインドウブロシ 自己の記憶域と同時に , 決まった特性 , あ ージを読み出すことになるて、しよう。 ージャのようにシステムの側から呼び出さ るいは動作をもっているという意味におい て , オプジェクト指向の概念て、いうオプジ れる関数がいくっかあります。それらの関 ウインドウブロシージャ 数は , アプリケーションのモジュール定義 ェクトとよく似ています。オプジェクト指 向言語て、はオプジェクトに動作するきっか ファイル ( 拡張子 . def : Windows のアプリケ ウインドウブロシージャは最初に示した ーションプログラムをリンクするとき指定 けを与えるものをメッセージと呼んて、いま イベントループのスイッチ文だけを抜き出 します ) の EXPORTS 文に列挙しておきま す。 Windows や PM て、はこのことを意識し したような関数てす。先ほどのふたつのポ てか , イベントのことをメッセージと呼ん す。その事情は [ 文献 5 ] に詳解されているの タンをもったウインドウを想定すると Win て、います。同様にイベント ( ディスパッチ ) て、参考にしてください dows のものは次のようになるてしよう。 ループは「メッセージループ」と呼んていま メッセージループには , TransIateMes long FAR PASCAL WndProc( す。今後本稿て、も Windows や PM に関して sage( ) という API がディスパッチルーチン HWND hWnd, の前に入れられています。この API はどれか はイベントという言葉の代わりにメッセー unsigned iMessage, のキーポードが押されたというキーストロ ジという言葉を使うことにします。 WORD wParam, ークメッセージからキャラクタコードメッ メッセージループ LONG IParam) セージを作ってキューに入れます。ほとん どの Windows のプログラムのメッセージル これまて、にイベントループとディスパッ ープはこのようになっています。また GetM es チループの例をひとつずつ紹介しました。 sage ( ) の第 2 引数に特定のウインドウへのハ このふたつのループを見て , 「このループは ンドルを入れると , そのウインドウ向けの どうやって終わるのだろう」と疑問に思われ メッセージだけが読み出されます。第 3 , 4 引 たかもしれません。いろいろなウインドウ システムのイベントループの抜け方を比較 Fig. 4 MSG 構造体 これらの構造体は SKD に付属の Windows. h ヘッダファイルで定義されています。 するのもおもしろいのてすが , Windows の メッセージループを見ていくことにします。 / * ウインドウクラスデータ構造体 * / Windows てはキューからメッセージを読み typedef struct tagWNDCLASS { / * クラススタイル * / WORD style; 出すには , 通常 GetMessage( ) を使います。 (FAR PASCAL *lpfnWndProc) ( ) ; / * ウインドウブロシージャ * / long この API はアプリケーション終了を知らせる / * ウインドウクラスの付加情報を記憶するバイト数 * / int cbClsExtra; WM QUIT メッセージを読み込んだ場合にだ int / * ウインドウインスタンスの cbWndExtra; / * プログラムインスタンスのハンドル * / HANDLE hlnstance; け 0 ( 偽 ) を返し , そのほかのメッセージを読 クラスアイコンのハンドル * / HICON hlcon; み込んだときには 0 以外の値 ( 真 ) を返しま / * クラスマウスカーソルのハンドル * / HCURSOR hCursor; / * クラス背景ブラシのハンドル * / す。そこてメッセージループは次のように HBRUSH hbrBackground; LPSTR lpszMenuName; / * クラスメニューのリソース名 * / 己述てきます。 LPSTR lpszCIassName; / * ウインドウクラスの名前 * / while (GetMessage(&msg, NULL, 0 , 0 ) ) { ) WNDCLASS; TransIateMessage(&msg); / * メッセージデータ構造体 * / DispatchMessage(&msg); typedef struct tagMSG HWND hwnd; / * メッセージを受け取るウインドウのハンドル * / WORD message; / * メッセージ番号 * / , こて , プログラムからは直接ウインド WORD wParam; / * メッセージの付加情報 * / ウブロシージャを呼び出してはいない LONG lParam; / * メッセージの付加情報 * / に注意してください。 DispatchMessage( ) DWORD time; / * メッセージがキューにポストされた時間 * / / * メッセージがポストされたときのマウスカーソルの位置 * / POINT pt; A 曰が , メッセージが送られるべきウインド } MSG ウのウインドウブロシージャを呼び出して switch (iMessage) { case WM COMMAND: switch (wParam) { case ID YES: 1 三ロ 特集最新ウインドウシステム入門 57

2. 月刊 C MAGAZINE 1990年6月号

C 十十 プログラミング 入門 Fig. 2 「エラトステネスのふるい」による素数の生成 整数の集合 ■オプジェクトとメッセージ こてのプログラムの設計は , 次のふたつの要素 によって進めます。ひとつはプログラムの動作単位 のオプジェクト , もうひとつはオプジェクト間の情 報交換のメッセージて、す。その動作イメージは , Fig. 3 のように示すことがて、きます。 上記のような設計により , 素数生成アルゴリズム をオプジェクトおよびメッセージて、表現すれば , そ のプログラムは , ふたつのオプジェクトおよびその 間のメッセージから構成されます。それらのオプジ ェクトは以下のようなものて、す。 ・オプジェクト Gen( ジェネレータ ) このオプジェクトは , 2 以上の整数を次々に生成し ます。その整数は , 次に説明するオプジェクト Filter のふるいにかけられます。 ・オプジェクト Filter( フィルタ ) 最小の整数 7 は素数である このオプジェクトは , ひとつの素数をもち , その て、は , それらを出力ストリーム cout に渡していま 値により , ほかのオプジェクトから ( メッセージによ す。 り ) 受け取った整数にふるいをかけます。実際は , 受 け取った整数が自身の素数の倍数て、あ要吸収 ( 無視 ) ■プログラム解説 し , 倍数てない場合に次のオプジェクトに渡します。 このようにふたつのオプジェクトとして表現され 渡す先の , 次のオプジェクトがなければ , その整数 た問題を , C 十十のプログラムとしてコード化するこ は素数てあるから , 新しいオプジェクト FiIter を生成 とにします。 します。 ・オプジェクト Filter( フィルタ ) 上記の動作を図示すると , Fig. 4 のようになりま まず , オプジェクト FiIter は , List6 のようにクラス す。そして , 各オプジェクト F Ⅲ e 「がもつ素数を集め 定義がてきます。このオプジェクトは , 内部データ れば , 目的の素数の集合を得ることがてきます。 Fig. 4 Fig. 3 オプジェクトとメッセージの並列動作のイメージ Fig. 4 プログラム p ⅱ mes の動作のイメージ Gen 素数 〇〇 0 8 最小の整数 2 は素数である 〇〇 2 の倍数を取り除く 〇 0 〇 〇 0 〇 最小の整数 5 は素数である 5 の倍数を取り除く 〇〇 最小の整数 3 は素数である 3 の倍数を取り除く 2 ′ 3 ′ 4 第 5 ′ 6 を 7.8 ′ . ′ 20 ′ 21 ′ 22 を F 搬・「 2 を 21 を 3 21 ′ 03 ・ am cout 21. 2 104 CMAGAZINE 19 6

3. 月刊 C MAGAZINE 1990年6月号

"HeIIo, wo 日 d / " を表示するプログラム ( C ) 60 : { List2 int PASCA し WinMain(HANDLB hlnstance, / * この起動用のハンドル * / long FAR PASCA し HelloWndProc (HWND, uns igned, WORD, LONG) : 1 : #include く windows. h> 2 : 3 : 4 : 5 : 7 : 8 : 10 : 13 : 14 : 17 : 19 : 20 : 22 : 23 : 24 : 26 : 28 : 29 : 30 : 32 : 33 : 34 : 35 : 36 : 38 : 39 : 40 : 41 : 42 : 43 : 44 : 45 : 46 : 48 : 49 : 50 : 52 : 53 : 54 : } 55 : 56 : 57 : 58 : 59 : 62 : 64 : 66 : 68 : HANDLE hPrevInstance, LPSTR lpCmd し ine, int nCmdShow) HWND hWnd; MSG msg; WNDC し ASS wndClass : / * 前の起動のハンドル * / / * コマンド行の引数 * / / * ウインドウの表示のされ方 * / / * メイン・ウインドウ用のハンドル * / / * メッセージ・ループ内でメッセージを保持する * / / * ウインドウ・クラスの構造体 * / if (!hPrevInstance) { / * これが最初の起動か ? * / wndCIass. style = NU しし : wndCIass.IpfnWndProc = Hel loWndProc; wndClass. hlnstance = hlnstance; wndClass. hlcon = し oa con ( NU しし , IDI_APP し ICATION) : wndC lass. hCursor = し oadCursor (NULL, IDC_ARROW) : wndCI ass. hbrBackground = GetStock0bject ()H I TE_BRUSH) : if (!RegisterCIass(&wndCIass)) { wndCIass. IpszClassName = (LPSTR) " HE しし 0 " : ( し PSTR) NUL し : wndClass.IpszMenuName / * 初期化不能なので終了する * / return ()U しし ) : hWnd = CreateWi ndow ( ” HEL し 0 ” ” Hello, World" WS_OVERLAPPEDWINDOW, CW_USEDEPAU し T, CW_USEDEFAU し T, CW_USEDEPAU し T, CW_USEDEFAULT, NU しし NU しし hlnstance, NU しい : / * ウインドウ・クラス名 * / / * ウインドウ名 * / / * ウインドウのスタイル * / / * x 位置 * / / * y 位置 * / / * ウインドウの幅 * / / * ウインドウの高さ * / / * 親のハンドル * / / * メニューの I D * / / * インスタンス * / / * 追加的情報 * / if (!hWnd) { return ()U しし ) : / * ウインドウを作れるか ? * / / * 作れなければ Windows に戻る * / ShowWindow(hWnd, nCmdShow) : / * メイン・ウインドウを表示 * / UpdateWindow (hWnd) : / * WM_PAI NT メッセージを送る * / while (GetMessage(&msg, NU しし , NU しし , NU しし )) { TransIateMessage (&msg) : DispatchMessage (&msg) : return (msg. wParam) : / * PostQuitMessage からの帰値 * / long FAR PASCA し HelloWndProc(HWND hWnd, / * ウインドウのハンドル * / uns igned Message, WORD wParam, LONG lParam) swi tch (Message) { PAI NTSTRUCT ps : HDC hDC : / * メッセージのタイプ * / / * 追加的情報 * / / * 同上 * / / * ウインドウは破壊される * / case WM_DESTROY : PostQu itMessage ( 0 ) : break : / * ウインドウはリペイントされる * / case WM-PAINT: hDC = BeginPaint(hWnd, &ps) : Text0ut (hDC, 1, EndPa int (hWnd, &ps) : break : / * Windows にすべておまかせする * / default: return (DefW indowProc (hWnd, Message, wParan, lParan)) : } / * end switch * / return ()U しい : ” Hello, World!", 13 ) : いるのて、す。ひとつの例て、説明します。 ウインドウをひとつ作りましよう。この ードを示します。 プログラムて、す。 List2 に , C による同じコ これが , たった 3 行の HeIlo , world / ′′ 目を書き加えるだけてす。 world / クを表示したかったら , す。さらに , このウインドウに Hello List 1 の 1 , 2 行目のようなコードになりま に出るだけのウインドウて、す。 Actor て、は , ウインドウはなんにもて、きない , List1 の 3 行 ただ画面 のがふつうて、す。つまり Windows アプリ のて , コードとデータがかなりの量になる medium のメモリモデルて書くことが多い のアプリケーションは small または てき上がることに気づきます。 Windows ないのて , かなり小さな . EXE ファイルが ードは実際には . EXE ファイル中に含まれ チンだけがリンクされて , Windows のコ き彫りになります。 C て、書くと , スタブルー dows SDK との間の , ある大きな違いが浮 を実行する段階になると , Actor と Win 実際にアプリケーションを作って , それ 行性能 するメソッドが , すて、に存在するからて、す。 なかった , いろいろな状況に応じて処理を はプログラマがいちいち書かなくてはなら Actor が定義しているクラスの・中に , C て、 す。 Actor だとコードが少なくなるのは , いうふたつのメッセージだけを扱っていま 例て、は , WM DESTROY と WM PAINT と 処理するための関数は必要て、す。 List1 の事 すだけて、あっても , これらのメッセージを メッセージをただ Windows の処理用に渡 ジループも書かなくてはなりません。また , からのメッセージを扱うための , メッセー ドウを表示するよう指示します。 Windows 生成し , そして最後に , Windows にウイン インドウのクラスを登録し , ウインドウを の部分て、す。 Windows 中て、は , ューザのウ C のコードのほとんどが , セットアップ 「なぜこんな大量のコードになるんだ ? 」 窓 (Windows) によじ登る方法 21

4. 月刊 C MAGAZINE 1990年6月号

ある人は , そのシンタクスを批判していま す。 Actor は C と Pascal の混血みたいて、 す。たとえば Actor の文は , EW n e w ( E d i tW i n d 0 w , T h e P 0 rt , " e d i t menu", "Sample EditWindow', nil ) ; と 書いて , EW という名の新たな EditWin dow を生成します。 このコードは C プログラマが見ても , 目瞭然て、しよう。 ThePort は , 現在アクティ プな Actor のウインドウの , ウインドウハ ンドルを表す Actor のグローバル変数て、 す oeditmenu は , これから使いたいメニュ ーて、す ( この場合は editmenu は Windows が事前に定義しているものてす ) 。、、 Samp EditMenu" というテキストは , ウインドウ のキャプションて、あり , 最後の引数 nil は , ウインドウの位置とサイズを制御します。 この場合 nil は , システムがデフォルトの サイズと位置を使う , という意味て、す。 C プログラマがとまどうのは , new が関 という点てす。これはメッ 数名て、はない , セージ名なのて、す。このメッセージのレシ ーノヾが , EditWindow という Actor のクラ スて、す。こういった Actor の用語の使い方 に慣れることが , C プログラマにとっては 難しく , この文を見ると今て、も new が関数 名て、 EditWindow がその引数だ , と思って しまいます。 先ほどの 1 行が , テキストエデイタの半分 て、す。残る半分は , show(EW, 1 ) ; て、す。 第っしきデヾッグ Windows アプリケーションのデバッグ は , つねに難物て、す。 Microsoft は Win dows の下て走るデバッガを提供していま せん。使えるのは ,DOS の下て、の SYMDEB か CodeView てす。また , Microsoft が Windows のヾデノヾッグ用パーション〃と呼 んて、いるものを作ることもてきます。これ は正規のバージョンに , 致命的なエラーに 関するメッセージを AUX : ポートに送れ る機能を加えたもの , みたいな動作をしま す〔訳注 : この小節の原タイトルは "Debugging panes" て , つまりウインド ウの窓ガラス (pane) と , デバッグの苦し み・苦痛 ( pain ) を語呂合わせしています〕。 このやり方にはふたつの問題点がありま す。まず , 致命的なエラーを告げるエラー メッセージが , 謎めいていて , しかもマニ ュアルなどての説明が不十分て、す ( 工ラー コードに関するヘルプ機能はありますが , これもあまり役に立ちません ) 。第二に 部のプログラムはデバッグ用パーションの 下て、は正しく走らないのて、す。たとえば CASE : W (Caseworks 社製 ) は , Windows のデバッグ用パージョンの下て、は暴走する ことがありますが , 正規バージョンて、は無 難に走ります。 SYMDEB と CodeView を Windows の 下て、は使えない , という点を先ほど指摘し ました。これは実は , 半分ほど本当て、す。 これらのデバッガは , Windows アプリケ ーションとしては走りませんが , Windows を制御するプログラムとしては走るのてす。 これらのツールを使うためには , Windows アプリケーション用のコードを , 特殊なス イッチ ( コンパイラオプション ) つきて、コン パイルします。それから CodeView または SYMDEB を走らせ , それらに , Windows とアプリケーションを走らせるよう指示し ます。 CodeView や SYMDEB の Win dows SDK 用パーションは , Windows の ローカル変数領域や , グローバルヒープに ついて知っています。また , Windows のメ モリ操作方法についても知っています。 れらを使って , 実動中のアプリケーション のようすを見たり , メモリの使われ方や変 数の値を調べたり , あるいはコード中にプ レークポイントやウォッチボイントを設定 することがてきます。こういう機能によっ て , 確かにバグの所在を突き止めることは 楽になります。しかしこれらのデバッガを 使うためには , COM : ポートに第 2 のモニ タ , または端末装置をつながなくてはなら ないのてす。 Actor のデバッガはやや違います。バグ が発生すると ( それはたいてい , オプジェク トに , そのオプジェクトが理解てきないメ ッセージが送られたときてす ) , ダイアログ ポックスがポップアップします。そのキャ プションはエラーメッセージてあり , リス トボックスには , そのエラーを起こしたメ ッセージが入っています。、、 O にの上をクリ ックするとエラーを無視 , そして "Debug" をクリックするとデバッガを起動します。 デバッガの中て、は , メッセージをより詳 しく調べることがてき , また , メッセージ 中て、使われている変数 ( 渡された引数とロ ーカル変数の両方 ) を調べることもてきま す。実行コードの実態を見ることもてきま す。問題の箇所がわかれば , デバッガの中 にいながらコードの修正とテスト実行がて、 きます。 Actor はバグを起こしたメッセー ジを再送します。この方法は明らかに , CodeView/SYMDEB を使うよりまして す。小さなミスなら , 気軽にスイスイ直し ていけるのて、す。 ただし , Actor のデバッガは完全無欠て、 はありません。 Actor を暴走させたり , ハン グさせるのは , かなり簡単てす。これには 苛立ちます。 DDE を使う Windows アプリ ケーションを作っていたとき , タイマを起 動する Windows 関数のコールを書き加え ました。まずいことに , 私はアプリケーシ ョンのオプジェクトのクラスの中に , タイ マを操作するためのメソッドを作らなかっ たのてす。そのコードを走らせると , Actor は即死しました。このバグを直した後も , コードの別の部分がタイマを使っていまし た。メッセージ名を書きまちがえたときは , ダイアログボックスが出て , 某オプジェク トにはそのメッセージが理解て、きない と 告げられました。一方タイマはバックグラ ウンドて作動をつづけていますから , ダイ アログボックスが次から次へと出ます。す ぐに Actor のスタックは満杯になり , Act 。 r はご逝去あそばしたのてした。 Actor のデバッガはよくない といって いるのてはありません。むしろその逆てす。 それは非常に便利てすし , Windows 用の そのほかのツールに比べると , ずいぶんま 窓 (Windows) によじ登る方法 19

5. 月刊 C MAGAZINE 1990年6月号

ば , その数値は新しい素数て、す。その場合 , 新しい に素数 prime と , 次のオプジェクト F ⅱ te 「へのポイン 素数をもつ新しいオプジェクト F ⅱ ter を演算子 new を タ , そして , 生成のためのコンストラクタ , 破棄の 使って生成し , そのポインタを next に格納します。 ためのディストラクタ , メッセージのためのメンノヾ 関数 to をもちます。コンストラクタは , 受け取った整 ディストラクタは , そのオプジェクタを削除するだ 数を自身の素数 p ⅱ me にし , かっ , その整数値を出力 けてはなく , next がさすオプジェクトをも削除しま ストリーム co ut に渡します。メンバ関数 10 は , ほか す。 のオプジェクトからメッセージを送信される代わり ・オプジェクト Gen( ジェネレータ ) に呼び出されます。 オプジェクト Gen の動作は単純てす。それは , 所定 オプジェクトは , メンバ関数 to て受け取った数値が の整数値まての整数を次々に生成するだけて、 , その p ⅱ me の倍数かどうかを調べ , 倍数て、あれば , 次のオ クラス定義は , List7 のようになります。 プジェクトへのポインタ next がさすオプジェクトのメ このオプジェクトは , たんにコンストラクタおよ ンバ関数 to を呼び出します ( メッセージの送信 ) 。受け びディストラクタだけをもち , このコンストラクタ 取った数値が倍数て、あれば , 何もせず数値を破棄し が , 2 から引数 max まて、の整数値を生成し , オプジェ ます。 クト F ⅱ te 「群のふるいに渡します。なお , 整数を渡す なお , next がまだオプジェクトをさしていなけれ オプジェクト Filter(prime. cc から抜粋 ) #include く stream. h> / / 出力ストリームの宣言を得る / / オプジェクト F ⅱ ter の定義 class PiIter { pr ivate : int prime; / / 自身の素数を格納する F ⅱ ter* next : public: Filter(int num); Filter(void) { delete next; } void to(int num); List6 / / コンストラクタ Filter::Filter(int num) { pr ー me = n um : next = NUL し : / / 出力ストリームに渡す cout くく " [ " くく prime くく” ] " 〃メッセージの代りに使われるメンバ関数 to VOid Filter::to(int num) { if (num % prine) { / / 自身の素数の倍数かどうか調べる / / 次のふるい (F i I ter) がなければ = NUL し ) { if (next = / / 新たにふるいを生成する next = new Pi ltec(num) : } else { / / 次のふるいに渡す (*next) . to (num) : 5 ] 2 [ 9 [ ] 2 [ 1 4 [ [ ー 3 ] 9 [ ー [ 3 3 ] ] 1 ] 8 [ 9 -1 一〔 7- 2 ] 7 一 [ 9 ー ] 8 [ 0 [ 3 0 ] 6 り 1- ] 7- 〔 3 [ [ 1 2 ] 6 9 3 ー ] 7 [ 0 [ 一 1 ・ 3 ] ] 〔ーー 2 1 」 6 1- 1 1- ] 6 「 - 1 ] 7 〔 9 4 [ 7- 1- ] 5 [ 例 行 実 の ・ 5 8 6 [ 9 -4 ム 一「′ 3 9 ] 5 [ 9 グ ロ 2 ] - ー・ ] 4 [ プ [ ] 5 [ 7 4 7 一 5 [ ー 4- 5 C 十十プログラミング入門 105

6. 月刊 C MAGAZINE 1990年6月号

/ * 「はい」の処理 * / ID NO: / * 「いいえ」の処理 * / default: case break ; hWnd, iMessage, return DefWindowProc( 58 CMAGAZINE 19 6 いうことになります。なお , Windows のメ ドウクラス ( のウインドウブロシージャ ) と のはメイン関数とボタンの持ち主のウイン に定義ずみなのて , プログラマが記述する ルバーなどのウインドウクラスはシステム になります。実際には , ボタンやスクロー と呼んて、いますが , その概要は Fig. 5 のよう いました。これを「メッセージ駆動モデル」 ログラミングモデルの解説をひととおり行 こまてて , Windows と PM に共通なプ もよいことて、すが・・・ るからてす。これは , はじめは知らなくて インドウブロシージャを呼び出すことにな るときは DefWinProc( ) て、はなく , ほかのウ ンドウブロシージャのチェインを使ってい 理という変ないい回しを使ったのは , ウィ 行うことになります ( ここて , 最後まて未処 P 「 oc ( ) A 曰を呼び出してデフォルトの処理を 最後まて未処理のメッセージは DefWin 処理する必要はないのて、すが , そういった ジが送られています。そのすべてを自分て、 のメッセージ以外にもいろいろなメッセー ウインドウブロシージャにはボタンから ウインドウ自身の仕事だからて、す。 れを行う必要はありません。それはボタン ますが , ウインドウブロシージャて、は , そ もとに戻るようすを描く処理が必要になり リリースに合わせてボタンを押し込んだり , のは , たとえば , マウスポタンのプレスと は大きく違います。イベントループ内のも メントを入れましたが , 実際の処理の内容 ープと同じ / * 「はい」の処理 * / というコ ボタンの処理に最初に示したイベントル イン関数は main ( ) て、はなく , WinMain() と いう関数になっています。 Windows 自身が MS-DOS のアプリケーションなのて、すから わからなくもないて、しよう ( リンカも SDK に 付属の LINK4. EXE を使用します ) 。 Win ows/PM A 日の整理 Windows や PM の API (Application Pro gram lnterface) は公開されているものだけ て、数百種類になります。これらを整理する ために PM て、は API の名前に 3 文字の接頭字 をつけているわけて、すが ( 本誌 ' 90 年 3 月号参 照 ) , Windows て、はそのようなことは行われ ていません。しかし API はもっと本質的な分 類が可能て、す。ここて、はそれを紹介します。 キーワードは「データ構造指向 ( data struc ture-oriented) 」としておきます。 任意の関数を「 Function 」と表すことにし ます。ハンドルにはいくつかのタイプがあ るのてすが , ここて、は HANDLE 型というこ とて、表すことにします ( ハンドルはオプジェ クトを表していました ) 。そうすると , API はプロトタイプ宣言の形て、表せば次のよう 2 . ~ Function(HANDLE, 1 . HANDLE Function(... ) ; な 3 種類に分類することがて、きます。 3 . そのほか HANDLE 型のない A 曰 Fig. 5 メッセージ駆動モデル maln ハンドルを返し , かっ第 1 引数にハンドル をとる 1. と 2. を組み合わせたような API もあ ります。ここて 1. と 2. に注目してください 1. はオプジェクトを生成し , そのハンドル を返す API て、 , 2. はハンドルて、表されるオプ ジェクトを操作するための API と . なっていま す。 Windows や PM て、は , ハンドルをオプ ジェクトごとに , ウインドウに対しては HWND 型て、あるとか , ビットマップ対しては HBIT MAP 型のように分類されます。たとえばウ インドウを操作する API は , すべて Function(HWND, という形になります。 また , Windows て、グラフィックデバイス に描画する際には , デバイスコンテキスト と呼ばれるオプジェクトが必要て、す。デバ イスコンテキストのハンドルは HDC 型を使 います。したがって描画に使用する API は , Function(HDC, という形て、表されます。 Windows てはこの 形式の API を GDI ファンクションと呼んて、い ます。 PM のような接頭字がなくても , API はしつかり分類てきるのて、す。 デバイスコンテキストについて簡単に説 明しておきます OGDI ファンクションのうち たとえば , 線を引く API は , BOOL LineTo(HDC hDC, int X, int Y)•, のようになっています。この API< は (X , Y) ーウインドウクラス 0 初期化する 0 メッセージループ はい いいえ 「ウインドウブロシージャ - - ホタンウインドウクラスー ーーボタンウインドウブロシージャ

7. 月刊 C MAGAZINE 1990年6月号

半径などを一定の値として扱うことがて、き ンに移っています。このようにして実現さ 画面の構成 ます。半円の下にはシステムフォントを使 れたマルチタスクをノンプリエンプテイプ って方位の名前を書いたりするのて、 , 半円 なマルチタスクと呼んて、います。しかし , の上下左右には最低て、も左右にシステムフ このプラネタリウムのウインドウのサイ それて、もイベントが何も発生していない時 オントの半キャラクタ分 , 上には 1 キャラク ズは自由に変更することがて、きます。プロ 間というのはかなり残っています。そのよ タ分 , 下に 2 キャラクタ分の余裕があるよう グラムて、は , それに応じて星空を描く半円 うな時間を利用して行う処理をバックグラ にします。以上のことをふまえてクライア の大きさを調整しなければなりません。ま ウンドタスクと呼ぶことにしましよう。 ント領域への描画には Fig. 6 のような論理座 た , ディスプレイアダブタの種類によって Windows のプリンタスプーラもバックグラ 標系を用いることにします。実際の論理座 はスクリーンのドットは必ずしも正方形に ウンドタスクを利用しているユーティリテ 標形の設定は SetPlanetMapM0de( ) 関数の なっているとはかぎりません。きちんとし ィのひとって、す。 中て、行っています。このようなプログラム た半円を描くにはドットの縦横比に応じた Windows て、バックグラウンドタスクを実 て、はウインドウのサイズが小さくなったと 調整が必要になります。実は , そういった 現するには , メッセージループを次のよう きどうするかという問題があります。 Win 問題は , Windows のアイソトロヒ。ック ( is なものに変更します。 dows のアプリケーション作成のときの原則 otropic ) マッヒ。ングモードを使用することに while ( 1 ) として , 同種の問題に関しては既存のアプ よって解決されます。アイソトロピックマ if (PeekMessge(&msg, NULL, 0, O, リケーションに倣うということがあります。 ッヒ。ングモードて、は x 軸の論理単位と Y 軸の PM REMOVE)) 今回は Windows のリバーシを参考にしてみ 論理単位の長さが実際に画面に表示された WM QUIT) if (msg. message とき等しくなるほか , プログラムの側て、は リバーシはウインドウのサイズに ウインドウのサイズにかかわらず , 半円の 応じて盤の大きさが調整されますが , ある Fig. 6 プラネタリウムの論理座標系 break ; TransIateMessage(&msg) : DispathcMessage(&msg) : } else / * バックグラウンド タスクを実行する * / PeekMessage( ) AP の第 5 引数に PM REMO VE を指定すると , プログラムのメッセージ キューに待機中のメッセージがあればそれ を読み出して 0 以外の値を返しますが , それ 以外はほかの実行中のどのアプリケーショ ンのキューの中に待機中のメッセージがな くなると 0 を返します。て、すからこれを利用 するとほかの実行中のアプリケーションの 妨げにならずに , バックグラウンドタスク を実行てきるようになるわけて、す。その代 わり , ループを抜けるための処理を自分て、 行っていることに注意してください なお , プリエンプテイプなマルチタスク 環境て、ある OS / 2 PM< は , このようなバッ クグラウンドの処理にさらによい方法が残 されています。その方法が [ 文献 8 ] や [ 文 献 10 ] に説明されているのて、 , もしプラネ タリウムプログラムの PM への移植を試みる ことがあれば , ぜひ参考にしてください 60 CMAGAZINE 1990 6 y Char k—XxCharJ XxCharm 2XyChar 0 システムフォント ー xChar yChar

8. 月刊 C MAGAZINE 1990年6月号

CAGUINE 6 ・よかった記事の番号 ( P. 157 参照 ) と理由をお書きください。 ① ・つまらなかった記事の番号 ( P. 157 参照 ) と理由をお書きください。 ① ・本誌以外のご購読パソコン雑誌は ? ・今後 , どのような記事をお望みですか ? ( 具体的にお書きください ) ・編集部へのメッセージをお願いします。

9. 月刊 C MAGAZINE 1990年6月号

C 十十 プログラミング 入門 オプジェクト Gen(prime. cc から抜粋 ) / / オプジェクト Gen の定義 class Gen { private : P ⅱ ter* next; public: Gen(int max) : Gen(void) { delete next; } / / コンストラクタ Gen : : Gen (int nax) { cout くく "prines [ 1 ド / / 1 は特別な素数 next = new FiIter(2) : for ( i nt n = 3 : n ← nax : n + = 1 ) { / / 最大値 max までの整数を次々に / / 生成し , ふるい (F i 1 ter) に渡す (*next). to (n) : List7 main(p 「 ime. cc から抜粋 ) List8 〃関数 main void nain(void) { Gen aGen()0 の : / * 500 までの素数 ( Primes ) を得る * / ためのメッセージは , 実際には , オプジェクト Filter ジェクト指向言語のプログラムにしばしば使われる のメンバ関数 to の呼び出しになります。ディストラク スタイルてす。これを , C 十十のコルーチンパッケー タは , オプジェクト F ⅱ te 「のディストラクタ同様 , next ジなどといっしょに使えば , C 十十ても並列動作オプ がさすオプジェクト FiIter も削除しようとします。そ ジェクトのプログラムが記述てきることになります。 れゆえ , オプジェクト Gen を削除すれば , それにつな これらは , とくに , シミュレーションなどのプログ がる全オプジェクトが連続して削除されます。 ラムの記述に便利てす。 ・関数 main ほか 終わりに 関数 main(List8) は , 素数の最大値を与えて , オプ ジェクト Gen を生成するだけてす ( 注 3 ) 。後の処理は オプジェクト Gen および F ⅱ te 「に任され , 関数 main は 今回は , 抽象データ型を組み合わせ , 作成したプ 何もしません。また , オプジェクト Gen の生成は , 関 ログラム , クラスをプログラムの動作単位にみなし 数 main 中てされる必要はありません。以下のよう たプログラムを示しました。 次回は , 本誌の特集が GNU ということてすから , 本連載ても GNU に関係した g 十十 , libg 十十などを中 Gen aGen(500); 心に , C 十十のクラスライプラリを紹介しようと考え VOid ています。 main(void) { } 大域オプジェクトとすることもてきます。 [ 参考文献 ] なお , このようなプログラミングて重要なのは , ( 1 ) Lippman,S. B. , C 十十 PRIMER, 〃 Addis これらのオプジェクトの動作に逐次処理の必要がな on-Wesley , 1989. いことてす。すなわち , 各オプジェクトは , 互いに ( 2 ) 淵ー博監修「並列論理型言語 GHC とその応用』 ( 注 3 ) IDEA C 十十ては , 独立しており , その同期はメッセージのみて取られ スタックの容量の関係て , 共立出版 , 1987. 最大値は 50 ( 耳呈度に制限さ ます。これらのプログラミングは , 最近の並列オプ れる。 106 CMAGAZINE 19 6

10. 月刊 C MAGAZINE 1990年6月号

TIFF ( タグイメージファイルフォーマ RTF ( リッチテキストフォーマット ) メタファイル TIFF は画像データフォーマットて、ある。 イメージデータファイルの先頭部分にタグ 情報を付加し , イメージデータの内容がア プリケーションソフトて、判別て、きるように なっている。 RTF は , ワープロ文書の標準形式て、あ る 0PostScript と同様に , 制御コードも文字 列となっている。 RTF-J として日本語規格 化が進行中て、ある。 メタファイルは , Windows の表示関連命 令 GDI ( グラフィックデバイスインタフェイ ス ) に対応したファイル形式て、 , 文字 , 図形 などに中間形式として幅広く使われている。 このほか , ExceI などの表計算ソフト , デ ータベースソフト用の BIFF 形式なども , 規 格化の方向にある。 これらのデータを , 複数のプログラム間 て、稼働中にやりとりするための機能として DDE ( ダイナミックデータェクスチェンジ ) が提供されている。 Windows プログラマ 本誌読者のプロ , アマプログラマの方々 の関心事て、ある , ソフトウェア開発者から 見た Windows の利点 , 欠点を解説する。 プログラム設計 Windows て、稼働するソフトウェアを設計 する際の最大の問題点は , 『オプジェクト指 向を活かした設計がなじみにくい』ことて、 ある。マウス , プルダウンメニュー , アイ コン , スクロールノヾー , ダイアログ , リス トボックスといった単語を理解し , Windows の設計思想を理解しなければならない。外 部仕様を決定する際には , Excel や PageMa ker をひととおり使いこなす必要がある。 52 CMAGAZINE 1990 6 外部仕様が決定て、きても , 次に『情報不 明朝体 窓を開く ゴシック体 忘を開く れる。 すると半分以下の期間て、開発て、きると思わ DTP ソフトや作図ソフトも MS-DOS と比較 また , グラフィックスが扱いやすいのて、 , とも可能て、ある。 グして , 画面の遷移や操作性を検証するこ て、 , 画面設計をもとに実際にプログラミン メニューやダイアログも簡単に作れるの ラマには向いていないかもしれない るため , オリジナリティを追及するプログ ただ , Windows は操作性の統一が重要て、あ ば , それて、外部仕様は作成て、きてしまう。 決め , メニュー展開も ExceI のまねをすれ ラムスタイルガイドに沿ってメッセージを とも簡単て、ある。アプリケーションプログ 外部仕様の設計は , 理解してしまうとい ている。 は , これをカバーして余りある利点をもっ しかし , 問題点はこの程度て、 , Windows が咼い。 の大きなプログラムとなってしまう可能性 いと , センスの悪い , オプジェクトサイズ ェイス ) 関数の機能や用途を十分に把握しな API ( アプリケーションプログラムインタフ 機能設計 , モシュール設計も Windows の かもしれない るが , それがわかるまて、に数か月を要する 編集は EditControI という機能て、簡単に行え う問題が生じる。矩形領域内の文字列入力 , 足て、 Windows の資源が活用て、きない』とい プログラミンク プログラミングについては , ま ffWindows の設計思想の理解から入らねばならない Windows のプログラムは , Mac や BTRON 同様 , 『イベント駆動型』て、ある。従来のプ ログラミングて、は , 主役はプログラマて、あ った。自分て、 , ほしいときにキーポードか らデータをもらい , 表示したいときに勝手 に画面にデータを描いていた。 これが , イベント駆動て、は , OS 側が主役 となる。 Windows がアプリケーションプロ グラムに対して , さまざまな要求を突きつ けてくる。やれマウスがどこに動いただの , 画面を再表示しろなどというメッセージが , Windows から飛び込んて、くる 0Windows プ ログラマはその要求をセッセと処理しなけ ればならない。主役て、いたいプログラマに は Windows は向いていない このように , メインループがあり , その 中て、送られてくるメッセージを処理するプ ログラムとなるため , 他人が書いたプログ ラムは理解しづらいものとなる。 また , デバイス依存がない分だけ , 手続 きが複雑となり , プログラムは COBOL のよ うに冗長となる。画面に、、 Hello 〃と表示す るには , MS ー DOS て℃言語を使えば 1 行て、記 述て、きるが , Windows て、は数十行のプログ ラムとなる。 Windows のプログラミングは , 500 種類以 上の API 関数を使うわけて、あるが , 日本て、 Windows アプリケーションがなかなか現れ ない要因は , これらの関数を理解するため の資料が決定的に不足て、あり , Windows プ ログラミングマニュアルの不足て、ある。 関数のリファレンスマニュアルは , fWin dows 開発ツール』という 9 万円のソフトに 1 セットだけしか入っていない。関数リファ レンスはプログラマ 1 人に 1 冊は最低必要な のて , 『 9 万円 x プログラマ人数』の出費を 覚悟しなければならない。 OS / 2 プレゼンテ ーションマネージャのプログラミング関連