Export MFC Dialog from DLL

July 21: updated, see bottom

In VC ++ 2005, I have 2 projects. Firstly, the MFC DLL project (and not the extension DLL), which has a simple dialog:

TestDlg.h

#pragma once #include "afxwin.h" #include "resource.h" // CTestDlg dialog namespace Dialogs { class __declspec(dllexport) CTestDlg : public CDialog { DECLARE_DYNAMIC(CTestDlg ) public: CTestDlg (CWnd* pParent = NULL); // standard constructor virtual ~CTestDlg (); // Dialog Data enum { IDD = IDD_TEST_DLG }; } } 

Then I have a Win32 console application with MFC libraries that does:

TestApp.cpp

 #include "stdafx.h" #include "TestApp.h" #include <TestDlg.h> #ifdef _DEBUG #define new DEBUG_NEW #endif CWinApp theApp; using namespace std; int _tmain(int argc, TCHAR* argv[], TCHAR* envp[]) { int nRetCode = 0; // initialize MFC and print and error on failure if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0)) { // TODO: change error code to suit your needs _tprintf(_T("Fatal Error: MFC initialization failed\n")); nRetCode = 1; } else { Dialogs::CTestDlg dlg; dlg.DoModal(); } return nRetCode; } 

It builds and starts, but the dialogue does not appear. Going to DoModal () ...

dlgcore.cpp

 INT_PTR CDialog::DoModal() { // can be constructed with a resource template or InitModalIndirect ASSERT(m_lpszTemplateName != NULL || m_hDialogTemplate != NULL || m_lpDialogTemplate != NULL); // load resource as necessary LPCDLGTEMPLATE lpDialogTemplate = m_lpDialogTemplate; HGLOBAL hDialogTemplate = m_hDialogTemplate; HINSTANCE hInst = AfxGetResourceHandle(); if (m_lpszTemplateName != NULL) { hInst = AfxFindResourceHandle(m_lpszTemplateName, RT_DIALOG); HRSRC hResource = ::FindResource(hInst, m_lpszTemplateName, RT_DIALOG); hDialogTemplate = LoadResource(hInst, hResource); } if (hDialogTemplate != NULL) lpDialogTemplate = (LPCDLGTEMPLATE)LockResource(hDialogTemplate); // return -1 in case of failure to load the dialog template resource if (lpDialogTemplate == NULL) return -1; ... more stuff 

For some reason, it seems that it cannot load the resource, returning -1 at the end of the copied section. I looked through several articles about CodeGuru, etc., and did not see anything obvious. Is my class not exported / imported? Or is it a resource problem? Or the problem I'm trying to display from the console (MFC)?

July 21st update I created an overridden DoModal like this:

 INT_PTR CTestDlg::DoModal() { AFX_MANAGE_STATE(AfxGetStaticModuleState( )); return CDialog::DoModal(); } 

This seems to work though I have to redefine another method to get more universal functionality?

+6
dll visual-c ++ mfc
source share
4 answers

As you noticed, the problem is that MFC does not find the resource, since the module context is installed on your main EXE, and not on the DLL containing the dialog resource.

Manually calling AFX_MANAGE_STATE to ensure that the context of the DLL is established is one way it works, but it is not transparent. The ideal way is to compile your DLL as an extension DLL, so that MFC can take care of loading the resource from the list of DLL extensions and managing memory between the DLL files.

Perhaps you can reduce the creation of the extension DLL and simply create your own instance of CDynLinkLibrary , which will add your DLL to the main list of resources. I have not tried this, preferring to use the _AFXDLL dll extension route instead, so this may or may not work.

The MSDN article in the Extension DLL can help you determine if they are appropriate in your case and what advantages / disadvantages they bring.

+9
source share

Exclusively download * .lib

 Hinstance = Loadlibray("*.lib"); AfxSetResourceHandle(Hinstance); // this way you can load the resource in you dll not the current app resource. 

then destination you code:

 CTestDlg dlg; dlg.DoModal(); 
+4
source share

I'm not sure if this design can really work. If possible, export only the function that opens the dialog box inside the DLL.

But perhaps using AFX_MANAGE_STATE -macro may help you.

+2
source share

AFX_MANAGE_STATE does not work for me. In my case, exe called a dialog from another dll, which called another dialogue from a third dll. AFX_MANAGE_STATE returned the context of the second dll instead of the third. To fix this, I redefine DoModel and switch the context there.

 INT_PTR YourDialog::DoModal() { HINSTANCE _hInstance = AfxGetResourceHandle(); __try { HMODULE dllModule = ::GetModuleHandle("<Your_DlgSourceDll>.dll"); AfxSetResourceHandle(dllModule); return CDialog::DoModal(); } __finally { AfxSetResourceHandle(_hInstance); } } 
0
source share

All Articles