Using DLLs in an EXE
Stig Hellholm -- stig.hellholm@sands.se
Monday, July 08, 1996
Environment: VC++ 4.1 / MFC 4.0 / NT4.0
I have an application that I would like to slpit into one DLL (which
can be used by other applications) and an EXE. I use the dll just fine
but when I'm using a dialog in the dll it fails. The DoModal function
returns -1. When I debug it it fails on allocating a resource for the
Dialog.
Have I missed something obvious or????
Any help will be appreciated.
:-) Stig Hellholm
Bill Campbell -- bill_campbell@ppp.ablecom.net
Friday, July 12, 1996
[Mini-digest: 5 responses]
Stig,
You need to set the resource handle to your dll...
Have a global handle
HINSTANCE hDllInstance;
In Dll main assign it
in DllMain(...HINSTANCE hin...)
{
hDllInstance=hin;
}
Before you call your dialog
HINSTANCE hOld = AfxGetInstanceHandle() // get current running instance
AfxSetResourceHandle(hInstance);
DOModal etc
AfxSetResourceHandle(hold) // remember to set it back
hope this helps I know it works
Bill
-----From: Prasad Vemuri
I Assume you are using Microsoft Extension DLL's:
Calling the DoModal() of the dialog that is there in DLL would cause
this kind of problem, Because the Executable resources are searched for the dialog ResoiurceID.
You need to set the resource handle of the DLL to be the App resource handle
and Call the DoModal() by overriding the function int CDialog::DoModal(). After
the call set the resource handle back to the Application. The sample
code looks like this..
/////////
ourdlg.cpp
extern AFX_EXTENSION_MODULE extensionDLL;
int COurDialog::DoModal()
{
HINSTANCE hAppRes = AfxGetResourceHandle();
if ( (!hAppRes) || (!extensionDLL.hResource))
return -1;
AfxSetResourceHandle(extensionDLL.hResource);
int nRet = CDialog::DoModal();
// Set the resource handle back,,
AfxSetResourceHandle(hAppRes);
return nRet;
}
/////////////////////
In DLL write the following code, part of it was generated by the
AppWizard.
extern AFX_EXTENSION_MODULE extensionDLL = {NULL,NULL};
extern "C" int APIENTRY
DLLMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
{
if (dwReason == DLL_PROCESS_ATTACH)
{
TRACE0("Your Dll Initializing!\n");
AfxInitExtensionModule(extensionDLL, hInstance);
// Insert this DLL into the resource chain
new CDynLinkLibrary(extensionDLL, hInstance);
}
else if (dwReason == DLL_PROCESS_DETACH)
{
TRACE0("Your DLL Terminating!\n");
}
return 1; // OK
}
/////////////////////////////////////////////////////////////
Hope this would solve your problem..
Prasad Vemuri(K.P)....
******************************************************************************
Prasad V Vemuri (K.P) TSI VISION (Switch Interfaces)
Technical Consultant CSC Communications Industry Services
Voice.(217)351-8250 Ext:2293 TRIS Division
Fax.(217)351-2640 115 North Neil
Email: pvemuri@mars.csci.csc.com Champaign, IL 61824-0770
*****************************************************************************
-----From: Tim Peacock
This is due to module state. Try to read TN058 and the MFC encyclopaedia
article "Managing the State Data of MFC Modules", both on MSDN.
MFC usually operates in the 'state' of the calling module, so that when you
instantiate a dialogue (for example) the resource is loaded using the
callers state. This means that MFC will pick up the resource from your program
- just what you want. In an extension DLL you usually want the same
behaviour because you're just extending the behaviour of MFC, so no extra
work has to be done.
However, in a non-extension DLL, such as yours, with its own resources,
what you want is for the MFC
routines in the DLL to pick up the resources of the *DLL*, not the calling
module. This is why the AppWizard instantiates an apparently useless
CWinApp object in your DLL - don't trash it because it initialises
your DLL's module state. The next thing you have to do is to manually switch
state at the entry points to your DLL using the AFX_MANAGE_STATE macro.
Since you can't really predict what MFC is going to do in the background and
you must switch state *every* time a DLL boundary is crossed, the only
recourse you have is to severely restrict your exported interface. What i
usually do is to export a single function for each dialogue. That routine
instantiates the dialogue and returns the result of DoModal. Don't export
the dialogue class, it's real trouble.
>From recent correspondence i'd suggest avoiding instantiating threads
in a non-extension DLL as well - i've never seen any documentation or
useful discussion on the interaction of thread and module state.
Best of luck and don't give up.
tim.
-----From: Paulo Soares
You are probably loading the resources from the EXE instead of the DLL. Here's the code that I use to avoid this:
int MyClass::DoModal()
{
HINSTANCE mymod;
mymod = AfxGetResourceHandle();
AfxSetResourceHandle(GetModuleHandle("MyDllName"));
int i = CDialog::DoModal();
AfxSetResourceHandle(mymod);
return i;
}
Best Regards,
Paulo Soares
psoares@ip.pt
-----From: "Grant Shirreffs (Great Elk)"
At a guess, you're using the MFC in a DLL as well. To make your DLL find
the dialog box resource it needs, you need to put the following at the
start of all exported entry-point functions in your DLL:
AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
Without this, the DLL will look for its resources in the EXE file.
Grant Shirreffs
grant.s@greatelk.co.nz
Mario Contestabile -- Mario_Contestabile.UOS__MTL@UOSMTL2.universal.com
Monday, July 15, 1996
[Mini-digest: 3 responses]
>I have an application that I would like to slpit into one DLL (which
>can be used by other applications) and an EXE. I use the dll just fine
>but when I'm using a dialog in the dll it fails. The DoModal function
>returns -1. When I debug it it fails on allocating a resource for the
>Dialog.
See AfxSetResourceHandle() and TN057.
mcontest@universal.com
-----From: Greg Dean
You need to use AfxSetResourceHandle() to access resources in your DLL.
By default, when you load a resource it gets it from the app. In your
DLL where you're going to use a resource, save the current resource
handle using AfxGetResourceHandle() and set the DLL's resource handle
(make sure it's saved in the DLL initialization code). When you're done
make sure you call AfxSetResourceHandle() with the saved handle.
GCD
Greg Dean
GregD@asymetrix.com
Howl like a Coyote!
-----From: tim
I had the same problem and resolved it by making the DLL an extension dll and following
the instructions listed in Inside Visual C++ Version 4, by David Kruglinski. The information that
you are looking for is on page 505 and is well worth reading.
Tim Gonda
tgonda@mstus.com
| Вернуться в корень Архива
|