1

我有一个使用 OCX 控件的 VC++6.0 构建的遗留应用程序。我已升级应用程序以使用 VS2013 构建。最初我让它构建并成功运行,但是当我尝试使用类向导重新生成 ocx.h 和 ocx.cpp 文件时

  1. 在解决方案资源管理器中右键单击项目
  2. 从 ActiveX 控件中选择 Add:Class:MFCClass
  3. [添加] 按钮
  4. 从注册控件列表中选择 OCX
  5. 选择要复制的接口
  6. [完成]按钮

生成的 h 和 cpp 输出文件缺少所有 Attribute 方法

        // Attributes
public:
        // Operations
public:
        void ClearTablet()
    { . . .

我还尝试直接为 Class Wizard 提供 OCX 文件,而不是使用注册表,但结果相同。我求助于手动编辑 ocx.h 和 ocx.cpp 文件来添加缺少的属性方法,但不明白为什么类向导不生成它们。我想回到 VC++6.0 版本,看看它是否能正确生成文件,但我不清楚如何使用 6.0 来生成 ocx.h 和 ocx.cpp 文件,因为相同的菜单选项不可用。

添加 3-5-2018 以回应 Hans 评论

这是原始 OCX 项目中缺少的属性之一

=====文件:SigPlusCtl.h=========

class CSigPlusCtrl : public COleControl
{
    DECLARE_DYNCREATE(CSigPlusCtrl)

    DECLARE_INTERFACE_MAP()
    . . .
    // Dispatch maps
    //{{AFX_DISPATCH(CSigPlusCtrl)
    afx_msg short GetImageFileFormat();
    afx_msg void SetImageFileFormat(short nNewValue);
    . . .

=====文件:SigPlusCtl.cpp=========

// Dispatch map
BEGIN_DISPATCH_MAP(CSigPlusCtrl, COleControl)
//{{AFX_DISPATCH_MAP(CSigPlusCtrl)
DISP_PROPERTY_EX(CSigPlusCtrl, "ImageFileFormat", GetImageFileFormat, SetImageFileFormat, VT_I2)
. . .

=====文件:SigPlusImage.cpp====

short CSigPlusCtrl::GetImageFileFormat() 
{
    return ImageFileFormat;
}

void CSigPlusCtrl::SetImageFileFormat( short nNewValue) 
{
    if ( ( nNewValue >= 0 ) && ( nNewValue <= 11 ) )
    {
        ImageFileFormat = nNewValue;
    }
    SetModifiedFlag();
} 
. . .

这是我必须添加到容器项目中生成的 .h 和 .cpp 文件中以使用此缺失属性的内容。在尝试使用 VS2013 重新生成它们之前,我从容器应用程序中的原始 OCX .h 和 .cpp 文件中复制了此代码。由于我无法使用 VC++6.0 重新生成这些文件(请参阅下面的第一条评论),我不知道这个复制的代码是否最初是由 VC++6.0 向导创建的,或者原始程序员也编辑了这些头文件。

========文件:sigplus=================

// Attributes
public:
    short GetImageFileFormat();
    void SetImageFileFormat(short);
. . .

========文件:sigplus.cpp=============

// CSigPlus properties

short CSigPlus::GetImageFileFormat()
{
    short result;
    GetProperty(0x1, VT_I2, (void*)&result);
    return result;
}

void CSigPlus::SetImageFileFormat(short propVal)
{
    SetProperty(0x1, VT_I2, propVal);
}
. . .

我不知道类向导是否重要,但方法位置有点不合常规,因为 OCX 控件方法的实现分散在多个 .cpp 文件中,而不是全部位于 SigPlusCtl.cpp 文件中

2018 年 3 月 20 日添加

根据 Hans 在 3-20 上的评论,我尝试使用 Visual Studio 2013 打开 ocx 文件以检查 TYPELIB。但是当我展开 TYPELIB 文件夹时,它只显示了一个 HEX 转储。 在此处输入图像描述

查看使用OLE/COM 对象查看器的 OCX TypeLib 界面,我看到“属性”下列出了缺少的属性,但我没有看到 Get 和 Set 方法的明确声明。例如,有一个属性ImageFileFormat但没有GetImageFileFormatSetImageFileFormat。在 OCX 控件的源代码中有这些 Get/Set 方法的明确定义。

SigPlusCtl.cpp: DISP_PROPERTY_EX(CSigPlusCtrl, "ImageFileFormat", GetImageFileFormat, SetImageFileFormat, VT_I2)
SigPlusCtl.h:     afx_msg short GetImageFileFormat();
SigPlusImage.cpp: short CSigPlusCtrl::GetImageFileFormat() 
SigPlus.map:  0001:00012ed0       ?GetImageFileFormat@CSigPlusCtrl@@IAEFXZ 10013ed0 f   SigPlusImage.obj

我是否应该期望在 OLE 查看器中看到明确列出方法下的 Get 和 Set方法:

    dispinterface _DSigPlus {
        properties:
            [id(0x00000001)            
]
            short ImageFileFormat;
            [id(0x00000002)            
]
            short ImageXSize;
            [id(0x00000003)            
]
            short ImageYSize;
            [id(0x00000004)            
]
            o o o 
]
            BSTR TabletGraphicFile;
            [id(0x00000042)            
]
            long TabletTimer;
            [id(0xfffffe0b), bindable, requestedit            
]
            OLE_COLOR BackColor;
            [id(0xfffffdff), bindable, requestedit            
]
            OLE_COLOR ForeColor;
        methods:
            [id(0x00000043)]
            void ClearTablet();
            [id(0x00000044)]
            o o o

添加 3-20-18 17:00 PDT

我在评论中查找了@HansPassart 提到的#import 。此 Microsoft 特定指令似乎是使用类向导的替代方法。我从项目中删除了类向导生成的文件 sigplus.h 和 sigplus.cpp 并添加了

#import "file:SigPlus.tlb" 

到主头文件。编译后,#import指令会生成 sigplus.TLH 和 sigplus.TLI(头文件和实现)文件,然后包含 sigplus.TLH,然后显式包含 TLI 文件。编译时,#import 会生成这两个文件,然后包含生成的“Release/sigplus.tlh”。这些生成的文件确实包含缺少的 Get/Set 方法,但它们无法编译。TLH 文件为 OCX 类 _DSigPlus 使用不同的名称,并将其放在命名空间中。但即使在考虑了这些差异之后,TLH 文件中的类声明使用 IDispatch 作为类向导使用 CWnd 的父类,并且在编译时有以下未解析的纯虚方法来自 IUnknown,它是 IDispatch 的父类。

c:\demoocx\DemoOCXDlg.h(24): error C2259: 'SIGPLUSLib::_DSigPlus' : cannot instantiate abstract class
          due to following members:
          'HRESULT IUnknown::QueryInterface(const IID &,void **)' : is abstract
          C:\Program Files (x86)\Windows Kits\8.1\Include\um\unknwnbase.h(114) : see declaration of 'IUnknown::QueryInterface'
          'ULONG IUnknown::AddRef(void)' : is abstract
          C:\Program Files (x86)\Windows Kits\8.1\Include\um\unknwnbase.h(118) : see declaration of 'IUnknown::AddRef'
          'ULONG IUnknown::Release(void)' : is abstract
          C:\Program Files (x86)\Windows Kits\8.1\Include\um\unknwnbase.h(120) : see declaration of 'IUnknown::Release'
          'HRESULT IDispatch::GetTypeInfoCount(UINT *)' : is abstract
          c:\program files (x86)\windows kits\8.1\include\um\oaidl.h(2187) : see declaration of 'IDispatch::GetTypeInfoCount'
          'HRESULT IDispatch::GetTypeInfo(UINT,LCID,ITypeInfo **)' : is abstract
          c:\program files (x86)\windows kits\8.1\include\um\oaidl.h(2190) : see declaration of 'IDispatch::GetTypeInfo'
          'HRESULT IDispatch::GetIDsOfNames(const IID &,LPOLESTR *,UINT,LCID,DISPID *)' : is abstract
          c:\program files (x86)\windows kits\8.1\include\um\oaidl.h(2195) : see declaration of 'IDispatch::GetIDsOfNames'
          'HRESULT IDispatch::Invoke(DISPID,const IID &,LCID,WORD,DISPPARAMS *,VARIANT *,EXCEPINFO *,UINT *)' : is abstract
          c:\program files (x86)\windows kits\8.1\include\um\oaidl.h(2202) : see declaration of 'IDispatch::Invoke'
4

0 回答 0