WebView2控制元件應用詳解系列部落格
.NET混合開發解決方案2 WebView2與Edge瀏覽器的區別
.NET混合開發解決方案5 WebView2執行時與分發應用
.NET混合開發解決方案7 WinForm程式中通過NuGet管理器引用整合WebView2控制元件
.NET混合開發解決方案8 WinForm程式中通過設定固定版本執行時的BrowserExecutableFolder屬性整合WebView2控制元件
.NET混合開發解決方案9 WebView2控制元件的導航事件
Edge瀏覽器中的網頁,點選滑鼠右鍵,出現上下文選單及子選單,如下圖
WebView2控制元件載入網頁後,滑鼠在網頁上點選右鍵,也會出現上下文選單,如下圖
對比可以看出WebView2控制元件中的右鍵上下文選單內容比Edge瀏覽器中網頁的右鍵右鍵上下文選單的數量少。結合我的部落格《.NET混合開發解決方案2 WebView2與Edge瀏覽器的區別》可知,WebView2控制元件中對於網頁右鍵上下文選單做了裁剪。
在企業級應用軟體開發中,可能有以下幾種種常有且實用的需求
使用 webView2.CoreWebView2.ExecuteScriptAsync() 方法執行JS指令碼即可實現禁用右鍵選單
await webView.CoreWebView2.ExecuteScriptAsync("window.addEventListener('contextmenu', window => {window.preventDefault();});");
或者通過C#編碼禁用右鍵選單
webView2.CoreWebView2.Settings.AreDefaultContextMenusEnabled = false;
有的開發者小夥伴會說,我在網頁中寫JS也可以禁用右鍵上選單,確實如此
function document.oncontextmenu() { return false; } function nocontextmenu() { if(document.all) { event.cancelBubble=true; event.returnvalue=false; return false; } }
但是通過WebView2進行控制,一方面不改變網頁本身的功能,另一方面可以統一控制網頁右鍵選單的啟用與禁用。
通過WebView2能禁用右鍵選單,理論上也可以自定義右鍵選單。WebView2提供了豐富的API供開發者使用,參考微軟官方文件《自定義 WebView2 中的上下文選單》,可以實現自定義的右鍵選單。
關於右鍵選單的術語
- 選單項 包括核取方塊、命令、單選按鈕、分隔符和子選單。
- 命令 五種型別的選單項之一。
- 上下文選單 屬於 WebView2 控制元件的預設上下文選單 (右鍵單擊選單) 或自定義上下文選單 (右鍵單擊選單) 屬於主機應用。
與WebView2控制元件右鍵選單相關的事件、類、屬性與列舉
-
CoreWebView2ContextMenuItemKind 列舉
CoreWebView2ContextMenuItemKind.Command
CoreWebView2ContextMenuItemKind.Separator
指示為目標屬性建立上下文選單的上下文種類。此列舉將始終表示導致上下文選單請求的活動元素。例如,如果有一個包含多個影像、音訊和文字的選擇,終端使用者在此選擇中右鍵單擊的元素將是此列舉表示的選項。
-
- Audio 指示上下文選單是為音訊元素建立的。
- Image 指示上下文選單是為影像元素建立的。
- Page 指示上下文選單是為頁面建立的,沒有任何其他內容。
- SelectedText 指示上下文選單是為所選文字建立的。
- Video 指示上下文選單是為視訊元素建立的。
-
CoreWebView2ContextMenuItemKind 列舉
CheckBox
Radio
Separator
Submenu
首先獲取WebView2控制元件的預設右鍵選單列表,檢視每一項的具體屬性資訊。通過註冊WebView2的ContextMenuRequested事件,使用事件引數CoreWebView2ContextMenuRequestedEventArgs中提供的資料來顯示包含所選條目的自定義上下文選單。
預設提供12個右鍵選單項(包含分隔符),除錯程式碼檢視每個選單項資訊,如下
觀察12個選單項,可以發現以下規律
- 分割線的Kind值為Separator,其餘選單項的Kind值為Command。
- 分割線的CommandId值為-1,label值為空字串,name值為other。
- Kind值為Command的選單項CommandId、label、name值不同且唯一。
一般的應用程式保留【返回】、【前進】、【重新整理】三個選單項即可滿足。此時就需要刪除其他的選單項。實現邏輯如下
1 private void CoreWebView2_ContextMenuRequested(object? sender, CoreWebView2ContextMenuRequestedEventArgs args) 2 { 3 IList<CoreWebView2ContextMenuItem> allMenuList = args.MenuItems; 4 5 var itemOfSaveAs = allMenuList.FirstOrDefault(x => x.Name == "saveAs"); 6 if (itemOfSaveAs != null) 7 allMenuList.Remove(itemOfSaveAs); 8 9 var itemOfPrint = allMenuList.FirstOrDefault(x => x.Name == "print"); 10 if (itemOfPrint != null) 11 allMenuList.Remove(itemOfPrint); 12 13 var itemOfCreateQRCode = allMenuList.FirstOrDefault(x => x.Label == "為此頁面建立 QR 程式碼"); 14 if (itemOfCreateQRCode != null) 15 allMenuList.Remove(itemOfCreateQRCode); 16 17 var itemOfShare = allMenuList.FirstOrDefault(x => x.CommandId == 50460); 18 if (itemOfShare != null) 19 allMenuList.Remove(itemOfShare); 20 21 var itemOfSaveInspectElement = allMenuList.FirstOrDefault(x => x.Name == "inspectElement"); 22 if (itemOfSaveInspectElement != null) 23 allMenuList.Remove(itemOfSaveInspectElement); 24 }
測試效果如下圖
現在只有【返回】、【前進】、【重新整理】選單項了,但是最後還有一條分割線。
除錯程式碼可知目前還有7個選單項,其中第4,5,6,7項都是分割線。在12個原始選單項中就包含有四個分割線,所以此處需要刪除這4個分割線
修改邏輯程式碼
再次測試,效果如下圖
如果是清空所有的選單項就比較簡單了,直接清空右鍵選單列表
IList<CoreWebView2ContextMenuItem> allMenuList = args.MenuItems; allMenuList.Clear();//清空所有的預設選單項
上述第二個場景中保留了【返回】、【前進】、【重新整理】三個選單項,滿足大多數場景的需求。考慮一些極端情況,系統需要統一實現自定義的右鍵選單功能。
通過一個簡單的示例來演示如何實現自定義WebView2 中的上下文選單。
場景:在第二個場景的基礎之上,增加2個自定義右鍵選單項。
先看下實現效果
同樣需要在WebView2控制元件的ContextMenuRequested事件中實現
private void CoreWebView2_ContextMenuRequested(object? sender, CoreWebView2ContextMenuRequestedEventArgs args) { IList<CoreWebView2ContextMenuItem> allMenuList = args.MenuItems; PopulateContextMenu(args, allMenuList); }
其中新增選單項的邏輯如下
CoreWebView2ContextMenuItem 類不能直接例項化,需要使用 webView2.CoreWebView2.Environment.CreateContextMenuItem() 類建立一個選單物件。CreateContextMenuItem() 方法中傳遞三個引數
1、選單項的名稱。如果是分割線,則設定為空字串。
2、選單項的圖示,是檔案流物件。如果不設定,則賦值為null。
3、選單項的型別,包含Command(命令按鈕)、CheckBox(核取方塊)、Radio(單選框)、Separator(分割線)、Submenu(子選單)。
程式中我設定了CheckBox,但是執行後沒有生效,暫時不知道什麼原因。如有小夥伴研究出來了,可以分享一下。
選單項還有Label、CommandId屬性,但是隻讀,無法賦值
除錯程式可以看到,建立選單時,CommandId的值是自動分配的,Label的值與Name相同。
ContextMenuRequested
事件。當應用檢測到此事件時,應用應執行以下操作的一些組合:將自定義選單項新增到預設上下文選單。- 從預設上下文選單中刪除自定義選單項。
- 開啟自定義上下文選單。
該 ContextMenuRequested
事件指示使用者請求開啟上下文選單。
WebView2 控制元件引發此事件,指示使用者請求在 WebView2 控制元件中開啟上下文選單,例如右鍵單擊。
僅當前網頁允許顯示上下文選單時,WebView2 控制元件才會引發 ContextMenuRequested
事件,即 AreDefaultContextMenusEnabled
= true
時引發該事件。
CoreWebView2ContextMenuRequestedEventArgs 包含以下資訊:
-
要填充自定義上下文選單的
ContextMenuItem
物件的有序列表。 已排序列表包括以下內容:- 選單項的內部名稱。
- 選單項的 UI 標籤,顯示給 UI 中的使用者。
- 選單項的型別。
- 鍵盤快捷方式說明(如有
Alt+C
)。 - 自定義選單項的任何其他屬性。
-
請求上下文選單的座標,以便應用可以檢測使用者右鍵單擊的 UI 項。 座標是根據 WebView2 控制元件的左上角定義的。
-
包含所選上下文型別的選擇物件 和相應的上下文選單引數資料。
當使用者在上下文選單上選擇自定義選單項時,WebView2 控制元件將觸發 CustomItemSelected
事件,開發者在該事件中可以自定義業務邏輯。