X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/92049cd473c81fbce934e71796b2d841d5e605fa..71185527a05c27931cd65359c1b23f0018b646ed:/src/msw/stattext.cpp diff --git a/src/msw/stattext.cpp b/src/msw/stattext.cpp index da9906d988..f7ced7f939 100644 --- a/src/msw/stattext.cpp +++ b/src/msw/stattext.cpp @@ -1,18 +1,14 @@ ///////////////////////////////////////////////////////////////////////////// -// Name: stattext.cpp +// Name: src/msw/stattext.cpp // Purpose: wxStaticText // Author: Julian Smart // Modified by: // Created: 04/01/98 // RCS-ID: $Id$ -// Copyright: (c) Julian Smart and Markus Holzem -// Licence: wxWindows license +// Copyright: (c) Julian Smart +// Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// -#ifdef __GNUG__ -#pragma implementation "stattext.h" -#endif - // For compilers that support precompilation, includes "wx.h". #include "wx/wxprec.h" @@ -20,198 +16,219 @@ #pragma hdrstop #endif -#ifndef WX_PRECOMP -#include "wx/event.h" -#include "wx/app.h" -#include "wx/brush.h" -#endif +#if wxUSE_STATTEXT #include "wx/stattext.h" -#include "wx/msw/private.h" -#include -#if !USE_SHARED_LIBRARY -IMPLEMENT_DYNAMIC_CLASS(wxStaticText, wxControl) +#ifndef WX_PRECOMP + #include "wx/event.h" + #include "wx/app.h" + #include "wx/brush.h" + #include "wx/dcclient.h" + #include "wx/settings.h" #endif -bool wxStaticText::Create(wxWindow *parent, wxWindowID id, - const wxString& label, - const wxPoint& pos, - const wxSize& size, - long style, - const wxString& name) +#include "wx/msw/private.h" + +bool wxStaticText::Create(wxWindow *parent, + wxWindowID id, + const wxString& label, + const wxPoint& pos, + const wxSize& size, + long style, + const wxString& name) { - SetName(name); - if (parent) parent->AddChild(this); - - SetBackgroundColour(parent->GetBackgroundColour()) ; - SetForegroundColour(parent->GetForegroundColour()) ; - - if ( id == -1 ) - m_windowId = (int)NewControlId(); - else - m_windowId = id; - - int x = pos.x; - int y = pos.y; - int width = size.x; - int height = size.y; - - m_windowStyle = style; - - long msStyle = WS_CHILD|WS_VISIBLE; - if (m_windowStyle & wxALIGN_CENTRE) - msStyle |= SS_CENTER; - else if (m_windowStyle & wxALIGN_RIGHT) - msStyle |= SS_RIGHT; - else - msStyle |= SS_LEFT; - - // Even with extended styles, need to combine with WS_BORDER - // for them to look right. - if ( wxStyleHasBorder(m_windowStyle) ) - msStyle |= WS_BORDER; - - m_hWnd = (WXHWND)::CreateWindowEx(MakeExtendedStyle(m_windowStyle), _T("STATIC"), (const wxChar *)label, - msStyle, - 0, 0, 0, 0, (HWND) parent->GetHWND(), (HMENU)m_windowId, - wxGetInstance(), NULL); - - wxCHECK_MSG( m_hWnd, FALSE, _T("Failed to create static ctrl") ); - -#if wxUSE_CTL3D -/* - if (!(GetParent()->GetWindowStyleFlag() & wxUSER_COLOURS)) - Ctl3dSubclassCtl(static_item); -*/ -#endif + if ( !CreateControl(parent, id, pos, size, style, wxDefaultValidator, name) ) + return false; + + if ( !MSWCreateControl(wxT("STATIC"), wxEmptyString, pos, size) ) + return false; + + // we set the label here and not through MSWCreateControl() because we + // need to do many operation on it for ellipsization&markup support + SetLabel(label); - SubclassWin(m_hWnd); + // as we didn't pass the correct label to MSWCreateControl(), it didn't set + // the initial size correctly -- do it now + InvalidateBestSize(); + SetInitialSize(size); - SetFont(parent->GetFont()); - SetSize(x, y, width, height); + // NOTE: if the label contains ampersand characters which are interpreted as + // accelerators, they will be rendered (at least on WinXP) only if the + // static text is placed inside a window class which correctly handles + // focusing by TAB traversal (e.g. wxPanel). - return TRUE; + return true; } -void wxStaticText::DoSetSize(int x, int y, int width, int height, int sizeFlags) +WXDWORD wxStaticText::MSWGetStyle(long style, WXDWORD *exstyle) const { - int currentX, currentY; - GetPosition(¤tX, ¤tY); - - int x1 = x; - int y1 = y; - - if (x == -1 || (sizeFlags & wxSIZE_ALLOW_MINUS_ONE)) - x1 = currentX; - if (y == -1 || (sizeFlags & wxSIZE_ALLOW_MINUS_ONE)) - y1 = currentY; - - AdjustForParentClientOrigin(x1, y1, sizeFlags); - - int actualWidth = width; - int actualHeight = height; - - wxString text(wxGetWindowText(GetHWND())); - - int widthTextMax = 0, widthLine, - heightTextTotal = 0, heightLine; - - wxString curLine; - for ( const char *pc = text; ; pc++ ) { - if ( *pc == '\n' || *pc == '\0' ) { - GetTextExtent(curLine, &widthLine, &heightLine); - if ( widthLine > widthTextMax ) - widthTextMax = widthLine; - heightTextTotal += heightLine; - - if ( *pc == '\n' ) { - curLine.Empty(); - } - else { - // the end of string - break; - } - } - else { - curLine += *pc; - } - } - - int ww, hh; - GetSize(&ww, &hh); + WXDWORD msStyle = wxControl::MSWGetStyle(style, exstyle); + + // translate the alignment flags to the Windows ones + // + // note that both wxALIGN_LEFT and SS_LEFT are equal to 0 so we shouldn't + // test for them using & operator + if ( style & wxALIGN_CENTRE ) + msStyle |= SS_CENTER; + else if ( style & wxALIGN_RIGHT ) + msStyle |= SS_RIGHT; + else + msStyle |= SS_LEFT; - // If we're prepared to use the existing width, then... - if (width == -1 && ((sizeFlags & wxSIZE_AUTO_WIDTH) != wxSIZE_AUTO_WIDTH)) +#ifdef SS_ENDELLIPSIS + // this style is necessary to receive mouse events + // Win NT and later have the SS_ENDELLIPSIS style which is useful to us: + if (wxGetOsVersion() == wxOS_WINDOWS_NT) { - actualWidth = ww; + // for now, add the SS_ENDELLIPSIS style if wxST_ELLIPSIZE_END is given; + // we may need to remove it later in ::SetLabel() if the given label + // has newlines + if ( style & wxST_ELLIPSIZE_END ) + msStyle |= SS_ENDELLIPSIS; } - else if (width == -1) +#endif // SS_ENDELLIPSIS + + msStyle |= SS_NOTIFY; + + return msStyle; +} + +wxSize wxStaticText::DoGetBestClientSize() const +{ + wxClientDC dc(const_cast(this)); + wxFont font(GetFont()); + if (!font.IsOk()) + font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT); + + dc.SetFont(font); + + wxCoord widthTextMax, heightTextTotal; + dc.GetMultiLineTextExtent(GetLabelText(), &widthTextMax, &heightTextTotal); + +#ifdef __WXWINCE__ + if ( widthTextMax ) + widthTextMax += 2; +#endif // __WXWINCE__ + + // It looks like the static control needs "slightly" more vertical space + // than the character height and while the text isn't actually truncated if + // we use just the minimal height, it is positioned differently than when + // the control has enough space and this result in the text in edit and + // static controls not being aligned when the controls themselves are. As + // this is something you really should be able to count on, increase the + // space allocated for the control so that the base lines do align + // correctly. Notice that while the above is true at least for the single + // line controls, there doesn't seem to do any harm to allocate two extra + // pixels in multi-line case neither so do it always for consistency. + // + // I still have no idea why exactly is this needed nor why should we use 2 + // and not something else. This seems to work in all the configurations + // though (small/large fonts, different OS versions, ...) so just hard code + // it for now. If we need something better later it might be worth looking + // at the height of the text control returned by ::GetComboBoxInfo() as it + // seems to be the "minimal acceptable" height. + heightTextTotal += 2; + + return wxSize(widthTextMax, heightTextTotal); +} + +void wxStaticText::DoSetSize(int x, int y, int w, int h, int sizeFlags) +{ + // note: we first need to set the size and _then_ call UpdateLabel + wxStaticTextBase::DoSetSize(x, y, w, h, sizeFlags); + +#ifdef SS_ENDELLIPSIS + // do we need to ellipsize the contents? + long styleReal = ::GetWindowLong(GetHwnd(), GWL_STYLE); + if ( !(styleReal & SS_ENDELLIPSIS) ) { - actualWidth = widthTextMax; + // we don't have SS_ENDELLIPSIS style: + // we need to (eventually) do ellipsization ourselves + UpdateLabel(); } - - // If we're prepared to use the existing height, then... - if (height == -1 && ((sizeFlags & wxSIZE_AUTO_HEIGHT) != wxSIZE_AUTO_HEIGHT)) + //else: we don't or the OS will do it for us +#endif // SS_ENDELLIPSIS + + // we need to refresh the window after changing its size as the standard + // control doesn't always update itself properly + Refresh(); +} + +void wxStaticText::SetLabel(const wxString& label) +{ +#ifdef SS_ENDELLIPSIS + long styleReal = ::GetWindowLong(GetHwnd(), GWL_STYLE); + if ( HasFlag(wxST_ELLIPSIZE_END) && + wxGetOsVersion() == wxOS_WINDOWS_NT ) { - actualHeight = hh; + // adding SS_ENDELLIPSIS or SS_ENDELLIPSIS "disables" the correct + // newline handling in static texts: the newlines in the labels are + // shown as square. Thus we don't use it even on newer OS when + // the static label contains a newline. + if ( label.Contains(wxT('\n')) ) + styleReal &= ~SS_ENDELLIPSIS; + else + styleReal |= SS_ENDELLIPSIS; + + ::SetWindowLong(GetHwnd(), GWL_STYLE, styleReal); } - else if (height == -1) + else // style not supported natively { - actualHeight = heightTextTotal; + styleReal &= ~SS_ENDELLIPSIS; + ::SetWindowLong(GetHwnd(), GWL_STYLE, styleReal); } - - MoveWindow(GetHwnd(), x1, y1, actualWidth, actualHeight, TRUE); -} +#endif // SS_ENDELLIPSIS -void wxStaticText::SetLabel(const wxString& label) -{ - SetWindowText(GetHwnd(), label); + // save the label in m_labelOrig with both the markup (if any) and + // the mnemonics characters (if any) + m_labelOrig = label; - DoSetSize(-1, -1, -1, -1, wxSIZE_AUTO_WIDTH | wxSIZE_AUTO_HEIGHT); +#ifdef SS_ENDELLIPSIS + if ( styleReal & SS_ENDELLIPSIS ) + DoSetLabel(GetLabel()); + else +#endif // SS_ENDELLIPSIS + DoSetLabel(GetEllipsizedLabel()); + + // adjust the size of the window to fit to the label unless autoresizing is + // disabled + if ( !HasFlag(wxST_NO_AUTORESIZE) && + !IsEllipsized() ) // if ellipsize is ON, then we don't want to get resized! + { + InvalidateBestSize(); + DoSetSize(wxDefaultCoord, wxDefaultCoord, wxDefaultCoord, wxDefaultCoord, + wxSIZE_AUTO_WIDTH | wxSIZE_AUTO_HEIGHT); + } } -WXHBRUSH wxStaticText::OnCtlColor(WXHDC pDC, WXHWND pWnd, WXUINT nCtlColor, - WXUINT message, WXWPARAM wParam, WXLPARAM lParam) +bool wxStaticText::SetFont(const wxFont& font) { -/* -#if wxUSE_CTL3D - if ( m_useCtl3D ) - { - HBRUSH hbrush = Ctl3dCtlColorEx(message, wParam, lParam); - - if (hbrush != (HBRUSH) 0) - return hbrush; - else - return (HBRUSH)MSWDefWindowProc(message, wParam, lParam); - } -#endif -*/ + bool ret = wxControl::SetFont(font); - if (GetParent()->GetTransparentBackground()) - SetBkMode((HDC) pDC, TRANSPARENT); - else - SetBkMode((HDC) pDC, OPAQUE); + // adjust the size of the window to fit to the label unless autoresizing is + // disabled + if ( !HasFlag(wxST_NO_AUTORESIZE) ) + { + InvalidateBestSize(); + DoSetSize(wxDefaultCoord, wxDefaultCoord, wxDefaultCoord, wxDefaultCoord, + wxSIZE_AUTO_WIDTH | wxSIZE_AUTO_HEIGHT); + } - ::SetBkColor((HDC) pDC, RGB(GetBackgroundColour().Red(), GetBackgroundColour().Green(), GetBackgroundColour().Blue())); - ::SetTextColor((HDC) pDC, RGB(GetForegroundColour().Red(), GetForegroundColour().Green(), GetForegroundColour().Blue())); + return ret; +} - wxBrush *backgroundBrush = wxTheBrushList->FindOrCreateBrush(GetBackgroundColour(), wxSOLID); +// for wxST_ELLIPSIZE_* support: - // Note that this will be cleaned up in wxApp::OnIdle, if backgroundBrush - // has a zero usage count. -// backgroundBrush->RealizeResource(); - return (WXHBRUSH) backgroundBrush->GetResourceHandle(); +wxString wxStaticText::DoGetLabel() const +{ + return wxGetWindowText(GetHwnd()); } -long wxStaticText::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam) +void wxStaticText::DoSetLabel(const wxString& str) { - // Ensure that static items get messages. Some controls don't like this - // message to be intercepted (e.g. RichEdit), hence the tests. - if (nMsg == WM_NCHITTEST) - return (long)HTCLIENT; - - return wxWindow::MSWWindowProc(nMsg, wParam, lParam); + SetWindowText(GetHwnd(), str.c_str()); } +#endif // wxUSE_STATTEXT