C/C++ と wxWidgetsでGUIプログラミング

C/C++でGUIプログラム作ってみたく、WinAPI触るのもアレなので、ライブラリないかと探したら便利そげなwxWidgetsというクロスプラットフォームライブラリを見っけたのでHello Worldするまでを簡単にまとめてみる。
環境は

Windows 8.1
g++ 4.8.1
wxWidgets ver.3.0.2(現状最新)
MinGW + msys

VCの人はやり方がちがうらしいです。

導入

まずここからソースコードをDL
wxWidgets公式
WindowsならSource Codeって項目の中のWindows ~ってのをDL。

DLしたらmsysのhomeディレクトリ以下のどこでもいいので解凍。
そうしたらcdコマンドで入る。通常は

cd (上階層)\wxWidgets-3.0.2\

解凍時にフォルダ名を変えているなら適宜変更。

そうしたらmakeの前にconfigureだけども、
このサイト(参考)をみたらMinGWでは、

./configure --prefix=/mingw --enable-unicode --disable-debug --disable-shared --with-msw --with-regex

こういう感じに指定してあげる。

./configure -h

でほかのフラグも見れるので分かる人は適宜変更するといいかも。

コマンドを打つと勝手に分析してmakefileを作ってくれるのですこしまつ。
完了したら、

make

して

make install

でwxWidgetsの導入は終わり。ライブラリとかヘッダはこちらの環境だと

MinGW\msys\1.0\mingw

以下にインストールされてる。

HelloWorldプログラム

ここからはプログラムに移って、Hello Worldのプログラムはこんな感じになる。

#include <wx/wx.h>
enum {
	wxID_TEXT_LABEL
};

//ベースとなるクラス。wxAppクラスを継承する。OnInitはwxAppでvirtualに宣言されている。
class App : public wxApp{
public:
	bool OnInit();
};

//GUIとかを扱うクラス。wxFrameを継承。
class Window : public wxFrame{
public:
	Window(const wxString&,int,int);
	//引数にイベントの詳細がとんでくる。
	void OnClose(wxCommandEvent&);
private:
	//詳細はよくわからないけど必要。
	wxDECLARE_EVENT_TABLE();
};

//イベントの関連付け
//ウィンドウを閉じた時に実行する関数を関連付ける。
wxBEGIN_EVENT_TABLE(Window,wxFrame)
	EVT_MENU(wxID_EXIT,Window::OnClose)
wxEND_EVENT_TABLE()

/*
wxFrameの初期化とテキストを表示するためのクラスの作成
wxString型はいわゆるWinAPIのLPSTR型みたいな感じ。WinAPIでTEXTマクロを使うようにwxWidgetsではwxTマクロを使う。
wxID_ANYはなんにでも使えるwxWidgets側で用意されてる定数。普通はenumでユーザー側で定数は用意したほうがいいと思う。
wxDefaultPositionは定数。
wxSize((int)幅,(int)高さ)でサイズを指定できる。
*/
Window::Window(const wxString& title,int ws,int hs) :
	wxFrame(NULL,wxID_ANY,title,wxDefaultPosition,wxSize(ws,hs)){

	//文字を扱うクラス。
	//コンストラクタは第一引数に親クラスのポインタ、第二引数にID(enumしたやつ。)
	//第三引数にはデフォルトで表示される文字列。その後はサイズとか位置とかの指定が続くけど今回は無し。勝手にデフォルトになる。
	wxStaticText *text = new wxStaticText(this,wxID_TEXT_LABEL,wxT("HelloWorld!"));

	//ウィンドウを中央にする。
	Centre();
}

//引数をつかわないときはWXUNUSEDで明示してあげる。(なくてもうごく)
void Window::OnClose(wxCommandEvent& WXUNUSED(event)){
	//特に終了処理はないのでなにもせずClose
	Close(true);
}

//wxAppを継承したクラスを指定するとそのクラスをエントリーポイントとして実行される。今回の場合はAppクラス。
IMPLEMENT_APP(App);

//実行される時にまずはじめにこの関数が実行される。
bool App::OnInit(){
	//Windowクラスをインスタンス化してコンストラクタの引数でウィンドウのタイトルとウィンドウのサイズを指定する。
	Window *window = new Window(wxT("Hello"),100,60);
	//ウィンドウを見えるようにする。
	window->Show(true);

	return true;
}

だいたいはコメントでどんな感じの意味は書いています(正しいかはちょっと微妙…)

以下makefile

CXX=$(shell wx-config --cxx)
CFLAGS=-O2 -Wall

TARGET = HelloWorld
OBJECTS = main.o

# make all
.cpp.o:
	$(CXX) -c `wx-config --cxxflags` -o $@ $<

$(TARGET) : $(OBJECTS)
	$(CXX) $(CFLAGS) -o $(TARGET) $(OBJECTS) `wx-config --libs`

clean:
	@rm -f *.o $(TARGET).exe

これでmakeするとビルドしてくれる。

wx-config --libsとかをくくってるのは'じゃなくて`なのでお間違えなきよう。

実行ファイルはこれだけでも50MBとかなるので、サイズが気になる人は

strip *.exe

すると若干小さくなる。

参考とかリファレンス

ほかのクラスとかマルチスレッド化とかについては日本語が多くはないですが、
こことか
http://wxwindowsjp.osdn.jp/docs/html/wx/wx.htm
公式リファレンスを若干日本語化したこことか

http://murank.github.io/wxwidgetsjp/2.9.4/index.html
みるといいかも。

マルチスレッド化できるとむずかしいですが、いろいろ楽なのでやっといて損はないかも。
WinAPIさわらなくてもこんな感じにC/C++でGUIプログラムが作れるし、さらにマルチプラットフォームなので同じコードでLinuxでも動くのでとっても便利だと思った。

-std=c++11やるとコンパイルがエラーするので、std::threadとかC++11以降サポート系は使用不可を確認。