クラス: wxCloseEvent, wxWindow
ウィンドウの削除は混乱しやすいテーマなので、この概要ではいつ、どのようにウィンドウを削除するか、もしくはユーザの要求に応じてウィンドウを閉じるかについて、理解の手助けになる情報を提供します。
ユーザがフレームやダイアログの閉じるボタンを押下したときや、終了コマンドを実行したときに wxWidgets は wxWindow::Close を呼び出します。そして、これは EVT_CLOSE イベントを生成します: wxCloseEvent 参照。
適切なイベントハンドラを定義し、ウィンドウを破棄するか決定するのはアプリケーションの責務です。なんらかの理由で強制的にアプリケーションを終了させる場合 (wxCloseEvent::CanVeto が false を返却する場合)、常にウィンドウを破棄するべきです。それ以外の場合では終了要求を無視するか、安全に終了できるか決定する前にユーザへ確認するという選択肢があります。ウィンドウを破棄しない場合、EVT_CLOSE ハンドラで wxCloseEvent::Veto を呼び出し、呼び出し元へそのことを通知するようにしてください。この関数を呼ぶことで呼び出し元へ有用な情報を提供します。
wxCloseEvent ハンドラではウィンドウを破棄するときに wxWindow::Destroy のみを使用するようにし、delete
演算子を使用しないでください。これは、いくつかのウィンドウクラスではすべてのイベントが処理されるまでウィンドウを実際に削除しないためです。このようにしない場合、イベントが存在しないウィンドウに送信される危険性があります。
次の章で補足しますが、Close の呼び出しはウィンドウが破棄されることを保証しません。確実にウィンドウを破棄する場合、wxWindow::Destroy を呼び出してください。
アプリケーションではフレームワークが行なうように wxWindow::Close イベントを使用するか、もしくは直接 wxWindow::Destroy を呼び出すことができます。Close() を使用している場合は引数に true を渡すことで、このフレームを確実に破棄したいと考えており、終了要求を拒否できないことをイベントハンドラへ通知できます。
Destroy の代わりに Close を使用する利点は EVT_CLOSE イベントハンドラで任意の後処理を行える点です。例えば、ユーザに作業中のドキュメントを保存するように確認した後でドキュメントを閉じるといったことができます。Close は (false を返却したときに) 終了処理を拒否できるのに対し、Destroy は確実にウィンドウを削除します。
wxDialog のデフォルトの終了イベントハンドラは wxID_CANCEL イベントを生成する Cancel コマンドを模倣します。このキャンセルイベントのハンドラ自身が Close を呼ぶため、無限ループのチェックが行われます。wxID_CANCEL のデフォルトハンドラは (モードレスの場合に) ダイアログを非表示にするか、(モーダルの場合に) EndModal(wxID_CANCEL) を呼びます。言い換えると、デフォルトではダイアログは破棄されません。(ダイアログはスタック上に作られるかもしれないので、動的に生成されると仮定することはできません)
wxFrame のデフォルトの終了ハンドラは Destroy() を使用してフレームを破棄します。
ユーザがメニューから終了を選んだときに何をすべきですか?フレームの wxWindow::Close を単純に呼ぶことができます。これにより、フレームを破棄する独自の終了イベントハンドラが実行されます。
このときにアプリケーションを安全に終了できるかどうかを自前の終了イベントハンドラ、もしくは終了メニューコマンドハンドラから確認することができます。例えば、すべてのファイルが保存されているか確認したいと思うかもしれません。保存して終了するか、保存せずに終了するか、終了コマンドを完全にキャンセルするかをユーザが選択できるようにしてください。
wxWidgets アプリケーションは最後のトップレベルウィンドウ (wxFrame または wxDialog) が破棄されたときに自動的に終了します。アプリケーション全体の後処理は wxApp::OnExit (これは仮想関数であって、イベントハンドラではありません) に配置してください。
子ウィンドウは親ウィンドウのデストラクタで削除されます。これは子ウィンドウであればフレームやダイアログも含みます。そのため、親ウィンドウの終了ハンドラで明示的に子フレームや子ダイアログを終了させたいと思うかもしれません。
これまでは 'マネージド' ウィンドウ、つまりフレームやダイアログについて話してきました。コントロールなど、親を持つウィンドウは直ちに削除され、通常は終了イベントハンドラを持ちません。とはいえ、必要であればそれらを実装することができます。一貫性を保つために、これらの種類のウィンドウを明示的に削除するときは delete
演算子の代わりに引き続き wxWindow::Destroy 関数を使用してください。