[[Hirofumi Fujii Start Page]]

* MinGW/MSYS での wxWidgets について [#kfeafdf7]
以前 [[WindowsでのEclipseによるC/C++プログラム開発]] で wxWidgets/wxGrade を
やろうとして失敗した。

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

* Install [#t27e7891]
** Install [#t27e7891]
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

** 愚痴、、 [#md85e4ba]
おもむろに 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 を動かす [#t9e2adf8]
ま、愚痴っても始まらないので、まずは、 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 を動かす [#oe786d27]
せっかく 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