show native-looking (with 3D shadow) help tooltips for context help, if possible, using wxCHMHelpController

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@39725 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin
2006-06-14 17:46:51 +00:00
parent 7cf41a5d66
commit 392c5133ff
3 changed files with 110 additions and 79 deletions

View File

@@ -20,7 +20,6 @@ class WXDLLEXPORT wxCHMHelpController : public wxHelpControllerBase
{ {
public: public:
wxCHMHelpController(wxWindow* parentWindow = NULL): wxHelpControllerBase(parentWindow) { } wxCHMHelpController(wxWindow* parentWindow = NULL): wxHelpControllerBase(parentWindow) { }
virtual ~wxCHMHelpController();
// Must call this to set the filename // Must call this to set the filename
virtual bool Initialize(const wxString& file); virtual bool Initialize(const wxString& file);
@@ -40,6 +39,11 @@ public:
wxString GetHelpFile() const { return m_helpFile; } wxString GetHelpFile() const { return m_helpFile; }
// helper of DisplayTextPopup(), also used in wxSimpleHelpProvider::ShowHelp
static bool ShowContextHelpPopup(const wxString& text,
const wxPoint& pos,
wxWindow *window);
protected: protected:
// Append extension if necessary. // Append extension if necessary.
wxString GetValidFilename(const wxString& file) const; wxString GetValidFilename(const wxString& file) const;

View File

@@ -34,6 +34,11 @@
#include "wx/module.h" #include "wx/module.h"
#include "wx/cshelp.h" #include "wx/cshelp.h"
#if wxUSE_MS_HTML_HELP
#include "wx/msw/helpchm.h" // for ShowContextHelpPopup
#include "wx/utils.h" // for wxGetMousePosition()
#endif
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// wxContextHelpEvtHandler private class // wxContextHelpEvtHandler private class
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@@ -378,29 +383,46 @@ void wxSimpleHelpProvider::RemoveHelp(wxWindowBase* window)
bool wxSimpleHelpProvider::ShowHelp(wxWindowBase *window) bool wxSimpleHelpProvider::ShowHelp(wxWindowBase *window)
{ {
#if wxUSE_TIPWINDOW #if wxUSE_MS_HTML_HELP || wxUSE_TIPWINDOW
static wxTipWindow* s_tipWindow = NULL;
if (s_tipWindow)
{
// Prevent s_tipWindow being nulled in OnIdle,
// thereby removing the chance for the window to be closed by ShowHelp
s_tipWindow->SetTipWindowPtr(NULL);
s_tipWindow->Close();
}
s_tipWindow = NULL;
const wxString text = GetHelpTextMaybeAtPoint(window); const wxString text = GetHelpTextMaybeAtPoint(window);
if ( !text.empty() ) if ( !text.empty() )
{ {
s_tipWindow = new wxTipWindow((wxWindow *)window, text, // use the native help popup style if it's available
100, &s_tipWindow); #if wxUSE_MS_HTML_HELP
if ( !wxCHMHelpController::ShowContextHelpPopup
(
text,
wxGetMousePosition(),
(wxWindow *)window
) )
#endif // wxUSE_MS_HTML_HELP
{
#if wxUSE_TIPWINDOW
static wxTipWindow* s_tipWindow = NULL;
if ( s_tipWindow )
{
// Prevent s_tipWindow being nulled in OnIdle, thereby removing
// the chance for the window to be closed by ShowHelp
s_tipWindow->SetTipWindowPtr(NULL);
s_tipWindow->Close();
}
s_tipWindow = new wxTipWindow((wxWindow *)window, text,
100, &s_tipWindow);
#else // !wxUSE_TIPWINDOW
// we tried wxCHMHelpController but it failed and we don't have
// wxTipWindow to fall back on, so
return false;
#endif // wxUSE_TIPWINDOW
}
return true; return true;
} }
#else #else // !wxUSE_MS_HTML_HELP && !wxUSE_TIPWINDOW
wxUnusedVar(window); wxUnusedVar(window);
#endif // wxUSE_TIPWINDOW #endif // wxUSE_MS_HTML_HELP || wxUSE_TIPWINDOW
return false; return false;
} }

View File

@@ -44,59 +44,58 @@
#define HTMLHELP_NAME wxT("HtmlHelpW") #define HTMLHELP_NAME wxT("HtmlHelpW")
#endif #endif
// dll symbol handle HTMLHELP GetHtmlHelpFunction()
static HTMLHELP gs_htmlHelp = 0;
static bool LoadHtmlHelpLibrary()
{ {
wxPluginLibrary *lib = wxPluginManager::LoadLibrary( _T("HHCTRL.OCX"), wxDL_DEFAULT | wxDL_VERBATIM ); static HTMLHELP s_htmlHelp = NULL;
if( !lib ) if ( !s_htmlHelp )
{ {
wxLogError(_("MS HTML Help functions are unavailable because the MS HTML Help library is not installed on this machine. Please install it.")); static wxDynamicLibrary s_dllHtmlHelp(_T("HHCTRL.OCX"), wxDL_VERBATIM);
return false;
}
else
{
gs_htmlHelp = (HTMLHELP)lib->GetSymbol( HTMLHELP_NAME );
if( !gs_htmlHelp ) if ( !s_dllHtmlHelp.IsLoaded() )
{ {
wxLogError(_("Failed to initialize MS HTML Help.")); wxLogError(_("MS HTML Help functions are unavailable because the MS HTML Help library is not installed on this machine. Please install it."));
}
lib->UnrefLib(); else
return false ; {
s_htmlHelp = (HTMLHELP)s_dllHtmlHelp.GetSymbol(HTMLHELP_NAME);
if ( !s_htmlHelp )
{
wxLogError(_("Failed to initialize MS HTML Help."));
}
} }
} }
return true; return s_htmlHelp;
} }
static void UnloadHtmlHelpLibrary() // find the window to use in HtmlHelp() call: use the given one by default but
// fall back to the top level app window and then the desktop if it's NULL
static HWND GetSuitableHWND(wxWindow *win)
{ {
if ( gs_htmlHelp ) if ( !win && wxTheApp )
{ win = wxTheApp->GetTopWindow();
if (wxPluginManager::UnloadLibrary( _T("HHCTRL.OCX") ))
gs_htmlHelp = 0; return win ? GetHwndOf(win) : ::GetDesktopWindow();
}
} }
static HWND GetSuitableHWND(wxCHMHelpController* controller) // wrap the real HtmlHelp() but just return false (and not crash) if it
// couldn't be loaded
//
// it also takes a wxWindow instead of HWND
static bool
CallHtmlHelpFunction(wxWindow *win, const wxChar *str, UINT uint, DWORD dword)
{ {
if (controller->GetParentWindow()) HTMLHELP htmlHelp = GetHtmlHelpFunction();
return (HWND) controller->GetParentWindow()->GetHWND();
else if (wxTheApp->GetTopWindow()) return htmlHelp && htmlHelp(GetSuitableHWND(win), str, uint, dword);
return (HWND) wxTheApp->GetTopWindow()->GetHWND();
else
return GetDesktopWindow();
} }
IMPLEMENT_DYNAMIC_CLASS(wxCHMHelpController, wxHelpControllerBase) IMPLEMENT_DYNAMIC_CLASS(wxCHMHelpController, wxHelpControllerBase)
bool wxCHMHelpController::Initialize(const wxString& filename) bool wxCHMHelpController::Initialize(const wxString& filename)
{ {
// warn on failure if ( !GetHtmlHelpFunction() )
if( !LoadHtmlHelpLibrary() )
return false; return false;
m_helpFile = filename; m_helpFile = filename;
@@ -112,40 +111,43 @@ bool wxCHMHelpController::LoadFile(const wxString& file)
bool wxCHMHelpController::DisplayContents() bool wxCHMHelpController::DisplayContents()
{ {
if (m_helpFile.IsEmpty()) return false; if (m_helpFile.IsEmpty())
return false;
wxString str = GetValidFilename(m_helpFile); wxString str = GetValidFilename(m_helpFile);
gs_htmlHelp(GetSuitableHWND(this), (const wxChar*) str, HH_DISPLAY_TOPIC, 0L); return CallHtmlHelpFunction(GetParentWindow(), str, HH_DISPLAY_TOPIC, 0L);
return true;
} }
// Use topic or HTML filename // Use topic or HTML filename
bool wxCHMHelpController::DisplaySection(const wxString& section) bool wxCHMHelpController::DisplaySection(const wxString& section)
{ {
if (m_helpFile.IsEmpty()) return false; if (m_helpFile.IsEmpty())
return false;
wxString str = GetValidFilename(m_helpFile); wxString str = GetValidFilename(m_helpFile);
// Is this an HTML file or a keyword? // Is this an HTML file or a keyword?
bool isFilename = (section.Find(wxT(".htm")) != wxNOT_FOUND); if ( section.Find(wxT(".htm")) != wxNOT_FOUND )
{
// interpret as a file name
return CallHtmlHelpFunction(GetParentWindow(), str, HH_DISPLAY_TOPIC,
wxPtrToUInt(section.c_str()));
}
if (isFilename) return KeywordSearch(section);
gs_htmlHelp(GetSuitableHWND(this), (const wxChar*) str, HH_DISPLAY_TOPIC, (DWORD) (const wxChar*) section);
else
KeywordSearch(section);
return true;
} }
// Use context number // Use context number
bool wxCHMHelpController::DisplaySection(int section) bool wxCHMHelpController::DisplaySection(int section)
{ {
if (m_helpFile.IsEmpty()) return false; if (m_helpFile.IsEmpty())
return false;
wxString str = GetValidFilename(m_helpFile); wxString str = GetValidFilename(m_helpFile);
gs_htmlHelp(GetSuitableHWND(this), (const wxChar*) str, HH_HELP_CONTEXT, (DWORD)section); return CallHtmlHelpFunction(GetParentWindow(), str, HH_HELP_CONTEXT,
return true; (DWORD)section);
} }
bool wxCHMHelpController::DisplayContextPopup(int contextId) bool wxCHMHelpController::DisplayContextPopup(int contextId)
@@ -169,11 +171,20 @@ bool wxCHMHelpController::DisplayContextPopup(int contextId)
popup.pszFont = NULL; popup.pszFont = NULL;
popup.pszText = NULL; popup.pszText = NULL;
gs_htmlHelp(GetSuitableHWND(this), (const wxChar*) str, HH_DISPLAY_TEXT_POPUP, (DWORD) & popup); return CallHtmlHelpFunction(GetParentWindow(), str, HH_DISPLAY_TEXT_POPUP,
return true; wxPtrToUInt(&popup));
} }
bool wxCHMHelpController::DisplayTextPopup(const wxString& text, const wxPoint& pos) bool
wxCHMHelpController::DisplayTextPopup(const wxString& text, const wxPoint& pos)
{
return ShowContextHelpPopup(text, pos, GetParentWindow());
}
/* static */
bool wxCHMHelpController::ShowContextHelpPopup(const wxString& text,
const wxPoint& pos,
wxWindow *window)
{ {
HH_POPUP popup; HH_POPUP popup;
popup.cbStruct = sizeof(popup); popup.cbStruct = sizeof(popup);
@@ -186,8 +197,8 @@ bool wxCHMHelpController::DisplayTextPopup(const wxString& text, const wxPoint&
popup.pszFont = NULL; popup.pszFont = NULL;
popup.pszText = (const wxChar*) text; popup.pszText = (const wxChar*) text;
gs_htmlHelp(GetSuitableHWND(this), NULL, HH_DISPLAY_TEXT_POPUP, (DWORD) & popup); return CallHtmlHelpFunction(window, NULL, HH_DISPLAY_TEXT_POPUP,
return true; wxPtrToUInt(&popup));
} }
bool wxCHMHelpController::DisplayBlock(long block) bool wxCHMHelpController::DisplayBlock(long block)
@@ -198,7 +209,8 @@ bool wxCHMHelpController::DisplayBlock(long block)
bool wxCHMHelpController::KeywordSearch(const wxString& k, bool wxCHMHelpController::KeywordSearch(const wxString& k,
wxHelpSearchMode WXUNUSED(mode)) wxHelpSearchMode WXUNUSED(mode))
{ {
if (m_helpFile.IsEmpty()) return false; if (m_helpFile.IsEmpty())
return false;
wxString str = GetValidFilename(m_helpFile); wxString str = GetValidFilename(m_helpFile);
@@ -212,15 +224,13 @@ bool wxCHMHelpController::KeywordSearch(const wxString& k,
link.pszWindow = NULL ; link.pszWindow = NULL ;
link.fIndexOnFail = TRUE ; link.fIndexOnFail = TRUE ;
gs_htmlHelp(GetSuitableHWND(this), (const wxChar*) str, HH_KEYWORD_LOOKUP, (DWORD)& link); return CallHtmlHelpFunction(GetParentWindow(), str, HH_KEYWORD_LOOKUP,
return true; wxPtrToUInt(&link));
} }
bool wxCHMHelpController::Quit() bool wxCHMHelpController::Quit()
{ {
gs_htmlHelp(GetSuitableHWND(this), 0, HH_CLOSE_ALL, 0L); return CallHtmlHelpFunction(GetParentWindow(), NULL, HH_CLOSE_ALL, 0L);
return true;
} }
// Append extension if necessary. // Append extension if necessary.
@@ -239,9 +249,4 @@ wxString wxCHMHelpController::GetValidFilename(const wxString& file) const
return fullName; return fullName;
} }
wxCHMHelpController::~wxCHMHelpController()
{
UnloadHtmlHelpLibrary();
}
#endif // wxUSE_HELP #endif // wxUSE_HELP