阅读完本文后, 你将可以自定义InfoPath Logic Inspector, 并且能够轻松地做到下图所示的改动.
我将会以一个更复杂且更实用的例子来示范如何自定义InfoPath Logic Inspector.
InfoPath Logic Inspector 的局限
InfoPath Logic Inspector最令人头痛的事莫过于无法复制其中的内容. 再加上它是一个模式对话框, 对于InfoPath 开发人员来说实在是不方便. 如果能够提供复制当前内容的功能, 将会方便很多.
InfoPath Logic Inspector 到底是什么?
既然InfoPath没有暴露任何有关Logic Inspector的接口, 那么就需要我们自己探索了. 首先要弄清楚Logic Inspector到底是由什么控件组成的. 使用Visual Studio的工具Spy++, 可以很容易查看到Logic Inspector实际上是一个IE控件.
OK. 接下来, 我们要将Logic Inspector中的内容抓取出来. 下面的代码展示了如何获取IE控件中的内容. 在文章的附件中会有完整的代码.
EnumWindows(new EnumWindowsProc(EvalWindow), IntPtr.Zero); foreach (IntPtr hwnd in ipHwnds) { StringBuilder sb = new StringBuilder(256); GetWindowText(hwnd, sb, 256); IntPtr hwndIPIE = IntPtr.Zero; IntPtr parentHwnd = hwnd; String className = String.Empty; while (!className.Equals("Internet Explorer_Server")) { EnumChildProc childProc = new EnumChildProc(EnumChildWindows); EnumChildWindows(parentHwnd, childProc, ref hwndIPIE); className = GetClassName(hwndIPIE); parentHwnd = hwndIPIE; } IHTMLDocument2 htmlDoc = IEDOMFromhWnd(hwndIPIE); String htmlText = htmlDoc.body.parentElement.outerHTML; StreamWriter sw = new StreamWriter(String.Format("d:\\{0}.html", sb.ToString())); sw.Write(htmlText); sw.Close(); }
以下是从Logic Inspector 抓取的内容:
<html> <head> <title>Logic Inspector</title> <meta content="text/html; charset=utf-8" http-equiv="Content-Type"></meta> </head> <frameset id="idframeset" framespacing="2" border="2" cols="50%,50%"> <FRAME id=overallFrame src="res://1033\ipdsintl.dll/InspectorOverallFrames.html" scrolling=yes> <FRAME id=fieldFrame src="res://1033\ipdsintl.dll/InspectorFieldFrames.html" scrolling=yes> </frameset> </html>
很明显, Logic Inspector 由2个Frame组成: "overallFrame" 和 "fieldFrame". 从名字即可知道"overallFrame"指代Logic Inspector的左半部, "fieldFrame" 指代Logic Inspector的右半部.
如果你足够细心, 就会发现一个奇妙的地方. 这2个Frame的source居然是从一个dll中读取的. 而这个ipdsintl.dll就是揭开InfoPath 秘密的重点.
IPDSINTL.DLL -- InfoPath 的资源文件
首先我们要找到IPDSINTL.DLL到底在哪. 从它的上级目录"1033"来看, 这个文件应该在Microsoft Office文件夹下. 如我所料, 它确实是老老实实呆在这的:
%ProgramFiles%\Microsoft Office\Office12\1033\IPDSINTL.DLL
把这个DLL拖到Visual Studio中, 可以看到其实它是InfoPath重要的资源文件.
还记得2个frame的路径吗? 赶紧看看HTML文件夹下的内容吧: