CWnd作为ActiveX控件在C ++中没有.dll或.ocx文件?

时间:2011-11-07 20:03:06

标签: dynamic mfc activex idispatch cwnd

亲爱的MFC / ActiveX / COM破解,我'继承'旧MFC应用程序的源代码(最初使用Visual Studio 6创建) 它在VS 2010中构建并运行到目前为止,但是已经嵌入了一些ActiveX控件作为源代码,显然是由生成的  Visual Studio向导(.h和.cpp文件,见下文);  但是不在自己的子项目中,以便生成.dll或.ocx文件。 以下是一个此类控件的头文件的相关部分:

#if !defined(AFX_CHARTFX_H__F8A080E0_0647_11D4_92B0_0000E886CDCC__INCLUDED_)
#define AFX_CHARTFX_H__F8A080E0_0647_11D4_92B0_0000E886CDCC__INCLUDED_

#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000
// Machine generated IDispatch wrapper class(es) created by Microsoft Visual C++

// NOTE: Do not modify the contents of this file.  If this class is regenerated by
//  Microsoft Visual C++, your modifications will be overwritten.

/////////////////////////////////////////////////////////////////////////////
// CChartfx wrapper class

class CChartfx : public CWnd
{
protected:
    DECLARE_DYNCREATE(CChartfx)
public:
    CLSID const& GetClsid()
    {
        static CLSID const clsid
            = { 0x8996b0a1, 0xd7be, 0x101b, { 0x86, 0x50, 0x0, 0xaa, 0x0, 0x3a, 0x55, 0x93 } };
        return clsid;
    }
    virtual BOOL Create(LPCTSTR lpszClassName,
        LPCTSTR lpszWindowName, DWORD dwStyle,
        const RECT& rect,
        CWnd* pParentWnd, UINT nID,
        CCreateContext* pContext = NULL)
    { return CreateControl(GetClsid(), lpszWindowName, dwStyle, rect, pParentWnd, nID); }

    BOOL Create(LPCTSTR lpszWindowName, DWORD dwStyle,
        const RECT& rect, CWnd* pParentWnd, UINT nID,
        CFile* pPersist = NULL, BOOL bStorage = FALSE,
        BSTR bstrLicKey = NULL)
    { return CreateControl(GetClsid(), lpszWindowName, dwStyle, rect, pParentWnd, nID,
        pPersist, bStorage, bstrLicKey); }
    //rest of header file omitted

请注意,此类继承自CWnd而不是某些 OCX课程。但是因为所有MFC窗口都是COM组件(因为我在某处读取)并且这是生成的 代码它应该已经工作了一段时间。我还读到这可能真的是一个迁移差距 发生在2005年之前的某个地方。 还要注意DECLARE_DYNCREATE,所以我认为这是使用IDispatch接口的后期绑定。 因此MFC将为我们调用Create()函数。

以上控件通过包含CDialog(也使用VS向导创建)的聚合使用:

//... analysedlg.h  - leading auto-generated stuff omitted
class CAnalyseDlg : public CDialog
{
  CChartfx m_chhrtfx;
  //... enum for resource ID, DoDataExchange, message map, other members…
}

反过来,对话框嵌入在应用程序的视图类中(同样,通过成员变量)和 通过在菜单项事件处理程序中调用DoModal()来创建。

所以,当我点击相应的菜单项时,我得到一个m_hWnd NULL断言并且在点击时 弹出对话中的“重试”,下面的堆栈(摘录):

mfc100d.dll!COleControlContainer::FillListSitesOrWnds(_AFX_OCC_DIALOG_INFO * pOccDlgInfo)  line 925 + 0x23 Bytes    C++
mfc100d.dll!COccManager::CreateDlgControls(CWnd * pWndParent, const char * lpszResourceName, _AFX_OCC_DIALOG_INFO * pOccDlgInfo)  line 410  C++
mfc100d.dll!CDialog::HandleInitDialog(unsigned int __formal, unsigned int __formal)  line 715 + 0x22 Bytes  C++
mfc100d.dll!CWnd::OnWndMsg(unsigned int message, unsigned int wParam, long lParam, long * pResult)  line 2383 + 0x11 Bytes  C++
mfc100d.dll!CWnd::WindowProc(unsigned int message, unsigned int wParam, long lParam)  line 2087 + 0x20 Bytes    C++
mfc100d.dll!AfxCallWndProc(CWnd * pWnd, HWND__ * hWnd, unsigned int nMsg, unsigned int wParam, long lParam)  line 257 + 0x1c Bytes  C++
mfc100d.dll!AfxWndProc(HWND__ * hWnd, unsigned int nMsg, unsigned int wParam, long lParam)  line 420    C++
mfc100d.dll!AfxWndProcBase(HWND__ * hWnd, unsigned int nMsg, unsigned int wParam, long lParam)  line 420 + 0x15 Bytes   C++
user32.dll!766162fa()   
[missing frames omitted by me]  
mfc100d.dll!CWnd::CreateDlgIndirect(const DLGTEMPLATE * lpDialogTemplate, CWnd * pParentWnd, HINSTANCE__ * hInst)  line 366 + 0x2a Bytes    C++
mfc100d.dll!CDialog::DoModal()  line 630 + 0x20 Bytes   C++

在VS调试输出中,有以下几行:

CoCreateInstance of OLE control {8996B0A1-D7BE-101B-8650-00AA003A5593} failed.
>>> Result code: 0x80040154
>>> Is the control is properly registered?
Warning: Resource items and Win32 Z-order lists are out of sync. Tab order may be not defined well. 

显然,对CoCreateInstance的调用已经完成,并且在没有断言的情况下默默地失败 本来不错的。有人知道这是哪里吗?

我的核心问题是,在这种情况下,通常MFC是否会照顾是否正确 注册控件,即使它不在.dll或.ocx项目中,并且它必须有效 像过去一样。我在某处读到带有DialogTemplate的CreateDlgIndirect是一种方式 无需.dll或.ocx文件即可创建ActiveX控件。在上面的堆栈中,这称为, 也可以,但不是用于ActiveX控件,而是用于对话。

有谁知道更多有关此问题以及如何解决此问题? 如果我必须手动注册控件,例如使用regsvr32.exe或通过源代码, 有没有.dll或.ocx文件的方法?或者我必须重新打包ActiveX组件 他们自己的项目(无论如何更基于组件/模块化)?

我希望我的问题描述足够精确,我会非常感谢任何答案。 亲切的问候。

1 个答案:

答案 0 :(得分:0)

我在使用旧的ActiveX控件时遇到此问题。显然它是公寓线程,我试图用COINIT_MULTITHREADED调用CoInitializeEx()。