Focus being Stolen By Control...

JaedenRuiner

Well-known member
Joined
Aug 13, 2007
Messages
340
Programming Experience
10+
In the process of setting up my databindings, I've discovered, quite annoyingly, that the databindings can't always be perfect. Case and point, the WebBrowser component. I tried to bind the DocumentText property to a Column in my database and it didn't work at all. (quite depressing).

So instead, since i'm already doing some crazy bindingsource manipulation in my form already, i figured i should just put my updates in there, and for your benefit here is the code of my particular situation...
VB.NET:
        Dim bind As BindingSource = sender
         If TypeOf bind.DataSource Is BindingSource Then bind = bind.DataSource
         If bind IsNot bind_Tbls Then
            bind.Position = bind_Tbls.Position
            If bind Is bind_MailBox Then 'for the mailbox bind we have 
                       'to some tricky things with the WebBrowser Component
               If (bind_Tbls.Position > -1) Then 'if the position is a valid record
                  If BodyBrowser.Document Is Nothing Then BodyBrowser.DocumentText = "<html></html>"
                  Dim doc As HtmlDocument = _
                      BodyBrowser.Document.OpenNew(True) 'create the new browser document
                  doc.Write(bind(bind.Position)("Body")) 'write the email body text to the html document
                  SentDateTimePicker.Visible = (Not DirectCast(bind_Tbls.Current, _ 
                                        RexamShipDataSet.tbl_MailBoxRow).IsSentNull)
               ElseIf bind_Tbls.Position = -1 Then
                  BodyBrowser.Document.OpenNew(True) 'else clear the browser document, 
                         ' to keep the form blank on no entries
               End If
            End If
         End If

Now, have no doubt this works perfectly every time, without any errors, But...
The damn Browser component keeps stealing focus from me. I'm scrolling my datagridview, which is bound to bind_Tbls bindingsource, and the position changes. That calls the _positionchanged() event above for the bindingsource, which updates the "embedded" bindingsource, and then checks if the "embedded" source is for the Mailbox. If it is, I open a new document in the browser and the write the html from the current row's body column into the document and all is well, but it appears that when I write into the document, it steals the focus. Is there a way to prevent this, or can anyone think of a better way to display a Database/Table/Column string text of HTML, that wouldn't involve the repetitive re-creating of the browser document.

Personally, I would like a component that just displays HTML without all the over head of web-interfacing that the WebBrowser Component comes with, and I know I could use the ActiveControl.Select method in that event section there, i'm just wondering if there is a better way to come about this that I haven't thought of yet (or are completely unaware of)

Thanks
 
Crazy stuff like this is why I don't bind any controls to a BindingManager. I know it's more work, but by not using a BindingManager I actually get the app working correctly in the same amount of time and with less irritated customer's calls.
 
But i thought I explained, i'm not using the binding manager for this. For the TextBoxes and other Edit fields it works just fine for my purposes. It's only for the WebBrowser component. THe issue, imho, is not the BindingSource, or any of that, but the WebBrowser/HTMLDocument component. Why oh why did Microsoft only release the HTMLDOcument class as a subset to the WebBrowser? Html DOM should be parsed from direct text into a HTMLDocument object with no need of a URL / Web capable component wrapping it up.

But because they didn't do it smartly like that, I have to use the WebBrowser component to display my Html Formatted Email Body. And when I request that the WebBrowser display it, the Focus is stolen from my DataGridView. The issue is the Browser component not the binding source.
thanks
 
So after setting all the stuff up in the web browser can't you have your code set focus back to the datagrid? It's the only thing I can suggest since the web browser control has to be used.
 
Actually, I did try that, but there were two problems.

First: I didn't work. I put the code in the bindingsource::positionChanged() event handler where I'm filling the webbrowser component. When I stepped through the function (with a breakpoint) the DGV was re-selected, but when i just ran it, it never regained the focus. It's like that bastard creation of Microsoft's, that when you load an application and then click away to something else, that application thinks it has the right to switch back to itself when its done loading. Some do it, some don't, I personally find that behavior offensive and aggravating, and it appears the WebBrowser component has a little something of that in itself, change focus "once" the document loads. I can trap that though so I may be able to work around.

Second:
I'd like to use the currently selected control, but VB again has a minor flaw with guarded comparison to other languages, and that is that Form.ActiveControl (similar to Form.KeyPreview) do not precisely work. The KeyPreview has never "Previewed" any key presses going to child controls, which is how it is handled in other languages (Delphi to be precise, as well as C++), and similarly the Form.ActiveControl is a SplitContainer, which means I need to recurse through the Active Controls until i reach:
TypeOf ActiveControl is :
  • TextBox
  • ComboBox
  • DataGridView
  • etc
and that is just a pain in my foot.

Thanks
 
I think you'll struggle to edit the DocumentText in this way; i've never achieved it and genuienly, the easiest way I've found to make a WebBrowser control load a block of HTML is to write it to disk, then tell the browser to navigate to it..

There are certain stages of a WebBrowser life where you cannot edit the document on show by tweaking its DocumentText property

And when I request that the WebBrowser display it, the Focus is stolen from my DataGridView. The issue is the Browser component not the binding source.
thanks

When the documentcomplete event fires, set the focus back?
 
I think you'll struggle to edit the DocumentText in this way; i've never achieved it and genuienly, the easiest way I've found to make a WebBrowser control load a block of HTML is to write it to disk, then tell the browser to navigate to it..

There are certain stages of a WebBrowser life where you cannot edit the document on show by tweaking its DocumentText property

Yea, I found that out when I tried the databinding. The write to disk works but a rather effective memory methodology is the:
VB.NET:
  WebBrowser.Document.OpenNew()
  WebBrowser.Document.Write("blah")
By calling the OpenNew()/Write() sequence it always reloads the fresh page from a direct HTML string, so no need to muck up the HD by creating/using/loading/deleting temp files every time the user changes the current record in the DB.

When the documentcomplete event fires, set the focus back?
I was thinking about that, but again it is still a pain, because there is no global variable or access point for:
"Give me the Object that current has the focus."
Activecontrol does not work. Example:

Form
  • TabControl
    • SplitContainer1
      • splitcontainer2
        • tabcontrol
          • TextBoxes, ComboBoxes, etc
          • splitcontainer3
          • SplitContainer4
            • DGV
            • DGV
      • DGV

    so by looking at my form the Form.ActiveControl could be pointing to any one of the splitcontainers and NOT the active TextBox, or DGV, etc. So the only way to find the active control is through a recursive function that seeks out the control with the Focused() property set to true.
    And that is a pain - unless you know of a faster way to achieve this effect:
    VB.NET:
    GlobalControl = Application.GiveTheControlThatHasInputFocus()
    browser.document.opennew()
    browser.document.write(x)
    
    sub browser_documentcompleted()
      globalcontrol.focus
    end sub

    Thanks
 
I have not been able to reproduce the problem of browser control stealing focus, still it's like I have seen that happening before some time in some context... actually I think I may be thinking about the browser stealing focus from embedded Flash objects.

About ContainerControl.ActiveControl method it is correct that is returns the "most active" control in it's Controls collection, searching recursively until you hit a non-container is not a pain, and usually there is very few levels of nested containers. Here is a sample that seems to work:
VB.NET:
Function InputControl(ByVal c As ContainerControl) As Control
    Dim act As Control = c.ActiveControl
    If TypeOf act Is ContainerControl Then
        act = InputControl(CType(act, ContainerControl))
    End If
    Return act
End Function
For example InputControl(Me) given the form instance should return the active control that is not a container. If you knew which container it is supposed to be you can of course call that directly; SplitContainer2.ActiveControl.

By the way, you use Select method, and not Focus method.
KeyPreview has never "Previewed" any key presses going to child controls
What do you mean?
 
KeyPreview has never "Previewed" any key presses going to child controls
What do you mean?

I mean, you put a TabControl on the form and then two TextBoxes. Then Set the Form Key Preview to true, and trap the event.

The event never fires while either of the TextBox's have the focus.
Not very preview if you ask me. THe Form.KeyPreview only preview's key going directly to the form's HWND, it does not "peek" at all the "sub-controls" input. But I ask you: how many times to key commands go directly to the form itself? never, they go to the "child controls". so the key preview has never work as it should for me (or at least how I think it should, based on other RAD based development software).

Thanks for the suggestions otherwise. I figured I'd have to do the recursive function, and as for the error, yea, it isn't 100% all the time. But when it happens it, you can't break out of it, so from then on, no matter what control's you click, select edit, etc, that browser clings to the focus, so I want to prevent it by just always making sure.

Thanks
 
I mean, you put a TabControl on the form and then two TextBoxes. Then Set the Form Key Preview to true, and trap the event.

The event never fires while either of the TextBox's have the focus.
Well, the form does raise the KeyUp/Press/Down events in that case, that's exactly what it should do, and I have never seen it do otherwise.
 
Back
Top