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