Question WebBrowser Control disables the Form when it navigates while not visible

VBobCat

Well-known member
Joined
Sep 6, 2011
Messages
137
Location
S?o Paulo, Brazil
Programming Experience
3-5
Hello friends,

My application has a single Form. It always shows in full dock one of a set of several UserControls. They alternate as user demands different functions from the application, so that the Form is one along all runtime and it remains the same. Note: this is the desired design. To achieve that, just one usercontrol is added each time, and shows in a TableLayoutPanel named "Grid" set in a "Parent" UserControl named "UcNav" (because there are some controls that remain with the form). When they need to change, the exiting UC is removed from the .Controls collection and the entering UC is added to the .Controls collection. All that is done with this piece of code:
Public Class UcNav
    Private WithEvents cOn As UserControl
    Private Titles As New Dictionary(Of UserControl, String)
    Private Actions As New Dictionary(Of UserControl, Action(Of DialogResult))
    Public Shared Function [Get](ByVal c As UserControl) As UcNav
        If c IsNot Nothing AndAlso c.Parent IsNot Nothing AndAlso c.Parent.Parent IsNot Nothing Then
            Return TryCast(c.Parent.Parent, UcNav)
        Else
            Return Nothing
        End If
    End Function
    Public Sub New(ByVal c As UserControl, t As String, Optional ByVal a As Action(Of DialogResult) = Nothing)
        InitializeComponent()
        Dock = DockStyle.Fill
        Add(c, t, a)
    End Sub
    Public Property ControlOn As UserControl
        Get
            Return cOn
        End Get
        Private Set(value As UserControl)
            If cOn IsNot Nothing Then
                Grid.Controls.Remove(cOn)
            End If
            If value IsNot Nothing Then
                AdjustSizes(value)
                Grid.Controls.Add(value, 0, 1)
                value.Dock = DockStyle.Fill
                cOn = value
            End If
            LabelTitles.Text = String.Concat(From kvp In Titles Select "?" & kvp.Value & "  ").Trim
            ButtonRewind.Visible = Titles.Count > 1
        End Set
    End Property
    Public Sub Add(ByVal c As UserControl, t As String, Optional ByVal a As Action(Of DialogResult) = Nothing)
        Titles.Add(c, t)
        Actions.Add(c, a)
        ControlOn = c
    End Sub
    Public Sub Rewind(Optional ByVal dr As DialogResult = DialogResult.None)
        If Titles.Count > 1 Then
            Dim a = Actions(cOn)
            Titles.Remove(cOn)
            Actions.Remove(cOn)
            ControlOn = Titles.Last.Key
            If a IsNot Nothing Then a.Invoke(dr)
        End If
    End Sub
    Private Sub ButtonRewind_Click(sender As Object, e As EventArgs) Handles ButtonRewind.Click
        Dim cancel = False, cancelFunc = TryCast(cOn.Tag, Func(Of Boolean))
        If cancelFunc IsNot Nothing Then cancel = cancelFunc.Invoke
        If Not cancel Then Rewind()
    End Sub
    Private Sub AdjustSizes(ByVal c As Control)
        Dim f = FindForm()
        If f IsNot Nothing Then
            Dim cSize = New Size(Grid.GetColumnWidths(0), Grid.GetRowHeights(1))
            Dim fSize = f.Size - cSize
            Dim nSize = New Size(fSize.Width + c.MinimumSize.Width, fSize.Height + c.MinimumSize.Height)
            Dim xSize = New Size(fSize.Width + c.MaximumSize.Width, fSize.Height + c.MaximumSize.Height)
            If xSize.Width = fSize.Width Then xSize.Width = 0
            If xSize.Height = fSize.Height Then xSize.Height = 0
            f.MinimumSize = New Size
            f.MaximumSize = New Size
            f.MinimumSize = nSize
            f.MaximumSize = xSize
        End If
    End Sub
End Class


Some of these UserControls, however, do something even when they are not added to the form, therefore invisible. That causes no problem except that annoyng behavior: when a WebBrowser navigates, if its parent UserControl is not the one which is showing at the form, it makes the Form to deactivate. The intriguing thing is that I catched the "Deactivate" event from the form, and the Form.ActiveForm shared property keeps pointing to the right Form, but it gets unfocused (and there is no clue about where has the focus gone to).

This post describes a similar problem, but that solution didn't worked for me.

Do you guys could help me sort out (and prevent) this focus loss?

Thank you very much!
 
There are similar threads, like "webbrowser steals focus" (btw it is the loaded web page that in some cases causes it, not the browser), and one suggestion that I found was to set browsers parent Enabled=False before navigate. I tested this with a webbrowser on a usercontrol that was not added to the form. When enabled it stole focus, when not enabled it didn't.
 
Thanks a lot, JohnH. I made a Sub to handle ParentChanged events of both UserControl and WebBrowser (the latter in order to run upon UserControl's initialization). It tests whether WebBroser.FindForm Is Nothing and sets UserControl.Enabled property accordingly. It solved the problem!
 
Last edited:
Back
Top