c# - WebBrowser 控件未响应 InvokeMember ("click")

标签 c# javascript webbrowser-control

在我生命中度过了 5 天之后,我即将放弃这个,但在此之前我咨询过一次专家。

我有一个加载网页的 WebBrowser 控件,我以编程方式抓取其内容。在 IE(或任何其他浏览器)中单击页面中的特定菜单项会弹出文件打开对话框。但是使用 InvokeMember() 在 WebBrowser 控件中单击相同的按钮显然无论如何都不做任何事情。我已经经历了几个 SO 问题,例如 Setting Browser Features以确保我的控件的行为与 IE 完全一样,但这并没有成功。

我甚至检查了按钮在后台执行的实际 javascript 函数,并使用 HtmlDocument.InvokeScript() 手动调用它但不能这样做,因为底层函数采用 MouseEvent 的参数类型(实际上是点击事件),我不确定如何在 C# 中创建该对象。

另一种方法是将焦点设置到该特定按钮,然后尝试 SendKeys ,但这将不起作用,因为 WebBrowser 控件不可见。它只是一个内存中的实例。更具体地说,WebBrowser

编辑

应读者的要求,这是我用来查找元素的简单代码:

var MyButton = WB.Document.GetElementById("processfilelink");

processfilelink是一个 anchor 标记(<a href='#' ... >),我已经确认这个元素确实存在于文档的正文中。该网页使用 jQuery 的 delegate绑定(bind)此 anchor 的 click 的功能事件到目标函数。找到按钮后,我只需调用 InvokeMember()像这样:

MyButton.InvokeMember("click");

注意:我还在页面代码中看到了 mousedown、mouseup 和 focus 事件的绑定(bind)。我希望所有这些事件在调用 click 时自动触发,但为了确保我添加了 InvokeMember也呼吁这些事件。结果也好不到哪里去。

最佳答案

来自评论:

... load this page in full IE browser, use F12 Tools to debug it and execute button.click() in JavaScript console. Does it work as expected this way?

那么,您已经尝试过了,结果是:

... now that's interesting. It doesn't work! But clicking on the item by hand does work flawlessly. What's going on here?

我怀疑 as MyButton.InvokeMember("click") 不起作用。显然,该页面通过 onclick 事件以外的其他方式处理此点击。它很可能使用 onmousedownonmouseup 事件。研究页面的脚本逻辑以验证是否属于这种情况,使用 F12 调试器并放置一些断点。

已更新,如果发现该页面确实使用了 onmousedown/onmouseup,您需要将 WebBrowser 可见并通过发布 WM_LBUTTONDOWN 使其自动化:

using System;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace WindowsFormsApplication_22979038
{
    public partial class MainForm : Form
    {
        public MainForm()
        {
            InitializeComponent();
        }

        private void MainForm_Load(object sender, EventArgs e)
        {
            this.webBrowser.DocumentText = "<a id='goLink' href='javascript:alert(\"Hello!\"),undefined'>Go</a><script></script>";

            this.webBrowser.DocumentCompleted += webBrowser_DocumentCompleted;
        }

        void webBrowser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
        {
            var element = this.webBrowser.Document.GetElementById("goLink");
            element.Focus();
            var hwnd = GetFocus();
            if (!IsChild(this.webBrowser.Handle, hwnd))
                throw new ApplicationException("Unexpected focused window.");

            var rect = GetElementRect(element);
            IntPtr wParam = (IntPtr)MK_LBUTTON;
            IntPtr lParam = (IntPtr)(rect.Left | rect.Top << 16);
            PostMessage(hwnd, WM_LBUTTONDOWN, wParam, lParam);
            PostMessage(hwnd, WM_LBUTTONUP, wParam, lParam);
        }

        // get the element rect in window client area coordinates
        static Rectangle GetElementRect(HtmlElement element)
        {
            var rect = element.OffsetRectangle;
            int left = 0, top = 0;
            var parent = element;
            while (true)
            {
                parent = parent.OffsetParent;
                if (parent == null)
                    return new Rectangle(rect.X + left, rect.Y + top, rect.Width, rect.Height);
                var parentRect = parent.OffsetRectangle;
                left += parentRect.Left;
                top += parentRect.Top;
            }
        }

        // interop

        const int MK_LBUTTON = 0x0001;
        const int WM_LBUTTONDOWN = 0x0201;
        const int WM_LBUTTONUP = 0x0202;

        [StructLayout(LayoutKind.Sequential)]
        public struct POINT
        {
            public int x;
            public int y;
        }

        [DllImport("User32.dll", CharSet = CharSet.Auto)]
        static extern int PostMessage(IntPtr hwnd, int msg, IntPtr wparam, IntPtr lparam);

        [DllImport("User32.dll", ExactSpelling = true, CharSet = CharSet.Auto)]
        static extern IntPtr GetFocus();

        [DllImport("User32.dll", SetLastError = true, ExactSpelling = true, CharSet = CharSet.Auto)]
        static extern bool IsChild(IntPtr hWndParent, IntPtr hWnd);
    }
}

关于c# - WebBrowser 控件未响应 InvokeMember ("click"),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22979038/

相关文章:

c# - Image.FromFile 为无效图像格式抛出 OutOfMemoryException 是否有原因?

c# - 如何使用配置转换删除 ConnectionString

c# - 在运行时通过 foreach 命令向网格添加多个控件 (C# WPF)

c# - 从 Windows 窗体应用程序以横向模式打印 SSRS 报告

javascript - 用户输入作为 JavaScript 变量

javascript - 关闭菜单图标上和外部的汉堡菜单

javascript - 手动添加此打开的电子邮件共享对话框

c# - 在运行时使用 jQuery 将 JavaScript 注入(inject) WebBrowser

c# - 一般重新加载或刷新 WebBrowser 控件和窗体

c# - EventHandle.WaitOne + WebBrowser = 等待 DocumentComplete 时死锁