<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      不是我變態,我也是被逼的。客戶喜歡Word 2007里的Custom Task Pane,希望在側邊欄上放一些界面。但是他們剛剛從Word 97升級到2003,完全沒有可能升級到更高的版本。我之前給他們做過一個DEMO,是用ActionsPane技術實現的。他們覺得挺好,就要這個。但是我不喜歡ActionsPane,所以只能自己想辦法嘍。為什么不喜歡ActionsPane?理由有很多:

      1、綁定到Template,部署困難

      2、排版有問題

      3、穩定性不好,.NET控件是以ActiveX形式放置在上面的

      很快,我就注意到Word 2003不是沒有TaskPane的:

       

      那么我可不可以把我的東西放上去呢?那我們來查查MSDN吧。確實還有這么一個Interface,就叫TaskPane:

      http://msdn.microsoft.com/de-de/library/microsoft.office.interop.word.taskpane_members(VS.80).aspx

      但是很遺憾,我們在上面找不到任何線索,可以把我們控件加上去的。但是我們可以用Application.TaskPanes[xxx].Visible來控制特定TaskPane的開關。也算有點收獲啦。

      然后我們又注意到,這個TaskPane怎么看起來這么像Command Bar?它還真的就是一個CommandBar。用Application.CommandBars["Task Pane"].Visible,我們也可以開關TaskPane(不過必須要在TaskPane已經打開過一次的前提下)。而且MsoControlType里有也有一條msoControlWorkPane。嗯,看起來有戲?。。。門都沒有。MSDN上明說了,Work pane. Cannot be created through the object model。

      顯然,用微軟官方API的辦法是死路一條。但是也不是完全沒有收獲。

      1、通過Application.TaskPanes[xxx]我們可以可靠的開關TaskPane上的某一頁

      2、我們知道Application.CommandBars["Task Pane"]對應的就是TaskPane所在的Command Bar。

      曾經有一個讓我恨之入骨的Office開發庫,名字叫Addin-Express(大家不要用啊,誰用誰后悔)。當年我們用它就是因為它可以在Outlook里做類似的事情,在Email Composer上憑空多一塊區域出來(類似于Outlook 2007的Form Region)。它的實現原理其實就是用一個獨立的WinForm窗口,然后用為win32 api SetParent把窗口“融合”到Outlook上去。同時通過SetWindowLong的辦法攔截目標窗口的WndProc(窗口事件處理函數,所有的GUI事件的起點),達到你縮放我也縮放的目的。這次我決定不用Addin-Express來做(它也沒實現這個功能),但是可以利用其原理。

      在.NET中攔截WndProc的最簡單的辦法是用NativeWindow這個類。只要override WndProc那個方法就可以了 。

      public class Window : NativeWindow, IDisposable {
        
      protected override void WndProc(ref Message message) {
          
      // Your code
          base.WndProc(ref message);
        }
      }

      雖然知道大概的原理,不過還有一個難點一個疑問需要解決。那就是,到底以哪個Window來Parent?而且,這個Parent在隱藏之后再重現出來會不會被重新創建。如果父窗口每次都會被銷毀,那我們也沒法用SetParent大法了。這個時候就是Spy++出場的時候了。

      高亮的那個窗口就是我們的目標了。而且經過試驗證明,窗口SetParent到它身上之后,一直都在。 注意,如果設在NUIPane上是不行的,必須是在NetUIHWND上。這個窗口的ClassName是固定的,但是XML Structure那個TaskPane的窗口ClassName不一樣,不過也是一樣可以SetParent的。

      不過還有一個問題。我如何得到這個目標窗口的句柄呢?我甚至都沒法得到當前Word窗口的句柄。這個時候就需要依賴CommandBar的一個特性了,Accessible。這是Windows用來服務殘障人士的API。對于我們來說,就是CommandBar對象都實現了IAccessible這個Interface,然后我們就可以:

      OleAcc.WindowFromAccessibleObject((IAccessible) commandBar);

       WindowFromAccessibleObject是OleAcc這個DLL上的一個API。用來獲得Accssible對象的窗口句柄。利用Accessibility API可以做很多有意思的事情,比如http://blogs.officezealot.com/whitechapel/archive/2005/04/10/4514.aspx。這里就用了相反的一個操作,AccessibleObjectFromWindow來獲得Excel的對象,當年在寫Excel的UDF的時候幫了我的大忙。

      還有一個難點就是,如果TaskPane沒有打開我怎么SetParent。這個時候當然是利用前面提到的Application.TaskPanes[xxx]的方法來得到接口,并設置Visible了。不過還是有一個時間差。你設置下Visible之后,是一個異步地打開TaskPane的過程。所以當你接下來做SetParent的時候,那邊可能還沒有完成窗口的初始化。我現在只能用一個新線程Sleep(300)來完成這個任務。并不是完全不可靠,也不是完全可靠。最完美的解決方案還是升級到Word 2007。

       知道了上述的機要。實現Word 2003下的Custom Task Pane就是體力活了。用GetWindowRect來縮放,用GetPixel來融合背景色。最終的效果是這個樣子的。


      而且能縮能放,能關閉能打開,能Dock能Undock。遺憾的是必須要犧牲掉Word內建的TaskPane中的某一個。不過好在Word 2003中有那么多人們用不著的功能,犧牲掉一兩個,沒誰會注意到的,對吧?:)

      posted on 2008-11-01 19:38  taowen  閱讀(3302)  評論(4)    收藏  舉報
      主站蜘蛛池模板: 成 人 免费 在线电影| 国产成人8x视频一区二区| 日韩乱码卡一卡2卡三卡四| 九九re线精品视频在线观看视频 | 澳门永久av免费网站| 武装少女在线观看高清完整版免费 | 国产精品午夜福利资源| 国内自拍小视频在线看| 亚洲av不卡电影在线网址最新| 三人成全免费观看电视剧高清| 国产精品污www在线观看| 国产精品一区二区不卡视频| 亚洲另类激情专区小说图片| 肥臀浪妇太爽了快点再快点| 日本免费人成视频在线观看| 亚洲中文日韩一区二区三区| 亚洲欧美中文字幕日韩一区二区| 中文字幕亚洲综合久久| 国产精品高清视亚洲精品| 熟妇激情一区二区三区| 樱花草视频www日本韩国| www国产精品内射熟女| 国产亚洲精品久久yy50| 狠狠躁日日躁夜夜躁欧美老妇 | 国产成人高清亚洲综合| 日日爽日日操| 国产精品99久久免费| 日韩熟女乱综合一区二区| 国产高清精品在线91| 熟妇人妻任你躁在线视频| 中国女人熟毛茸茸A毛片| 池州市| 18禁精品一区二区三区| 亚洲天堂av日韩精品| 四虎永久精品在线视频| 亚洲高清WWW色好看美女| 欧美日本一区二区视频在线观看| 玩弄放荡人妻少妇系列| 亚洲人ⅴsaⅴ国产精品| 久久国产乱子伦免费精品无码| 中文字幕有码免费视频|