OXlib++ パーツ作成 ソフトウェア開発の株式会社OUK



OXlib++ パーツ作成 C++にて書き直された、X-window GUI構築ソフトOXlib++です。さまざまな問題点を簡単・便利に解決します。

OXlib++ パーツ作成 ソフトウェア開発の株式会社OUK


OXlib++部品作成

コンパイラ

OXlib++は g++の使用を前提に作られている。

g++でなくても、できのいいC++コンパイラ なら、コンパイル可能である。

NEWS-4000のようなできの悪いコンパイラ ではまったくコンパイルできない。

注意

OXlib++はコメントに日本語を多用している。

ところが g++をはじめ代表的なC++コンパイラ は日本語を解釈してくれない。

特に SJIS を使用する場合、2バイト目が 0x5C になることがある。

ゆえにコメント行(//)で最後の文字が「表」など 0x5C で終了する文字を書くと、\n が無視され次の行もコメントになってしまう。

OXlib++のオリジナルなコードは全て検査してあるが、ユーザが作るクラスは用心が必要だ。

ファイル名の銘々規則

ファイル名は DOS への転送を考慮し、「8文字+.+3文字」の旧 DOS ファイル名規則を厳守する。

ただし、unix 上のファイル名はすべて英小文字である。

  1. 先頭部分

    ファイル名の先頭2文字で種別を表す。

    • OX - 基本クラスおよび独立クラス
    • OC - GUI部品クラス
    • OR - OXresDefCクラスで定義するリソーステーブル。OCファイルとペアで存在。
  2. 拡張子

    一般的なCコンパイラ (g++)の銘々規則に従う。

    • CXX - コンパイルするソースコード。
    • H - コンパイルするC++の定義ヘッダー。
    • MAK - makeの指示ファイル。

メンバ名の銘々規則

  1. メンバ変数

    以下に示す規則で変数を宣言し、右側に必ず変数の説明を記述すること。

    xK自由につける(32文字まで)
    変数の種別
    x = P public
    K = M private もしくは protected

    変数の型を表す識別文字(1~3小文字)

    • cchar 1バイトの符号付き整数で文字を表す。
    • bBYTE unsinged char のことで、1バイトの符号無し整数。
    • s short 2バイトの符号付き整数
    • wWORD unsigned short のことで、2バイトの符号無し整数。
    • iint 2バイトもしくは4バイトの符号付き整数
    • uiUINT unsigned int のことで、2バイトもしくは4バイトの符号付き整数
    • fBOOL intと同じだが、論理変数を表わす。(TRUE、FALSE)
    • llong 4バイトの符号付き整数
    • dwDWORD unsigned long のことで、4バイトの符号無し整数。
    • ddouble 倍精度浮動小数点データ(バイト数はコンパイラに依存)
    • tfloat 浮動小数点データ(バイト数はコンパイラに依存)
    • ポインタの場合はさらに先頭にpをつける。特別な型は型名の頭2~3文字をとって区別する。
  2. メンバとリソース名
    • リソース名

      旧OXlibの互換性のため常にrOXで始める。例えばrOXresNameとなる。

    • private変数

      そのクラスにしか必要のない変数。名前は自由である。

      xMname x=変数の型 name=リソース名

    • protected変数

      リソースとして使用しているデータ。

      名前はメンバ変数 銘々規則にのっとり、以下のように付ける。

      xMname

      x=変数の型

      name=リソース名

      例えばrOXresNameの整数型のメンバ変数 は以下のようになる。

      iMresName

    • private関数

      派生クラスでも利用しない関数。

      小文字で始める。

      詳細なるインターフェースの記述は不要であるが関数の説明は記述すること。

    • protected関数

      派生クラスで使う可能性のある関数。

      名前は大文字で始まる任意の名前。

    • public関数

      先頭2~3文字で用途を定めている。

      ただし、旧 OXlib と互換性のための関数はこの限りではなく以前と同じの名前を使用する。

      1. リソース名により決まる。以下の例はリソース名 rOXresNameのときの名前である。

        • GRresName リソースの値を取得。
        • SRresName リソースに値を設定。
        • GTresName 旧リソース名に対応してテーブルに記述されるリソース読みだし関数。
        • STresNamex旧リソース名に対応してテーブルに記述されるリソース読みだし関数。
      2. その他の汎用的な関数の名前

        • EvEventName イベント処理。
        • Getxx一般取得。
        • Setxx一般設定。
        • Isxxxx調査のための関数で返り値はBOOL型。
        • CreateX11オブジェクトの生成。

GUI部品クラスの構造

OXlib++ではユーザのGUI部品クラスの拡張を許している。

独自のGUI部品を作成するには、必ず既に定義されているクラスの基底クラスとして定義した方が無難である。

OXlib++のフレーム・ワークはそれほどユーザにクラス構造を強制するものではないから、理屈の上では独自のクラスを作っても動作させることは可能だ。

その場合においても既存のクラスの動作をよく理解することが必要である。

  1. クラス・ヘッダー・ファイルの構成

    それほど厳密な規定ではないが、OXlib++のGUI部品コードのヘッダー・ファイル(oc~.h)は以下の構成で記述することが好ましい。

    1. タイトル・ヘッダー

      適当なタイトルヘッダーを記述する。

      OXlib++の標準は以下の書式である。

      //======================================ヘッダー定義開始

      // ZWIN04:oc部品ファイル.h

      // クラス分類:部品クラス名:クラスの簡単な説明

      //                  CopyRight表示

      // 改定履歴

      //======================================ヘッダー定義終了

    2. 二重インクルード防止定義

      二重に定義されてコンパイル・エラーを出さないように以下の定義でヘッダー全体をくるむ。

      注意

      ファイル最後に#endifを忘れないこと。

      #ifndef __ファイル名_H

      #define __ファイル名_H

    3. クラス概要などの説明

      #ifdef LL

      #endif

      で説明を囲む。

    4. 下位クラスのコンストラクタ定義のためのマクロ定義

      定義はすべて大文字でおこなう。

      ヘッダー・ファイルのコンストラクタの引数定義に使用。(デフォルト値定義)
      #define 当該部品名_ARGINIT 基底クラス部品名_ARGINIT,当該部品名引数型引数名前=デフォルト値....
      コード・ファイルのコンストラクタの引数定義に使用。(引数宣言のみ)
      #define 当該部品名_ARGLIST 基底クラス部品名_ARGLIST,当該部品名引数型引数名前....
      上位コンストラクタ呼出引数の定義
      #define 当該部品名_CALLARG 基底クラス部品名_CALLARG,当該部品名引数名前....
    5. クラス定義

      GUI部品クラスは必ず OXbaseC、もしくは OXbaseC を基底クラスとするクラスの派生クラスでなければならない。

      class クラス名 :

      public 基底クラス・クラス定義

    6. リソース定義Tableの定義

      旧リソース名でアクセスできるように、OXlib++ではリソース名とメンバ関数が1対になったテーブルを定義する。

      実際のテーブル定義ファイルは or~.cxx である。

      private:

      static const OXresDefC resStbl[];

      その他のprivateメンバ変数 の定義を続ける。

    7. リソースに使用するメンバ変数の定義

      GR~やSR~のリソース取得・設定メンバ関数より参照される変数の定義。

      protected:

      public:

    8. 部品特性Tableの定義

      static const OXpartsC partsStbl;

    9. その他のpublib変数の定義

      もちろん無い方が好ましい。

      private:

    10. クラス内部関数の定義

      下位クラスの使用を許可する関数を定義

      protected:

    11. 初期化および消滅やoperatorなどのメンバ関数

      コンストラクタ はマクロを使用して記述する。

    12. 部品に固有な定義データを返すすべての部品の共通仮想関数

      部品の特性を表すstaticデータテーブルを返す。

      virtual const OXpartsC& GRpartsDef(void) const//各種部品固有のデータ

      {

      return (OXtextC::partsStbl);部品定義テーブルの参照を返す。

      }

      注意

      下位部品クラスは必ずこの関数をオーバーライドしなければならない。

      詳細はOXbaseC基底クラスの仕様を参照されたし(oxbase.h)

    13. OXlibリソース取得・設定

      OXlib++の新規リソース、および、リソースをメンバ関数で扱うときに使用する。

      もちろん引数は自由に決めてよい。

    14. BOXのイベント処理

      基底クラスの仮想関数を再定義して、部品の動作を記述する。

    15. 旧OXlibリソース取得・設定

      OXresDefCテーブルに記述されるべきメンバ関数。

      取得はGT、設定はSTで始まり、引数は以下のように決まっている。

      • リソース名でのリソース取得

        OXERR GTリソース名(//Success=処理成功もしくは1..n=OXlibエラーコード

        OXstringC& stOut//OUT:読みだしたリソース文字列

        );

      • リソース名でのリソース設定

        OXERR STtopAlign(//Success=処理成功もしくは1..n=OXlibエラーコード

        OXstringC& stIn//IN:設定するリソース文字列

        );

      通常、リソース・メンバ変数 を文字列に変更するだけなので、なるべくヘッダー内にインライン関数として記述する。

      このリソース・テーブル関数は仮想関数である必要はない。

      なぜなら、OXlib++の標準処理は必ず指定クラスからリソース・テーブルを検索するので、同じ名前のリソース名があれば、下位クラスの方が優先されるからである。

    16. クラス定義の終了

      }; //Class end

    17. ヘッダー定義の終了

      先の二重インクルード防止用の #ifndef に対応する。忘れてはいけない。

      #endif //Include header end

  2. ソース・コードの構成

    ソース・コードはクラス定義 ヘッダーと同じ名前を持った oc~.cxx ファイルに記述される。

    1. タイトル・ヘッダー

      適当なタイトルヘッダーを記述する。

      OXlib++の標準は以下の書式である。

      //======================================ヘッダー定義開始

      // ZWIN04:oc部品ファイル.cxx

      // クラス分類:部品クラス名:クラスの簡単な説明

      //                  CopyRight表示

      // 改定履歴

      //======================================ヘッダー定義終了

    2. ヘッダーのインクルード定義

      標準では必ず以下のファイルをインクルードする。

      #include "oxlibpp.h"

    3. オブジェクトを生成するstatic関数

      部品定義テーブル に記述するための自分自身のオブジェクトを生成するためのstatic関数を定義する。

      メンバ関数の形式は以下に決まっている。

      部品名にて動的に部品を生成するために必須である。

      static 自クラス名* NewObject(

      CCH* pcBoxName, //IN:新しく生成するBOXの名前

      OXbaseC* const pbsUpper //IN:上位BOXのポインタ。NULLのときは最上位BOX

      )

      {

      return (new 自クラスコンストラクタ

      (pcBoxName, pbsUpper));

      }

    4. 部品定義テーブル

      部品の動的生成 のために使用するクラス情報の定義。

      OXlib++の標準部品では必ず必要である。

      もし、無ければ動的生成やリソースエディタから扱うことができなくなる。

      部品定義テーブル は OXpartsC クラスのオブジェクトである。

      OXpartsCクラスは oxparts.h に定義されている。

      なお、オブジェクト生成関数の定義ためキャスト・マクロ NEWBOXFUNC が用意されている。

      const OXpartsC クラス名::partsStbl = {

      部品名(ユーザが認識する部品名)

      部品の説明(リソース・エディタで表示する部品の簡単な説明)

      OXpartsC::eSINGLE,//

      部品の種類(以下のどれかを定義する)

      eNOUSE = 0,//単独では使用できない部品(メタクラス部品)

      eSINGLE,//単独で使用する部品

      eGROUP//グループ化部品(下位のBOXを制御)

      FocusChangeMask | KeyPressMask | ExposureMask,//

      イベントマスクの値(X11のイベントマスク値を記述、この部品が受け取るイベントを示す)

      オブジェクトを生成するstatic関数へのポインタ。

      (通常(NEWBOXFUNC)NewObjectとなる)

      リソース定義

      Table(or~.cxxにて定義されるリソース定義テーブルのポインタ)

      基底クラスの部品定義Tableのポインタ(リソースを上位クラスに渡り検索するときに必要)

      };

    5. コンストラクタ

      クラス名::クラス名(

      当該クラス引数マクロ(デフォルト値の記述なし)

      ) : 基底クラス(基底クラス引数マクロ)

      {

      各リソースのデフォルト値を代入。

      }

    6. イベント処理(仮想関数)

      基底クラスで定義されているイベント処理をこのクラス専用に書き直す。

      関数の型は以下のように決まっている。

      Bool クラス名::Evイベント名(

      const X11のイベント構造体型& evイベントの種類により異なる

      )

      {

      まず基底クラスの処理を呼び出して返り値を検査する。

      OXbaseCのイベント処理は呼び出した方がよい。最低限のイベント処理がなされている。

      OXbaseCのイベント処理を呼び出さないとデバッグメッセージが表示されない。

      自分のイベント処理を記述。

      派生クラスが継続してイベント処理を実行してもよいなら True を返す。

      イベント処理を中止するなら False を返す。

      }

  3. 新規部品の登録

    OXlib++ で使用するGUI部品クラスは必ずファイル allparts.cxx に定義しなければならない。

    allparts.cxx は すべての部品定義クラス(OXpartsC)のオブジェクト・ポインタの配列を定義している。

    この配列変数名は partsAllTbl[] でありシステム唯一だ。

    OXlib++ は partsAllTbl[] を検索することにより、部品名から部品定義テーブル を得ることができる。

    1. 部品の検索

      全部品テーブル partsAllTbl[] から任意の部品名を検索して、部品定義テーブル を得るには ALsearchParts("部品名"); が用意されている。

    2. apdumy.cxx

      常に部品テーブル allparts.cxx をリンクすると、使用しない部品までアプリケーションにリンクされてしまうことになる。

      これを防止するために、文字列名で部品を動的生成する必要の無いアプリケーションでは、apdumy をリンクするとよい。

      このとき ALsearchParts() は常にエラーとなる。メモリは節約されるが、文字列名での部品生成は、もちろんできなくなる。

    3. 部品の動的生成

      OXlib++ ではプログラム中から new を用いて動的にクラスオブジェクトを生成するのは何の制限もない。

      自由におこなえる。

      部品名にて動的に生成するには ALsearchParts() にて部品定義テーブル を検索し、部品定義テーブル に定義されているオブジェクト生成 static 関数を呼び出す。

      例えば BOX 名 "mainw" で部品名 "TEXT" という最上位の BOX を生成するには以下の様にコーディングする。

      const OXpartsC* pparts;

      if ((pparts = ALsearchParts("TEXT")) == Null) return (12);

      OXbaseC* pbox = pparts->NewBox("mainw", Null);

      ただし、もっと便利な関数が用意されている。

      CreateBoxFromResRec("BOXフルネーム部品名");

      リソースファイルから直接BOXを生成して、さらにリソースを設定することもできる。

      MakeBoxFromResFile("リソースファイル名", "最上位BOX名");

  4. リソース定義

    rOX で始まる文字列リソース名で扱うべきリソースを定義する。

    文字列リソースは旧 OXlib と同様にGetResource() と SetResrouce()関数より使用する。

    文字列リソースの取り決めの必要の無いリソースはテーブル定義は不要である。

    この場合、メンバ関数を直接使用してリソースにアクセスする。

    もちろんリソースの動的生成やリソース・エディタからの設定はできない。

    1. リソース・テーブルの定義

      リソース・テーブルはファイル oc~.cxx にて記述する OXresDefCクラスのオブジェクト配列である。

      OXresDefCクラスはファイル oxresdef.h に定義されている。

      const OXresDefC OXtextC::resStbl[] = {テーブルの定義

      {最初のリソースの定義

      1. リソース名(rOXで始まる旧OXlib銘々法と同じ。ただし常に文字列で扱うので定数定義は不要)
      2. リソースの説明(リソース・エディタで表示される説明文章)
      3. リソース取得関数(キャスト・マクロ(RESFUNC)を用いて定義する GT~のメンバ関数へのポインタ)
      4. リソース設定関数(キャスト・マクロ(RESFUNC)を用いて定義する ST~のメンバ関数へのポインタ)
      5. リソースの種別(以下の定義のどれか)
        • eVOID :型は不明
        • eINT :int(4バイト整数)
        • eSTRING :OXstringC(文字列)
        • eBOOL :論理型(True/False)
        • eENUMTBL :enum (文字列テーブルより選択)テーブルは(7)で記述
        • eENUMFILE :enum (ファイルより選択)ファイル名は(7)で記述
        • eDOUBLE :double(浮動小数)
        • eFUNC :Function(実行のみのリソースで値は持たない)
      6. リソースエディタの入力の種別(リソースエディタが使用するリソース入力の部品を記述)
        • eNONE :ユーザ入力は許されない :eFUNCなど
        • eEDITBOX :EditBoxによる文字列入力 :eINT, eSTRING, eDOUBLE
        • eCHECKBOX :CheckBoxによるON/OFFの入力 :eBOOL
        • eRADIOBUT :RadioButtonによる選択入力 :eENUMTBL
        • eLISTBOX :ListBoxによる選択入力 :eNUMFILE
        • eDIALOG :特別なダイアログボックスによる入力
        • :リソース別にダイアログを用意する。ダイアログ名は(7)で記述する。
      7. リソースエディタへの情報(補助情報を(5)と(6)の種別により文字列で記述)

        使用しないときは Null とする。

        • (5)=eENUMTBL

          :選択文字列は","(カンマ)で区切って定義

        • (5)=eENUMFILE

          :リストボックスに表示すべきファイル名

          :定義ファイルは #define の形式C言語のヘッダ形式

        • (6)=eDIALOG

          :特別ダイアログボックスの名前、","(カンマ)の後ろにパラメータ

          :リソースエディタにより定義されている。ダイアログにてパラメータも定義

          現在サポートされている特別ダイアログ

          • CURSOR :Cursor Font 選択
          • FONT1B :1バイトフォント選択
          • FONT2B :2バイトフォント選択
          • COLOR :色名選択

      },

      {

      次のリソースの定義

      },

      RESTBLEND //テーブル終了記号

      };

    2. 文字列リソースの取得と設定

      常に仮想関数 OXbaseC::SetResource() と OXbaseC::GetResource() を使用してリソースの取得と設定をおこなうことを前提としている。

      • リソースの取得

        GetResource(リソース名、取得したリソースの値文字列)で、常にリソースの値は文字列(OXstringCの参照)で返される。

      • リソースの設定

        SetResource(リソース名、設定するリソースの値文字列、再描画フラッグ)

      もしくは

      SetResource(リソースファイルのリソース設定文字列、再描画フラッグ)

      で、常に設定値は文字列で指示する。

    3. テーブル検索の手順

      まず、最初に自クラスのリソース定義 テーブルを検索する。

      このとき部品定義テーブル よりリソース定義 テーブルのポインタを取得する。

      部品定義テーブル のポインタを返す static 関数は必ず定義されている。

      自クラスのリソース定義 テーブルにリソース名の記述が無ければ、1つ上のクラスのリソース定義 テーブルを検索する。

      このとき上位クラスの部品定義テーブル は自クラスの部品定義テーブル より得る。

      以上の動作をくり返し、最上位基底クラスOXbaseCまでのリソース定義 テーブルを検索する。

      リソース名を見つければ、リソース定義 テーブルに記述してあるメンバ関数を呼び出す。

  5. グループ部品制御

    グループ部品は自オブジェクトの下につながるBOXを制御する部品である。

    例えば OXradioButtonFrameや OXscrollBar などがある。

    グループ部品の制御はもちろんクラス内部の動作なのでアプリケーションには無関係であるし、そうでなければならない。

    グループ部品制御
    1. 下位BOXのコールバック利用

      グループ部品を作成するときに、グループ部品クラスで、 GroupCallBack()をオーバーライドすると、下位BOX のコールバックがすべてモニタできることになる。

      もちろん、下位BOXのユーザ登録のコールバック関数は呼び出され、その後に GroupCallBack()が呼び出される。

      下位BOXコールバックモニタ関数の呼び出し形式を以下に示す。

      virtual void GroupCallback(OXcallbackC* pboxCb, //IN:コールバックが起こったBOX

      const int iKind, //IN:部品ごとに定義されたコールバックの種類

      const XEvent* pev //IN:コールバック時に発生したイベント構造体

      );

    2. 下位BOXイベント利用

      自BOXの下につながるBOXのイベントそのものを利用してグループ部品を作成する場合に使用する。

      下位BOXのすべてのイベントをモニタすることにより、より汎用的なグループ部品の作成が可能になる。

      グループ部品BOXの場合に下位BOXでイベントが発生したときに以下の仮想メンバ関数が呼び出される。

      グループ部品はこの関数をオーバライドすることにより、下位BOXのすべてのイベントがモニタできる。

      virtual Bool DispatchLowerEvent(const XEvent& ev,

      OXbaseC* pBox /*IN:実際にイベントが発生したBOXオブジェクトのポインタ*/);

      ただし以下のイベントではDispatchLowerEvent()は呼び出されない。

      • Expose
      • GraphicsExpose
      • NoExpose
      • PressCont
      • DoubleClick
      • CaretTimer