SDIプログラムからモーダルダイアログを閉じた途端エラーになります。 – プログラミング – Home

SDIプログラムからモーダルダイアログ...
 
通知
すべてクリア

[解決済] SDIプログラムからモーダルダイアログを閉じた途端エラーになります。

固定ページ 1 / 2

VC++6user
 VC++6user
(@VC 6user)
ゲスト
結合: 20年前
投稿: 23
Topic starter  

お世話になります。
タイトルの繰り返しになりますが
SDI(Form View)プログラムの中で、モーダルダイアログを閉じた途端

Debug Assertion Failed

File: wincore.cpp
Line: 875

などとエラーボックスが現れて、止まってしまいます。^^;

ダイアログに一つエディットボックスを貼り付けましたが
それ以外、クラスを新規作成して特に何も処理を追加していない段階で
ダイアログをDoModal()して、OKボタンでもキャンセルボタンでも
とにかく閉じた途端、エラーになります。

まだまだ初心者の段階なもので、自分では原因が思い及びません。
どうかご助言よろしくお願い致します。

CmyDialog myDLG;

if (myDLG.DoModal() == IDOK) {
・・・・・
何らかの処理
}
else return FALSE;


引用未解決
トピックタグ
n
 n
(@n)
ゲスト
結合: 21年前
投稿: 90
 

すいませんが、
VCのバージョンやサービスパックの当て具合によって
>File: wincore.cpp
>Line: 875
の指す内容が違ってくるようなので、それも書いて欲しいです。


返信引用
あいる
 あいる
(@あいる)
ゲスト
結合: 20年前
投稿: 55
 

結構見かけるのは・・・

if (myDLG.DoModal() == IDOK) {
・・・・・
何らかの処理
}

この「何らかの処理」のところで、消滅しているエディットボックスを操作してるとかでしょう
か?
> Debug Assertion Failed
とのことなので、ありそうです。

DoModalは、抜けるときにウィンドウを破棄してしまうので、
こういうことがよく見られます。

とりあえず、その「なんらかの処理」のところをすべてコメントアウトして
それでもエラーがでるなら他の原因だと思います。

# 何らかの処理と省略されているので推測でしかいえませんが・・・


返信引用
psz
 psz
(@psz)
ゲスト
結合: 20年前
投稿: 3
 

「何らかの処理」というのは
myDlg.m_edit.GetWindowText();
とか、
myDlg.GetDlgItem(IDC_EDIT1);
みたいなことで、そこでアサートしているのだろうと推測してみる。
(その時点ではエディットボックスは破棄されてるから、もうアクセスできないよ)


返信引用
FrozenAquarium
 FrozenAquarium
(@FrozenAquarium)
ゲスト
結合: 22年前
投稿: 22
 

> OKボタンでもキャンセルボタンでも

という事なのでダイアログを閉じたときに
走るダイアログクラスの中の処理が
原因じゃないかと思うんですが。


返信引用
VC++6user
 VC++6user
(@VC 6user)
ゲスト
結合: 20年前
投稿: 23
Topic starter  

お世話になってます。

ダイアログに貼り付けたエディットボックスには、ビュークラスとの
文字列の受け渡しをしようと、CString型のm_textという
コントロールメンバ変数というのでしたっけ?を設けました。
ダイアログクラスには、後で徐々に処理追加するつもりで
PreTranslateMessage関数やPreCreateWindow関数,
OninitDialog関数などをオーバーライドしました。
PreCreateWindow関数の中でダイアログの初期表示位置とかを
操作できるものと勘違い?して、cs.x,cs.yなどに100とかを座標値の
つもりで入れたりしましたが、なんだかその関数は呼ばれてないみたいで?
ダイアログはセンターに現れるだけですね?
他の関数の中は今のところ、手を加えていません。

とりあえず、原因を絞り込もうと、ちょっとへんてこですが
呼ぶ側を下のようにしてみても、やはりダイアログをモーダルして
閉じただけで、同じエラーになります。
本当はm_textの値を受け渡してループ処理を続けたいのですが・・・^^;

ダイアログクラスの中に何かあるのでしょうか?
クラスウィザードでダイアログクラスを新規作成して、ほとんど手を
加えてませんので、今の自分では原因が思い当たりません。
Visual C++(Studio)6.0 Enterpriseを元のままで
使用していまして、サービスパックは当てていません。
どうか引き続きご助言よろしくお願い致します。

CString ss;
ss.Empty();
CmyDialog myDLG;

while(1) {
myDLG.m_text = ss;
if (myDLG.DoModal() == IDOK) return TRUE;
else return FALSE;

・・・・
・・・・
・・・・
・・・・
・・・・
}  


返信引用
VC++6user
 VC++6user
(@VC 6user)
ゲスト
結合: 20年前
投稿: 23
Topic starter  

例えば、DAOを使用している場合
レコードセットをAddNew()して
Update()か、CancelUpdate()待ちの間に
ダイアログをモーダルして閉じると
プログラムが落ちたりすることはあるのでしょうか?

試しに、OnDraw()関数の中に
ダイアログをモーダルして閉じる処理を入れてみると
何も起こらず、プログラムは初期起動しましたが・・・


返信引用
VC++6user
 VC++6user
(@VC 6user)
ゲスト
結合: 20年前
投稿: 23
Topic starter  

ん~DAOを使ってデータベースとレコードセットを構築して
オープン中にダイアログをモーダルして閉じると落ちたりするのでしょうか~?
今だ、はっきりわかりません・・・^^;


返信引用
VC++6user
 VC++6user
(@VC 6user)
ゲスト
結合: 20年前
投稿: 23
Topic starter  

何度もすいません。^^;閉じた途端というよりも
自分らが書くダイアログをモーダルした関数から
リターンしていって、もっとずっとコアな部分まで
戻ったところで落ちるようですが・・・
何か防ぐ方法はございませんでしょうか?


返信引用
VC++6user
 VC++6user
(@VC 6user)
ゲスト
結合: 20年前
投稿: 23
Topic starter  

エラーメッセージボックスに[中止][再試行][無視]のボタンがありまして
[無視]をクリックすると、プログラムは当面そのまま走るのですが
後々まずいことになるのでしょうか?大丈夫ならば、エラーメッセージボックスなど
表示させずに、デフォルトで[無視]を選択したかのように進める方法等
あるのでしょうか?ご助言下さい。よろしくお願い致します。


返信引用
wood
 wood
(@wood)
ゲスト
結合: 23年前
投稿: 895
 

>if (myDLG.DoModal() == IDOK) {
> ・・・・・
> 何らかの処理   ← 1
>}          ← 2
>else return FALSE;  ← 3
>           ← 4
1・2・3・4の内どこまで落ちないでステップ実行できる?

>File: wincore.cpp
>Line: 875
は何の関数内部ですか?

デバック実行中であれば、関数の呼び出し順序を表示しているタブが表示されて
いるはずですけど、自分のソースのどこから、その関数に到達してるか
見てみましたか


返信引用
psz
 psz
(@psz)
ゲスト
結合: 20年前
投稿: 3
 

wood さんの補足になりますが、

>デバック実行中であれば、関数の呼び出し順序を表示しているタブが表示されて
>いるはずですけど、自分のソースのどこから、その関数に到達してるか
>見てみましたか

エラーメッセージボックス表示されたら、[再試行]ボタンを押してください。
エラー個所で停止すると思います。
そこで、コールスタックウィンドウを見ます。
([表示]-[デバッグウィンドウ]-[コールスタック]で表示されます)
コールスタックウィンドウの一番上の行に表示されているのが現在実行中の関数で、
次の行にはその関数の呼び出し元の関数...、といった具合に続いています。

それを見ても自分ではよくわからない、ってことなら、
質問時にその内容を提示するといいでしょう。
(ウィンドウの内容を全選択して、ctrl + C で内容をクリップボードにコピーできます)

File: wincore.cpp
Line: 875
は、おそらく、CWnd::AssertValid()関数の ASSERT(::IsWindow(m_hWnd)); の行だと思われ
ます。
これは、その時点で存在すべきウィンドウが存在しない(未作成または破棄済み)という意味で
す。
CWnd::AssertValid()は各所から呼ばれるので、どこから呼ばれたかを知る必要があると思い
ます。

#私は DAO 使ったことがないので、そこが絡んでいるとお手上げですが (^^;;;


返信引用
VC++6user
 VC++6user
(@VC 6user)
ゲスト
結合: 20年前
投稿: 23
Topic starter  

皆様、お世話になります。
実は、オーバーライドしたPreTranslateMessage関数から呼ばれる先で
ダイアログのインスタンスを生成して、DoModal()しているのですが
インスタンスを生成しても、DoModal()だけコメントアウトすれば落ちません。

それで下記のコードのように、DoModal()して閉じた直後を判断するフラグを
設定して、真の時には以降の処理を避けてやれば、落ちないようになりました。

psz様がご助言下さった「その時点で存在すべきウィンドウが存在しない
(未作成又は破棄済み)」という意味のメッセージが、DoModal()して
閉じてスコープも抜けて無くなったダイアログのことなのでしょうか?
きっちりはわかっていませんが・・・
PreTranslateMessage関数の中でキー検知して、飛ばした先でDoModal()した
直後は、オーバーライド元?へ通してはまずいのですね?

BOOL C????View::PreTranslateMessage(MSG* pMsg)
{
// TODO: この位置に固有の処理を追加するか、または基本クラスを呼び出してください

if (pMsg->message == WM_KEYDOWN || pMsg->message == WM_SYSKEYDOWN) {
if (m_bAddMode)
KeyInputField(pMsg); ←この中の方でDoModal()してるのですが
else
KeyChangeProcess(pMsg);
}
if (FLG) { // DoModal()後のAssert防止フラグ
FLG = FALSE;
return TRUE;
}
return CFormView::PreTranslateMessage(pMsg);
}


返信引用
monkey
 monkey
(@monkey)
ゲスト
結合: 21年前
投稿: 70
 

KeyInputField関数がどのような処理をしているのか分からないので原因は特定できませ
ん(原因が特定できるかどうかも分からない).
ただ,キーが押されたメッセージをハンドルするなら,PreTranslateMessage関数でな
く,OnKeyDown関数,OnSysKeyDown関数をオーバーライドした方が問題は少ないように思
います.


返信引用
VC++6user
 VC++6user
(@VC 6user)
ゲスト
結合: 20年前
投稿: 23
Topic starter  

monkey様、ご助言ありがとうございます。

OnkeyDown関数は、フォームビューにコントロールを配置して
それらがフォーカスを持つと効かない・・・と本に書いてありまして
そういう場合は、PreTranslateMessage関数を使えばいいとの
ことでしたので、それに従えば、この様でした。^^;

OnSysKeyDown関数については、その本では詳しく載っていません
でしたが、検出できるキーが文字通りシステムキーのみ?だとか
制限あるのではないか?と思いましてパスしていました。


返信引用
固定ページ 1 / 2

返信する

投稿者名

投稿者メールアドレス

タイトル *

プレビュー 0リビジョン 保存しました
共有:
タイトルとURLをコピーしました