从数学输入控件接收输入

本部分介绍如何使用活动模板库 (ATL) 和组件对象模型 (COM) 从数学输入控件检索 MathML 标记。

若要从数学输入控件检索已识别的数学公式,可以替代按下插入按钮时发生的行为。 为此,需要设置一个事件处理程序,用于实现 _IMathInputControlEvents 接口支持的各种事件。 设置事件处理程序涉及对要支持的事件执行以下步骤,在本例中 (插入) 。

创建包含事件接收器的模板类

实现使用数学输入控件的事件接收器时,必须先指定接收器 ID。然后,必须创建一个从事件、事件控件处理程序和数学输入控件事件接口继承的模板类。 以下代码演示如何设置接收器 ID 并创建从必要接口继承的此类模板类 CMathInputControlEventHandler。 此模板类还设置为具有专用的未知接口指针,该指针将用于在初始化时将数学输入控件传递给它,m_ulAdviseCount成员用于计算建议/取消添加的调用数。

  
#pragma once
static const int MATHINPUTCONTROL_SINK_ID = 1 ;

template <class T>
class ATL_NO_VTABLE CMathInputControlEventHandler :
    public IDispEventSimpleImpl<MATHINPUTCONTROL_SINK_ID, CMathInputControlEventHandler<T>, &__uuidof(_IMathInputControlEvents)>
{
private:
    IUnknown    *m_pUnknown;
    ULONG m_ulAdviseCount;
    CDialog *m_pMain;

注意

如果不使用对话,则实现中的成员 m_pMain 应不同。

 

有了基本模板类后,必须为要重写的事件处理程序提供前向声明,然后必须为要处理的事件设置接收器映射。 下面的代码演示如何为 Insert 方法设置事件处理程序,当用户单击数学输入控件上的插入按钮时调用,以及当用户单击数学输入控件上的取消按钮时调用 的 Close 方法。

  
public:
    static const _ATL_FUNC_INFO OnMICInsertInfo; // = {CC_STDCALL, VT_I4, 1, {VT_BSTR}};
    static const _ATL_FUNC_INFO OnMICCloseInfo;  // = {CC_STDCALL, VT_I4, 0, {VT_EMPTY}};

    BEGIN_SINK_MAP(CMathInputControlEventHandler)
        SINK_ENTRY_INFO(MATHINPUTCONTROL_SINK_ID, __uuidof(_IMathInputControlEvents), DISPID_MICInsert, OnMICInsert, const_cast<_ATL_FUNC_INFO*>(&OnMICInsertInfo))
        SINK_ENTRY_INFO(MATHINPUTCONTROL_SINK_ID, __uuidof(_IMathInputControlEvents), DISPID_MICClose, OnMICClose, const_cast<_ATL_FUNC_INFO*>(&OnMICCloseInfo))  
    END_SINK_MAP()

由于你将使用数学输入控件,因此设置对相关接口的内部引用会很有用。 在示例类中创建以下实用工具函数来设置此引用。

    
  HRESULT Initialize(IUnknown *pUnknown, CDialog *pMain)
  {
    m_pMain  = pMain;
    m_pUnknown = pUnknown;
    m_ulAdviseCount = 0;
    return S_OK;
  }
  

设置事件处理程序

设置事件接收器后,需要创建事件接收器的实现。 在以下代码示例的两种方法中,事件接收器检索数学输入控件接口的句柄。 在 Insert 函数中,识别结果显示为 MathML,并且控件处于隐藏状态。 在 Close 函数中,数学输入控件处于隐藏状态。

  
    // Methods
    HRESULT __stdcall OnMICInsert( BSTR bstrRecoResult)
    {
        CComQIPtr<IMathInputControl> spMIC(m_pUnknown);
        HRESULT hr=S_OK;
        if (spMIC)
        {           
            MessageBox(NULL,bstrRecoResult,L"Recognition Result",MB_OK);
            hr = spMIC->Hide();
            return hr;  
        }
        return E_FAIL;          
    }

    HRESULT __stdcall OnMICClose()
    {
        CComPtr<IMathInputControl> spMIC;
        HRESULT hr = m_pUnknown->QueryInterface<IMathInputControl>(&spMIC);
        if (SUCCEEDED(hr))
        {           
            hr = spMIC->Hide();
            return hr;  
        }
        return hr;                  
    }
};  

继承 main 类中的事件处理程序类

实现模板类后,需要将其继承到要设置数学输入控件的类中。 就本指南而言,此类是一个对话,CMIC_TEST_EVENTSDlg。 在对话框标头中,必须包含必需的标头,并且必须继承创建的模板类。 要继承的类和事件处理程序必须具有前向声明,以便实现模板。 下面的代码示例演示如何执行此操作。

#pragma once
#include <atlbase.h>
#include <atlwin.h>

// include for MIC
#include "micaut.h"

// include for event sinks
#include <iacom.h>
#include "mathinputcontroleventhandler.h"

class CMIC_TEST_EVENTSDlg;

const _ATL_FUNC_INFO CMathInputControlEventHandler<CMIC_TEST_EVENTSDlg>::OnMICInsertInfo = {CC_STDCALL, VT_I4, 1, {VT_BSTR}};
const _ATL_FUNC_INFO CMathInputControlEventHandler<CMIC_TEST_EVENTSDlg>::OnMICCloseInfo = {CC_STDCALL, VT_I4, 0, {VT_EMPTY}};

// CMIC_TEST_EVENTSDlg dialog
class CMIC_TEST_EVENTSDlg : public CDialog,
    public CMathInputControlEventHandler<CMIC_TEST_EVENTSDlg>
{
  public:
  CComPtr<IMathInputControl> m_spMIC; // Math Input Control

  

注意

模板类型 (CMIC_TEST_EventsDlg)将有所不同,除非你为类命名与示例相同。

 

初始化类以继承事件接收器 ()

将类设置为从模板类继承后,即可将其设置为处理事件。 这将包括初始化 类,以具有数学输入控件和调用类的句柄。 此外,必须将处理事件中的数学输入控件发送到 CMathInputControlEventHandler 示例类继承的 DispEventAdvise 方法。 从示例类中的 OnInitDialog 方法调用以下代码以执行这些操作。

// includes for implementation
#include "micaut_i.c"

// include for event handler
#include "mathinputcontroleventhandler.h"

...

OnInitDialog{
  ...

  // TODO: Add extra initialization here
  CoInitialize(NULL);
  HRESULT hr = g_spMIC.CoCreateInstance(CLSID_MathInputControl);
  if (SUCCEEDED(hr)){
    hr = CMathInputControlEventHandler<CMIC_TEST_EVENTSDlg>::Initialize(m_spMIC, this);
      if (SUCCEEDED(hr)){
        hr = CMathInputControlEventHandler<CMIC_TEST_EVENTSDlg>::DispEventAdvise(m_spMIC);            
        if (SUCCEEDED(hr)){
          hr = m_spMIC->Show();  
        }
      }
    }
  }  
}
  

注意

除非将类命名为与示例相同的名称,否则模板类型(在本示例中CMIC_TEST_EventsDlg)将有所不同。