X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/c0ed460c2e7802793d591c84f3cfdbff159c5549..ba8c878f957da36c14879b747a2d54d7fe01baa8:/src/msw/stattext.cpp diff --git a/src/msw/stattext.cpp b/src/msw/stattext.cpp index 3c7f1df266..a3b52cac70 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,192 +16,272 @@ #pragma hdrstop #endif +#if wxUSE_STATTEXT + +#include "wx/stattext.h" + #ifndef WX_PRECOMP -#include "wx/app.h" + #include "wx/event.h" + #include "wx/app.h" + #include "wx/brush.h" + #include "wx/dcclient.h" + #include "wx/settings.h" #endif -#include "wx/stattext.h" #include "wx/msw/private.h" -#include -#if !USE_SHARED_LIBRARY +#if wxUSE_EXTENDED_RTTI +WX_DEFINE_FLAGS( wxStaticTextStyle ) + +wxBEGIN_FLAGS( wxStaticTextStyle ) + // new style border flags, we put them first to + // use them for streaming out + wxFLAGS_MEMBER(wxBORDER_SIMPLE) + wxFLAGS_MEMBER(wxBORDER_SUNKEN) + wxFLAGS_MEMBER(wxBORDER_DOUBLE) + wxFLAGS_MEMBER(wxBORDER_RAISED) + wxFLAGS_MEMBER(wxBORDER_STATIC) + wxFLAGS_MEMBER(wxBORDER_NONE) + + // old style border flags + wxFLAGS_MEMBER(wxSIMPLE_BORDER) + wxFLAGS_MEMBER(wxSUNKEN_BORDER) + wxFLAGS_MEMBER(wxDOUBLE_BORDER) + wxFLAGS_MEMBER(wxRAISED_BORDER) + wxFLAGS_MEMBER(wxSTATIC_BORDER) + wxFLAGS_MEMBER(wxBORDER) + + // standard window styles + wxFLAGS_MEMBER(wxTAB_TRAVERSAL) + wxFLAGS_MEMBER(wxCLIP_CHILDREN) + wxFLAGS_MEMBER(wxTRANSPARENT_WINDOW) + wxFLAGS_MEMBER(wxWANTS_CHARS) + wxFLAGS_MEMBER(wxFULL_REPAINT_ON_RESIZE) + wxFLAGS_MEMBER(wxALWAYS_SHOW_SB ) + wxFLAGS_MEMBER(wxVSCROLL) + wxFLAGS_MEMBER(wxHSCROLL) + + wxFLAGS_MEMBER(wxST_NO_AUTORESIZE) + wxFLAGS_MEMBER(wxALIGN_LEFT) + wxFLAGS_MEMBER(wxALIGN_RIGHT) + wxFLAGS_MEMBER(wxALIGN_CENTRE) + +wxEND_FLAGS( wxStaticTextStyle ) + +IMPLEMENT_DYNAMIC_CLASS_XTI(wxStaticText, wxControl,"wx/stattext.h") + +wxBEGIN_PROPERTIES_TABLE(wxStaticText) + wxPROPERTY( Label,wxString, SetLabel, GetLabel, wxString() , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) + wxPROPERTY_FLAGS( WindowStyle , wxStaticTextStyle , long , SetWindowStyleFlag , GetWindowStyleFlag , EMPTY_MACROVALUE, 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // style +wxEND_PROPERTIES_TABLE() + +wxBEGIN_HANDLERS_TABLE(wxStaticText) +wxEND_HANDLERS_TABLE() + +wxCONSTRUCTOR_6( wxStaticText , wxWindow* , Parent , wxWindowID , Id , wxString , Label , wxPoint , Position , wxSize , Size , long , WindowStyle ) +#else IMPLEMENT_DYNAMIC_CLASS(wxStaticText, wxControl) #endif -bool wxStaticText::Create(wxWindow *parent, wxWindowID id, - const wxString& label, - const wxPoint& pos, - const wxSize& size, - long style, - const wxString& name) +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), "STATIC", (const char *)label, - msStyle, - 0, 0, 0, 0, (HWND) parent->GetHWND(), (HMENU)m_windowId, - wxGetInstance(), NULL); - - wxCHECK_MSG( m_hWnd, FALSE, "Failed to create static ctrl" ); - -#if CTL3D -/* - if (!(GetParent()->GetWindowStyleFlag() & wxUSER_COLOURS)) - Ctl3dSubclassCtl(static_item); -*/ -#endif + if ( !CreateControl(parent, id, pos, size, style, wxDefaultValidator, name) ) + return false; - SubclassWin(m_hWnd); + if ( !MSWCreateControl(wxT("STATIC"), label, pos, size) ) + return false; - SetFont(parent->GetFont()); - SetSize(x, y, width, height); + return true; +} - return TRUE; +WXDWORD wxStaticText::MSWGetStyle(long style, WXDWORD *exstyle) const +{ + 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; + +#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) + { + // 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; + } +#endif // SS_ENDELLIPSIS + + msStyle |= SS_NOTIFY; + + return msStyle; } -void wxStaticText::SetSize(int x, int y, int width, int height, int sizeFlags) +wxSize wxStaticText::DoGetBestSize() 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; - - char buf[300]; - int current_width; - int cyf; - - ::GetWindowText((HWND) GetHWND(), buf, 300); - GetTextExtent(buf, ¤t_width, &cyf, NULL, NULL, & GetFont()); - - int ww, hh; - GetSize(&ww, &hh); - - // If we're prepared to use the existing width, then... - if (width == -1 && ((sizeFlags & wxSIZE_AUTO_WIDTH) != wxSIZE_AUTO_WIDTH)) - actualWidth = ww; - else if (width == -1) - { - int cx; - int cy; - wxGetCharSize(GetHWND(), &cx, &cy, & GetFont()); - actualWidth = (int)(current_width + cx) ; - } - - // If we're prepared to use the existing height, then... - if (height == -1 && ((sizeFlags & wxSIZE_AUTO_HEIGHT) != wxSIZE_AUTO_HEIGHT)) - actualHeight = hh; - else if (height == -1) - { - actualHeight = (int)(cyf) ; - } - - MoveWindow((HWND) GetHWND(), x1, y1, actualWidth, actualHeight, TRUE); + wxClientDC dc(wx_const_cast(wxStaticText *, this)); + wxFont font(GetFont()); + if (!font.Ok()) + 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__ + + // border takes extra space + // + // TODO: this is probably not wxStaticText-specific and should be moved + wxCoord border; + switch ( GetBorder() ) + { + case wxBORDER_STATIC: + case wxBORDER_SIMPLE: + border = 1; + break; + + case wxBORDER_SUNKEN: + border = 2; + break; + + case wxBORDER_RAISED: + case wxBORDER_DOUBLE: + border = 3; + break; + + default: + wxFAIL_MSG( _T("unknown border style") ); + // fall through + + case wxBORDER_NONE: + border = 0; + } + + widthTextMax += 2*border; + heightTextTotal += 2*border; + + wxSize best(widthTextMax, heightTextTotal); + CacheBestSize(best); + return best; } -void wxStaticText::SetLabel(const wxString& label) +void wxStaticText::DoSetSize(int x, int y, int w, int h, int sizeFlags) { - int w, h; - RECT rect; - - wxWindow *parent = GetParent(); - GetWindowRect((HWND) GetHWND(), &rect); - - // Since we now have the absolute screen coords, - // if there's a parent we must subtract its top left corner - POINT point; - point.x = rect.left; - point.y = rect.top; - if (parent) - { - ::ScreenToClient((HWND) parent->GetHWND(), &point); - } - - GetTextExtent(label, &w, &h, NULL, NULL, & GetFont()); - MoveWindow((HWND) GetHWND(), point.x, point.y, (int)(w + 10), (int)h, - TRUE); - SetWindowText((HWND) GetHWND(), (const char *)label); + // 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) ) + { + // we don't have SS_ENDELLIPSIS style: + // we need to (eventually) do ellipsization ourselves + UpdateLabel(); + } + //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(); } -WXHBRUSH wxStaticText::OnCtlColor(WXHDC pDC, WXHWND pWnd, WXUINT nCtlColor, - WXUINT message, WXWPARAM wParam, WXLPARAM lParam) +void wxStaticText::SetLabel(const wxString& label) { -/* -#if CTL3D - if ( m_useCtl3D ) - { - HBRUSH hbrush = Ctl3dCtlColorEx(message, wParam, lParam); - - if (hbrush != (HBRUSH) 0) - return hbrush; +#ifdef SS_ENDELLIPSIS + long styleReal = ::GetWindowLong(GetHwnd(), GWL_STYLE); + if ( HasFlag(wxST_ELLIPSIZE_END) && + wxGetOsVersion() == wxOS_WINDOWS_NT ) + { + // 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 // style not supported natively + { + styleReal &= ~SS_ENDELLIPSIS; + ::SetWindowLong(GetHwnd(), GWL_STYLE, styleReal); + } +#endif // SS_ENDELLIPSIS + + // this call will save the label in m_labelOrig and set it into this window + // (through wxWindow::SetLabel) + m_labelOrig = label; + +#ifdef SS_ENDELLIPSIS + if ( styleReal & SS_ENDELLIPSIS ) + DoSetLabel(RemoveMarkup(label)); else - return (HBRUSH)MSWDefWindowProc(message, wParam, lParam); - } -#endif -*/ - - if (GetParent()->GetTransparentBackground()) - SetBkMode((HDC) pDC, TRANSPARENT); - else - SetBkMode((HDC) pDC, OPAQUE); +#endif // SS_ENDELLIPSIS + DoSetLabel(GetEllipsizedLabelWithoutMarkup()); + + // 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); + } +} - ::SetBkColor((HDC) pDC, RGB(GetBackgroundColour().Red(), GetBackgroundColour().Green(), GetBackgroundColour().Blue())); - ::SetTextColor((HDC) pDC, RGB(GetForegroundColour().Red(), GetForegroundColour().Green(), GetForegroundColour().Blue())); +bool wxStaticText::SetFont(const wxFont& font) +{ + bool ret = wxControl::SetFont(font); + + // 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); + } + + 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