Update all windows associated with the tooltip when it changes in wxMSW.
Although the tooltip was initially correctly set for all windows associated with it, it was only updated for the main one if its text changed later. This resulted in leaving the old tooltip for the composite controls such as wxComboBox or controls with sub-windows such as wxRadioBox. Fix this by storing all windows associated with the tooltip (for space efficiency, only allocate the array if necessary however as it will be empty in the majority of cases) and apply SetTip() to all of them, not just the main one. Closes #12659. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@66053 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
parent
2d64bab703
commit
0ce0f1e9eb
@ -16,6 +16,7 @@
|
||||
#include "wx/gdicmn.h"
|
||||
|
||||
class WXDLLIMPEXP_FWD_CORE wxWindow;
|
||||
class wxToolTipOtherWindows;
|
||||
|
||||
class WXDLLIMPEXP_CORE wxToolTip : public wxObject
|
||||
{
|
||||
@ -64,11 +65,23 @@ public:
|
||||
// remove any tooltip from the window
|
||||
static void Remove(WXHWND hwnd, unsigned int id, const wxRect& rc);
|
||||
|
||||
// the rect we're associated with
|
||||
// Set the rectangle we're associated with. This rectangle is only used for
|
||||
// the main window, not any sub-windows added with Add() so in general it
|
||||
// makes sense to use it for tooltips associated with a single window only.
|
||||
void SetRect(const wxRect& rc);
|
||||
const wxRect& GetRect() const { return m_rect; }
|
||||
|
||||
private:
|
||||
// Adds a window other than our main m_window to this tooltip.
|
||||
void DoAddOtherWindow(WXHWND hWnd);
|
||||
|
||||
// Perform the specified operation for the given window only.
|
||||
void DoSetTip(WXHWND hWnd);
|
||||
void DoRemove(WXHWND hWnd);
|
||||
|
||||
// Call the given function for all windows we're associated with.
|
||||
void DoForAllWindows(void (wxToolTip::*func)(WXHWND));
|
||||
|
||||
|
||||
// the one and only one tooltip control we use - never access it directly
|
||||
// but use GetToolTipCtrl() which will create it when needed
|
||||
static WXHWND ms_hwndTT;
|
||||
@ -83,7 +96,8 @@ private:
|
||||
void Remove();
|
||||
|
||||
wxString m_text; // tooltip text
|
||||
wxWindow* m_window; // window we're associated with
|
||||
wxWindow* m_window; // main window we're associated with
|
||||
wxToolTipOtherWindows *m_others; // other windows associated with it or NULL
|
||||
wxRect m_rect; // the rect of the window for which this tooltip is shown
|
||||
// (or a rect with width/height == 0 to show it for the entire window)
|
||||
unsigned int m_id; // the id of this tooltip (ignored when m_rect width/height is 0)
|
||||
|
@ -34,6 +34,7 @@
|
||||
#endif
|
||||
|
||||
#include "wx/tokenzr.h"
|
||||
#include "wx/vector.h"
|
||||
#include "wx/msw/private.h"
|
||||
|
||||
#ifndef TTTOOLINFO_V1_SIZE
|
||||
@ -75,6 +76,12 @@ static WNDPROC gs_wndprocToolTip = (WNDPROC)NULL;
|
||||
// private classes
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// This is simply a wrapper for vector<HWND> but defined as a class to hide the
|
||||
// details from the public header.
|
||||
class wxToolTipOtherWindows : public wxVector<WXHWND>
|
||||
{
|
||||
};
|
||||
|
||||
// a wrapper around TOOLINFO Win32 structure
|
||||
#ifdef __VISUALC__
|
||||
#pragma warning( disable : 4097 ) // we inherit from a typedef - so what?
|
||||
@ -308,6 +315,7 @@ wxToolTip::wxToolTip(const wxString &tip)
|
||||
: m_text(tip)
|
||||
{
|
||||
m_window = NULL;
|
||||
m_others = NULL;
|
||||
|
||||
// make sure m_rect.IsEmpty() == true
|
||||
m_rect.SetWidth(0);
|
||||
@ -321,6 +329,7 @@ wxToolTip::wxToolTip(wxWindow* win, unsigned int id, const wxString &tip, const
|
||||
: m_text(tip), m_rect(rc), m_id(id)
|
||||
{
|
||||
m_window = NULL;
|
||||
m_others = NULL;
|
||||
|
||||
SetWindow(win);
|
||||
}
|
||||
@ -330,6 +339,8 @@ wxToolTip::~wxToolTip()
|
||||
// the tooltip has to be removed before deleting. Otherwise, if it is visible
|
||||
// while being deleted, there will be a delay before it goes away.
|
||||
Remove();
|
||||
|
||||
delete m_others;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -344,16 +355,36 @@ void wxToolTip::Remove(WXHWND hWnd, unsigned int id, const wxRect& rc)
|
||||
(void)SendTooltipMessage(GetToolTipCtrl(), TTM_DELTOOL, &ti);
|
||||
}
|
||||
|
||||
void wxToolTip::Remove()
|
||||
void wxToolTip::DoRemove(WXHWND hWnd)
|
||||
{
|
||||
// remove this tool from the tooltip control
|
||||
if ( m_window )
|
||||
if ( hWnd == m_window->GetHWND() )
|
||||
{
|
||||
Remove(m_window->GetHWND(), m_id, m_rect);
|
||||
// Remove the tooltip from the main window.
|
||||
Remove(hWnd, m_id, m_rect);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Not really sure what to pass to remove in this case...
|
||||
Remove(hWnd, 0, wxRect());
|
||||
}
|
||||
}
|
||||
|
||||
void wxToolTip::Remove()
|
||||
{
|
||||
DoForAllWindows(&wxToolTip::DoRemove);
|
||||
}
|
||||
|
||||
void wxToolTip::Add(WXHWND hWnd)
|
||||
{
|
||||
if ( !m_others )
|
||||
m_others = new wxToolTipOtherWindows;
|
||||
|
||||
m_others->push_back(hWnd);
|
||||
|
||||
DoAddOtherWindow(hWnd);
|
||||
}
|
||||
|
||||
void wxToolTip::DoAddOtherWindow(WXHWND hWnd)
|
||||
{
|
||||
HWND hwnd = (HWND)hWnd;
|
||||
|
||||
@ -486,7 +517,7 @@ void wxToolTip::SetWindow(wxWindow *win)
|
||||
HWND hwnd = GetDlgItem(GetHwndOf(m_window), id);
|
||||
if ( !hwnd )
|
||||
{
|
||||
// may be it's a child of parent of the control, in fact?
|
||||
// maybe it's a child of parent of the control, in fact?
|
||||
// (radiobuttons are subcontrols, i.e. children of the radiobox
|
||||
// for wxWidgets but are its siblings at Windows level)
|
||||
hwnd = GetDlgItem(GetHwndOf(m_window->GetParent()), id);
|
||||
@ -516,19 +547,43 @@ void wxToolTip::SetTip(const wxString& tip)
|
||||
{
|
||||
m_text = tip;
|
||||
|
||||
if ( m_window )
|
||||
DoForAllWindows(&wxToolTip::DoSetTip);
|
||||
}
|
||||
|
||||
void wxToolTip::DoSetTip(WXHWND hWnd)
|
||||
{
|
||||
// update the tip text shown by the control
|
||||
wxToolInfo ti((HWND)hWnd, m_id, m_rect);
|
||||
|
||||
// for some reason, changing the tooltip text directly results in
|
||||
// repaint of the controls under it, see #10520 -- but this doesn't
|
||||
// happen if we reset it first
|
||||
ti.lpszText = const_cast<wxChar *>(wxT(""));
|
||||
(void)SendTooltipMessage(GetToolTipCtrl(), TTM_UPDATETIPTEXT, &ti);
|
||||
|
||||
ti.lpszText = const_cast<wxChar *>(m_text.wx_str());
|
||||
(void)SendTooltipMessage(GetToolTipCtrl(), TTM_UPDATETIPTEXT, &ti);
|
||||
}
|
||||
|
||||
void wxToolTip::DoForAllWindows(void (wxToolTip::*func)(WXHWND))
|
||||
{
|
||||
if ( !m_window )
|
||||
{
|
||||
// update the tip text shown by the control
|
||||
wxToolInfo ti(GetHwndOf(m_window), m_id, m_rect);
|
||||
wxASSERT_MSG( !m_others,
|
||||
wxS("Can't have other windows without the main one.") );
|
||||
return;
|
||||
}
|
||||
|
||||
// for some reason, changing the tooltip text directly results in
|
||||
// repaint of the controls under it, see #10520 -- but this doesn't
|
||||
// happen if we reset it first
|
||||
ti.lpszText = const_cast<wxChar *>(wxT(""));
|
||||
(void)SendTooltipMessage(GetToolTipCtrl(), TTM_UPDATETIPTEXT, &ti);
|
||||
(this->*func)(m_window->GetHWND());
|
||||
|
||||
ti.lpszText = const_cast<wxChar *>(m_text.wx_str());
|
||||
(void)SendTooltipMessage(GetToolTipCtrl(), TTM_UPDATETIPTEXT, &ti);
|
||||
if ( m_others )
|
||||
{
|
||||
for ( wxToolTipOtherWindows::const_iterator it = m_others->begin();
|
||||
it != m_others->end();
|
||||
++it )
|
||||
{
|
||||
(this->*func)(*it);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user