ヌメロン製作講座第5回:グリッドクラスの作成
今回は本アプリケーションの肝であるグリッドクラスについて解説します。
ちなみに、そろそろソースコードが大きくなってきたのでここには解説に必要な変更点のみ掲載します。ビルドチェック済みの完全なソースファイルは、それぞれのファイル名にリンク(テキスト形式)しましたので使ってください。
グリッドクラスを実装すると、以下のようにやっとアプリらしい画面が表示されます。
ソースコードを見たいときは以下のリンクをクリックしてください。
グリッドクラス(calss Grid)
グリッドクラスはアプリケーションの表示と入力を管理します。
イメージとしてはエクセルのような表計算ソフトを思い出して下さい。
class Grid { public : HWND hwnd; SHORT maxCell; RECT rect; POINT offset; virtual Cell * GetCells() = 0; virtual VOID Init( HWND hWnd ); virtual VOID MakeGrid(); virtual BOOL CanSelectCell( Cell & cell ); virtual VOID Draw( HDC hdc ); }; class SetGrid : public Grid { public : static const int W1 = 70; static const int W2 = 270; static const int W3 = 20; static const int W4 = 26; static const int W5 = 59; static const int W6 = 59; static const int W7 = 58; static const int W8 = 46; static const int L1 = ( W1 ); static const int L2 = ( L1 + W2 + 6 ); static const int L3 = ( L2 + 195 ); static Cell cells[]; Cell * GetCells() { return cells; } };
class Grid は抽象クラスで、class SetGrid が今回使用している設定画面用のグリッドクラスです。今後、情報グリッドクラスと棋譜データグリッドクラス、分析データグリッドクラスが追加されます。
グリッドにはセルデータが必要なので基底クラスだけでは何もできません。従って派生クラスでは、純粋仮想関数の GetCells() を実装してセルデータアドレスを返す必要があります。
セルデータは静的データとして定義可能なように、明示的に仮想関数を含まないことを示す struct で定義してあります。*1
struct Cell { CellID cid; LPVOID param; LONG width; LONG height; LONG left; LONG top; VOID Draw( HDC hdc, POINT offset ); BOOL DrawFrame( HDC hdc, RECT rc ); BOOL DrawContent( HDC hdc, RECT rc ); VOID GetRect( RECT & rc, POINT offset ); BOOL GetText( PTCHAR text ); ParamID GetParamID() { return * ( ParamID * ) & param; } };
メンバ関数はデータ領域を必要としない*2のでこの場合サイズは 24 Bytes ですか。
設定画面グリッド(class SetGrid)の場合は、以下のようなセルデータ定義になります。
Cell SetGrid :: cells[] = { { CELL_LABEL, _T( "プレイ" ), W1 }, { CELL_BUTTON, ( LPVOID ) PARAM_START_BUTTON }, { CELL_BUTTON, ( LPVOID ) PARAM_END_BUTTON }, { CELL_BUTTON, ( LPVOID ) PARAM_NEW_BUTTON }, { CELL_NEWLINE }, { CELL_LABEL, _T( "棋譜データ" ), W1 }, { CELL_BUTTON, ( LPVOID ) PARAM_LOAD_BUTTON }, { CELL_BUTTON, ( LPVOID ) PARAM_SAVE_BUTTON }, { CELL_BUTTON, ( LPVOID ) PARAM_CLEAR_BUTTON }, { CELL_SEPARATOR }, { CELL_LABEL, _T( "タイトル" ), W1 }, { CELL_EDIT, ( LPVOID ) PARAM_TITLE, W2 }, { CELL_NEWLINE }, { CELL_LABEL, _T( "設定桁数" ), W1 }, { CELL_UPDOWN, ( LPVOID ) PARAM_COLUMN, W3 }, { CELL_NEWLINE }, { CELL_LABEL, _T( "ルール" ), W1 }, { CELL_COMBO, ( LPVOID ) PARAM_RULE, W2 }, { CELL_SEPARATOR2 }, { CELL_LABEL, _T( "先攻" ), 0, 0, L1 }, { CELL_LABEL, _T( "後攻" ), 0, 0, L2 }, { CELL_NEWLINE2 }, { CELL_LABEL, _T( "プレイヤー名" ), W1 }, { CELL_EDIT, ( LPVOID ) PARAM_NAME_FIRST, W2 }, { CELL_EDIT, ( LPVOID ) PARAM_NAME_SECOND, W2, 0, L2 }, { CELL_NEWLINE }, { CELL_LABEL, _T( "タイプ" ), W1 }, { CELL_COMBO, ( LPVOID ) PARAM_TYPE_FIRST, W2 }, { CELL_COMBO, ( LPVOID ) PARAM_TYPE_SECOND, W2, 0, L2 }, { CELL_NEWLINE }, { CELL_LABEL, _T( "カード" ), W1 }, { CELL_RIGHT, _T( "0 x" ), 0 }, { CELL_UPDOWN, ( LPVOID ) PARAM_CARD0_FIRST, W3 }, { CELL_RIGHT, _T( "1 x" ), W4 }, { CELL_UPDOWN, ( LPVOID ) PARAM_CARD1_FIRST, W3 }, { CELL_RIGHT, _T( "2 x" ), W4 }, { CELL_UPDOWN, ( LPVOID ) PARAM_CARD2_FIRST, W3 }, { CELL_RIGHT, _T( "3 x" ), W4 }, { CELL_UPDOWN, ( LPVOID ) PARAM_CARD3_FIRST, W3 }, { CELL_RIGHT, _T( "4 x" ), W4 }, { CELL_UPDOWN, ( LPVOID ) PARAM_CARD4_FIRST, W3 }, { CELL_RIGHT, _T( "0 x" ), 0, 0, L2 }, { CELL_UPDOWN, ( LPVOID ) PARAM_CARD0_SECOND, W3 }, { CELL_RIGHT, _T( "1 x" ), W4 }, { CELL_UPDOWN, ( LPVOID ) PARAM_CARD1_SECOND, W3 }, { CELL_RIGHT, _T( "2 x" ), W4 }, { CELL_UPDOWN, ( LPVOID ) PARAM_CARD2_SECOND, W3 }, { CELL_RIGHT, _T( "3 x" ), W4 }, { CELL_UPDOWN, ( LPVOID ) PARAM_CARD3_SECOND, W3 }, { CELL_RIGHT, _T( "4 x" ), W4 }, { CELL_UPDOWN, ( LPVOID ) PARAM_CARD4_SECOND, W3 }, { CELL_NEWLINE }, { CELL_RIGHT, _T( "5 x" ), 0, 0, L1 }, { CELL_UPDOWN, ( LPVOID ) PARAM_CARD5_FIRST, W3 }, { CELL_RIGHT, _T( "6 x" ), W4 }, { CELL_UPDOWN, ( LPVOID ) PARAM_CARD6_FIRST, W3 }, { CELL_RIGHT, _T( "7 x" ), W4 }, { CELL_UPDOWN, ( LPVOID ) PARAM_CARD7_FIRST, W3 }, { CELL_RIGHT, _T( "8 x" ), W4 }, { CELL_UPDOWN, ( LPVOID ) PARAM_CARD8_FIRST, W3 }, { CELL_RIGHT, _T( "9 x" ), W4 }, { CELL_UPDOWN, ( LPVOID ) PARAM_CARD9_FIRST, W3 }, { CELL_RIGHT, _T( "5 x" ), 0, 0, L2 }, { CELL_UPDOWN, ( LPVOID ) PARAM_CARD5_SECOND, W3 }, { CELL_RIGHT, _T( "6 x" ), W4 }, { CELL_UPDOWN, ( LPVOID ) PARAM_CARD6_SECOND, W3 }, { CELL_RIGHT, _T( "7 x" ), W4 }, { CELL_UPDOWN, ( LPVOID ) PARAM_CARD7_SECOND, W3 }, { CELL_RIGHT, _T( "8 x" ), W4 }, { CELL_UPDOWN, ( LPVOID ) PARAM_CARD8_SECOND, W3 }, { CELL_RIGHT, _T( "9 x" ), W4 }, { CELL_UPDOWN, ( LPVOID ) PARAM_CARD9_SECOND, W3 }, { CELL_NEWLINE }, { CELL_LABEL, _T( "アイテム" ), W1 }, { CELL_RIGHT, _T( "High&Low x" ), W5 }, { CELL_UPDOWN, ( LPVOID ) PARAM_HIGHLOW_FIRST, W3 }, { CELL_RIGHT, _T( "Double x" ), W6 }, { CELL_UPDOWN, ( LPVOID ) PARAM_DOUBLE_FIRST, W3 }, { CELL_RIGHT, _T( "Target x" ), W7 }, { CELL_UPDOWN, ( LPVOID ) PARAM_TARGET_FIRST, W3 }, { CELL_RIGHT, _T( "High&Low x" ), W5, 0, L2 }, { CELL_UPDOWN, ( LPVOID ) PARAM_HIGHLOW_SECOND, W3 }, { CELL_RIGHT, _T( "Double x" ), W6 }, { CELL_UPDOWN, ( LPVOID ) PARAM_DOUBLE_SECOND, W3 }, { CELL_RIGHT, _T( "Target x" ), W7 }, { CELL_UPDOWN, ( LPVOID ) PARAM_TARGET_SECOND, W3 }, { CELL_NEWLINE }, { CELL_RIGHT, _T( "Slash x" ), W5, 0, L1 }, { CELL_UPDOWN, ( LPVOID ) PARAM_SLASH_FIRST, W3 }, { CELL_RIGHT, _T( "Shuffle x" ), W6 }, { CELL_UPDOWN, ( LPVOID ) PARAM_SHUFFLE_FIRST, W3 }, { CELL_RIGHT, _T( "Change x" ), W7 }, { CELL_UPDOWN, ( LPVOID ) PARAM_CHANGE_FIRST, W3 }, { CELL_RIGHT, _T( "Slash x" ), W5, 0, L2 }, { CELL_UPDOWN, ( LPVOID ) PARAM_SLASH_SECOND, W3 }, { CELL_RIGHT, _T( "Shuffle x" ), W6 }, { CELL_UPDOWN, ( LPVOID ) PARAM_SHUFFLE_SECOND, W3 }, { CELL_RIGHT, _T( "Change x" ), W7 }, { CELL_UPDOWN, ( LPVOID ) PARAM_CHANGE_SECOND, W3 }, { CELL_NEWLINE }, { CELL_LABEL, _T( "設定ナンバー" ), W1 }, { CELL_NUMBER, ( LPVOID ) PARAM_OPEN_FIRST, W8 }, { CELL_NUMBER, ( LPVOID ) PARAM_OPEN_SECOND, W8, 0, L2 }, { CELL_SEPARATOR }, { CELL_NULL } };
必要なセルデータを必要なだけ書いて最後に CELL_NULL で終了マークを定義します。
メンバ変数の CellID cid がセルの種類、LPVOID param が表示データ情報を表します。
表示位置とサイズである width、height、left、top については 0 ならばグリッドが勝手に計算します。
セルの種類と表示パラメータの定義は以下の通りです。
enum CellID { CELL_NULL = 0, CELL_NEWLINE, CELL_NEWLINE2, CELL_SEPARATOR, CELL_SEPARATOR2, CELL_LABEL, CELL_RIGHT, CELL_BUTTON, CELL_EDIT, CELL_NUMBER, CELL_UPDOWN, CELL_COMBO, MAX_CELL }; enum ParamID { PARAM_NULL = 0, PARAM_START_BUTTON, PARAM_END_BUTTON, PARAM_NEW_BUTTON, PARAM_LOAD_BUTTON, PARAM_SAVE_BUTTON, PARAM_CLEAR_BUTTON, PARAM_TITLE, PARAM_COLUMN, PARAM_RULE, PARAM_NAME_FIRST, PARAM_NAME_SECOND, PARAM_TYPE_FIRST, PARAM_TYPE_SECOND, PARAM_CARD0_FIRST, PARAM_CARD1_FIRST, PARAM_CARD2_FIRST, PARAM_CARD3_FIRST, PARAM_CARD4_FIRST, PARAM_CARD5_FIRST, PARAM_CARD6_FIRST, PARAM_CARD7_FIRST, PARAM_CARD8_FIRST, PARAM_CARD9_FIRST, PARAM_CARD0_SECOND, PARAM_CARD1_SECOND, PARAM_CARD2_SECOND, PARAM_CARD3_SECOND, PARAM_CARD4_SECOND, PARAM_CARD5_SECOND, PARAM_CARD6_SECOND, PARAM_CARD7_SECOND, PARAM_CARD8_SECOND, PARAM_CARD9_SECOND, PARAM_HIGHLOW_FIRST, PARAM_DOUBLE_FIRST, PARAM_TARGET_FIRST, PARAM_SLASH_FIRST, PARAM_SHUFFLE_FIRST, PARAM_CHANGE_FIRST, PARAM_HIGHLOW_SECOND, PARAM_DOUBLE_SECOND, PARAM_TARGET_SECOND, PARAM_SLASH_SECOND, PARAM_SHUFFLE_SECOND, PARAM_CHANGE_SECOND, PARAM_OPEN_FIRST, PARAM_OPEN_SECOND, MAX_PARAM };
かなり長くなったので今回はここまでとします。
続きは次回で。