【问题标题】:WebBrowser control not responding to InvokeMember("click")WebBrowser 控件不响应 InvokeMember("click")
【发布时间】:2014-04-11 12:56:20
【问题描述】:

在我的生命中度过了 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 是一个锚标记 (<a href='#' ... >),我已经确认该元素确实存在于文档正文中。网页使用 jQuery 的delegate 特性将此锚点的click 事件绑定到目标函数。找到按钮后,我只需像这样调用InvokeMember()

MyButton.InvokeMember("click");

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

【问题讨论】:

  • 对于最接近的投票者,如果这是题外话,我想知道世界上什么才是题外话。
  • 抱歉...分心了一秒钟...请提供您用于查找元素的代码 - 以及您实际找到的元素。请注意,并非所有内容都是“可点击的”......否则无法提出任何建议。当您显示浏览器时,代码是否也有效?
  • @AlexeiLevenkov:谢谢。请查看我的编辑。
  • "A" 应该收到点击...如果您通过InvokeScript 将您自己的点击处理程序添加到该元素,它会被调用吗?您是否尝试过 InvokeScript 之类的 $("#InvokeScript").trigger("click")(假设您已经在页面上安装了 jQuery)?我相信,根据您如何使“WebBrowser 控件不可见”,它可能不会触发所有加载事件或合理地布置控件,从而使元素隐藏 - 检查文档的大小/状态...如果您可能需要使用 PhantomJS想要无头浏览器。
  • @Noseratio:哇,这很有趣。它不起作用!但是手动单击该项目确实可以完美地工作。这是怎么回事?

标签: c# javascript webbrowser-control


【解决方案1】:

来自cmets:

... 在完整的 IE 浏览器中加载此页面,使用 F12 工具调试它并 在 JavaScript 控制台中执行 button.click()。是否按预期工作 这边?

所以,你已经尝试过了,结果是:

...现在这很有趣。它不起作用!但是点击项目 手工确实完美无缺。这是怎么回事?

我怀疑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);
    }
}

【讨论】:

    猜你喜欢
    • 2013-04-03
    • 2011-02-08
    • 1970-01-01
    • 2013-10-03
    • 2014-10-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多