FOX GUI キット 〜ラジオボタン with ハンドラ〜

 今回の FOX のツールキットは今まで放ったらかしにしていたメッセージハンドラを追加してみます。 MFC を使用した場合はラジオボタンをグループ化した場合に複数のラジオボタンの中から一つだけ選択する様な処理はプロパティで簡単に実装出来ますが、FOX の場合はそれも自分で実装する必要があります。けど実装自体はもの凄く簡単でラジオボタンを配置するウィンドウのクラスを一つ作成して単にクリックに対応したハンドラを追加するだけです。
 まずラジオボタンを配置するウィンドウクラスを実装します。今回はメインウィンドウにラジオボタンを配置するのでメインウィンドウから派生したウィンドウクラスを定義します。
/**************************************************************************************/
/**
 *  @file     radio_button.h
 *
 *  @brief    ラジオボタン配置テストクラス (定義ファイル)
 *
 *  @author    jintan
 *  @date      2004.07.04
 *
 *  @version   $Revision: $
 *
 *  @li        Copyright © 2004 jintan All rights reserved.
 *  @li        URL: http://www.web-sky.org
 *  @li        Email: jintan@web-sky.org
 */
/**************************************************************************************/

#ifndef RadioButton_h
#define RadioButton_h

#include <fx.h>
            
/// @brief ボタン ID
/// ボタンの ID は派生元の FXMainWindow::ID_LAST から定義されないといけない
/// そうしないと ID が衝突してしまいうまくハンドラが機能しない
/// またこのクラスから派生するするウィンドウの事も考えて同じように ID_LAST を末尾に定義しておく
class RadioButton : public FXMainWindow {
  // ウィンドウ実装定義
  FXDECLARE (RadioButton);
public:
  /// @brief ボタン ID
  /// ボタンの ID は派生元の FXMainWindow::ID_LAST から定義されないといけない
  /// そうしないと ID が衝突してしまいうまくハンドラが機能しない
  /// またこのクラスから派生するするウィンドウの事も考えて同じように ID_LAST を末尾に定義しておく
  enum { ID_BUTTON_1 = FXMainWindow::ID_LAST, ID_BUTTON_2, ID_BUTTON_3, ID_LAST };
private:
  /// @brief 選択ボタン ID
  int select_button;
private:
  /// @brief デフォルトのコンストラクタ
  RadioButton ();
public:
  /// @brief コンストラクタ
  RadioButton (FXApp *, const FXString &, FXIcon *, FXIcon *, FXuint, FXint, FXint, FXint, FXint);
public:
  /// @brief メッセージハンドラ
  long onCommandButton (FXObject *, FXSelector, void *);
  /// @brief メッセージハンドラ
  long onUpdateButton (FXObject *, FXSelector, void *);
};
            
#endif // RadioButton_h          
/**************************************************************************************/
/**
 *  @file      radio_button.cpp
 *
 *  @brief     ラジオボタン配置テストクラス (実装ファイル)
 *
 *  @author    jintan
 *  @date      2004.07.04
 *
 *  @version   $Revision: $
 *
 *  @li        Copyright © 2004 jintan All rights reserved.
 *  @li        URL: http://www.web-sky.org
 *  @li        Email: jintan@web-sky.org
 */
/**************************************************************************************/

#include "radio_button.h"

// RadioButton 用のメッセージマップ
// - FXDEFMAP : 括弧内のウィンドウクラスのメッセージマップを定義します。
// - FXMAPFUNCS : 複数のコンポーネントのハンドラを定義します。
//                FXMAPFUNCS (コマンド ID, 開始コンポーネント ID, 終了コンポーネント ID, ハンドラ関数)
// - SEL_COMMAND : コンポーネントが選択された時に発行されるメッセージ
// - SEL_UPDATE : コンポーネントに定期的に発行されるメッセージ
FXDEFMAP (RadioButton)  RadioButtonMap [] = {
  FXMAPFUNCS (SEL_COMMAND, RadioButton::ID_BUTTON_1, RadioButton::ID_BUTTON_3, RadioButton::onCommandButton),
  FXMAPFUNCS (SEL_UPDATE, RadioButton::ID_BUTTON_1, RadioButton::ID_BUTTON_3, RadioButton::onUpdateButton),
};

// RadioButton の実装定義
// - FXIMPLEMENT : 実装定義マクロ
//                 (ウィンドウクラス名, 継承元ウィンドウクラス名, メッセージマップ定義配列, メッセージマップ定義数)
FXIMPLEMENT (RadioButton, FXMainWindow, RadioButtonMap, ARRAYNUMBER (RadioButtonMap))

/**
 *  RadioButton のデフォルトのコンストラクタ。
 *
 *  この関数が直接呼び出される事は無いがこの実装が無いと FXDEFMAP () マクロでエラーが発生する。
 *  なのでとりあえず空の実装を用意しておく。
 *  しかし実装するので外部から呼び出されるとマズいので属性は private にしておく。
 *
 */
RadioButton::RadioButton ()
{
} // RadioButton::RadioButton

/**
 *  @param [in] application  アプリケーション
 *  @param [in] name  アプリケーション名
 *  @param [in] icon  アプリケーションアイコン
 *  @param [in] mini  小さいアイコン
 *  @param [in] option  ウィンドウ属性
 *  @param [in] x  ウィンドウの左上 x 座標
 *  @param [in] y  ウィンドウの左上 y 座標
 *  @param [in] width  ウィンドウの横幅
 *  @param [in] height  ウィンドウの縦幅
 *
 *  メインウィンドウに配置されるコンポーネントを作成します。
 *  ただしこの時点ではメインウィンドウに配置されるだけで実際の表示は
 *  RadioButton::create () の時に行われます。
 * 
 */
RadioButton::RadioButton (FXApp * application, const FXString & name, FXIcon * icon,
                          FXIcon * mini, FXuint option, FXint x, FXint y, FXint width, FXint height)
: FXMainWindow (application, name, icon, mini, option, x, y, width, height),
  select_button (0)
{
  // レイアウトオプション
  const FXuint  rayout_option = GROUPBOX_TITLE_CENTER | FRAME_RIDGE | LAYOUT_CENTER_X | LAYOUT_CENTER_Y;

  // グループボックスの作成
  FXGroupBox *  group = new FXGroupBox (this, "ラジオボタンを纏めるグループボックス", rayout_option);

  // ラジオボタンの作成
  // ここで作成されるボタン達はメインウィンドウではなくメインウィンドウに配置される
  // グループボックスを親にしています。
  new FXRadioButton (group, "ラジオボタン@", this, ID_BUTTON_1);
  new FXRadioButton (group, "ラジオボタンA", this, ID_BUTTON_2);
  new FXRadioButton (group, "ラジオボタンB", this, ID_BUTTON_3);
} // RadioButton::RadioButton

/**
 *  @param [in] sender  メッセージの送信元
 *  @param [in] selector  受信メッセージ種類
 *  @param [in] param  メッセージ付加パラメータ
 *
 *  @return 常に 1
 *
 *  "ID_BUTTON_1" 〜 "ID_BUTTON_3" までが押された時の処理を行います。
 *
 *  押されたラジオボタンを選択中にします。
 *  実際にウィンドウに反映されるのは各コンポーネントの RadioButton::onUpdateButton () が
 *  呼び出された時に行います。
 *
 *  押されたボタンの ID は @p selector に格納されています。
 *  ID 部分のみを抜き出すには FXSELID () マクロを使用します。
 *
 */
long  RadioButton::onCommandButton (FXObject * sender, FXSelector selector, void * param)
{
  // ボタン ID を保存します
  select_button = FXSELID (selector);

  return 1;
} // RadioButton::onCommandButton

/**
 *  @param [in] sender  メッセージの送信元
 *  @param [in] selector  受信メッセージ種類
 *  @param [in] param  メッセージ付加パラメータ
 *
 *  @return 常に 1
 *
 *  定期的に呼び出され各コンポーネントを更新します。
 *
 *  現在選択されているラジオボタンにチェックを入れます。
 *  選択されていない場合はチェックを外します。
 *
 *  FXSELID (selector) == select_button なら ID_CHECK メッセージをボタンに送信します。
 *  FXSELID (selector) != select_button なら ID_UNCHECK メッセージをボタンに送信します。
 *
 */
long  RadioButton::onUpdateButton (FXObject * sender, FXSelector selector, void * param)
{
  // 選択されているボタンならば ID_CHECK を送信します
  // 選択されていないボタンならば ID_UNCHECK を送信します
  FXSelector  message = FXSEL (SEL_COMMAND, (select_button == FXSELID (selector) ? ID_CHECK : ID_UNCHECK));

  // メッセージ送信
  sender->handle (this, message, NULL);

  return 1;
} // RadioButton::onCommandButton
今回はソースをそのまま書いてみました。
前回までのソースのメインウィンドウの作成の代わりにこのクラスに書き換えるだけです。
FXMainWindow * main_window = new RadioButton (&application, "radio button", NULL, NULL, DECOR_ALL, -1, -1, 640, 480);