Add support for wxSTB_ELLIPSIZE_* and for wxSTB_SHOW_TIPS flags under wxMSW
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@60388 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -31,6 +31,7 @@
|
||||
#endif
|
||||
|
||||
#include "wx/msw/private.h"
|
||||
#include "wx/tooltip.h"
|
||||
#include <windowsx.h>
|
||||
|
||||
#if wxUSE_UXTHEME
|
||||
@@ -71,7 +72,7 @@ bool wxStatusBar::Create(wxWindow *parent,
|
||||
long style,
|
||||
const wxString& name)
|
||||
{
|
||||
wxCHECK_MSG( parent, false, wxT("status bar must have a parent") );
|
||||
wxCHECK_MSG( parent, false, "status bar must have a parent" );
|
||||
|
||||
SetName(name);
|
||||
SetWindowStyleFlag(style);
|
||||
@@ -167,11 +168,23 @@ bool wxStatusBar::SetFont(const wxFont& font)
|
||||
void wxStatusBar::SetFieldsCount(int nFields, const int *widths)
|
||||
{
|
||||
// this is a Windows limitation
|
||||
wxASSERT_MSG( (nFields > 0) && (nFields < 255), _T("too many fields") );
|
||||
wxASSERT_MSG( (nFields > 0) && (nFields < 255), "too many fields" );
|
||||
|
||||
wxStatusBarBase::SetFieldsCount(nFields, widths);
|
||||
|
||||
SetFieldsWidth();
|
||||
|
||||
// keep in synch also our m_tooltips array
|
||||
|
||||
// reset all current tooltips
|
||||
for (size_t i=0; i<m_tooltips.size(); i++)
|
||||
{
|
||||
delete m_tooltips[i];
|
||||
m_tooltips[i] = NULL;
|
||||
}
|
||||
|
||||
// shrink/expand the array:
|
||||
m_tooltips.resize(m_panes.GetCount(), NULL);
|
||||
}
|
||||
|
||||
void wxStatusBar::SetStatusWidths(int n, const int widths[])
|
||||
@@ -191,33 +204,42 @@ void wxStatusBar::SetFieldsWidth()
|
||||
|
||||
int extraWidth = aBorders[2]; // space between fields
|
||||
|
||||
|
||||
// distribute the available space (client width) among the various fields:
|
||||
|
||||
wxArrayInt widthsAbs =
|
||||
CalculateAbsWidths(GetClientSize().x - extraWidth*(m_panes.GetCount() - 1));
|
||||
|
||||
|
||||
// update the field widths in the native control:
|
||||
|
||||
int *pWidths = new int[m_panes.GetCount()];
|
||||
|
||||
int nCurPos = 0;
|
||||
for ( size_t i = 0; i < m_panes.GetCount(); i++ ) {
|
||||
for ( size_t i = 0; i < m_panes.GetCount(); i++ )
|
||||
{
|
||||
nCurPos += widthsAbs[i] + extraWidth;
|
||||
pWidths[i] = nCurPos;
|
||||
}
|
||||
|
||||
if ( !StatusBar_SetParts(GetHwnd(), m_panes.GetCount(), pWidths) ) {
|
||||
wxLogLastError(wxT("StatusBar_SetParts"));
|
||||
}
|
||||
if ( !StatusBar_SetParts(GetHwnd(), m_panes.GetCount(), pWidths) )
|
||||
wxLogLastError("StatusBar_SetParts");
|
||||
|
||||
delete [] pWidths;
|
||||
|
||||
|
||||
// FIXME: we may want to call UpdateFieldText() here since we may need to (de)ellipsize status texts
|
||||
}
|
||||
|
||||
void wxStatusBar::SetStatusText(const wxString& strText, int nField)
|
||||
{
|
||||
wxCHECK_RET( (nField >= 0) && ((size_t)nField < m_panes.GetCount()),
|
||||
_T("invalid statusbar field index") );
|
||||
"invalid statusbar field index" );
|
||||
|
||||
if ( strText == GetStatusText(nField) )
|
||||
{
|
||||
// don't call StatusBar_SetText() to avoid flicker
|
||||
return;
|
||||
// don't call StatusBar_SetText() to avoid flicker
|
||||
return;
|
||||
}
|
||||
|
||||
wxStatusBarBase::SetStatusText(strText, nField);
|
||||
@@ -256,18 +278,69 @@ void wxStatusBar::UpdateFieldText(int nField)
|
||||
else
|
||||
margin = 4;
|
||||
|
||||
// do we need to ellipsize this string?
|
||||
wxString ellipsizedStr =
|
||||
wxControl::Ellipsize(GetStatusText(nField), *m_pDC,
|
||||
GetLayoutDirection() == wxLayout_RightToLeft ? wxELLIPSIZE_START : wxELLIPSIZE_END,
|
||||
rc.GetWidth() - margin, // leave a small margin
|
||||
wxELLIPSIZE_EXPAND_TAB);
|
||||
int maxWidth = rc.GetWidth() - margin; // leave a small margin
|
||||
wxString text = GetStatusText(nField);
|
||||
|
||||
// Pass both field number and style. MSDN library doesn't mention
|
||||
// that nField and style have to be 'ORed'
|
||||
if ( !StatusBar_SetText(GetHwnd(), nField | style, ellipsizedStr.wx_str()) )
|
||||
// do we need to ellipsize this string?
|
||||
wxEllipsizeMode ellmode = (wxEllipsizeMode)-1;
|
||||
if (HasFlag(wxSTB_ELLIPSIZE_START)) ellmode = wxELLIPSIZE_START;
|
||||
else if (HasFlag(wxSTB_ELLIPSIZE_MIDDLE)) ellmode = wxELLIPSIZE_MIDDLE;
|
||||
else if (HasFlag(wxSTB_ELLIPSIZE_END)) ellmode = wxELLIPSIZE_END;
|
||||
|
||||
if (ellmode == (wxEllipsizeMode)-1)
|
||||
{
|
||||
wxLogLastError(wxT("StatusBar_SetText"));
|
||||
// if we have the wxSTB_SHOW_TIPS we must set the ellipsized flag even if
|
||||
// we don't ellipsize the text but just truncate it
|
||||
if (HasFlag(wxSTB_SHOW_TIPS))
|
||||
SetEllipsizedFlag(nField, m_pDC->GetTextExtent(text).GetWidth() > maxWidth);
|
||||
}
|
||||
else
|
||||
{
|
||||
text = wxControl::Ellipsize(text,
|
||||
*m_pDC,
|
||||
ellmode,
|
||||
maxWidth,
|
||||
wxELLIPSIZE_EXPAND_TAB);
|
||||
|
||||
// update the ellipsization status for this pane; this is used later to
|
||||
// decide whether a tooltip should be shown or not for this pane
|
||||
// (if we have wxSTB_SHOW_TIPS)
|
||||
SetEllipsizedFlag(nField, text != GetStatusText(nField));
|
||||
}
|
||||
|
||||
// Set the status text in the native control passing both field number and style.
|
||||
// NOTE: MSDN library doesn't mention that nField and style have to be 'ORed'
|
||||
if ( !StatusBar_SetText(GetHwnd(), nField | style, text.wx_str()) )
|
||||
wxLogLastError("StatusBar_SetText");
|
||||
|
||||
if (HasFlag(wxSTB_SHOW_TIPS))
|
||||
{
|
||||
wxASSERT(m_tooltips.size() == m_panes.GetCount());
|
||||
|
||||
if (m_tooltips[nField])
|
||||
{
|
||||
if (GetField(nField).IsEllipsized())
|
||||
{
|
||||
// update the rect of this tooltip:
|
||||
m_tooltips[nField]->SetRect(rc);
|
||||
|
||||
// update also the text:
|
||||
m_tooltips[nField]->SetTip(GetStatusText(nField));
|
||||
}
|
||||
else
|
||||
{
|
||||
// delete the tooltip associated with this pane; it's not needed anymore
|
||||
delete m_tooltips[nField];
|
||||
m_tooltips[nField] = NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// create a new tooltip for this pane if needed
|
||||
if (GetField(nField).IsEllipsized())
|
||||
m_tooltips[nField] = new wxToolTip(this, nField, GetStatusText(nField), rc);
|
||||
//else: leave m_tooltips[nField]==NULL
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -291,23 +364,21 @@ void wxStatusBar::SetMinHeight(int height)
|
||||
{
|
||||
SendMessage(GetHwnd(), SB_SETMINHEIGHT, height + 2*GetBorderY(), 0);
|
||||
|
||||
// have to send a (dummy) WM_SIZE to redraw it now
|
||||
// we have to send a (dummy) WM_SIZE to redraw it now
|
||||
SendMessage(GetHwnd(), WM_SIZE, 0, 0);
|
||||
}
|
||||
|
||||
bool wxStatusBar::GetFieldRect(int i, wxRect& rect) const
|
||||
{
|
||||
wxCHECK_MSG( (i >= 0) && ((size_t)i < m_panes.GetCount()), false,
|
||||
_T("invalid statusbar field index") );
|
||||
"invalid statusbar field index" );
|
||||
|
||||
RECT r;
|
||||
if ( !::SendMessage(GetHwnd(), SB_GETRECT, i, (LPARAM)&r) )
|
||||
{
|
||||
wxLogLastError(wxT("SendMessage(SB_GETRECT)"));
|
||||
}
|
||||
wxLogLastError("SendMessage(SB_GETRECT)");
|
||||
|
||||
#if wxUSE_UXTHEME
|
||||
wxUxThemeHandle theme((wxStatusBar *)this, L"Status"); // const_cast
|
||||
wxUxThemeHandle theme(const_cast<wxStatusBar*>(this), L"Status");
|
||||
if ( theme )
|
||||
{
|
||||
// by default Windows has a 2 pixel border to the right of the left
|
||||
@@ -428,14 +499,13 @@ void wxStatusBar::SetStatusStyles(int n, const int styles[])
|
||||
style = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
// The SB_SETTEXT message is both used to set the field's text as well as
|
||||
// the fields' styles. MSDN library doesn't mention
|
||||
// that nField and style have to be 'ORed'
|
||||
// the fields' styles.
|
||||
// NOTE: MSDN library doesn't mention that nField and style have to be 'ORed'
|
||||
wxString text = GetStatusText(i);
|
||||
if (!StatusBar_SetText(GetHwnd(), style | i, text.wx_str()))
|
||||
{
|
||||
wxLogLastError(wxT("StatusBar_SetText"));
|
||||
}
|
||||
wxLogLastError("StatusBar_SetText");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -483,7 +553,10 @@ wxStatusBar::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
|
||||
}
|
||||
#endif
|
||||
|
||||
if ( nMsg == WM_SIZE )
|
||||
bool needsEllipsization = HasFlag(wxSTB_ELLIPSIZE_START) ||
|
||||
HasFlag(wxSTB_ELLIPSIZE_MIDDLE) ||
|
||||
HasFlag(wxSTB_ELLIPSIZE_END);
|
||||
if ( nMsg == WM_SIZE && needsEllipsization )
|
||||
{
|
||||
for (int i=0; i<GetFieldsCount(); i++)
|
||||
UpdateFieldText(i);
|
||||
@@ -494,4 +567,47 @@ wxStatusBar::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam)
|
||||
return wxStatusBarBase::MSWWindowProc(nMsg, wParam, lParam);
|
||||
}
|
||||
|
||||
#if wxUSE_TOOLTIPS
|
||||
bool wxStatusBar::MSWProcessMessage(WXMSG* pMsg)
|
||||
{
|
||||
if ( HasFlag(wxSTB_SHOW_TIPS) )
|
||||
{
|
||||
// for a tooltip to be shown, we need to relay mouse events to it;
|
||||
// this is typically done by wxWindowMSW::MSWProcessMessage but only
|
||||
// if wxWindow::m_tooltip pointer is non-NULL.
|
||||
// Since wxStatusBar has multiple tooltips for a single HWND, it keeps
|
||||
// wxWindow::m_tooltip == NULL and then relays mouse events here:
|
||||
MSG *msg = (MSG *)pMsg;
|
||||
if ( msg->message == WM_MOUSEMOVE )
|
||||
wxToolTip::RelayEvent(pMsg);
|
||||
}
|
||||
|
||||
return wxWindow::MSWProcessMessage(pMsg);
|
||||
}
|
||||
|
||||
bool wxStatusBar::MSWOnNotify(int WXUNUSED(idCtrl), WXLPARAM lParam, WXLPARAM* WXUNUSED(result));
|
||||
{
|
||||
if ( HasFlag(wxSTB_SHOW_TIPS) )
|
||||
{
|
||||
// see comment in wxStatusBar::MSWProcessMessage for more info;
|
||||
// basically we need to override wxWindow::MSWOnNotify because
|
||||
// we have wxWindow::m_tooltip always NULL but we still use tooltips...
|
||||
|
||||
NMHDR* hdr = (NMHDR *)lParam;
|
||||
|
||||
wxString str;
|
||||
if (hdr->idFrom < m_tooltips.size() && m_tooltips[hdr->idFrom])
|
||||
str = m_tooltips[hdr->idFrom]->GetTip();
|
||||
|
||||
if ( HandleTooltipNotify(hdr->code, lParam, str))
|
||||
{
|
||||
// processed
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
#endif // wxUSE_TOOLTIPS
|
||||
|
||||
#endif // wxUSE_STATUSBAR && wxUSE_NATIVE_STATUSBAR
|
||||
|
Reference in New Issue
Block a user