2016-02-02 183 views
0

我正在使用CefSharp作爲Gui的Winforms項目。出於幾個原因,我想使用Winforms的ContextMenu類實現一個自定義的上下文菜單;在Html中呈現菜單或自定義ChromiumWebBrowser的上下文菜單(使用CefSharp.IContextMenuHandler)不是一種選擇。通過ChromiumWebBrowser顯示Winforms Contextmenu

它通過調用.NET對象我傳遞給RegisterAsyncJsObject上的方法Javascript代碼觸發的上下文菜單;使用Javascript阻止了默認的上下文菜單。我在Gui線程上調用方法調用,因爲通過「javascript橋」調用註冊對象來自不同的線程。

我的問題:手動顯示Winforms上下文菜單通過CefSharp.WinForms.ChromiumWebBrowser時,上下文菜單不會獲得鍵盤焦點(例如,使用箭頭鍵選擇項目不起作用,也不能使用Esc關閉上下文菜單);相反,鍵盤焦點仍然與ChromiumWebBrowser控件保持一致。而且,如果我點擊ChromiumWebBrowser的控制區域,上下文菜單也不會關閉。我只能通過用鼠標選擇一個項目或者單擊窗體中的其他控件(包含ChromiumWebBrowser)或其他完全控制的其他控件(例如桌面或其他應用程序)來關閉上下文菜單。

如果我引發的右鍵菜單在我的代碼的其他地方 - 最終使用調用myContextMenu.Show同樣的方法() - 根據需要上下文菜單獲取鍵盤焦點。但有一個問題仍然存在:當我在ChromiumWebBrowser控件中單擊時,它不會關閉。

我沒有用過IFocusHander,IContextMenuHandler,IKeyboardHandler - 要這樣呢?

我使用CEF 3.2454.1344.g2782fb8,鉻45.0.2454.101和.net 4.5.1。

不幸的是提取演示代碼是不合理的。

任何任何想法?

EDIT1: 閱讀評論之後,我決定來形容碼流更確切地說:

  • 當右擊的JavaScript將消息發送到已註冊的.NET對象,包含鼠標座標。通過在ContextMenu事件的MouseEvent參數上設置preventDefault可以防止默認的上下文菜單。
  • 註冊.NET對象接收消息並調用windowForm.Invoke(Sub() ...),因爲主/ GUI線程上未接收到該消息,但必須有處理爲上下文菜單正確顯示。創建
  • 的文本菜單和分配給包含實際ChromiumWebBrowser控制該用戶控件的ContextMenuStrip屬性。
  • 它使用ContextMenuStrip.Show(location)方法顯示。

問題:

  • 上下文菜單中沒有鍵盤焦點。
  • 所有鼠標事件似乎被ChromiumWebBrowser「吞噬」:單擊那裏沒有關閉上下文菜單。
  • 打開上下文菜單相同,除了使用不同的「觸發器」工作正常,除了第二個問題。
+0

首先,默認是運行在它自己的線程的消息循環,導致在某些問題情景,如與菜單交互。還有一個選項,請參閱https://github.com/cefsharp/CefSharp/commit/fe11f2eada542f49e4eef0feed9b2b0978446bbf#diff-f142d024925e73816b0fabd620d2f71d瞭解一些粗略的細節。 從那開始,然後回報。我個人會考慮修改現有的上下文菜單,通過'IContextMenuHandler'添加,刪除命令。 – amaitland

+0

作爲參考,可能需要提供一個工作示例,您的問題很複雜,並且根據您的工作情況稍做調整。 MinimalExample項目可以用作參考點。 https://github.com/cefsharp/CefSharp.MinimalExample很明顯,從改變消息循環開始,看看你能得到多少。 – amaitland

+0

@amaitland:感謝您的反饋!使用'IContextMenuHandler'不是一個可行的解決方案,因爲上下文菜單使用了幾個自定義菜單項類(當應用程序是僅限Gdi時實現的),而且瀏覽器的上下文菜單看起來不同:我正在尋找一個無縫集成即用戶不應該注意到Gui實際上是Html。 – mike

回答

0

最後解決方案很簡單;如果添加了以下步驟,一切都可以正常工作:

在顯示上下文菜單之前,使用ChromiumWebBrowser禁用UserControl並將焦點設置爲擁有的窗體;是這樣的:

Private Sub showContextMenu(position As Point) 
    Me.ctrlCefBrowser.Enabled = False 
    Me.Focus() 

    myContextMenu.Show(position) 
End Sub 

那把焦點遠離ChromiumWebBrowser,給上下文菜單機會鍵盤輸入作出響應。而且,通過禁用控件,鼠標事件不再被「吞噬」,因此單擊瀏覽器區域會導致上下文菜單再次消失。

然後,最後,添加事件處理程序的上下文菜單來重新啓用瀏覽器控件:

Private Sub myContextMenu_Closed(sender As Object, e As ToolStripDropDownClosedEventArgs) Handles myContextMenu.Closed 
    Me.ctrlCefBrowser.Enabled = True 
    Me.ctrlCefBrowser.Focus() 
End Sub 

該訣竅對我來說,現在我有一個完全可定製的GDI上下文菜單我網頁瀏覽器控制:o)

注意: 使用其他菜單時也會出現類似的問題,例如在主菜單或工具欄中:單擊ChromiumWebBrowser控件將不會關閉菜單(因爲鼠標事件也被「吞噬」)。可以應用相同的解決方案:打開下拉菜單時取消激活(Enabled = False)Web瀏覽器控件。當它關閉時,重新激活它。對於我的菜單,我使用派生類(Inherits ToolStripMenuItem),它將監聽器添加到相應的事件中。這就以全局和簡單的方式處理了這個問題。

編輯: 上面提出的解決方案留下了點擊禁用的瀏覽器控件關閉菜單按預期關閉的問題,但遺失了,即瀏覽器無法處理它。我現在的解決方法是:

  • 不要禁用瀏覽器控件。
  • 使用菜單項和上下文菜單的開放事件,跟蹤哪個菜單當前打開。
  • 當瀏覽器收到焦點(通過攔截WndProc消息可獲得)關閉打開的菜單。

實現實際的解決方案引起了一些頭疼的細節,但也許這有助於沿無論如​​何有人...