Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Show Dialog from MFC Extension DLL

1,019 views
Skip to first unread message

Nick Meyer

unread,
Feb 13, 2009, 11:56:54 AM2/13/09
to
Hi all,

I'm trying to show a dialog I've implemented inside an MFC extension DLL.
My app builds and compiles fine, but at runtime it's failing an assertion
during the initial call to the dialog's DoDataExchange method, where I've
mapped several controls using DDX_Control. The assertion is on line 42 of
dlgdata.cpp (VS2005 SP1) and it seems its because it can't find the control
with that ID. I've checked that the control with that ID is present on the
dialog. It's a regular modal dialog which I'm creating on the stack and then
calling DoModal.

Any "gotchas" I should know about showing dialogs defined in MFC extension
DLLs that might cause this problem?

Thanks,
Nick

Stephen Myers

unread,
Feb 13, 2009, 12:19:02 PM2/13/09
to

"Nick Meyer" wrote:

My guess is that the it can't find the dialog resource.

Are you using AFX_MANAGE_STATE(AfxGetStaticModuleState())?

David Ching

unread,
Feb 13, 2009, 12:36:14 PM2/13/09
to
"Stephen Myers" <Stephe...@discussions.microsoft.com> wrote in message
news:C3FF0CBC-F06E-4C4B...@microsoft.com...

>
> My guess is that the it can't find the dialog resource.
>
> Are you using AFX_MANAGE_STATE(AfxGetStaticModuleState())?
>

I never understood when you export a class in an MFC Extension DLL, do you
have to call AFX_MANAGE_STATE at the top of every method? This is a real
pain. And in this case where you export a class derived from CDialog, the
entry point is DoModal(), which is in CDialog, and is not overridden in the
derived class, so how do you call AFX_MANAGE_STATE in this case?

Thanks,
David

Stephen Myers

unread,
Feb 13, 2009, 1:51:00 PM2/13/09
to

"David Ching" wrote:

I agree that it's a pain. I'm working with regular DLL's so the rules may
be different. The trick is to have the proper hInstance when the dialog
resource is parsed. You might be able to get away with an override to
OnInitDialog.

Steve

Nick Meyer

unread,
Feb 13, 2009, 1:54:10 PM2/13/09
to
"David Ching" wrote:

> I never understood when you export a class in an MFC Extension DLL, do you
> have to call AFX_MANAGE_STATE at the top of every method? This is a real
> pain. And in this case where you export a class derived from CDialog, the
> entry point is DoModal(), which is in CDialog, and is not overridden in the
> derived class, so how do you call AFX_MANAGE_STATE in this case?
>

Hi Stephen and David,

My understanding is that AFX_MANAGE_STATE is only necessary in _regular_ MFC
DLLs, not _extension_ DLLs. At any rate, I tried that, and I found it made
the linker complain about redefinition of _DllMain. Not sure why.

I did find the problem, though -- the application was actually calling a
function inside the DLL itself that was attempting to create and display the
dialog. I added the following:

HINSTANCE hInstOld = ::AfxGetResourceHandle();
::AfxSetResourceHandle (McfCoreDLL.hModule);
// Dialog stuff
::AfxSetResourceHandle (hInstOld);

to change the resource handle to that of the DLL, and it worked.

I'm not sure I understand why this was necessary though -- if I understand
the MSDN docs correctly, executables can use resources from extension DLLs
they've loaded without knowing in which module the resources are defined.
Tracing through the CDialog::DoModal code, I find

if (m_lpszTemplateName != NULL)
{
hInst = AfxFindResourceHandle(m_lpszTemplateName, RT_DIALOG);
HRSRC hResource = ::FindResource(hInst, m_lpszTemplateName, RT_DIALOG);
hDialogTemplate = LoadResource(hInst, hResource);
}

executed. I thought that AfxFindResourceHandle would return the handle of
the DLL, not the handle of the EXE, but it seems it's returning the handle of
the EXE.

Maybe someone at MSFT or more experienced with the inner workings of MFC
DLLs can shed some light on this.

Thanks,
Nick

Ajay Kalra

unread,
Feb 13, 2009, 2:06:05 PM2/13/09
to
On Feb 13, 12:19 pm, Stephen Myers

You should never use AFX_MANAGE_STATE in a MFC Extension DLL. Its only
for MFC Regular DLLs.

--
Ajay

Ajay Kalra

unread,
Feb 13, 2009, 2:06:42 PM2/13/09
to
On Feb 13, 12:36 pm, "David Ching" <d...@remove-this.dcsoft.com>
wrote:
> "Stephen Myers" <StephenMy...@discussions.microsoft.com> wrote in message

>
> news:C3FF0CBC-F06E-4C4B...@microsoft.com...
>
>
>
> > My guess is that the it can't find the dialog resource.
>
> > Are you using AFX_MANAGE_STATE(AfxGetStaticModuleState())?
>
> I never understood when you export a class in an MFC Extension DLL, do you
> have to call AFX_MANAGE_STATE at the top of every method?

You dont ever use this macro in an Extension DLL.

--
Ajay

Stephen Myers

unread,
Feb 13, 2009, 2:06:10 PM2/13/09
to

"Nick Meyer" wrote:

Nick,

I wonder if it's due to a non-unique resource ID. If m_lpszTemplateName is
really just a UINT, it's quite possible the wrong resource would be located.

Regards,
Steve

Ajay Kalra

unread,
Feb 13, 2009, 2:15:09 PM2/13/09
to
On Feb 13, 11:56 am, Nick Meyer <NickMe...@discussions.microsoft.com>
wrote:

I dont know how your resoruces are setup but MFC extension DLLs, you
can chain resources together using CDynLinkLibrary. I dont understand
your problem though. If all your controls and dialog resides in one
DLL, you shouldnt have this problem as long as there is not ID
conflict. You must make sure that in extension DLLs *ALL* ids are
unique across all DLLs. You can ensure that by changing starting id in
resource.h.

Another method which I havent tried but is frequently mentioned in
this group is use of AfxSetResourceHandle. That may be a quick way to
get it working.

--
Ajay


Ajay Kalra

unread,
Feb 13, 2009, 2:20:46 PM2/13/09
to
On Feb 13, 1:54 pm, Nick Meyer <NickMe...@discussions.microsoft.com>
wrote:

> "David Ching" wrote:
> > I never understood when you export a class in an MFC Extension DLL, do you
> > have to call AFX_MANAGE_STATE at the top of every method?  This is a real
> > pain.  And in this case where you export a class derived from CDialog, the
> > entry point is DoModal(), which is in CDialog, and is not overridden in the
> > derived class, so how do you call AFX_MANAGE_STATE in this case?
>
> Hi Stephen and David,
>
> My understanding is that AFX_MANAGE_STATE is only necessary in _regular_ MFC
> DLLs, not _extension_ DLLs.  At any rate, I tried that, and I found it made
> the linker complain about redefinition of _DllMain.  Not sure why.

That is expected. You shouldnt use this macro in your case.


> I did find the problem, though -- the application was actually calling a
> function inside the DLL itself that was attempting to create and display the
> dialog.  I added the following:
>
> HINSTANCE hInstOld = ::AfxGetResourceHandle();
> ::AfxSetResourceHandle (McfCoreDLL.hModule);
> // Dialog stuff
> ::AfxSetResourceHandle (hInstOld);
>
> to change the resource handle to that of the DLL, and it worked.

That is what I mentioned in my other post. You can swap resouruce
handles at will or use CDynLinkLibrary(which I prefer).


> I'm not sure I understand why this was necessary though -- if I understand
> the MSDN docs correctly, executables can use resources from extension DLLs
> they've loaded without knowing in which module the resources are defined.  
> Tracing through the CDialog::DoModal code, I find

>         if (m_lpszTemplateName != NULL)
>         {
>                 hInst = AfxFindResourceHandle(m_lpszTemplateName, RT_DIALOG);
>                 HRSRC hResource = ::FindResource(hInst, m_lpszTemplateName, RT_DIALOG);
>                 hDialogTemplate = LoadResource(hInst, hResource);
>         }
>

> executed.  I thought that AfxFindResourceHandle would return the handle of
> the DLL, not the handle of the EXE, but it seems it's returning the handle of
> the EXE.

If you want your resoruces to be found by MFC, you should use
CDynLinkLibrary. If you use that, you dont have to do anything special
to swap resource handles etc. It will just work as MFC will find all
the ID in the resource chain that you constructed. Resources can span
multiple modules as long as they are put together in a chain.

--
Ajay

Nick Meyer

unread,
Feb 13, 2009, 2:24:00 PM2/13/09
to
"Stephen Myers" wrote:
> Nick,
>
> I wonder if it's due to a non-unique resource ID. If m_lpszTemplateName is
> really just a UINT, it's quite possible the wrong resource would be located.
>
> Regards,
> Steve

Hi Steve,

Ding ding ding! That was exactly the problem. The executable had a dialog
resource with the same ID as the DLL. I had searched the project for other
resources with the same ID as the control that MFC choked on, but not the
dialog. I guess changing the resource handle kept MFC from finding the one
in the executable first. After reassigning the conflicting IDs, it works.

Thanks,
Nick

Ajay Kalra

unread,
Feb 13, 2009, 3:20:52 PM2/13/09
to
On Feb 13, 2:24 pm, Nick Meyer <NickMe...@discussions.microsoft.com>
wrote:

What you have is a timebomb in your project. If you add another
resource in the module, it will conflict again. You need to change the
available ids for that module by editing resource.h. Each Extension
DLL in your solution should have an allocation of distinct IDs
otherwise you will have this perpetual problem.

--
Ajay

David Ching

unread,
Feb 13, 2009, 6:39:26 PM2/13/09
to
"Ajay Kalra" <ajay...@yahoo.com> wrote in message
news:fe1ee17c-77a9-43d0...@r41g2000yqm.googlegroups.com...

>> I never understood when you export a class in an MFC Extension DLL, do
>> you
>> have to call AFX_MANAGE_STATE at the top of every method?
>
>You dont ever use this macro in an Extension DLL.

Hmm, that sounds like a good enough reason to always create an Extension DLL
instead of a Regular DLL when exporting classes! I am trying to convert an
existing Win32 DLL to use MFC. Since it is a Win32 DLL, obviously it does
not export MFC classes yet, and I don't think it ever will. But it does
export a lot of normal C++ classes, and I can't see calling AFX_MANAGE_STATE
at the beginning of every method of those exported classes. But if you
don't have to in an Extension DLL, maybe I should just make it an Extension
DLL. Do you see any disadvantage to that?

Thanks,
David

Ajay Kalra

unread,
Feb 15, 2009, 12:02:39 AM2/15/09
to

"David Ching" <d...@remove-this.dcsoft.com> wrote in message
news:590BC17E-56DD-4806...@microsoft.com...

In a regular DLL, you can get away without using this macro if you dont plan
to use any resources in that method. However its a good practice to do it
but its mainly done to point to the right module for resources. If your DLL
is meant to be used only by MFC client, make it a Extnesion DLL otherwise go
with Regular DLL. I always go with a Extension DLL unless I want it to be
Regular for reason mentioned above.

--
Ajay

David Webber

unread,
Feb 15, 2009, 12:50:18 PM2/15/09
to

"Ajay Kalra" <ajay...@yahoo.com> wrote in message
news:51231156-b62e-4ff9...@t11g2000yqg.googlegroups.com...

On Feb 13, 11:56 am, Nick Meyer <NickMe...@discussions.microsoft.com>
wrote:

>...


Another method which I havent tried but is frequently mentioned in
this group is use of AfxSetResourceHandle. That may be a quick way to
get it working.<

I have never understood AFX_MANAGE_STATE( ) but I use
AfxSetResourceHandle( ) absolutely everwhere, as I have lots of DLLs with
resources.

In fact in each DLL with resources I have an exported class, whose sole
responsibility is to load resources belonging to the DLL.

There's a member function for loading each dialogue of the form
(schematically)

1. remember the current resource handle found with GetResourceHandle();
2. SetResourcehandle() to the DLL's handle.
3. Construct the modal dialogue class
4. Call its DoModal()
5. Reset the resource handle you found on entry - with SetResourceHandle()

The class does this also had members for loading strings, bitmaps, and
icons: wrappers around the API functions which manage the handles.

(It works fine and is very stable, but the only thing I haven't worked out
is how the various MFC language DLLs can be handled.)

Dave
--
David Webber
Author of 'Mozart the Music Processor'
http://www.mozart.co.uk
For discussion/support see
http://www.mozart.co.uk/mozartists/mailinglist.htm

Joseph M. Newcomer

unread,
Feb 15, 2009, 1:10:56 PM2/15/09
to
Note that when you do the stack backtrace, the line you are shown in the DDX_Control is
the line AFTER the one that fails...
joe

On Fri, 13 Feb 2009 08:56:54 -0800, Nick Meyer <Nick...@discussions.microsoft.com>
wrote:

Joseph M. Newcomer [MVP]
email: newc...@flounder.com
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm

Joseph M. Newcomer

unread,
Feb 15, 2009, 6:57:32 PM2/15/09
to
If it can't find the resource, I believe it asserts long before the DDX_Control events,
somewhere in the attempt to create the dialog. Looking at the output in the Debug window
would also help.
joe

On Fri, 13 Feb 2009 09:19:02 -0800, Stephen Myers <Stephe...@discussions.microsoft.com>
wrote:

Ajay Kalra

unread,
Feb 16, 2009, 10:00:43 AM2/16/09
to

"David Webber" <da...@musical-dot-demon-dot-co.uk> wrote in message
news:ucw1yX5j...@TK2MSFTNGP02.phx.gbl...

>
> "Ajay Kalra" <ajay...@yahoo.com> wrote in message
> news:51231156-b62e-4ff9...@t11g2000yqg.googlegroups.com...
> On Feb 13, 11:56 am, Nick Meyer <NickMe...@discussions.microsoft.com>
> wrote:
>
>>...
> Another method which I havent tried but is frequently mentioned in
> this group is use of AfxSetResourceHandle. That may be a quick way to
> get it working.<
>
> I have never understood AFX_MANAGE_STATE( ) but I use
> AfxSetResourceHandle( ) absolutely everwhere, as I have lots of DLLs with
> resources.
>

You cant get away from AFX_MANAGE_STATE if you have resources in a Regular
DLL. For an Extension DLL, it has no meaning. As far as AfxResourceHandle is
concerned, I never used it only because I used CDynLinkLibrary, which allows
resource chaining and it works well, especially if you have resources spread
over many many modules.

--
Ajay

Leo Violette

unread,
Feb 23, 2009, 7:08:03 AM2/23/09
to
I actually like using a regular DLL as it allows my dialog to be displayed
and used by both MFC applications as well as non-MFC applications.

I simplify things by exporting a non-MFC class that "represents" my dialog.
I add a DoModal (or ShowDialog) method to this class.

In the .cpp file, I #include the header file that contains the real dialog
declaration. And in the implementation of my DoModal, I call
AFX_MANAGE_STATE, then create the dialog object and call DoModal on it.
This way, the user of the DLL only sees the header
file that has no MFC in it, so they aren't exposed to it (this is what
allows ATL and console applications to use the DLL to show the dialog).

This works well for shared dialogs and also allows me to add other methods
to the exported class, like setting up inital values that I will
pass to the real dialog class. This has worked quite well for me in the
vast majority of situations and I've had no worries about sharing
resource ID's that come up with extension DLLs.

"David Ching" <d...@remove-this.dcsoft.com> wrote in message
news:590BC17E-56DD-4806...@microsoft.com...

David Ching

unread,
Feb 23, 2009, 9:28:36 AM2/23/09
to
"Leo Violette" <nineb...@comcast.net> wrote in message
news:2F1F182B-7983-4A39...@microsoft.com...

>I actually like using a regular DLL as it allows my dialog to be displayed
>and used by both MFC applications as well as non-MFC applications.
>
> I simplify things by exporting a non-MFC class that "represents" my
> dialog. I add a DoModal (or ShowDialog) method to this class.
>
> In the .cpp file, I #include the header file that contains the real dialog
> declaration. And in the implementation of my DoModal, I call
> AFX_MANAGE_STATE, then create the dialog object and call DoModal on it.
> This way, the user of the DLL only sees the header
> file that has no MFC in it, so they aren't exposed to it (this is what
> allows ATL and console applications to use the DLL to show the dialog).
>
> This works well for shared dialogs and also allows me to add other methods
> to the exported class, like setting up inital values that I will
> pass to the real dialog class. This has worked quite well for me in the
> vast majority of situations and I've had no worries about sharing
> resource ID's that come up with extension DLLs.
>

Yes, it sounds like this is a good solution for you. My DLL contains many
exported classes, none of which have anything to do with resources, so
thanks to Ajay for saying I don't need to call AFX_MANAGE_STATE even if it
is a Regular MFC DLL.

-- David

Ajay

unread,
Feb 23, 2009, 9:59:42 AM2/23/09
to
On Feb 23, 9:28 am, "David Ching" <d...@remove-this.dcsoft.com> wrote:
> "Leo Violette" <ninebal...@comcast.net> wrote in message

I was incomplete though. You need to make sure that you may need it
*if* you want to get to app state rather than your module's. For
example, AfxGetMainWnd will return null in your Regular DLL unless you
use AFX_MANAGE_STATE(of the app).

--
Ajay

David Ching

unread,
Feb 23, 2009, 12:50:31 PM2/23/09
to
"Ajay" <ajay...@yahoo.com> wrote in message
news:a8ec7f3c-08f9-49b6...@q9g2000yqc.googlegroups.com...

> I was incomplete though. You need to make sure that you may need it
> *if* you want to get to app state rather than your module's. For
> example, AfxGetMainWnd will return null in your Regular DLL unless you
> use AFX_MANAGE_STATE(of the app).

Thanks Ajay, that's clear enough. Not what I wanted to hear, but ....

-- David

0 new messages