CDialog :: Create无法与ActiveX控件对话

时间:2012-11-08 15:32:59

标签: mfc cdialog com-server

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

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

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

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

有关为什么在EXE内部工作并且在COM服务器中失败的任何建议?

6 个答案:

答案 0 :(得分:4)

我有完全相同的问题。在我的情况下,问题是我没有调用AfxEnableControlContainer()。我在我的应用程序的InitInstance成员函数中添加了一个调用,它修复了问题。

答案 1 :(得分: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部分并将其复制到新对话框

答案 2 :(得分:1)

在我的情况下,我在调用

时输入了错误的Dialog ID
BOOL Create(UINT nID, CWnd * pWnd);

DoDataExchange()失败了。

答案 3 :(得分:1)

这是另一种可以获得相同的Debug Assersion警告的情况(错误:没有ID dlgdata的数据交换控制:第40行):

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

此处an inspiring link from msdn

可能对某人有帮助:))

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

答案 4 :(得分:0)

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

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

经过一天的调试后,结果证明是.Net Assemblies版本不匹配问题。这导致OLE控件实例化失败。

WinDBG摘录:

  

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

     
    
      
        

结果代码:0x80131040

      
    
  

HRESULT值0x80131040含义:

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

答案 5 :(得分:-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