CefSharp Browser schluckt Key-Events

  • VB.NET

Es gibt 7 Antworten in diesem Thema. Der letzte Beitrag () ist von RodFromGermany.

    CefSharp Browser schluckt Key-Events

    Hallo zusammen,

    ich brauche eure Hilfe, ich komme nicht weiter.
    In meiner Windows-Anwendung habe ich den CefSharp integriert:

    Quellcode

    1. Dim settings As New CefSettings()
    2. With settings
    3. .CefCommandLineArgs.Add("force-device-scale-factor", "0.8")
    4. End With
    5. CefSharp.Cef.Initialize(settings)
    6. InitializeComponent()


    KeyPreview in meiner Form ist aktiv, KeyUp funktioniert prächtig.

    Im Browser geht dann gar nichts mehr, er verschluckt alles, keine Key-Ereignisse kommen in der Form an.
    Ich habe auch schon versucht dem Browser ein Handle hinzuzufügen, geht auch nicht.

    Google sagt mir dass ich den "IKeyboardHandler" implementieren sollte. Im CefSharp Projektordner finde ich auch eine "IKeyboardHandler.cs".
    Wie bitte kann ich das implementieren???

    Aus den Ergebnissen für C# werde ich nicht schlau, wie kann ich das in VB realisieren?

    Ich möchte einfach Hotkeys erstellen, die ich global in meinem Programm nutzen kann. Egal wo der Focus liegt, ob auf dem Browser oder sonstwo, er muss auf die Keys reagieren.


    Danke und Grüße,
    Stefan
    Brauch' ich die?
    @Hanuta Willkommen im Forum. :thumbup:
    Was muss ich tun, um das nachzuvollziehen?
    Informationen, Versionen, Installationen, Code ...
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Hi Rod,
    danke!

    Ich arbeite mit VisualStudio Community 2017, CefSharp.Winforms V.69.0.0

    In Form1_Load existiert folgender Code:

    VB.NET-Quellcode

    1. If Not CefSharp.Cef.IsInitialized Then
    2. Dim settings As New CefSettings()
    3. With settings
    4. .CachePath = "C:\cache\1"
    5. .CefCommandLineArgs.Add("force-device-scale-factor", "0.8")
    6. End With
    7. CefSharp.Cef.Initialize(settings)
    8. InitializeComponent()
    9. End If


    In einem TabControl werden bei Bedarf mehrere Browserinstanzen geladen.
    Dazu erstellen ich ein Panel mit einigen Comboboxen und dem Browser. Dieses Panel füge ich einem Tab hinzu:

    VB.NET-Quellcode

    1. Dim Browser As New ChromiumWebBrowser("https://...")
    2. With Browser
    3. .RequestContext = New RequestContext()
    4. .Name = "Browser_" & id
    5. End With
    6. AddHandler Browser.KeyUp, AddressOf Form1_KeyPress
    7. Dim NeuesPan As New Panel()
    8. With NeuesPan
    9. .Width = 820
    10. .Height = 680
    11. .Location = New Point(0, 0)
    12. .Controls.Add(Pan_FarmControl) ' Das später in der Function gebaute Control-Panel
    13. .Controls.Add(Browser)
    14. End With
    15. Dim NeuerTab As New TabPage()
    16. With NeuerTab
    17. .Text = AnzeigeName
    18. .Name = "tab_" & id
    19. .Controls.Add(NeuesPan)
    20. End With
    21. AddHandler NeuerTab.KeyUp, AddressOf Form1_KeyPress
    22. Me.Tab_Browser.TabPages.Add(NeuerTab)


    Die beiden Addhandler (6te und drittletzte Zeile) sollen dann folgende Sub ansprechen und später dort weiter verarbeitet werden :

    VB.NET-Quellcode

    1. Sub Form1_KeyPress(ByVal sender As Object, ByVal e As KeyEventArgs) Handles Me.KeyUp, Tab_Browser.KeyUp
    2. Lbl_Status.Text = e.KeyData.ToString
    3. Lbl_Status.Refresh()
    4. End Sub



    So, das war hoffentlich alles wichtige, gäbe es sonst noch etwas wichtiges zu wissen?


    Doch, ich habe da einen Ansatz gefunden, komme halt nur mit der Konvertierung der C#-Beispiele nicht klar. Nach jetzt 3 Tagen googelei erhoffe ich mir, dass mir jemand - wenn irgend möglich - einen leicht verdaulichen und verständlichen Code geben könnte.

    CEF is run in it's own message loop, so the standard events don't work.

    The first an easiest option is to implement IKeyboardHandler, you can check the CefSharp source for a more detailed example (there's one that forwards messages to the parent window if required).


    Grüße,
    Stefan
    Brauch' ich die?
    @Hanuta NeuerTab.KeyUp dürfte nicht stattfinden.
    Probierma, statt Deines CefSharp-Controls ein schnödes Panel auf die GUI zu ziehen.
    Dann neben Deinem CefSharp-Control einen Button zu platzieren.
    Wenn das funktioniert, sind es ggf. die falschen Events.
    Das IKeyboardHandler-Interface dürfte etwas tricky werden.
    Das kannst Du so implementieren:

    VB.NET-Quellcode

    1. Public Clas FormX
    2. Implements IKeyboardHandler
    3. ' ...
    4. End Class
    Dann klickst Du auf IKeyboardHandler und lässt das Studio das Interface implementieren.
    Was dann in die Prozeduren reinzuschreiben ist, weiß ich jetzt nicht, das sind aber nur zwei Methoden..
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Hi Rod,
    danke erstmal, einen klitzekleinen Schritt bin ich schon mal weiter.

    Als ich Dein "implements" einfügte, schluckte es mein VS anstandslos, ich konnte nichtmal darauf klicken und schauen was dann passiert.
    Allerdings bin ich dann auch schon am Ende, kannst Du mir erklären wie ich das folgende benutzen kann, also wie diesen Walk weitergehen kann?

    cefsharp.github.io/api/51.0.0/…Handler_OnPreKeyEvent.htm

    Sorry für meine vielleicht vollkommende Noob-Fragestellung, aber da bin ich mit meinem Halbwissen echt am Ende...

    Ach so, ja - Dein Gedanke mit dem Panel funktioniert prächtig, das ganze knickt ein sobald der Browser mit ins Spiel kommt.
    Brauch' ich die?
    @Hanuta Keine Ahnung.
    Da musst Du mal intensiv Frau Google befragen und die Homepage des Herstellers flöhen.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Hallo nochmal ;)

    Ich habe etwas übersehen, Dein "Implement" hat mir zwei Functions beschert:

    VB.NET-Quellcode

    1. Public Function OnPreKeyEvent(chromiumWebBrowser As IWebBrowser, browser As IBrowser, type As KeyType, windowsKeyCode As Integer, nativeKeyCode As Integer, modifiers As CefEventFlags, isSystemKey As Boolean, ByRef isKeyboardShortcut As Boolean) As Boolean Implements IKeyboardHandler.OnPreKeyEvent
    2. Throw New NotImplementedException()
    3. End Function
    4. Public Function OnKeyEvent(chromiumWebBrowser As IWebBrowser, browser As IBrowser, type As KeyType, windowsKeyCode As Integer, nativeKeyCode As Integer, modifiers As CefEventFlags, isSystemKey As Boolean) As Boolean Implements IKeyboardHandler.OnKeyEvent
    5. Throw New NotImplementedException()
    6. End Function


    Hilft Dir das vielleicht weiter? Der Sinn der Functions entzieht sich mir...
    Und da hätte ich noch ein kleines Codemonster gefunden, leider in C# :(

    C#-Quellcode

    1. namespace CefSharp.WinForms.Example.Handlers
    2. {
    3. public class KeyboardHandler : IKeyboardHandler
    4. {
    5. /// <inheritdoc/>>
    6. public bool OnPreKeyEvent(IWebBrowser chromiumWebBrowser, IBrowser browser, KeyType type, int windowsKeyCode, int nativeKeyCode, CefEventFlags modifiers, bool isSystemKey, ref bool isKeyboardShortcut)
    7. {
    8. const int WM_SYSKEYDOWN = 0x104;
    9. const int WM_KEYDOWN = 0x100;
    10. const int WM_KEYUP = 0x101;
    11. const int WM_SYSKEYUP = 0x105;
    12. const int WM_CHAR = 0x102;
    13. const int WM_SYSCHAR = 0x106;
    14. const int VK_TAB = 0x9;
    15. const int VK_LEFT = 0x25;
    16. const int VK_UP = 0x26;
    17. const int VK_RIGHT = 0x27;
    18. const int VK_DOWN = 0x28;
    19. isKeyboardShortcut = false;
    20. // Don't deal with TABs by default:
    21. // TODO: Are there any additional ones we need to be careful of?
    22. // i.e. Escape, Return, etc...?
    23. if (windowsKeyCode == VK_TAB || windowsKeyCode == VK_LEFT || windowsKeyCode == VK_UP || windowsKeyCode == VK_DOWN || windowsKeyCode == VK_RIGHT)
    24. {
    25. return false;
    26. }
    27. var result = false;
    28. var control = chromiumWebBrowser as Control;
    29. var msgType = 0;
    30. switch (type)
    31. {
    32. case KeyType.RawKeyDown:
    33. if (isSystemKey)
    34. {
    35. msgType = WM_SYSKEYDOWN;
    36. }
    37. else
    38. {
    39. msgType = WM_KEYDOWN;
    40. }
    41. break;
    42. case KeyType.KeyUp:
    43. if (isSystemKey)
    44. {
    45. msgType = WM_SYSKEYUP;
    46. }
    47. else
    48. {
    49. msgType = WM_KEYUP;
    50. }
    51. break;
    52. case KeyType.Char:
    53. if (isSystemKey)
    54. {
    55. msgType = WM_SYSCHAR;
    56. }
    57. else
    58. {
    59. msgType = WM_CHAR;
    60. }
    61. break;
    62. default:
    63. Trace.Assert(false);
    64. break;
    65. }
    66. // We have to adapt from CEF's UI thread message loop to our fronting WinForm control here.
    67. // So, we have to make some calls that Application.Run usually ends up handling for us:
    68. var state = PreProcessControlState.MessageNotNeeded;
    69. // We can't use BeginInvoke here, because we need the results for the return value
    70. // and isKeyboardShortcut. In theory this shouldn't deadlock, because
    71. // atm this is the only synchronous operation between the two threads.
    72. control.Invoke(new Action(() =>
    73. {
    74. var msg = new Message
    75. {
    76. HWnd = control.Handle,
    77. Msg = msgType,
    78. WParam = new IntPtr(windowsKeyCode),
    79. LParam = new IntPtr(nativeKeyCode)
    80. };
    81. // First comes Application.AddMessageFilter related processing:
    82. // 99.9% of the time in WinForms this doesn't do anything interesting.
    83. var processed = Application.FilterMessage(ref msg);
    84. if (processed)
    85. {
    86. state = PreProcessControlState.MessageProcessed;
    87. }
    88. else
    89. {
    90. // Next we see if our control (or one of its parents)
    91. // wants first crack at the message via several possible Control methods.
    92. // This includes things like Mnemonics/Accelerators/Menu Shortcuts/etc...
    93. state = control.PreProcessControlMessage(ref msg);
    94. }
    95. }));
    96. if (state == PreProcessControlState.MessageNeeded)
    97. {
    98. // TODO: Determine how to track MessageNeeded for OnKeyEvent.
    99. isKeyboardShortcut = true;
    100. }
    101. else if (state == PreProcessControlState.MessageProcessed)
    102. {
    103. // Most of the interesting cases get processed by PreProcessControlMessage.
    104. result = true;
    105. }
    106. Debug.WriteLine("OnPreKeyEvent: KeyType: {0} 0x{1:X} Modifiers: {2}", type, windowsKeyCode, modifiers);
    107. Debug.WriteLine("OnPreKeyEvent PreProcessControlState: {0}", state);
    108. return result;
    109. }
    110. /// <inheritdoc/>>
    111. public bool OnKeyEvent(IWebBrowser chromiumWebBrowser, IBrowser browser, KeyType type, int windowsKeyCode, int nativeKeyCode, CefEventFlags modifiers, bool isSystemKey)
    112. {
    113. var result = false;
    114. Debug.WriteLine("OnKeyEvent: KeyType: {0} 0x{1:X} Modifiers: {2}", type, windowsKeyCode, modifiers);
    115. // TODO: Handle MessageNeeded cases here somehow.
    116. return result;
    117. }
    118. }
    119. }
    Brauch' ich die?

    Hanuta schrieb:

    Dein "Implement" hat mir zwei Functions beschert:
    Genau die meinte ich.
    Das Throw New NotImplementedException() musst Du durch Deinen eigenen Code ersetzen.
    Was da reingehört - keine Ahnung, musste mal Frau Google befragen.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!