我如何接受 MathML?

Ian*_*oyd 5 winapi mathml windows-7

今天我发现 Windows 7 附带了一个非常令人印象深刻的 MathPanel 实用程序,用于执行方程式的手写识别:

在此输入图像描述

这很好。(这里我输入了sRGB色彩空间伽玛转换部分的公式)

但现在我似乎无法用它做任何事情。

有一个插入按钮。我假设单击“插入”会将其插入到其后面活动的应用程序中(就像屏幕键盘的工作原理一样):

在此输入图像描述

但我假设它将作为粘贴操作进行操作。

我在帮助中找不到有关应用程序需要什么才能使其工作的信息。没有提及某些软件必须支持的任何特殊 API。

我在 MSDN 上也找不到任何关于接受方程插入需要什么特殊 API 的信息。

我必须实现哪些 API、注册、回调、侦听器、消息、COM 对象才能接收 MathPanel 输入?

我提到MathML 的唯一原因是因为SuperUser 的一个答案提到了 MathML

理论上,任何支持MathML(数学标记语言)的应用程序都可以与 Windows 7 数学输入面板一起使用。数学输入面板仅适用于支持 MathML 的程序。以下是一些此类应用程序:StarOffice、OpenOffice、Opera 和 Maple。

那么我如何让我的程序支持MathML?

据我所知 MathML 是一种标记语言;不是 Windows API。这就像说“我如何让我的程序支持 HTML?” Html 是文本,您可以将其粘贴到任何地方。

MathPad 拒绝粘贴,除非我“支持”MathML?


更新

单击“插入”后检查IDataObject剪贴板上的,我看到两种可用格式(都不是文本,这解释了为什么我没有得到任何标记):

格式1:

     CLIPFORMAT cfFormat: "MathML Presentation" (49839)
PDVTargetDevice ptd:      0x00000000
          DWORD dwAspect: DVASPECT_CONTENT
          DWORD lindex:   -1
          DWORD tymed:    1  (TYMED_HGLOBAL)
Run Code Online (Sandbox Code Playgroud)

格式2:

     CLIPFORMAT cfFormat:"MathML" (49838)
PDVTargetDevice ptd:      0x00000000
          DWORD dwAspect: DVASPECT_CONTENT
          DWORD lindex:   -1
          DWORD tymed:    1  (TYMED_HGLOBAL)
Run Code Online (Sandbox Code Playgroud)

所以至少现在我有一些剪贴板格式:

  • “MathML 演示”
  • “数学ML”

我仍然无法在 MSDN 上找到任何有关这两种剪贴板格式的信息。

Ian*_*oyd 3

监视发送到我的窗口的消息,看起来Math Input Panel应用程序发送了一个Ctrl+V

  • WM_KEYDOWN (0x11)VK_CONTROL
  • WM_KEYDOWN (0x56)V
  • WM_CHAR (0x16)
  • WM_KEYUP (0x11)VK_CONTROL
  • WM_KEYUP (0x56)V

因此,您需要识别有人正在尝试按 Ctrl+V。然后您必须提取内容。

首先注册三种剪贴板格式:

Handle CF_MathML_Presentation = RegisterClipboardFormat("MathML Presentation");
Handle CF_MathML_Content = RegisterClipboardFormat("MathML Content");
Handle CF_MathML = RegisterClipboardFormat("MathML");
Run Code Online (Sandbox Code Playgroud)

注意: W3C 数学标记语言 (MathML) 3.0 版的附录 B记录了要注册的 Windows 剪贴板格式名称:

  • 通用 MathML Windows 剪贴板名称:MathML
  • 演示文稿 MathML Windows 剪贴板名称:MathML Presentation
  • 内容 MathML Windows 剪贴板名称:MathML Content

IDataObject然后获取剪贴板中的句柄:

IDataObject dataObject;
OleGetClipboard(dataObject);
Run Code Online (Sandbox Code Playgroud)

然后枚举所有格式,寻找您喜欢的一种:

IEnumFORMATETC enum;
dataObject.EnumFormatEtc(DATADIR_GET, out enum);

String mathXml = "";

foreach (FormatEtc format in enum)
{
    if (format.cfFormat = CF_MathML_Presentation) ||
       (format.cfFormat = CF_MathML_Content) ||
       (format.cfFormat = CF_MathML)
    {
        //We know how to handle these formats:
        STGMEDIUM medium;
        dataObject.GetData(format.cfFormat, out medium);

        mathXml = GetStringFromStorageMedium(medium); //handles all the nasty HGlobal/IStream/IStorage nonsense
    }
}

ShowMessage(mathXml); //tada!
Run Code Online (Sandbox Code Playgroud)

Microsoft 还允许您对数学输入 COM 对象进行编程

//Create the COM object
IMathInputControl mathInputControl = CreateComObject(CLSID_MathInputControl);
mathInputControl.Show();
Run Code Online (Sandbox Code Playgroud)

然后您可以创建一个接收通知事件的对象:

class MathEvents : _IMathInputControlEvents
{
    public HRESULT Insert(String mathXml)
    {
       //Notifies the event handler when the Insert button is clicked.
       MessageBox.Show(mathXml);
       return S_OK;
    }

    public HRESULT Clear()
    {
       //Notifies the event handler when the Clear button is clicked.      
       return S_OK;
    }

    public HRESULT Close()
    {
       //Notifies the event handler when the Close button is clicked.
       return S_OK;
    }

    public HRESULT PaintHRESULT Paint(LONG_PTR hdc, LONG Left, LONG Top, LONG Right, LONG Bottom, LONG Element, LONG State)
    {
       //Notifies the event handler when the buttons and background of the control require painting.
       return S_OK;           
    }
Run Code Online (Sandbox Code Playgroud)

缺少的部分是如何提供mathInputControl对回调对象的引用。

这是超级秘密的复杂 COM 代码,涉及ConnectionPointContainer, andAdvise`,这是C# 无法完成的。

但你不需要这样做,你可以直接使用Ctrl+V.