OXlib++部品作成
コンパイラ
OXlib++は g++の使用を前提に作られている。
g++でなくても、できのいいC++コンパイラ なら、コンパイル可能である。
NEWS-4000のようなコンパイラではまったくコンパイルできない。
注意
OXlib++はコメントに日本語を多用している。
ところが g++をはじめ代表的なC++コンパイラ は日本語を解釈してくれない。
特に SJIS を使用する場合、2バイト目が 0x5C になることがある。
ゆえにコメント行(//)で最後の文字が「表」など 0x5C で終了する文字を書くと、\n が無視され次の行もコメントになってしまう。
OXlib++のオリジナルなコードは全て検査してあるが、ユーザが作るクラスは用心が必要だ。
ファイル名の銘々規則
ファイル名は DOS への転送を考慮し、「8文字+.+3文字」の旧 DOS ファイル名規則を厳守する。
ただし、unix 上のファイル名はすべて英小文字である。
先頭部分
ファイル名の先頭2文字で種別を表す。
- OX - 基本クラスおよび独立クラス
- OC - GUI部品クラス
- OR - OXresDefCクラスで定義するリソーステーブル。OCファイルとペアで存在。
拡張子
一般的なCコンパイラ (g++)の銘々規則に従う。
- CXX - コンパイルするソースコード。
- H - コンパイルするC++の定義ヘッダー。
- MAK - makeの指示ファイル。
メンバ名の銘々規則
メンバ変数
X | K | 自由につける(32文字まで) |
変数の種別
- x = P public
- K = M private もしくは protected
変数の型を表す識別文字(1~3小文字)
c | char 1バイトの符号付き整数で文字を表す。 |
b | BYTE unsinged char のことで、1バイトの符号無し整数。 |
s | short 2バイトの符号付き整数 |
w | WORD unsigned short のことで、2バイトの符号無し整数。 |
i | int 2バイトもしくは4バイトの符号付き整数 |
u i | UINT unsigned int のことで、2バイトもしくは4バイトの符号付き整数 |
f | BOOL intと同じだが、論理変数を表わす。(TRUE,FALSE) |
l | long 4バイトの符号付き整数 |
dw | DWORD unsigned long のことで、4バイトの符号無し整数。 |
d | double 倍精度浮動小数点データ(バイト数はコンパイラに依存) |
t | float 浮動小数点データ(バイト数はコンパイラに依存) |
ポインタの場合はさらに先頭にpをつける。特別な型は型名の頭2~3文字をとって区別する。
メンバとリソース名
リソース名
旧OXlibの互換性のため常にrOXで始める。例えばrOXresNameとなる。
private変数
そのクラスにしか必要のない変数。名前は自由である。
xMname x=変数の型 name=リソース名
protected変数
リソースとして使用しているデータ。
名前はメンバ変数 銘々規則にのっとり、以下のように付ける。
xMname
- x=変数の型
- name=リソース名
例えばrOXresNameの整数型のメンバ変数 は以下のようになる。
iMresName
private関数
派生クラスでも利用しない関数。
小文字で始める。
詳細なるインターフェースの記述は不要であるが関数の説明は記述すること。
protected関数
派生クラスで使う可能性のある関数。
名前は大文字で始まる任意の名前。
public関数
先頭2~3文字で用途を定めている。 ただし、旧 OXlib と互換性のための関数はこの限りではなく以前と同じの名前を使用する。
リソース名により決まる。
以下の例はリソース名 rOXresNameのときの名前である。
GRresName | リソースの値を取得。 |
SRresName | リソースに値を設定。 |
GTresName | 旧リソース名に対応してテーブルに記述されるリソース読みだし関数。 |
STresNamex | 旧リソース名に対応してテーブルに記述されるリソース読みだし関数。 |
その他の汎用的な関数の名前
EvEventName | イベント処理。 |
Getxx | 一般取得。 |
Setxx | 一般設定。 |
Isxxxx | 調査のための関数で返り値はBOOL型。 |
CreateX11 | オブジェクトの生成。 |
GUI部品クラスの構造
OXlib++ではユーザのGUI部品クラスの拡張を許している。
独自のGUI部品を作成するには、必ず既に定義されているクラスの基底クラスとして定義した方が無難である。
OXlib++のフレーム・ワークはそれほどユーザにクラス構造を強制するものではないから、理屈の上では独自のクラスを作っても動作させることは可能だ。
その場合においても既存のクラスの動作をよく理解することが必要である。
クラス・ヘッダー・ファイルの構成
それほど厳密な規定ではないが、OXlib++のGUI部品コードのヘッダー・ファイル(oc~.h)は以下の構成で記述することが好ましい。
-
タイトル・ヘッダー
適当なタイトルヘッダーを記述する。
OXlib++の標準は以下の書式である。//======================================ヘッダー定義開始 // ZWIN04:oc部品ファイル.h // クラス分類:部品クラス名:クラスの簡単な説明 // CopyRight表示 // 改定履歴 //======================================ヘッダー定義終了
-
二重インクルード防止定義
二重に定義されてコンパイル・エラーを出さないように以下の定義でヘッダー全体をくるむ。
注意
ファイル最後に#endifを忘れないこと。- #ifndef __ファイル名_H
- #define __ファイル名_H
-
クラス概要などの説明
- #ifdef LL
- #endif
で説明を囲む。
-
下位クラスのコンストラクタ定義のためのマクロ定義
定義はすべて大文字でおこなう。
-
ヘッダー・ファイルのコンストラクタの引数定義に使用。(デフォルト値定義)
#define 当該部品名_ARGINIT 基底クラス部品名_ARGINIT,当該部品名引数型引数名前=デフォルト値....
-
コード・ファイルのコンストラクタの引数定義に使用。(引数宣言のみ)
#define 当該部品名_ARGLIST 基底クラス部品名_ARGLIST,当該部品名引数型引数名前....
-
上位コンストラクタ呼出引数の定義
#define 当該部品名_CALLARG 基底クラス部品名_CALLARG,当該部品名引数名前....
-
-
クラス定義
GUI部品クラスは必ず OXbaseC、もしくは OXbaseC を基底クラスとするクラスの派生クラスでなければならない。
class クラス名 : public 基底クラス・クラス定義
-
リソース定義Tableの定義
旧リソース名でアクセスできるように、OXlib++ではリソース名とメンバ関数が1対になったテーブルを定義する。
実際のテーブル定義ファイルは or~.cxx である。private: static const OXresDefC resStbl[];
その他のprivateメンバ変数 の定義を続ける。
-
リソースに使用するメンバ変数の定義
GR~やSR~のリソース取得・設定メンバ関数より参照される変数の定義。
protected: public:
-
部品特性Tableの定義
static const OXpartsC partsStbl;
-
その他のpublib変数の定義
もちろん無い方が好ましい。
private:
-
クラス内部関数の定義
下位クラスの使用を許可する関数を定義
protected:
-
初期化および消滅やoperatorなどのメンバ関数
コンストラクタ はマクロを使用して記述する。
-
部品に固有な定義データを返すすべての部品の共通仮想関数
部品の特性を表すstaticデータテーブルを返す。
virtual const OXpartsC& GRpartsDef(void) const//各種部品固有のデータ { return (OXtextC::partsStbl);部品定義テーブルの参照を返す。 }
注意
下位部品クラスは必ずこの関数をオーバーライドしなければならない。
詳細はOXbaseC基底クラスの仕様を参照されたし(oxbase.h) -
OXlibリソース取得・設定
OXlib++の新規リソース、および、リソースをメンバ関数で扱うときに使用する。
もちろん引数は自由に決めてよい。 -
BOXのイベント処理
基底クラスの仮想関数を再定義して、部品の動作を記述する。
-
旧OXlibリソース取得・設定
OXresDefCテーブルに記述されるべきメンバ関数。
取得はGT、設定はSTで始まり、引数は以下のように決まっている。リソース名でのリソース取得
OXERR GTリソース名( //Success=処理成功もしくは1..n=OXlibエラーコード OXstringC& stOut//OUT:読みだしたリソース文字列 );
リソース名でのリソース設定
OXERR STtopAlign(//Success=処理成功もしくは1..n=OXlibエラーコード OXstringC& stIn//IN:設定するリソース文字列 );
通常、リソース・メンバ変数 を文字列に変更するだけなので、なるべくヘッダー内にインライン関数として記述する。
このリソース・テーブル関数は仮想関数である必要はない。
なぜなら、OXlib++の標準処理は必ず指定クラスからリソース・テーブルを検索するので、同じ名前のリソース名があれば、下位クラスの方が優先されるからである。 -
クラス定義の終了
}; //Class end
-
ヘッダー定義の終了
先の二重インクルード防止用の #ifndef に対応する。忘れてはいけない。
#endif //Include header end
新規部品の登録
Xlib++ で使用するGUI部品クラスは必ずファイル allparts.cxx に定義しなければならない。
allparts.cxx は すべての部品定義クラス(OXpartsC)のオブジェクト・ポインタの配列を定義している。
この配列変数名は partsAllTbl[] でありシステム唯一だ。
OXlib++ は partsAllTbl[] を検索することにより、部品名から部品定義テーブル を得ることができる。
部品の検索
全部品テーブル partsAllTbl[] から任意の部品名を検索して、部品定義テーブル を得るには ALsearchParts("部品名"); が用意されている。
apdumy.cxx
常に部品テーブル allparts.cxx をリンクすると、使用しない部品までアプリケーションにリンクされてしまうことになる。
これを防止するために、文字列名で部品を動的生成する必要の無いアプリケーションでは、apdumy をリンクするとよい。
このとき ALsearchParts() は常にエラーとなる。メモリは節約されるが、文字列名での部品生成は、もちろんできなくなる。-
部品の動的生成
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名");
リソース定義
rOX で始まる文字列リソース名で扱うべきリソースを定義する。
文字列リソースは旧 OXlib と同様にGetResource() と SetResrouce()関数より使用する。
文字列リソースの取り決めの必要の無いリソースはテーブル定義は不要である。
この場合、メンバ関数を直接使用してリソースにアクセスする。
もちろんリソースの動的生成やリソース・エディタからの設定はできない。
リソース・テーブルの定義
リソース・テーブルはファイル oc~.cxx にて記述する OXresDefCクラスのオブジェクト配列である。 OXresDefCクラスはファイル oxresdef.h に定義されている。
const OXresDefC OXtextC::resStbl[] = {テーブルの定義 {最初のリソースの定義 リソース名(rOXで始まる旧OXlib銘々法と同じ。ただし常に文字列で扱うので定数定義は不要) リソースの説明(リソース・エディタで表示される説明文章) リソース取得関数(キャスト・マクロ(RESFUNC)を用いて定義する GT~のメンバ関数へのポインタ) リソース設定関数(キャスト・マクロ(RESFUNC)を用いて定義する ST~のメンバ関数へのポインタ) リソースの種別(以下の定義のどれか) eVOID :型は不明 eINT :int(4バイト整数) eSTRING :OXstringC(文字列) eBOOL :論理型(True/False) eENUMTBL :enum (文字列テーブルより選択)テーブルは(7)で記述 eENUMFILE :enum (ファイルより選択)ファイル名は(7)で記述 eDOUBLE :double(浮動小数) eFUNC :Function(実行のみのリソースで値は持たない) リソースエディタの入力の種別(リソースエディタが使用するリソース入力の部品を記述) eNONE :ユーザ入力は許されない :eFUNCなど eEDITBOX :EditBoxによる文字列入力 :eINT, eSTRING, eDOUBLE eCHECKBOX :CheckBoxによるON/OFFの入力 :eBOOL eRADIOBUT :RadioButtonによる選択入力 :eENUMTBL eLISTBOX :ListBoxによる選択入力 :eNUMFILE eDIALOG :特別なダイアログボックスによる入力 :リソース別にダイアログを用意する。ダイアログ名は(7)で記述する。 リソースエディタへの情報(補助情報を(5)と(6)の種別により文字列で記述) 使用しないときは Null とする。 (5)=eENUMTBL :選択文字列は","(カンマ)で区切って定義 (5)=eENUMFILE :リストボックスに表示すべきファイル名 :定義ファイルは #define の形式C言語のヘッダ形式 (6)=eDIALOG :特別ダイアログボックスの名前、","(カンマ)の後ろにパラメータ :リソースエディタにより定義されている。ダイアログにてパラメータも定義 現在サポートされている特別ダイアログ CURSOR :Cursor Font 選択 FONT1B :1バイトフォント選択 FONT2B :2バイトフォント選択 COLOR :色名選択 }, { 次のリソースの定義 }, RESTBLEND //テーブル終了記号 };
文字列リソースの取得と設定
常に仮想関数 OXbaseC::SetResource() と OXbaseC::GetResource() を使用してリソースの取得と設定をおこなうことを前提としている。
リソースの取得
GetResource(リソース名、取得したリソースの値文字列)で、常にリソースの値は文字列(OXstringCの参照)で返される。リソースの設定
SetResource(リソース名、設定するリソースの値文字列、再描画フラッグ)もしくは
SetResource(リソースファイルのリソース設定文字列、再描画フラッグ)
で、常に設定値は文字列で指示する。テーブル検索の手順
- まず、最初に自クラスのリソース定義 テーブルを検索する。
- このとき部品定義テーブル よりリソース定義 テーブルのポインタを取得する。
- 部品定義テーブル のポインタを返す static 関数は必ず定義されている。
- 自クラスのリソース定義 テーブルにリソース名の記述が無ければ、1つ上のクラスのリソース定義 テーブルを検索する。
- このとき上位クラスの部品定義テーブル は自クラスの部品定義テーブル より得る。
- 以上の動作をくり返し、最上位基底クラスOXbaseCまでのリソース定義 テーブルを検索する。
- リソース名を見つければ、リソース定義 テーブルに記述してあるメンバ関数を呼び出す。
グループ部品制御
グループ部品は自オブジェクトの下につながるBOXを制御する部品である。
例えば OXradioButtonFrameや OXscrollBar などがある。
グループ部品の制御はもちろんクラス内部の動作なのでアプリケーションには無関係であるし、そうでなければならない。
下位BOXのコールバック利用
グループ部品を作成するときに、グループ部品クラスで、 GroupCallBack()をオーバーライドすると、下位BOX のコールバックがすべてモニタできることになる。
もちろん、下位BOXのユーザ登録のコールバック関数は呼び出され、その後に GroupCallBack()が呼び出される。
下位BOXコールバックモニタ関数の呼び出し形式を以下に示す。virtual void GroupCallback(OXcallbackC* pboxCb, //IN:コールバックが起こったBOX const int iKind, //IN:部品ごとに定義されたコールバックの種類 const XEvent* pev //IN:コールバック時に発生したイベント構造体 );
下位BOXイベント利用
自BOXの下につながるBOXのイベントそのものを利用してグループ部品を作成する場合に使用する。
下位BOXのすべてのイベントをモニタすることにより、より汎用的なグループ部品の作成が可能になる。
グループ部品BOXの場合に下位BOXでイベントが発生したときに以下の仮想メンバ関数が呼び出される。
グループ部品はこの関数をオーバライドすることにより、下位BOXのすべてのイベントがモニタできる。virtual Bool DispatchLowerEvent(const XEvent&ev, OXbaseC* pBox /*IN:実際にイベントが発生したBOXオブジェクトのポインタ*/);
ただし以下のイベントではDispatchLowerEvent()は呼び出されない。
Expose GraphicsExpose NoExpose PressCont DoubleClick CaretTimer