Internet 上的 ActiveX 控件

ActiveX 控件是 OLE 控件规范的更新版本。

重要

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

控件是开发可编程软件组件的主要体系结构,可用于各种不同容器,包括 Internet 上的 COM 感知 Web 浏览器。 任何 ActiveX 控件都可以是 Internet 控件,并且可以将其功能添加到活动文档或成为网页的一部分。 网页上的控件可以使用脚本相互通信。

ActiveX 控件不限于 Internet。 只要控件支持该容器所需的接口,ActiveX 控件也可用于任何容器。

ActiveX 控件具有多项优势,包括:

  • 所需的接口比以前的 OLE 控件少。

  • 能够无窗口且始终处于就地活动状态。

若要成为 ActiveX 控件,控件必须:

  • IUnknown支持接口。

  • 是 COM 对象。

  • 导出 DLLRegisterServerDLLUnRegisterServer

  • 支持功能所需的其他接口。

使现有控件 Internet-Friendly

设计在 Internet 环境中运行良好的控件需要考虑 Internet 上的传输速率相对较低。 可以使用现有控件;但是,应该执行一些步骤来减小代码大小,并异步下载控件属性。

若要提高控件的性能,请遵循以下有关效率注意事项的提示:

  • 实现 ActiveX 控件:优化一文中所述的技术。

  • 请考虑如何实例化控件。

  • 异步;不要按住其他程序。

  • 在小块中下载数据。

    下载大型流(如位图或视频数据)时,请与容器协作以异步方式访问控件的数据。 以增量或渐进方式检索数据,与其他可能同时检索数据的其他控件合作。 代码也可以异步下载。

  • 在后台下载代码和属性。

  • 尽快激活用户界面。

  • 考虑如何存储持久性数据,包括属性和大型数据 BLOB(例如位图图像或视频数据)。

    具有大量持久数据的控件(如大型位图或 AVI 文件)需要注意下载方法。 文档或页面可以尽快可见,并允许用户在控件检索后台数据时与页面交互。

  • 编写高效的例程以保持代码大小和运行时间。

    小型按钮和标签控件(仅包含少量字节的持久性数据)适用于 Internet 环境,并且适用于浏览器内部。

  • 考虑将进度传达给容器。

    在异步下载中通知容器进度,包括用户何时可以开始与页面交互,以及下载完成后。 容器可以向用户显示进度(如完成百分比)。

  • 考虑如何在客户端计算机上注册控件。

创建新的 ActiveX 控件

使用应用程序向导创建新控件时,可以选择启用对异步名字对象和其他优化的支持。 若要添加异步下载控件属性的支持,请执行以下步骤:

使用 MFC ActiveX 控件向导创建项目

  1. 单击“文件”菜单上的“新建”。

  2. 从 Visual Studio 中选择 MFC ActiveX 控件向导 C++项目并命名项目。

  3. “控件设置” 页上,选择 “异步加载属性”。 选择此选项会为你设置就绪状态属性和就绪状态更改事件。

    还可以选择其他优化,如 ActiveX 控件:优化中所述的无窗口激活

  4. 选择“完成”以创建项目

创建派生自 CDataPathProperty 的类

  1. 创建派生自 CDataPathProperty. 的类。

  2. 在包含控件头文件的每个源文件中,在此类的头文件之前添加此文件的头文件。

  3. 在此类中,重写 OnDataAvailable。 每当数据可供显示时,将调用此函数。 当数据变得可用时,你可以以任何方式处理它,例如,通过逐步呈现它。

    下面的代码摘录是逐步在编辑控件中显示数据的简单示例。 请注意使用标志 BSCF_FIRSTDATANOTIFICATION 清除编辑控件。

    void CMyDataPathProperty::OnDataAvailable(DWORD dwSize, DWORD bscfFlag)
    {
       CListCtrl list_ctrl;
       CEdit *edit = list_ctrl.GetEditControl();
       if ((bscfFlag & BSCF_FIRSTDATANOTIFICATION) && edit->m_hWnd)
       {
          edit->SetSel(0, -1);
          edit->Clear();
       }
    
       if (dwSize > 0)
       {
          CString string;
          LPTSTR str = string.GetBuffer(dwSize);
          UINT nBytesRead = Read(str, dwSize);
          if (nBytesRead > 0)
          {
             string.ReleaseBuffer(nBytesRead);
             edit->SetSel(-1, -1);
             edit->ReplaceSel(string);
          }
       }
    }
    

    请注意,必须包括 AFXCMN。要使用该类的 CListCtrl H。

  4. 当控件的总体状态发生更改(例如,从加载到初始化或用户交互),调用 COleControl::InternalSetReadyState。 如果控件只有一个数据路径属性,则可以在 BSCF_LASTDATANOTIFICATION 上添加代码,以通知容器下载已完成。 例如:

    if (bscfFlag & BSCF_LASTDATANOTIFICATION)
    {
       GetControl()->InternalSetReadyState(READYSTATE_COMPLETE);
    }
    
  5. 替代 OnProgress。 在中 OnProgress,你将传递一个数字,其中显示最大范围,一个数字显示当前下载的距离。 可以使用这些数字向用户显示状态,例如完成百分比。

下一过程将属性添加到控件,以使用刚刚派生的类。

添加属性

  1. 类视图中,右键单击库节点下方的接口,然后选择“ 添加”,然后选择“ 添加属性”。 这将启动 “添加属性向导”。

  2. “添加属性向导”中,选择 “设置/获取方法 ”单选按钮,键入 属性名称,例如 EditControlText,然后选择 BSTR 作为 属性类型

  3. 单击“完成”。

  4. 将 -derived 类的成员 CDataPathProperty变量声明到 ActiveX 控件类。

    CMyDataPathProperty EditControlText;
    
  5. Get/Set实现方法。 对于 Get,返回字符串。 对于 Set,加载属性和调用 SetModifiedFlag

    BSTR CMFCActiveXControlCtrl::GetEditControlText(void)
    {
       AFX_MANAGE_STATE(AfxGetStaticModuleState());
    
       CString strResult;
       strResult = EditControlText.GetPath();
       return strResult.AllocSysString();
    }
    
    void CMFCActiveXControlCtrl::SetEditControlText(LPCTSTR newVal)
    {
       AFX_MANAGE_STATE(AfxGetStaticModuleState());
    
       Load(newVal, EditControlText);
       SetModifiedFlag();
    }
    
  6. DoPropExchange 中,添加以下行:

    PX_DataPath(pPX, _T("DataPath"), EditControlText);
    
  7. 重写 ResetData 以通过添加以下行来通知属性重置其控件:

    EditControlText.ResetData();
    

决定是否派生自 CDataPathProperty 还是 CCachedDataPathProperty

前面的示例介绍了从中派生控件属性 CDataPathProperty的步骤。 如果要下载经常更改的实时数据,并且不需要保留所有数据,但仅保留当前值,则这是一个不错的选择。 例如股票时钟周期控件。

也可以派生自 CCachedDataPathProperty。 在这种情况下,下载的数据缓存在内存文件中。 如果需要保留所有下载的数据(例如,以渐进方式呈现位图的控件),这是一个不错的选择。 在这种情况下,该类具有包含数据的成员变量:

CMemFile m_Cache;

在 ActiveX 控件类中,可以使用此内存映射文件 OnDraw 来显示数据。 在 ActiveX 控件 CCachedDataPathProperty派生类中,在调用基类实现后重写成员函数 OnDataAvailable 并使控件失效。

void CMyCachedDataPathProperty::OnDataAvailable(DWORD dwSize, DWORD bscfFlag)
{
   CCachedDataPathProperty::OnDataAvailable(dwSize, bscfFlag);
   GetControl()->InvalidateControl();
}

使用 ActiveX 控件异步下载数据

应以异步方式通过网络下载数据。 这样做的优点是,如果传输大量数据或连接速度缓慢,则下载过程不会阻止客户端上的其他进程。

异步名字对象提供了一种通过网络异步下载数据的方法。 异步名字对象的读取作会立即返回,即使作尚未完成。

例如,如果只有 10 个字节可用,并且读取在 1K 文件上异步调用,则 Read 不会阻止,但返回当前可用的 10 个字节。

使用类实现异步名字对象CAsyncMonikerFile。 但是,ActiveX 控件可以使用 CDataPathProperty 派生自 CAsyncMonikerFile的类来帮助实现异步控件属性。

在网页上显示控件

下面是用于在网页上插入控件的对象标记和属性的示例。

<OBJECT
  CLASSID="clsid:FC25B780-75BE-11CF-8B01-444553540000"
  CODEBASE="/ie/download/activex/iechart.ocx"
  ID=chart1
  WIDTH=400
  HEIGHT=200
  ALIGN=center
  HSPACE=0
  VSPACE=0>
  <PARAM NAME="BackColor" value="#ffffff"/>
  <PARAM NAME="ForeColor" value="#0000ff"/>
  <PARAM NAME="url" VALUE="/ie/controls/chart/mychart.txt"/>
</OBJECT>

更新现有 OLE 控件以使用新的 ActiveX 控件功能

如果 OLE 控件是使用 4.2 之前的 Visual C++ 版本创建的,则可以执行一些步骤来提高其性能并增强其功能。 有关这些更改的详细讨论,请参阅 ActiveX 控件:优化

如果要向现有控件添加异步属性支持,则需要自行添加就绪状态属性和 ReadyStateChange 事件。 在控件的构造函数中,添加:

m_lReadyState = READYSTATE_LOADING;

通过调用 COleControl::InternalSetReadyState 下载代码时,将更新就绪状态。 你可以调用的一个位置是从 OnProgress -derived 类的重写中调用InternalSetReadyStateCDataPathProperty

另请参阅

MFC 互联网编程任务
MFC Internet 编程基础知识