从 DLL 导出 MFC 对话框

2022-01-12 00:00:00 dll visual-c++ mfc

7 月 21 日:更新,见底部

在 VC++ 2005 中,我有 2 个项目.首先,一个 MFC DLL 项目(不是扩展 DLL),它有一个简单的对话框:

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 };
    }
}

然后我有一个带有 MFC 库的 Win32 控制台应用程序:

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
"));
        nRetCode = 1;
    }
    else
    {

        Dialogs::CTestDlg dlg;
        dlg.DoModal();
    }
    return nRetCode;
}

它构建并运行,但没有出现对话框.步入 DoModal()...

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

无论出于何种原因,它似乎无法加载资源,在复制部分的末尾返回 -1.我看过一些关于 CodeGuru 等的文章,但没有看到任何明显的东西.我的班级没有被导出/导入吗?还是资源问题?还是我试图从控制台 (MFC) 应用程序显示它的问题?

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?

7 月 21 日更新我这样创建了一个覆盖的 DoModal:

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?

推荐答案

正如您所指出的,问题是 MFC 没有找到资源,因为模块上下文设置为您的主 EXE 而不是包含对话资源.

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.

手动调用 AFX_MANAGE_STATE 以确保建立 DLL 上下文是解决此问题的一种方法,但它不是透明的.理想的方法是将您的 DLL 编译为扩展 DLL,以便 MFC 可以负责从扩展 DLL 列表中加载资源并管理 DLL 之间的内存.

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.

您可以创建扩展 DLL 的捷径,只需创建您自己的 CDynLinkLibrary 实例,这会将您的 DLL 添加到主资源列表中.我没有尝试过,而是更喜欢使用扩展 dll _AFXDLL 路由,所以这可能会也可能不会.

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.

关于 扩展 DLL 的 MSDN 文章 可以帮助您确定它们是否适合您的情况,以及它们带来的优点/缺点.

The MSDN article on Extension DLLs may help you determine if they are suitable in your case, and what advantages/drawbacks they bring.

相关文章