Hirofumi Fujii Start Page

MinGW/MSYS での wxWidgets について

以前 WindowsでのEclipseによるC/C++プログラム開発 で wxWidgets/wxGrade を やろうとして失敗した。

今回は、wxGrade に頼らずに wxWidgets と、その application を 動かしてみる。今回の主な興味は UNICODE 対応状況をみたいということである。 かなりの予備知識が必要な気もするが、日本語まで含め、 一応すんなり動いたので、まとめておく。

Install

wxWidgets を MSYS/MinGW で install してみた。通常の(Unix-likeな)やりかた (configure;make;make install)で、すんなりできた。

  • wxWidgets-2.8.10
  • gcc 3.4.5 (mingw-vista special r3)

今回 install した machine は、733MHz 512K RAM Windows-2000(SP4) という 構成であるが configure に 約7分、make に約1時間10分、make install に約2分であった。 samples のいくつかも make してみたが、こちらもすんなり動いた。

が、、よく見たら、Unicode を enable にしてなかった。 というわけで、2009-09-14 Unicode を enable にして再 install。

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

愚痴、、

おもむろに sample を見てみたが、、

これ、Microsoft Foundation Class (MFC) を base にしてるみたいだ。 MFC は古くから(Windows 3.1 ぐらいから?)提供されているもので、 互換性を可能な限り保ったまま進化してきているので、今の C++ の 感覚からすると、ひどく古い感じがする(better C と言ったところか、、)。 まあ、これはもう一段 wrap すればよいと言えばよいのだが、、。

もう一つの問題は、今なら STL を使うところを全部自前でやっている点。 せっかく STL を使おうと思っても、こちらも、もう 一段 wrap しなければ 使えない。std::string 対応の wxString などは、80% 互換性を達している とのことらしいが、80% だろうが、90% だろうが、99.999% だろうが 互換で無い部分がある以上、user は気を使って wrap しなければならない。 std::iostream もしかり。

それに、wxString は Unicode 版か ANSI 版かで異なる。これも Microsoft の古くからの手法であるが、単一言語を扱うならともかく、 多国語対応にしようとすると、内部的には Unicode (あるいは もっと大きな set )にして、読み込む相手言語や encode 方法に より std::string と std::wstring を使いわけるなどということが 頻繁に生じる。つまり、std::string 、std::wstring どちらか一方で 済むというものではない。

と思ったが、configure option に enable-std_string とか enable-std_iostream とかある。これも付けておもむろに、、と思ったら、どうやら、これが default らしい。[2009-09-14 記]

また、namespace を使っていない、MACRO が多用されているのも問題。 名前や MACRO が global space に置かれてしまうと、例えば他の library との衝突が起こった時、それを回避するのが非常に困難になる。 wxWidgets の application は他の library を一切使うなというなら 話は別だが。

というわけで、ちょっと wxWidgets application を書く意欲がかなり 低下中。

自前の application を動かす

ま、愚痴っても始まらないので、まずは、 http://www.wxwidgets.org/docs/tutorials/hello.htm を動かしてみる。

書かれている通りに hworld.cpp を作る。

// hworld.cpp

#include <wx/wx.h>

class MyApp: public wxApp
{
	virtual bool OnInit();
};

class MyFrame: public wxFrame
{
public:
	MyFrame(const wxString& title, const wxPoint& pos,
		const wxSize& size);
	void OnQuit(wxCommandEvent& event);
	void OnAbout(wxCommandEvent& event);

	DECLARE_EVENT_TABLE()
};

enum
{
	ID_Quit = 1,
	ID_About,
};

BEGIN_EVENT_TABLE(MyFrame, wxFrame)
EVT_MENU(ID_Quit, MyFrame::OnQuit)
EVT_MENU(ID_About, MyFrame::OnAbout)
END_EVENT_TABLE()

IMPLEMENT_APP(MyApp)

bool
MyApp::OnInit()
{
	MyFrame* frame = new MyFrame(
		_T("Hello World"), wxPoint(50,50),
		wxSize(450,340));
	frame->Show(TRUE);
	SetTopWindow(frame);
	return true;
}

MyFrame::MyFrame(const wxString& title,
	const wxPoint& pos, const wxSize& size) :
	wxFrame((wxFrame*)0, -1, title, pos, size)
{
	wxMenu* menuFile = new wxMenu;
	menuFile->Append(ID_About, _T("&About..."));
	menuFile->AppendSeparator();
	menuFile->Append(ID_Quit, _T("E&xit"));

	wxMenuBar* menuBar = new wxMenuBar;
	menuBar->Append(menuFile, _T("&File"));

	SetMenuBar(menuBar);

	CreateStatusBar();
	SetStatusText(_("Welcome to wxWidgets!"));
}

void
MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
{
	Close(true);
}

void
MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
{
	wxMessageBox(_T("This is a wxWidgets Hello world sample"),
		_T("About Hello World"), wxOK | wxICON_INFORMATION, this);
}

次に書かれている通りに

g++ hworld.cpp `wx-config --libs` `wx-config --cxxflags` -o hworld

としてみる。おお、できた。

./hworld

おお、動いた。

が、ちょっと待て。この wx-cofig は、option で指定された 文字列を打ち出すもので、wxWidgets を install した各種 path やら 必要な library やらを打ち出してくる。で、よく見ると -lwsock32 となって いる!これは古い WINSOCK だ。configure で --disable-socket とか するべきだったか、、

自前の日本語 application を動かす

せっかく UNICODE 対応、std::string 対応で install した(はずな)ので、 一部日本語を入れてみる。UNICODE 対応なので、UNICODE を直接そのまま入れれば 表示できるはずである。また、wxString は(多分)std::wstring と等価に なるように設計されているのではないかと想像されるので、wxString を引数と しているところに std::wstring を入れる。というわけで、いささか強引では あるが、、

// jworld.cpp

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

class MyApp: public wxApp
{
	virtual bool OnInit();
};

class MyFrame: public wxFrame
{
public:
	MyFrame(const wxString& title, const wxPoint& pos,
		const wxSize& size);
	void OnQuit(wxCommandEvent& event);
	void OnAbout(wxCommandEvent& event);

	DECLARE_EVENT_TABLE()
};

enum
{
	ID_Quit = 1,
	ID_About,
};

BEGIN_EVENT_TABLE(MyFrame, wxFrame)
EVT_MENU(ID_Quit, MyFrame::OnQuit)
EVT_MENU(ID_About, MyFrame::OnAbout)
END_EVENT_TABLE()

IMPLEMENT_APP(MyApp)

bool
MyApp::OnInit()
{
	MyFrame* frame = new MyFrame(
		_T("Hello World"), wxPoint(50,50),
		wxSize(450,340));
	frame->Show(TRUE);
	SetTopWindow(frame);
	return true;
}

MyFrame::MyFrame(const wxString& title,
	const wxPoint& pos, const wxSize& size) :
	wxFrame((wxFrame*)0, -1, title, pos, size)
{
	wxMenu* menuFile = new wxMenu;
	menuFile->Append(ID_About, _T("&About..."));
	menuFile->AppendSeparator();
	menuFile->Append(ID_Quit, _T("E&xit"));

	std::wstring menutitle;
	menutitle.push_back((wchar_t)0x30d5);
	menutitle.push_back((wchar_t)0x30a1);
	menutitle.push_back((wchar_t)0x30a4);
	menutitle.push_back((wchar_t)0x30eb);

	wxMenuBar* menuBar = new wxMenuBar;
	menuBar->Append(menuFile, menutitle);

	SetMenuBar(menuBar);

	CreateStatusBar();
	std::wstring msg;
	msg.append(_T("wxWidgets "));
	msg.push_back((wchar_t)0x306b);
	msg.push_back((wchar_t)0x3088);
	msg.push_back((wchar_t)0x3046);
	msg.push_back((wchar_t)0x3053);
	msg.push_back((wchar_t)0x305d);
	msg.push_back((wchar_t)0x0021);
	SetStatusText(msg);
}

void
MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
{
	Close(true);
}

void
MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
{
	wxMessageBox(_T("This is a wxWidgets Hello world sample"),
		_T("About Hello World"), wxOK | wxICON_INFORMATION, this);
}

で、上と同様に

g++ jworld.cpp `wx-config --libs` `wx-config --cxxflags` -o jworld

としてみる。あ、できた。

./jworld

あ、動いた。日本語が表示されてる。


トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2009-09-16 (水) 12:16:32