CD Player の制作中に、インデックスデータの登録用ダイアログボックスがどうしても必要になりました。
Visual C++ では、ダイアログボックスは通常、リソースエディタでお絵かきをする感覚で作ることができます。
そして、ダイアログボックスを実際に作成するには
ダイアログボックスのクラスをCTestDlgとすると、
CTestDlg dlg; dlg.DoModal();と、します。 このようにしてできるダイアログボックスをモーダルダイアログボックスといいます。
しかし、この方法で生成されるダイアログボックスは、ダイアログボックスが開いている間は、アプリケーション本体のウインドウにはアクセスできません。
僕が現在使っているCD Playerは便利なのですが、曲名のデータの編集中は、他の操作ができません。
曲名の登録用のダイアログボックスが開いている間は、アプリケーションのウインドウにアクセスできないのです。
だから、今度自作するCD Playerは、CDの操作と、曲名登録を平行してできるようにしたいと思っていました。
そこで、モードレスダイアログボックスというのを使うことにしました。
これなら、ダイアログボックスを開きながら、アプリケーションの他の操作をすることも可能です。
しかし、困ったことに名前は知っていたのですが、実際にどうすればいいかはさっぱりわかりませんでした。
そこで、また本を買ってきました。(お金が〜〜〜〜)
よって、以下はほとんど受け売りの解説です。
モードレスダイアログボックスというのは、生成されるときと、破壊されるときのタイミングが任意になります。
親ウインドウがあれば、いつでも生成、破壊が可能です。
また、親ウインドウが破壊されると、自動的にダイアログボックスも破壊されます。
モーダルダイアログボックスでは、生成、破壊をすべて自動的に行っていましたが、
モードレスダイアログボックスは、生成、破壊のタイミングが任意ですから、生成、破壊のコードも書かなければなりません。
モードレスダイアログボックスを生成するには、
CTestDlg* dlg = new CTestDlg; dlg->Create(IDD_TEST_DIALOG);と、します。なお、"IDD_TEST_DIALOG"は、ダイアログボックスのリソースIDです。
それでは、破壊はどうなるでしょう。
dlg->DestroyWindow();と、なります。しかし、この状態では、確かに「ウインドウ」は破壊されますが、CTestDlgという「オブジェクト」はまだメモリに残ったままです。
dlg->DestroyWindow(); //ウインドウの破壊 delete dlg; //オブジェクトの破壊と、書くか、CTestDlgクラスの中のPostNcDestroy()をオーバーライドし、
void CTestDlg::PostNcDestroy() { delete this; //自分自身のオブジェクトの破壊 }と、書くかすれば、実現できます。 後者は、自動クリーンアップと言います。PostNcDestroy()はウインドウが破壊されたときにMFCから呼び出されます。
あと、<OK>ボタンと<キャンセル>ボタンを無効にしておきます。そうしないと、予期しないタイミングでダイアログボックスが閉じてしまいます。
<キャンセル>ボタンがたとえなくても、もしも、ESCキーが押されれば、<キャンセル>ボタンをクリックしたのと同じ働きをするからです。
システムメニューの「閉じる」や、ウインドウをクローズするボタン(×印のボタン)をクリックしても同じです。
また、リターンキーは<OK>ボタンを押したことになります。
ですから、OnOK()とOnCancel()を、オーバーライドします。
void CTestDlg::OnOK() { //独自の処理 } void CTestDlg::OnCalcel() { //独自の処理 }と、します。Default()という関数を呼び出せば、ボタンがあれば、ボタンが押されるように見えるだけで何もしないようにすることができます。
void CTestDlg::OnOK() { Default(); } void CTestDlg::OnCalcel() { Default(); }
また、モードレスダイアログボックスでは、DDX/DDVの働きも変わります。
モーダルダイアログボックスでは、DoModal()関数の中で、DDX/DDVをサポートするコードが記述されていましたが、
それを、自分で定期的に呼び出してやらなければなりません。それには、UpdateData()という関数を使います。
UpdateData(FALSE);で、DDX変数から、コントロールに値がセットされ、
UpdateData(TRUE);で、コントロールからDDX変数に値がコピーされます。
僕が制作中のCD Playerでは、ビュークラスとのやりとりが必要だったので、ダイアログボックスのコンストラクタで、ビュークラスへのポインタを渡すようにして、
内部の処理も、これとは少し変えてあります。
参考文献:「Visual C++ プログラミングテクニック」 田口景介 著 アスキー出版局
E-Mail:wbs03748@mail.wbs.ne.jp
質問・感想などのメールはこちらへ。
Copyright(C) 1997 Shingo Nakagawa / e-mail:wbs03748@mail.wbs.ne.jp