はい!しっかり読み直しつつ,自分で頑張っていきます!!
解決しましたら,また書き込みます。
chamaroさん,アドバイスをしていただき,ありがとうございました!!!
> ASSERT(::IsWindow(m_hWnd)); ←★ここ
でアサートされているのだから、このクラスのオブジェクトである、viewがWindowではないと
いうことです。viewがCreateされていないのでは?
アサートでプログラムが停止しているので、何が問題かはASSERT関数の引数で明白と思います
が、いかがでしょう。
maruさん,お返事ありがとうございます。
>viewがCreateされていないのでは?
とは PreCreateWindow のようなプログラムがないのではないかということなのでしょ
うか?
確かにdispViewの中にはそのようなプログラムは見あたりません。
これは追加すべきなのでしょうか?
よろしくお願いします。
うわっ!! 今,Blueさんが書き込んでくださった部分に気づきました。。
Blueさん,申し訳ありません。
>((CdispView*)view.GetDlgItem(IDC_EXPLORER1)).・・
もBlueさんがアドバイスしてくださった辺りの時にしてみましたが,結果はだめでした。
見過ごしてしまっていたとはいえ,アドバイスしてくださったのに申し訳ありませんでし
た。。
というか、単純にdispViewが表示されているか?と言うことなんですけど。
> m_browser1ですが,これはdispViewに配置しているWebBrowserコントロールで,
> このViewをimDialogというダイアログから呼び出して(?)実行させるようにしようとして
> います。
ダイアログからViewを呼び出すと言うのがよく分かりません。
ダイアログのボタンを押すと、MDIにViewが作成されると言うこと?
そもそも、このCdispViewクラスは何から派生しているのですか?
maruさん,お返事ありがとうございます!
私がしっかり理解できていないので,説明が足りなかったり,意味分からないことを言っ
て申し訳ないです。
>単純にdispViewが表示されているか?
ダイアログの[キャンセル]ボタンを押すと,dispViewのFormは表示されます。
>ダイアログのボタンを押すと、MDIにViewが作成されると言うこと?
そのとおりです。
流れとしては,
1)メニューバーから項目を選択
2)ダイアログが表示される
3)ダイアログの[実行]ボタンを押すと,MDI内にdispViewが表示される
その際,ダイアログ内で指定した内容のものを表示させる
ということをしたいと思っいます。
>このCdispViewクラスは何から派生しているのですか?
CFormViewからの派生クラスです。
いっぱいいっぱいで書籍やネットで調べながらプログラムを組んでいっている次第ですの
で,ご指摘していただけて感謝します。
viewが表示されているとすると::IsWindow(m_hWnd)が失敗する理由がわからない。
引っかかるのは
> ダイアログの[キャンセル]ボタンを押すと,dispViewのFormは表示されます。
[キャンセル]ではdispViewのFormを表示するだけだが、[実行]で何かしようとした時に
エラーが発生する。と言うシチュエーションならば、理解できる。
ダイアログボックスのOnOK()内ではまだdispViewのウィンドウが生成(Create)されて
いない(と思う)ためアサートが発生していることになる。もし、そうならば、該当の処
理をOnOK()内で実行するのは不可能。ウィンドウが生成(Create)された後に該当の処
理を実行する必要がある。CdispView::OnInitialUpdate()あたりで処理するのが適切か
な。
上記シチュエーションではないとすると私には分かりません。
どこかのコードでm_hWndを破壊しているとか...
maruさん,アドバイスありがとうございます!
>[キャンセル]ではdispViewのFormを表示するだけだが、[実行]で何かしようとした時に
エラーが発生する。
というシチュエーションだと思っています。
>まだdispViewのウィンドウが生成(Create)されていない(と思う)ためアサートが発
生している
これもその通りだと思います。
色々調べて行く中で,「ウィンドウが生成されていない」という問題があるのではないか
と思ったのですが,その生成方法もわからず・・・
>CdispView::OnInitialUpdate()あたりで処理
ここでは
CFormView::OnInitialUpdate();
CDC* pDC;
pDC=GetDC();
CimDialog dlg;
if (dlg.DoModal()==IDCANCEL)
return;
という処理を行っています。
ここで今回はOKボタンの代わりに「インポート」ボタンを用意しているので,この中でイ
ンポートボタン用の処理を追加しようとしたのですが,実行してみてもここには読み込み
にきてくれないようで・・・imDialogの方でOnBnClickedimをオーバーライドして書き込
んでいます。
>どこかのコードでm_hWndを破壊しているとか...
とのことですが・・・これも調べていく中で,疑わなければならないのかなと思っている
のですが,
どこで壊しているのかも,なぜ壊れているのかも見当がつかず・・・といった感じです。
破壊している場合,何か対処方はあるのでしょうか?
よろしくお願いします!!
気になった所だけ反応しておきます。
壊れている場合は、壊れている原因を探らないかぎり対処方法は有りません。
というか、辻褄合わせの対応をしても不具合の対応にはなりませんし。
で、かなり重くなりますけれど特定のアドレスの内容が書き換わったらブレイクするような
ブレイクポイントのはり方があったと思います。
それを使って正常なm_hWndが設定された以降を追いかければ、あるいはわかるかもしれま
せん。
この手のメモリ破壊系のネタは追いかけるのがとても難しいので確実な方法と言うのは
無いと思います。ひたすら地道に追いかけるしか無いと思いますよ。
あと、どこかでメモリを壊した結果、その二次被害でm_hWndの内容が壊されるケースも
無いとは言い切れませんが、最初からそこまで想定して追うのは無理なので、
現象が起きている所から遡って見ていくしか無いと思います。
あと、よくあるのはひたすらコードを削って行っておかしくなくなる境目辺りのコードを
もう一回見直すと言うのも有りますけれど、メモリ破壊の原因によってはコードを削ると
再現しなくなるケースもあるのでこれも確実な方法とは言い切れないです。
PATIOさん,反応ありがとうございます!
・・・かなりヤバイ状態に陥ってるんですかね。。
もうちょっとあがいてみます。
それでもダメなら,PATIOさんがおっしゃってくれた方法で対処していこうと思います。
全体的に辻褄合わせな感じがするから,怖いです。。
私の指摘したシチュエーションだと
> どこかのコードでm_hWndを破壊しているとか...
というより、viewが正しいオブジェクトを参照していないような気がします。
CdispView::OnInitialUpdateでダイアログを表示して、そのダイアログのインサートボタン
ハンドラの中で、
((CExplorer1*)view.GetDlgItem(IDC_EXPLORER1))->Navigate2(COleVariant(url
[k]),NULL,NULL,NULL,NULL);
を呼び出し、そのGetDlgItem(IDC_EXPLORER1))の中でASSERT(::IsWindow(m_hWnd));
が失敗しているという認識で正しいでしょうか?
ダイアログのハンドラ中で呼び出し元のviewをどうやって取得しているのでしょうか?
ちなみにCdispView::OnInitialUpdate()でGetDlgItem(IDC_EXPLORER1)は成功するの
でしょうか?そこで成功すればダイアログ中でCdispViewのオブジェクトを取得できてい
ないことになる。そこでも失敗するのならば、...。人のコードをソコまでデバッグする
気はない。
普通に考えるとViewからダイアログを出し、そのダイアログからViewを使う場合、ダイア
ログにViewのthisポインタを渡し、ダイアログではポインタ経由で関数を呼び出すと思う
のだが、GetDlgItem()をドット演算子で呼び出している所を見ると渡しているのはthis
ではなく*thisなのかな?
CdispView::OnInitialUpdate()でGetDlgItem(IDC_EXPLORER1)は成功するならば、
>どこかのコードでm_hWndを破壊しているとか...
だとしてもCdispView::OnInitialUpdate()からインサートボタンハンドラの間のはずですよ。
maruさん,お付き合いいただきありがとうございます!
maruさんの認識で合っています。まさにそのとおりです。
>ダイアログのハンドラ中で呼び出し元のviewをどうやって取得しているのでしょうか?
ダイアログのプログラム内では
CDC* pDC;
pDC=GetDC();
CdispView view;
このようにして関連づけてるつもりなのですが・・・これはおかしいのでしょうか?
>CdispView::OnInitialUpdate()でGetDlgItem(IDC_EXPLORER1)は成功するのでしょうか?
成功しませんでした。
インポート用のプログラムを呼びにきている気配もありませんでした。
>普通に考えると~
thisポインタを使おうと考えつかないくらいの初心者で・・・・
thisポインタについて調べてみます。
ホント,お付き合いいただけて感謝です。
> ダイアログのプログラム内では
> CDC* pDC;
> pDC=GetDC();
> CdispView view;
>このようにして関連づけてるつもりなのですが・・・これはおかしいのでしょうか?
だめです。
ここで宣言したviewは実際の目に見えるウィンドウと関連付いていません。
従って、ダイアログのプログラムでview.GetDlgItem()は失敗します。
ダイアログのボタンハンドラで必要としているのは呼び出し元のフォームの
コントロールなので、ダイアログのコンストラクタでFormのthisポインタを
渡す等の方法で、ダイアログ側でその値を保持する必要があります。
class CimDialog : public CDialog
{ public:
CimDialog(CdispView* pView) {m_dispView = pView;}
private:
CdispView* m_dispView;
...
}
CdispView::OnInitialUpdate()
{ CFormView::OnInitialUpdate();
CimDialog dlg(this);
if (dlg.DoModal()==IDCANCEL)
...
}
CimDialog::OnInsert()
{
((CExplorer1*)m_dispView->GetDlgItem(IDC_EXPLORER1)) ...
...
}
>>CdispView::OnInitialUpdate()でGetDlgItem(IDC_EXPLORER1)は成功するのでしょうか?
> 成功しませんでした。
本当ですか!?そうであるとするとかなり重症です。
CdispView::OnInitialUpdate()
{ CWnd* wnd = GetDlgItem(IDC_EXPLORER1);
}
単純に上記のコードが失敗するとなると、
...
MFCのフレームワークの使いかたが間違っている?
もう私の手に負えません。
本当にSDIで動作していたんですか?
maruさん,プログラムまで示していただいて・・・ありがとうございます!
その通り書き込んでみたのですが,ビルドエラーが出てしまいまして・・・
>{ public:
> CimDialog(CdispView* pView) {m_dispView = pView;}
> private:
> CdispView* m_dispView;
の部分で多数のエラーが出ていました。
ですので,今はこのエラーを消すことをまず頑張ってみます。
>>>CdispView::OnInitialUpdate()でGetDlgItem(IDC_EXPLORER1)は成功するのでしょうか?
>> 成功しませんでした。
ですが,SDIの時はダイアログなどを使っていませんでした。
また,GetDlgItemは使っておらず,m_browserなどのコントロール変数で指示をだしてい
ました。
このようなやり方では成功しています。
> その通り書き込んでみたのですが,ビルドエラーが出てしまいまして・・・
完全なコードを示さないとだめか。
それくらいの応用はできると踏んだ私が甘かった。
---imDialog.h---
class CimDialog : public CDialog
{
public:
CimDialog(CdispView* pView); // コンストラクタ追加
enum { IDD = ダイアログID };
private:
CdispView* m_dispView; // メンバー変数追加
...
}
---imDialog.cpp---
// CimDialogのコンストラクタ
CimDialog::CimDialog(CdispView* pView)
: CDialog(CimDialog::IDD), m_dispView(pView)
// その他の必要とするメンバー変数初期化
{
// 必要とする初期化コード
}
> また,GetDlgItemは使っておらず,m_browserなどのコントロール変数で指示をだしてい
> ました。
> このようなやり方では成功しています。
従来は、chamaroさんが書かれてようにDDX_XXXXX(IDXXX, m_browser1)が
DoDataExchange()で実行されたいたため、m_browserを使用することができたのです。
このダイアログデータ交換処理の内部でGetDlgItem()相当の機能が実行されています。
私が
> 本当にSDIで動作していたんですか?
と言っているのは、よくこの程度の知識でちゃんと動作する物が作れる!と関心しているんで
す。
話を元に戻して、
有効なm_browser1がCdispViewにあるのならば、上記で示したCdispViewのポインタを
渡さなくてもbrowser1のポインタをダイアログに渡せば良いだけの話。
---imDialog.h---
class CimDialog : public CDialog
{
public:
CimDialog(CExplorer1* pExplorer); // コンストラクタ追加
enum { IDD = ダイアログID };
private:
CExplorer1* m_pExplorer; // メンバー変数追加
...
}
---imDialog.cpp---
// CimDialogのコンストラクタ
CimDialog::CimDialog(CExplorer1* pExplorer)
: CDialog(CimDialog::IDD), m_pExplorer(pExplorer)
// その他の必要とするメンバー変数初期化
{
// 必要とする初期化コード
}
CimDialog::OnInsert()
{
m_pExplorer->Navigate2(COleVariant(url[k]),NULL,NULL,NULL,NULL);
...
}
---dispView.cpp---
CdispView::OnInitialUpdate()
{ CFormView::OnInitialUpdate();
CimDialog dlg(m_browser1);
if (dlg.DoModal()==IDCANCEL)
...
}
必要となる宣言等は正しく行なってね。
結局、従来はviewの中で閉じていた処理をviewをダイアログに分けたが、その間の
データ(コントロールを含む)の受け渡しが出来ていない。ということのようです。
C++をもう一度勉強し直すことをお勧めします。