2002/11/05
作る目標は、ダイアログ形式の画面が一つで構成されていて、長い処理の進捗を示すラベルと、キャンセルボタンだけの単純なもの。これをVC++で作ってみましょう。
ではとりあえずVisualStudioにて。
新規作成では、MFC AppWizard(exe)を選択
本当はWizardなんか使わない方が勉強になるんでしょうが、コンパイルやリンクオプションなどを全て自分で設定していかないといけなくなって本来の目的と違う所で挫折しちゃいそうなので、安易にWizardに頼ってしまいましょう!
OKをクリック
ダイアログを作成するので、「ダイアログ」を選択します。
次へ
バージョン情報や、ActiveXコンロールは今回は使わないので、できるだけシンプルに使わないチェックは、外しました。
次へ
「MFCの共有DLLを使用」にすると、EXEモジュールのサイズが小さくなります。これをスタティックライブラリに変更すると、EXEファイル内にライブラリを持ち込むそうで、共有DLLのバージョン互換性に悩まなくて良くなるそうですが、今は初期値のままにしましょ
次へ
これでプロジェクトを生成する準備ができました。ここで言っていることは、
クラスCLesson1Appというアプリケーションクラスと
クラスCLesson1Dlgというダイアログ用のクラスを下記の名前で生成する事を言っています。
CLesson1Dlgを選択状態にすると、基本クラス以外のファイル名などが変更できるようですが、今回は初期値のまま
終了をクリック
Wizardは、たくさんのファイルを吐き出しました。
主だった物から見ていきましょう。
そのほかヘッダーもCPPに対応して作成されているようですね。最後のReadMe.txt内に生成したファイルの詳しい(解る人にしか解らん)説明が載っていますので、無駄でも一読を。
この段階で一応動かす事ができます。けど、たぶん今はデバッグモードがカレントになっています。生成するexeなどが大きいサイズになるので、デバッグしないなら、リリースモードに変更してしまいましょう。
[F5]を押下すると、デバッグ情報を作成しないととかナンタラカンタラ聞いてきますが、無視してエイヤ〜
以下のフォームが出てくれば成功ですね
[OK]または[キャンセル]をクリックすれば、終了します。
さて、ここで基本的な仕組みを見てみましょう。本当に初歩的な事だけ。
lesson1.cppは何をしとるんじゃ?です
lesson1.cppの中をみると、解るものと解らんものがありますね。
わかるものだけを整理してみると、
CLesson1App::CLesson1App()
これはコンストラクターですね。
BOOL CLesson1App::InitInstance()
どうも初期化用のメソッドのようです。
このメソッド中に
CLesson1Dlg dlg;
m_pMainWnd = &dlg;
int nResponse = dlg.DoModal();
どうもこの青字の部分がダイアログをインスタンスを生成して、モーダルダイアログを表示しているようです。そういう事か。
ここで一つ気になることを実験してみましょう。VBで、今回のような時間のかかる処理を行なう場合、適宜DoEventsを入れないとボタンのイベントや、フォームの再描画が行われない事がありましたですね〜。VCでも同じような事になるのでしょうか。ではさっそく。
時間のかかる処理として5秒スリープを2回ループする処理としてみましょう。この処理をあるボタンクリックで走るようにします。また別のボタンを作って、そのボタンを押すと、メッセージボックスを表示するような処理を作ってみましょう。
まず簡単なメッセージボックス表示ボタンから。
ボタンを選択して、適当な大きさにドラッグします。
作成したボタンを右クリックからプロパティーを選択して、キャプションを下のように「メッセージ表示」としてみました」
作成したボタンをダブルクリックすると、メソッド名を聞いてきた後、自動的に対応するメソッドが作成されます。まるでVBみたいですが、実際は複雑そうな事をやってそうですね。クラスウィザードを見ると、オブジェクトID→メッセージ→メンバーメソッドというように対応付けがなされているようです。
今は気軽に、メッセージを出力する実装をしてみましょう
void CLesson1Dlg::OnButton1()
{
// TODO: この位置にコントロール通知ハンドラ用のコードを追加してください
AfxMessageBox("OnButton1");
}
[F5]を押下して試しに実行してみましょう。
次は、長い処理時間もどきです。さっきと同様に、Button2で作成してみましょう。
キャプションは“実行”と、してみました。
ダブルクリックをして、メッセージハンドラーメソッドを作成します。
void CLesson1Dlg::OnButton2() { // TODO: この位置にコントロール通知ハンドラ用のコードを追加してください int i; for(i=0;i<2;i++){ Sleep(1000); Beep(440,100); } }
Beep(440Hz、100ms)です。音叉代わりに使えそうです。これで、処理中であることが耳で確認できそうです。さて実験してみましょう。
2回目の音が鳴る前に“メッセージ”ボタンを押しても、メッセージボックスが表示されるのは、2回目のBeep音の後ですねてことは、処理中の時は他のボタンは受け付けてくれないって事が容易に想像できます。
今回作りたい物は、長い処理中にキャンセルしたいって事ですから、これじゃ〜処理が終わってからキャンセルされちゃう事になり、意味無いですね。う〜ん、やっぱりスレッド!をつかわなアカンな〜