すごく基本的な質問かもしれませんが教えてください。
モーダルダイアログの戻り値についてですが
正常にダイアログが終了した場合や、異常終了した場合など
どのような値が返されるのでしょうか。
正常時は閉じるために呼んだ CDialog::EndDialog に渡した値
(たいてい IDOK とか IDCANCEL とか)
異常時は -1 か IDABORT
すいません、便乗質問です
-1 は、異常時
IDABORT は、中止ボタン押下時
だと思うのですが。。。
異常時のときに IDABORT が戻ってくるパターンとはどのようなときなのでしょうか
また、もし中止ボタンがあるダイアログの場合、正常終了と異常終了を
どのように切り分けるのでしょうか
それほど厳密なルールがあるわけじゃないから、「場合によって臨機応変」かと。
メッセージボックスならある程度規則性がありそうだけど、Shell や Windows のバージ
ョンによって細かい挙動が違ってそうだし、その他大勢のダイアログなんて、内部がど
んな実装になってるかなんて分かったもんじゃないでしょ?
自社の開発グループ内で、とかなら、そこで現実に即したルールを設定してそれに従え
ばいいんじゃないですか?
そういう意味ではそうなんですけど
そういうことを聞いているのではないような。。。
確かに、プログラムの中で EndDialog( hwnd, -1 ) ってやってしまったり
その他の値をどうにでも返せるわけなので厳密ではない
臨機応変、ってのはわかりますが。。。
DialogBox 関数内部で(WM_INITDIALOG が送られる以前までの間に)
異常終了した場合の値、を問題にしていると思うのですがどうでしょう?
その後に何を返すかは確かに臨機応変だと思います
(というか、自分で決めればよいだけです)
>そういう意味ではそうなんですけど
>そういうことを聞いているのではないような。。。
んー、そんなにデリケートな質問だったのかな? (^^;
でも確かに、以上終了時の IDABORT ってどんな時だろう?
>DialogBox 関数内部で(WM_INITDIALOG が送られる以前までの間に)
>異常終了した場合の値、を問題にしていると思うのですがどうでしょう?
は、ダイアログテンプレートが不適切とかですよね?
これは -1 なんじゃないのかな?
それ以外の場合があるとしたらチビっとは気になるけど。。。
でも通常、DoModal() の戻り値なんて IDOK/IDAPPLY(だっけ?) かどうかだけが重要
なんじゃないかな?
ダイアログ内部で起きたエラーはダイアログ内部で始末つけるべきだと思われ。
>その後に何を返すかは確かに臨機応変だと思います
>(というか、自分で決めればよいだけです)
(独自の)ダイアログが表示されちゃったら、もうそれはダイアログの実装しだいです
もんね。
>んー、そんなにデリケートな質問だったのかな? (^^;
ん~、確かに元質問者のたけさんの意図以上の内容かもしれない。。。
>でも確かに、異常終了時の IDABORT ってどんな時だろう?
それが気になったので便乗質問したんです
>>DialogBox 関数内部で(WM_INITDIALOG が送られる以前までの間に)
>>異常終了した場合の値、を問題にしていると思うのですがどうでしょう?
>は、ダイアログテンプレートが不適切とかですよね?
>これは -1 なんじゃないのかな?
もしくは、ダイアログ作成時に確保するメモリがない場合
ウィンドウ(ダイアログだってウィンドウだから)を作るときに
リソースが足りなかった場合、まぁ、どちらにしても -1 ですよね
> それ以外の場合があるとしたらチビっとは気になるけど。。。
> でも通常、DoModal() の戻り値なんて IDOK/IDAPPLY(だっけ?) かどうかだけが重要
> なんじゃないかな?
厳密にいえば(すいません、SDK的に)
switch( DialogBox( ... ) )
{
case IDOK: case IDCANCEL:
// それなりの処理
break;
case -1:
// エラー処理
break;
}
と処理すべきなんですけど、、、
確かにすでにダイアログも出せない状況でできるエラー処理なんてないから
普通は、-1 を聞いて処理なんてしないですよね
ただ「ダイアログが表示されたのか、表示もされなかったのか」を
判断して行うことを決める状況ってのもごく稀にありそうが気がするんですよ
> ダイアログ内部で起きたエラーはダイアログ内部で始末つけるべきだと思われ。
はい、WM_INITDIALOG が来たあとはそのとおりだと思います
で、結局何が聞きたかったかというと
>異常時は -1 か IDABORT
であるならば
switch( DialogBox( ... ) )
{
case IDOK: case IDCANCEL:
// それなりの処理
break;
case -1:
// エラー処理
// もうメッセージボックスも出せないかもしれないから
// 例えば、GetLastError() の戻りをログに吐き出すとか
break;
case IDABORT:
// ここに来る場合はどんなパターンでエラーが起こったのだろう?
// GetLastError() には有効な値が入っているのだろうか?
break;
}
ということなのです
(長々とすいません)
追加。。。
...
case IDABORT:
// ここに来る場合はどんなパターンでエラーが起こったのだろう?
// GetLastError() には有効な値が入っているのだろうか?
// また、表示しようとしたダイアログに IDABORT ボタンがある場合
// いかにして正常終了と切り分けるのだろう?
break;
}
最新のMSDNライブラリによると、CDialog::DoModalの戻り値は、
戻り値
ダイアログ ボックスを閉じる CDialog::EndDialog メンバ関数のパラメータ nResult に渡
す int 値を返します。
ダイアログ ボックスを作成できなかった場合は、戻り値 -1 を返します。
それ以外のエラーが発生した場合は、IDABORT を返します。
その場合、Output window に GetLastError のエラー情報が含まれます。
だそうです。
ありがとうございます
(なんとなくすっきりしませんが)
DialogBox() の戻りの説明としては -1 のことだけで
IDABORT に関してはふれていませんので
DialogBox() の戻り
正常時 EndDialog() の指定値
異常時 -1
CDialog::DoModal() の戻り
正常時 EndDialog() の指定値
異常時 -1 (DoModal内部で呼び出したDialogBoxが-1を戻したとき)
IDABORT (DialogBoxは成功したがDoModal(というかその他のMFCの要素)でエラーが
あった場合)
どちらの場合も GetLastError() は有効(なのかなぁ。。。)
と理解しました
# 元質問者のたけさんは、SDKかMFCか書いていないので
# 結果的に必要十分な答えになったかと思います
>厳密にいえば(すいません、SDK的に)
>
>switch( DialogBox( ... ) )
>{
> case IDOK: case IDCANCEL:
> // それなりの処理
> break;
> case -1:
> // エラー処理
> break;
>}
>
>と処理すべきなんですけど、、、
えー、そんなことしないなー
ほとんどの場合
switch (DialogBox(...))
{
case IDOK:
// DoSomeThing();
break;
}
でおしまい。
IDCANCEL で実行する処理なんか無いし、エラーがあったとしても具体的にどんな対応が
できるか不明な場合が多いし。まぁ、せいぜいログに書き出すとかくらいかな?
余談ですが、メッセージボックスのダイアログは動的に作成されるものではないので、
かなりシステムが不安定でも利用可能である可能性が高いです。
> ダイアログ ボックスを作成できなかった場合は、戻り値 -1 を返します。
> それ以外のエラーが発生した場合は、IDABORT を返します。
「中止」を含むダイアログで、「中止」が押下されてモーダル状態を脱した時と、-1 で
表せないエラーの切り分けができないのが気持ち悪いかなぁ。。。
>えー、そんなことしないなー
>
>ほとんどの場合
>
>switch (DialogBox(...))
>{
>case IDOK:
> // DoSomeThing();
> break;
>}
>
>でおしまい。
>
>IDCANCEL で実行する処理なんか無いし、エラーがあったとしても具体的にどんな対応が
>できるか不明な場合が多いし。まぁ、せいぜいログに書き出すとかくらいかな?
私もそうですよ
ただ、以前、警備システムのプログラムを開発した経験があり
「ユーザーが本当に、警備状態の「取り消し」ボタンを押したのか?」
(つまり、ダイアログが表示され、ユーザーの意思で「取り消し」したのか)
をチェックすることを求められたので、、、
まぁ、Windows でプログラム動かしてる時点であまり確実性なんて関係ないんですが(笑)
>余談ですが、メッセージボックスのダイアログは動的に作成されるものではないので、
>かなりシステムが不安定でも利用可能である可能性が高いです。
なるほど、そうなんですか、覚えておきます
>「中止」を含むダイアログで、「中止」が押下されてモーダル状態を脱した時と、-1 で
>表せないエラーの切り分けができないのが気持ち悪いかなぁ。。。
MFC(DoModal)で、プログラムする場合は、「中止」ボタンに IDABORT を割り振らず
違うIDにしておけばよいですよね(まぁ、DialogBoxでもそうです)
どうしても、IDABORT を使わなければならない状況って
MessageBox の MB_ABORTRETRYIGNORE のときですが
これは、-1 がエラーで、IDABORT がボタン押下でしょう