5

我有一个模块可以创建一个包含 ActiveX 控件的无模式对话框。该模块是 MFC EXE 应用程序的一部分,对话框的创建工作正常。最近,我将模块移到 ATL/COM 服务器中,并将对话框资源从 EXE 复制到 COM 服务器中。尝试使用CDialog::Create()错误创建无模式对话框时。

我调试CDialog::Create并注意到它在::CreateDialogIndirect()返回NULLGetLastError返回时失败0。我在对话框资源属性中将“No Fail Create”标志更改为 True,并获得了有关错误的更多详细信息。问题发生在宏DoDataExchange()内的对话框中。DDX_Control这将调用CDataExchange::PrepareCtrl()控件的资源 ID,如下所示:

HWND CDataExchange::PrepareCtrl(int nIDC)
{
   ASSERT(nIDC != 0);
   ASSERT(nIDC != -1); // not allowed
   HWND hWndCtrl;
   COleControlSite* pSite = NULL;
   m_pDlgWnd->GetDlgItem(nIDC, &hWndCtrl);
   if (hWndCtrl == NULL)
   {
      // Could be a windowless OCX
      pSite = m_pDlgWnd->GetOleControlSite(nIDC);
      if (pSite == NULL)
      {
         TRACE(traceAppMsg, 0, "Error: no data exchange control with ID 0x%04X.\n", nIDC);
         ASSERT(FALSE);
         AfxThrowNotSupportedException();
      }
   }
   m_idLastControl = nIDC;
   m_bEditLastControl = FALSE; // not an edit item by default

   return hWndCtrl;
}

由于传递的资源 ID ,对该函数的调用m_pDlgWnd->GetOleControlSite()失败。顺便说一下,资源 ID 是控件的 ID。

关于为什么这在 EXE 中有效并在 COM 服务器中失败的任何建议?

4

6 回答 6

4

我有完全相同的问题。就我而言,问题原来是我没有调用 AfxEnableControlContainer()。我在我的应用程序的 InitInstance 成员函数中添加了一个调用,它解决了这个问题。

于 2013-04-23T17:55:19.390 回答
2

前几天遇到了类似的问题。将控件从一个对话框资源复制到另一个。事实上,您不能像使用其他 MFC 控件那样将 ActiveX 控件从一个对话框复制到另一个对话框。对于 ActiveX 控件,rc 文件包含一个 DLGINIT 部分。例如,我有一个带有 IE WebBrowser 控件的表单:

IDD_ONLINE_REPORTVIEW_FORM DIALOGEX 0, 0, 320, 200
STYLE DS_SETFONT | DS_CONTROL | WS_CHILD
FONT 8, "MS Sans Serif", 0, 0, 0x0
BEGIN
    CONTROL         "",IDC_EXPLORER1,"{8856F961-340A-11D0-A96B-00C04FD705A2}",WS_TABSTOP,7,61,299,77
END

在 rc 文件下面,有一个 DLGINIT 部分:

IDD_ONLINE_REPORTVIEW_FORM DLGINIT
BEGIN
    IDC_EXPLORER1, 0x376, 160, 0
0x0000, 0x0000, 0x004c, 0x0000, 0x2e68, 0x0000, 0x0ceb, 0x0000, 0x0000, 
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
0x0000, 0x0000, 0x004c, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 
0x0000, 0xd0e0, 0x0057, 0x3573, 0x11cf, 0x69ae, 0x0008, 0x2e2b, 0x6212, 
0x0008, 0x0000, 0x0000, 0x0000, 0x004c, 0x0000, 0x1401, 0x0002, 0x0000, 
0x0000, 0x00c0, 0x0000, 0x0000, 0x4600, 0x0080, 0x0000, 0x0000, 0x0000, 
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0000, 
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 
    0
END

打开 rc 文件的源并搜索您的控件 ID。搜索 DLGINIT 部分并将其复制到您的新对话框中

于 2012-11-09T00:39:22.027 回答
1

这是另一种情况,可以得到相同的调试断言警告(错误:没有 ID dlgdata 的数据交换控制:第 40 行):

例如,如果您通过虚函数 CDialogExExample::Create(CONTROL_ID, ..) 创建 CDialogExExample 的对话框实例,而 CONTROL_ID 与 CDialogExample 头文件中的 IDD_EXAMPLE(enum{ IDD = IDD_EXAMPLE};) 不一致......然后一个可以添加控制总是失败。

这是来自 msdn 的鼓舞人心的链接

可能对某人有帮助:)

PS:这种情况可能与@Hank Chang的回答相同

于 2017-07-03T08:43:22.233 回答
1

就我而言,我在调用时输入了错误的对话框 ID

BOOL Create(UINT nID, CWnd * pWnd);

所以失败了DoDataExchange()

于 2016-04-25T07:41:30.270 回答
0

就我而言,我有一个 MFC 对话框,它通过 ActiveX 托管 .Net UI 控件。

调试后我发现,DoModal 失败并返回 -1,GetLastError 给出 0。

经过一天的调试,原来是.Net Assemblies 版本不匹配的问题。这会导致 OLE 控件实例化失败。

WinDBG 摘录:

(21b0.71cc):CLR 异常 - 代码 e0434352(第一次机会)OLE 控件 {EE3C4329-83A8-4DD8-A74C-680AC01AC593} 的 CoCreateInstance 失败。

结果代码:0x80131040

HRESULT 值 0x80131040 含义:

找到的程序集的清单定义与程序集引用不匹配。

于 2017-08-04T11:14:45.063 回答
-1

在出现确切错误后我找到的解决方案是检查头文件中的类定义。假设班级是

然后在下面的代码中

class CNewDlg : public CMyBaseDlg
{
    DECLARE_DYNAMIC(CNewDlg)
public:
    CNewDlg(CWnd* pParent = NULL);   // standard constructor
    virtual ~CNewDlg();

    // Dialog Data
    enum { IDD = IDD_MYNEWDIALOGID };

检查线路:

enum { IDD = IDD_MYNEWDIALOGID };

确保您拥有正确的 ID。您收到的错误可能是由于从先前创建的控件/对话框的另一个头文件中复制和粘贴代码而没有更新此 ID。

这应该与 .rc 文件中对话框的定义相匹配。例如:

IDD_MYNEWDIALOGID DIALOGEX 0, 0, 445, 314
于 2019-01-16T12:50:03.703 回答