CefSharp 浏览器不会在 C# WinForms 应用程序中触发任何鼠标事件

Fli*_*int 1 c# handler winforms mousedown cefsharp

所以我的最终目标是检测用户何时在网页上按下鼠标左键(任何元素,如按钮、图像等)。有了这个,我将运行一些 javascript 来根据用户点击的位置获取我需要的正确的 html 数据。

不用再进一步,我已经陷入了第一部分,我的浏览器控件似乎没有触发任何与鼠标相关的事件。然而,它似乎确实提供了像 MouseDown、MouseEnter、MouseClick 等处理程序,但似乎没有触发它们中的任何一个。

我尝试使用文本框控件和按钮设置一个简单的 WinForms 测试项目。浏览器是手动添加的,如下所示:

using CefSharp;
using CefSharp.WinForms;
using System;
using System.Drawing;
using System.Windows.Forms;

namespace myProject
{
    public partial class Form1 : Form
    {
        public ChromiumWebBrowser browser;
        private string myUrl = "https://www.google.com/";
        
        public Form1()
        {
            InitializeComponent();
            InitializeChromium();

            browser.MouseDown += ChromeBrowser_MouseDown;
        }

        public void InitializeChromium()
        {
            browser = new ChromiumWebBrowser(myUrl);

            browser.Location = new Point(26, 59);
            browser.Size = new Size(988,566);
            browser.Dock = DockStyle.None;
            this.Controls.Add(browser);

        }

        private void ChromeBrowser_MouseDown(object sender, MouseEventArgs e)
        {
            //This handler never gets fired!!!

            if (e.Button == MouseButtons.Left)
            {
                //get value from html element
            }
        }

        private void button1_Click(object sender, EventArgs e)
        {
            browser.Load(addressBar.Text);
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            Cef.Shutdown();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我尝试浏览很多网站,包括有关Handlers 的官方文档,但似乎无法弄清楚我是否必须做更复杂的事情来监听鼠标事件并对鼠标事件采取行动,或者我应该能够实现它就像任何其他事件一样。

有人可以帮我修复 MouseDown 事件处理程序吗?

Fli*_*int 10

花了一段时间,但终于抽出时间来发布我自己的答案!希望其他人会发现这很有用。

感谢 @amaitland 在评论中指出 CefSharp 浏览器不会触发任何键盘或鼠标事件,也感谢您发布此链接,最终使我找到了答案。

解决方法是注入一些 Javascript(当浏览器加载完框架时),然后该 Javascript 将侦听并检测任何鼠标/键盘事件。发生火灾时,您的 Javascript 会调用CefSharp.PostMessage(data);它在自己的线程上通知 CefSharp 浏览器并返回任何有用的内容data(取决于您的脚本)。

初始化事件处理程序

browser.JavascriptMessageReceived += Browser_JavascriptMessageReceived;&添加browser.FrameLoadEnd += Browser_FrameLoadEnd;到初始化中将激活必要的挂钩,如下所示(按照我原来的示例):

public void InitializeChromium()
        {
            browser = new ChromiumWebBrowser(myUrl);

            browser.Location = new Point(26, 59);
            browser.Size = new Size(988,566);
            browser.Dock = DockStyle.None;
            this.Controls.Add(browser);

            browser.JavascriptMessageReceived += Browser_JavascriptMessageReceived;
            browser.FrameLoadEnd += Browser_FrameLoadEnd;
        }
Run Code Online (Sandbox Code Playgroud)

实现事件处理程序

现在剩下要做的就是通过添加以下内容来实现这些事件处理程序:

        private void Browser_FrameLoadEnd(object sender, FrameLoadEndEventArgs e)
        {
            if (e.Frame.IsMain)
            {
                browser.ExecuteScriptAsync(@"
                    document.addEventListener('click', function(e) {
                        var parent = e.target.parentElement;

                        // run some validation with if(){..}
                        // some more javascript

                        CefSharp.PostMessage(parent.outerHTML);
                    }, false);
                ");
            }
        }

        private void Browser_JavascriptMessageReceived(object sender, JavascriptMessageReceivedEventArgs e)
        {
            if (e.Message != null)
            {
                // Extract data from e.Message.toString() and use delegates/callbacks/Invokes 
                // to reference the main UI thread for updating the necessary controls.
            }
        }

Run Code Online (Sandbox Code Playgroud)

加载网页/框架后,Browser_FrameLoadEnd处理程序将运行,然后注入您的自定义 Javascript。仅当从 Javascript 调用Browser_JavascriptMessageReceived时,才会触发该处理程序。CefSharp.PostMessage(data);

另外,我没有按照此链接的document.body.onmouseup建议在 javascript 中使用,而是选择使用 for来获取目标/点击的元素。就我而言,这对于获取属于该单击元素的parentElement 的必要数据至关重要。(请记住,我的实际案例适用于与谷歌不同的网站,如我的示例所示document.addEventListener('click', function(e)

完整示例代码

完整的扩展示例代码如下所示:

using CefSharp;
using CefSharp.WinForms;
using System;
using System.Drawing;
using System.Windows.Forms;

namespace myProject
{
    public partial class Form1 : Form
    {
        public ChromiumWebBrowser browser;
        private string myUrl = "https://www.google.com/";
        
        public Form1()
        {
            InitializeComponent();
            InitializeChromium();
        }

        public void InitializeChromium()
        {
            browser = new ChromiumWebBrowser(myUrl);

            browser.Location = new Point(26, 59);
            browser.Size = new Size(988,566);
            browser.Dock = DockStyle.None;
            this.Controls.Add(browser);

            browser.JavascriptMessageReceived += Browser_JavascriptMessageReceived;
            browser.FrameLoadEnd += Browser_FrameLoadEnd;
        }

        private void Browser_FrameLoadEnd(object sender, FrameLoadEndEventArgs e)
        {
            if (e.Frame.IsMain)
            {
                browser.ExecuteScriptAsync(@"
                    document.addEventListener('click', function(e) {
                        var parent = e.target.parentElement;

                        // run some validation with if(){..}
                        // some more javascript

                        CefSharp.PostMessage(parent.outerHTML);
                    }, false);
                ");
            }
        }

        private void Browser_JavascriptMessageReceived(object sender, JavascriptMessageReceivedEventArgs e)
        {
            if (e.Message != null)
            {
                // Extract data from e.Message.toString() and use delegates/callbacks/Invokes 
                // to reference the main UI thread for updating the necessary controls.
            }
        }

        private void button1_Click(object sender, EventArgs e)
        {
            browser.Load(addressBar.Text);
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            Cef.Shutdown();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)