none
HTML Help (*.chm) in vorhandenes MFC Programm einbinden. RRS feed

  • Frage

  • Guten Tag,

    leider muß ich wieder mal um Hilfe bitten! Es gelingt mir einfach nicht meine schöne *.chm Datei in mein fertiges Programm einzubinden.

    Auisgangssitution: Betriebssystem:        Windows 10 Pro x64
                               Entwicklungssystem:  Visual C++ 2010 Professional
                               Anwendung:              RPwMgr.exe (Debugversion x86)
                               Hilfesystem:              RPwMgrHelp.chm

    Ich möchte mittels F1-Taste und aus einem Menue heraus nun nur die Hilfe mit Anzeige der Startseite anzeigen, mehr nicht. Es ist momentan keine Context sensitive Anzeige von Topics geplant. Diese soll sich der Benutzer nach der Gliederung selber aussuchen.

    Bisher habe ich mir daran fast die Ohren gebrochen. Ich möchte hier nicht mit der Schilderung meiner diversen Versuche langweilen und stelle nur die zwei Fragen: Wie geht das? Gibt es dazu irgendwo vernünftige Beispiele?

    K. H. Renders.


    M. Thaddaeus

    Sonntag, 24. Januar 2016 15:54

Antworten

  • Hallo nochmal,

    für den Fall, dass der Aufruf der Hilfe noch nicht funktioniert, läßt sich auch eine Fehlermeldung ermitteln. Deshalb hier mal mein ganzes kleines Beispiel (MBCS-Variante):

    #include <windows.h>
    #include <htmlhelp.h>
    
    struct HH_LAST_ERROR
    {
    	int		cbStruct;
    	HRESULT	hr;
    	BSTR	description;
    };
    
    int WINAPI WinMain(HINSTANCE, HINSTANCE, char * cmdLine, int)
    {
    	HWND			hWnd;
    	DWORD			topicId = 0;
    	HH_LAST_ERROR	lastError;
    	char			* desc = 0;
    	int				len;
    
    	hWnd = HtmlHelp(0, "filename.chm", topicId ? HH_HELP_CONTEXT : HH_DISPLAY_TOPIC, topicId);
    	if (!hWnd)
    	{
    		memset(&lastError, 0, sizeof(HH_LAST_ERROR));
    		lastError.cbStruct = sizeof(HH_LAST_ERROR);
    
    		hWnd = HtmlHelp(0, 0, HH_GET_LAST_ERROR, (DWORD)&lastError);
    		if (hWnd && /* FAILED(lastError.hr) && */ lastError.description)
    		{
    			len = WideCharToMultiByte(CP_ACP, 0, lastError.description, -1, 0, 0, 0, 0);
    			if (len)
    			{
    				desc = new char [len];
    				if (desc)
    				{
    					*desc = '\0';
    					len = WideCharToMultiByte(CP_ACP, 0, lastError.description, -1, desc, len, 0, 0);
    				}
    			}
    			SysFreeString(lastError.description);
    		}
    		if (desc && *desc)
    			MessageBox(0, desc, "HtmlHelp", MB_OK);
    		else
    			MessageBox(0, "Die Hilfe konnte nicht aufgerufen werden.", "HtmlHelp", MB_OK);
    
    		if (desc) delete []desc;
    		return -1;
    	}
    	while (IsWindow(hWnd))
    		Sleep(500);
    	return 0;
    }

    Gruß
    Heiko

    Montag, 25. Januar 2016 14:08
  • Also ich habe mal das Beispiel von Heiko genommen. Letztich funktioniert es so wie er gesagt hatte. Er hat nur ein paar Schreibfehler drin gehabt mit der Variablen topicId. Rein von der Funktionalität ist aber alles korrekt

    #include <windows.h>
    #include <htmlhelp.h>
    #include <tchar.h>
    
    #pragma comment(lib, "htmlhelp.lib")
    
    int _cdecl _tmain (int argc, TCHAR *argv[])
    {        
    
    	DWORD topicId = 0;
    	HWND hWnd = HtmlHelp(0, _T("D:\\Verzeichnis\\noch einverzeichnis\\name_des_chmfiles.chm"), topicId ? HH_HELP_CONTEXT : HH_DISPLAY_TOPIC, topicId);
    
    	while (IsWindow(hWnd))
    		Sleep(500);
    }
    Wenn Du obigen code jetzt verwendest sollte das in einem Kommandozeilenprojekt problemlos funktionieren.


    Best regards

    Bordon

    Note: Posted code pieces may not have a good programming style and may not perfect. It is also possible that they do not work in all situations. Code pieces are only indended to explain something particualar.

    Dienstag, 26. Januar 2016 07:04
  • Guten Tag,

    hiermit möchte ich Heiko und Bordon herzlich für Ihre Mühe danken. Sie haben mich auf die richtige Färte gesetzt.

    Mit dem Beitrag von Bordon, welcher den Beitrag von Heiko ergänzte konnte ich tatsächlich meine Hilfe öffnem. Hierzu habe ich OnHelp überschrieben. Was mich allerdings störte, war die Tatsache, daß in der Hilfe von VC++ 2010 die Funktion HtmlHelp in der folgened Weise angegeben war:

         CWinApp::HtmlHelp() oder CWnd::HtmlHelp(), in beiden Fällen ist die Funktion:

          virtual void HtmlHelp(DWORD_PTR, UINT nCmd = 0x000F);

    Dann stieß ich auf die Funktion CWinApp::EnableHlmlHelp(); weche ich nun im Constructor der Hauptfunktion meiner Anwendung aufrufe:

    CRPwMgrApp::CRPwMgrApp()
    {
      EnableHtmlHelp();
      // Neustart-Manager unterstützen
        m_dwRestartManagerSupportFlags = AFX_RESTART_MANAGER_SUPPORT_RESTART;
    }

    und in der Funktionhatte ich bereits die folgenden Zeilen eingefügt:

    BOOL CRPMgrApp::InitInstance()
    {
      ...
      ...

      m_scHelpFilespec = m_scModulePath + m_scApplName + _T("Help.chm");
      strcpy_s(szHelpFilespec, MAX_PATH, m_scHelpFilespec.GetBuffer());
      if (HelpFile.GetStatus(m_scHelpFilespec.GetBuffer(), tStatus))
      {
        free((void*)m_pszHelpFilePath);
        m_pszHelpFilePath = _tcsdup(szHelpFilespec);
      }
      else
      {
         ...
         ...
      }

      scHelpFilespec.ReleaseBuffer();
      ...
      ...

    }

    und in meinem Dialog überschrieb ich die OnHelp Funktion:

    BEGIN_MESSAGE_MAP(CRPasswordManagerDlg, CDialogEx)
        ON_WM_SYSCOMMAND()
        ON_WM_PAINT()
        ON_WM_QUERYDRAGICON()
        ...
        ...
        ON_COMMAND(ID_HELP, &CRPwMgrDlg::OnHelp)
    END_MESSAGE_MAP()

    void CRPwMgrDlg::OnHelp()
    {
      theApp.HtmlHelp(1000);
    }

    ich löschte

    #include <windows.h>
    #include <htmlhelp.h>

    und

    #pragma comment(lib, "htmlhelp.lib")

    aus meinem Code und der Hifesystem Aufruf funktionierte sowohl mit F1 als auch über das Hilfe Menue eiwandfrei! So einfach ist das --- wenn man es weiß und wenn man eine MFC-Anwendung verwendet.

    Somit ist mein Problem gelöst! Mit nochmaligem Dank verbleibe ich

    mit freundlichen Grüßen
        K. H. Renders


    M. Thaddaeus

    Mittwoch, 27. Januar 2016 15:34

Alle Antworten

  • Hallo,

    hilft dir vielleicht dieser Code-Schnipsel weiter:

    #include <windows.h>
    #include <htmlhelp.h>
    
    {
    	DWORD topicId = 0;
    	HWND hWnd = HtmlHelp(0, "<CHM-Dateiname>", TopicId ? HH_HELP_CONTEXT : HH_DISPLAY_TOPIC, TopicId);
    
    	while (IsWindow(hWnd))
    		Sleep(500);
    }

    HtmlHelp()

    Gruß
    Heiko



    • Bearbeitet Heiko65456465 Sonntag, 24. Januar 2016 19:06
    • Als Antwort vorgeschlagen Bordon Montag, 25. Januar 2016 11:10
    Sonntag, 24. Januar 2016 19:01
  • Guten Tag Heiko,

    Dank für Deine schnelle Antwot. Leider funktioniert das nicht!

    void CRPwMgrDlg::OnHelp()
    {
       CString scStr = _T("RPwMgrHelp.chm");
       DWORD TopicID = 0;

       // 1 weder diese:
       HWND hWnd
    = HtmlHelp(0, "RPwMgrHelp.chm", TopicId ? HH_HELP_CONTEXT : HH_DISPLAY_TOPIC, TopicId);

       // 2 noch diese:
       HWND hWnd = ::HtmlHelp(0, scStr.GetBuffer(), HH_DISPLAY_TOPIC, NULL);
    }

    Nr. 1 läßt sich bei mir nicht compilieren und Nr. 2 bringt Linker Fehler "unresolved external ..."! Deine #includes habe ich drin. Was nun??? Wo steckt der Haken?

    Gruß

       K. H. Renders


    M. Thaddaeus

    Montag, 25. Januar 2016 12:51
  • Hallo,

    ja, stimmt. In den Projekteingenschaften muß unter Linker/Eingabe/Zusätzliche Abhängigkeiten noch HtmlHelp.lib angefügt werden. Dann sollte es funktionieren.

    Je nachdem, ob du Unicode oder MBCS verwendest, muß der Dateiname entsprechend übergeben werden.

    Da du MFC verwendest, kannst du eventuell auch CWinApp::HtmlHelp() verwenden, welche die API-Funktion kapselt.

    Gruß
    Heiko

    Montag, 25. Januar 2016 13:56
  • Hallo nochmal,

    für den Fall, dass der Aufruf der Hilfe noch nicht funktioniert, läßt sich auch eine Fehlermeldung ermitteln. Deshalb hier mal mein ganzes kleines Beispiel (MBCS-Variante):

    #include <windows.h>
    #include <htmlhelp.h>
    
    struct HH_LAST_ERROR
    {
    	int		cbStruct;
    	HRESULT	hr;
    	BSTR	description;
    };
    
    int WINAPI WinMain(HINSTANCE, HINSTANCE, char * cmdLine, int)
    {
    	HWND			hWnd;
    	DWORD			topicId = 0;
    	HH_LAST_ERROR	lastError;
    	char			* desc = 0;
    	int				len;
    
    	hWnd = HtmlHelp(0, "filename.chm", topicId ? HH_HELP_CONTEXT : HH_DISPLAY_TOPIC, topicId);
    	if (!hWnd)
    	{
    		memset(&lastError, 0, sizeof(HH_LAST_ERROR));
    		lastError.cbStruct = sizeof(HH_LAST_ERROR);
    
    		hWnd = HtmlHelp(0, 0, HH_GET_LAST_ERROR, (DWORD)&lastError);
    		if (hWnd && /* FAILED(lastError.hr) && */ lastError.description)
    		{
    			len = WideCharToMultiByte(CP_ACP, 0, lastError.description, -1, 0, 0, 0, 0);
    			if (len)
    			{
    				desc = new char [len];
    				if (desc)
    				{
    					*desc = '\0';
    					len = WideCharToMultiByte(CP_ACP, 0, lastError.description, -1, desc, len, 0, 0);
    				}
    			}
    			SysFreeString(lastError.description);
    		}
    		if (desc && *desc)
    			MessageBox(0, desc, "HtmlHelp", MB_OK);
    		else
    			MessageBox(0, "Die Hilfe konnte nicht aufgerufen werden.", "HtmlHelp", MB_OK);
    
    		if (desc) delete []desc;
    		return -1;
    	}
    	while (IsWindow(hWnd))
    		Sleep(500);
    	return 0;
    }

    Gruß
    Heiko

    Montag, 25. Januar 2016 14:08
  • Also ich habe mal das Beispiel von Heiko genommen. Letztich funktioniert es so wie er gesagt hatte. Er hat nur ein paar Schreibfehler drin gehabt mit der Variablen topicId. Rein von der Funktionalität ist aber alles korrekt

    #include <windows.h>
    #include <htmlhelp.h>
    #include <tchar.h>
    
    #pragma comment(lib, "htmlhelp.lib")
    
    int _cdecl _tmain (int argc, TCHAR *argv[])
    {        
    
    	DWORD topicId = 0;
    	HWND hWnd = HtmlHelp(0, _T("D:\\Verzeichnis\\noch einverzeichnis\\name_des_chmfiles.chm"), topicId ? HH_HELP_CONTEXT : HH_DISPLAY_TOPIC, topicId);
    
    	while (IsWindow(hWnd))
    		Sleep(500);
    }
    Wenn Du obigen code jetzt verwendest sollte das in einem Kommandozeilenprojekt problemlos funktionieren.


    Best regards

    Bordon

    Note: Posted code pieces may not have a good programming style and may not perfect. It is also possible that they do not work in all situations. Code pieces are only indended to explain something particualar.

    Dienstag, 26. Januar 2016 07:04
  • Guten Tag,

    hiermit möchte ich Heiko und Bordon herzlich für Ihre Mühe danken. Sie haben mich auf die richtige Färte gesetzt.

    Mit dem Beitrag von Bordon, welcher den Beitrag von Heiko ergänzte konnte ich tatsächlich meine Hilfe öffnem. Hierzu habe ich OnHelp überschrieben. Was mich allerdings störte, war die Tatsache, daß in der Hilfe von VC++ 2010 die Funktion HtmlHelp in der folgened Weise angegeben war:

         CWinApp::HtmlHelp() oder CWnd::HtmlHelp(), in beiden Fällen ist die Funktion:

          virtual void HtmlHelp(DWORD_PTR, UINT nCmd = 0x000F);

    Dann stieß ich auf die Funktion CWinApp::EnableHlmlHelp(); weche ich nun im Constructor der Hauptfunktion meiner Anwendung aufrufe:

    CRPwMgrApp::CRPwMgrApp()
    {
      EnableHtmlHelp();
      // Neustart-Manager unterstützen
        m_dwRestartManagerSupportFlags = AFX_RESTART_MANAGER_SUPPORT_RESTART;
    }

    und in der Funktionhatte ich bereits die folgenden Zeilen eingefügt:

    BOOL CRPMgrApp::InitInstance()
    {
      ...
      ...

      m_scHelpFilespec = m_scModulePath + m_scApplName + _T("Help.chm");
      strcpy_s(szHelpFilespec, MAX_PATH, m_scHelpFilespec.GetBuffer());
      if (HelpFile.GetStatus(m_scHelpFilespec.GetBuffer(), tStatus))
      {
        free((void*)m_pszHelpFilePath);
        m_pszHelpFilePath = _tcsdup(szHelpFilespec);
      }
      else
      {
         ...
         ...
      }

      scHelpFilespec.ReleaseBuffer();
      ...
      ...

    }

    und in meinem Dialog überschrieb ich die OnHelp Funktion:

    BEGIN_MESSAGE_MAP(CRPasswordManagerDlg, CDialogEx)
        ON_WM_SYSCOMMAND()
        ON_WM_PAINT()
        ON_WM_QUERYDRAGICON()
        ...
        ...
        ON_COMMAND(ID_HELP, &CRPwMgrDlg::OnHelp)
    END_MESSAGE_MAP()

    void CRPwMgrDlg::OnHelp()
    {
      theApp.HtmlHelp(1000);
    }

    ich löschte

    #include <windows.h>
    #include <htmlhelp.h>

    und

    #pragma comment(lib, "htmlhelp.lib")

    aus meinem Code und der Hifesystem Aufruf funktionierte sowohl mit F1 als auch über das Hilfe Menue eiwandfrei! So einfach ist das --- wenn man es weiß und wenn man eine MFC-Anwendung verwendet.

    Somit ist mein Problem gelöst! Mit nochmaligem Dank verbleibe ich

    mit freundlichen Grüßen
        K. H. Renders


    M. Thaddaeus

    Mittwoch, 27. Januar 2016 15:34