View RSS Feed

Development Team Blog

Getting More Out of Your Browser Control - Part II

Rating: 2 votes, 5.00 average.
In the first blog I told you how to connect to the HTML document object inside your Microsoft Internet Explorer browser object. How you can dynamically load a string holding a HTML document structure. In this blog I will extend this a bit.

Let's go back to the Did You Know dialog in DataBase Explorer and look what extras we can learn from there.

Context Menu
If you bring up that dialog and you right click the browser control you will notice you cannot get to the source code of the HTML document (view source). There are two reasons for that. First the HTML is dynamically constructed and this means that the browser control does not have a source but more important we override the context menu with one coded in Visual DataFlex. What do you have to do for that?

First we need to tell the browser control not to show a context menu at all. You can do that by adding
HTML Code:
oncontextmenu="return false;
to the body element of the original document that we create. So the data to be loaded should be changed from:
HTML Code:
<html><body><p>This is a test</p></body></html>
to:
HTML Code:
<html><body oncontextmenu="return false;<p>This is a test</p></body></html>
I wanted to mark the addition in red again but inside a HTML wrapper tag vBulletin apparently won't let you do that.

Now we have cancelled the original floating menu we can add our own code. BTW, if you do not cancel the built in context menu operation you would get two, one from yourself and one from the browser, very confusing for the end-user I would say. To add our own context menu we grab the OnComoncontextmenu event in the cComHTMLDocument object. So change the oHTMLDocument object to:
Code:
Object oHTMLDocument is a cComHTMLDocument
    Procedure OnComoncontextmenu
        Send Popup of oContextMenu
    End_Procedure
End_Object
The next step is to create a context menu object in Visual DataFlex. You can do this by simply create an object from the Visual DataFlex Studio class palette. Let us see what is behind the Copy Text menu item in the context menu of Database Explorer's Did You Know dialog. While the real floating / context menu contains more options the source code we now look at would be:
Code:
Object oContextMenu is a cCJContextMenu
    Object oCopyMenuItem is a cCJMenuItem
        Set psCaption to "Copy"
        Set psImage to "ActionCopy.ico"
                
        Procedure OnExecute Variant vCommandBarControl
            Delegate Send CopyText
        End_Procedure
    End_Object
End_Object
Pretty standard Visual DataFlex code, right? But if you look at the Microsoft HTML classes you won't find a CopyText function, so we need to write this ourselves. What exactly do we want to copy? All information of the information from a particular node? Let's say we want to copy the text from the paragraph element. This means we need to create an object of the cComHTMLParaElement class for this and we need to find the paragraph element in the document and then work from there. First create the cComHTMLParaElement object by coding:
Code:
Object oHTMLParagraphElement is a cComHTMLParaElement
End_Object
Make the object a sibling of the oHTMLDocument object.
The easiest way to find our element is by assigning an ID to the element before loading. So change the
HTML Code:
<html><body><p>This is a test</p></body></html>
into:
HTML Code:
<html><body><p id="Test">This is a test</p></body></html>
In our CopyText procedure we can find the element with the id "Test". We do this - like in JavaScript - with an GetElementById.
Code:
Procedure CopyText
    Variant vDocument vElement
    String sText
            
    Get ComDocument to vDocument
    Set pvComObject of oHTMLDocument to vDocument

    Get ComGetElementById of oHTMLDocument "Test" to vElement
    If (not (IsNullComObject (vElement))) Begin
        Set pvComObject of oHTMLParagraphElement to vElement
        Get ComInnerText of oHTMLParagraphElement to sText
    End
End_Procedure
How do we copy the text to the Windows clipboard? Difficult? No, there is a CLIPBOARD: driver for the standard DataFlex I/O commands (Direct_Input / Direct_Output). So add the following code to the CopyText method.
Code:
Move (Seq_New_Channel ()) to iChannel
If (iChannel <> DF_SEQ_CHANNEL_NOT_AVAILABLE) Begin
    Direct_Output channel iChannel "CLIPBOARD:"
    Write channel iChannel sText
    Close_Output channel iChannel
    Send Seq_Release_Channel iChannel
End
Of course do not forget to declare the variable iChannel.

This finishes the second blog about Getting More Out of Your Browser Control. I have nothing ready yet but I might continue with another blog in the future about this subject. If you have wishes for extensions post a comment.

Comments

  1. Ola Eldoy's Avatar
    Very interesting, Vincent!
    Thanks for two very educating blog posts.

    I have a suggestion for a future blog post: Automating an online service. For example, you could let the browser control log on to Twitter, and then collect your "following" list. This is just a suggestion - it could be any online service of your picking (collecting a bank statement? uploading a file to a web page? picking the weather forecast from a web page? In short, a real life example of interacting with the DOM).
  2. jaarden's Avatar
    Vincent Thnx!

    This is great and exactly what I was looking for a long time.
    In the mean time I am also able to click a link in the browser to open a view/dialog with the OnComBeforeNavigate2.

    With this technique we are now able to show xml/html/images directly from a database without first saving the content to disk.

    Still I wonder how far this gets in the context of performance, memory (in case of many embedded objects) and stability over alle Windows and IE versions?
    I can figure this out myself but if someone have more experience it would be great to share.

    Greetz,

    Jeroen Aarden
  3. Marco's Avatar
    Great article Vincent!

    I guess my request is also 'embedded' in the one from Ola, but I'd like to see a update Values into a form input fields.
    Eg I'm looking up details of a business on a business register (eg KvK in Netherlands). I have the application open a embedded browser with the business search page open. Then I have a button on the same dbview that 'enters the search fields'. so eg the webpage might have a form input with ID 'Name' and one with 'City' and 'State' it also has a search button.
    I'd like by pressing the VDF button, for a value to be entered in to each of the Name, City and State fields and the submit button pressed.

    So basically some interaction with the DOM. I know its possible, but never got around actually making it work...

    Cheers,
    Marco
  4. Vincent Oorsprong's Avatar
    Jeroen,

    Showing of not stored images is not possible in the IE 8 or lower based cComWebbrowser object. I have seen mentions that it is possible from IE9 but have no experience with this yet.

    I won't be worried too much about the number of Visual DataFlex COM proxy objects. I would be worried about the huge class include file and therefor I suggested to copy and paste code on a needed basis instead of including the full ComScriptlet.pkg of 270,000 lines of code.
  5. Vincent Oorsprong's Avatar
    Ola,

    Have been using the code for a DNB (Dutch National Bank) example and will see if I can show that code after Synergy.
  6. Vincent Oorsprong's Avatar
    Marco,

    Was playing with an example where an AJAX application is running in the browser control. It did work a bit but I also ran into some problems which would most likely require a lot of investigation time to find out how to address it. The documentation provided by Microsoft is - as very sadly common with COM libraries - quite limited.