L'exportation d'une boîte de Dialogue MFC à partir d'une DLL
21 juillet: mise à Jour, voir en bas de
Dans VC++ 2005, j'ai 2 projets. Tout d'abord, un projet MFC DLL (pas une DLL d'extension) qui a une simple boîte de dialogue:
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 };
}
}
Puis j'ai une application console Win32, MFC bibliothèques, qui n':
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;
}
Il construit et exécute, mais aucune boîte de dialogue s'affiche. Entrer dans 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
Pour quelque raison que ce soit, il semble qu'il ne peut pas charger la ressource, de retour de -1 à la fin de la section copiée. J'ai regardé quelques articles sur CodeGuru, etc, et pas vu quelque chose d'évident. Est ma classe à ne pas être exportés/importés droit? Ou est-ce un problème de ressource? Ou est le problème que j'essaie de l'afficher à partir d'une console (MFC) app?
21 juillet, Jour
J'ai créé un substituée DoModal de la manière suivante:
INT_PTR CTestDlg::DoModal()
{
AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
return CDialog::DoModal();
}
Cela semble fonctionner bien que devrais-je être majeur une autre méthode pour obtenir les fonctionnalités plus générique?
Vous devez vous connecter pour publier un commentaire.
Comme vous l'avez remarqué, le problème est que le MFC n'est pas de trouver la ressource, puisque le module de contexte est mis à votre principale EXE plutôt que la DLL contenant la ressource de boîte de dialogue.
Manuellement appeler
AFX_MANAGE_STATE
pour assurer la DLL contexte est établi est une façon de travailler, mais il n'est pas transparent. L'idéal est de compiler votre fichier DLL comme une DLL d'extension, de sorte que le MFC peut prendre soin de chargement de la ressource à partir d'une liste de Dll d'extension et de gestion de la mémoire entre les Dll.Vous pourriez être capable de couper à la création de la DLL d'extension et de tout simplement créer votre propre
CDynLinkLibrary
exemple, qui ajoute votre fichier DLL à la ressource principale de la liste. Je n'ai pas essayé cela, préférant prendre la dll d'extension _AFXDLL route, de sorte que cela peut ou peut ne pas fonctionner.L'article MSDN sur Dll D'Extension peut vous aider à déterminer si elles sont adaptées à votre cas, et quels sont les avantages/inconvénients qu'ils apportent.
Explicitement charge de vous *.lib
ensuite la destination de votre code:
Je ne sais pas si cette construction peut réellement fonctionner. Si possible, l'exportation juste une fonction qui ouvre la boîte de dialogue à l'intérieur de la DLL.
Mais peut-être l'utilisation de la
AFX_MANAGE_STATE
-macro peut vous aider.Dialogs::CTestDlg *Dialogs::ShowTestDlg()
?AFX_MANAGE_STATE ne fonctionne pas pour moi. Dans mon cas, le fichier exe a été d'appeler une boîte de dialogue à partir d'une autre dll qui en appelle une autre boîte de dialogue à partir du 3 dll. AFX_MANAGE_STATE revenait cadre de la 2e dll à la place de 3ème. Pour corriger cela, je suis primordial DoModel et en faisant le changement de contexte là.