パソコンでプログラミングしよう ウィンドウズC++プログラミング環境の構築
1.6.3.6(15)
Code::BlocksのwxSmithプラグイン

統合開発環境Code::Blocksに付属するRADツールwxSmithプラグインを説明する。

wxSmithはCode::Blocksのプラグイン(拡張機能)の一つでwxWidgetsライブラリ使用アプリケーションのGUI開発を支援するRAD(Rapid Application Development)ツールである。wxSmithはトップレベルウィンドウ(wxFrame、wxDialog)あるいはパネル(wxPanel)の派生であるユーザー定義ウィンドウクラスを記述するインクルードファイル(*.h)/ソースコードファイル(*.cpp)をwxWidgetsリソースファイル(*.wxs)と共に生成し、wxSmithエディタでGUIをWYSIWYG(What You See Is What You Get)編集する。編集は*.h/*.cpp/*.wxsに自動反映される。wxSmithエディタの操作性は一般的なグラフィック編集ソフトに程遠く使いこなしは習熟を必要とする。

wxSmithプラグイン

wxSmithプラグインはCode::Blocksにシームレスに統合されて、[wxSmith|Add wxXXX]を実行してトップレベルウィンドウあるいはパネルを生成する。ダイアログなら[wxSmith|Add wxDialog]を実行して[New wxDialog resource]ダイアログを開きクラス名、ファイル名を入力して[OK]を押す。[Multiple selection]ダイアログが開きダイアログを使用するターゲットにチェックして[OK]を押せば*.h/*.cpp/*.wxsにwxDialog派生をユーザー定義ウィンドウとして生成してwxSmithエディタが開く。[New wxDialog resource]ダイアログで[OK]の前に[Advanced options]をクリックすれば詳細なオプション設定できるがデフォルトのままで良い。

覚え書き
Code::Blocksは[wxSmith|Add wxScrollingDialog]というメニューでwxScrollingDialog派生クラスを生成するが、wxScrollingDialogはwxWidgetsライブラリに属さず利用できない。
覚え書き
日本語アプリケーションをどのように開発するかに述べたようにwxSmithは入力された文字列を_マクロで囲んでソースコードに挿入する。[Advanced options]で[Use internationalization (translatable applications)]のチェックを外すと文字列を_Tマクロで囲んでソースコードに挿入して国際化対象としない。ユニコード(手法)で_TマクロはL""リテラルなので、このチェックを外してエディタ文字コード/コンパイラ入力文字コードをUTF-8とすれば日本語を含む任意言語をwxSmithで書き込みアプリケーションを作成できる。しかし本サイトはGNU gettextによる国際化機能にこだわりこの手法は意図的に無視する。

ウィザード(K1K2など)の作成するwxWidgetsプロジェクトはメインウィンドウの*.wxsを自動作成する。こういった既成の*.wxsをwxSmithエディタに読み込むには[Management]ウィンドウ[Projects]ページツリービューで[...|Resources|wxsmith|*.wxs]をダブルクリックする。[Project|Add files]または[Project|Remove files]で*.wxsを*.h/*.cppと同様にプロジェクトへ追加またはプロジェクトから削除できるが、これらをwxSmithは認識しない。*.wxsの追加/削除をwxSmithに認識させるにはXML形式で記述されるプロジェクトファイル(*.cbp)を直接編集し[...|Extensions|wxsmith|resources]ノードに追加/削除する。

<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<CodeBlocks_project_file>
<FileVersion major="1" minor="6" />
<Project>
...
<Unit filename="wxsmith/Desktop1Frame.wxs" />
<Extensions>
<lib_finder disable_auto="1" />
<wxsmith version="1">
<gui name="wxWidgets" src="Desktop1App.cpp" main="Desktop1Frame" init_handlers="necessary" language="CPP" />
<resources>
<wxFrame wxs="wxsmith/Desktop1Frame.wxs" src="Desktop1Frame.cpp" hdr="Desktop1Frame.h" fwddecl="0" i18n="1" name="Desktop1Frame" language="CPP" />
</resources>
</wxsmith>
</Extensions>
</Project>
</CodeBlocks_project_file>

ユーザーインターフェース

信頼できるwxSmithドキュメントはチュートリアルだけでCode::Blocksに統合されたユーザーインターフェースを説明する用語が明確に定義されていないため、本サイトは以下に定義する。wxSmithのユーザーインターフェースは[Management]ウィンドウ[Resources]ページに表示されるwxSmithリソースマネージャと、コードエディタの代わりに表示されるwxSmithエディタである。

wxSmithリソースマネージャはワークスペースに読み込まれている全プロジェクトのwxSmithリソースをツリービューで管理する。[Resources]はルートノードで下位にプロジェクトノードを持つ。その下位はユーザー定義ウィンドウを基底クラス(wxFrame、wxDialog、wxPanel)で分類するノードで、それぞれの下位にユーザー定義ウィンドウノードを持つ。ユーザー定義ウィンドウノードは基底クラス名のノードと[Tools]ノードを持ち、前者はウィンドウ配置されるコンポーネント(ウィジェットコンポーネント)のルートであり、後者はウィンドウ配置されないコンポーネント(ツールコンポーネント)のルートであり、いずれも下位に"コンポーネントノード"を所有関係に基づき階層表示する。前者は基底クラスから継承するプロパティ/イベントを表示編集するノードを兼ね、これを"ウィンドウノード"と呼ぶ。ツリービューの下にプロパティエディタとイベントエディタがあり、両者をアイコンボタンで切り替えて選択したウィンドウ/コンポーネントのプロパティ/イベントを表示編集する。ウィンドウ/コンポーネント以外のノードはプロパティ/イベントを持たないため、それらを選択するとプロパティ/イベントエディタは選択前の状態を維持する。

覚え書き
ツリー階層に基底クラス名が2回現れるのはかなり奇妙に感じる。ユーザー定義ウィンドウのプロパティ/イベント表示編集はユーザー定義ウィンドウクラス名を持つノードでなく、下位の基底クラス名を持つノードを選択しなければならない事を強調する。

wxSmithエディタは中央にWYSIWYG表示されるユーザー定義ウィンドウにウィジェットコンポーネントを配置する。配置するコンポーネントは下のコンポーネントパレットから選択する。ウィンドウに配置できないツールコンポーネントは上のツールホルダーパネルに配置する。配置したコンポーネントの選択はリソースマネージャとエディタで連動するが、リソースマネージャでウィンドウ/コンポーネント以外のノードを選択する場合のみエディタは選択前の状態を維持する。右にコマンドパネルがあり、配置方法の選択、配置されたコンポーネントの削除、プレビューなどを行う。

"コンポーネント"はチュートリアルに準拠して定義する。wxSmithのリソース(ユーザー定義ウィンドウ)はコンポーネントで構成される。全てのボタン、テキストボックス、リストなどはコンポーネントである。サイザー、スペーサー(空スペースを加えるもの)、メニュー項目、タイマーといった抽象的な存在もコンポーネントである。すなわち基本的にリソースに含まれるもの全てをコンポーネントと呼ぶ。

コンポーネントはウィンドウに配置される"ウィジェットコンポーネント"とウィンドウに配置されない"ツールコンポーネント"に二分され、多数派はウィジェットコンポーネントである。ウィジェットコンポーネントで自らに他のウィジェットコンポーネントを部品として配置できるもの(例えばwxPanel)を"コンテナコンポーネント"と呼ぶ。トップレベルウィンドウは便宜上コンテナコンポーネントに含める。ウィジェットコンポーネントのほとんどはwxWidgetsコントロール(wxControl派生)に対応するが、コンポーネントパレット[Layout]ページのサイザーはwxWidgetsサイザー(wxSizer派生)に対応し、スペーサー(Spacer)のようにそもそもwxWidgetsオブジェクトに対応しないものもある。ツールコンポーネントは[Dialogs]ページのダイアログと[Tools]ページのその他ツールであり、ダイアログはwxWidgetsダイアログ(wxDialog派生)に対応し、その他ツールはそれぞれ何らかのwxWidgetsオブジェクトに対応する。その他ツールに含まれるメニューバー(wxMenuBar)、ステータスバー(wxStatusBar)、ツールバー(wxToolBar)はウィンドウの一部として表示されるため本来はウィジェットコンポーネントとするべきと思うが、wxSmithはこれらをツールコンポーネントとして扱いWYSIWYGに配置せず、かつwxFrame派生のユーザー定義ウィンドウのみに追加できる。wxWidgetsライブラリはwxStatusBarとwxToolBarをwxControl派生としてこの制約は課しておらず、マニュアル実装でwxWindow派生に普通に追加できる。一方wxMenuBarはwxControl派生でなくこのような追加はできない。

wxSmithはwxWidgetsライブラリをより高次で再抽象化し、wxSmithコンポーネントはwxWidgetsオブジェクトにそのまま対応しない。wxSmithコンポーネントプロパティのあるものは対応するwxWidgetsオブジェクトのコンストラクタへの実引数であり、あるものはセッターメンバ関数への実引数であり、あるものは別オブジェクトのメンバ関数に渡す実引数であり、その他様々である。重要な例はほとんどのコンポーネント(例えばwxTextCtrl)が持つIs memberプロパティで、これをチェックするとwxTextCtrlインスタンスをメンバ変数に保持してコンストラクタ外からも参照できる。別の重要な例はサイザー(例えばwxBoxSizer)に配置したウィジェットコンポーネント(例えばwxTextCtrl)で、wxBoxSizerがwxTextCtrlを配置するためのサイザーパラメータがwxTextCtrlのプロパティとして表示される。サイザーパラメータはソースコードでwxBoxSizerインスタンスメンバ関数への実引数であり、サイザー配置しない場合はプロパティとして表示されない。Is memberもサイザーパラメータもC++クラス的にはwxTextCtrlのプロパティと呼べず、このようにコンポーネントプロパティとソースコードの関係は複雑で直感から程遠い。

wxSmithが生成挿入するソースコード

wxSmithが生成挿入するコードはマーカーとなるコメント行//(*<種類>(<クラス名>)と//*)に挟んで明示する。他にマーカー行で明示しないがソースコードにイベントハンドラメンバ関数定義のスケルトンを挿入する。マーカー行に挟まれた部分はマニュアル編集を想定せず、編集したとしてもwxSmithの編集が常に上書きする。Handlersは例外で、wxSmithイベントエディタからハンドラを除外してもHandlersからメンバ関数宣言は削除されない。ハンドラメンバ関数を削除するにはソースコードのメンバ関数定義と一緒にマニュアル削除する。Handlers、Identifies、Declarationsはクラススコープに挿入されてアクセス指定子(private/protected/public)は[New wxXXX resource]ダイアログ[Advanced options|Scopes]の設定に従う。なおアクセス指定子はマーカー行に挟まれておらず、マニュアル編集で変更できる。

ファイル 種類 説明 備考
インクルード Headers 公開されるwxWidgetsインクルードファイル -
Handlers イベントハンドラメンバ関数の宣言 -
Identifies wxWindow派生コンポーネントのID値宣言 -
Declarations メンバとして保持されるwxWindow派生コンポーネントの宣言 -
ソースコード InternalHeaders 公開されないwxWidgetsインクルードファイル -
IdInit wxWindow派生コンポーネントのID値定義 -
EventTable 静的なイベントマップ 使用しない
Initialize ウィンドウとコントロールの構築、動的なイベントマップ -
Destroy ウィンドウとコントロールの解体 使用しない

動作確認(1)のDesktop1プロジェクトメインウインドウで生成挿入部を例示する。

Desktop1Frame.h

#ifndef DESKTOP1MAIN_H
#define DESKTOP1MAIN_H
//(*Headers(Desktop1Frame)
#include <wx/frame.h>
...
//*)
...
class Desktop1Frame: public wxFrame
{
public:
Desktop1Frame(wxWindow* parent,wxWindowID id = -1);
virtual ~Desktop1Frame();
private:
//(*Handlers(Desktop1Frame)
void OnQuit(wxCommandEvent& event);
...
//*)
//(*Identifiers(Desktop1Frame)
static const long idMenuQuit;
...
//*)
//(*Declarations(Desktop1Frame)
wxStatusBar* StatusBar1;
//*)
...
DECLARE_EVENT_TABLE()
};
#endif // DESKTOP1MAIN_H

Desktop1Frame.cpp

#include "wx_pch.h"
...
//(*InternalHeaders(Desktop1Frame)
#include <wx/intl.h>
...
//*)
...
//(*IdInit(Desktop1Frame)
const long Desktop1Frame::idMenuQuit = wxNewId();
...
//*)
BEGIN_EVENT_TABLE(Desktop1Frame,wxFrame)
//(*EventTable(Desktop1Frame)
//*)
END_EVENT_TABLE()
Desktop1Frame::Desktop1Frame(wxWindow* parent,wxWindowID id)
{
//(*Initialize(Desktop1Frame)
wxMenu* Menu1;
...
Create(parent, id, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_STYLE, _T("id"));
MenuBar1 = new wxMenuBar();
...
Connect(idMenuQuit,wxEVT_COMMAND_MENU_SELECTED,(wxObjectEventFunction)&Desktop1Frame::OnQuit);
...
//*)
...
}
Desktop1Frame::~Desktop1Frame()
{
//(*Destroy(Desktop1Frame)
//*)
}
void Desktop1Frame::OnQuit(wxCommandEvent& event)
{
...
}
...

操作方法

基本的な操作方法

コンポーネントをWYSIWYG表示されるユーザー定義ウィンドウあるいはツールホルダーパネルに配置し、プロパティ/イベントをそれぞれのエディタで編集する。コンポーネントの配置方法は変則的でグラフィック編集ソフト的なものを期待すると面食らう。コマンドパネルボタンの機能を説明する。

コマンド 機能
Insert new widgets by pointing with mouse 新しいコンポーネントをマウスカーソル位置に挿入する
Insert new widgets into current selection 新しいコンポーネントを現在の選択の中に挿入する
Insert new widgets before current selection 新しいコンポーネントを現在の選択の後に挿入する
Insert new widgets after current selection 新しいコンポーネントを現在の選択の前に挿入する
Delete current selection 現在の選択を削除する
Show preview プレビューを表示する
Open / Close Quick Properties panel クイックプロパティパネルを開く/閉じる

[Insert ...]は挿入モードを選択するもので、選択した挿入モードはアイコンにチェックマークが付く。[Delete ...]と[Show ...]は説明する必要は無いだろう。[Open / Close ...]はサイザープロパティ設定を簡易化するツールを開く/閉じるが、開発者も役に立たないと認めていて無視する。

ツールコンポーネントの配置は単純で、挿入モードに関係なくパレットで選択すれば即時にツールホルダーパネルに配置される。配置されたツールコンポーネントの順番はクリップボード操作([Edit|Cut]と[Edit|Paste])で変更できる。

ウィジェットコンポーネントの配置はサイザーコンポーネントを用いる場合とそうでない場合で操作性が全く異なる。一般的なGUI編集ツール(例えばエクセルのVBAフォームデザイナー)はレイアウトフリー(任意の位置に部品を配置できる)でこれに近いものはサイザーコンポーネントを用いない場合だが、同等の操作性は期待できない。VBAフォームデザイナーならツールボックスからコントロールをドラッグドロップするが、同様を行うには[Insert ... by pointing with mouse]を選択して、パレットでコンポーネントを選択して、配置したい場所をクリックする。つまりパレットから直接ドラッグドロップできない。最初のコンポーネントは何故かウィンドウサイズに合わせて拡大する。2番目のコンポーネントは最初のコンポーネントがコンテナコンポーネントならその中に配置するが、そうでないと最初のコンポーネントが突然縮小する。配置したコンポーネントはマウスで移動/サイズ変更できるが、いくつかのコンポーネントは不可解な挙動を示す。例えばwxPanelコンポーネントをサイズ拡大すると短距離のドラッグ移動ができなくなり、まるで移動開始の閾値を自サイズ相対値で判定しているようだ。コンポーネントをコンテナコンポーネントへドラッグして挿入する事はできる。クリップボード操作は可能だが切り取ったコンポーネントを空のコンテナコンポーネントに貼り付ける事は恐らくできない。その他うまく説明できない事態に何度も遭遇し、最悪にはCode::Blocksがクラッシュして全ての編集を失う。

これらはフラストレーションを溜め込みwxSmithの有用性を否定しかねない結果をもたらすが、想像するにwxSmithはレイアウトフリーが不得意で、サイザーコンポーネントで必ずレイアウト管理すると決めれば十分使用に耐える。チュートリアルもサイザーコンポーネント使用を前提とする。

サイザーコンポーネントの利用

サイザーコンポーネント(wxSizer派生)はコンテナコンポーネントが所有し、コンテナに配置されるウィジェットコンポーネント(コンテナ部品)のレイアウトとコンテナコンポーネントのサイズを管理する。最初に"所有"を定義する。wxSmithコンポーネントの"所有"はwxSmithリソースマネージャのツリービューにおける上下関係とする。wxWidgetsオブジェクトの"所有"は所有オブジェクトが解体時に被所有オブジェクトを解体する関係とする。コンテナコンポーネントがサイザーコンポーネントを所有する場合、wxSmithコンポーネントではサイザーコンポーネントがコンテナ部品を所有するが、wxWidgetsオブジェクトではコンテナオブジェクトがコンテナ部品に対応するオブジェクトを所有して、この例外を除けば両者は概ね一致する。以降はwxSmithコンポーネントの文脈を用いる。

サイザーコンポーネントをまとめる。これ以外にサイザーとコントロールと組み合わせたコンポーネントが存在するが省略する。サイザーコンポーネントは他のサイザーコンポーネントをコンテナ部品に所有してさらに複雑なレイアウトに対応する。

サイザー 説明 部品配置
wxBoxSizer 縦横いずれかで一次元配置する シーケンシャル
wxGridSizer 等幅、等高のグリッドで二次元配置する シーケンシャル
wxFlexGridSizer 可変幅、可変高のグリッドで二次元配置する シーケンシャル
wxGridBagSizer 可変幅、可変高、可変スパンのグリッドで二次元配置する ランダム

シーケンシャル部品配置はウィジェットコンポーネントを構築順でグリッド配置する。ランダム部品配置はコンポーネントのプロパティで配置セルを指定する。主にシーケンシャル部品配置で任意セルを空白とする手段としてSpacerコンポーネントが用意される。シーケンシャル部品配置は構築順が配置を決定するが、ランダム部品配置はプロパティが指定する。いずれのサイザーもウィジェットコンポーネントの配置方法は同じで二つある。

第一の方法はコマンドパネル[Insert new widgets by pointing with mouse]を選択する。配置したいコンポーネントをコンポーネントパレットで選択してマウスをWYSIWYG表示ユーザー定義ウィンドウへ移動すればターゲットとなり得るコンポーネントがダークブルーで示される。ターゲットは空のサイザーコンポーネントあるい全コンテナ部品のどちらかで、前者であればそのままクリックして最初のコンポーネント構築となる。後者であればマウスを任意のコンテナ部品へ移動して左半分または右半分がライトブルーに変化し、クリックして前あるいは後に構築を挿入する。後者の場合にコンテナ部品以外をクリックすれば最後に構築を追加する。

第二の方法は最初にターゲットとなるコンポーネントをWYSIWYG表示ユーザー定義ウィンドウあるいはリソースマネージャのツリービューで選択する。コマンドパネル[Insert new widgets into current selection]、[Insert new widgets before current selection]、[Insert new widgets after current selection]のいずれかを選択し、パレットでコンポーネントを選択すればコマンドに従い構築される。コマンドは状況検知して例えばコンテナでないコンポーネントに[Insert ... into ...]を選択できない。コンポーネントが重なりターゲットがマウス指定できない場合は第一の方法は無理で、ツリービュー選択で第二の方法を用いる。

コンテナ部品はドラッグ移動で構築順やコンテナを変更できる。シーケンシャル部品配置なら構築順の変更はそのまま配置の変更となる。マウスでサイズ変更できるが、サイザーコンポーネントとそれがサイズ管理するコンポーネントは変更を拒絶する。クリップボード貼り付けは選択の前に挿入されて概ね直感通りだが、空のコンテナへは貼り付けできない。

KTxtEditのオプション設定ダイアログ

サイザーコンポーネントの利用は複雑でトライアンドエラーで経験を積むしかない。サイト作成者はwxBoxSizerとwxFlexGridSizerの組み合わせに限定し、経験上これで十分と考えている。コンポーネントのIs memberプロパティはコンポーネント対応wxWidgetsオブジェクトをコンストラクタの外から参照する場合のみチェックしている。IdentifierプロパティはwxID_ANYとしてwxWidgetオブジェクトコンストラクタに渡しID値の生成を委ねるが、wxSmithはをその入力文字列をウィンドウ名としても渡してしまう。そのため全てが同じウィンドウ名_T("wxID_ANY")を持ち、コントロールをウィンドウ名で検索する事はできない。コンテナ部品はサイザープロパティでサイザー中の振る舞いを定義するが、その最重要はExpandとProportionと考える。トップレベルウィンドウが固定サイズならExpandをTRUE、Proportionを0を基本とする。wxStaticTextは例外で、自身のプロパティで縦方向の文字アライメントを定義できないため、ExpandをFALSEとしてVertical alignをCenterとする。何であれプレビューと修正の繰り返しは必須と覚悟する。

覚え書き
wxWidgetsライブラリはwxWindow派生インスタンスをID値あるいはウィンドウ名で識別する。ID値は普通は一意だが複数コントロールが同じハンドラをコールする場合は意図的に同値とする場合がある。wxSmithはIdentifierプロパティに事前定義ID値(wxID_XXX)以外の文字列を与えると、インクルードファイル//(Identifiers(<クラス名>) ... //)とソースコードファイル//(IdInit(<クラス名>) ... //)にスタティッククラスメンバ定数として宣言/定義する。wxSmithは定義にwxNewId関数を用いるが厳密には一意が保証されておらず、wxID_ANYによる方法が推奨される。 wxID_ANYは特殊な事前定義ID値で二つの目的で使用する。第一はwxWindow派生コンストラクタにID値として与え、一意のID値生成をコンストラクタに委ねる。この場合の真のID値はGetIdメンバ関数で取得できる。第二はイベントマップにID値として与え、全コントロールからのイベントを捕捉するハンドラを定義する。

KTxtEditプロジェクトのオプション設定ダイアログの作成をサンプルとして作成する。[wxSmith|Add wxDialog]の[New wxDialog resouce]ダイアログで[Class Name]テキストボックスにOptionDialogを入力し[OK]を押す。wxSmithエディタが生成されたOptionDialog.wxsスケルトンを読み込み開くので、以下のコンポーネントを順次配置する。チュートリアルは最初にwxBoxSizerとwxPanelを配置してwxPanelにコントロールを追加せよとするが、wxDialog派生ではメリットは見当たらず本サイトは省略する。Notebook(wxNotebookコンポーネント)にページを追加するには、選択右クリックで表示されるコンテキストメニュー[Add new page]を実行する。TextCtrlAppearance(TextCtrlコンポーネント)のProportionを1として[Appearance]ページの隙間を埋める。Notebook(wxNotebookコンポーネント)のProportionが0のままではTextCtrlAppearanceが不要に拡大してStdDialogButtonSizer(wxStdDialogButtonSizerコンポーネント)が見えなくなるケースが存在し、これも1とする。StdDialogButtonSizer(wxStdDialogButtonSizerコンポーネント)はExpandをTRUEとするとボタンが右寄せとなるためFALSEとして、Horizontal alignをCenterとする。

覚え書き
コンポーネントIdentifierをwxID_ANYとしてID値生成をコンストラクタに委ねる場合、ハンドラはwxSmith生成スケルトンによらずGetIdメンバ関数を用いてマニュアル実装する。なぜならwxSmith生成スケルトンにはID値としてwxID_ANYが渡されてるため全コントロールのイベントを捕捉して意図と異なる結果となる。ハンドラをwxSmith生成スケルトンによる場合は必ず一意のID値を明示的に与える。
覚え書き
チュートリアルが主張する最初のwxBoxSizerとwxPanelの必要性はwxFrame派生に関する話かもしれない。wxFrame派生でこれらを省略すると以下の不具合となる可能性がある。
  • wxFrameのデフォルト背景色が標準的なものと異なり配置コントロールのマージン(Border widthプロパティ)がゼロでないと不自然な外見になる。
  • タブキーによるコントロールの選択順が混乱する場合がある。wxFrameがデフォルトでwxTAB_TRAVERSALスタイルを持たないためと考えるが確認していない。
覚え書き
Code::Blocksが20.03にアップデートされて以降、コンポーネントをwxSmithエディタへ配置を試みると[wxWidgets Debug Alert]ダイアログが開き"A debugging check in this application has failed. ... Adding a window already in a sizer, detach it first!"が表示される事がある。恐らく無害で[Don't show this dialog again]にチェックして[Continue]で継続する。
コンポーネント Var name Is member Identifier Expand Proportion その他のプロパティ
wxDialog - - - - - Title="Option settings"
└ wxBoxSizer BoxSizer FALSE - - - Orientation="wxVERTICAL"
 ├ wxNotebook Notebook TRUE wxID_ANY TRUE 1 右クリック[Add new page]でwxPanelを追加する
 │├ wxPanel PanelFile FALSE wxID_ANY - - Page name="File", Background="Window background"
 ││└ wxFlexGridSizer FlexGridSizerFile FALSE - - - Cols="2", Glowable cols="0"
 ││ ├ wxStaticText StaticTextRecentFilesMax FALSE wxID_ANY FALSE 0 Label="Recent files max", Horizontal align="Left", Vertical align="Center"
 ││ ├ wxSpinCtrl SpinCtrlRecentFilesMax TRUE wxID_ANY TRUE 0 Value="10", Min="1", Max="20"
 ││ ├ wxStaticText StaticTextDefaultEncoding FALSE wxID_ANY FALSE 0 Label="Default encoding", Horizontal align="Left", Vertical align="Center"
 ││ ├ wxChoice ChoiceDefaultEncoding TRUE wxID_ANY TRUE 0
 ││ ├ Spacer - - - TRUE 0
 ││ ├ wxCheckBox CheckBoxDefaultByteOrderMark TRUE wxID_ANY TRUE 0 Label="Byte order mark"
 ││ ├ wxStaticText StaticTextDefaultEndOfLine FALSE wxID_ANY FALSE 0 Label="Default end of line", Horizontal align="Left", Vertical align="Center"
 ││ └ wxChoice ChoiceDefaultEndOfLine TRUE wxID_ANY TRUE 0
 │└ wxPanel PanelAppearance FALSE wxID_ANY - - Page name="Appearance", Background="Window background"
 │ └ wxBoxSizer BoxSizerAppearance FALSE - - - Orientation="wxVERTICAL"
 │  ├ wxTextCtrl TextCtrlAppearance TRUE wxID_ANY TRUE 1 Style="wxTE_MULTILINE, wxTE_READONLY"
 │  └ wxBoxSizer BoxSizerAppearanceButtons FALSE - TRUE 0 Orientation="wxHORIZONTAL"
 │   ├ wxButton ButtonAppearanceForegroundColor FALSE wxID_ANY TRUE 0 Label="FG Color..."
 │   ├ wxButton ButtonAppearanceBackgroundColor FALSE wxID_ANY TRUE 0 Label="BG Color..."
 │   └ wxButton ButtonAppearanceFont FALSE wxID_ANY TRUE 0 Label="Font..."
 └ wxStdDialogButtonSizer StdDialogButtonSizer FALSE - FALSE 0 Horizontal align="Center"

[File]、[Appearance]の2ページからなるオプション設定ダイアログが生成できるはずだ。