]> git.saurik.com Git - wxWidgets.git/blob - src/msw/textmeasure.cpp
Fixed centering/right alignment of last line
[wxWidgets.git] / src / msw / textmeasure.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/msw/textmeasure.cpp
3 // Purpose: wxTextMeasure implementation for wxMSW
4 // Author: Manuel Martin
5 // Created: 2012-10-05
6 // RCS-ID: $Id:
7 // Copyright: (c) 1997-2012 wxWidgets team
8 // Licence: wxWindows licence
9 ///////////////////////////////////////////////////////////////////////////////
10
11 // ============================================================================
12 // declarations
13 // ============================================================================
14
15 // ----------------------------------------------------------------------------
16 // headers
17 // ----------------------------------------------------------------------------
18
19 // for compilers that support precompilation, includes "wx.h".
20 #include "wx/wxprec.h"
21
22 #ifdef __BORLANDC__
23 #pragma hdrstop
24 #endif
25
26 #include "wx/msw/private.h"
27
28 #ifndef WX_PRECOMP
29 #include "wx/window.h"
30 #include "wx/font.h"
31 #endif //WX_PRECOMP
32
33 #include "wx/private/textmeasure.h"
34
35 #include "wx/msw/dc.h"
36
37 // ============================================================================
38 // wxTextMeasure implementation
39 // ============================================================================
40
41 void wxTextMeasure::Init()
42 {
43 m_hdc = NULL;
44 m_hfontOld = NULL;
45
46 if ( m_dc )
47 {
48 wxClassInfo* const ci = m_dc->GetImpl()->GetClassInfo();
49
50 if ( ci->IsKindOf(wxCLASSINFO(wxMSWDCImpl)))
51 {
52 m_useDCImpl = false;
53 }
54 }
55 }
56
57 void wxTextMeasure::BeginMeasuring()
58 {
59 if ( m_dc )
60 {
61 m_hdc = m_dc->GetHDC();
62
63 // Non-native wxDC subclasses should override their DoGetTextExtent()
64 // and other methods.
65 wxASSERT_MSG( m_hdc, wxS("Must not be used with non-native wxDCs") );
66 }
67 else if ( m_win )
68 {
69 m_hdc = ::GetDC(GetHwndOf(m_win));
70 }
71
72 // We need to set the font if it's explicitly specified, of course, but
73 // also if we're associated with a window because the window HDC created
74 // above has the default font selected into it and not the font of the
75 // window.
76 if ( m_font || m_win )
77 m_hfontOld = (HFONT)::SelectObject(m_hdc, GetHfontOf(GetFont()));
78 }
79
80 void wxTextMeasure::EndMeasuring()
81 {
82 if ( m_hfontOld )
83 {
84 ::SelectObject(m_hdc, m_hfontOld);
85 m_hfontOld = NULL;
86 }
87
88 if ( m_win )
89 ::ReleaseDC(GetHwndOf(m_win), m_hdc);
90 //else: our HDC belongs to m_dc, don't touch it
91
92 m_hdc = NULL;
93 }
94
95 // Notice we don't check here the font. It is supposed to be OK before the call.
96 void wxTextMeasure::DoGetTextExtent(const wxString& string,
97 wxCoord *width,
98 wxCoord *height,
99 wxCoord *descent,
100 wxCoord *externalLeading)
101 {
102 SIZE sizeRect;
103 const size_t len = string.length();
104 if ( !::GetTextExtentPoint32(m_hdc, string.t_str(), len, &sizeRect) )
105 {
106 wxLogLastError(wxT("GetTextExtentPoint32()"));
107 }
108
109 #if !defined(_WIN32_WCE) || (_WIN32_WCE >= 400)
110 // the result computed by GetTextExtentPoint32() may be too small as it
111 // accounts for under/overhang of the first/last character while we want
112 // just the bounding rect for this string so adjust the width as needed
113 // (using API not available in 2002 SDKs of WinCE)
114 if ( len > 0 )
115 {
116 ABC widthABC;
117 const wxChar chFirst = *string.begin();
118 if ( ::GetCharABCWidths(m_hdc, chFirst, chFirst, &widthABC) )
119 {
120 if ( widthABC.abcA < 0 )
121 sizeRect.cx -= widthABC.abcA;
122
123 if ( len > 1 )
124 {
125 const wxChar chLast = *string.rbegin();
126 ::GetCharABCWidths(m_hdc, chLast, chLast, &widthABC);
127 }
128 //else: we already have the width of the last character
129
130 if ( widthABC.abcC < 0 )
131 sizeRect.cx -= widthABC.abcC;
132 }
133 //else: GetCharABCWidths() failed, not a TrueType font?
134 }
135 #endif // !defined(_WIN32_WCE) || (_WIN32_WCE >= 400)
136
137 *width = sizeRect.cx;
138 *height = sizeRect.cy;
139
140 if ( descent || externalLeading )
141 {
142 TEXTMETRIC tm;
143 ::GetTextMetrics(m_hdc, &tm);
144 if ( descent )
145 *descent = tm.tmDescent;
146 if ( externalLeading )
147 *externalLeading = tm.tmExternalLeading;
148 }
149 }
150
151 bool wxTextMeasure::DoGetPartialTextExtents(const wxString& text,
152 wxArrayInt& widths,
153 double scaleX)
154 {
155 if ( !m_hdc )
156 return wxTextMeasureBase::DoGetPartialTextExtents(text, widths, scaleX);
157
158 static int maxLenText = -1;
159 static int maxWidth = -1;
160
161 if (maxLenText == -1)
162 {
163 // Win9x and WinNT+ have different limits
164 int version = wxGetOsVersion();
165 maxLenText = version == wxOS_WINDOWS_NT ? 65535 : 8192;
166 maxWidth = version == wxOS_WINDOWS_NT ? INT_MAX : 32767;
167 }
168
169 int len = text.length();
170 if ( len > maxLenText )
171 len = maxLenText;
172
173 int fit = 0;
174 SIZE sz = {0,0};
175 if ( !::GetTextExtentExPoint(m_hdc,
176 text.t_str(), // string to check
177 len,
178 maxWidth,
179 &fit, // [out] count of chars
180 // that will fit
181 &widths[0], // array to fill
182 &sz) )
183 {
184 wxLogLastError(wxT("GetTextExtentExPoint"));
185
186 return false;
187 }
188
189 return true;
190 }