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:
@@ -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;
|
||||||
|
@@ -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;
|
||||||
}
|
}
|
||||||
|
@@ -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
|
||||||
|
Reference in New Issue
Block a user