MFC ActiveX 控件:高级主题

本文介绍与开发 ActiveX 控件相关的高级主题。 这些包括:

重要

ActiveX 是一项不推荐用于新开发的旧技术。 有关取代 ActiveX 的新式技术的详细信息,请参阅 ActiveX 控件

在 ActiveX 控件中使用数据库类

由于 ActiveX 控件类是类库的一部分,因此可以应用相同的过程和规则,以便在标准 MFC 应用程序中使用数据库类来开发使用 MFC 数据库类的 ActiveX 控件。

有关 MFC 数据库类的一般概述,请参阅 MFC 数据库类(DAO 和 ODBC)。 本文介绍了 MFC ODBC 类和 MFC DAO 类,并指导你详细了解这两个类。

注释

DAO 通过 Office 2013 获得支持。 DAO 3.6 是最终版本,它被视为已过时。 Visual C++ 环境和向导不支持 DAO(尽管包含 DAO 类,但仍可使用它们)。 Microsoft建议对新项目使用 OLE DB 模板ODBC 和 MFC 。 应仅在维护现有应用程序时使用 DAO。

实现参数化属性

参数化属性(有时称为属性数组)是一种将值的同质集合公开为控件的单个属性的方法。 例如,可以使用参数化属性将数组或字典公开为属性。 在 Visual Basic 中,使用数组表示法访问此类属性:

x = o.Array(2, 3) ' gets element of 2D array
o.Array(2, 3) = 7 ' sets element of 2D array

使用“添加属性向导”实现参数化属性。 添加属性向导通过添加一对 Get/Set 函数来实现该属性,这些函数允许控件用户使用上述表示法或标准方式访问该属性。

与方法和属性类似,参数化属性还限制允许的参数数。 对于参数化属性,限制为 15 个参数(保留一个用于存储属性值的参数)。

以下过程添加一个名为 Array 的参数化属性,该属性可作为整数的二维数组进行访问。

使用“添加属性向导”添加参数化属性

  1. 加载控件的项目。

  2. 在类视图中,展开控件的库节点。

  3. 右键单击控件(库节点的第二个节点)的接口节点以打开快捷菜单。

  4. 在快捷菜单中,单击“ 添加 ”,然后单击“ 添加属性”。

  5. “属性名称 ”框中,键入 Array

  6. “属性类型” 框中,选择 short

  7. 对于 实现 类型,请单击 “获取/设置方法”。

  8. “获取函数 ”和 “设置函数” 框中,键入 Get 和 Set Functions 的唯一名称或接受默认名称。

  9. 使用参数名称和参数类型控件添加名为 row类型 short)的参数。

  10. 添加名为 column类型 short)的第二个参数。

  11. 单击“完成”。

添加属性向导所做的更改

添加自定义属性时,“添加属性向导”会更改控件类标头(。H) 和实现 (.CPP) 文件。

以下行将添加到控件类。H 文件:

SHORT GetArray(SHORT row, SHORT column);
void SetArray(SHORT row, SHORT column, SHORT newVal);

此代码声明两个调用 GetArray 的函数, SetArray 允许用户在访问属性时请求特定的行和列。

此外,“添加属性向导”将以下行添加到控件调度映射(位于控件类实现中)。CPP) 文件:

DISP_PROPERTY_PARAM_ID(CMyAxUICtrl, "Array", dispidArray, GetArray, SetArray, VT_I2, VTS_I2 VTS_I2)

最后,将函数的GetArraySetArray实现添加到末尾。CPP 文件。 在大多数情况下,将修改 Get 函数以返回属性的值。 Set 函数通常包含应在属性更改之前或之后执行的代码。

若要使此属性很有用,可以在类型控件 short类中声明二维数组成员变量,以存储参数化属性的值。 然后,可以修改 Get 函数以返回存储在正确行和列的值,如参数指示,并修改 Set 函数以更新行和列参数引用的值。

处理 ActiveX 控件中的错误

如果控件中出现错误条件,可能需要将错误报告给控件容器。 报告错误有两种方法,具体取决于发生错误的情况。 如果错误发生在属性的 Get 或 Set 函数中,或者在 OLE 自动化方法的实现中发生,控件应调用 COleControl::ThrowError,该作会向控件用户发出错误信号。 如果错误发生在任何其他时间,该控件应调用 COleControl::FireError,这会触发库存错误事件。

若要指示发生的错误类型,控件必须向或传递FireError错误代码ThrowError。 错误代码是具有 32 位值的 OLE 状态代码。 如果可能,请从 OLECTL 中定义的标准代码集中选择错误代码。H 头文件。 下表汇总了这些代码。

ActiveX 控件错误代码

错误 DESCRIPTION
CTL_E_ILLEGALFUNCTIONCALL 非法函数调用
CTL_E_OVERFLOW 溢出
CTL_E_OUTOFMEMORY 内存不足
CTL_E_DIVISIONBYZERO 被零除
CTL_E_OUTOFSTRINGSPACE 字符串空间不足
CTL_E_OUTOFSTACKSPACE 堆栈空间不足
CTL_E_BADFILENAMEORNUMBER 文件名或数字错误
CTL_E_FILENOTFOUND 找不到文件
CTL_E_BADFILEMODE 文件模式错误
CTL_E_FILEALREADYOPEN 文件已打开
CTL_E_DEVICEIOERROR 设备 I/O 错误
CTL_E_FILEALREADYEXISTS 文件已存在
CTL_E_BADRECORDLENGTH 错误的记录长度
CTL_E_DISKFULL 磁盘已满
CTL_E_BADRECORDNUMBER 错误的记录编号
CTL_E_BADFILENAME 文件名错误
CTL_E_TOOMANYFILES 文件过多
CTL_E_DEVICEUNAVAILABLE 设备不可用
CTL_E_PERMISSIONDENIED 权限被拒绝
CTL_E_DISKNOTREADY 磁盘未就绪
CTL_E_PATHFILEACCESSERROR 路径/文件访问错误
CTL_E_PATHNOTFOUND 找不到路径
CTL_E_INVALIDPATTERNSTRING 无效的模式字符串
CTL_E_INVALIDUSEOFNULL NULL 的使用无效
CTL_E_INVALIDFILEFORMAT 文件格式无效
CTL_E_INVALIDPROPERTYVALUE 属性值无效
CTL_E_INVALIDPROPERTYARRAYINDEX 属性数组索引无效
CTL_E_SETNOTSUPPORTEDATRUNTIME 运行时不支持设置。
CTL_E_SETNOTSUPPORTED 不支持 Set 语句(只读属性)
CTL_E_NEEDPROPERTYARRAYINDEX 需要属性数组索引
CTL_E_SETNOTPERMITTED 不允许进行设置
CTL_E_GETNOTSUPPORTEDATRUNTIME 运行时不支持 Get 语句
CTL_E_GETNOTSUPPORTED 不支持 Get(只写属性)
CTL_E_PROPERTYNOTFOUND 找不到属性
CTL_E_INVALIDCLIPBOARDFORMAT 剪贴板格式无效
CTL_E_INVALIDPICTURE 图片无效
CTL_E_PRINTERERROR 打印机错误
CTL_E_CANTSAVEFILETOTEMP 无法将文件保存到 TEMP
CTL_E_SEARCHTEXTNOTFOUND 找不到搜索文本
CTL_E_REPLACEMENTSTOOLONG 替换内容太长

如有必要,请使用 CUSTOM_CTL_SCODE 宏为某个标准代码未涵盖的条件定义自定义错误代码。 此宏的参数应为介于 1000 和 32767 之间的整数(包括 32767)。 例如:

#define MYCTL_E_SPECIALERROR CUSTOM_CTL_SCODE(1000)

如果要创建 ActiveX 控件来替换现有的 VBX 控件,请使用 VBX 控件用来确保错误代码兼容的相同数值定义 ActiveX 控件错误代码。

处理控件中的特殊键

在某些情况下,你可能希望以特殊方式处理某些击键组合;例如,在多行文本框控件中按下 ENTER 键时插入新行,或者在按下方向键 ID 时在一组编辑控件之间移动。

如果 ActiveX 控件的基类是 COleControl,则可以重写 CWnd::P reTranslateMessage 来处理消息,然后容器处理它们。 使用此方法时,如果处理替代PreTranslateMessage中的消息,请始终返回 TRUE

下面的代码示例演示了处理与方向键相关的任何消息的可能方法。

BOOL CMyAxUICtrl::PreTranslateMessage(MSG* pMsg)
{
   BOOL bHandleNow = FALSE;

   switch (pMsg->message)
   {
   case WM_KEYDOWN:
      switch (pMsg->wParam)
      {
      case VK_UP:
      case VK_DOWN:
      case VK_LEFT:
      case VK_RIGHT:
         bHandleNow = TRUE;
         break;
      }
      if (bHandleNow)
      {
         OnKeyDown((UINT)pMsg->wParam, LOWORD(pMsg->lParam), HIWORD(pMsg->lParam));
      }
      break;
   }
   return bHandleNow;
}

有关处理 ActiveX 控件的键盘接口的详细信息,请参阅 ActiveX SDK 文档。

访问运行时不可见的对话控件

可以创建没有用户界面且在运行时不可见的对话框控件。 如果在运行时 ActiveX 控件中添加一个不可见控件,并使用 CWnd::GetDlgItem 访问控件,该控件将无法正常工作。 相反,应使用以下方法之一来获取表示控件的对象:

  • 使用“添加成员变量向导”,选择 “控件变量 ”,然后选择控件的 ID。 输入成员变量名称,并选择控件的包装类作为 控件类型

    -或-

  • 将局部变量和子类声明为对话框项。 插入类似于以下内容的代码(CMyCtrl 是包装类,IDC_MYCTRL1是控件的 ID):

    CCirc myCirc;
    myCirc.SubclassDlgItem(IDC_CIRCCTRL2, this);
    // ... use myCirc ...
    myCirc.UnsubclassWindow();
    

另请参阅

MFC ActiveX 控件