★☆=====================================================================☆★ 【wxWindowsでGUIプログラミング】 第1号:Hello World をつくろう 2003.04.29(Tue) ★☆=====================================================================☆★ こんにちは,二条です。今年のゴールデンウィークは短いという噂ですが,皆様いかがお過ごしでしょうか? 私は家でごろごろしながらイラクの博物館を略奪する白昼夢を見ていたりします。ひとつでいいから遺跡の出土品を家に飾ってみたい…… wxWindowsの環境設定はお済みですか? まだの方は,創刊号を参考にしてぜひ環境を作ってみてください。 バックナンバーは,まぐまぐのサイト http://www.mag2.com/m/0000108320.htm で見ることができます。 また, http://members10.tsukaeru.net/ariera/soft/wx.html こちらにダウンロード用のテキストファイルも用意してありますので,今回からの方は参考にしてくださいませ。 今回は,月並みですが「Hello World」プログラムを作ってみます。コマンドラインと異なり,GUIでは「Hello World」にも様々な見せ方があります。簡単すぎてアホくさいと思わず,手を動かして実行ファイルをつくってみてください。 ------------------------------------------------------------------------ (1)とりあえず,コンパイルしてみよう。 まず,以下の内容を, HelloWorld.cpp とか適当に名前をつけて,適当な場所に保存してください。 専用の作業ディレクトリをつくったほうがよいでしょう。 // ここから /*01*/ #include "wx/wxprec.h" /*02*/ /*03*/ #ifndef WX_PRECOMP /*04*/ #include "wx/wx.h" /*05*/ #endif /*06*/ /*07*/ class HelloWorldApp : public wxApp /*08*/ { /*09*/ public: /*10*/ virtual bool OnInit(); /*11*/ }; /*12*/ /*13*/ DECLARE_APP(HelloWorldApp) /*14*/ /*15*/ IMPLEMENT_APP(HelloWorldApp) /*16*/ /*17*/ bool HelloWorldApp*/*/OnInit() /*18*/ { /*19*/ wxFrame *frame = new wxFrame((wxFrame*) NULL, -1, "Hello World"); /*20*/ frame->CreateStatusBar(); /*21*/ frame->SetStatusText("Hello World"); /*22*/ frame->Show(TRUE); /*23*/ SetTopWindow(frame); /*24*/ return true; /*25*/ } // ここまで 今回は,コンパイル・リンクオプションについて深く考えるのはやめて,wxWindowsについていたサンプルを使って手抜きしましょう。以下の説明では,wxWindowsをインストールしたディレクトリ(C:\wxWindows-2.4.0 など)を,(WXWIN)と表記します。 ※ Windows + MinGW の方は,(WXWIN)\samples\minimal\makefile.g95 を HelloWorld.cppを置いたディレクトリにコピーして,コピーしたファイルを書き換えます。書き換える場所は2箇所です。(パスの区切りは\ではなく/を使ったほうが無難です。) WXDIR = (WXWIN) TARGET = HelloWorld それから, HelloWorld.rc という名前のファイルを作成し, #include "wx/msw/wx.rc" の1行だけを書いてください。 そして,コマンドプロンプト(DOSプロンプト)をたちあげ, HelloWorld.cppを置いたディレクトリに移動してください。 まず,wxWindowsのライブラリを作成した場合と同じように, > (WXWIN)\src\mingw32.bat を実行します。 それから, > make -f makefile.g95 とすると,コンパイル・リンクできます。WXMAKINGDLL,FINALのオプションは,前回説明した,wxWindowsをコンパイルする場合と同じものが使えます。 ※ Linux の方は,makefile.g95 のかわりに makefile.unx をコピーし, PROGRAM = HelloWorld この部分を書き換えてください。 Linuxの場合は,rcファイルは不要です。 ※ Windows + VC++ の方は,(WXWIN)\samples\minimal\minimal.dsp と dsw を,HelloWorld.dsp, HelloWorld.dsw と名前を変えてコピーしてください。そして,dsw をダブルクリックしてVC++ をたちあげ,「プロジェクト」-「設定」で設定画面を出し,wxWindowsをコンパイルしたときと同じデバッグ/リリースを選んでください。「デバッグ」タブの実行ファイル名と,「リンク」タブの「オブジェクト/ライブラリモジュール」を書き換えてください。wxWindowsのライブラリは,zlib.lib, regex.lib, png.lib, jpeg.lib, tiff.lib, wxmsw.lib の6つですので,これらのパスを相対パスでも絶対パスでも構いませんので,前回作成したライブラリの場所を指すようにしておいてください。そして,ビルドすると,コンパイル・リンクできます。 ------------------------------------------------------------------------ (2)プログラムの解説 (1)のプログラムは,実行するとタイトルとステータスバーに「HelloWorld」と書いたウインドウが出るだけです。通常右上にある,最大化・最小化・閉じるボタンは,普通に動作すると思います。 このプログラムの1行目は,VC++などのプリコンパイルヘッダに対応したコンパイラのためのインクルードファイル,3〜5行目がプリコンパイルヘッダに対応していないコンパイラのためのインクルードファイルを読み込んでいます。 7〜11行目で,wxApp クラスを継承した HelloWorldApp クラスを定義しています。C++などのオブジェクト指向言語を使っている方にはおなじみの書き方だと思います。C言語しか使ったことがない方には,少しわかりにくいかもしれませんが,まあそういうものだと思ってください。 wxWindowsでGUIアプリケーションを作るには,まずwxApp クラスを継承したクラスを必ずひとつ作り,OnInit()というメソッド(メンバー関数)を用意する必要があります。OnInit()はアプリケーションの初期化時に呼ばれるメソッドです。OnInit()は,wxApp クラスで仮想関数(virtual)として定義されていますので,HelloWorldApp でオーバーライドすることになります。10行目でvirtualがついているのは,HelloWorldApp クラスを継承して新しいクラスをつくったときのためで,このプログラムでは必須ではありません。 また,ファイル名が HelloWorld.cpp だから,クラス名は HelloWorldApp にしなければならない,ということはありません。適当に,好きな名前をつけても構いません。 では,なぜ HelloWorldApp::OnInit() をプログラムの初期化時に呼べるのかというと,15行目の IMPLEMENT_APP で HelloWorldApp を指定しているからです。この IMPLEMENT_APP がプログラムのエントリーポイント(main関数やWinMain関数に相当するもの)で,アプリケーションクラスHelloWorldAppのインスタンスを作るためのマクロです。こういうところをマクロ化することで,Windows/Linuxといった環境の差を吸収しているらしいです。 説明が飛んでしまいましたが,13行目の IMPLEMENT_APP は,HelloWorldAppクラスのインスタンスにアクセスする関数 wxGetApp() を使えるようにするためのマクロです。このソースコードでは,wxGetApp() を使っていないので,なくても構いません。 ソースをヘッダファイルと実装ファイルに分ける場合は,13行目までがヘッダファイルの内容,15行目以降が実装ファイルの内容となります。 そして,17〜25行目が,HelloWorldApp::OnInit() の実装です。ここでは,最低一つのwxFrameかwxDialog(かそれを継承したクラス)をつくって,その中の一つをトップウインドウに設定する必要があります。通常のアプリケーションでは,wxFrameかwxDialogを継承したクラスを作って,そこにボタンなどの部品を配置していきますが,今回は画面上に何も置かないので,wxFrame をそのまま使っています。 19行目が,wxFrame クラスのオブジェクト(インスタンス,実体)を作っている部分です。引数は,親フレームなし,ウインドウID -1,タイトルが"Hello World",という意味です。ウインドウIDは,イベントと部品の関連づけに使うものですが,今回は使わないので-1にしておきます。 20行目でステータスバーを作成して,21行目でそこに "Hello World" の文字を書いています。 22行目でフレームを表示し,23行目でフレームをトップウインドウに設定しています。22行目を消してコンパイルすると,実行しても何も表示されませんが,プロセスは動いています。タスクマネージャ(Win)や ps と kill (Linux)でプロセスを終了させないと,起動したままになってしまいますので注意してください。 最後にtrueを返しているのは初期化が無事に終わったことを示しています。このメソッドがfalseを返せば,初期化に失敗したことになり,exit()等を呼ばなくてもアプリケーションは終了します。 ところで,19行目でnewしたframeはdeleteしなくていいの?と疑問に思う方も多いかもしれません。wxWindowsでは,トップウインドウにしたオブジェクトはアプリケーションが終了するときに消してくれるので,明示的に消す必要はありません。同じようにして,上の例では出てきませんが,wxFrameやwxDialogを継承したクラスのメンバー変数(ポインタ)として宣言され,そのクラス内で作られたオブジェクトは,親(フレームやダイアログ)クラスのインスタンスが破棄されるときに自動的に開放されます。 ------------------------------------------------------------------------ 今回はこれで終わりです。次回はボタンやメニュー,ダイアログボックスなどを使ってHelloWorld する予定です。 編集後記: 前回は1行80文字で整形しながら書いていたのですが,結構面倒だったので,今回はエディタの「折り返し」モードで全文を書いて,後で「整形」をかけることにしました。いつものエディタに「指定行数で改行」というメニューがあったので安心していたのですが,使ってみると「うぎゃぁぁ!」でした。タイトルなど,1行80文字以下で手動で入れた改行がすべて削除され,すべてを1行80文字に詰め込まれてしまったのです。 探せば高機能な整形用フリーソフトもあると思うのですが,探す気力がなかったのでPerlでいいかげんなスクリプトを書いてどうにか処理しましたが,日本語(多バイト文字)の罠で数十分はまりました。皆様も日本語の罠には気をつけてください。 次回発行日は2003.5.11(日)の予定です。 ★☆=====================================================================☆★ メールマガジン:wxWindowsでGUIプログラミング 第1号 2003.04.29(Tue) 発行人:二条 ご意見・ご感想はこちらへ: ariera@members10.tsukaeru.net 解除・バックナンバーはこちらからどうぞ http://members10.tsukaeru.net/ariera/soft/wx.html マイサイト「気まぐれ歴史散歩」もよろしくお願いします http://members10.tsukaeru.net/walk/ このメールマガジンは「まぐまぐ」を使って配信しています http://www.mag2.com/ ★☆=====================================================================☆★