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)
所以至少现在我有一些剪贴板格式:
我仍然无法在 MSDN 上找到任何有关这两种剪贴板格式的信息。
监视发送到我的窗口的消息,看起来Math Input Panel
应用程序发送了一个Ctrl+V
:
VK_CONTROL
V
键VK_CONTROL
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, and
Advise`,这是C# 无法完成的。
但你不需要这样做,你可以直接使用Ctrl+V
.