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

这很好。 (这里我已经输入了 sRGB 颜色空间 Gamma 转换部分的公式)

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

有一个 插入 按钮。我会假设单击 插入 会将其插入到其后面处于事件状态的应用程序中(很像屏幕键盘的工作原理):

除了我假设它会作为粘贴操作运行。

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

我也无法在 MSDN 上找到有关接受方程插入所需的特殊 API 的任何信息。

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

我提到 MathML 的唯一原因是因为 SuperUser mentioned MathML 的答案:



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

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

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

更新

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

格式一:

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

格式2:
     CLIPFORMAT cfFormat:"MathML" (49838)
PDVTargetDevice ptd:      0x00000000
          DWORD dwAspect: DVASPECT_CONTENT
          DWORD lindex:   -1
          DWORD tymed:    1  (TYMED_HGLOBAL)

所以至少现在我有一些剪贴板格式:
  • "MathML 演示"
  • "MathML"

  • 我仍然无法在 MSDN 上找到任何关于剪贴板格式的信息。

    最佳答案

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

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

  • 所以你需要认识到有人试图按下 Ctrl+V。然后您必须提取内容。

    首先注册三种剪贴板格式:
    Handle CF_MathML_Presentation = RegisterClipboardFormat("MathML Presentation");
    Handle CF_MathML_Content = RegisterClipboardFormat("MathML Content");
    Handle CF_MathML = RegisterClipboardFormat("MathML");
    



    然后获取剪贴板中 IDataObject 的句柄:
    IDataObject dataObject;
    OleGetClipboard(dataObject);
    

    然后枚举所有格式,寻找您喜欢的格式:
    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!
    

    Microsoft 还允许您 program the Math Input COM object :
    //Create the COM object
    IMathInputControl mathInputControl = CreateComObject(CLSID_MathInputControl);
    mathInputControl.Show();
    

    然后,您可以创建一个接收通知事件的对象:
    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;
        }
    

    缺少的要素是如何为 mathInputControl 提供对回调对象的引用。

    这是 super secret 的复杂COM代码,涉及ConnectionPointContainer, and Advise`,which不能从C#中完成。

    但是你不需要,你可以使用 Ctrl+V

    关于winapi - 我如何接受 MathML?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/9364890/

    10-12 21:37