いつもお世話になっています。
アプリとDLLをVC++,MFCで作成しています。
DLL側でダイアログをモードレスで表示させるため、
アプリ側からCWnd*を渡して、DLL側でHoge->Create(pWnd)とすると
強制終了してしまいます。
アプリ側
HogeDllFunc(this);
DLL側
void HogeDllFunc(CWnd* pWnd)
{
pHogeDlg = new CHogeDlg;
pHogeDlg->Create(pWnd);
}
CWndの渡し方の問題でしょうか?
ご教授願います。
リソース問題じゃないの?
DLLと本体では別のリソースが参照されるから
そこらへんをググってとあるキーワードを入れれば解決する希ガス
返信有難うございます。
AFX_MANAGE_STATE(AfxGetStaticModuleState());
は既に記述してあります。
DLL側
void HogeDllFunc(CWnd* pWnd)
{
pHogeDlg = new CHogeDlg;
pHogeDlg->Create(pWnd);
}
[補足]
※ pHogeDlgはDLL側に作成したダイアログのインスタンスです。
サイトのサンプルでは同じ渡し方をしているんですが
なぜだめなのかわかりません。
どんなサンプルを参照されたかわかりませんが
void HogeDllFunc(CWnd* pWnd)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
pHogeDlg = new CHogeDlg;
pHogeDlg->Create(pWnd);
}
が正しいんじゃないのかな
何度も有難うございます。
ご提示頂いたコードでもだめでした。
pHogeDlg->Create(pWnd);
で強制終了してしまいます。
ちなみにDLL内で
pWnd->MessageBox()
とやると正常に表示されるので、pWndは正常に渡っていると思われます。
どなたか同じ現象を見たことある方はいらっしゃいますでしょうか?
うーーん、
まず、サンプルもDLLなんですか?
Create文のパラメータですが、
Create(UINT nID,CWnd *pWnd);
ですよね。
CWnd *pWndは省略できても、nIDは省略できないことになってます。
あと、実際CWnd *pWndも省略できないです。
「m_hWnd==NULL」等の例外が発生します。
pWndは親ウィンドウのCWndです。
thisポインタじゃまずいのでは?
>pHogeDlg->Create(pWnd);
>で強制終了してしまいます。
こうではなく。
void CXXX::OpenDlg()
{
Create(nID,pWnd);
}
で、
pHogeDlg->OpenDlg();
でないとまずいと思います。
hogeがcreateをオーバーライドして自前でIDDを
入れてるとか邪推したんだけど
hoge::create(CWnd* p)
{
CDialog::Create(IDD, p);
}
的な。主の連絡を待ちますか。
皆様、ありがとうございます。
とおりすがり様の言う通り、Createは
BOOL hoge::create(CWnd* p)
{
return CDialog::Create(IDD, p);
}
となっています。説明不足ですいません。
参考にしたサイトは以下です。
http://www.kab-studio.biz/Programing/Codian/DLL_Hook_SClass/05.html
エクスポートはしていません。
参考にしたのは親ダイアログのCWndをDLL側に渡す方法だけです。
アプリ側のダイアログを親したダイアログをDLL側から起動したいだけです。
エクスポートしていません?何だか良くわからなくなってきた。
まずはデバッグしてみては如何かな?
いろいろ略します。
exe側
extern C
{
__declspec(dllexport) void __cdecl DllFunc(CWnd* pWnd);
}
void ExeFunc(CWnd* pWnd)
{
LoadLibrary、GetProcAddressなど
(*_DllFunc)(AfxGetMainWnd());
}
dll側
extern C
{
__declspec(dllexport) void __cdecl DllFunc(CWnd* pWnd);
}
void DllFunc(CWnd* pWnd)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
hoge dlg = new hoge;
hoge->create(pWnd);
hoge->ShowWindow(SW_SHOW);
}
こんな感じでいけるはずなんだけど。
すいません、できません..
>エクスポートしていません?何だか良くわからなくなってきた。
アプリ側でLibをリンクして、DLL側のヘッダをインクルードしています。
アプリ側でもモードレスダイアログを表示させる個所がありますが
Create(this)で問題なく動いているので、
DLL側で表示させるのも同じようにすればよいと思っているのですが...
もう少し調べてみます。
試してみました。
exe側の呼び出し
DllFunc(::AfxGetApp()->m_pMainWnd);
dll側
CConfigrationDialog* g_pDlg;
void __declspec(dllexport) __cdecl DllFunc(CWnd* pParent)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
// pParent->MessageBox(_T(Called DllFunc));
if (g_pDlg == 0)
{ g_pDlg = new CTestDialog(pParent);
g_pDlg->Create(CTestDialog::IDD, pParent);
g_pDlg->ShowWindow(SW_SHOW);
} else
{ delete pDlg;
pDlg = 0;
}
}
だと、確かにCWnd::AssertValid()でアサートが発生。thisはCFrameWndオブジェクト。
g_pDlg->Create(CTestDialog::IDD, 0);
にするとうまく動いている(ように見える)。なぜだろう。
なお、CDialog::Create()の説明には
「pParentWnd が NULL の場合は、作成されるダイアログ ボックスの親ウィンドウまた
はオーナー ウィンドウは、アプリケーションのメイン ウィンドウに設定されます。」
と書いてあるので、
Create(CTestDialog::IDD);
でもとりあえずいいんじゃないかな。
maru様、わざわざ有難うございます。
私のところだけだと思っていましたが、ほかでもでるんですね。
>Create(CTestDialog::IDD);
>でもとりあえずいいんじゃないかな。
上記だと確かに正常に表示されますが、親ウィンドウが設定されていないため
子ダイアログ(DLL側の画面)表示中に、下の画面(アプリ側の呼び出し元画面)のボタン等が
押下可能になってしまうのが、うまくありません。
もう少し調べてみます。
> 子ダイアログ(DLL側の画面)表示中に、下の画面(アプリ側の呼び出し元画面)のボタン
等が
> 押下可能になってしまうのが、うまくありません。
私の環境では、呼び出し元の画面を問題なく操作出来ています。
というか、モードレスダイアログなんだから、下の画面が操作出来ないのは問題外。
モードレスとモーダルの動きを勘違いしているような気がします。
モードレスの場合、自動で親ウインドウも含めて他のウインドウを無効化する事は
無いはずです。なので、操作が出来て正常です。
押下可能と言う部分が仕様にあっていないのであれば、モードレスにする事自体が
おかしいのではと言う気がします。
普通はこう言う動きを期待するのであれば、モーダルダイアログにします。
あと、COFさんの現象とmaruさんの現象が全く同じなのかも分からないですよね。
COFさんの場合でもデバッグモードならCWnd::AssertValid()でアサートが発生するんで
しょうか?
アサートが発生するのであれば、なぜアサートが発生するのかまで確認した方が良いよう
な気もします。
それとも強制終了と言うのがアサートの事なのかなぁ。