21-го июля: Обновленный, посмотрите нижнюю часть
В VC ++ 2005 у меня есть 2 проекта. Во-первых, проект DLL MFC (не дополнительный DLL), который имеет простое диалоговое окно:
#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 };
}
}
Затем у меня есть приложение консоли Win32 с библиотеками MFC, который делает:
#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;
}
Это создает и увеличивается, но никакое диалоговое окно не появляется. Продвижение в 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
По любой причине кажется, что это не может загрузить ресурс, возвратившись-1 в конце скопированного раздела. Я посмотрел на несколько статей о CodeGuru, и т.д., и не видел что-либо очевидное. Мой класс не являющийся, экспортировал/импортировал право? Или действительно ли это - проблема ресурса? Или состоит в том проблема, что я пытаюсь отобразить его от консоли (MFC) приложение?
21-го июля Обновление я создал переопределенный DoModal как так:
INT_PTR CTestDlg::DoModal()
{
AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
return CDialog::DoModal();
}
Это, кажется, работает, хотя должен я переопределить другой метод для получения более универсальной функциональности?
Как вы заметили, проблема в том, что MFC не находит ресурс, поскольку контекст модуля установлен на ваш основной EXE, а не на DLL, содержащую ресурс диалога.
Ручной вызов AFX_MANAGE_STATE
, чтобы убедиться, что контекст DLL установлен, является одним из способов решения этой проблемы, но он не прозрачен. Идеальным способом является компиляция вашей DLL как DLL расширения, чтобы MFC мог позаботиться о загрузке ресурса из списка DLL расширения и управлении памятью между DLL.
Возможно, вы сможете обойтись без создания DLL расширения и просто создать собственный экземпляр CDynLinkLibrary
, который добавит вашу DLL в список основных ресурсов. Я не пробовал этого, предпочитая вместо этого использовать путь расширения DLL _AFXDLL, так что это может сработать, а может и нет.
Статья MSDN о DLL расширения может помочь вам определить, подходят ли они в вашем случае, и какие преимущества/недостатки они дают.
Я не уверен, что эта конструкция действительно может работать. Если возможно, экспортируйте только функцию, которая открывает диалог внутри DLL.
Но, возможно, вам поможет использование макроса AFX_MANAGE_STATE
.