As long as we get file names to consider for the final Scriptlet packaging, we store them in a listbox, whose reference we're passing in and out through the various subroutines. In particular, we're using a specialized function to add a new file name to the list. Before adding the name, this function performs some actions. For example, it checks whether the name already exists, and whether the file name is an HTML document. In this case, it adds the name to the list but runs a recursive routine to process its content.
Public Const LB_FINDSTRINGEXACT = &H1A2
Declare Function SendMessageString Lib "user32" Alias "SendMessageA" ( _
ByVal hwnd As Long, _
ByVal wMsg As Long, _
ByVal wParam As Long, _
ByVal lParam As String _
) As Long
' Add subroutine
Private Sub Add(ByVal list As ListBox, ByVal s As String)
Dim errCode As Integer
errCode = SendMessageString(list.hwnd, LB_FINDSTRINGEXACT, -1, s)
If errCode = -1 Then
list.AddItem s
If InStr(1, s, ".htm") > 0 Then
If InStr(1, s, "/") = 0 Or InStr(1, s, "\") = 0 Then
s = App.Path + "\" + s
End If
WebBrowser2.Navigate s
End If
End If
End Sub
By means of the LB_FINDSTRINGEXACT
message we can check whether the specified string already exists or not in the listbox. To do so, we make use of a specialized version of the Win32 API function SendMessage
. In this case, we redeclared its fourth argument, and transformed it in As String
instead of As Any
. To avoid conflicts, we also declared an alias for this function.
Declare Function SendMessageString Lib "user32" Alias "SendMessageA" ( _
ByVal hwnd As Long, _
ByVal wMsg As Long, _
ByVal wParam As Long, _
ByVal lParam As String _
) As Long
This normally occurs in Visual Basic programming, and represents the Visual Basic counterpart of a well-known mechanism called "type-casting".
Using the LB_FINDSTRINGEXACT
message means that you must specify a couple of parameters. The first one—known as wParam—
is the starting position for the search. If you pass –1 then the search begins from the first item in the listbox. The second argument—usually referred to as lParam—
is now the string to search for. The function returns –1 if fails. A failure means that the specified item doesn't exist in the listbox, so we can add it safely.
Immediately after inserting a new item into the listbox, we check the file name for a substring like .htm
. In practice, we try to find out whether the file is an HTML document. If it is, then we need to scan it too, in a recursive manner.
If InStr(1, s, ".htm") > 0 Then
If InStr(1, s, "/") = 0 Or InStr(1, s, "\") = 0 Then
s = App.Path + "\" + s
End If
WebBrowser2.Navigate s
End If
As shown in the above listing, we apply recursion by using a second but hidden WebBrowser control. In the example, we add the current directory to the file name. This is needed to enable the WebBrowser to successfully navigate to the URL. While this is quite rare, however, you ought to make sure that the file name doesn't already include a path. To test whether a path is included, we must verify if a slash or a backslash is present somewhere in the string.
The application's current path is given by App.Path
. You could also use the Win32 API function GetCurrentDirectory
to find out about the current system directory.
You should consider that even if the HTML source code doesn't include a path, when accessing an element through the Dynamic HTML object model you find it, and a protocol prefix too!
For example, let's look at the following HTML code snippet:
<BODY>
This is a reference to <a href="testflex.htm">a new HTML file</a>.
</BODY>
This page includes a link to the local file testflex.htm
. As you can see, there is no path and no protocol inside the file name. However, when you load the page through WebBrowser, and access its object model, the document.links
collection returns
file:///c:/path/testflex.htm
as its first element. Note that the file name now includes the full original path and even a string denoting the protocol to access it. In this case, since it is a local file, we have file://
. In addition, note that the slash replaced all the backslashes that are more usual in a path name.
This kind of processing takes place for all the elements recognized through the Dynamic HTML object model. Everything but the Scriptlets. In fact, if your page includes a Scriptlet then the data
attribute that stores the name of the component remains unchanged.
This is the reason we sometimes need to add a path, as shown above, before instantiating a new WebBrowser control.
This second browsing object might not necessarily be visible. However, it's better to avoid using the most natural approach to hide a control. In fact, if you hide a WebBrowser control by setting its Visible
property to False, then you won't be able to access its document object model.
To make it invisible you need to place it outside the visible portion of the form that actually contains it, or put the WebBrowser below another control.