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 VemuriI 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 DeanYou 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
| Вернуться в корень Архива |