=[広告]======================================================================  『英語学習が変わる!』ペット型ロボットと英会話レッスン! http://px.a8.net/svt/ejp?a8mat=IGP80+DN6NMI+5K+1NL9XV ============================================================================= ★☆=====================================================================☆★ 【wxWindowsでGUIプログラミング】 第9号: 調子笛ソフト改造(3) 2004.02.26(Thu) ★☆=====================================================================☆★  こんにちは,二条です。  当メルマガでも紹介している調子笛ソフトの改造が一通り終わりました。 できあがったソースとWindows実行ファイルを http://members10.tsukaeru.net/ariera/soft/fue.html にて配布していますので,興味のある方はダウンロードしてみてください。 *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*- [1] サンプルプログラム 調子笛ソフト改造(3) *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-  こちらは,今までの内容が簡単すぎるという方のために,少し複雑なサンプルを作ってみるコーナーです。(初心者の方でも,ソースをコピー&ペーストするだけで,とりあえず動くものは作れます。)  今回は,前回までの内容を前提としていますので,初購読の方はお手数ですが,バックナンバーを参考にしてください。  今回は「実行画面から設定ダイアログを出し,各音名と周波数が変更できるようにする」という改造の中から,設定状態を保存するwxConfigクラスについて解説します。  今回のソースコードはバックナンバー置き場にはありません。興味のある方は冒頭にある調子笛ソフト置き場からダウンロードしてください。 ------------------------------------------------------------------------ (1)wxConfigクラスって何?  wxConfigクラスとは,アプリケーションの設定を保存・読み込みするためのクラスです。厳密には,wxConfigというクラスはなく,wxConfigBaseを基本クラスとして,wxIniConfig, wxFileConfig, wxRegConfigなどといったクラスがあり,wxConfigはWin32ではwxRegConfig,Win16ではwxIniConfig,UnixではwxFileConfigにtypedefされているようです。  ということは,Win32でwxConfigを使って設定を保存すると内容がレジストリに書き込まれるということです。個人的にレジストリは好きではないので,今回はwxConfigではなくwxFileConfigを使ってみることにしました。  これを使うと,ファイル出入力について深く考えずに設定ファイルを扱うことができます。 ------------------------------------------------------------------------ (2)周波数設定を保存するクラスを作る  改造前の調子笛ソフトでは,各音の周波数等は固定だったので,fue_freq.h というファイルに周波数等の配列を置いてありました。今回は周波数等を可変にするので,設定を保存するクラス FueFreq を作りました。それに伴って,fue_freq.h の中身は,単なる周波数等の配列から,class FueFreq のクラス宣言となります。このクラスには,現在の周波数等の設定を保存する配列と,wxConfigBaseのポインタ,各メンバー変数にアクセスするためのメソッドを用意します。  デフォルトの周波数や,初期設定ファイル名等の固定項目は,FueFreqクラスのstatic変数とするのがすっきりしているのですが,static const にすると初期化や参照がいろいろ面倒そうなので,思考放棄してグローバル変数として fue_freq.h に書いておきました。  wxConfigのインスタンスは,wxConfigBase::Set(wxConfigBase*), wxConfigBase::Get() というstatic関数を使うことによって,アプリケーションのどこからでも参照可能なようにグローバル化することもできるようなのですが,今回はwxConfigに格納するのは周波数関連の設定だけで,周波数設定はFueFreqクラスに格納するという設計ですので,グローバル化せずにFueFreqクラスのメンバーとしておきます。 ------------------------------------------------------------------------ (3)wxFileConfigの初期化  wxFileConfigのインスタンス作成は fue_freq.cpp の21行目あたり,FueFreqクラスのコンストラクタで行っています。 config = new wxFileConfig(_T(""), _T(""), _T(confname), _T(""), wxCONFIG_USE_LOCAL_FILE|wxCONFIG_USE_RELATIVE_PATH);  コンストラクタの第1引数はアプリケーション名,第2引数はベンダー名,第3引数はローカルファイル名,第4引数はグローバルファイル名,第5引数は様々な設定です。  この引数はwxConfigBaseのコンストラクタにそのまま渡されるものです。  アプリケーション名はレジストリを使う場合はキー名,ファイルを使う場合でそのファイル名が省略されていたらそのファイル名となります。省略した場合はwxApp::GetAppName()で取得できるアプリケーション名が設定されます。どちらにしても,ここでは必要ないので空文字列にしておきます。  ベンダー名はレジストリのアプリケーション名に追加されるもののようですが,これもここでは必要ありません。  次のローカルファイル名とグローバルファイル名の違いは,実はよくわかっていません。wxWindowsのヘルプファイルによると,configクラスの種類(wxIniConfig, wxFileConfigなど)によってどちらが必要かが違うようです。とりあえず,WindowsでwxFileConfigクラスを使う場合は,ローカルの方にしないといけないようですので,ローカルファイルの方に名前を設定します。confnameはfue_freq.hで設定されているグローバル変数で,"fue.ini" が入っています。  最後の設定は,wxCONFIG_USE_LOCAL_FILEまたはwxCONFIG_USE_GLOBAL_FILEと, wxCONFIG_USE_RELATIVE_PATH,wxCONFIG_USE_NO_ESCAPE_CHARACTERS のORで設定できるようです。 見たまんまですがwxCONFIG_USE_LOCAL_FILEはローカルファイルを使う, wxCONFIG_USE_GLOBAL_FILEはグローバルファイルを使うという意味です。 wxCONFIG_USE_RELATIVE_PATHは相対パスを使う(絶対パスではなく)という意味で,ここでは実行ファイルと同じ場所に設定ファイルを作りたいので,相対パス設定とします。 wxCONFIG_USE_NO_ESCAPE_CHARACTERSは,バックスラッシュ(\)などの特殊文字をエスケープ(\\)しないという設定で,wxWindowsで作られていないプログラムで設定ファイルを読む場合のために用意されているようです。これを設定した場合は特殊文字の処理は自分で何とかしないといけないようですが,今回はwxFileConfigのインスタンスを通してしか設定ファイルを使わないので,気にしないことにします。 ------------------------------------------------------------------------ (4)設定ファイルの読み書き  ソースコード上では,インスタンス作成の次に設定ファイルを読むコードが続きますが,先に書き込みの方を説明します。  fue_freq.cpp の41行目あたりで呼び出しているsave_config_freq(定義部分は100行目あたり)の中でも書き込みを行っていますが,その次の行 config->Write(_T("LastPrompt"), 1); が一番簡単な設定データの書き込みです。Write()の第1引数がキー,第2引数が値になります。これはファイルでは LastPrompt=1 のように記述されます。第1引数はwxString型,第2引数はwxString,long, double, bool のどれかの型となります。つまり,wxConfigで保存できるのはこれらの単純な型だけで,オブジェクトをバイナリのまま保存するといった機能はありません。  ここではチェックしていませんが,この関数は成功したらTRUE,失敗したらFALSEを返します。  また,キーはパスつきで設定することができます。 config->Write(_T("/Path/LastPrompt"), 1); または config->Write(_T("Path/LastPrompt"), 1); と書くと,レジストリではパスの意味がはっきりするのでしょうが,ファイルではこうなります。 [Path] LastPrompt=1 config->Write(_T("/Path/Hoge/LastPrompt"), 1); とすると,以下のようになります。 [Path] [Path/Hoge] LastPrompt=1  パスはSetPath()を使って設定することもできます。 wxString oldPath = config->GetPath(); config->SetPath("/Path/Hoge"); config->Write(_T("LastPrompt"), 1); config->SetPath(oldPath); これでも"/Path/Hoge/LastPrompt"を指定したのと同じように書きこまれます。 最後にパスを元に戻すのがミソのようです。  読み込み部分は同じファイルの24行目〜 wxString str; if(config->Read(_T("LastPrompt"), &str)) { :  のところで行っています。第1引数は読み込む設定のキー,第2引数は値を読み込む変数のアドレスです。ここの型にはwxString,long, double, boolのどれかを入れることができます。また第3引数としてデフォルト値(設定がない場合の値)を入れることもできます。読み込みに成功したらTRUE, 失敗したらFALSEを返します。  "LastPrompt"というキーは書き込みが正常に終わったことを示すために,すべての設定を書きこんだあとに1を書きこんでいます。読み込むときには,"LastPrompt"の値があれば周波数等の設定をファイルから読み込み,値がなければデフォルトの設定とします。  これだけで設定のファイル保存・読み込みができてしまうので,とても簡単です。こんなに簡単でいいのだろうかと思ってしまったり…… ------------------------------------------------------------------------  今回はここまでにします。次回はwxConfigをユーザー設定のインポート・エクスポートに流用する話と,設定画面であるwxDialogを継承したクラスについて説明し,「調子笛ソフト改造」の解説を終わりにしたいと思います。  その後は別のプログラムを一から作って行きたいと思います。どんなプログラムにするかは未定ですが,ネット関連のものにしようかと考えています。何かご希望がありましたらお気軽にご連絡ください。 =[広告]======================================================================  ◇就職・転職にだんぜん有利! 社内での注目度もUP! http://px.a8.net/svt/ejp?a8mat=NXRD3+758T6+3UW+61RIB ============================================================================= *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*- [2] ワンポイント解説 ダイアログエディタを使う(3) *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-  こちらは,初心者向けのワンポイント解説コーナーです。  今回は,前回までの内容を前提としていますので,初購読の方はお手数ですが,バックナンバーを参考にしてください。 ------------------------------------------------------------------------ (1)「閉じる」ボタンをつける  だいぶん時間が空いてしまいましたが,第7号で作成したtest.wxr と test.cpp というファイルを発掘してみてください。はじめての方は第6号,第7号を参考にしてファイルを作ってください。  まず,test.cpp の30行目あたり,TestFrameクラスの定義の下に以下の5行を追加してください。 class MyDialog : public wxDialog { private: DECLARE_EVENT_TABLE() };  これは,wxDialogというクラスを継承して,MyDialogというクラスを作っています。  そして,元の51行目あたりの wxDialog *dialog = new wxDialog; を MyDialog *dialog = new MyDialog; と書き換えてください。  「閉じる」ボタンを動作させるには,「閉じるボタン」と「閉じるという処理」を関連づける必要がありますが,これを行うにはwxDialogのままではダメで,これを継承した新しいクラスを作る必要があります。  DECLARE_EVENT_TABLE()は,関連付けを行うという宣言です。  最後に,test.cppの一番最後に以下の3行を追加してください。 「101」の部分には,test.wxr から適当なボタンを選んで,その"control = ["の次にある数字を書きこんでください。この数字はオブジェクトIDと呼ばれるもので,ボタンを特定するのに使います。  この部分で,101のボタンを押したらMyDialog::OnCancelという関数を実行するという関連付けを行っています。 BEGIN_EVENT_TABLE(MyDialog, wxDialog) EVT_BUTTON(101, MyDialog::OnCancel) END_EVENT_TABLE()  これでコンパイル&リンクして,実行してみてください。EVT_BUTTONで設定したボタンを押すと,ダイアログが閉じるはずです。相変わらずアプリケーションの枠の方は閉じませんので,「×」ボタンで終了させてください。  上で設定したMyDialog::OnCancelという関数は,親クラスのwxDialog::OnCancelをそのまま呼び出しているのですが,これは test.cppの dialog->ShowModal(); の戻り値として,wxID_CANCEL を返してダイアログを閉じるという関数です。OnOKとすると,戻り値はwxID_OKとなります。  今回のプログラムでは,戻り値は使っていませんので,どちらでもダイアログを閉じるだけで動作は変わりません。 ------------------------------------------------------------------------  今回はここまでにします。  次回はダイアログを閉じるだけでなく,アプリケーション全体を終了させるボタンを作成します。 *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*- [3] 番外編 Borland C++ の環境設定 *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-  読者の方から,Borland C++(以下bcc)でのwxの使い方について質問を受けたので,この機会にうちにもbcc環境を作っておこうと作業をはじめたら,思わぬところでハマりました。あまり役にはたたないかもしれませんが,アホな笑い話だと思ってお読みくださいませ。 ------------------------------------------------------------------------ (1)環境 ●wxWindowsは,既に展開してある2.4.0を使います。  (インストールパスは C:\wxWindows-2.4.0) ●bccは既にインストール済みのフリー版Borland C++ Compiler 5.5を使います。 ●OSはWinXPです。 ------------------------------------------------------------------------ (2)手順 ●環境変数WXWINの設定をします。 コマンドプロンプトをたちあげて, > set WXWIN=C:\wxWindows-2.4.0 で完了。 install.txtに「C:\wxWindows-2.4.0」とか「Program Files」のように,スペースと-が入っていてはダメで,「C:\wxwind~1.4」のような16ビットDOSのファイル名で書けばOKと書いてありますが,とりあえず無視。 ●ライブラリのコンパイルをします。 上でたちあげたコマンドプロンプトで > cd C:\wxWindows240Bcc\src\msw > make -f makefile.b32 ん??makefileの書式が違うとか言って怒られます。 よく考えたらデフォルトでbccを使うようになっていないため,MinGWのmakeを呼んでいるようです。 なので,パスを設定してやりなおし。 > set PATH=C:\borland\bcc55\Bin;%PATH% > cd C:\wxWindows240Bcc\src\msw > make -f makefile.b32 これでうまくいきました。 C:\wxWindows-2.4.0\lib\wx32ds.lib ができています。 ●サンプルをコンパイルします。 > cd C:\wxWindows-2.4.0\samples\minimal > make -f makefile.b32 ここでリンカに怒られます。よく見ると「-」をパスの一部ではなく何か別の特別な文字と認識してくれるようです。 最初のWXWINの注意書きを無視したのがいけなかったようです。 まず,注意書きの通り「set WXWIN=C:\wxwind~1.4」にしてみましたが,これはWin9x系だけの話で,NT系(2000,XP)ではパスとして認識されないのでダメです。 次に「set WXWIN="C:\wxWindows-2.4.0"」のように""で囲んでみましたが,makefileに $(WXDIR)\include\wx\msw\wx.rc などと書いてあるようなのでやっぱりダメです。 makefileの「$(WXDIR)\include\wx\msw\wx.rc」のようなところを全部探し出して""で囲んでみようかと思ったのですが,面倒なので「wxWindows-2.4.0」のディレクトリ名を「wxWindows240Bcc」に変えて最初からやりなおしたら,サンプルまでうまくコンパイルできました。  というわけで,注意書きを無視してはいけませんというお話でした。  しかし,bccでのコンパイルはとってもはやいです。MinGWを使うと,ライブラリをコンパイルするのには猫舌の私がお茶を入れて飲み終わるぐらいの時間がかかるのに,bccでは一瞬にして終わりました。サンプルプログラムのコンパイル速度も格段に違います。  最近,MinGWを捨ててbccに乗り換えようかと本気で考えています。 ------------------------------------------------------------------------ 編集後記:  だんだん暖かくなってきました。花粉症の人には最悪な季節のようですが,花粉症もなく,寒いのが苦手な私にとっては嬉しい季節です。冬眠から覚めて春眠暁を覚えず……結局いつでも布団から抜け出せないことに変わりはありません。もしかして,最近話題の「睡眠障害」では??と自己チェックしてみましたが,やっぱり私の場合はただのナマケモノのようでした(笑) =[広告]====================================================================== ウザイけどちょっと気になる!? オークションで売られている情報を無料公開中 http://www6.ocn.ne.jp/~prize/free.html ============================================================================= ★☆=====================================================================☆★ メールマガジン:wxWindowsでGUIプログラミング 第9号 2004.02.26(Thu) 発行人:二条 ご意見・ご感想はこちらへ: ariera@members10.tsukaeru.net こちらからもメールが送れます http://members10.tsukaeru.net/ariera/other/form/form.cgi 解除・バックナンバーはこちらからどうぞ http://members10.tsukaeru.net/ariera/soft/wx.html マイサイト「気まぐれ歴史散歩」もよろしくお願いします http://members10.tsukaeru.net/ このメールマガジンは「まぐまぐ」を使って配信しています http://www.mag2.com/ ★☆=====================================================================☆★