It seems to be quite easy to export dialogs from
mfc-extension dll's.
Just export the corresponding class with
AFX_EXT_CLASS
and your done. If you do so with an application
and a dll you create from scratch you probably
even will succeed. But if you insert more and
more resources in both the application and the
dll,
you will get some serious bugs. Here is the
reason:
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 "extension
DLL". 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
extension DLL.
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.
News:
1 UCanCode Advance E-XD++
CAD Drawing and Printing Solution
Source Code Solution for C/C++, .NET V2023 is released!
2
UCanCode Advance E-XD++
HMI & SCADA Source Code Solution for C/C++, .NET V2023 is released!
3
UCanCode
Advance E-XD++ GIS SVG Drawing and Printing Solution
Source Code Solution for C/C++, .NET V2023 is released!