• 締切済み

MFC オリジナルDLLからエクスポートしたビュークラスを CMultiDocTemplate で登録すると Assert Failed! が出る

環境はVisualStudio2005、MDIプロジェクトと拡張DLLプロジェクトを1つのソリューションに作成しています。 MDIアプリを作成していますが InitInstance() 関数内の CMultiDocTemplateの引数 RUNTIME_CLASS() 実行時にAssert Failed!が出ます。 CMultiDocTemplate に登録するビュークラスはオリジナルの拡張DLL内でCFormViewクラスから派生させたクラスです。 特に変わったことをしている訳ではなく、ほとんどウィザードがソースを吐いた状態のままです。 "COriginalView" をデフォルトの "CMyView" にするとエラーは出ません。 また、"COriginalView" もコントロールを1ヶ置いてビューフォームとクラスを作成し、 AFX_EXT_CLASS でエクスポートして参照できています。 また、MDI側でフォームとクラスを作成しそれを使用した場合はエラーは出ません。 ドキュメント/ビューアーキテクチャの理解が足りない為起きている問題だと思います。 宜しくお願い致します。 --- 詳細 ------------------------------------------------ CMultiDocTemplate* pDocTemplate; pDocTemplate = new CMultiDocTemplate(IDR_MAINFRAME,   RUNTIME_CLASS(CMyDoc),   RUNTIME_CLASS(CChildFrame),   RUNTIME_CLASS(CDllView)); ←これ実行時に Assert が出る AddDocTemplate(pDocTemplate); ---------------------------------------------------------

みんなの回答

  • davidfox
  • ベストアンサー率58% (21/36)
回答No.2

"COriginalView" が何なのか判りませんが、要はDLL側にあるビューで CMultiDocTemplate が成功しないと言う事でしょうか。 VisualStudio2005 が手元に無いのですが、MDI側のどこかに CRuntimeClass* p = RUNTIME_CLASS(CDllView); を書いても失敗するのでしょう。 どうすれば解決するか判りませんが、MDI側で CDllView の派生クラスは作成できませんか?

sakuzo3
質問者

補足

コメント頂きありがとうございます。 COriginalViewはDLL側で作成したビュークラスです。 (テンプレートとなるダイアログを作成しウィザードを使用してクラスを作成しました)。 CRuntimeClass* p = RUNTIME_CLASS(COriginalView); は実行できました(エラー無し)。 また、MDI側でCOriginalViewの派生を作成しそれを用いても状況は変わらずです。。。 ちなみにドキュメントクラスですが、MDI側で作成したクラス(もちろん動作可能)をDLL側へ移したものを使用しています。

  • z64423
  • ベストアンサー率53% (26/49)
回答No.1

MFC はもう何年も使ってないので、マトモな回答はできませんが… どのファイルのどこの行で ASSERT しているかがメッセージとして表示されると思うので、これを追いかければ原因が分かると思います。 Visual C++ には MFC のソースが付いてきますし、CMultiDocTemplate のコンストラクタが呼ばれる箇所から F11 でじっくりステップ実行していっても、ASSERT 位置にたどり着けます。 CMultiDocTemplate クラスのコンストラクタのソース(VS2005 添付のソース)をみる限りは、  ASSERT(m_docList.IsEmpty()); となっているため、InitInstance() でドキュメントを作る時点ではドキュメントは空でないといけない、ということだと思います。 もしかしたら、CMultiDocTemplate の親クラスのコンストラクタ内で ASSERT しているのかもしれませんが、どちらにしろ、ASSERT している原因が分からなければ対応は出来ないと思いますよ。

sakuzo3
質問者

補足

ASSERTは「doctempl.cpp」の以下の場所で出ます。 CDocTemplateのコンストラクタです。 初心者なもので何がマズくてここでASSERTが出るのか分かりません。 ----------------- CDocTemplate::CDocTemplate(UINT nIDResource, CRuntimeClass* pDocClass, CRuntimeClass* pFrameClass, CRuntimeClass* pViewClass) {  ASSERT_VALID_IDR(nIDResource);  ASSERT(pDocClass == NULL ||   pDocClass->IsDerivedFrom(RUNTIME_CLASS(CDocument))); ←※ここで出る  ASSERT(pFrameClass == NULL ||   pFrameClass->IsDerivedFrom(RUNTIME_CLASS(CFrameWnd)));  ASSERT(pViewClass == NULL ||   pViewClass->IsDerivedFrom(RUNTIME_CLASS(CView)));

関連するQ&A

  • 【MFC】キャンセルボタン処理が実装できない

    VC++2005(MFC)にて下記サイトを参考にMDIアプリケーションを作成しています。 http://www.alpha-net.ne.jp/users2/uk413/vc/VCT_MDI1.html 手順として、プロジェクトを新規作成し、MFC AppWizard(exe)で 新規プロジェクト名をMDITest1に設定し、アプリケーションの種類はMDI、 ビュークラスCMDITest1Viewの基本クラスはCFormViewとします。 リソースビューより、自動生成されたフォームの上に、 Buttonを配置し、イベントハンドラOnBnClickedButton1()内にて、 IDCANCEL()処理にて、ボタン押下時のウィンドウを閉じる処理を 実装したいのですが、コンパイルエラーが発生します。 基本クラスがCDialogクラスの場合は実装できるような気がするのですが。。 フォームビューだと、キャンセル処理は実装不可能なのでしょうか? また、不可能だとしたらウィンドウを閉じる処理はどのように実装すればよいのでしょうか? 解決策をご存知の方おられましたら、お手数ですがご教授宜しくお願い致します。

  • ツールバーから選択でウィンドウ生成

    下記URLのサンプルコード http://www.alpha-net.ne.jp/users2/uk413/vc/VCT_MDI1.html​ を参考に、VC++2005(MFC)にてMDIアプリケーションを作成しています。 サンプルを参照にソースコードを記述し、プログラム起動時に MDIウィンドウを生成することは出来ましたが、 これを『ツールバーからメニューを選択し、ウィンドウを出す』ように 改良したいのです。 下記に起動時にMDIウィンドウを生成するソースコードを記載します。 「☆☆☆追加☆☆☆」で囲まれた箇所が、 上記URL解説を元に自分で追加した箇所で、それ以外はスケルトンです。 解決策ご存知の方おられましたら、お手数ですがご教授お願い致します。 【呼び出し元クラス:CMDITest1App】 BOOL CMDITest1App::InitInstance(){ INITCOMMONCONTROLSEX InitCtrls; InitCtrls.dwSize = sizeof(InitCtrls); InitCtrls.dwICC = ICC_WIN95_CLASSES; InitCommonControlsEx(&InitCtrls); CWinApp::InitInstance(); if (!AfxOleInit()) { AfxMessageBox(IDP_OLE_INIT_FAILED); return FALSE; } AfxEnableControlContainer(); SetRegistryKey(_T("アプリケーション ウィザードで生成されたローカル アプリケーション")); LoadStdProfileSettings(4); // 標準の INI ファイルのオプションをロードします (MRU を含む) // アプリケーション用のドキュメント テンプレートを登録します。ドキュメント テンプレート // はドキュメント、フレーム ウィンドウとビューを結合するために機能します。 CMultiDocTemplate* pDocTemplate; pDocTemplate = new CMultiDocTemplate(IDR_MDITest1TYPE, RUNTIME_CLASS(CMDITest1Doc), RUNTIME_CLASS(CChildFrame), // カスタム MDI 子フレーム RUNTIME_CLASS(CMDITest1View)); if (!pDocTemplate) return FALSE; AddDocTemplate(pDocTemplate); //☆☆☆追加☆☆☆ CMultiDocTemplate* pDocTemplate2; pDocTemplate2 = new CMultiDocTemplate(IDR_MDITest1TYPE2, RUNTIME_CLASS(CMDITest1Doc), RUNTIME_CLASS(CChildFrame), // カスタム MDI 子フレーム RUNTIME_CLASS(CMDITest1View2)); if (!pDocTemplate2) return FALSE; AddDocTemplate(pDocTemplate2); //☆☆☆追加☆☆☆ // メイン MDI フレーム ウィンドウを作成します。 CMainFrame* pMainFrame = new CMainFrame; if (!pMainFrame || !pMainFrame->LoadFrame(IDR_MAINFRAME)) { delete pMainFrame; return FALSE; } m_pMainWnd = pMainFrame; // 接尾辞が存在する場合にのみ DragAcceptFiles を呼び出します。 // MDI アプリケーションでは、この呼び出しは、m_pMainWnd を設定した直後に発生しなければなりません。 // DDE、file open など標準のシェル コマンドのコマンド ラインを解析します。 CCommandLineInfo cmdInfo; ParseCommandLine(cmdInfo); // コマンド ラインで指定されたディスパッチ コマンドです。アプリケーションが // /RegServer、/Register、/Unregserver または /Unregister で起動された場合、False を返します。 if (!ProcessShellCommand(cmdInfo)) return FALSE; // メイン ウィンドウが初期化されたので、表示と更新を行います。 pMainFrame->ShowWindow(m_nCmdShow); pMainFrame->UpdateWindow(); //☆☆☆追加☆☆☆ pMainFrame->OpenView(pDocTemplate2); //☆☆☆追加☆☆☆ return TRUE; } 【呼び出し先クラス:CMainFrame】 //☆☆☆追加☆☆☆ void CMainFrame::OpenView(CDocTemplate *pTemplate){ CDocument* pDoc = MDIGetActive()->GetActiveDocument(); CMDIChildWnd* pNewFrame = (CMDIChildWnd*)pTemplate->CreateNewFrame(pDoc, NULL); if( pNewFrame ) pTemplate->InitialUpdateFrame(pNewFrame, pDoc); } //☆☆☆追加☆☆☆

  • ウィンドウの作成

    VC++のMDIで基本クラスをCFormViewにしてアプリケーションを作成しています。  フォームにボタンをおいて、それを押すと別のフォーム(ウィンドウ)が表示されそこにカメラの動画像がでるようにさせたいのですがどのようにしたらよいでしょうか??今、別のフォーム(ウィンドウ)を表示させるところで悩んでいます…

  • VC++ オリジナルDLLを使用するとアプリを終了させる時にメモリリークする

    VisualStudio2005 C++ユーザです。 メモリリークの解決の糸口を探しています。 オリジナルDLLでクラスを作成しそれをオリジナルアプリ側で宣言だけして実行、アプリを閉じると「Detected memory leaks!」と表示されます。 アプリもDLLもデフォルト状態での使用のため、何が原因かさっぱりです。 解決の手引きお願い致します。 ●作成DLL ・DLLの種類>MFC拡張DLL ・クラスはエクスポートするように記述変更  >class AFX_EXT_CLASS CHogehoge : public CObject ・メンバ関数 InitHogehoge() として「int i=0;」のみ記述 ●作成アプリ(MDI形式) ・プロジェクト形式 MFC標準 ・共有DLLでMFCを使用に設定 ・以下のようにクラスの宣言  >例 void CTestApp::OnAppAbout()内にCHogehoge abc;を宣言 ●現象 ・アプリを終了させた時に以下が出力される Detected memory leaks! Dumping objects -> d:\実験\f_tool\f_tool.cpp(53) : {65} client block at 0x003B9028, subtype c0, 64 bytes long. a CDynLinkLibrary object at $003B9028, 64 bytes long a CDynLinkLibrary object at $003B9028, 64 bytes long {59} client block at 0x003B3298, subtype c0, 64 bytes long. a CDynLinkLibrary object at $003B3298, 64 bytes long a CDynLinkLibrary object at $003B3298, 64 bytes long Object dump complete. F_TOOL.DLL Terminating! プログラム '[192] Test.exe: ネイティブ' はコード 0 (0x0) で終了しました。 ●特記事項 エクスポートしたクラス自体は参照出来ているので基本的なミスはないつもり。 出力の「d:\実験\f_tool\f_tool.cpp(53) : {65} client block at ・・・.」はDLL側の「new CDynLinkLibrary(F_TOOLDLL);」行。 宜しくお願い致します。

  • ウィンドウ生成時にアクセス違反エラー

    下記URLのサンプルコード http://www.alpha-net.ne.jp/users2/uk413/vc/VCT_MDI1.html を参考に、VC++2005(MFC)にてMDIアプリケーションを作成しています。 正常に動作すれば、プログラム起動時に2つのウィンドウが表示されるはずですが、 問題箇所「DEBUG!!!」にて、 「MDITest1.exe の 0x00416420 でハンドルされていない例外が発生しました: 0xC0000005: 場所 0x00000000 を読み込み中にアクセス違反が発生しました。」 といったエラーが発生し、実行が出来ない状態です。 下記にソースコードを記載します。ベタ貼りで申し訳ありません。。 「☆☆☆追加☆☆☆」で囲まれた箇所が上記URL解説を元に自分で追加した箇所で、 それ以外はスケルトンなので、基本的にサンプルコードと同じです。 解決策ご存知の方おられましたら、お手数ですがご教授お願い致します。 【呼び出し元クラス:CMDITest1App】 BOOL CMDITest1App::InitInstance(){ INITCOMMONCONTROLSEX InitCtrls; InitCtrls.dwSize = sizeof(InitCtrls); InitCtrls.dwICC = ICC_WIN95_CLASSES; InitCommonControlsEx(&InitCtrls); CWinApp::InitInstance(); if (!AfxOleInit()) { AfxMessageBox(IDP_OLE_INIT_FAILED); return FALSE; } AfxEnableControlContainer(); SetRegistryKey(_T("アプリケーション ウィザードで生成されたローカル アプリケーション")); LoadStdProfileSettings(4); // 標準の INI ファイルのオプションをロードします (MRU を含む) // アプリケーション用のドキュメント テンプレートを登録します。ドキュメント テンプレート // はドキュメント、フレーム ウィンドウとビューを結合するために機能します。 CMultiDocTemplate* pDocTemplate; pDocTemplate = new CMultiDocTemplate(IDR_MDITest1TYPE, RUNTIME_CLASS(CMDITest1Doc), RUNTIME_CLASS(CChildFrame), // カスタム MDI 子フレーム RUNTIME_CLASS(CMDITest1View)); if (!pDocTemplate) return FALSE; AddDocTemplate(pDocTemplate); //☆☆☆追加☆☆☆ CMultiDocTemplate* pDocTemplate2; pDocTemplate2 = new CMultiDocTemplate(IDR_MDITest1TYPE2, RUNTIME_CLASS(CMDITest1Doc), RUNTIME_CLASS(CChildFrame), // カスタム MDI 子フレーム RUNTIME_CLASS(CMDITest1View2)); if (!pDocTemplate2) return FALSE; AddDocTemplate(pDocTemplate2); //☆☆☆追加☆☆☆ // メイン MDI フレーム ウィンドウを作成します。 CMainFrame* pMainFrame = new CMainFrame; if (!pMainFrame || !pMainFrame->LoadFrame(IDR_MAINFRAME)) { delete pMainFrame; return FALSE; } m_pMainWnd = pMainFrame; // 接尾辞が存在する場合にのみ DragAcceptFiles を呼び出します。 // MDI アプリケーションでは、この呼び出しは、m_pMainWnd を設定した直後に発生しなければなりません。 //☆☆☆追加☆☆☆ pMainFrame->OpenView(pDocTemplate2); //☆☆☆追加☆☆☆ // DDE、file open など標準のシェル コマンドのコマンド ラインを解析します。 CCommandLineInfo cmdInfo; ParseCommandLine(cmdInfo); // コマンド ラインで指定されたディスパッチ コマンドです。アプリケーションが // /RegServer、/Register、/Unregserver または /Unregister で起動された場合、False を返します。 if (!ProcessShellCommand(cmdInfo)) return FALSE; // メイン ウィンドウが初期化されたので、表示と更新を行います。 pMainFrame->ShowWindow(m_nCmdShow); pMainFrame->UpdateWindow(); return TRUE; } 【呼び出し先クラス:CMainFrame】※問題箇所有り void CMainFrame::OpenView(CDocTemplate *pTemplate){ CDocument* pDoc = MDIGetActive()->GetActiveDocument();   //DEBUG!!! CMDIChildWnd* pNewFrame = (CMDIChildWnd*)pTemplate->CreateNewFrame(pDoc, NULL); if( pNewFrame ) pTemplate->InitialUpdateFrame(pNewFrame, pDoc); }

  • ツールバーから選択で一つだけウィンドウ生成

    VC++2005(MFC)にてMDIアプリケーションを作成しております。 前回当サイトの質問 http://oshiete1.goo.ne.jp/qa4708537.html にて、参照URL(http://www.alpha-net.ne.jp/users2/uk413/vc/VCT_MDI1.html)と、 回答者様のご指摘により問題解決したのですが、 このままだと、メニュー選択するとウィンドウ1とウィンドウ2が 再び現れてしまい、合計4つのウィンドウが現れることになります。 (ウィンドウ1:2個、ウィンドウ2:2個) 起動時にウィンドウ1のみ表示させる方法は自力で作成したのですが、 メニュー選択でウィンドウを一つ(ウィンドウ2)だけ 追加生成するようにし、合計2つの別々のウィンドウが現れるようにしたいのです。 下記に改良した現時点でのソースコードを記載します。 「☆☆☆追加☆☆☆」で囲まれた箇所が、上記質問URLを元に改変した ソースコードになります。他はスケルトンです。 【呼び出し元クラス:CMDITest1App】 CMDITest1App::CMDITest1App(){ //コンストラクタ //☆☆☆追加☆☆☆ m_WndFlg == false; //☆☆☆追加☆☆☆ } BOOL CMDITest1App::InitInstance(){ ・・・ //スケルトン //☆☆☆追加☆☆☆ CMultiDocTemplate* pDocTemplate2; pDocTemplate2 = new CMultiDocTemplate(IDR_MDITest1TYPE2, RUNTIME_CLASS(CMDITest1Doc), RUNTIME_CLASS(CChildFrame), // カスタム MDI 子フレーム RUNTIME_CLASS(CMDITest1View2)); if (!pDocTemplate2) return FALSE; AddDocTemplate(pDocTemplate2); m_pDocTemplate2 = pDocTemplate2; //☆☆☆追加☆☆☆ ・・・ return TRUE; } 【オーバーライドした関数:OnFileNew()】 //☆☆☆追加☆☆☆ void CMDITest1App::OnFileNew(){ CWinApp::OnFileNew(); if( m_WndFlg == true ){ //初回起動時は生成しない ((CMainFrame*)m_pMainWnd)->OpenView( m_pDocTemplate2 ); } m_WndFlg = true; } //☆☆☆追加☆☆☆ 何か良い方法ございましたら、ご教授お願い致します。 また、現在MDIでのアプリケーション作成について作成手順が分からず大変苦戦しております。 何か順序を追って作成していけるような参考サイト・文献などあれば、 そちらの方もご教授頂けますと幸いです。

  • 【ASP.NET MVC3】共通ビュークラス

    いつも大変にお世話になっています。 ASP.NET MVC3で作成しているシステムで、すべてのビューに、共通のプロパティを用意したいと考えております。 以前のASP.NETでは、System.Web.UI.Page を継承したカスタムクラスを継承していました。 public MyCustomPage : System.Web.UI.Page {  // 共通のプロパティやメソッド } public class Index : MyCustomPage {  public page_load(Object o, EventArgs e){ // ページロード処理 } }; このような継承定義をビューのクラスで行いたく思います。 MVC3のビューで、たとえば、MyViewModelというビューモデルを埋め込んだ、以下のようなクラスは、どのやって定義したら良いのでしょう? @inherits MyCustomView<MyViewModel> 土曜の夜だというのに、まだ帰れません(泣 何とぞよろしくお願い致します。

  • VC++で作成したアプリ起動時のウィンドウサイズについて

    VC++初心者の者です。初投稿です。宜しくお願いします。 ※何を言っているのか解らない、情報が足りないって場合は聞いてください。超初心者ですので宜しくお願いします。。。 VC++で作成したMDIアプリを起動させた時、 又は新しくウィンドウを開いた時の デフォルトウィンドウサイズを指定する方法を どなたか教えていただけませんでしょうか? また、開いたウィンドウをリサイズできないように するにはどうしたら良いでしょうか? (ViewクラスはCFormViewを基底としています。) 宜しくお願い致します。

  • CMainFrameクラスなどのオブジェクトはどこで定義されていますか?

    VC++6.0です。 SDIベースでスケルトンを作るとCMainFrameクラスなどが作られます。ソースの中でこれらのクラスのオブジェクトが生成されている部分を見たいのですが、見つかりません。 InitInstance()の中のRUNTIME_CLASS()があやしいような気がしますが、これなんでしょうか? ただしRUNTIME_CLASS()の関連ページを読んでもよくわかりませんでした。 今の目標はスケルトンで生成されたCMainFrameのオブジェクトのメンバにアクセスすることです。 よろしくお願いします。

  • SDIアプリ内からもう一つSDIを作成する方法

    開発環境:WindowsXPSp3 + VC++2010 SDIの単純なアプリケーションと、スタティックリンクしているDLL(拡張DLL)があります。 exeのツールバーにあるボタンをクリックすると、DLL内にあるCreateNewWindowという関数を呼ぶようになっています。 このCreateNewWindowでは以下のようなコードが書かれています。 ------------------------------------------------------------------ CSingleDocTemplate* g_pNewWnd ; // グローバル void WINAPI CreateNewWindow() {   if( NULL == g_pNewWnd ) {     g_pNewWnd = new CSingleDocTemplate(       IDR_NEWWINDOW,       RUNTIME_CLASS( CSDIWndDoc ),       RUNTIME_CLASS( CSDIWndFrame ),       RUNTIME_CLASS( CSDIWndView )     );     CDocument* pDocumanet = g_pNewWnd->OpenDocumentFile( NULL ) ;   } } ※初期化や破棄処理は適宜行っているものとします。 ------------------------------------------------------------------ このように、Exeのほうに1つのSDIが存在している状態で、さらにDLL内で別のSDIのウィンドウを作成することは許されるのでしょうか? 実行すると、一応、ウィンドウは作成されるのですが、これらのフレーム内でCMFCToolBarを作成すると、DLLのこの関数でSDIを作成した時点でexe側のツールバーがおかしくなります。 具体的にはDLLのリソースにあるツールバーがexeのツールバーとして不完全な状態で反映され、DLLで作ったSDIウィンドウでは、ツールバーの領域だけ確保されてなにも無い状態です。 この関数を実行するまではexeのツールバーは正常に表示・動作しています。もちろん、リソースIDがユニークになているのは確認済みです。 やりたいことは、SDIやダイアログなどからボタンを押したら動的にSDIのウィンドウを生成して提供するDLLを作成したいのです。 参考になるサイトや書籍、アドバイスを頂けませんでしょうか。 よろしくお願いします。

専門家に質問してみよう