Show Sitemap ..Help2HTMLHelpWinHelp

HTMLHelp API - VBA, VB6 and VB2003

Download

FAQ

Links

HTMLHelp API - Deklaration

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:

HTMLHelp API - HH_CLOSE ALL Note

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. 

EXCEL VBA Workaround:

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)

?

Search From Application

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

HTMLHelp and Visual Basic for Applications

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.

HTMLHelp and Visual Basic 6

Using a module for Visual Basic 6 projects

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

HTMLHelp and Visual Basic 2003 (.net)

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 ..

Note:

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

Using a module for VB.net projects

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
Top ...