]> git.saurik.com Git - wxWidgets.git/blob - src/msw/pen.cpp
docking hint bug fix
[wxWidgets.git] / src / msw / pen.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/msw/pen.cpp
3 // Purpose: wxPen
4 // Author: Julian Smart
5 // Modified by:
6 // Created: 04/01/98
7 // RCS-ID: $Id$
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 // For compilers that support precompilation, includes "wx.h".
13 #include "wx/wxprec.h"
14
15 #ifdef __BORLANDC__
16 #pragma hdrstop
17 #endif
18
19 #include "wx/pen.h"
20
21 #ifndef WX_PRECOMP
22 #include <stdio.h>
23 #include "wx/list.h"
24 #include "wx/utils.h"
25 #include "wx/app.h"
26 #endif
27
28 #include "wx/msw/private.h"
29
30 static int wx2msPenStyle(int wx_style);
31
32 IMPLEMENT_DYNAMIC_CLASS(wxPen, wxGDIObject)
33
34 wxPenRefData::wxPenRefData()
35 {
36 m_style = wxSOLID;
37 m_width = 1;
38 m_join = wxJOIN_ROUND ;
39 m_cap = wxCAP_ROUND ;
40 m_nbDash = 0 ;
41 m_dash = (wxDash*)NULL;
42 m_hPen = 0;
43 }
44
45 wxPenRefData::wxPenRefData(const wxPenRefData& data)
46 :wxGDIRefData()
47 {
48 m_style = data.m_style;
49 m_width = data.m_width;
50 m_join = data.m_join;
51 m_cap = data.m_cap;
52 m_nbDash = data.m_nbDash;
53 m_dash = data.m_dash;
54 m_colour = data.m_colour;
55 m_hPen = 0;
56 }
57
58 wxPenRefData::~wxPenRefData()
59 {
60 if ( m_hPen )
61 ::DeleteObject((HPEN) m_hPen);
62 }
63
64 // Pens
65
66 wxPen::wxPen()
67 {
68 }
69
70 wxPen::~wxPen()
71 {
72 }
73
74 // Should implement Create
75 wxPen::wxPen(const wxColour& col, int Width, int Style)
76 {
77 m_refData = new wxPenRefData;
78
79 M_PENDATA->m_colour = col;
80 // M_PENDATA->m_stipple = NULL;
81 M_PENDATA->m_width = Width;
82 M_PENDATA->m_style = Style;
83 M_PENDATA->m_join = wxJOIN_ROUND ;
84 M_PENDATA->m_cap = wxCAP_ROUND ;
85 M_PENDATA->m_nbDash = 0 ;
86 M_PENDATA->m_dash = (wxDash*)NULL;
87 M_PENDATA->m_hPen = 0 ;
88
89 RealizeResource();
90 }
91
92 wxPen::wxPen(const wxBitmap& stipple, int Width)
93 {
94 m_refData = new wxPenRefData;
95
96 // M_PENDATA->m_colour = col;
97 M_PENDATA->m_stipple = stipple;
98 M_PENDATA->m_width = Width;
99 M_PENDATA->m_style = wxSTIPPLE;
100 M_PENDATA->m_join = wxJOIN_ROUND ;
101 M_PENDATA->m_cap = wxCAP_ROUND ;
102 M_PENDATA->m_nbDash = 0 ;
103 M_PENDATA->m_dash = (wxDash*)NULL;
104 M_PENDATA->m_hPen = 0 ;
105
106 RealizeResource();
107 }
108
109 bool wxPen::RealizeResource()
110 {
111 if ( !M_PENDATA || M_PENDATA->m_hPen )
112 return false;
113
114 if (M_PENDATA->m_style==wxTRANSPARENT)
115 {
116 M_PENDATA->m_hPen = (WXHPEN) ::GetStockObject(NULL_PEN);
117 return true;
118 }
119
120 static const int os = wxGetOsVersion();
121 COLORREF ms_colour = M_PENDATA->m_colour.GetPixel();
122
123 // Join style, Cap style, Pen Stippling
124 #if !defined(__WXMICROWIN__) && !defined(__WXWINCE__)
125 // Only NT can display dashed or dotted lines with width > 1
126 if ( os != wxOS_WINDOWS_NT &&
127 (M_PENDATA->m_style == wxDOT ||
128 M_PENDATA->m_style == wxLONG_DASH ||
129 M_PENDATA->m_style == wxSHORT_DASH ||
130 M_PENDATA->m_style == wxDOT_DASH ||
131 M_PENDATA->m_style == wxUSER_DASH) &&
132 M_PENDATA->m_width > 1 )
133 {
134 M_PENDATA->m_width = 1;
135 }
136
137 if (M_PENDATA->m_join==wxJOIN_ROUND &&
138 M_PENDATA->m_cap==wxCAP_ROUND &&
139 M_PENDATA->m_style!=wxUSER_DASH &&
140 M_PENDATA->m_style!=wxSTIPPLE &&
141 M_PENDATA->m_width <= 1)
142 {
143 M_PENDATA->m_hPen =
144 (WXHPEN) CreatePen( wx2msPenStyle(M_PENDATA->m_style),
145 M_PENDATA->m_width,
146 ms_colour );
147 }
148 else
149 {
150 DWORD ms_style = PS_GEOMETRIC | wx2msPenStyle(M_PENDATA->m_style);
151
152 switch(M_PENDATA->m_join)
153 {
154 case wxJOIN_BEVEL: ms_style |= PS_JOIN_BEVEL; break;
155 case wxJOIN_MITER: ms_style |= PS_JOIN_MITER; break;
156 default:
157 case wxJOIN_ROUND: ms_style |= PS_JOIN_ROUND; break;
158 }
159
160 switch(M_PENDATA->m_cap)
161 {
162 case wxCAP_PROJECTING: ms_style |= PS_ENDCAP_SQUARE; break;
163 case wxCAP_BUTT: ms_style |= PS_ENDCAP_FLAT; break;
164 default:
165 case wxCAP_ROUND: ms_style |= PS_ENDCAP_ROUND; break;
166 }
167
168 LOGBRUSH logb;
169
170 switch(M_PENDATA->m_style)
171 {
172 case wxSTIPPLE:
173 logb.lbStyle = BS_PATTERN ;
174 if (M_PENDATA->m_stipple.Ok())
175 logb.lbHatch = (LONG)M_PENDATA->m_stipple.GetHBITMAP();
176 else
177 logb.lbHatch = (LONG)0;
178 break;
179 case wxBDIAGONAL_HATCH:
180 logb.lbStyle = BS_HATCHED;
181 logb.lbHatch = HS_BDIAGONAL;
182 break;
183 case wxCROSSDIAG_HATCH:
184 logb.lbStyle = BS_HATCHED;
185 logb.lbHatch = HS_DIAGCROSS;
186 break;
187 case wxFDIAGONAL_HATCH:
188 logb.lbStyle = BS_HATCHED;
189 logb.lbHatch = HS_FDIAGONAL;
190 break;
191 case wxCROSS_HATCH:
192 logb.lbStyle = BS_HATCHED;
193 logb.lbHatch = HS_CROSS;
194 break;
195 case wxHORIZONTAL_HATCH:
196 logb.lbStyle = BS_HATCHED;
197 logb.lbHatch = HS_HORIZONTAL;
198 break;
199 case wxVERTICAL_HATCH:
200 logb.lbStyle = BS_HATCHED;
201 logb.lbHatch = HS_VERTICAL;
202 break;
203 default:
204 logb.lbStyle = BS_SOLID;
205 #ifdef __WXDEBUG__
206 // this should be unnecessary (it's unused) but suppresses the Purify
207 // messages about uninitialized memory read
208 logb.lbHatch = 0;
209 #endif
210 break;
211 }
212
213 logb.lbColor = ms_colour;
214
215 wxMSWDash *real_dash;
216 if (M_PENDATA->m_style==wxUSER_DASH && M_PENDATA->m_nbDash && M_PENDATA->m_dash)
217 {
218 real_dash = new wxMSWDash[M_PENDATA->m_nbDash];
219 int rw = M_PENDATA->m_width > 1 ? M_PENDATA->m_width : 1;
220 for ( int i = 0; i < M_PENDATA->m_nbDash; i++ )
221 real_dash[i] = M_PENDATA->m_dash[i] * rw;
222 }
223 else
224 {
225 real_dash = (wxMSWDash*)NULL;
226 }
227
228 M_PENDATA->m_hPen =
229 (WXHPEN) ExtCreatePen( ms_style,
230 M_PENDATA->m_width,
231 &logb,
232 M_PENDATA->m_style == wxUSER_DASH
233 ? M_PENDATA->m_nbDash
234 : 0,
235 (LPDWORD)real_dash );
236
237 delete [] real_dash;
238 }
239 #else // WinCE
240 M_PENDATA->m_hPen =
241 (WXHPEN) CreatePen( wx2msPenStyle(M_PENDATA->m_style),
242 M_PENDATA->m_width,
243 ms_colour );
244 #endif // !WinCE/WinCE
245
246 return true;
247 }
248
249 WXHANDLE wxPen::GetResourceHandle() const
250 {
251 if ( !M_PENDATA )
252 return 0;
253 else
254 return (WXHANDLE)M_PENDATA->m_hPen;
255 }
256
257 bool wxPen::FreeResource(bool WXUNUSED(force))
258 {
259 if (M_PENDATA && (M_PENDATA->m_hPen != 0))
260 {
261 DeleteObject((HPEN) M_PENDATA->m_hPen);
262 M_PENDATA->m_hPen = 0;
263 return true;
264 }
265 else return false;
266 }
267
268 bool wxPen::IsFree() const
269 {
270 return (M_PENDATA && M_PENDATA->m_hPen == 0);
271 }
272
273 void wxPen::Unshare()
274 {
275 // Don't change shared data
276 if (!m_refData)
277 {
278 m_refData = new wxPenRefData();
279 }
280 else
281 {
282 wxPenRefData* ref = new wxPenRefData(*(wxPenRefData*)m_refData);
283 UnRef();
284 m_refData = ref;
285 }
286 }
287
288 void wxPen::SetColour(const wxColour& col)
289 {
290 Unshare();
291
292 M_PENDATA->m_colour = col;
293
294 RealizeResource();
295 }
296
297 void wxPen::SetColour(unsigned char r, unsigned char g, unsigned char b)
298 {
299 Unshare();
300
301 M_PENDATA->m_colour.Set(r, g, b);
302
303 RealizeResource();
304 }
305
306 void wxPen::SetWidth(int Width)
307 {
308 Unshare();
309
310 M_PENDATA->m_width = Width;
311
312 RealizeResource();
313 }
314
315 void wxPen::SetStyle(int Style)
316 {
317 Unshare();
318
319 M_PENDATA->m_style = Style;
320
321 RealizeResource();
322 }
323
324 void wxPen::SetStipple(const wxBitmap& Stipple)
325 {
326 Unshare();
327
328 M_PENDATA->m_stipple = Stipple;
329 M_PENDATA->m_style = wxSTIPPLE;
330
331 RealizeResource();
332 }
333
334 void wxPen::SetDashes(int nb_dashes, const wxDash *Dash)
335 {
336 Unshare();
337
338 M_PENDATA->m_nbDash = nb_dashes;
339 M_PENDATA->m_dash = (wxDash *)Dash;
340
341 RealizeResource();
342 }
343
344 void wxPen::SetJoin(int Join)
345 {
346 Unshare();
347
348 M_PENDATA->m_join = Join;
349
350 RealizeResource();
351 }
352
353 void wxPen::SetCap(int Cap)
354 {
355 Unshare();
356
357 M_PENDATA->m_cap = Cap;
358
359 RealizeResource();
360 }
361
362 int wx2msPenStyle(int wx_style)
363 {
364 #if !defined(__WXMICROWIN__) && !defined(__WXWINCE__)
365 switch (wx_style)
366 {
367 case wxDOT:
368 return PS_DOT;
369
370 case wxDOT_DASH:
371 return PS_DASHDOT;
372
373 case wxSHORT_DASH:
374 case wxLONG_DASH:
375 return PS_DASH;
376
377 case wxTRANSPARENT:
378 return PS_NULL;
379
380 case wxUSER_DASH:
381 return PS_USERSTYLE;
382 }
383 #else
384 wxUnusedVar(wx_style);
385 #endif
386 return PS_SOLID;
387 }