c++visual-c++html-help

HtmlHelp MS API search string


Does any one in 2017 knows how to implement calling HtmlHelp function that will open .chm file with "Search" pane and query string in it's listbox and will be able to execute this query?

I try following:

HH_FTS_QUERY query;

query.cbStruct         = sizeof(HH_FTS_QUERY);
query.fUniCodeStrings  = TRUE;
query.pszSearchQuery   = szSearchStr;
query.iProximity       = HH_FTS_DEFAULT_PROXIMITY;
query.fStemmedSearch   = TRUE;
query.fTitleOnly       = TRUE;
query.fExecute         = TRUE;
query.pszWindow        = NULL;

HWND hHelpWnd = ::HtmlHelp(m_hWnd, szFile, HH_DISPLAY_SEARCH, (DWORD_PTR)&query);

but the query in query.pszSearchQuery won't be executed. I have opened .chm file with query.pszSearchQuery in "Search" pane's listbox on my screen, but I have to click "List Topics" myself to show results of search.


Solution

  • With the help of HTMLHelp API - VBA, VB6 and VB2003, i will try to reply. I believe there no API function to list topics in vc++. You have send button click event to launched help window.

    LRESULT OnSearch(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
    {
            TCHAR szBuf[128];
            GetDlgItem(IDC_EDIT1).GetWindowText(szBuf, sizeof(szBuf));
    
            if (!_tcslen(szBuf))
                return 0;
    
            //
            // First, invoke HtmlHelp with HH_DISPLAY_SEARCH. 
            // It doesn't execute search, but it's need for showing 'search' tab.
            //
            HH_FTS_QUERY fq;
            ZeroMemory(&fq, sizeof(fq));
            fq.cbStruct = sizeof(fq);
            fq.fUniCodeStrings = FALSE;
            fq.pszSearchQuery = (LPCTSTR)szBuf;
            fq.iProximity       = HH_FTS_DEFAULT_PROXIMITY;
            fq.fStemmedSearch   = FALSE;
            fq.fTitleOnly       = FALSE;
            fq.fExecute         = FALSE;
            fq.pszWindow        = NULL;
            HWND hwndHelp = ::HtmlHelp(NULL, _T("realplay.chm"), HH_DISPLAY_SEARCH, (DWORD)&fq);
    
            //
            // Find query combobox and set query text.
            // 
            HWND hPaneWnd, hPaneLast, hTabWnd, hDlgWnd, hCtlWnd;
    
            hPaneWnd = FindWindowEx(hwndHelp, NULL, _T("HH Child"), NULL);
            for (;;) // last HH Child
            {
                hPaneLast = FindWindowEx(hwndHelp, hPaneWnd, _T("HH Child"), NULL); // last HH Child
                if (!hPaneLast)
                    break;
                hPaneWnd = hPaneLast;
            }
            ATLTRACE("hPaneWnd == %x", hPaneWnd);
    
            hCtlWnd = FindWindowEx(hPaneWnd, NULL, _T("Button"), NULL); // skip Tab Control
            //
            // 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
            //         ...
            if (hCtlWnd)
            {
                hCtlWnd = FindWindowEx(hPaneWnd, NULL, _T("Edit"), NULL); // skip Tab Control
                // Set window text
                ATLASSERT(hCtlWnd != NULL);
                ::SendMessage(hCtlWnd, WM_SETTEXT, 0, (LPARAM)szBuf);   // fill it by our query
    
                ::SendMessage(hwndHelp, WM_COMMAND, 0xbc7, 0); // 0x3ee -- 'List Topics' button, it runs search
                if (::SendMessage(GetDlgItem(IDC_CHECK1), BM_GETCHECK, 0, 0) == BST_CHECKED)
                    ::SendMessage(hwndHelp, WM_COMMAND, 0xbbe, 0); // 0x3f1 -- 'Display' button, it shows first item
            }
            //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
            //         ...
            else
            {
    
                hTabWnd = FindWindowEx(hPaneWnd, NULL, _T("SysTabControl32"), NULL); // skip Tab Control
                hDlgWnd = FindWindowEx(hTabWnd, NULL, NULL, NULL); // skip dialog
    
                TCHAR szClass[64];
                GetClassName(hDlgWnd, szClass, sizeof(szClass));
                ATLTRACE("hDlgWnd(1) == %x", hDlgWnd);
                if (!_tcsstr(szClass, "#")) // Is it dialog?
                    hDlgWnd = FindWindowEx(hTabWnd, hDlgWnd, NULL, NULL); // skip dialog
                hCtlWnd = FindWindowEx(hDlgWnd, NULL, _T("ComboBox"), NULL); // well, it's combobox
    
                // Set window text
                ATLASSERT(hCtlWnd != NULL);
                ::SendMessage(hCtlWnd, WM_SETTEXT, 0, (LPARAM)szBuf);   // fill it by our query
    
                //
                // Run search and show first finded page
                //
                ::SendMessage(hwndHelp, WM_COMMAND, 0x3ee, 0); // 0x3ee -- 'List Topics' button, it runs search
                if (::SendMessage(GetDlgItem(IDC_CHECK1), BM_GETCHECK, 0, 0) == BST_CHECKED)
                    ::SendMessage(hwndHelp, WM_COMMAND, 0x3f1, 0); // 0x3f1 -- 'Display' button, it shows first item
            }
            return 0;
    }
    

    EDIT:

    You can get control ID of List Topic by spy++ enter image description here