Export dialogs in MFC Extension DLLs
The regular way to identify a specific resource is its ID. This is an integer constant defined by the resource editor. Now say you have got a resource (which is a string) called ID_MY_TEXT.
CString strText; strText.LoadString( ID_MY_TEXT ); afxDump << strText;
Code like this prints the resource-string into the debug window. Sometimes you may get a wrong text and this happens only if the text is in a mfc-extension-dll (mfc-ext-dll). The reason for this error lies in the way the application gets a resource. Since both the application and the dll can have a resource file, IDs can be the same for different resources. (Which is very likely because the VC resource editor starts numbering the IDs at a certain value for each module.)
As you may guess the order the application searches for a resource is first in your application and afterwards in your dll(s) (and finally in the mfc-resources). We need to change the search order for resources.
There is another article on this site which deals with dialog exports from DLL's. But that (as far as I have tested) works only in regular-mfc-dlls.
I wrote a class that (with a little change in the dll main source file and the dialog) will enable you to freely call your dialog from wherever you want. Like:
CMyApp::OnDLLDialog()
{
CDLLDialog dlg;
dlg.DoModal();
}
As you see there is no need for an export function (which would not be very OO).
I wrote a simple class that sets the resource handle of the dll at its construction and sets back the previous handle at its destruction.
Here it is:
/////////////////////////////////////////////////////////////////////////////////////////////
// File ExtDllState.h
////////////////////////////////////////////////////////////////////////////////////////////
#ifndef __EXTDLLSTATE_H__
#define __EXTDLLSTATE_H__
class CEXTDLLState
{
public:
CEXTDLLState();
~CEXTDLLState();
protected:
HINSTANCE m_hInstOld;
};
#endif
////////////////////////////////////////////////////////////////////////////////////////////
File ExtDllState.cpp
////////////////////////////////////////////////////////////////////////////////////////////
CEXTDLLState::CEXTDLLState()
{
m_hInstOld = AfxGetResourceHandle();
AfxSetResourceHandle(extensionDLL.hModule);
}
CEXTDLLState::~CEXTDLLState()
{
AfxSetResourceHandle(m_hInstOld);
}
//////////////////////////////////////////////////////////////////////////////////////
Quite short as you may see, but there is a little more to do:
Copy the class texts from above into the files ExtDllState.h and ExtDllState.cpp. Put BOTH files in a public include directory where every project can reach it. In your DLL go to the main source file (which is named after the DLL). Here you find something like this:
static AFX_EXTENSION_MODULE MY_DLL_NAMEDLL = { NULL, NULL };
where MY_DLL_NAME your dll name is (:
Replace this variable name with "extensionDLL". Below this line put the following lines:
#include "EXTDLLState.h"
#include "ExtDllState.cpp"
Look for occurrences of MY_DLL_NAMEDLL in the rest of the file and replace it with extensionDLL. Occurrences can only happen in this file since the variable is static.
Now if you want to export a Dialog go into the source file of the corresponding class and include EXTDLLState.h again. Override the function DoModal() (Best done with the ClassWizard). You should get something like:
int CMyDLLDlg::DoModal()
{
// TODO: Add your specialized code here and/or call the base class
return CDialog::DoModal();
}
replace the TODO line with "CEXTDLLState State;". Now it looks like
int CDLLDlgDlg::DoModal()
{
CEXTDLLState State;
return CDialog::DoModal();
}
With this approach you got a comfortable way to export classes that use resources. Be aware that if you need resources in other places too, to define CEXTDLLState before use. (Especially this must be done with modeless dialogs!!!).
You can use CEXTDLLState everywhere you want to access resources in mfc-ext-dlls. You will always get the right thing. I hope this will help some of you, since I had some troubles till I found an easy and nice way to do handle this.

Comments
Assertion failute in Debug build
Posted by rahul.shukla on 09/09/2008 02:17amHi, I have created an MFC extension DLL, And did the same thing but its giving assertion failure at m_hInstOld = AfxGetResourceHandle(); Its because of ... _AFXWIN_INLINE HINSTANCE AFXAPI AfxGetResourceHandle() { ASSERT(afxCurrentResourceHandle != NULL); return afxCurrentResourceHandle; } I am not able to find out How the afxCurrentResourceHandle is getting NULL.ReplyAlternate Approach
Posted by Atul Arora on 03/08/2004 12:55amHi Andreas, Good article. I found an alternate approach to do this. You dont have to make a new class. Instead, AFX_MANAGE_STATE(AfxGetStaticModuleState( )); in the function int CDLLDlgDlg::DoModal() { AFX_MANAGE_STATE(AfxGetStaticModuleState( )); return CDialog::DoModal(); } Call this function to set the module state before initialization and/or to restore the previous module state after cleanup (end of current scope). By default, MFC uses the resource handle of the main application to load the resource template. If you have an exported function in a DLL, such as one that launches a dialog box in the DLL, this template is actually stored in the DLL module. You need to switch the module state for the correct handle to be used. You can do this by adding the following code to the beginning of the function: AFX_MANAGE_STATE(AfxGetStaticModuleState( )); So, you dont require a new class to manage this.ReplyAlternate Approach
Posted by Atul Arora on 03/08/2004 12:52amHi Andreas, Good article. I found an alternate approach to do this. You dont have to make a new class. Instead, AFX_MANAGE_STATE(AfxGetStaticModuleState( )); in the function int CDLLDlgDlg::DoModal() { AFX_MANAGE_STATE(AfxGetStaticModuleState( )); return CDialog::DoModal(); } Call this function to set the module state before initialization and/or to restore the previous module state after cleanup (end of current scope). By default, MFC uses the resource handle of the main application to load the resource template. If you have an exported function in a DLL, such as one that launches a dialog box in the DLL, this template is actually stored in the DLL module. You need to switch the module state for the correct handle to be used. You can do this by adding the following code to the beginning of the function: AFX_MANAGE_STATE(AfxGetStaticModuleState( )); So, you dont require a new class to manage this.ReplyHow to convert pdf file to text file in vb & vc?
Posted by Legacy on 11/07/2003 12:00amOriginally posted by: prajakta
I have a code of pdf2txt but it converts only 1st 3 pages from pdf to txt. can anyone help me how to change the content of that dll, so that i can convert the whole pdf file to the txt.
ReplyGreat work
Posted by Legacy on 08/14/2003 12:00amOriginally posted by: Aman
This had really helped me. Thanx!!
Replyhow can I Add Progress control into win32 dll(not use MFC dll),
Posted by Legacy on 11/22/2002 12:00amOriginally posted by: ttmonkey
how can I Add Progress control into win32 dll(not use MFC dll),
ReplyDynamic Loading DLL with class export.
Posted by Legacy on 06/25/2002 12:00amOriginally posted by: Mac
I've a dll Which exports a Class. How do I dynamically load it?
Thank you.
ReplyMac
ExtFloodFill
Posted by Legacy on 05/20/2002 12:00amOriginally posted by: shankar reddy
please explain how to use ExtFloodFill function
Replyneed help
Posted by Legacy on 11/07/2001 12:00amOriginally posted by: yujie_cai
I can't make it work!
ReplyWho can send me a simple sample in MFC.Thank you very much
Dialogs in MFC extension DLL's
Posted by Legacy on 10/04/2001 12:00amOriginally posted by: Brad Vrabete
Hi,
I have problems creating dialogs from within a class defined in an MFC extension dll. The most annoying fact is that it was working under Windows NT but it is no longer working under W2K. I tried all the suggestions posted here but nothing seems to help. Any idea?
ReplyLoading, Please Wait ...