こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

アンマネージ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 ;
}

ご存知の方がいらっしゃれば、ご教授ください。
よろしくお願いします。

投稿日時 - 2009-07-14 00:46:07

QNo.5123713

困ってます

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

こんにちは。
異なる言語を使ったプログラムは組んだことないのですが、多分同じではないかと思ってレスさせてください。


質問で書かれているプログラムでは、恐らく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 ) ;
}

とすればちゃんと表示されると思います。
各関数についてはヘルプを見てください。

投稿日時 - 2009-07-14 10:07:41

お礼

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が発生・・・
}

投稿日時 - 2009-07-14 13:25:06

ANo.1

このQ&Aは役に立ちましたか?

0人が「このQ&Aが役に立った」と投票しています

回答(2)

ANo.2

マネージドから呼び出した場合にMFC周りの初期化がうまくいっていないのが原因のようですよ

VC++で Win32APPやMFCEXEで お作りになったMFCDLL.DLLのdispDlgを呼ぶようなアプリを作ってみてはいかがでしょう
多分アサートはされないはずです

このとき dlg->Createから呼ばれたCDialog::Createで呼ばれる
_AfxCheckDialogTemplate関数でAfxFindResourceHandleを呼び出します
この中でAfxGetModuleStateで取得した pModuleStateメンバーの値と

マネージから呼ばれた場合とで比較してみましょう
マネージから呼ばれた場合 m_hCurrentResourceHandleなどのメンバーがNULLになっているようです

投稿日時 - 2009-07-15 01:26:47

お礼

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

投稿日時 - 2009-07-15 23:37:32

あなたにオススメの質問