InfoPath 揭祕 (一)

閱讀完本文後, 你將可以自定義InfoPath Logic Inspector, 並且能夠輕鬆地做到下圖所示的改動.
 
Logic
 
我將會以一個更復雜且更實用的例子來示範如何自定義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控件中的內容. 在文章的附件中會有完整的代碼.

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

以下是從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重要的資源文件.

 

 

還記得2個frame的路徑嗎? 趕緊看看HTML文件夾下的內容吧:

 

 

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

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

"Copy Text" 可以複製當前Logic Inspector 的文字內容至剪貼板.

"Copy HTML" 可以複製當前Logic Inspector 的HTML內容至剪貼板.

Conclusion

發現了IPDSINTL.DLL後, 我們不僅僅能修改Logic Inspector, 連InfoPath內置的控件也可以修改了. 接下來就需要大家發揮自己的想象力了~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章