VB: ActiveX

FTP    ::    ActiveX |  1  |  2  |  3  |  4  |- 5 -|

   
Web Control - Initialization

 
Private Sub Form_Load()
     Dim dum, strT
 
     tboLinkID = Form_fsubMainLinks!anID
 
     web2.Object.Navigate "about:blank"
     dum = fWaitTillReady()
 
     web2.Object.Document.DesignMode = "On"
     web2.Object.Document.ExecCommand "AbsolutePosition", False, True
     web2.Object.Document.ExecCommand "2D-Position", False, True
     web2.Object.Document.bgColor = fHexSwap(Hex(14603987))
     dum = fWaitTillReady()
 
     If IsNull(Form_fsubMainLinks!tboNoteBig) Then
         web2.Object.Document.body.innerHTML = ""
     Else
         If Form_fsubMainLinks!tglAbs Then
             Form_fsubMainLinks!tboAbstract = fRegExp(Form_fsubMainLinks!tboAbstract, "&#([^;]*);", "<SPAN v2=$1>&#$1;</SPAN>", True)
             web2.Object.Document.body.innerHTML = Form_fsubMainLinks!tboAbstract
         Else
             Form_fsubMainLinks!tboNoteBig = fRegExp(Form_fsubMainLinks!tboNoteBig, "&#([^;]*);", "<SPAN v2=$1>&#$1;</SPAN>", True)
             web2.Object.Document.body.innerHTML = Form_fsubMainLinks!tboNoteBig
         End If
     End If
     dum = fWaitTillReady()
 
End Sub
 


 
Private Function fWaitTillReady()
 
     Do While web2.Object.ReadyState <> 4
         DoEvents
     Loop
 
End Function
 

 
 

To explain. In this example, we'll call the web browser control that was added to the form - web2. For some of these things, it's best to get a reply, to wait, until the control has done something. And calling this little wait til ready routine does that trick. It has to come back as 4, or else it just continues to wait. By using the Navigate method to go to a blank page, it won't try to load anything; or if you prefer, it's loading a blank page. This is just like a mini-browser. The all-important DesignMode is switched on, as you can see. And the hex swap merely takes a hex value with 6 digits and swaps the first two for the last two, swapping red and blue values in other words, to correct for the way Hex returns its value.

This web control is placed in a popup form. Let's call it, popWebC. It doesn't have to be a popup. It just is in this example. The size of this popup and the size of the web2 control are set in the form's 'design mode'. You stretch out both form and web browser control to the largest size you might prefer. Then you will change one of the properties on the control (such as including address bar, etc). Then save the form. Now once you popup this form, you're editing a blank page, in this case. And here it's simply loaded with what is in a particular field showing in the form which pops it up; that form is named, Form_fsubMainLinks, in this example. In fact, the unique ID of the underlying record is saved at the start (to a text control on the popup) in order to double-check when the popup is closed. The web control doesn't automatically move or update with the underlying form. The form knows about the web control, as it were, but the web control doesn't know about the form, except to check for toggle switches. You could provide a follow-along update, with some more programming. But there are cases where you don't want this, where you want it unlinked as it were. So given this approach, and perhaps by mistake, one could open the popup and then lose it behind other windows. You might forget about it and then move to another record on the form. And you probably don't want to close the edited result on the new record, a different record, except in some very particular case.

Only one instance of the popup will be open. So here the same popup serves double duty. There are a couple of toggles on the form which pops it up. The popup can be used to edit the field which is linked to a text box, tboNoteBig, which holds the contents of a memo field (very large text field). Or it can also edit tboAbstract, which is a summary of the longer 'bigger' note. So before popping anything up, these are toggle buttons are pressed or released in order to determine which gets edited by the web control. Again, one toggle is for the big note. The other toggle is for the abstract. See that, just below.

Now, the control first loads nothing, a blank page. Then whichever field is loaded into the innerHTML property of the web control. Edit mode is on. Ready to go. Whichever field is edited by the web browser control, the same transform is used. And you can see that this transform is a regular expression (actually another custom routine covering the actual Microsoft regex). The purpose of this is just to handle high unicode values. If you just specify the unicode as a numeric entity (similar to &#160; which is for a space or blank letter, but which have values > 255), while this will look as intended in the web control, which can handle unicode characters directly, you can't save it for next time. Next time, you will just see a question mark in that spot, instead; that's assuming the underlying fields are incapable of storing unicode, directly. So this places a span around the unicode character, and saves its 'cell' number, its code, its position in the font file, as an attribute. When it comes time to save the edited text, then it's easy enough to perform another transform and get all the unicode once again represented as numeric entities, which themselves are just plain text. The SPAN is used because it both doesn't change the display and is a legit HTML tag. It will survive any auto-edit or filtering done by the web control before this reverse transform can be performed. Other elements conceivably could be automatically removed, and the scheme would not work. And this also assumes that no other legitimate SPAN has for its first attribute - v2.

As mentioned, in this example, the web control is in a popup window/form:

 
Private Sub tglNoteBig_Click()
 
     If Len(tboNoteBig) > 0 And tglAbs = False Then
         DoCmd.OpenForm "popWebC"
     Else
         tglBigNote = False
     End If
 
End Sub
 
Private Sub tglAbstract_Click()
 
     If Len(tboNoteBig) > 0 And Len(tboAbstract) > 0 And tglNBig = False Then
         DoCmd.OpenForm "popWebC"
     Else
         tglRheimsSum = False
     End If
 
End Sub
 

 
 

If one were curious, in other words. In short, if one toggle is down, then the other is locked out. And you could transfer one to the other, after the popup is opened, by switching the opener toggle up and the other down, and then closing/saving the popup. But this is getting a bit too much into a particular example, rather than the web control itself.

 
Web Control - Read

 

Because this example sets up a web control in a pop-up window/form, sort of a 'zoom view'-plus for a particular field and text box in an underlying form, there finally comes the time to close the window. Edit complete. As the innerHTML was used to load the web control, so it is read to get the final HTML text:

 
Private Sub Form_Close()
     Dim response, strT As String
 
     If tboLinkID <> Form_fsubMainLinks!anID Then
         response = MsgBox("This is not the link you started with" & vbCrLf & vbCrLf & "Save it anyway?", vbYesNo, "NOT THE SAME LINK")
         If response = vbNo Then Exit Sub
     End If
 
     Do While InStr(web2.Object.Document.body.innerHTML, "<font") = 1
         web2.Object.Document.body.innerHTML = web2.Object.Document.body.firstChild.innerHTML
     Loop
 
     strT = web2.Object.Document.body.innerHTML
     Form_fsubMainLinks.sPop fRegExp(strT, "]*).>.*?/SPAN>", "&#$1;", True)
 
End Sub
 

 
 

But first, the unique id, which was previously saved, is double-checked against the id of the current form record. If it's a match, if everything is okay, then any leading FONT tags are removed. And lastly, the regular expression is used to turn those spans back into just the numeric entities for unicode characters. The edited text is passed to a routine on the main form, which in turn will update the record.

Again, and as suggested above, the use of SPAN to tag unicode during editing also calls to mind something else of this Microsoft web browser control. The control, the code, the libraries, are designed on a certain model of HTML, and will not allow just any attribute for any tag. In some cases, if you add in unexpected attributes, then edit that field, the attribute will be gone when you save it back. One trick is just to prefix a space before the value of the attribute. So if you want to add a class attribute most unexpectedly to something like a line break, <BR>, it would be - <BR class=" whatever">. Note the leading space before, "whatever". Then, when it comes time to assemble the final page, a simple regexp or other text replace routine can be used to remove that leading space from all class attributes.

 
Web Control - Selection

 

Since this is HTML markup, there will come a point where you might want to go beyond the built in commands. It's recommended that you stick with these for simple markup, like bold (ctrl-b), italic (ctrl-i), simple anchor/hyperlink (ctrl-k), etc. But you might want to add some elaborate tag and attribute values of your own, to a highlighted section of text - a range of text. How do you do that?

You can highlight some text with the mouse. Then you have to read where in the field that is. This can be done using the IHTMLTxtRange class:

 
Public Function fTglElement(strElmt As String, flgNest As Boolean, strAttr As String)
     Dim txtRng As IHTMLTxtRange
 
     Set txtRng = web2.Document.selection.createRange
     If Len(txtRng.HTMLText) > 0 Then
         If txtRng.parentElement.tagName = strElmt And Not flgNest Then
             txtRng.parentElement.outerHTML = txtRng.parentElement.innerHTML
         Else
             txtRng.pasteHTML "<" & strElmt & strAttr & ">" & txtRng.HTMLText & ""
         End If
         DoEvents
 
     End If
 
End Function
 

 
 

The highlight range is found by using the createRange method, as shown. This object/class, IHTMLTxtRange, has a property where one can double-check that there actually was a selection. If greater than zero, there is also another flag, just in this particular routine and example, used to check if the immediately superior element is just the same as the one to be added, here. There may be some case where you'd want to nest the same element/tag in the HTML. But if not, or if you just hit the button one too many times, then the text is enclosed in the single tag, and whatever list of attributes is included.

You can also just paste in special characters in the same way:

 
Public Function fSpecialKey(strKey As String)
    Dim txtRng As IHTMLTxtRange

    Set txtRng = web2.Document.selection.createRange
    txtRng.pasteHTML (strKey)
    DoEvents

End Function

 

 

In both cases, it might assume that you've created a button bar in the Office application, with special buttons for the custom tags, or special characters. But that's beyond the present scope.

 
Web Control - Conclusion

 

Once again, surely more could be added. It's essentially a simple control. But there are some references below for both this and the treeview which might provide some further detail and inspiration.


 
 More to read:

History Brief history of BASIC
ActiveX Old 1997 Byte article on just what is - ActiveX?
Note Peter Aitken's brief note on just what is - ActiveX
vbwm.com Paul Duffield's old 1999 article on writing your own ActiveX
WB .NET .NET version of the web browser control
Rick Strahl Catch-all run-through of some topics here, including the WB control
Irvine/Liang Ch. 3 (incl. treeviews) of Irvine and Liang's 1999 Advanced Visual Basic 6
O'Reilly From Nutshell series, Evan Dictor briefly describes the treeview and how to use it
VBaccelerator VBaccelerator.com 'classic VB' ActiveX treeview controls
Brad Generally the use of API commands to modify a treeview
Point Ltd. Complete Access db treeview example, including use of graphics
VBnet 'Classic VB' site describing API call, FindFirstFile, and filling in a treeview
VBnet 'Classic VB' site describing why it remains a 'classic VB' site (see Sept 2002 entry)
Petition Early 2005 petition to Microsoft from VBnet-fans to maintain 'classic VB', and note via blog as to whether MS managers have a track record of listening