21st July: Updated, see bottom
In VC++ 2005 I have 2 projects. Firstly, a MFC DLL project (not an extension DLL) which has a simple dialog:
#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 app, with MFC libraries, that does:
#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 runs up, but no dialog appears. Stepping into DoModal()...
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 whatever reason it seems it can't load the resource, returning -1 at the end of the copied section. I've looked at a few articles on CodeGuru, etc, and not seen anything obvious. Is my class not being exported/imported right? Or is it a resource problem? Or is the problem that I'm trying to display it from a console (MFC) app?
21st July Update I created an overridden DoModal as so:
INT_PTR CTestDlg::DoModal()
{
AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
return CDialog::DoModal();
}
This seems to work although should I be overriding a different method to get the functionality more generic?
To import the dll use Project/Class Wizard (available until VS 2017) and select the "Add Class" dropdown and then "MFC Class From TypeLib" item. Select "Add class from File" in the Wizard dialog and click the "..." button to navigate to select GdPicture. NET.
An MFC DLL is a binary file that acts as a shared library of functions that can be used simultaneously by multiple applications. The easiest way to create an MFC DLL project is to use the MFC DLL Wizard.
As you've noted, the problem is that MFC is not finding the resource, since the module context is set to your main EXE rather than the DLL containing the dialog resource.
Manually calling AFX_MANAGE_STATE
to ensure the DLL context is established is one way to work this, but it's 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 a list of extension DLLs and managing memory between the DLLs.
You may be able to short-cut creating the extension DLL and simply create your own CDynLinkLibrary
instance, which adds your DLL to the main resource list. I have not tried this, preferring instead to take the extension dll _AFXDLL route, so this may or may not work.
The MSDN article on Extension DLLs may help you determine if they are suitable in your case, and what advantages/drawbacks they bring.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With