天天看點

InfoPath 揭秘 (一)

閱讀完本文後, 你将可以自定義InfoPath Logic Inspector, 并且能夠輕松地做到下圖所示的改動.

InfoPath 揭秘 (一)

我将會以一個更複雜且更實用的例子來示範如何自定義InfoPath Logic Inspector.

InfoPath Logic Inspector 的局限

InfoPath Logic Inspector最令人頭痛的事莫過于無法複制其中的内容. 再加上它是一個模式對話框, 對于InfoPath 開發人員來說實在是不友善. 如果能夠提供複制目前内容的功能, 将會友善很多.

InfoPath Logic Inspector 到底是什麼?

既然InfoPath沒有暴露任何有關Logic Inspector的接口, 那麼就需要我們自己探索了. 首先要弄清楚Logic Inspector到底是由什麼控件組成的. 使用Visual Studio的工具Spy++, 可以很容易檢視到Logic Inspector實際上是一個IE控件.

InfoPath 揭秘 (一)
OK. 接下來, 我們要将Logic Inspector中的内容抓取出來. 下面的代碼展示了如何擷取IE控件中的内容. 在文章的附件中會有完整的代碼.

  1. EnumWindows(new EnumWindowsProc(EvalWindow), IntPtr.Zero);  
  2.             foreach (IntPtr hwnd in ipHwnds)  
  3.             {  
  4.                 StringBuilder sb = new StringBuilder(256);  
  5.                 GetWindowText(hwnd, sb, 256);  
  6.                 IntPtr hwndIPIE = IntPtr.Zero;  
  7.                 IntPtr parentHwnd = hwnd;  
  8.                 String className = String.Empty;  
  9.                 while (!className.Equals("Internet Explorer_Server"))  
  10.                 {  
  11.                     EnumChildProc childProc = new EnumChildProc(EnumChildWindows);  
  12.                     EnumChildWindows(parentHwnd, childProc, ref hwndIPIE);  
  13.                     className = GetClassName(hwndIPIE);  
  14.                     parentHwnd = hwndIPIE;  
  15.                 }  
  16.                 IHTMLDocument2 htmlDoc = IEDOMFromhWnd(hwndIPIE);  
  17.                 String htmlText = htmlDoc.body.parentElement.outerHTML;  
  18.                 StreamWriter sw = new StreamWriter(String.Format("d:\\{0}.html", sb.ToString()));  
  19.                 sw.Write(htmlText);  
  20.                 sw.Close();  
  21.             }  

以下是從Logic Inspector 抓取的内容:

  1. <html> 
  2. <head> 
  3.     <title>Logic Inspector</title> 
  4.     <meta content="text/html; charset=utf-8" http-equiv="Content-Type"></meta> 
  5. </head> 
  6. <frameset id="idframeset" framespacing="2" border="2" cols="50%,50%"> 
  7. <FRAME id=overallFrame src="res://1033\ipdsintl.dll/InspectorOverallFrames.html" scrolling=yes> 
  8. <FRAME id=fieldFrame src="res://1033\ipdsintl.dll/InspectorFieldFrames.html" scrolling=yes> 
  9. </frameset> 
  10. </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重要的資源檔案.

InfoPath 揭秘 (一)

還記得2個frame的路徑嗎? 趕緊看看HTML檔案夾下的内容吧:

InfoPath 揭秘 (一)

在這裡不僅找到了2個Frame的source, 還有InfoPath所用控件的定義. 接下來的任務就是修改相應的檔案, 并且儲存回DLL. 再用新的DLL覆寫原來的DLL. 相信這是每個程式員都能做的事, 我就不贅述了.

使用附件中的"INSPECTORFIELD.HTML"檔案覆寫IPDSINTL.DLL相應的檔案, 可以得到如下效果:

InfoPath 揭秘 (一)

"Copy Text" 可以複制目前Logic Inspector 的文字内容至剪貼闆.

下一篇: asp分頁