ln 川 a ⅱ行匪 III 町ⅱ計 Ma れ門 ボーランド BorIand C 十十 Turbo C 十十 fo 「 Windows 基本クラスのⅲ nstance を呼び出してからメッセージボックスを表示 List 1 Q ObjectWindows でアプリケー ションを作成していますが , アプ リケーションを起動するときに 度だけメッセージを表示するのは どうすればよいでしようか A TApplication の派生クラスて、 lnitlnstance メンノヾ関数をオーバラ イドし , 基本クラスの lnitlnstanc e を呼び出してからメッセージボ、ツ クスなどを表示します (List 1 ) 。メ インウインドウが表示される前に メッセージを表示したい場合はメ インウインドウに割り当てるウィ ンドウクラスて、 SetupWindow メン バ関数をオーバライドします (List Q C 十十のクラスを使って Wind ows の DLL を作成するときの注意 点を教えてください。 A c 十十のクラスを Windows の DLL に定義し , 実行ファイル (. EX E) て、そのクラスを継承するような 場合は , C て、 DLL を作成する場合に 比べて制約や注意すべき点がいろ いろあります。具体的な注意点を 以下に示しますのて、 , 参考にして ください。 DLL の作成や利用に関 しては , マニュアルをご覧くださ 1 ) ラージモデルで開発する DLL と . EXE は , それぞれ固有の データセグメントを持ちます。 れは , 両者て、共有する可能性のあ るものは , far て、宣言する必要があ ることを示しています。たとえば , DLL と . EXE のどちらて、もオプジェ クトを生成することがて、きますか ら , this•'* インタはどちらのデータ も正しくアクセスて、きるよう far,-\ インタて、なければなりません。同 様にメンバ関数も far 関数て、なけれ ばなりません。 データポインタとコードボイン タが両方とも far ポインタて、なけれ ばならないため , ラージモデルを 使う必要があるのて、す。なお , W indows アプリケーションて、は , hu ge モデルは使えません。 2 ) クラスの宣言 クラスが仮想関数を持っ場合 , そのクラスは仮想関数テープルへ のポインタを持ちます。通常 , 仮 想関数テープルは , nearztk インタ によって示されています。これは , ラージモデルて、も同じて、 , ラージ モデルて、は near 領域にある仮想関 数テープルの要素が far 関数へのポ インタを示しています。 1 ) と同じ理由により , 仮想関数 テープルも DLL と . EXE て、共有す るためには far ポインタによって示 される必要があります。このため には , クラスの宣言を huge か _exp ort のいずれかて、宣言するかー Vf オ プションを使います。 huge は , ク ラスの仮想関数テープルをデータ セグメントて、なくコードセグメン トに配置し far ポインタによってア クセスするようにします。 -Vf オプ ションは , コマンドラインからこ れを指定するオプションて、す。 e xport は huge と似ていますが , クラ ス内のメンバ関数をすべて工クス ポート関数にします。 DLL と . EXE て、クラスを共有す るときは , . EXE から DLL 内のメン バ関数を呼び出すこともあります から , DLL 内て、のクラスは expor t を使って宣言しなければなりませ 1 : class TMYApp: public TApplication { 3 : pub ⅱ c : void lnitlnstance(void) TAppIication::InitInstance(); MessageBox(Mai nWindow->HWi ndov, 9 : 8 : 7 : 6 : 5 : 4 : 2 : 10 : - } , ” He Ⅱ 0 ” . MB_OK); 6 : 1 : ” Startup Message , メインウインドウが表示される前にメッセージを表示 List 2 1 : class TMainWindow: public TWindow { pub ⅱ c : void SetupWindow(void) { TWindow: :SetupWindow() ; MessageBox(HWindow, ” Startup Message 7 : 5 : 4 : 3 : 2 : [common. h] List 3 DLL と . EXE てクラスを共有する例 ” He Ⅱ 0 ” MB_OK) : 2 : 3 : 4 : 5 : 6 : 7 : 8 : 9 : 10 : 1 : 3 : 5 : 1 : 3 : 5 : 6 : #if defined(--DLL-_) #define -EXPORT -export #else #define _EXPORT huge #endi f class -EXPORT A { pub ⅱ c : virtual void func(); int num; Cdll-prog. cpp] #include ” common. h" 2 : / / 基本クラス内のメンパ関数の実装 void A::func(void) puts( ” A::func"); [exe-prog. cpp] #include ” common. h ” 2 : / / DLL で実装されたクラスの利用 VOid global-func() A object; object. func(); 162 C MAGAZINE 1993 7
ムプログラミング大作戦 98 & 00S / ゲー る方法を模索しましよう。 観点から List 4 形式 , Point から派生しない ほうて、いきます。 Rect のメンバ関数として は移動 ( move ) , サイズの変更 ( gr 。 w ) , 空か どうか (isEmpty) などがありますのて、ちょい Point クラスはその名のとおり , ある点を ちょいと実装しておきます。 あとは Window への布石として , ある点 表現するためのクラスて、す。私たちはプロ Pointp が Rect 内に含まれるかそうて、ない グラムて、画面を扱うとき , ごく自然に直行 かを返す関数 contains ( ) を用意しましよう 座標系を使用しています。直行座標系を使 用するときには , その上の点を表すのに (x, (List 5 ) 。見てわかるとおり , minmax テス トによる至極簡単なものて、す。引数 Pointp y) という表現を使うと思います。プログラ みがあります。これは世間て、 isA 関係と ha は関数内て、参照されるだけなのて const 指定 ムを組むときはこれとまったく同じものて、 s A 関係として知られているものらしいのて、 すが , 要するに継承て、クラスを作るのか , て、変更を禁止し , Point& として参照引数と すが , PC の画面座標の都合て、通常の x ー y 平 して呼び出し時のオーバヘッドを軽減して 面とは少し異なった下向きが y 十方向になる あるクラスをメンバとして取り込んて、しま います。 inline 指定すればさらなる高速化を ような座標系を使用します。このほうが便 うか , という話て、す。 象は動物て、ある ( is A) と , 象は長い鼻を 図ることがて、きます。 利だからて、す。以上をふまえて , ある画面 持っている (has A) という例がよく使われて 上の点を (), y) として表現したいならば , Window クラス改 います。つまり象というものは動物クラス 自然と List 1 のように書けます。 を継承していて , 長い鼻クラスを有してい Point クラスは基本的にはこれだけて、す。 る , あるいは動物と長い鼻が出会ったとき Window クラスのときもやはり先の悩みが 演算子をオーバロードして点の移動を加算 に , 長い鼻と動物はお互い直接には関係の や減算て。表現したり , 等しい点を等号て、判 発生します。 Rect から派生するか , Windo ない要素として象を構成することになった , w クラスの要素として Rect 型のメンバ変数を 断したりすることも簡単に実現て、きます。 などと言葉て、いってもなんだかよくわから 取り込むかという問題て、す。あるいは , Re たとえばふたつの点が等しいというのは , ないて、すね。まあ , 象の場合は長い鼻の派 ct 型とはまったく別個に記述するという選択 2 点の x , y 座標それぞれが等しいて、しようか 生て、はなく , 動物の継承を選んだほうが妥 もあります。 Window は Rect て、て、きること ら L i s t 2 のように書くことがて、きるて、しよう。 ( 変形や移動 ) はて、きてほしいのて、 Rect から 当だというのはわかりやすいと思いますが , 演算子オーバロードは凄く格好のいい 区別が徴妙なこともよくあります。 の派生て、行ってみたいと思います。とりあ C 十十の拡張だと思います。しかし , Point さて , 今回は Point と Rect の関係を決める えす今回は List 6 のようなメンバ変数とメン 程度の簡単な例なら誰が書いても同じて、し のて、すが , 白状すると , これがどっちがい バ関数を作成しました。この中て、 もう少し複雑なオプジェクト間て、 ようが , いのかいまだによくわからないのて、す。 の演算の定義は書く人によってまったく違 virtual void handIeMouse Rect を Point からの派生にすると , List 3 (const Point p) うものになりかねません。 のようになり , そうて、なければ List 4 のよう = 0 がついているメンバ関数があります C 十十はうまく使うと実にスマートに書け になるて、しよう。このふたつのどちらがい が , このようなメンバ関数は純粋仮想関数 る場面が多いのて、すが , うつかりはまると いのか決断に迷うところて、す。 List 3 のほう と呼ばれ , これを持つクラスは抽象クラス 完全にわけのわからないものになってしま と呼ばれています。要するにこれ自体を使 がムダが少ないように思えます。 List 4 のほ うような罠がたくさんあります。気をつけ うは左上と右下の点を Point として扱えるの って実際に何かを行うことはないけれども , ましよう。ちょっと便利に使うくらいがち て、楽そうて、す。 C 十十のキーワードは「楽」て、 こからさらに派生させるときに便利なク ようどよい気がします。 ある , ともう何度もいわれていると思いま ラスて、す。純粋仮想関数はわずらわしい実 装がいらないのて、理論的にクラスを構築し す。実際そうだと思いますが , 今回はその Rect 内に Point p があるかを判定する Fig. 1 Paint 型と Rect 型 Point クラス width POint origin Point P hieght Paint R ect クラス lSt Point クラスがて、きたら , 次は当然ながら 矩形を表現する Rect クラスを実装しようと いう展開が、、お約束クて、す。 (Fig. 1)0 さて , こて℃十十 ( というより Objective な設計 の , かも ) て、クラスを作るときに出くわす悩 b001 Rect: :contains(const point& p) return b001 ( P. x 〉 = origin. x & & P. x く end. x & & P. Y > = origin. Y & & P. Y く end. Y) ; 98 & DOS / v ゲームプログラミング大作戦 71
98 & 00S / ゲームプロクラミンク 大作 キャラクタ工テイタの作成 ( 2 ) 0 2 野村広 今回は予告どおり , 先月のどうにか点か打 てる程度のマウスの練プログラムみたい なものに , 実寸 ( 1 倍 ) ウインドウとファイル の読み書きと , あと少し追加します。 に渡すのに f ( win. x , win. y) などと書かなけ 則回からだいぶいじってしまったのて、ソ ればなりませんし , 領域は (win. xl, win. x ースのみてくれは変わってしまいましたが , やっていることは同じて、す。前回は感じを 2 , win. yl, win. (2) と長ったらしくなって 擱むための限定的な使用方法の一発プログ 実寸ウインドウを追加する前に将来に備 きます。初期化時はいたしかたないとして も , 一度初期化したらあとは「 win. 領域」や「 w ラム的なものて、したが , 今回はもう少し一 えて少し Window クラスの見直しをしましよ 般性を持たせてみました。 う。前回はただ漠然と「ウインドウとかいう ⅲー > 領域」のような感じて、ほかのルーチンに もの」という感じて、扱っていました。このま 渡したいものて、す。そこて、 , 点と矩形を表 ゲームプログラミングと名がつく記事な のに全然実際のゲーム作りに入りませんが , まガリガリ書くこともて、きるのて、すが , も す Point と Rect を導入します。 Point クラス ツールを作って基礎力を養うということて、 を導入すれば , ウインドウ内の点は f ( Poin うひとっスマートさに欠けます。この先ウ 勘弁してください t p) : と書けて見やすいし , タイプ量も減っ どのみちゲームを作る インドウに機能が追加されるに従って繁雑 ときにはツールが必要になるのて、 , ムダに さは増大する一方て、しよう。 て手が疲れません。このふたつのクラスを はならないと思います。 今の段階て、もウインドウ win 内の点を関数 使って Window クラスを効率よくアクセスす 日 ect クラスを Point クラスから導出 Point クラスを導入 Window クラスの見直し iSt ist class Rect : public P0int { public: lnt ex, ey; int width, height; Rect(int sx, int sy, int awidth' int aheight) point(sx, (Y), width(awidth), height(aheight) 0 : class P0int { int x, y; / / メンパ / / コンストラクタ Point(int ax, int (y) ( X = ax; Y = ay ; 文は Point(int ax, int ay) Rect クラスに Point クラスのメンノヾ変数を持たせる ist class Rect { public: POint origin, end; int width, height; Rect(int ax, int ay, int w, int h); Rect(P0int pl, Point p2); ふたつの点が等しい ist (const Point& pl, p2 ) Point& const = 02. x & & pl. y = p2. y; b001 operator return pl. x 70 C MAGAZINE 1993 7
マウスカーソルを書いたり消したりのタイ 通する性質をまとめて Button クラスを構築 ミングの問題だと思うのて、 , 改良を加えて することにしましよう (List 17 ) 。ラベル用 もう少し快適に描画て、きるようにしました。 の文字列へのポインタと , 論理型の hit とい マウスボ、タンが押されたとき , 以前と同 前回のボ、タンは Window クラスから直接各 うボ、タンが押されたかどうかをのフラグを じ位置にマウスがあったらなにもしないて、 ( といっても Exitåx•タンだけ ) を導出しまし メンバ変数として用意します ohit は isHit( ) 戻るようにして , ムダなカーソルの Show, たが , ボタンもたくさんになってくると , て、参照して , 一度参照されるとクリアされ Hide をなくしています。 ZoomWindow の 同じようなメンバ変数やメンバ関数がだぶ るようにしてあります。 メンバ変数に前回アクセスしたポイントを ってくることに気がっきます。同じような Button クラスもやはり Window クラスと 保存する Point IastPoint を追加します (List ものをまとめるというのは , プログラムの 同様 , 実際のインスタンスを持っことはな 16 ) 。 世界て、は常識的なことて、す。各ボ、タンの共 いと判断して抽象クラスとしておきます。 Window クラスと本質的になんら変わるとこ ろはありません。ボ、タンが押された = ウィ ンドウ内て、マウスがクリックされたという ことなのて、 , handIeMouse ( ) をそのまま制 御関数として使用て、きます。 ラベル用に文字列確保のために関数 newS tr ( ) も追加します。ただ単に文字列の長さ 分の領域を確保して strcpy ( ) するだけのも のて、す (List 18 ) 。 ホタン lSt ロードボタン class LoadButton : publ ic Button { ZoomWindow *targetWin; public: LoadButton(const Rect& bounds, const char *aLabel, ZoomWindow *target) Button(bounds, aLabeI), targetWin(target) { } virtual void handleMouse(const P0int 0 ) { targetWin- 〉 pattern- 〉 :read(targetWin- 〉 pattern- 〉 name) : targetWin—〉 reDraw() : 前回アクセスしたホイントを保存 旧 ビットマップボタンのようなもの void ZoomWindow: :handleMouse(const point p) if (Mstat. Lbt) { Point tmp = toLocal(p); if (tmp ! = lastPoint) { putPixel (tmp, currentColor) ; lastPoint tmp; } else if (Mstat. Rbt) { mouseHide() ; currentColor ::getPixel(). x, p. y); mouseShow() : waitReleaseRButton() ; いにい ) いに ( に一新一い ~ いいいい ~ りにに ~ いいにに ~ ににいに = に一 今回のサンプルプログラムて、実際に , のエデイタて、作成したパターン ( といっても ただの落書き ) をボ、タンとして張り付けて使 用してみました。 pattern のファイル名をボ、 タンのラベル名といっしょにして読み込み , 各ボ、タンの位置に合わせて draw ( ) を呼んて、 描いています。 ボ、タンの枠はそれぞれのデザインに合わ せて描いたり描かなかったりしています。 けっこうカまかせなやり方て、すが , 本格的 なビットマップボ、タンにはおよばないもの の , それなりの雰囲気は味わえます (Fig. いちおう少しはゲーム作成に役立ちそう ラベル用文字列確保の関数 newSt 「 ( ) Button クラスを構築 class Button : public Window { protected: b001 hit; char *label : public: Button(const Rect& bounds, const char *aLabeI) Window(bounds), hit(FALSE), label(newStr(aLabel)) { } virtual -Button() ; b001 isHit() { b001 retval = hit; hit = FALSE; return retval ; void setLabel (const char (S) ; char *getLabel ( ) const ( return label; virtual void handleMouse(const P0int& P) 旧 char *newStr(const char *S) if(s = NULL) return NULL; char *tmp = new charCstrIen(s) + 1]; strcpy(tmp, s) ; return tmp; 76 C MAGAZINE 1993 7
98 & 00S / ゲームプログラミンク大作戦 lSt すべてのウインドウの始まりとなる DeskTop クラス と呼ぶことが多いのて、 , それにならって De skTop クラスを Window クラスから派生しま す (Fig. 3 ) 。 あるひとつのアプリケーションて、使用す るウインドウは , すべてこの DeskTop に所 属することになります。 DeskTop の行うこ とは , ひたすらマウスを監視して , マウス が押されたらそれがどのウインドウ上て、押 されたのかを発見し (findWindow()), その 見つけた Window にマウスが押されたことを 通知することて、す。通知といってもまだメ ッセージのたぐいは実装されていないのて、 , 各ウインドウの適切なマウス処理関数を呼 び出すだけて、す (List 7 , Fig. 4 ) 。 各 Window は insert( ) 関数を使用して , D eskT 叩の子ウインドウとして登録していき ます (List 8 ) 。こうすることによって , すべ てのウインドウが DeskTop 経由て、アクセス 可能になります。いいかえれば , 登録され ていないウインドウはマウスがその中て、押 ースて、は 1 倍ウインドウのみの問題なのて、 , 1 ドットずっ広げてやります。と , 同時に R されたかどうかの調査がされないのて、 , 何 この間題は捨ておくことにします。見栄え かを起こすきっかけを永遠に与えられず , ealWindow : : putPixeI (Pöint P) て、は右下 のいいウインドウに枠は必須なのて、 , その に 1 ドットシフトして描いてやる必要があり 存在しないも同然なのて、す。 うちにちゃんとやります。 ⅲ sert ( ) は引数て、与えられたウインドウ , ます。 なにやらめんどくさいことになってしま あるいはその派生クラスのオプジェクトを 子ウインドウリストの始め ( 終わりて、もよい ) いました。なせこのようなはめになったの か , 反省しつつ考察してみましよう。つま に追加して , 自分へのポインタを返します。 前回作成した Pattern 構造体にいくっかメ り , ウインドウの枠と描画領域の区別がな 自分へのポインタを返すことによって登録 ンバ関数を追加してクラスとして使用しま かったためにこのような手間が生じたのて、 したいウインドウを一度に連結処理するこ しよう。別に struct のままて、もかまいません す。て、も , 枠を別扱いにするほうがめんど とがて、きます。また 1 倍ウインドウ ( RealW が , class といっておいたほうがメンバ関数 くさいのて、はないて、しようか ? 今回のケ indow) は , 工ディットする幅より上下左右 Fig. 5 ZoomWindow は xl とノヾターンテータをアクセスする Fig. 4 目的のウインドウを見つける class DeskTop : public WindOW { public: DeskTop(const Rect& bounds) : Window (bounds) { } virtual void handleMouse(const P0int P) : void DeskTop: : handleMouse(const point P) { Window *wp; = NULL)) { / / どのウインドウにマウス if ((wp = findWindow(p)) ! = this & & ()p ! / / がいるのか取得ボタンが wp->handIeMouse(p) : / / 押された時の処理に制御 / / を移す し DeskTop に各 Window を登録する *deskTop = new DeskTop(Rect(0, 0 , 640 , 48 の ) : DeskTop RealWindow *rw = new ReaIWindow(Rect(200, 50 , 32 + 2 , 32 + 2 ) ) : ZoomWindow *zw = new ZoomWindow(Rect(300, 50 , 32 * zoom, 32 * zoom), zoom, &Pattern( ” test" , 0 , 32 , 32 ) ) ; deskTop ->insert(zw) ->insert(rw) ; Pattern クラス winl 上でマウスがクリックされると DeskTop → findWindow( ) •winl → findWindow( ) •win4 → findWindow( ) が検索されて win4 → handleMouse が起動される 1 倍ウインドウ W ・ inl Win3 Win4 Win2 Realwin Pattern パターンテータ ZoomWindow 98 & DOS / v ゲームプログラミング大作戦 73
ていく際の助けになります。 この部分は前回のものと本質的に同等のも います。理論的にはそれて、よいのて、すが , 前回の Window クラスから子ウインドウの のて、す。 現実て、は有限個のウインドウしか扱えませ 追加がおもな変更になっています (Fig. 2 ) 。 子ウインドウと , 自分と同列のウインド ん。上限と下限はどのように設定し , ある 自分を所有している親ウインドウが owner に ウの 2 種類のリストが交錯してやや混乱しま いは判定したらよいて、しようか。 なります。自分の所有している子ウインド すがじっくり考えて理解しましよう。 子ウインドウの限界というか , いちばん ウのいちばん始めのものへのポインタが fir 最後のウインドウというのは別に間題なく st て、す。自分が owner の始めに位置している リストの先を NULL にて、も落としてしまえ なら , 自分自身は owner → first ( ) になると ばすぐ解決します。しかし , 始まりのウィ いうことてす。 last(), findWindow(), f ウインドウが入れ子構造になっているこ ンドウはどうて、しよう。前回は winT 叩とし ront ( ) , insert ( ) , remove ( ) は , いずれも とは理解していただけたて、しようか ? あ て例外的な変数を使用して初めの一撃とし 自分の所有しているウインドウに対しての るウインドウに注目すると owner ウインドウ て使用しました。 どうせならこのいちばん アクセスとして作成します。 next ( ) , prev が上にあり , first<' 始まる子ウインドウが下 最初のもウインドウて、あったほうが気持ち ( ) は自分と同階層のウインドウの次 , また に連なっているのがイメージて、きると思い がいいて、しよう。 DeskTop クラスを導入し は前のウインドウを返します onext ( ) はメ ます。そのイメージは上にも下にも無限の たい動機はそんなところて、す。そのための ンバ変数 nextWindow を単に返すだけて、す。 ウインドウが連なっているものになると思 始まりのウインドウを ( 伝統的に ) DeskT 叩 日 ect クラスから導出した Window クラス DeskTo p クラス List 6 旧 / / 座標系変換 virtual POint toLocal(Point src) : virtual POint t0G10baI(P0int src); / / 枠を描く virtual void drawFrame() ; / / 同レベルの次又は前の windo 響 Window *next() : Window *prev() ; / / 子ウインドウ関係 Window *last(); Window *findWindow(const POint p) ; Window *front(Window *wp) ; Window *insert(Window *wp) : Window *remove(Window *wp) ; / / マウス処理 virtual void handleMouse(const P0int P) / / 点をうっ virtual VOid putPixel(Point P, byte C010r ) ; class Window : public Rect public: Window *owner; Window *first; Window *nextWindow; / / コンストラクタ Window(const Rect& bounds) ; virtual Window() { shutDown() ; virtual void shutDown() ; 〃 window の枠を設定 void setBounds (const Rect& bounds) : / / 枠を取得 Rect getBounds ( ) ; / / 枠を正規化 void regular() : / / parent / / child Fig. 2 子ウインドウの連鎖 Fig. 3 すべての Window は DeskTop の上にある DeskT0 p NULL ・ nextWindow fi 「 St ・ nextWindow first ・ nextWindow fi 「 st ・ nextWind0W fi 「 St U LL ・ nextWindow first ・ nextWindow ULL first IJ LL ULL NULL ※順番はサンプルとは違います 72 C MAGAZINE 1993 7
最新ロ 0 ロロレポート プラリなら , なんとかプラウズすることが 可能て、す。 CPAD 25 ルキーポードというテクニックを用いてい ます ( 17 行目 ) 。また , 、、 . fin" という拡張子を もっファイルを編集するとき , 自動的に fin モードにするため , . fin というマクロを定義 して , そこから fin mode を呼び出すように します ( 51 ~ 54 行目 ) 。 今回は , fin の実行のみて、したが , fin のコ マンドの入力補完や , アウトラインプロセ ッサなど , さまざまな機能を定義して , ロ ーカルキーボ、一ドに割り当てることがて、き るて、しよう。筆者は , fin モードのほかに TeX モードや , prolog モードを作って活用 しています。 BRIEF に付属のマクロには , TLIB ( ポーランドのライプラリアン ) や PV CS ( バージョン管理システム ) を操作するた めのインタフェイスマクロがあります。 Li st 4 を参考にして , いろいろなプログラムの ューザインタフェイスとして BRIEF を使え ないか考えてみるのもおもしろいて、しよう。 おまけの C 十十クラスプラウザ 規模の大きいマクロの例として , C 十十用 のクラスプラウザを作成してみました。 Fi g. 4 がその実行画面て、 , 中央にクラス , 右に メンバ関数の一覧がアルファベット順に表 示されており , クラスやメンバ関数を宣 定義している場所に , ワンタッチて、ジャン プすることがて、きます。このほか , 基本ク ラスと派生クラスの一覧を表示して , カー ソルキーて、 , クラス継承ツリーをたどるこ とがて、きます。 通常 , クラスプラウザというと , 別プロ グラムになっていて , ふだん使い慣れてい るエデイタとの整合が悪いことが多いのて すが , このクラスプラウザは , まさに組み 込みなのて、 , 整合はバッチリて、す。 このプラウザは , C 十十のソースの解析か ら , ウインドウの操作まて , 全部 BRIEF の マクロて、記述してあります。マクロの規模 が大きいのて、 , ときどき「メモリを使い果た しました」のメッセージが出ることがありま すが , それて、も , MS-C/C 十十の MFC や , BC 十十の OpenWindows 程度のクラスライ BRIEF の正規表現によるパターンマッチ ングのおかげて、 , プログラムが短くて済み , 動作スヒ。ードも思ったほど遅くありません て、した。このマクロは 1 日程度て作成するこ とがて、きましたが , 同じ処理をするプログ ラムを C 言語て、書いたとしたら , 解析部分て、 さえ 1 日て、は済まなかったと思います。 以上 , BRIEF について , 特徴を紹介し , 強力なマクロプログラミングの実例につい て紹介しました。 最近て、は , DOS 上て、動く GNU Emacs (D emacs) の登場て、 , 強力な競争相手がひとつ 増えたわけて、すが , マルチタスクをサポー トしない DOS 上ては , Emacs の持ち味が今 ひとっ発揮て、きていないようて、す。 その点 , もともと DOS 用に開発された BR IEF は ,パソコン上て、の開発のために必要十 分な機能を持ちつつ , また , 286 マシンて、も 動作すること , マクロ言語が C 言語に似てい ること , オーバラップウインドウが使える ことなど , Demacs にない利点を備えていま す。 本記事て、 BRIEF に興味を持たれた方は , ぜひ一度実際に BRIEF に触って , 自分に合 った開発環境を構築してみてください。最 初の敷居は少し高いかもしれませんが , マ クロを使いこんて、いくにつれて , 高機能工 デイタによって , いかに作業効率が向上す るかを実感すると思います。 まめ 「 BRIEF Ver. 3.0 JR2.00 」 FAX 0425 ( 27 ) 引 27 TEL 0425 ( 23 ) 4469 BR 旧 F ユーザサポート係 日本システム ( 株 ) 〒円 0 立川市曙町ト田一 2 く問い合わせ先 > く価格 > ー清ビル 20 , 000 円 Ver• C 言語開発支援ツール ドキュメント情報を自動生成 ソース上で統括管理 C ソース内部を一元管理する ソース整形機能 ( AN 準拠 ) 統合環境モードによるスピー ティーで円滑な操作を実現 十数種に及ぶ自動出力機能に より仕様書作成を完全自動化 発売 5 年の実積と数百キロス テップに対応するプロ仕様 広かる CPAD の世界 C ソースの解析・管理・学習ツールとして 特長 〒 760 香川県高松市西内町 3 ー 15 オオッカ商事システムクリエイト事業部 ロ HTSUKA 受付時間 / AMIO : 0 ト 5 : 圓月曜ー金曜 ( 祝日除く ) TEL ロ 878-5 ト 1807 ( 技術的なこ員問・こ相談にお電話てお答えします。 ) ソフトウェアインフォメーションセンター ( 教育・企業向けには 10 ユーサーバックもございます ) *128,000 く他機種用〉 標準価格く消費税別〉・・・・・¥ 98 , OOO 佃シリーズ用〉 く商標登録出願中 > く資料請求番リ 147 > 最新開発環境レホート 147
the world through 曲 e 叩 sunglasses 00king a って , 複数プラットホーム向けの市販のユ ーティリティ類を作っています。 Eigen が G uild を選んだのは , そのマルチプラットホー ム対応機能と , ( オプションて、提供される ) モデリングプログラムのためて、す。彼の感 想て、は , Guild のいちばん良い点は , SDK と のインタフェイスが楽だ , という点。これ は , その他のツールがさばっている点だそ うて、す。また , GuiId はカスタマサポートが 立派て、 , 〔出来上がったアプリケーションの〕 実行性能も一般的に良好ということて、す。 欠点は , 学習曲線が高い〔習得が難しい〕 ことて、す。彼の感想て、は , GuiId は非常に取 つつきやすいけれども , プロジェクトの重 要部分を手がけるころになると , 急に難し くなるそうて、す。その他の欠点は , マニュ アルの出来ばえ , 新バージョンが開発中て、 あること , そしてマルチプラットホム向 けの共通機能がやや貧しいことて、す。複数 のネイテイプの GUI に対するカバー範囲を , Guild はもっと広げる必要があります。 ばくが話を聞いた二人目は , TASC 社の N ancy Streifel て、す。彼女は , Guild のカスタ マサポートに満足しており , 覗き ( snooper ) 機能がお気に入りて、 , またイベントループ の各種機能が強力だと言っています。その イベントループの中て、は , 基本的に どの イベントに何を結び付けてもよいのて、す。 StreifeI は , ライプラリのカバー範囲につい ても満足していました。低レベルの , 個々 のプラットホーム独自のスタイルを目指さ ごく使いやすいということて、 ないかぎり , す。彼女の見解て、は , 唯一の深刻な弱点が 例外処理て、す。 GuiId は , 例外が起きると報 lnmark DeveIopment 社 zApp 告も何もしないのて、す。 22 C MAGAZINE 1993 7 ( 価格などはメーカーに直接問い合わせのこ トウェアの一種て、す。恰好いい設計環境や かすんなり定住してしまう , そういうソフ zApp は , ばくのマシンの上にいつの間に クラスプラウザはありませんけど , とにか く良質なコードを提供しているのて、す。 zA pp は元々は lnmark 社が , 同社の経理財務分 野向けのソフトウェア製品の移植作業を楽 にするために内製したものて、す。本稿て、取 り上げた製品の中て、は珍しく , クラスライ プラリて、あるとともにアプリケーションフ レームワーク方式て、もあるという製品て、す。 lnmark 社は , 新バージョンの開発て、忙しか ったため , ばくが指定したサンプルアプリ ケーションを作ってはくれませんて、した。 そこて、 , zApp のサンプルプログラムは , ス ヒ。ードの比較のためにばくが作った二つだ けて、す。 lnmark 社の強みは , コードの質て、す。ソ ースコードも , 説明やコメントがしつかり 書かれています。ソースコードをパーサて、 フィルタしてプリンタにかければ , 完全な リファレンスマニュアルがて、きてしまいま す。ライプラリもきわめて充実していて , メモリ管理や , グラフィカルオプジェクト を操作するための強力な機能も含まれてい ます。ューザ入力の確認チェックという部 分て、は Zinc に劣りますが , この方面も次の バージョンて、は強化されるて、しよう。 zApp は現在 , Windows 3.1 と NT をサポ ートしています。 OS/2 と Motif 向けも , や がて発売されます。また , MEWL 〔 DOS 向 けのマルチウインドウシステム開発用ライ プラリ製品〕を使って DOS もサポートして います。マニュアルは分かりやすいのて、す が , 実習書という点て、はやや不満て、す。た だし , ソースコードて、提供しているサンプ ルプログラムは豊富て、す。その中には , Ch arles Petzold の Programming Windows (Microsoft Press, 1993 ) [ 1 ] の中のサンプル プログラムがすべて含まれています。 zApp には , プログラム作りを支援するツ ール類はとくに含まれていません。しかし リソースファイルをサポートしていますか ら , 別途お気に入りの画面設計ツール〔リ ソースエデイタなど〕を使ってダイアログ などを作り , それを操作するコードを zApp を使って作るというやり方がて、きます。 lnm ark 社自身が , デザイナー〔リソースエディ タなどの設計ツール〕を将来提供すること もありえますが , 今現在 , 各 GUI のネイティ プのインタフェイスデザイナーを使えます し , その場合のコード量も比較的少ないて、 すから , 自社製品として作ることはずっと 後回しになるて、しよう。 Windows-$495, OS / 2 ー $ 995 , UNIX Motif—$1, 495 Liant の C 十十 /Views は , ばくの本の中て、 は , マニュアルやコード中のコメント類が 充実しているという点て、 , 高い評価をケえ ています。、、 HeIIo world 〃プログラムを作っ てから , それにメニューやダイアログなど を加えていくという教え方をしているライ プラリ製品が多い中て、 , Liant は , クラスの 作り方 , 派生クラスの作り方 , クラスのイ ンスタンスの作り方 , そしてアプリケーシ ョンの作り方まて、 , みっちりと教えてくれ ます。これだけ教え方が詳しいのは , たぶ ん製品中に GUI の構築ツールが含まれていな いからて、しよう。 Liant は現在 , Digitalk の SmalltaIk/V のプラウザに似たクラスプラウ ザを用いていますが , 構築ツールを提供す る計画はもっています。その結果 , あの詳 しいマニュアルを , 全面的に変えることは しないて、ほしいて、すね。 Liant のプラウザの良い点は , その内蔵パ ーサて、す。コンパイルしていない , あるい はコンパイルて、きないファイルて、もプラウ ズて、きます。またこのプラウザは , あなた が作るプログラムのための makefile も , 自 動的に作ってくれます。 このプラウザのほかにも C 十十 /Views は , いかにもプロ向け製品という感じのツ ールを , 幾つか含めています。まず , ソー スファイルとヘッダファイルの圧縮解凍 , ソースとヘッダからのドキュメンテーショ ンファイルの作成 , そしてアプリケーショ ンの環境ファイルのアップデートをやって C 十十 /Views Liant 社
ファイル八ンドルの 0 にコンソール入力を割り当て直す 1 : # i ncl ude く s td i 0. h> 2 : #include く i 0. h 〉 3 : #include く fcntl. h> 4 : #include く conio. h> 5 : 6 : main() bufCBUFSIZ]; 8 : Char 9 : int handle, handle2, handle3; i nt ⅱ nes : FILÉ *fp; 12 : handle = fileno(stdin); 13 : / / handle は標準入力のファイルハンドル ( 0 ) ん。派生クラスて、は , far 仮想関数 呼び出せます。 handle2 = dup(handle) : / / 標準入力を二重化 - 叩 en("CON", O-RDONLY); handle3 / / コンソール入力をオープン テープルを使う huge を使って宣言 dup2(handle3, handle) : 16 : / / ファイルハンドル O にコンソール入力を連結 fp ニ fd 叩 en(handIe2, / / もとの標準入力をファイルストリームに します。 List 3 にプログラム例を ー ines Q プログラムがリダイレクトさ vhile (fgets(buf, sizeof buf, (p)) { / / リダイレクト先からの入力を 示します。 fputs(buf, stdout); 20 : / / 標準出力へ if ( + + lines 〉 23 ) { 22 : 3 ) スマートコールバックを使う ー ines れているときでも , getch などのラ fputs("More. 23 : . Yn ” stdout); 24 : vhile (kbhit()) getch(); / / キーパッフアのクリア DLL て、基本クラスを宣言し , . E イプラリ関数がコンソールからの 25 : getch() : / / コンソール入力待ち 26 : XE て、そこから新たなクラスを派生 入力を受け付けるようにしたいの 27 : 28 : することもあります。本来 , Wind ですが , どうすればよいでしよう 29 : } ows の DLL から . EXE 内の関数を か。 呼び戻させるには , MakeProcIns A 標準入力を対象とするライプ tance て、関数に対応するインスタン スサンクというものを作成しなけ ラリ関数は , 常にファイルハンド ればなりません。メンバ関数のひ ルの 0 を使うようになっています。 とつひとつに対してインスタンス したがって , ファイルハンドルの サンクを作成することは非常に手 0 にコンソール入力を割り当て直す ことて、 , ライプラリ関数がコンソ 間がかかります。 こうした手間を省くために , Bo ール入力を使うことがて、きます。 rland C 十十にはスマートコールバ List 4 にプログラム例を示します。 ックというオプションが用意され ています。 . EXE ファイルをコンパ Q DOS/V 版 Borland c + + でグ イルするときにスマートコールバ ックを指定すれば , インスタンス ラフィックスを使っていますが , VGA モード以外でも漢字文字列を サンクがなくても DLL から . EXE 内 の関数を呼び戻すことがて、きるよ グラフィックス画面に表示するに うになります。スマートコールバ はどうすればよいでしようか。 ックは , コマンドラインコンパイ A 標準添付されているグラフィ ラて、は一 WS オプションに相当しま す。 ックスドライバのうち , DOSVGA なお , スマートコールバックは 以外て、は日本語の表示をサポート 実行ファイルのためのオプション していません。 て、あり , DLL て、は使えません。 文字フォントを取得する関数 do svgetfont を使って , 直接グラフィ スマートコールノヾックによって , DLL て、宣言された基本クラスの仮 ックス画面にイメージを展開する 想関数を . EXE の派生クラスて、オー 必要があります。 List 5 にプログラ バライドしても仮想関数を正しく ム例を示します。 List 4 List 5 char fbufC32] : initgraph(&gd, "C: YYBORLANDCYYBGI") : &gm, eouttextxy(50, 50 , " 漢字出力のテストプログラム " ) : getch(); closegraph() : return 0 ; 叮ー 8 0 11 り乙ワ -4 ・ : : 4 一ト LO LOLO return 0 : dosvgetfont を使って , 直接グラフィックス画面にイメージを展開 1 : #include く graphics. h> 2 : #include く dosv. h> 3 : #include く jctype. h 〉 4 : #include く coniO. h 〉 5 : 6 : typedef unsigned char BYTE; 7 : typedef unsigned short WORD; 8 : 9 : VOid outcharxy(int X, int y, code) unsigned BYTE fbuf[32] : i n t i X, i y, i W, i C : WORD bi ts; i 響 = co de く 0x 100 ? 8 ・ ニ getcolor() : dosvgetfont(code, iw, 16 , 0 , fbuf); for ( i y = 0 : i y く 16 ; i y + + ) { b i ts ニ fbuf [ i y] くく 8 ; 20 : e ー se 22 : ニ (fbuf[iy*2] くく 8 ) + fbufCiy*2 + 1 ] : b i t s for (ix 23 : 0 : i X くⅳ : i x 十十 , b i ts く← l) putpixel(x + ix, y + iy, (bits & 0X800 の ? ・ ー C 25 : 26 : } 28 : VOid eouttextxy(int x, int y, const char *str) 30 : i n t i , k : 32 : for (i ニ 0 : str[i); 33 : i f (k ) { 34 : outcharxy(x + i*8, y, k + (BYTE)strCi]); 35 : 36 : } else if (iskanji((BYTE)strCi])) { k = (BYTE)str[iJ くく 8 ; 38 : } e lse { 39 : outcharxy(x + i*8, Y, strCi]); 4 4 : int main(void) 46 : int gd = CGA, gm ニ CGACO; List 5 lnformation from CompiIer Makers 163
—Effectiv C + + SOFT 、 B. W. カーニハン 修による ュータ学 世 的なコン 話 の Add ・ ついに千行 邦版第 1 弾 0 好評発レ中 C + の 5 の急所 訳 定価 3 , 00 円 ( 税込 ) ーズ著 岩谷 スコット・マイ 「知識」と「実 とのギャップを埋めるヘく て生まれた、 視のガイドブック 実践 プロ プログラマ養 講座に講師として携わった 者が、その実 の過程で感じこ間題点を、びやすく理解 やすい構成で 践教 ケ ミン。技術を高めるこめには欠かない一冊であ 4 章 クラスと数 . その設計と宣 5 章 クラスと数 . その実装 継承とオブジェクト指向設計 6 章 7 章 その他 ~ 、の 50 の所 CONTENTS Guides for C Programmers フミング技法を提示 ! 具体的なプロ C プロ ラマのバイ レ誕生 ! ラマのた C プロ の ための実ガイド C プグラマ C をあ程度理解した方こ、 C + + の具体的な機能を実例を、 げて紹。 C + + による本的な活用の事伊を、わかりやすく 俊英柴田 洋が贈る、 C + + 説書の決定版。から C + + へ、その 張の必然性と C + の特長を系統的解説して 望洋博士の入門シリーズ② C プロクラマのための C + + 入門 A 0 de fo ′ 0 Programmers 条田望洋・一 [ 著 ] C プログラマのための実践ガイド いシャラーム・ヘクマトプール第・岩谷安 コ■ロ■国 B5 判・ 285 。ージ 定価 3 , 600 円 ( 込 ) 5 変形判・ 332 ページ 定 2 , 900 円 ( 税込 ) IB 饂 S ! 田当 S0fIBANK BOÜKS 智 ソ ト ^ ンク株式会出版事業部