wxWidgetsでクロスプラットフォーム開発 ~ Visual Studio 2015への導入 ~

クロスプラットフォームなソフトを作りたいと思って探していると、wxWidgetsというものがあったので使ってみようということに。

###・What is wxWidgets?
クロスプラットフォームでGUIを作れるC/C++向けのライブラリ。
特徴は何と言っても「各OSのUIに溶け込める」ということ。
これはwxWidgetsが極力UIをOS本来の機能を使って描画してるから(ウィンドウ、ボタンなど)
そのためパッと見ではOSネイティブのアプリと違いが判らない。

wxWidgetsを使っている有名なアプリの一つに、波形編集ソフトの[Audacity](https://ja.osdn.net/projects/audacity/)がある。
![audacity.png](https://qiita-image-store.s3.amazonaws.com/0/155534/0a64597a-fc4c-475b-d042-2525ec542663.png)


##導入手順

Visual Studio 2015がインストールされている前提で話を進める

###１．wxWidgetsのダウンロード
[ダウンロードページ](http://www.wxwidgets.org/downloads/)にアクセスする。
執筆時点の最新安定板は3.0.2なので、それのWindows用ソースをダウンロードする(zip,7zは好みで)

![wx1.png](https://qiita-image-store.s3.amazonaws.com/0/155534/d493e77b-0b6f-756d-416f-6edbaca8bcd5.png)


###２．wxWidgetsのビルド
ダウンロードしたアーカイブを適当な場所に解凍する。
ここでは「C:\wxWidgets」に解凍したものとして進める。

次に、「wxWidgets\build\msw\wx_vc12.sln」をVS2015で開く。
すると、ビルド用のソリューションが読み込まれる。
あとは「<b>ソリューションのビルド</b>」を実行するだけでひとりでにlib,dllなどが出来上がる。
「Debug」「Release」「DLL Debug」「DLL Release」の各オプションについてコンパイルしておく。

※なお、このビルドプロジェクトではデフォルトでCRTを動的リンクするようになているので、
作成したプログラムで静的リンクをしたい場合はwxWidgetsのほうも変更しておく(各プロジェクトについて)

###３．環境変数の設定
WXWINという環境変数にwxWidgetsを解凍したディレクトリを設定しておく。
![wx4.png](https://qiita-image-store.s3.amazonaws.com/0/155534/f36c3be2-9679-85af-b404-85e9ebbcf79f.png)

<br>
*******

以上で導入は完了。なんと簡単なことだろうか！


##サンプルプロジェクトの作成
HelloWorld的なものを作ってみる。

###１．プロジェクトの作成
普通のWin32プロジェクトを作る。
![wx2.png](https://qiita-image-store.s3.amazonaws.com/0/155534/f0935e17-2f72-3e76-9c5d-0f1d7ee2ed09.png)
<br>
プロジェクトの種類は「Windows アプリケーション」で良いが、空のプロジェクトにしておく。
そして何より重要なのは「<b>Security Development Lifecycle(SDL)チェックを無効にする</b>」ことだ。
これをしないとコンパイルができない。
![wx3.png](https://qiita-image-store.s3.amazonaws.com/0/155534/50dc1e39-ec66-662e-4243-78a09a89f738.png)

プロジェクトができたら、プロパティからディレクトリの設定をする。

・インクルードパスには「<b>\$(WXWIN)\include;\$(WXWIN)\include\msvc</b>」を追加する
・ライブラリパスには、wxWidgetsを静的リンクするなら「<b>\$(WXWIN)\lib\vc_lib</b>」、動的リンクするなら「<b>\$(WXWIN)\lib\vc_dll」を追加する

なお、ライブラリパスには、Debugに動的リンク、Releaseに静的リンクを設定することをお勧めする。
これは、Debugビルドで静的リンクをするとリンクに異常に時間がかかるためである。


###２．プログラムの作成
[ここ](http://docs.wxwidgets.org/trunk/overview_helloworld.html)の最後のソースをコピペしてみる。

```cpp
// wxWidgets "Hello world" Program
// For compilers that support precompilation, includes "wx/wx.h".
#include <wx/wxprec.h>
#ifndef WX_PRECOMP
    #include <wx/wx.h>
#endif
class MyApp: public wxApp
{
public:
    virtual bool OnInit();
};
class MyFrame: public wxFrame
{
public:
    MyFrame();
private:
    void OnHello(wxCommandEvent& event);
    void OnExit(wxCommandEvent& event);
    void OnAbout(wxCommandEvent& event);
};
enum
{
    ID_Hello = 1
};
wxIMPLEMENT_APP(MyApp);
bool MyApp::OnInit()
{
    MyFrame *frame = new MyFrame();
    frame->Show( true );
    return true;
}
MyFrame::MyFrame()
        : wxFrame(NULL, wxID_ANY, "Hello World")
{
    wxMenu *menuFile = new wxMenu;
    menuFile->Append(ID_Hello, "&Hello...\tCtrl-H",
                     "Help string shown in status bar for this menu item");
    menuFile->AppendSeparator();
    menuFile->Append(wxID_EXIT);
    wxMenu *menuHelp = new wxMenu;
    menuHelp->Append(wxID_ABOUT);
    wxMenuBar *menuBar = new wxMenuBar;
    menuBar->Append( menuFile, "&File" );
    menuBar->Append( menuHelp, "&Help" );
    SetMenuBar( menuBar );
    CreateStatusBar();
    SetStatusText( "Welcome to wxWidgets!" );
    Bind(wxEVT_MENU, &MyFrame::OnHello, this, ID_Hello);
    Bind(wxEVT_MENU, &MyFrame::OnAbout, this, wxID_ABOUT);
    Bind(wxEVT_MENU, &MyFrame::OnExit, this, wxID_EXIT);
}
void MyFrame::OnExit(wxCommandEvent& event)
{
    Close( true );
}
void MyFrame::OnAbout(wxCommandEvent& event)
{
    wxMessageBox( "This is a wxWidgets' Hello world sample",
                  "About Hello World", wxOK | wxICON_INFORMATION );
}
void MyFrame::OnHello(wxCommandEvent& event)
{
    wxLogMessage("Hello world from wxWidgets!");
}
```

で、ビルドして実行。警告がたくさん出るが気にしない。

![wx5.png](https://qiita-image-store.s3.amazonaws.com/0/155534/3f111464-28d6-b7eb-00fe-fb567922239f.png)
うまく動いているようだ。

###まとめ
導入も大して煩雑でないのにクロスプラットフォームなGUIが書けるとはなかなか強い。
作るのが楽しそうだ。