C++による GUI構築ツール Oxlib

OXlib++プログラム

旧OXlibからの変更

従来の OXlib は言語Cで記述されていたためクラス派生が困難で、ほとんどの機能が基底クラスに実装されていた。
OXlib++はC++を前提にしているので、クラスの実装そのものが旧 OXlib からかなり変更されている。

  1. 基底クラスから他のクラスへ移動したリソース

    OXlib++では積極的にクラス派生を使用している。
    ゆえに、旧 OXlib の Base Class のメンバはずいぶん減少している。

    1. OXtextCクラスへ移動
      • usint topaln:1; //文字を上詰めに表示(False)
      • usint botaln:1; //文字を下詰めに表示(False)
      • usint leftaln:1; //文字を左詰めに表示(False)
      • usint rightaln:1; //文字を右詰めに表示(False)
    2. OXwinManCクラスへ移動
      • usint winman:1; //Window managerの介在を受ける
      • usint dswmsize:1; //Window managerによるresizeを受付けない
      • usint dswmpos:1; //Window managerによる位置移動を受付けない
      • usint appmodal:1; //モード付きBOX(閉じるまで他処理禁止)
      • usint fcsunmap:1; //Focusを失ったとき自動的にunmapされる
    3. OXcallbackCクラスへ移動
      • int result; //操作の結果
      • int status; //現在のBOXの状態
      • int argument; //cbfunc()に使用する汎用引数
      • int (*cbfunc)(); //ユーザのコールバック関数
  2. 独立したメンバとして実装
    • usint button1:1; //マウスボタン1を有効にする
    • usint button2:1; //マウスボタン2を有効にする
    • usint button3:1; //マウスボタン3を有効にする
  3. 名前の変更されたリソース
    1. 名前の変更されたリソース

      旧 OXlib では簡単にリソースを追加できないため rOXsizeOption を多目的に利用していた。

      OXlib++ではそのようなリソースはすべて改められた。

      • rOXsizeOption --> rOXsizeShadow box.iMsizeShadow //影の高さ
    2. 名前の変更されたフラッグ(直接使用するとき分かりやすいように)
      • usint nounmap:1; --> noUnmap //一度mapすれば永久にunmapされない
      • usint nodestroy:1; --> noDestroy //永久にWindowやPixmapが破棄されない
    3. 名前が変更され、意味が逆になったフラッグ(直接使用するとき分かりやすいように)
      • usint dsautomap:1 --> autoMap //上位がmapされても自動的にmapされない-->される
      • usint dsautomake:1; --> autoMake //上位がmakeされても自動的にmakeされない-->される
      • usint inhfocus:1; --> setFocus //ButtonPressでFocusをセットしない-->する
  4. 無理矢理リソース名に当てていた操作関数

    旧OXlibではメンバ関数そのものが実装できなかったので、すべての操作をリソース名でおこなっていた。

    • rOXfocus--> SetFocus()
    • rOXpointerPos --> GetPointerPos() SetPointerPos()
    • rOXwaitView --> WaitView()
    • rOXraiseTop --> RaiseTop()
  5. 廃止されたリソース

    C++の仕様上不要なリソースを廃止した。

    • rOXreference box.etc //多目的pointer参照リソース
    • rOXetcResource box.etc //特別リソースへのPointer
    • rOXpixmap box.drawmap[BITMAPNUM]; //描画に使うPixmapやBitmap
    • rOXprevlBox box.prevlBox //同一レベル、前のBOX
    • rOXnextlBox public member //同一レベル、後のBOX
    • rOXupperBox public member //上のレベルのBOX
    • rOXlowerBox public member //下のレベルのBOX
    • rOXownCon box.ownCon //部品へのPoiner
  6. 部品構造体

    旧 OXlib は部品クラスを定義するのに部品構造体 を使っていた。
    OXlib++の場合、クラス定義そのものであるので、インスタンスとクラスを分けて定義する必要はなくなった。
    部品の動作特性を表すフラッグは各クラスに仮想関数として実装されている。
    従来 OXCONP 定義されていたデフォルトのイベント処理に関するフラッグは、OXmainC に仮想関数として実装されている。
    従来の OXCONP 構造体メンバの変更を以下にまとめる。

    1. typedef struct _OXDRWS{
      • usint window:1; Windowをつくる ==>MakeBox()
      • usint pixmap:1; Pixmapをつくる ==>MakeBox()
      • usint bitmap:1; Bitmapをつくる ==>MakeBox()
      • usint num:3; OXmakeBox()時つくるDrawableの枚数 ==>MakeBox()
      • usint mapfocus:1; Map時Focusをもつ ==> MapBox()
      • usint prsfocus:1; Mouse Press時にFocusをもつ ==> MapBox()
      • usint dslbell:1; Deselのマウスクリック時ブザー ==> evButtonPress()
      • usint nocmpex:1; Exposeイベントを圧縮しない ==> evExpose()
      • usint prtfont:1; Printer Fontを使用する ==> PrintBox()

      } OXDRWP;

    2. typedef struct _OXCONS{
      • dword patGrp; この部品の部品類名 ==>廃止
      • long mask; この部品で受け付けるEvent mask ==>OXpartsC
      • OXDRWP draw; BOXを作るときの仕様 ==>(1)参照
      • int (*makefunc)(); OXmakeBox()の直後に実行される初期化関数 ==>仮想関数 MakeBox()
      • int (*destfunc)(); OXdestroyBox()の直前に実行される終了関数 ==>仮想関数 DestroyBox()
      • OXEVTP *evtTbl; Event関数翻訳テーブルのPointer ==>仮想関数evXXXX()
      • OXEVTP *rgetTbl; GetResource 関数翻訳テーブルのPointer ==>各部品クラスに実装
      • OXEVTP *rputTbl; SetResource 関数翻訳テーブルのPointer ==>各部品クラスに実装
      • OXEVTP *keyTbl; Key関数翻訳テーブルのPointer ==>各部品クラスに実装
      • _OXCONPP super; この部品のSuperClassへのPointer ==> OXpartsC
      • int (*mapfunc)(); OXmapBox()の直後に実行される初期化関数 ==>仮想関数 MapBox()
      • int (*unmapfunc)() OXunmapBox()の直前に実行される終了関数 ==>仮想関数 UnmapBox()
      • char* name; 部品名 ==>OXpartsC
      • short pno; 部品番号 ==>廃止
      • short kind; 部品 配置の種類 0:Normal 1:fixed ==>廃止
      • byte boxW; どちらかの大きさを100としたときの幅 ==>廃止
      • byte boxH; どちらかの大きさを100としたときの高さ ==>廃止
      • byte xoffs; たくさん配置したとき+するX方向offset ==>廃止
      • byte yoffs; たくさん配置したとき+するY方向offset ==>廃止
      • short cmpnum; 特別リソースに関する情報の数 ==>廃止
      • short mknum; 下位BOXを作成するための情報の数 ==>廃止
      • OXCMRP *cmpres; 特別リソースに関する情報 ==>廃止
      • OXLOWP *mklow; 下位BOXを作成するための情報 ==>廃止
      • char **cbspec; コールバック関数 の引数の定義 ==>廃止

      } OXCONP;

OXlib++のアプリケーション構造

GUIオブジェクト生成方法

GUIオブジェクトの生成方法により以下の3つである。

  1. 静的

    旧OXlibと同様にstaticなクラスオブジェクトを定義する方法。
    リソース・コンパイラの出力は常に静的 オブジェクトの定義の羅列である。
    オブジェクトはアプリケーションのロード時に構築される。
    このとき、GUIオブジェクトは変数名としてBOX名を_(アンダースコア)で接続した名前が与えられる。

  2. 動的

    プログラム中 new により自由に動的 なGUIオブジェクトを作成可能である。
    通常のC++のクラスオブジェクトの生成と全く同じである。
    このとき、コンストラクタの引数にてリソースが与えられる。

  3. リソース・ファイルより完全動的

    旧OXlibでは、リソース・エディタの出力であるリソース・ファイルをアプリケーションの起動時に読み込んで、基本リソースの再設定だけは可能であった。
    新しいOXlib++では、リソース・ファイルをアプリケーションの起動時に読み込んで、完全に動的 にクラスオブジェクトの生成とリソースの設定が可能である。
    BOXツリーの定義にしたがって起動時にBOXを構築するのである。

  4. 注意

    このとき必ずすべての部品を定義した allparts.o をリンクする必要がある。
    C++ は動的 なクラス生成は不可能だからだ。
    ただし、allparts.o をリンクすると、常にすべての部品のコードがリンクされるのでアプリケーションの容量が多少大きくなる。
    もちろん、リソースファイルによる動的 にオブジェクトを作り出さないときは allparts.o のかわりに apdumy.o をリンクすると使用している部品のみのコードしかリンクされない。

コールバック構造

OXlib++のコールバックはアプリケーションとGUIとの通信をおこなうための機構である。
本来 GUI とアプリケーションは美しく分離されていなければならない。
美しさは設計者の思想そのものである。
OXlib++は分離の美しい分離方法を実現するために複数のコールバック機構を提供している。

  1. コールバックの種類

    コールバックは OXcallbackC::SRcallback() にて設定する。
    SRcallback()の引数により自動的 にコールバック機構が決まる。

    • ユーザクラスのメンバ関数にコールバック

      ユーザが GUI の動作を記述するクラスを定義し、そのオブジェクトにコールバックする場合に用いる。
      例えばダイアログ・ボックス単位に処理をクラス化し、ダイアログに載るボタンのコールバックをそれぞれ対応するメンバ関数に割り当てる場合に用いる。

      設定書式

      SRcallback(&OXtopCサブクラスのユーザオブジェクト, メンバ関数のポインタ);
      起動関数は void func(OXbaseC*, int, int) な OXtopCサブクラスのメンバ関数でなければならない。
      メンバ関数が省略されれば Callback(OXbaseC*, int, int)が呼び出される。

      使用例

      class UserC : public OXtopC {
      public:
      MyCback(OXbaseC* box, int iKind, int iArg){}
      } UserObj;
      SRcallback(&UserObj, (TBACK)&UserC::MyCback);
      デフォルトのメンバCallback()を呼び出す場合。
      SRcallback(&UserObj, Null);

    • 任意のstatic関数にコールバック

      最も手軽に、かつ、乱暴に普通の静的 な関数にコールバック関数 を設定する。
      本来 C++では使うべきではないが、エラー処理など共通処理を記述するのは便利だろう。

      設定書式

      SRcallback(static関数のポインタ);
      起動関数は static void func(OXbaseC*, int, int) でなければならない。
      メンバ関数が省略されれば Callback(OXbaseC*, int, int)が呼び出される。

      使用例

      static MyFunc(OXbaseC* box, int iKind, int iArg){}
      SRcallback(MyFunc);

    • 別プロセスの起動

      GUIをプロセスの集合として設計した場合に使用する。
      コールバックは常に新しいプロセスを起動するので、GUIとアプリケーションの分離はほぼ完全である。

      設定書式

      SRcallback("起動されるファイル名", "起動時の引数文字列");
      指定したファイルを指定した引数で起動する。
      以降、パイプで接続して各種メッセージのやりとりをおこなう。

      使用例

      SRcallback("MyScript", "cb1");
      キーボードより「MyScript cb1」と打ったときと同じ。

    • メッセージパッシング方式のコールバック

      OXshell にて起動された OXlib++アプリケーションの場合のみ使用できる機構。
      OXshell はパイプによりGUIとアプリケーションを通信する。詳細は OXshell 参照。

      設定書式

      SRcallback("メッセージ文字列");
      OXshell にメッセージ文字列を送信する。

      使用例

      SRcallback("CB1");

    • 任意のBOXのコールバック指定をそのまま適用

      任意のBOXのコールバック指定と同じ内容で設定する。設定のコピーと考えられる。
      指定した BOX は 必ず OXcallbackC のサブクラスの BOX でなければエラーとなる。

      設定書式

      SRcallback(OXcallbackCのサブクラスのBOX);

      使用例

      SRcallback(&boxCb);

      このBOXを boxCb と同じコールバック設定とする。

  2. コールバック関数

    コールバックが起こり、実際にアプリケーションを呼び出す関数は常に以下の引数を持った形をしてる。

    
    void Cback( 
    OXbaseC* pboxOrg, //IN:コールバックが発生したBOX(オブジェクト
        int iKind, //IN:コールバックの種別(部品により異なる)
        int iArg //IN:rOXargumentの値
    );
    
    

    pboxOrg は Cback が呼び出されたBOX のポインタである。
    この BOX ポインタを活用することにより、コールバックが発生したGUIに関する情報を得ることができる。
    例えば、pboxOrg->GetTopBox() はコールバック発生BOXの最上位BOXのポインタを返す。
    その下の "OK" とういう名前のBOXのポインタは以下のように表すことができる。

    OXbaseC *pboxMain = pboxOrg->GetTopBox();
    OXbaseC *pboxOK = pboxMain->BOX("OK");

    2つ目の引数 iKind は部品が決めたコールバックの種類 である。
    どの場面でコールバックが起こったかを知ることができる。
    例えば、OXbarSlider クラスでは、iKind により以下のようにコールバックの種別が定義されている。

    • 0=減少側(上又は左側)のページ部が押された
    • 1=増加側(下又は右側)のページ部が押された
    • 2=スライダをドラッグしている最中
    • 3=スライダをドラッグした後Releaseされた

    最後の引数 iArg はアプリケーションが自由に指定できるコールバック引数である。
    リソース rOXargumentの値そのものを引数にしている。コールバックが起こる前にアプリケーションから SRargument()にて数値を設定しておく。
    コールバックを起動する部品が固有の値を持つ場合に使用する。
    例えば、ボタンが10個並んでいて、単に1~10までの数字を処理する場合は、リソースに1~10を指定しておくと、共通のコールバック関数 で処理できる。

ページトップへ