![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() |
![]() ![]() |
The HtmlHelp() API function is declared as follows:
Declare Function HtmlHelp Lib "hhctrl.ocx" Alias "HtmlHelpA" _ (ByVal hwndCaller As Long, ByVal pszFile As String, _ ByVal uCommand As Long, ByVal dwData As Long) As Long
hwndCaller
The hwndCaller member is defined as a handle to an application window or Null. If a window handle is specified, the HTML Help window will be forced to be on-top of the calling window. If a 0 (zero) is specified, this condition will not occur.
When a handle, the corresponding window owns the html help window and receives any messages sent by htmlhelp back to the owner. By setting this to null (0& in VB parlance), one can effectively telling it that the desktop is the owner, thus allowing the window to fall behind the application.
pszFile
File to display; optionally also specifies which window type to display it in, delimited with the right angle bracket character (filename>windowtype). If you omit the window type, the HtmlHelp function will use the default window type specified in the HTML Help project file. For uCommand values that don't require a source file, pszFile can be Null, or 0 (zero), in VBA. However, a compiled HTML Help file is typically specified.
uCommand
The action to perform; see the remainder of this section for examples of how to display a Help topic by using either the HH_HELP_CONTEXT or HH_DISPLAY_TOPIC command.
HH_DISPLAY_TOPIC
Displays a Help topic by passing the URL of the HTML file that contains the topic as the dwData argument.
HH_HELP_CONTEXT
Displays a Help topic by passing the mapped context ID for the topic as the dwData argument.
dwData
Specifies additional data depending on the value of uCommand. Note that in this declaration this argument is declared As Any, because this argument accepts several different data types. You must be careful to pass the correct data type or risk an invalid page fault (also known as general protection fault [GPF]).
Return Values
Depending on the specified uCommand and the result HTMLHelp returns one or both of the following:
If you call the HH API directly from your application, and not via a second helper program like HH.EXE or KEYHH.EXE, then you MUST close any open help windows before shutting down the application or you will probably crash Windows.
The call to close all windows is simply. Because of a bug in the HH API make sure you call this in your main form's Query_Unload event not OnClose.
For more info see our knowledge base: HH_CLOSE_ALL Bug and HH_INITIALIZE
Private Sub Query_Unload(Cancel As Integer) Call HtmlHelp(Me.hWnd, "", HH_CLOSE_ALL, 0) End Sub.
See also: Download EXCEL Example
Trying to get around Excel crashing with a GPF General Protection Fault (Microsoft Windows program crash/error) when I tried to close the help file using HTMLHelp 0&, "", HH_CLOSE_ALL, 0&. The Microsoft knowledge base and other solutions on the Net suggested changes to the registry, which is not practical as would have to go to each user's PC to implement that. So had to use the tried and tested method of problem solving: Used random changes to see what works. The method that works, is to not leave the pszFile parm blank as the API says in the close_all call, but to give the CHM file name there.
So this seems to work if only one help window is open:
Call HtmlHelp(0, ThisWorkbook.Path & "\CHM-example.chm", HH_CLOSE_ALL, 0)
?
HH Workshop API documents how to move to the search tab and initiate a search. Unfortunately the initiating a search part has always been broken in HH. The only way around this would be to find the HH window and search pane controls. Then control those controls from your application using via low level Windows API calls.
Dmitry Karpezo, <dkarpezo AT lycosmail.com> posted a small code example on MSHelp2 Yahoo group.
The Visual Basic form this site includes a Visual Basic 6 translation and GUI example. See modul below:
Attribute VB_Name = "modHelpSearch" '****************************************************************************** '----- Modul HH API for Visual Basic 6 - (c) Ulrich Kulle '----- 2006-08-28 Version 1.0 first release for performing a search from application '****************************************************************************** '----- Thanks to Dimitry Karpezo for the C++ version of this code '------------------------------------------------------------------------------ Private Declare Function HtmlHelpSearch Lib "hhctrl.ocx" Alias "HtmlHelpA" _ (ByVal hwndCaller As Long, ByVal pszFile As String, _ ByVal uCommand As Long, dwData As HH_FTS_QUERY) As Long Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" _ (ByVal hwnd As Long, ByVal wMsg As Long, _ ByVal wParam As Long, ByVal lParam As Any) As Long Private Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" _ (ByVal hWndParent As Long, ByVal hWndChildAfter As Long, _ ByVal lpClassName As String, ByVal lpWindowName As String) As Long Private Declare Function GetClassName Lib "user32" Alias "GetClassNameA" _ (ByVal hwnd As Long, ByVal lpClassName As String, _ ByVal nMaxCount As Long) As Long Public Declare Function GetDlgItem Lib "user32" _ (ByVal hDlg As Long, ByVal nIDDlgItem As Long) As Long ' API const '------------------------------------------------------------------------------ Public Const WM_COMMAND As Long = &H111 ' WM_COMMAND = 0x0111 Public Const WM_SETTEXT As Long = &HC ' WM_SETTEXT = 0x000C ' HH API const '------------------------------------------------------------------------------ Public Const HH_DISPLAY_TOPIC = &H0 ' select last opened tab, [display a specified topic] Public Const HH_DISPLAY_TOC = &H1 ' select contents tab, [display a specified topic] Public Const HH_DISPLAY_INDEX = &H2 ' select index tab and searches for a keyword Public Const HH_DISPLAY_SEARCH = &H3 ' select search tab (perform a search is fixed here) Private Const HH_SET_WIN_TYPE = &H4 Private Const HH_GET_WIN_TYPE = &H5 Private Const HH_GET_WIN_HANDLE = &H6 Private Const HH_DISPLAY_TEXT_POPUP = &HE ' Display string resource ID or Private Const HH_HELP_CONTEXT = &HF ' display mapped numeric value in dwData Private Const HH_TP_HELP_CONTEXTMENU = &H10 ' Text pop-up help, similar to WinHelp Private Const HH_TP_HELP_WM_HELP = &H11 ' text pop-up help, similar to WinHelp ' HH_DISPLAY_SEARCH Command Related Structures and Constants '----------------------------------------------------------- Public Const HH_FTS_DEFAULT_PROXIMITY = -1 Public Const HH_MAX_TABS = 19 ' maximum number of tabs Public Type HH_FTS_QUERY ' UDT for accessing the Search tab cbStruct As Long ' Sizeof structure in bytes. fUniCodeStrings As Long ' TRUE if all strings are unicode. pszSearchQuery As String ' String containing the search query. iProximity As Long ' Word proximity. fStemmedSearch As Long ' TRUE for StemmedSearch only. fTitleOnly As Long ' TRUE for Title search only. fExecute As Long ' TRUE to initiate the search. pszWindow As String ' Window to display in End Type Public Sub PerformSearch(ByVal intHelpFile As Integer, ByVal sSearch As String, _ Optional ByVal bShowFirstResult As Boolean) '------------------------------------------------------------------------------ ' show search tab and perform search ' ** BUG: ** HTML Help: HH_DISPLAY_SEARCH API Command Does Not Perform a Search ' http://support.microsoft.com/kb/241381/en-us ' fixed by translation from C++ code from Dimitry Karpezo '------------------------------------------------------------------------------ Dim bDisplayFirstTopic As Boolean Dim searchIt As HH_FTS_QUERY Dim RetVal As Long Dim hwndhelp As Long '--- Dim hPaneWnd As Long '--- Dim hPaneLast As Long '--- Dim hTabWnd As Long '--- Dim hDlgWnd As Long '--- Dim hCtlWnd As Long '--- '--- check for search term -------------------------------------------------- If Len(sSearch) = 0 Then MsgBox "Please input a Search Term!" Exit Sub End If '--- First, invoke HtmlHelp with HH_DISPLAY_SEARCH. '--- It doesn't execute search, but it's need for showing 'search' tab. '---------------------------------------------------------------------------- With searchIt .cbStruct = Len(searchIt) ' Size of structute in bytes .fUniCodeStrings = 0& ' TRUE if all strings are unicode .pszSearchQuery = sSearch ' String containing the search query .iProximity = HH_FTS_DEFAULT_PROXIMITY ' word proximity .fStemmedSearch = 0& ' TRUE for StemmedSearch only .fTitleOnly = 1& ' TRUE for Title Search only .fExecute = 0& ' TRUE to initiate the search .pszWindow = "" ' Window to display in End With hwndhelp = HtmlHelpSearch(0&, HFile(intHelpFile), HH_DISPLAY_SEARCH, searchIt) '--- Find query combobox at help viewers search tab and set query text. '---------------------------------------------------------------------------- hPaneWnd = FindWindowEx(hwndhelp, ByVal CLng(0), "HH Child", vbNullString) For i = 1 To HH_MAX_TABS '--- tab's limited to 19 '--- last HH Child -------------------------------------------------------- hPaneLast = FindWindowEx(hwndhelp, hPaneWnd, "HH Child", vbNullString) If hPaneLast = 0 Then Exit For hPaneWnd = hPaneLast Next i '--- skip Tab Control ------------------------------------------------------- hCtlWnd = FindWindowEx(hPaneWnd, ByVal CLng(0), "Button", vbNullString) If hCtlWnd <> 0 Then '---------------------------------------------------------------------------- ' There are two types of interfaces: ' ' 1. ' Window hierarchy: ' + Main window ' + HH Child ' + Browser ... ' + HH Child <- second "HH Child" window ' - Edit <- we have to fill this edit ' - Buttons <- and press this buttons ' ... '---------------------------------------------------------------------------- '--- skip Tab Control ----- hCtlWnd = FindWindowEx(hPaneWnd, ByVal CLng(0), "Edit", vbNullString) ' Set window text and fill it by our query '-------------------------------------------------------------------------- SendMessage hCtlWnd, WM_SETTEXT, ByVal CLng(0), sSearch '--- // 0x3ee (?) 0xbc7 -- 'List Topics' button, it runs search SendMessage hwndhelp, WM_COMMAND, &HBC7, ByVal CLng(0) '--- // 0x3f1 (?) 0xbbe -- 'Display' button, it shows first item If bShowFirstResult Then SendMessage hwndhelp, WM_COMMAND, &HBBE, ByVal CLng(0) End If Else '---------------------------------------------------------------------------- ' 2. ' Window hierarchy: ' + Main window ' + HH Child ' + Browser ... ' + HH Child <- second "HH Child" window ' + Tab Control ' + Dialog ' - Combobox <- we have to fill this combo ' - Buttons <- and press this buttons ' ... '---------------------------------------------------------------------------- '--- skip Tab Control hTabWnd = FindWindowEx(hPaneWnd, ByVal CLng(0), "SysTabControl32", vbNullString) '--- skip dialog hDlgWnd = FindWindowEx(hTabWnd, ByVal CLng(0), vbNullString, vbNullString) '--- create a string-buffer Dim szClass As String * 255 RetVal = GetClassName(hDlgWnd, szClass, 255) ' e.g. a standard Windows Message Box has the class name "#32770". '-------------------------------------------------------------------------- If Not Left(szClass, 1) = "#" Then '--- Is it dialog? '--- skip dialog hDlgWnd = FindWindowEx(hTabWnd, hDlgWnd, vbNullString, vbNullString) End If '--- well, it's combobox hCtlWnd = FindWindowEx(hDlgWnd, ByVal CLng(0), "ComboBox", vbNullString) ' Set window text and fill it by our query '-------------------------------------------------------------------------- SendMessage hCtlWnd, WM_SETTEXT, ByVal CLng(0), sSearch ' Run search ' ------------------------------------------------------------------------- '--- 0x3ee -- 'List Topics' button, it runs search SendMessage hwndhelp, WM_COMMAND, &H3EE, ByVal CLng(0) ' Show first query result [optional] ' ------------------------------------------------------------------------- '--- 0x3f1 -- 'Display' button, it shows first item If bShowFirstResult Then SendMessage hwndhelp, WM_COMMAND, &H3F1, ByVal CLng(0) End If End If End Sub
How to call HTMLHelp from a VBA Macro?
Declare Function HtmlHelp Lib "hhctrl.ocx" _ Alias "HtmlHelpA" _ (ByVal hWnd As Long, _ ByVal lpHelpFile As String, _ ByVal wCommand As Long, _ ByVal dwData As Long) As Long Const HH_DISPLAY_TOPIC = &H0 Const HH_SET_WIN_TYPE = &H4 Const HH_GET_WIN_TYPE = &H5 Const HH_GET_WIN_HANDLE = &H6 Const HH_DISPLAY_TEXT_POPUP = &HE ' Display string resource ID or text in a pop-up window. Const HH_HELP_CONTEXT = &HF ' Display mapped numeric value in dwData. Const HH_TP_HELP_CONTEXTMENU = &H10 ' Text pop-up help, similar to WinHelp's HELP_CONTEXTMENU. Const HH_TP_HELP_WM_HELP = &H11 ' text pop-up help, similar to WinHelp's HELP_WM_HELP. Sub OpenHelp(ByVal ContextId As Long) 'The return value is the window handle of the created help window. Dim hwndHH as Long hwndHH = HtmlHelp(0, ThisWorkbook.Path & "\" & AppId & ".chm", HH_HELP_CONTEXT, ContextId) End Sub
to call the default topic of the HTMLHelp file please try:
hwndHH = HtmlHelp(0, ThisWorkbook.Path & "\" & "Helpfile" & ".chm", HH_DISPLAY_TOPIC, 0)
The Context_ID will submit.
At the control element for which the help shall be called set the HelpContextID property to 1030 e.g. in Visual Basic. The exact procedure can be recognized in the example project.
Example:
'****************************************************************************** '----- Modul - definition for HTMLHelp - (c) Ulrich Kulle '----- 2002-08-26 Version 1.0 first release '----- 2005-07-17 Version 1.1 updated for Pop-Up help '****************************************************************************** '----- Portions of this code courtesy of David Liske. '----- Thanks to David Liske, Don Lammers, Matthew Brown and Thomas Schulz '------------------------------------------------------------------------------ Type HH_IDPAIR dwControlId As Long dwTopicId As Long End Type 'This array should contain the number of controls that have 'context-sensitive help, plus one more for a zero-terminating 'pair. Public ids(2) As HH_IDPAIR Declare Function GetDlgCtrlID Lib "user32" _ (ByVal hwnd As Long) As Long Public Declare Function HtmlHelp Lib "hhctrl.ocx" Alias "HtmlHelpA" _ (ByVal hwndCaller As Long, ByVal pszFile As String, _ ByVal uCommand As Long, ByVal dwData As Long) As Long Declare Function HTMLHelpTopic Lib "hhctrl.ocx" Alias "HtmlHelpA" _ (ByVal hwndCaller As Long, ByVal pszFile As String, _ ByVal uCommand As Long, ByVal dwData As String) As Long Private Declare Function HtmlHelpSearch Lib "hhctrl.ocx" Alias "HtmlHelpA" _ (ByVal hwndCaller As Long, ByVal pszFile As String, _ ByVal uCommand As Long, dwData As HH_FTS_QUERY) As Long Public Const HH_DISPLAY_TOPIC = &H0 ' select last opened tab, [display a specified topic] Public Const HH_DISPLAY_TOC = &H1 ' select contents tab, [display a specified topic] Public Const HH_DISPLAY_INDEX = &H2 ' select index tab and searches for a keyword Public Const HH_DISPLAY_SEARCH = &H3 ' select search tab and perform a search Private Const HH_SET_WIN_TYPE = &H4 Private Const HH_GET_WIN_TYPE = &H5 Private Const HH_GET_WIN_HANDLE = &H6 Private Const HH_DISPLAY_TEXT_POPUP = &HE ' Display string resource ID or Public Const HH_HELP_CONTEXT = &HF ' display mapped numeric value in dwData Private Const HH_TP_HELP_CONTEXTMENU = &H10 ' Text pop-up help, similar to WinHelp's HELP_CONTEXTMENU. Private Const HH_TP_HELP_WM_HELP = &H11 ' text pop-up help, similar to WinHelp's HELP_WM_HELP. Public Type HH_FTS_QUERY ' UDT for accessing the Search tab cbStruct As Long ' Sizeof structure in bytes. fUniCodeStrings As Long ' TRUE if all strings are unicode. pszSearchQuery As String ' String containing the search query. iProximity As Long ' Word proximity. fStemmedSearch As Long ' TRUE for StemmedSearch only. fTitleOnly As Long ' TRUE for Title search only. fExecute As Long ' TRUE to initiate the search. pszWindow As String ' Window to display in End Type Public Function HFile(ByVal i_HFile As Integer) As String '----- Set the string variable to include the application path of helpfile Select Case i_HFile Case 1 HFile = App.Path & "\help\CHM-example.chm" Case 2 '----- Place other Help file paths in successive case statements HFile = App.Path & "\help\CHM-other-language.chm" End Select End Function Public Sub ShowContents(ByVal intHelpFile As Integer) HtmlHelp hwnd, HFile(intHelpFile), HH_DISPLAY_TOC, 0 End Sub Public Sub ShowIndex(ByVal intHelpFile As Integer) HtmlHelp hwnd, HFile(intHelpFile), HH_DISPLAY_INDEX, 0 End Sub Public Sub ShowTopic(ByVal intHelpFile As Integer, strTopic As String) HTMLHelpTopic hwnd, HFile(intHelpFile), HH_DISPLAY_TOPIC, strTopic End Sub Public Sub ShowTopicID(ByVal intHelpFile As Integer, IdTopic As Long) HtmlHelp hwnd, HFile(intHelpFile), HH_HELP_CONTEXT, IdTopic End Sub '------------------------------------------------------------------------------ '----- display the search tab '----- bug: start searching with a string dosn't work '------------------------------------------------------------------------------ Public Sub ShowSearch(ByVal intHelpFile As Integer) Dim searchIt As HH_FTS_QUERY With searchIt .cbStruct = Len(searchIt) .fUniCodeStrings = 1& .pszSearchQuery = "foobar" .iProximity = 0& .fStemmedSearch = 0& .fTitleOnly = 1& .fExecute = 1& .pszWindow = "" End With Call HtmlHelpSearch(0&, HFile(intHelpFile), HH_DISPLAY_SEARCH, searchIt) End Sub
Providing help in your application should be one of the things that you shouldn't skip. Use the appropiate type of help based on specific need of your application. Sometimes it's better to use HTMLHelp files (CHM), but sometimes it will be enough to have only Pop-Up help or ToolTips.
If you already have experience with VB6, the first thing you may notice about .NET applications is they no longer support calling help using numeric Context IDs. But look, what has changed when using the good old HTMLHelp API call ..
At VB.net a basic problem consists in the declaration of the API function. You'll need to convert the LONG declares in the API to IntPtr or Int32 for .NET, since integers in .NET are 32bit, whereas they are 16bit in VB6.
Public Declare Function HTMLHelp_BaseCall Lib "hhctrl.ocx" Alias "HtmlHelpA" _ (ByVal hWnd As IntPtr, ByVal lpHelpFile As String, _ ByVal uCommand As Int32, ByVal dwData As Int32) As Int32
Example:
Module modHelp '------------------------------------------------------------------------ '--- (c) Ulrich Kulle, 2004-09-03 '--- The HTMLHelp function starts HTML Help and passes additional data '--- If the function succeeds, the return value is nonzero. '--- If the function fails, the return value is zero. Public Const HH_DISPLAY_TOPIC As Short = &H0 ' select last opened tab, [display a specified topic] Public Const HH_DISPLAY_TOC As Short = &H1 ' select contents tab, [display a specified topic] Public Const HH_DISPLAY_INDEX As Short = &H2 ' select index tab and searches for a keyword Public Const HH_DISPLAY_SEARCH As Short = &H3 ' select search tab and perform a search Public Const HH_HELP_CONTEXT As Short = &HF ' display mapped numeric value in dwData '--- The parameters of the API call MUST be an Integer type '--- old VB6 definition of the parameters was 'As Long' '*** hWnd is the handle of the window requesting help '*** lpHelpFile is a string containing path, name of the helpfile ' [optional]: file of the specific topic ' [optional]: name of a secondary window '*** uCommand specifies the type of help requested ' see some Help Command Constants above '*** dwData specifies additional data. The value used despends on the value of uCommand ' VB6 declaration is 'As Any' or 'As Long' !!! ' ********** Changes ********** ' (VB.net): Integer => IntPtr ' (VB.net): Long => Int32 ' (VB.net): Long => Int32 Public Declare Function HTMLHelp_BaseCall Lib "hhctrl.ocx" Alias "HtmlHelpA" _ (ByVal hWnd As IntPtr, ByVal lpHelpFile As String, _ ByVal uCommand As Int32, ByVal dwData As Int32) As Int32
Call to show Table of Contents
Public Sub ShowContents(ByVal intHelpFile As Integer) '--- Call to show Table of Contents --- Dim RetVal As Int32 RetVal = HTMLHelp_BaseCall(IntPtr.Zero, HFile(intHelpFile), HH_DISPLAY_TOC, 0) End Sub
Call to show Index
Public Sub ShowIndex(ByVal intHelpFile As Integer) '--- Call to show Index --- Dim RetVal As Int32 RetVal = HTMLHelp_BaseCall(IntPtr.Zero, HFile(intHelpFile), HH_DISPLAY_INDEX, 0) End Sub
Call to show topic
Public Sub ShowTopic(ByVal intHelpFile As Integer, ByVal strTopic As String) '--- Call to show topic --- Dim RetVal As Int32 RetVal = HTMLHelp_BaseCall(IntPtr.Zero, HFile(intHelpFile) & "::/" & strTopic, HH_DISPLAY_TOC, 0) End Sub
Call to show a topic by ContextID
Public Sub ShowTopicID(ByVal intHelpFile As Integer, ByVal IdTopic As Int32) '--- Call to show a topic by ContextID --- Dim RetVal As Int32 RetVal = HTMLHelp_BaseCall(IntPtr.Zero, HFile(intHelpFile), HH_HELP_CONTEXT, IdTopic) End Sub
To select a specific help file
Public Function HFile(ByVal i_HFile As Integer) As String Dim sHelpFile As String Dim sStartupPath As String '--- Initialize context-sensitive help --- sStartupPath = Application.StartupPath.ToString Select Case i_HFile Case 1 sHelpFile = Replace(sStartupPath, "\bin", "\hlp") & "\VBnetCHM.chm" Return sHelpFile Case 2 '--- Place other help file paths in successive case statements sHelpFile = Replace(sStartupPath, "\bin", "\hlp") & "\Help_Coding-Example_VB6.chm" Return sHelpFile End Select End Function
![]() |