LoginSignup
1
0

wxWidgetsのチュートリアル的なもの

Last updated at Posted at 2023-06-02

下記の環境が前提

0. はじめに

wxWidgetsでGUIアプリケーションを作成していく流れを掴んでもらうのが目標
過剰に書きすぎないようにするが、大事だと思ったところは深堀する

※単に関数と書いた場合はクラスのメンバ関数と読み替えること
※通常の関数はフリー関数と表記する

1. wxApp

wxWidgetsではmain関数を定義せず、マクロに任せてしまう
「wxApp」クラスの「OnInit」関数が実質的なコードの起点となる

ソースコード

App.h
#include <wx/wx.h>

//wxAppの派生クラスを定義してOnInit()をオーバーライド
class myApp : public wxApp
{
public:
    virtual bool OnInit() override;
};
App.cpp
#include "App.h"
#include <iostream>

//真のmain関数(エントリポイント)を生成するマクロ
wxIMPLEMENT_APP(myApp);

//事実上のmain関数
bool myApp::OnInit()
{
    //標準出力に文字列を出力
    std::cout << "Hallo World!\n";

    //trueでwxWidgetsのメインループへ、falseでプログラム即終了
    return true;
}

コンパイル

※今回に限って「-mwindows」は抜いてコンソールアプリケーションとしてビルド

g++ -O2 -finput-charset=CP932 -fexec-charset=CP932 -static-libgcc -static-libstdc++ -mthreads  App.cpp -o App.exe -I C:\wxWidgets\wxWidgets-3.2.2.1\include -I C:\wxWidgets\wxWidgets-3.2.2.1\lib\gcc_lib\mswu -L C:\wxWidgets\wxWidgets-3.2.2.1\lib\gcc_lib -lwxmsw32u -lwxmsw32u_gl -lwxscintilla -lwxtiff -lwxjpeg -lwxpng -lwxzlib -lwxregexu -lwxexpat -lkernel32 -luser32 -lgdi32 -lcomdlg32 -lwinspool -lwinmm -lshell32 -lshlwapi -lcomctl32 -lole32 -loleaut32 -luuid -lrpcrt4 -ladvapi32 -lversion -lws2_32 -lwininet -loleacc -luxtheme

実行結果

image.png

真のエントリポイントはどこか?

wxWidgetsで最初にやることをまとめると次の通り

  • 「wxApp」クラスの派生クラスをつくる
  • 「OnInit」関数をオーバーライドしてやりたい処理を書く
  • 定義した派生クラスを「wxIMPLEMENT_APP」マクロに渡す

あとはwxWidgets側で「OnInit」関数を最初に実行してくれる

真のエントリポイントは「wxIMPLEMENT_APP」マクロによって定義をされる
※参考までに自分の環境で「wxIMPLEMENT_APP」マクロをVSCodeに展開してもらった結果
image.png

2. wxFrame

ここではウィンドウを取り扱う
wxWidgetsでは「wxFrame」クラスが最も基本的なウィンドウとなる

また、widgetsクラスのコンストラクタで(おおむね)共通である第一引数・第二引数にも触れる
ついでにWindowIDの取り扱いも解説しておく

ソースコード

App.h
#include <wx/wx.h>

//wxAppの派生クラスを定義してOnInit()をオーバーライド
class myApp : public wxApp
{
public:
    virtual bool OnInit() override;
};
App.cpp
#include "App.h"

//真のmain関数(エントリポイント)を生成するマクロ
wxIMPLEMENT_APP(myApp);

//事実上のmain関数
bool myApp::OnInit()
{
    //ウィンドウを生成
    auto frame = new wxFrame(nullptr, wxID_ANY, "ウィンドウのタイトル");

    //ウィンドウを表示
    frame->Show();
    
    //trueでwxWidgetsのメインループへ、falseでプログラム即終了
    return true;
}

コンパイル

g++ -O2 -finput-charset=CP932 -fexec-charset=CP932 -static-libgcc -static-libstdc++ -mthreads -mwindows App.cpp -o App.exe -I C:\wxWidgets\wxWidgets-3.2.2.1\include -I C:\wxWidgets\wxWidgets-3.2.2.1\lib\gcc_lib\mswu -L C:\wxWidgets\wxWidgets-3.2.2.1\lib\gcc_lib -lwxmsw32u -lwxmsw32u_gl -lwxscintilla -lwxtiff -lwxjpeg -lwxpng -lwxzlib -lwxregexu -lwxexpat -lkernel32 -luser32 -lgdi32 -lcomdlg32 -lwinspool -lwinmm -lshell32 -lshlwapi -lcomctl32 -lole32 -loleaut32 -luuid -lrpcrt4 -ladvapi32 -lversion -lws2_32 -lwininet -loleacc -luxtheme

実行結果

image.png

widgetクラスのコンストラクタ

下記は「wxFrame」クラスのコンストラクタである

auto frame = new wxFrame(nullptr, wxID_ANY, "ウィンドウのタイトル");

「wxFrame」クラスに限らず、widgetクラスのコンストラクタで要求される第一・ 第二引数はおおむね同じだ

  • 第一引数:親widgetのポインタ
    ※「wxFrame」は最上位のwidgetのため今回はnullptr

  • 第二引数:WindowID(すべてのwidget間でユニークとなることが要求される値)
    ※WindowIDを使った処理をしないなら「wxID_ANY」を指定して自動割振するとよい

WindowIDについてはwxWidget側で管理されている範囲がある

  • 自動割り当て範囲:「wxID_AUTO_LOWEST」~「wxID_AUTO_HIGHEST」
  • 予約済みIDの範囲:「wxID_LOWEST」~「wxID_HIGHEST」

手動でIDを管理する場合はこれらの範囲を避けること
https://docs.wxwidgets.org/3.2/overview_windowids.html

覚えなくていいが「wxFrame」のコンストラクタの完全な定義は次の通り
https://docs.wxwidgets.org/3.2/classwx_frame.html#a01b53ac2d4a5e6b0773ecbcf7b5f6af8

wxFrame (wxWindow *parent, wxWindowID id, const wxString &title, const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxDefaultSize, long style=wxDEFAULT_FRAME_STYLE, const wxString &name=wxFrameNameStr)

デフォルト値で引数が隠れているものが多いが、あとから設定できるものはひとまずデフォルト値に任せてしまうのもよいだろう

3. wxFrameをカスタマイズする準備

動作を変えない範囲で「wxFrame」クラスを継承した派生クラスを定義する
この派生クラスの定義がオリジナルプログラムの第一歩となる

ソースコード

frame.h
#include <wx/wx.h>

class myFrame : public wxFrame
{
public:
    //基底クラスと同じ引数を持つコンストラクタ(宣言)
    myFrame
    (
        wxWindow* parent,
        wxWindowID id,
        const wxString& title,
        const wxPoint& pos = wxDefaultPosition,
        const wxSize& size = wxDefaultSize,
        long style = wxDEFAULT_FRAME_STYLE,
        const wxString& name = wxFrameNameStr
    );

private:
    //今後のカスタマイズで必要があればここにメンバの追加
};
frame.cpp
#include "Frame.h"

 //基底クラスと同じ引数を持つコンストラクタ(定義)
myFrame::myFrame
(
    wxWindow* parent,
    wxWindowID id,
    const wxString& title,
    const wxPoint& pos,
    const wxSize& size,
    long style,
    const wxString& name

) : wxFrame(parent, id, title, pos, size, style, name)//基底クラスへの委譲コンストラクタ
{
    //今後ここにカスタマイズの処理を入れる予定
}
app.h
#include <wx/wx.h>

//wxAppの派生クラスを定義してOnInit()をオーバーライド
class myApp : public wxApp
{
public:
    virtual bool OnInit() override;
};
app.cpp
#include "App.h"
#include "Frame.h"

//真のmain関数(エントリポイント)を生成するマクロ
wxIMPLEMENT_APP(myApp);

//事実上のmain関数
bool myApp::OnInit()
{
    //「カスタマイズされた」ウィンドウを生成
    auto frame = new myFrame(nullptr, wxID_ANY, "ウィンドウのタイトル");

    //ウィンドウを表示
    frame->Show();
    
    //trueでwxWidgetsのメインループへ、falseでプログラム即終了
    return true;
}

コンパイル

 g++ -O2 -finput-charset=CP932 -fexec-charset=CP932 -static-libgcc -static-libstdc++ -mthreads -mwindows App.cpp Frame.cpp -o App.exe -I C:\wxWidgets\wxWidgets-3.2.2.1\include -I C:\wxWidgets\wxWidgets-3.2.2.1\lib\gcc_lib\mswu -L C:\wxWidgets\wxWidgets-3.2.2.1\lib\gcc_lib -lwxmsw32u -lwxmsw32u_gl -lwxscintilla -lwxtiff -lwxjpeg -lwxpng -lwxzlib -lwxregexu -lwxexpat -lkernel32 -luser32 -lgdi32 -lcomdlg32 -lwinspool -lwinmm -lshell32 -lshlwapi -lcomctl32 -lole32 -loleaut32 -luuid -lrpcrt4 -ladvapi32 -lversion -lws2_32 -lwininet -loleacc -luxtheme

実行結果

image.png

派生・継承によるwidgetクラスのカスタマイズ

「wxFrame」クラスを継承した「myFrame」派生クラスは基底クラスと同じ動作をするだけだが、今後の解説ではこのコードをひな形にカスタマイズを入れていく

「wxFrame」クラスに限らずwidgetクラスのカスタマイズは継承によるポリモーフィズムによって実現できる
内部的に使われる関数(virtualかつprivateではない)でもオーバーライドでデフォルトの挙動を変えられる

4. メニューバーとステータスバー

「wxFrame」クラスにはメニューバーとステータスバーを追加することができる
※一応ツールバーもあるがここでは解説しない
メニューバーのアイテムには構築の都合上「wxID_ANY」ではなく明示的にWindowIDを割り当てる
また、イベントハンドルについても解説する

ソースコード

frame.h
#include <wx/wx.h>

class myFrame : public wxFrame
{
public:
    //基底クラスと同じ引数を持つコンストラクタ(宣言)
    myFrame
    (
        wxWindow* parent,
        wxWindowID id,
        const wxString& title,
        const wxPoint& pos = wxDefaultPosition,
        const wxSize& size = wxDefaultSize,
        long style = wxDEFAULT_FRAME_STYLE,
        const wxString& name = wxFrameNameStr
    );

private:
    wxMenuBar* menu_bar;
    wxMenu* menu_file;
};
frame.cpp
#include "Frame.h"

 //基底クラスと同じ引数を持つコンストラクタ(定義)
myFrame::myFrame
(
    wxWindow* parent,
    wxWindowID id,
    const wxString& title,
    const wxPoint& pos,
    const wxSize& size,
    long style,
    const wxString& name

) : wxFrame(parent, id, title, pos, size, style, name)
{
    //メニューアイテムに割り当てるIDを列挙型を宣言しておく
    enum ID_MENU
    {
        ID_MENU_EXIT,
    };

    //メニューの構築
    menu_file = new wxMenu;
    menu_file->Append(ID_MENU_EXIT, "終了\tCtrl+Q");

    //メニューバーの構築とメニューバーにメニューをセット
    menu_bar = new wxMenuBar;
    menu_bar->Append(menu_file, "ファイル(&F)");

    //このWindowにメニューバーをセット
    SetMenuBar(menu_bar);

    //メニューの終了を押したらプログラム終了
    Bind(wxEVT_MENU, [=](wxCommandEvent& event)
    {
        Destroy();
    }, ID_MENU_EXIT);

    //ステータスバー
    CreateStatusBar();
    SetStatusText("ステータスバーはここ");

}
app.h
#include <wx/wx.h>

//wxAppの派生クラスを定義してOnInit()をオーバーライド
class myApp : public wxApp
{
public:
    virtual bool OnInit() override;
};
app.cpp
#include "App.h"
#include "Frame.h"

//真のmain関数(エントリポイント)を生成するマクロ
wxIMPLEMENT_APP(myApp);

//事実上のmain関数
bool myApp::OnInit()
{
    //「カスタマイズされた」ウィンドウを生成
    auto frame = new myFrame(nullptr, wxID_ANY, "ウィンドウのタイトル");

    //ウィンドウを表示
    frame->Show();
    
    //trueでwxWidgetsのメインループへ、falseでプログラム即終了
    return true;
}

コンパイル

 g++ -O2 -finput-charset=CP932 -fexec-charset=CP932 -static-libgcc -static-libstdc++ -mthreads -mwindows App.cpp Frame.cpp -o App.exe -I C:\wxWidgets\wxWidgets-3.2.2.1\include -I C:\wxWidgets\wxWidgets-3.2.2.1\lib\gcc_lib\mswu -L C:\wxWidgets\wxWidgets-3.2.2.1\lib\gcc_lib -lwxmsw32u -lwxmsw32u_gl -lwxscintilla -lwxtiff -lwxjpeg -lwxpng -lwxzlib -lwxregexu -lwxexpat -lkernel32 -luser32 -lgdi32 -lcomdlg32 -lwinspool -lwinmm -lshell32 -lshlwapi -lcomctl32 -lole32 -loleaut32 -luuid -lrpcrt4 -ladvapi32 -lversion -lws2_32 -lwininet -loleacc -luxtheme

実行結果

image.png

image.png

メニューの構成要素

メニュバーを構成する要素は次の通り

  • メニューバー(wxMenuBar)
  • メニュー(wxMenu)
  • メニューアイテム(wxMenuItem)

メニューアイテムに関しては「Append」関数で間接的に構築している
※リファレンスでも「wxMenu」の関数で生成するのが普通と記載があったのでそれに倣う

menu_file->Append(ID_MENU_EXIT, "終了\tCtrl+Q");

「wxID_ANY」ではなく、独自定義の「ID_MENU_EXIT」なのはイベントハンドルで必要になるから

イベントハンドル(その1)

GUIのプログラムは基本イベント駆動型となる
ユーザーの操作でイベントが発生して、何らかの処理が実行されることになる
したがって、イベントと処理を紐づけ(Bind)する必要がある

具体的にはこの部分

    //メニューの終了を押したらプログラム終了
    Bind(wxEVT_MENU, [=](wxCommandEvent& event)
    {
        Destroy();
    }, ID_MENU_EXIT);

「Bind」関数で「メニューアイテム押下のイベント」と「関数オブジェクト」を紐づけている
「ID_MENU_EXIT」を指定しているのは、どのメニューアイテムかの判別のため

関数オブジェクトの引数は適切なイベントの型を一つ持つ必要がある
この引数にはイベント発生時の様々な情報が含まれる

※関数オブジェクトを引数に受ける必要があるので「Bind」関数はテンプレートで定義されている

少し複雑なメニューバー

コードは示さないが複雑なメニューも表現できる

image.png

ステータスバー

特に難しいところはない
表示する内容を変えたい場合は適宜「SetStatusText」関数を呼び出せばいい

5. widgetをウィンドウ上に配置する

ちょっと長いが最後だ、頑張ろう

ソースコード

frame.h
#include <wx/wx.h>

class myFrame : public wxFrame
{
public:
    //基底クラスと同じ引数を持つコンストラクタ(宣言)
    myFrame
    (
        wxWindow* parent,
        wxWindowID id,
        const wxString& title,
        const wxPoint& pos = wxDefaultPosition,
        const wxSize& size = wxDefaultSize,
        long style = wxDEFAULT_FRAME_STYLE,
        const wxString& name = wxFrameNameStr
    );

private:
    wxMenuBar* menu_bar;
    wxMenu* menu_file;

    wxPanel* panel;
    wxTextCtrl* textCtrl;
    wxButton* button_uc;
    wxButton* button_lc;
};
frame.cpp
#include "Frame.h"

 //基底クラスと同じ引数を持つコンストラクタ(定義)
myFrame::myFrame
(
    wxWindow* parent,
    wxWindowID id,
    const wxString& title,
    const wxPoint& pos,
    const wxSize& size,
    long style,
    const wxString& name

) : wxFrame(parent, id, title, pos, size, style, name)//基底クラスへの委譲コンストラクタ
{
    //メニューアイテムに割り当てるIDを列挙型を宣言しておく
    enum ID_MENU
    {
        ID_MENU_EXIT,
    };

    //メニューの構築
    menu_file = new wxMenu;
    menu_file->Append(ID_MENU_EXIT, "終了\tCtrl+Q");

    //メニューバーの構築とメニューバーにメニューをセット
    menu_bar = new wxMenuBar;
    menu_bar->Append(menu_file, "ファイル(&F)");

    //このWindowにメニューバーをセット
    SetMenuBar(menu_bar);

    //メニューの終了を押したらプログラム終了
    Bind(wxEVT_MENU, [=](wxCommandEvent& event)
    {
        Destroy();
    }, ID_MENU_EXIT);

    //ステータスバー
    CreateStatusBar();
    SetStatusText("ステータスバーはここ");

    //パネル(親widgetはこのthisつまりmyFrame)
    panel = new wxPanel(this, wxID_ANY);

    //テキストコントロール(親widgetはpanel)
    textCtrl = new wxTextCtrl(panel, wxID_ANY);

    //ボタン(親widgetはpanel)
    button_uc = new wxButton(panel, wxID_ANY, "UpperCase");
    button_lc = new wxButton(panel, wxID_ANY, "LowerCase");

    //サイザー(垂直方向に詰める)
    auto vsizer = new wxBoxSizer(wxVERTICAL);

    //サイザー(水平方向に詰める)
    auto hsizer = new wxBoxSizer(wxHORIZONTAL);

    //レイアウトを整える
    panel->SetSizer(vsizer);

    vsizer->Add(textCtrl, 0, wxALIGN_CENTER);
    vsizer->Add(hsizer, 0, wxALIGN_CENTER);
        hsizer->Add(button_uc, 0, wxALIGN_CENTER);
        hsizer->Add(button_lc, 0, wxALIGN_CENTER);

    //UpperCaseボタンを押したら、TextCtrlの文字列をUpperCaseする
    button_uc->Bind(wxEVT_BUTTON, [=, this](wxCommandEvent& event)
    {
        //ダイアログ(親widgetはこのthisつまりmyFrame)
        auto dialog = wxMessageDialog(this, "テキストをUpperCaseしますか?", "タイトル", wxCANCEL);

        //ダイアログを表示して、OKボタンを押したらテキストの変換を実施する
        if(dialog.ShowModal() == wxID_OK)
        {
            auto text = textCtrl->GetValue();
            text.UpperCase();
            textCtrl->SetValue(text);
        }
    });

    //LowerCaseボタンを押したら、TextCtrlの文字列をLowerCaseする
    button_lc->Bind(wxEVT_BUTTON, [=, this](wxCommandEvent& event)
    {
        //ダイアログ(親widgetはこのthisつまりmyFrame)
        auto dialog = wxMessageDialog(this, "テキストをlowerCaseしますか?", "タイトル", wxCANCEL);

        //ダイアログを表示して、OKボタンを押したらテキストの変換を実施する    
        if(dialog.ShowModal() == wxID_OK)
        {
            auto text = textCtrl->GetValue();
            text.LowerCase();
            textCtrl->SetValue(text);
        }
    });
}
app.h
#include <wx/wx.h>

//wxAppの派生クラスを定義してOnInit()をオーバーライド
class myApp : public wxApp
{
public:
    virtual bool OnInit() override;
};
app.cpp
#include "App.h"
#include "Frame.h"

//真のmain関数(エントリポイント)を生成するマクロ
wxIMPLEMENT_APP(myApp);

//事実上のmain関数
bool myApp::OnInit()
{
    //「カスタマイズされた」ウィンドウを生成
    auto frame = new myFrame(nullptr, wxID_ANY, "ウィンドウのタイトル");

    //ウィンドウを表示
    frame->Show();
    
    //trueでwxWidgetsのメインループへ、falseでプログラム即終了
    return true;
}

コンパイル

 g++ -O2 -finput-charset=CP932 -fexec-charset=CP932 -static-libgcc -static-libstdc++ -mthreads -mwindows App.cpp Frame.cpp -o App.exe -I C:\wxWidgets\wxWidgets-3.2.2.1\include -I C:\wxWidgets\wxWidgets-3.2.2.1\lib\gcc_lib\mswu -L C:\wxWidgets\wxWidgets-3.2.2.1\lib\gcc_lib -lwxmsw32u -lwxmsw32u_gl -lwxscintilla -lwxtiff -lwxjpeg -lwxpng -lwxzlib -lwxregexu -lwxexpat -lkernel32 -luser32 -lgdi32 -lcomdlg32 -lwinspool -lwinmm -lshell32 -lshlwapi -lcomctl32 -lole32 -loleaut32 -luuid -lrpcrt4 -ladvapi32 -lversion -lws2_32 -lwininet -loleacc -luxtheme

実行結果

image.png

image.png

image.png

image.png

image.png

サイザー

widgetのレイアウトにはサイザーを使う
ウィンドウのサイズを変更したときなど、サイザーが追従してwidgetのレイアウトをコントロールしてくれる

    //サイザー(垂直方向に詰める)
    auto vsizer = new wxBoxSizer(wxVERTICAL);

    //サイザー(水平方向に詰める)
    auto hsizer = new wxBoxSizer(wxHORIZONTAL);

    //レイアウトを整える
    panel->SetSizer(vsizer);

    vsizer->Add(textCtrl, 0, wxALIGN_CENTER);
    vsizer->Add(hsizer, 0, wxALIGN_CENTER);
        hsizer->Add(button_uc, 0, wxALIGN_CENTER);
        hsizer->Add(button_lc, 0, wxALIGN_CENTER);

「wxBoxSizer」クラスは最もよく使うサイザーだ
コンストラクタに「wxVERTICAL」か「wxHORIZONTAL」を渡して、widgetを詰める方向を決める

サイザーにwidgetを追加するときは「Add」関数を使う
widgetだけでなくサイザーも受け取れるので構造を入れ子にすることもできる
第二引数以降はレイアウトに関するパラメーターだがここでは割愛する

※サイザーの詳細
https://docs.wxwidgets.org/3.2/overview_sizer.html

イベントハンドル(その2)

どのオブジェクトの「Bind」関数を呼び出しているか意識してほしい

    //LowerCaseボタンを押したら、TextCtrlの文字列をLowerCaseする
    button_lc->Bind(wxEVT_BUTTON, [=, this](wxCommandEvent& event)
    {
        //処理は省略
    });

親widgetの「Bind」関数ではなく、子widgetの「button_lc->Bind」関数を呼び出している
子widgetに直接紐づけているので、windowIDを指定は不要

そもそもすべてのイベントが親widgetに伝搬するわけではない
「wxCommandEvent」は汎用的なイベントで伝搬するので、メニューの押下イベントを親widgetで処理することができたのである

※例えば「wxGrid」クラスはより特化した「wxGridEvent」を発生させるが、親widgetには伝搬しない

小難しいことを考えたくなければ、子widgetの「Bind」関数でイベント処理するのがいいだろう

※イベントとイベントハンドリングの詳細
https://docs.wxwidgets.org/3.2/overview_events.html

ダイアログ

ダイアログにも触れておく

        //ダイアログ(親widgetはこのthisつまりmyFrame)
        auto dialog = wxMessageDialog(this, "テキストをlowerCaseしますか?", "タイトル", wxCANCEL);

        //ダイアログを表示して、OKボタンを押したらテキストの変換を実施する    
        if(dialog.ShowModal() == wxID_OK)
        {
            auto text = textCtrl->GetValue();
            text.LowerCase();
            textCtrl->SetValue(text);
        }

ここで使われている「wxMessageDialog」クラスは「wxDialog」クラスの派生クラスとなる

「ShowModal」関数でダイアログを表示する
ダイアログが閉じられるまでは親のウィンドウは操作不能になる
※「Modal」なウインドウと呼ばれる

「ShowModal」関数の戻り値はOKボタンを押したかキャンセルボタンを押したかの判定に使える
またカスタマイズしてメンバ変数を追加してそれを取得しても良い

「wxDialog」クラスの派生クラスを自分で定義してもいいが、下記のような便利なダイアログが用意されている
せっかく用意してくれているのだから便利に使わせてもらおう

  • wxColourDialog
  • wxDirDialog
  • wxFileDialog
  • wxFindReplaceDialog
  • wxFontDialog
  • wxGenericProgressDialog
  • wxProgressDialog
  • wxHtmlHelpDialog
  • wxMessageDialog
  • wxMultiChoiceDialog
  • wxNumberEntryDialog
  • wxPGArrayEditorDialog
  • wxPGArrayStringEditorDialog
  • wxPrintAbortDialog
  • wxPropertySheetDialog
  • wxRichTextFormattingDialog
  • wxRearrangeDialog
  • wxRichTextStyleOrganiserDialog
  • wxSingleChoiceDialog
  • wxSymbolPickerDialog
  • wxTextEntryDialog
  • wxPasswordEntryDialog
  • wxWizard

※メモリとダイアログの話(ダイアログは「new」でインスタンス化してないことに気づいたかな?)
https://wiki.wxwidgets.org/Avoiding_Memory_Leaks

その他

  • サンプルをコンパイルする
    実際に動かしてみるのは、つかえるwidget探しに役立つ

  • ドキュメントの読み方
    widgetのクラスごとにページが割かれているので必要になったら読みに行く
    • そのクラスの概要
    • スタイル
    • 関連するほかのクラス
    • 発生させるイベントの種類
    • publicなメンバ関数(つまり何ができるか)

※例としてwxTextCtrlのリンクを貼っておく

  • widgetのカスタマイズ
    widgetクラスにはvirtualかつprotectedで宣言されてるメンバー関数がある
    開発者にもアクセス可能なので、オーバーライドしつつその内部で少し動作を追加して元の関数を呼び出してやれば、ちょっとしたカスタマイズができる

  • wxWidgetsの改造
    ↑でどうしようもなくなったら、ライブラリのコードに手を入れるしかないが・・・
    ライセンス的に改造部分のソースコードを求められたら開示する義務が発生するかも?

参考

Programming Guides(公式ドキュメント)
https://docs.wxwidgets.org/3.2/page_topics.html

Hello World Example(公式ドキュメント)
https://docs.wxwidgets.org/3.2/overview_helloworld.html
公式のHallo World

wxWidgets の最小サンプル(qiitaの記事から、非常に参考になった)
https://qiita.com/mod_poppo/items/8e6baa50765e8573f883

wxWidgets tutorial(私が最初にやったやつ、良いチュートリアルだと思う)
https://zetcode.com/gui/wxwidgets/
※ただし、イベントハンドラへの登録にBindではなく今は非推奨なConnect使ってるので注意

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0