Webbrowser窃取焦点

6

我正在使用Winforms应用程序(C#)中的Webbrowser控件。当它执行自动化操作时,我的焦点控件从我正在使用的窗口中消失了。Web浏览器的表单也不会显示出来,我只是失去了对控件的焦点。现在我写这条消息的时候,我不得不一遍又一遍地点击文本框...

如何禁用Webbrowser中的此类行为?

我像这样创建一个不可见的Webbrowser:

var br = new WebBrowser();
br.Visible = false;
br.ScriptErrorsSuppressed = true;

请给予指导。

2
你发布的代码绝对与你遇到的问题毫无关系。如果你确定这个问题只在运行你的程序时出现,那么你需要发布你程序的其他部分的代码。 - Trevor Elliott
可能是重复的问题:如何防止 WebBrowser 控件窃取焦点?(https://dev59.com/zXI_5IYBdhLWcg3wBuNs) - Sheng Jiang 蒋晟
7个回答

16

我曾经也遇到过同样的问题:

一旦加载URL,Webbrowser控件就会从应用程序中抢占焦点。

这个方法适用于我:

  1. 在调用 Webbrowser.Navigate() 方法之前,将Webbrowser的父控件设置为 Enabled = false
  2. 在Webbrowser的 DocumentCompleted 事件中,将Webbrowser的父控件重新设置为 Enabled = true

你不能直接在Webbrowser上执行此操作,因为 WebBrowserBase.Enabled 不受支持。

如果有用,请告诉我。


可以使用Form.Activate()和Control.Focus()方法来重新获取焦点。 - Ravi M Patel
Ravi的解决方案更可靠。 - Nick Allan

2

2
我猜测在调用Navigate(或HtmlElement的Click方法导致导航)加载页面后,WebBrowser会获得焦点。可以在WebBrowser的DocumentComplete事件处理程序中将焦点返回到窗口上的控件(TextBox),但这很困难:
1. 何时确定哪个控件最初拥有焦点?在调用Navigate之前?这是不够的,因为用户可以在调用Navigate后但在处理DocumentComplete之前移动到另一个控件。 2. 据我所知,将焦点设置为TextBox将选择其所有内容,因此您需要将光标放回原始位置。但是,您什么时候存储原始位置?同样的问题。 3. 在单个Navigate(或Click)后可能会有多个DocumentComplete事件。
一个可能的解决方案是为您隐藏的WebBrowser创建一个单独的应用程序。这第二个应用程序将是不可见的,并且可以使用某些进程间通信(IPC)技术与原始GUI应用程序通信。由于在这种情况下WebBrowser将在不同的进程中运行,因此您有更好的机会不失去焦点并打扰用户。

不幸的是,即使在另一个进程中运行,Web控件仍然会窃取焦点。 - Tom

2

这是一个非常复杂的问题,需要由微软进行修订。一个应用程序突然抢占了焦点是不合逻辑的,但这取决于网站正在做什么。我不得不使用 CBT 过滤器来解决问题,详情请参见 http://msdn.microsoft.com/en-us/magazine/cc188966.aspx,并过滤掉不需要的 HCBT_ACTIVATE 和 HCBT_SETFOCUS(返回 1)。您可以使用 GetWindowClass(wParam) 来查看发生了什么。

即使以上方法并不能完全解决问题,应用程序窗口仍会暂时跳到前台,因此通过在当前前景窗口上使用 SetWindowPos HWND_TOPMOST 和 HWND_NOTOPMOST 进行了处理。HCBT_SETFOCUS 会被触发 2 或 3 次,因此在第一次设置 HWND_TOPMOST,在最后一次设置 HWND_NOTOPMOST。计算 classname == "Internet Explorer_Server" 的数量,应该是 2(或者可能取决于网站?),另一个是 "Shell Embedding",但不总是出现。希望能有所帮助。


2
我看了这个问题的所有其他答案,但它们对我都不起作用。但是我看到了一个有关设置Browser.Parent.Enabled = false;的答案,我试了一下,但出现了错误,所以我尝试了另一种方法,这只是我的想法。 Browser.Parent = new Control(); Browser.Parent.Enabled = false; 现在问题完全解决了,它不再夺取焦点。我使用Web浏览器类作为变量,它不在我的表单上。好吧,这对我有效,请尝试一下,这似乎是一个100%的解决方案。

1
Most of the methods won't work for me on more than one web browser. This method is work with any amount of web browsers;

1. Put web browser into a panel and set panel enabled to false, then navigate;

    webBrowser.Parent = panelBottom;
    panelWebBrowser.Enabled = false;
    webBrowser.Navigate("http://www.google.com");

2. Define a navigated event to web browser and delay panels enabling for a second;

    private void webBrowser_Navigated(object sender, WebBrowserNavigatedEventArgs e)
    {
        System.Threading.Timer timer = null;
        timer = new System.Threading.Timer((obj) =>
        {
            panelWebBrowser.Enabled = true;
            timer.Dispose();
        },null, 1000, Timeout.Infinite);
    }

0

我发送焦点回表单的解决方案:

        Private Sub Web_DocumentCompleted(sender As Object, e As WebBrowserDocumentCompletedEventArgs) Handles Web.DocumentCompleted
    If Me.Visible = False Then
        For Each f As Form In My.Application.OpenForms
            If TypeOf f Is frmLogin Then
                Dim fl As frmLogin = DirectCast(f, frmLogin)
                If fl.Visible = True Then
                    fl.Focus()
                    Exit For
                End If
            End If
        Next
    End If
End Sub

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接