閱讀完本文後, 你将可以自定義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檔案夾下的内容吧:
在這裡不僅找到了2個Frame的source, 還有InfoPath所用控件的定義. 接下來的任務就是修改相應的檔案, 并且儲存回DLL. 再用新的DLL覆寫原來的DLL. 相信這是每個程式員都能做的事, 我就不贅述了.
使用附件中的"INSPECTORFIELD.HTML"檔案覆寫IPDSINTL.DLL相應的檔案, 可以得到如下效果:
"Copy Text" 可以複制目前Logic Inspector 的文字内容至剪貼闆.