本家のオンラインマニュアル

プログラムのスタイル

 まず最初に,wxWidgetsのクラスを使用してGUIアプリを構築するプログラムのスタイルを, サンプルプログラムを挙げながら説明します.


■ 基本要素とその使い方  〜最も単純なアプリを例に〜

 「File」メニューから「Quit」を選択すると終了するだけのアプリを例に挙げて, GUIアプリ構築の流れを説明します.

 wxWidgetsでGUIアプリを実現するための最も基本的な方法が, wxAppクラスとwxFrameクラスの利用です. これは,アプリ本体をwxAppクラスのインスタンスとして, またアプリの主たるウィンドウフレームをwxFrameクラスのインスタンスとして実現するという方法です.

● wxAppクラス

class MyApp: public wxApp {
  public:
    MyFrame *frame;         // Window Frame
    virtual bool OnInit();  // Initialization (prototype)
};

 これはwxAppの派生クラスMyAppを定義している例です. このようにwxWidgetsが提供するクラスの派生クラスを定義して, 色々と機能を追加・拡張するというのが一般的な方法です.

 重要な基本事項ですが「wxAppクラスのインスタンスがアプリそのもの」ということになります.

 この例ではMyAppクラスは2つのメンバだけを持ちます. 1つは「アプリの主たるウィンドウ」であるframe(MyFrameクラス), もう1つはアプリの起動時に各種の初期化(例えばウィンドウの生成など)を行う関数OnInit()です. ただしこの段階ではOnInit()はプロトタイプ宣言だけで,まだ中身の記述はありません. 関数の存在だけが宣言されており,実際の動作の記述は別の部分で行います.(下記)

bool MyApp::OnInit() {
    // Window Construction
    frame = new MyFrame(10000,wxT("win00"));

    frame->Show(true);  // Display Window

    return(true);
}

 今回の初期化処理では,ウィンドウの生成(MyFrameクラスのオブジェクトの生成)と, ディスプレイへの表示のみです.

● プログラム本体はどこ?

 C言語でプログラムを作成する場合,関数mainに記述されたものが本体(最上位の関数)となります. wxWidgetsを利用したプログラムでもmain関数の記述はできますが, wxWidgetsの利用においては独自のマクロを記述するスタイルが一般的です.次の例を見てください.

DECLARE_APP(MyApp)
IMPLEMENT_APP(MyApp)

 このマクロはアプリケーションのクラス定義の後に記述するもので, IMPLEMENT_APP(MyApp)マクロの中にmain関数が埋め込まれています.

 さて,ここまででアプリ本体の定義ができたことになります. 次はアプリのウィンドウであるframeオブジェクト(MyFrameクラス)について説明します.

● wxFrame

 wxFrameクラスのオブジェクトは,wxWidgetsでウィンドウを実現するための基本的なクラスの1つです.

class MyFrame: public wxFrame {
  public:
    // Constructor
    MyFrame(int id, const wxString & title);

    // Event Handler for 'Quit' (prototype)
    virtual void On_mQuit(wxCommandEvent &event);
  private:
    wxMenuBar* menubar;  // Menu Bar for Window Frame
    // Entities for Event Handling (macro)
    DECLARE_EVENT_TABLE()
};

 この例ではwxFrameの派生クラスとしてMyFrameを定義して,ウィンドウの構造の詳細を定義したり, ユーザからの操作(イベント)に反応する仕組み(イベントハンドリング)を記述します.

 この例のMyFrameクラスでは,publicのメンバにコンストラクタと, 'Quit'メニューが選択された際のイベントハンドラの関数On_mQuit()が定義されています. privateのメンバとしては,ウィンドウに取り付けるメニューバーmenubar(wxMenubarクラス)がありますが, その他の必要なメンバをまとめて登録するマクロ DECLARE_EVENT_TABLE() の記述もあります.

 さて,ウィンドウのクラスが定義できたので, 次は実際にウィンドウオブジェクトを生成するコンストラクタについて説明します.

MyFrame::MyFrame(int id, const wxString & title)
  :wxFrame(NULL,id,title) {
    menubar = new wxMenuBar();
    wxMenu* mFile = new wxMenu();
    mFile->Append(10101, wxT("Quit"));
    menubar->Append(mFile, wxT("File"));
    SetMenuBar(menubar);

    SetTitle(title);
}

 このコンストラクタは,ウィンドウのタイトルバーに表示するタイトル文字列と, ウィンドウの識別番号であるwxIDを受け取ってウィンドウを生成します.

wxIDについて

 wxWidgetsでは,GUIのパーツ(wxWidgetsの世界ではコントロールと呼びます)には wxIDと呼ばれる番号(整数)を割り当てて識別します. また,ウィンドウに各種のコントロールを配置する際は,「親子」の階層関係を作ります. つまり,あるウィンドウにボタンなどを取り付ける場合は,そのウィンドウを, 取り付けるボタンなどのコントロールをとする上下関係(階層関係)をつくります. もちろん,ウィンドウの中に別のウィンドウオブジェクトを取り付けることも可能で, この親子関係はwxWidgetsの世界の基本構造の1つです.

 さて,上のMyFrameクラスですが,アプリの最上位のウィンドウを生成するためのクラスということで, 親が無いことを意味するNULLを指定して(2行目),自分のIDと, タイトル文字列を受け取ってインスタンスを生成します.

 'menubar = new wxMenuBar();' では, メニューを取り付けるメニューバーを生成しています. 個々のメニューは 'wxMenu* mFile = new wxMenu();' のようにして生成します. 更に,メニュー内の'Quit'などの項目は  'mFile->Append(10101, wxT("Quit"));' のようにして登録します. そして各種のメニュー項目を登録したメニューは 'menubar->Append(mFile, wxT("File"));'  のようにして,メニューのラベル'File'などをつけてをメニューバーに取り付けます.

 出来上がったメニューバーは 'SetMenuBar(menubar);' として,そのウィンドウに取り付けます.

 ウィンドウにタイトル文字列を設定するには 'SetTitle(title);' のようにします.

wxStringクラスについて

 通常の場合C言語では,文字列を格納した記憶領域をchar型のポインタとして示しますが, wxWidgetsには,文字列情報を扱うためにwxStringというクラスが用意されています. このクラスを利用すると,多バイト文字列を自然な形で扱うことができ, JavaのStringクラスに似た利便性が実現されます.

● イベントハンドリング

 今回の例のアプリは,'Quit'メニューが選択されたときに, On_mQuit()関数を呼び出して終了します.この流れを実現する方法(イベントハンドリング) について説明します.

 上の例では,メニュー項目'Quit'には'10101'という識別番号(wxID)が与えられています. これに対して関数On_mQuit()を結びつけるには,次のようなマクロの記述を行います.

BEGIN_EVENT_TABLE(MyFrame, wxFrame)
    EVT_MENU(10101, MyFrame::On_mQuit)
END_EVENT_TABLE()

 'BEGIN_EVENT_TABLE(MyFrame, wxFrame)' は,
  「wxFrameクラスの派生クラスMyFrameにイベントハンドラを登録する」
ということを意味します.また 'EVT_MENU(10101, MyFrame::On_mQuit)' は,
  「メニュー項目10101にMyFrameクラスの関数On_mQuitをイベントハンドラとして登録する」
ということを意味します.'END_EVENT_TABLE()' はイベントハンドラの登録作業の終了を意味します.

 さて,肝心の関数 'On_mQuit' の中身は次の通りです.

void MyFrame::On_mQuit(wxCommandEvent &event) {
    Close();  // Termination
}

 'Close()' はアプリを終了する関数で,これを実行することでアプリが実際に終了します.

 これでひと通りの説明が終わりました.プログラム全体を 'win00.cpp' として次に示します.

プログラム全体:win00.cpp
#include	 <wx/wx.h>

//-------------------------------------------------------
// Main Window Frame for Application
//-------------------------------------------------------

// Class of Window Frame
class MyFrame: public wxFrame {
  public:
    // Constructor
    MyFrame(int id, const wxString & title);

    // Event Handler for 'Quit' (prototype)
    virtual void On_mQuit(wxCommandEvent &event);
  private:
    wxMenuBar* menubar;  // Menu Bar for Window Frame
    // Entities for Event Handling (macro)
    DECLARE_EVENT_TABLE()
};

MyFrame::MyFrame(int id, const wxString & title)
  :wxFrame(NULL,id,title) {
    menubar = new wxMenuBar();
    wxMenu* mFile = new wxMenu();
    mFile->Append(10101, wxT("Quit"));
    menubar->Append(mFile, wxT("File"));
    SetMenuBar(menubar);

    SetTitle(title);
}


// Event Registoration
BEGIN_EVENT_TABLE(MyFrame, wxFrame)
    EVT_MENU(10101, MyFrame::On_mQuit)
END_EVENT_TABLE()

// Event Handler for 'Quit'
void MyFrame::On_mQuit(wxCommandEvent &event) {
    Close();  // Termination
}


//-------------------------------------------------------
// Application
//-------------------------------------------------------

// Application Class
class MyApp: public wxApp {
  public:
    MyFrame *frame;         // Window Frame
    virtual bool OnInit();  // Initialization (prototype)
};

// Initialization
bool MyApp::OnInit() {
    // Window Construction
    frame = new MyFrame(10000,wxT("win00"));

    frame->Show(true);  // Display Window

    return(true);
}

// Implementation of Application (macro)
DECLARE_APP(MyApp)
IMPLEMENT_APP(MyApp)

 このプログラムをコンパイルすると実行可能なバイナリが生成されます. それらを実行した例を下に示します.

     
Windowsの場合
Macintoshの場合

 このように,1つのソースプログラムから異なるOS用のアプリを作ることができます.

■ まとめ

 重要な項目だけ列挙しておきます.

  ・wxAppクラス
    'IMPLEMENT_APP(アプリのクラス)' でアプリの実装
    'OnInit()' でアプリの初期化(ウィンドウの生成など)

  ・wxFrameクラス

  ・イベントを扱うクラスで 'DECLARE_EVENT_TABLE()' マクロ

  ・イベントハンドリングの登録
    BEGIN_EVENT_TABLE(対象クラス, 元クラス)
      EVT_MENU(対象の識別番号, イベントハンドラの関数)
    END_EVENT_TABLE()

[ページトップへ]


2014/08/22