モードレスダイアログについて – プログラミング – Home

モードレスダイアログについて
 
通知
すべてクリア

[解決済] モードレスダイアログについて

固定ページ 1 / 2

COF
 COF
(@COF)
ゲスト
結合: 15年前
投稿: 53
Topic starter  

いつもお世話になっています。

アプリとDLLをVC++,MFCで作成しています。

DLL側でダイアログをモードレスで表示させるため、
アプリ側からCWnd*を渡して、DLL側でHoge->Create(pWnd)とすると
強制終了してしまいます。

アプリ側
HogeDllFunc(this);

DLL側
void HogeDllFunc(CWnd* pWnd)
{
pHogeDlg = new CHogeDlg;
pHogeDlg->Create(pWnd);
}

CWndの渡し方の問題でしょうか?
ご教授願います。


引用未解決
トピックタグ
とおりすがり
 とおりすがり
(@とおりすがり)
ゲスト
結合: 23年前
投稿: 180
 

リソース問題じゃないの?
DLLと本体では別のリソースが参照されるから
そこらへんをググってとあるキーワードを入れれば解決する希ガス


返信引用
COF
 COF
(@COF)
ゲスト
結合: 15年前
投稿: 53
Topic starter  

返信有難うございます。

AFX_MANAGE_STATE(AfxGetStaticModuleState());
は既に記述してあります。

DLL側
void HogeDllFunc(CWnd* pWnd)
{
pHogeDlg = new CHogeDlg;
pHogeDlg->Create(pWnd);
}
[補足]
※ pHogeDlgはDLL側に作成したダイアログのインスタンスです。

サイトのサンプルでは同じ渡し方をしているんですが
なぜだめなのかわかりません。


返信引用
とおりすがり
 とおりすがり
(@とおりすがり)
ゲスト
結合: 23年前
投稿: 180
 

どんなサンプルを参照されたかわかりませんが
void HogeDllFunc(CWnd* pWnd)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
pHogeDlg = new CHogeDlg;
pHogeDlg->Create(pWnd);
}
が正しいんじゃないのかな


返信引用
COF
 COF
(@COF)
ゲスト
結合: 15年前
投稿: 53
Topic starter  

何度も有難うございます。

ご提示頂いたコードでもだめでした。

pHogeDlg->Create(pWnd);
で強制終了してしまいます。

ちなみにDLL内で
pWnd->MessageBox()
とやると正常に表示されるので、pWndは正常に渡っていると思われます。

どなたか同じ現象を見たことある方はいらっしゃいますでしょうか?


返信引用
ITO
 ITO
(@ITO)
ゲスト
結合: 22年前
投稿: 1235
 

うーーん、
まず、サンプルもDLLなんですか?

Create文のパラメータですが、
 Create(UINT nID,CWnd *pWnd);
ですよね。

CWnd *pWndは省略できても、nIDは省略できないことになってます。
あと、実際CWnd *pWndも省略できないです。
「m_hWnd==NULL」等の例外が発生します。

pWndは親ウィンドウのCWndです。
thisポインタじゃまずいのでは?


返信引用
ITO
 ITO
(@ITO)
ゲスト
結合: 22年前
投稿: 1235
 

>pHogeDlg->Create(pWnd);
>で強制終了してしまいます。
こうではなく。
void CXXX::OpenDlg()
{
Create(nID,pWnd);
}
で、
pHogeDlg->OpenDlg();
でないとまずいと思います。


返信引用
とおりすがり
 とおりすがり
(@とおりすがり)
ゲスト
結合: 23年前
投稿: 180
 

hogeがcreateをオーバーライドして自前でIDDを
入れてるとか邪推したんだけど
hoge::create(CWnd* p)
{
CDialog::Create(IDD, p);
}
的な。主の連絡を待ちますか。


返信引用
COF
 COF
(@COF)
ゲスト
結合: 15年前
投稿: 53
Topic starter  

皆様、ありがとうございます。

とおりすがり様の言う通り、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側から起動したいだけです。


返信引用
とおりすがり
 とおりすがり
(@とおりすがり)
ゲスト
結合: 23年前
投稿: 180
 

エクスポートしていません?何だか良くわからなくなってきた。
まずはデバッグしてみては如何かな?
いろいろ略します。

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);
}
こんな感じでいけるはずなんだけど。


返信引用
COF
 COF
(@COF)
ゲスト
結合: 15年前
投稿: 53
Topic starter  

すいません、できません..

>エクスポートしていません?何だか良くわからなくなってきた。
アプリ側でLibをリンクして、DLL側のヘッダをインクルードしています。

アプリ側でもモードレスダイアログを表示させる個所がありますが
Create(this)で問題なく動いているので、
DLL側で表示させるのも同じようにすればよいと思っているのですが...

もう少し調べてみます。


返信引用
maru
 maru
(@maru)
ゲスト
結合: 17年前
投稿: 358
 

試してみました。
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);
でもとりあえずいいんじゃないかな。


返信引用
COF
 COF
(@COF)
ゲスト
結合: 15年前
投稿: 53
Topic starter  

maru様、わざわざ有難うございます。

私のところだけだと思っていましたが、ほかでもでるんですね。

>Create(CTestDialog::IDD);
>でもとりあえずいいんじゃないかな。
上記だと確かに正常に表示されますが、親ウィンドウが設定されていないため
子ダイアログ(DLL側の画面)表示中に、下の画面(アプリ側の呼び出し元画面)のボタン等が
押下可能になってしまうのが、うまくありません。

もう少し調べてみます。


返信引用
maru
 maru
(@maru)
ゲスト
結合: 17年前
投稿: 358
 

> 子ダイアログ(DLL側の画面)表示中に、下の画面(アプリ側の呼び出し元画面)のボタン
等が
> 押下可能になってしまうのが、うまくありません。
私の環境では、呼び出し元の画面を問題なく操作出来ています。
というか、モードレスダイアログなんだから、下の画面が操作出来ないのは問題外。


返信引用
PATIO
(@patio)
Famed Member
結合: 3年前
投稿: 2660
 

モードレスとモーダルの動きを勘違いしているような気がします。
モードレスの場合、自動で親ウインドウも含めて他のウインドウを無効化する事は
無いはずです。なので、操作が出来て正常です。
押下可能と言う部分が仕様にあっていないのであれば、モードレスにする事自体が
おかしいのではと言う気がします。
普通はこう言う動きを期待するのであれば、モーダルダイアログにします。

あと、COFさんの現象とmaruさんの現象が全く同じなのかも分からないですよね。
COFさんの場合でもデバッグモードならCWnd::AssertValid()でアサートが発生するんで
しょうか?
アサートが発生するのであれば、なぜアサートが発生するのかまで確認した方が良いよう
な気もします。
それとも強制終了と言うのがアサートの事なのかなぁ。


返信引用
固定ページ 1 / 2

返信する

投稿者名

投稿者メールアドレス

タイトル *

プレビュー 0リビジョン 保存しました
共有:
タイトルとURLをコピーしました