• ベストアンサー

アンマネージDLLで、ダイアログを表示する方法

現在、Visual Studio 2005の、Visual C#、C++/CLI、MFCを使ったシステムを構築しています。 具体的には、MFCで書かれた(拡張DLL)でダイアログを表示。これをC++/CLIでラップし、C#から呼び出して使いたいと思っております。 そこで、http://soudan1.biglobe.ne.jp/qa3834982.htmlを参考にして、以下のように作ったのですが、DLL内のdlg.DoModal()のコールで、 AfxGetResourceHandle()でASSERTが発生してしまいます。 //// C#のフォーム using LogGphWrap; namespace DllTestApp { public partial class Form1 : Form { private void button1_Click(object sender, EventArgs e) { Wrapdll.Wrapper.DlgOpen(this.Handle.ToInt32()); } } } //// Wrapdll(CRLのクラスライブラリ) [Wrapdll.h] [DllImport("MFCdll.dll")] bool dspDlg(int hDib); namespace Wrapdll { public ref class Wrapper { public: static bool DlgOpen(int hDib) { return ( dspDlg(hDib) ) ; } }; } //// MFCdll(MFCの拡張DLL) [MFCdll.h] #include "resource.h" bool dspDlg(HWND hDib); //// MFCdll(MFCの拡張DLL) [MFCdll.cpp] extern "C" int APIENTRY DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved) { :   デフォルトのまま : } bool dspDlg (HWND hDib) { AFX_MANAGE_STATE(AfxGetAppModuleState()); AfxMessageBox(_T("ちょっとお試し"), 0, 0) ;  CTestDlg *dlg = new CTestDlg(CWnd::FromHandle(hDib));  dlg->Create(IDD_DIALOG) ; <====この部分でASSERTが発生!!  return TRUE ; } ご存知の方がいらっしゃれば、ご教授ください。 よろしくお願いします。

質問者が選んだベストアンサー

  • ベストアンサー
  • takupy
  • ベストアンサー率100% (3/3)
回答No.1

こんにちは。 異なる言語を使ったプログラムは組んだことないのですが、多分同じではないかと思ってレスさせてください。 質問で書かれているプログラムでは、恐らくDLL側にリソースエディタでダイアログを作成されたと思いますが、DLL側から参照使用としているリソースはそのままではアプリケーション側(呼出元)のリソースを参照としているためにASSERTが発生します。DLL側にセットされたリソースを読もうとはしていません。 これを回避するためにはDLLのインスタンスハンドルを取得して直接読むようにするのが良いと思います。 HMODULE  hModule ; HRSRC   hResource ; hModule    = ::GetModuleHandle( モジュール名 ) ; hResource    = ::FindResource( hModule, MAKEINTRESOURCE( リソースID ), RT_DIALOG ) ; m_hResGlobal  = ::LoadResource( hModule, hResource ) ; m_hResGlobalをクラスのメンバーとして保持しておき、 CTestDlg::Create( CWnd* const lpwndParent ) {    CDialog::CreateIndirect( m_hResGlobal, lpwndParent ) ; } とすればちゃんと表示されると思います。 各関数についてはヘルプを見てください。

take_716
質問者

お礼

takupyさん、レス有難うございました。 ご指摘のように、インスタンスハンドルを取得したのですが、 やはり、ASSERTが発生してしまいます。 デバックでチェックする限りでは、モジュールもリソースも 取得できているようなのですが・・・ HMODULE  hModule ; HRSRC   hResource ; hModule    = ::GetModuleHandle( _T("MFCdll") ) ; hResource    = ::FindResource( hModule, MAKEINTRESOURCE(IDD_DIALOG), RT_DIALOG ) ; m_hResGlobal  = ::LoadResource( hModule, hResource ) ; CTestDlg::Create( CWnd* const lpwndParent ) {    CDialog::CreateIndirect( m_hResGlobal, lpwndParent ) ;<=====この要求時のAfxGetResourceHandle()でASSERTが発生・・・ }

すると、全ての回答が全文表示されます。

その他の回答 (1)

  • redfox63
  • ベストアンサー率71% (1325/1856)
回答No.2

マネージドから呼び出した場合にMFC周りの初期化がうまくいっていないのが原因のようですよ VC++で Win32APPやMFCEXEで お作りになったMFCDLL.DLLのdispDlgを呼ぶようなアプリを作ってみてはいかがでしょう 多分アサートはされないはずです このとき dlg->Createから呼ばれたCDialog::Createで呼ばれる _AfxCheckDialogTemplate関数でAfxFindResourceHandleを呼び出します この中でAfxGetModuleStateで取得した pModuleStateメンバーの値と マネージから呼ばれた場合とで比較してみましょう マネージから呼ばれた場合 m_hCurrentResourceHandleなどのメンバーがNULLになっているようです

take_716
質問者

お礼

redfox63さん、有難うございます。 いろいろと試してみたのですが、結局、 マネージDLLで作り直す方向で考えています。 ご指導有難うございました。

すると、全ての回答が全文表示されます。

関連するQ&A