1. 程式人生 > >解決 WPF 自繪窗體 AllowsTransparency = true 和 Webbrowser 等內建窗體顯示衝突的辦法和思路

解決 WPF 自繪窗體 AllowsTransparency = true 和 Webbrowser 等內建窗體顯示衝突的辦法和思路

       上述示例程式的幾個關鍵點:

  1. WPF 窗體為主窗體,窗體風格為 AllowsTransparency = true
  2. 分別對主窗體內建 WPF 的 Webbrowser 控制元件和 Winform 的 Webbrowser 控制元件進行了演示
  3. 完美的窗體縮放、移動、最大化等操作
  4. 演示隨意調整窗體背景透明度
  5. 示例程式碼簡單易操作,是可以找得到的最完美,而且的確是完美的解決辦法

       山寨關鍵點

       一、關鍵程式碼如下:

WPF

WebBrowserOverlay wbo = new WebBrowserOverlay(_webBrowserPlacementTarget);
System.Windows.Controls.WebBrowser wb = wbo.WebBrowser;
wb.Navigate(new Uri(“

http://blog.csdn.net/hikaliv/”));

Winform

WebBrowserOverlayWF wbo = new WebBrowserOverlayWF(_webBrowserPlacementTarget);
System.Windows.Forms.WebBrowser wb = wbo.WebBrowser;
wb.Navigate(new Uri(“
http://blog.csdn.net/hikaliv”));

       這兩段程式碼分別是你在程式裡面安置 WPF 的 Webbrowser 控制元件或 Winform 的 Webbrowser 控制元件的方法——關鍵在你不能放錯地方。注意

:程式碼你只能放在主窗體的建構函式處,InitializeComponent() 方法之後。

       二、別忘了在工程 References 裡面新增 System.Windows.Presentation.dll,若要用到 Winform 的控制元件,還需要新增 System.Windows.Forms.dll 引用。

       三、不得設定 WindowStartupLocation 屬性。

       這不是我的方法和示例程式碼,這是微軟工程師的方法和示例程式碼,詳見我轉載他們的幾篇關鍵文章:

       此示例完整地詮釋了一種最可取的辦法——在主窗體上劃出一塊區域,由一塊 FrameworkELement Object 的可視域(CompositionTarget)

來呈現瀏覽器控制元件所屬的頂級窗體——重點是這個“頂級窗體(Top-Level Window)”——以實現”視覺上”瀏覽器“內嵌”在主窗體。

       此法三個關鍵點用紅字標出。這三個關鍵點也道出了此法作為最可取之法——其實也是唯一可取之法的原因。或許還有其它辦法,但效果一定都不理想,靈活性也差。最終的效果是需要“視覺上內嵌”,而事實上並不需要邏輯上內嵌——因為邏輯內嵌的結果是不想要的,否則也不會有這個困難了。這個問題出現的關鍵在於上面第三篇文章介紹的內容,還有一點是 WPF(DirectX)和 Win32(GDI)的渲染順序——其實這些倒並不噁心,真正噁心的地方在於 Webbrowser 這個控制元件……你會發現 template 對它無用,而且用你能找到的最強大的內查工具看它是鉛板一塊,透視不得。WPF 的 Webbrowser 到底是個什麼神祕的東西需要這麼保密?——不僅神祕,而且古老——關鍵是古老,Winform 和 WPF 其實都沒有對它進行重寫以使它至少在 UI 上可以更強大,不,不僅 UI 體驗上沒有加強,而且事實功能上反而一代比一代更加弱小——建議大夥兒徹底放棄 system.windows.controls.webbrowser 好了,當它根本沒存在過,視而不見,只用 system.windows.forms.webbrowser,或者直接用 MFC 的,反正只不過需要加層 WindowsHost 或者 HWNDSOURCE 而已。

       正因為 Webbrowser 的噁心,因此唯一正確的思路則是必須將它和 WPF 主窗體邏輯解體。否則只能取締 WPF 窗體的 AllowsTransparency = true 屬性約束,使 WPF 的 Transparent/Alpha 通道渲染和這個控制元件的底層渲染不衝突。想闖闖沒有 AllowsTransparency = true 屬性約束的 WPF 自制窗體嗎?自己去處理無盡的 WINDOWS MESSAGE 麻煩吧——友情提示一聲—— WPF 渲染和系統(GDI)渲染是兩層,截訊息的辦法是行不通的……如果你還想再架層 DWM 渲染的話……祝你愉快。

       總之,WPF 自制窗體“內嵌”Webbrowser 控制元件必須的兩點:

  1. AllowsTransparency = true。這簡簡單單一句話……其實背後的水很深很深……沒它你試試……
  2. 控制元件與主窗體必須邏輯解體。

       問題癥結

       一句話概括就是“窗體的邏輯和渲染衝突”。我不知道非 WIN 系統是否會存在這個問題,然而在 WINDOWS 系統上,這是一個很噁心的問題。而且這也並非是個案,因為說得不好聽點兒,這根本就是版本間不可相容的事兒,是微軟產品的通病。我不瞭解 Apple 的 MAC 系統是如何渲染的,但我體會到了 WPF 渲染的代價——這麼多層、重複渲染、渲染衝突,而且還不如 MAC 的效果好,對硬體寬容,效能高……唉……

       抱怨一下,為何微軟的 WPF 開發團隊這麼“懶”呢?把 system.windows.controls.webbrowser 寫得比 system.windows.forms.webbrowser 要差,殘廢,而且 WPF 下面的 Datagrid 也遠不如 Winform 的 Datagridview。MS 平臺軟體開發的方向,從 MFC 的實打實,經過 Winform 越來越向 WPF 的華而不實的方向走……WPF 確立了一種全新的窗體組織形式,讓 UI 和控制元件開發實現了鬆耦合、自動化,但不能用實用性的缺失為交換。記得 .net framework 剛出來的時候,全新的 C#.net 體驗讓學長傳達給我他在微軟工程院從工程師那裡聽到的一句話——MFC 的末日到了……效率不效率的其實並非重點,重點是新框架下的控制元件比舊框架下的控制元件不實用……那又如何宣判得了舊框架的死刑呢?

相關推薦

解決 WPF 窗體 AllowsTransparency = true Webbrowser 窗體顯示衝突辦法思路

       上述示例程式的幾個關鍵點: WPF 窗體為主窗體,窗體風格為 AllowsTransparency = true 分別對主窗體內建 WPF 的 Webbrowser 控制元件和 Winform 的 Webbrowser 控制元件進行了演示 完美的窗體縮放、

MFC listbox , ComboBox 下拉列表框 如何設定其列表項的高度寬度?

自繪ListBox 設定其列表項的高度和寬度可以通過過載虛擬函式 MeasureItem (LPMEASUREITEMSTRUCT lpMeasureItemStruct) 來實現: void CMyComboBox::MeasureItem(LPMEASUREITEMST

js中的物件,宿主物件定義物件

JS中,可以將物件分為“內建物件”、“宿主物件”和“自定義物件”三種。 1,內建物件 js中的內建物件包括Array、Boolean、Date、Function、Global、Math、Number、Object、RegExp、String以及各種錯誤類物件,包括Erro

DELPHI一個對付存匯漏的辦法技巧

客戶端程序 類型 手動 顯示 釋放內存 解決 div 對話 時間 DELPHI是要手動釋放內存的,如果客戶端程序有泄漏,可能不是很大問題, 但是如果你是用DELPHI做服務端程序,有泄漏的話,時間一長會占用很多內存,直到服務端程序要關閉重啟.所以內存泄漏還是有害的. 而且程

【轉】Python 函式 locals() globals()

Python 內建函式 locals() 和globals() 轉自: https://blog.csdn.net/sxingming/article/details/52061630

判斷qq瀏覽器微信瀏覽器

var ua = navigator.userAgent.toLowerCase(), isWx = false,isQQ = false, isQQInstalled = false; if(ua.indexOf(' qq')>-1 &

Day06for迴圈字串的方法

Day06 1.for迴圈(迭代器迴圈) while迴圈 條件迴圈,迴圈是否結束取決於條件的真假 for迴圈,迭代器迴圈,多用於迴圈取值,迴圈是否結束取決於被迴圈資料的元素個數 2.range(1,5) 取值顧頭不顧尾,python2中為列表[1,2,3,4] python3 中為rang

列表字串的方法

列表中轉悠的內建方法: 1、append()  #在列表末尾新增新的物件 2、count()   #統計某個元素在列表中出現的次數 3、extend()    #在列表末尾一次性追加另一個序列中的多個值(用新列表擴充套件原來的列表) 4、index()   #從列表中找出某個值第一個匹配項的

python中的面向物件之類的設計常用的方法

一、面向物件和麵向過程的對比 1、面向物件 oop:object oriented programming 面向物件的基本概念 面向物件的程式設計核心是物件 我們之前學習的程式設計方式就是面向過程的 面向過程和麵向物件,是兩種不同的程式設計方式 對比面向過程的特點,可以更

python函式chr,ordunichr

chr(i) 引數i可以是十進位制數字也可以是十六進位制數字 返回字串對應的ascii字元 >>>chr(97) # 十進位制 >"a" >>>chr(0x30) # 十六進位制 >"0" unichr(i)

Python 函式 locals() globals()

1》這兩個函式主要提供,基於字典的訪問區域性變數和全域性變數的方式。 python 使用叫做名字空間的東西來記錄變數的軌跡。名字空間是一個字典 ,它的鍵就是字串形式的變數名字,它的值就是變數的實際值。 名字空間可以像 Python 的 dictionary 一樣進行訪問。

Python用字串做二進位制乘法Python呼叫進位制轉換我踩的坑

注意本文加法的思想來源於 https://blog.csdn.net/qiubingcsdn/article/details/82263114 其餘為我自己做的 字串str的末位是實際上計算的首位,所以第一步是翻轉字串 首先弄清楚python的字串列表

Python的有序集合listtuple

list----一種有序集合 classmates=['Mike','Bob','Tom'] classmates[-1]--------Tom,即倒數第一個 classmates[-2]--------Bob,即倒數第二個   classmates.append('A

微信瀏覽器支付寶瀏覽器 進行防止返回,返回跳轉到指定頁面

//防止返回歷史記錄 pushHistory(); function pushHistory() { var state = { title: "title", url: "#" }; window.history.pushState(sta

django的cookiesession以及訊號、快取

cookie和session cookie和session的作用: cookie和session都記錄了客戶端的某種狀態,用來跟蹤使用者訪問網站的整個回話。兩者最大的區別是cookie的資訊是存放在瀏覽器客戶端的,而session是存放在伺服器端的 cookie的基本操作 co

JSP的3個編譯指令、7個動作指令9個物件

3個編譯指令: 1、page:針對當前頁面的指令<%@ page ...%> 2、include:指定包含另一個頁面<%@ include file="jsp.jsp"%> 3、taglib:定義和訪問自定義標籤<%@ tag

mysql函式時間加減時間戳轉換

SELECT openid, FROM_UNIXTIME(createtime, '%Y-%m-%d') as registertime FROM etao_mokucloud_.ims_zofui_task_user WHERE uniacid = 7 AND

(灰常重要)jsp九大內物件整理總結EL表示式物件

轉自:https://blog.csdn.net/haha_sir/article/details/80350374https://www.cnblogs.com/sharpel/p/5870114.html一、什麼是內建物件1、我的理解是: jsp內建物件,不需要new來建

python中的面向物件(簡單類的建立以及方法,私有屬性私有方法的使用)

一、什麼面向物件和麵向過程? 面向物件:--誰來做? 相比較函式,面向物件是更大的封裝,根據職責在一個物件中封裝多個方法 1.在完成某一個需求前,首先確定職責--要做的事(方法) 2.根據職責確定不同的物件,在物件內部封裝不同的方法(多個) 3.最後完成程式碼

JavaScript常用物件及其相應屬性方法(一)

JavaSript物件的型別為Object型別,JavaSript物件分為內建物件和自定義物件。常用的JavaSript內建物件有以下4中:String,Date,Array,Math. String : 主要用於處理字串,常用屬性為length,常用方法如下