Microsoft Internet Knowledge Base by Murray Cox - GUI Computing
The recent release of Microsoft Internet Explorer 3.0 (beta and release) internally use an ActiveX control named "SHDOCVW.OCX", which provides its browsing features. This OCX plugs right into VB, and gives you the identical browsing window that IE3.0 uses (including the display of Java applets and hosting ActiveX controls). Unfortunately, as yet, the control is undocumented - and while the control is fairly simple to use you will have to use the Object Browser and a bit of imagination to work out its properties, methods, and events.
This article showcases a useful VB Add-In for the web browser control. I will describe an Internet Knowledge Base Add-In for Visual Basic 4.0 - 32 bit.
|
|
I will not cover the theory on creating a VB Add-In, but feel free to click here to see a brief overview, and other references on the subject. |
|
First an overview of the Add-In. I will create a project named GUIAddIn which contains a public class called KnowledgeBase. This class adds a menu item to the Visual Basic Integrated Development Environment (VB-IDE). When the user (in this case a developer) clicks on this menu item, the class displays a query form. Once the user fills in the form, and clicks the "GO!" command button, a form containing the browser control appears with the results of the knowledge base search. From here the user can navigate with the hyperlinks (and back and forwards) to find the required article, or go back to the query form. I use VB 4.0 - 32 bit, as the OCX is only currently a 32 bit control. This 32 bit VB also lets me compile the OLE Server as a DLL, which results in faster execution and easily allows modal dialogs to be displayed (on top of the VB-IDE). |
|
Our Add-In adds one menu item to the Add-In menu group when it connects to the VB IDE, labeled "Knowledge Base", which is the way the user displays the query form. This is put in the procedure "ConnectAdd-In" which occurs when Visual Basic starts up and loads the Add-In, or when the Add-In is manually added to the development environment. Here is the code for ConnectAdd-In:
Public Sub ConnectAddIn(vbinstance As Object)
' Store this instance of vb in a member variable
Set m_vb = vbinstance
' Add the menu for knowledge base
Set m_mnuKnowledgeBase = m_vb.AddInMenu.MenuItems.Add("&Knowledge Base")
' Connect the event handler for the menu to this class
m_hmnuKnowledgeBase = m_mnuKnowledgeBase.ConnectEvents(Me)
' Set up a reference in our query form, so it knows what instance of
' result form to use
Set m_frmSearch.m_frmResults = m_frmResults
End Sub
Similarly we have a DisconnectAddIn, whose job it is to remove any menus created, and clean-up. Here it is:
Public Sub DisconnectAddIn(Mode As Integer)
' In case anything happens
On Error Resume Next
' Unload the form and destroy any memory associated with it
Unload m_frmResults
Set m_frmResults = Nothing
Unload m_frmSearch
Set m_frmSearch = Nothing
' Disconnect the event handler from the menu
m_mnuKnowledgeBase.DisconnectEvents m_hmnuKnowledgeBase
' Remove the menu
m_vb.AddInMenu.MenuItems.Remove m_mnuKnowledgeBase
End Sub
You must remember that multiple instances of VB may be running that are all using your client. For this reason, you must create new instances of each form that you want to use for each instance of your class. Thus forms must be declared in the class declarations section as:
dim m_frmResult as new frmResult
These are the declarations for my KnowledgeBase class:
' Member variable for the instance of the VBIDE Private m_vb As VBIDE.Application ' Member variable for the instance of the menu line Private m_mnuKnowledgeBase As VBIDE.MenuLine ' Member variable storing handle to the menu item Private m_hmnuKnowledgeBase As Long ' Private member instances of the forms Private m_frmSearch As New frmSearch Private m_frmResults As New frmResults
In our ConnectAddIn subprocedure, we connected the menu to an event handler. This causes the procedure AfterClick to be called when the menu item is clicked. We declare this procedure in our class, and we put code in to show our query form.
Public Sub AfterClick()
m_frmSearch.Show vbModal
End Sub
Now that we have set up our class, we can concern ourselves with elements that most VB programmers are more comfortable with: designing forms, and writing code for them. But first we set up some global variables for use in the rest of the program. When the Add-In DLL is first loaded, the procedure Main is called. We use this to set up global information that every instance of the Add-In will use.
Sub main()
' Set up global array of strings for parameter of the product selected
ReDim g_sProductParameters(43)
g_sProductParameters(0) = "KB_access"
g_sProductParameters(1) = "KB_automap"
g_sProductParameters(2) = "KB_basic"
.
.
.
g_sProductParameters(41) = "KB_works"
g_sProductParameters(42) = "KB_dosword"
g_sProductParameters(43) = "KB_word"
' Set up global array of strings for parameter of the category selected
ReDim Preserve g_sCategoryParameters(27)
g_sCategoryParameters(0) = ""
g_sCategoryParameters(1) = "kbappnote"
g_sCategoryParameters(2) = "kbbuglist"
.
.
.
g_sCategoryParameters(25) = "kbtool"
g_sCategoryParameters(26) = "kbtshoot"
g_sCategoryParameters(27) = "kbui"
End Sub
These global string arrays store the parameters that will be passed to the Microsoft Knowledge Base URL, via the browser control.
Basically the only code we have in the frmSearch module is to respond to the user's click of the Go button. When this occurs, there are two things we must do:
To check if the query has not been entered before, I use SendMessageA to send a CB_FINDSTRINGEXACT message to the combo-box asking, if it has been entered yet.
' Store the search string sSearch = Trim(cboSearch) ' See if the search string is in the ComboBox's list portion nFoundEntry = SendMessage(cboSearch.hwnd, CB_FINDSTRINGEXACT, ByVal -1, ByVal sSearch) 'If it isn't - add it If nFoundEntry = -1 Then cboSearch.AddItem cboSearch.Text End If
To generate the correct URL for the search we want to conduct, I examined the way Microsoft's Knowledge Base Search
web page did it. Here is an example of the URL generated from a search:
Presumably, Microsoft are using their Internet Information Server with an ISAPI DLL named "Fts.dll", which receives the parameters passed to it, and passes back the HTML code to the browser - representing the Search Results. What we are interested in is the stuff after the "?" - the parameters. It is not too difficult to decide that the URL that we need to use is based on the following line:
http://www.microsoft.com/isapi/fts.dll?db=PRODUCT_PARAM&qu=CATEGORY_PARAM
&qu=QUERY_PARAM&mh=MAX_HITS_PARAM
Here's the code:
' Replace any spaces with the character "+"
nPositionSpace = InStr(sSearch, " ")
Do While (nPositionSpace <> 0)
Mid(sSearch, nPositionSpace, 1) = "+"
nPositionSpace = InStr(sSearch, " ")
Loop
' Navigate to the Microsoft URL based on
' http://www.microsoft.com/isapi/fts.dll?db=PRODUCT_PARAM&qu=CATEGORY_PARAM
&qu=QUERY_PARAM&mh=MAX_HITS_PARAM
m_frmResults.wbResults.Navigate "http://www.microsoft.com/isapi/fts.dll?" _
& "db=" & g_sProductParameters(cboProduct.ListIndex) _
& "&qu=" & g_sCategoryParameters(cboCategory.ListIndex) _
& "&qu=" & sSearch _
& "&mh=" & txtMaximumHits
First we replace any spaces in the query with the character "+" (as required by fts.dll). Next we use the global arrays of strings, that we set up a minute ago, to pass the product and category parameters. Now we just show the frmSearch form.
If m_frmResults.Visible = False Then
m_frmResults.Show vbModal
End If
| We should get something similar to the image on the left. The code in this form is limited to the resizing of the screen, and clicking of the toolbar buttons. Note that much of the functionality of the Internet Explorer is exposed in the web browser control. For example, you could implement status text and status bars, describing the progress of the download. Even the context sensitive right mouse-clicks on the browsers are fully functional. |
Here is the code for the toolbar buttons (all one liners).
Private Sub tbrToolBar_ButtonClick(ByVal Button As Button)
' To handle navigation too far back or too far forward. Could easily implement
' disabling the relevant button when the user navigates to the beginning or end
' of the history list.
On Error Resume Next
Select Case Button.Key
Case "Search"
m_frmSearch.Show vbModal
Case "Refresh"
wbResults.Refresh
Case "Back"
wbResults.GoBack
Case "Forward"
wbResults.GoForward
End Select
End Sub
Now, once we have compiled the OLE DLL, add the following line to your vb.ini file in the windows directory under the [Add-Ins32] section:
GUIAddIn.KnowledgeBase=1
This causes the Add-In to be added to the VBIDE when it is started. A value of 0 indicates that the Add-In will be manually added.
The code for this Add-In is included in the
downloadable zip file (25 KB).
Any questions or comments, mail me...murrayc@gui.com.au