]> git.saurik.com Git - wxWidgets.git/blob - src/msw/pen.cpp
no message
[wxWidgets.git] / src / msw / pen.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: 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 and Markus Holzem
9 // Licence: wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
11
12 #ifdef __GNUG__
13 #pragma implementation "pen.h"
14 #endif
15
16 // For compilers that support precompilation, includes "wx.h".
17 #include "wx/wxprec.h"
18
19 #ifdef __BORLANDC__
20 #pragma hdrstop
21 #endif
22
23 #ifndef WX_PRECOMP
24 #include <stdio.h>
25 #include "wx/setup.h"
26 #include "wx/list.h"
27 #include "wx/utils.h"
28 #include "wx/app.h"
29 #include "wx/pen.h"
30 #endif
31
32 #include "wx/msw/private.h"
33 #include "assert.h"
34
35 #if !USE_SHARED_LIBRARIES
36 IMPLEMENT_DYNAMIC_CLASS(wxPen, wxGDIObject)
37 #endif
38
39 wxPenRefData::wxPenRefData(void)
40 {
41 m_style = wxSOLID;
42 m_width = 1;
43 m_join = wxJOIN_ROUND ;
44 m_cap = wxCAP_ROUND ;
45 m_nbDash = 0 ;
46 m_dash = 0 ;
47 m_hPen = 0;
48 }
49
50 wxPenRefData::wxPenRefData(const wxPenRefData& data)
51 {
52 m_style = data.m_style;
53 m_width = data.m_width;
54 m_join = data.m_join;
55 m_cap = data.m_cap;
56 m_nbDash = data.m_nbDash;
57 m_dash = data.m_dash;
58 m_colour = data.m_colour;
59 m_hPen = 0;
60 }
61
62 wxPenRefData::~wxPenRefData(void)
63 {
64 if ( m_hPen )
65 ::DeleteObject((HPEN) m_hPen);
66 }
67
68 // Pens
69
70 wxPen::wxPen(void)
71 {
72 if ( wxThePenList )
73 wxThePenList->AddPen(this);
74 }
75
76 wxPen::~wxPen()
77 {
78 if (wxThePenList)
79 wxThePenList->RemovePen(this);
80 }
81
82 // Should implement Create
83 wxPen::wxPen(const wxColour& col, int Width, int Style)
84 {
85 m_refData = new wxPenRefData;
86
87 M_PENDATA->m_colour = col;
88 // M_PENDATA->m_stipple = NULL;
89 M_PENDATA->m_width = Width;
90 M_PENDATA->m_style = Style;
91 M_PENDATA->m_join = wxJOIN_ROUND ;
92 M_PENDATA->m_cap = wxCAP_ROUND ;
93 M_PENDATA->m_nbDash = 0 ;
94 M_PENDATA->m_dash = 0 ;
95 M_PENDATA->m_hPen = 0 ;
96
97 #ifndef __WIN32__
98 // In Windows, only a pen of width = 1 can be dotted or dashed!
99 if ((Style == wxDOT) || (Style == wxLONG_DASH) ||
100 (Style == wxSHORT_DASH) || (Style == wxDOT_DASH) ||
101 (Style == wxUSER_DASH))
102 M_PENDATA->m_width = 1;
103 #else
104 /***
105 DWORD vers = GetVersion() ;
106 WORD high = HIWORD(vers) ; // high bit=0 for NT, 1 for Win32s
107 // Win32s doesn't support wide dashed pens
108
109 if ((high&0x8000)!=0)
110 ***/
111 if (wxGetOsVersion()==wxWIN32S)
112 {
113 // In Windows, only a pen of width = 1 can be dotted or dashed!
114 if ((Style == wxDOT) || (Style == wxLONG_DASH) ||
115 (Style == wxSHORT_DASH) || (Style == wxDOT_DASH) ||
116 (Style == wxUSER_DASH))
117 M_PENDATA->m_width = 1;
118 }
119 #endif
120 RealizeResource();
121
122 if ( wxThePenList )
123 wxThePenList->AddPen(this);
124 }
125
126 wxPen::wxPen(const wxBitmap& stipple, int Width)
127 {
128 m_refData = new wxPenRefData;
129
130 // M_PENDATA->m_colour = col;
131 M_PENDATA->m_stipple = stipple;
132 M_PENDATA->m_width = Width;
133 M_PENDATA->m_style = wxSTIPPLE;
134 M_PENDATA->m_join = wxJOIN_ROUND ;
135 M_PENDATA->m_cap = wxCAP_ROUND ;
136 M_PENDATA->m_nbDash = 0 ;
137 M_PENDATA->m_dash = 0 ;
138 M_PENDATA->m_hPen = 0 ;
139
140 RealizeResource();
141
142 if ( wxThePenList )
143 wxThePenList->AddPen(this);
144 }
145
146 wxPen::wxPen(const wxString& col, int Width, int Style)
147 {
148 m_refData = new wxPenRefData;
149
150 M_PENDATA->m_colour = col;
151 // M_PENDATA->m_stipple = NULL ;
152 M_PENDATA->m_width = Width;
153 M_PENDATA->m_style = Style;
154 M_PENDATA->m_join = wxJOIN_ROUND ;
155 M_PENDATA->m_cap = wxCAP_ROUND ;
156 M_PENDATA->m_nbDash = 0 ;
157 M_PENDATA->m_dash = 0 ;
158 M_PENDATA->m_hPen = 0 ;
159
160 RealizeResource();
161
162 if ( wxThePenList )
163 wxThePenList->AddPen(this);
164 }
165
166 bool wxPen::RealizeResource(void)
167 {
168 if (M_PENDATA && (M_PENDATA->m_hPen == 0))
169 {
170 if (M_PENDATA->m_style==wxTRANSPARENT)
171 {
172 M_PENDATA->m_hPen = (WXHPEN) ::GetStockObject(NULL_PEN);
173 return TRUE;
174 }
175
176 COLORREF ms_colour = 0 ;
177 ms_colour = M_PENDATA->m_colour.GetPixel() ;
178
179 // Join style, Cap style, Pen Stippling only on Win32.
180 // Currently no time to find equivalent on Win3.1, sorry
181 // [if such equiv exist!!]
182 #ifdef __WIN32__
183 if (M_PENDATA->m_join==wxJOIN_ROUND &&
184 M_PENDATA->m_cap==wxCAP_ROUND &&
185 M_PENDATA->m_style!=wxUSER_DASH &&
186 M_PENDATA->m_style!=wxSTIPPLE &&
187 M_PENDATA->m_width <= 1
188 )
189 M_PENDATA->m_hPen = (WXHPEN) CreatePen(wx2msPenStyle(M_PENDATA->m_style), M_PENDATA->m_width, ms_colour);
190 else
191 {
192 DWORD ms_style = PS_GEOMETRIC|wx2msPenStyle(M_PENDATA->m_style) ;
193
194 LOGBRUSH logb ;
195
196 switch(M_PENDATA->m_join)
197 {
198 case wxJOIN_BEVEL: ms_style |= PS_JOIN_BEVEL ; break ;
199 case wxJOIN_MITER: ms_style |= PS_JOIN_MITER ; break ;
200 default:
201 case wxJOIN_ROUND: ms_style |= PS_JOIN_ROUND ; break ;
202 }
203
204 switch(M_PENDATA->m_cap)
205 {
206 case wxCAP_PROJECTING: ms_style |= PS_ENDCAP_SQUARE ; break ;
207 case wxCAP_BUTT: ms_style |= PS_ENDCAP_FLAT ; break ;
208 default:
209 case wxCAP_ROUND: ms_style |= PS_ENDCAP_ROUND ; break ;
210 }
211
212 switch(M_PENDATA->m_style)
213 {
214 case wxSTIPPLE:
215 logb.lbStyle = BS_PATTERN ;
216 if (M_PENDATA->m_stipple.Ok())
217 logb.lbHatch = (LONG)M_PENDATA->m_stipple.GetHBITMAP() ;
218 else
219 logb.lbHatch = (LONG)0 ;
220 break ;
221 case wxBDIAGONAL_HATCH:
222 logb.lbStyle = BS_HATCHED ;
223 logb.lbHatch = HS_BDIAGONAL ;
224 break ;
225 case wxCROSSDIAG_HATCH:
226 logb.lbStyle = BS_HATCHED ;
227 logb.lbHatch = HS_DIAGCROSS ;
228 break ;
229 case wxFDIAGONAL_HATCH:
230 logb.lbStyle = BS_HATCHED ;
231 logb.lbHatch = HS_FDIAGONAL ;
232 break ;
233 case wxCROSS_HATCH:
234 logb.lbStyle = BS_HATCHED ;
235 logb.lbHatch = HS_CROSS ;
236 break ;
237 case wxHORIZONTAL_HATCH:
238 logb.lbStyle = BS_HATCHED ;
239 logb.lbHatch = HS_HORIZONTAL ;
240 break ;
241 case wxVERTICAL_HATCH:
242 logb.lbStyle = BS_HATCHED ;
243 logb.lbHatch = HS_VERTICAL ;
244 break ;
245 default:
246 logb.lbStyle = BS_SOLID ;
247 break ;
248 }
249 logb.lbColor = ms_colour ;
250 wxDash *real_dash ;
251 if (M_PENDATA->m_style==wxUSER_DASH && M_PENDATA->m_nbDash && M_PENDATA->m_dash)
252 {
253 real_dash = new wxDash[M_PENDATA->m_nbDash] ;
254 int i;
255 for (i=0;i<M_PENDATA->m_nbDash;i++)
256 real_dash[i] = M_PENDATA->m_dash[i] * M_PENDATA->m_width ;
257 }
258 else
259 real_dash = 0 ;
260
261 // Win32s doesn't have ExtCreatePen function...
262 if (wxGetOsVersion()==wxWINDOWS_NT || wxGetOsVersion()==wxWIN95)
263 M_PENDATA->m_hPen = (WXHPEN) ExtCreatePen(ms_style,M_PENDATA->m_width,&logb,
264 M_PENDATA->m_style==wxUSER_DASH ? M_PENDATA->m_nbDash:0, (const DWORD *)real_dash);
265 else
266 M_PENDATA->m_hPen = (WXHPEN) CreatePen(wx2msPenStyle(M_PENDATA->m_style), M_PENDATA->m_width, ms_colour);
267
268 if (real_dash)
269 delete [] real_dash ;
270 }
271 #else
272 M_PENDATA->m_hPen = (WXHPEN) CreatePen(wx2msPenStyle(M_PENDATA->m_style), M_PENDATA->m_width, ms_colour);
273 #endif
274 #ifdef WXDEBUG_CREATE
275 if (M_PENDATA->m_hPen==0)
276 wxError("Cannot create pen","Internal error") ;
277 #endif
278 return TRUE;
279 }
280 return FALSE;
281 }
282
283 WXHANDLE wxPen::GetResourceHandle(void)
284 {
285 if ( !M_PENDATA )
286 return 0;
287 else
288 return (WXHANDLE)M_PENDATA->m_hPen;
289 }
290
291 bool wxPen::FreeResource(bool force)
292 {
293 if (M_PENDATA && (M_PENDATA->m_hPen != 0))
294 {
295 DeleteObject((HPEN) M_PENDATA->m_hPen);
296 M_PENDATA->m_hPen = 0;
297 return TRUE;
298 }
299 else return FALSE;
300 }
301
302 bool wxPen::IsFree(void)
303 {
304 return (M_PENDATA && M_PENDATA->m_hPen == 0);
305 }
306
307 void wxPen::Unshare()
308 {
309 // Don't change shared data
310 if (!m_refData)
311 {
312 m_refData = new wxPenRefData();
313 }
314 else
315 {
316 wxPenRefData* ref = new wxPenRefData(*(wxPenRefData*)m_refData);
317 UnRef();
318 m_refData = ref;
319 }
320 }
321
322 void wxPen::SetColour(const wxColour& col)
323 {
324 Unshare();
325
326 M_PENDATA->m_colour = col;
327
328 RealizeResource();
329 }
330
331 void wxPen::SetColour(const wxString& col)
332 {
333 Unshare();
334
335 M_PENDATA->m_colour = col;
336
337 RealizeResource();
338 }
339
340 void wxPen::SetColour(const unsigned char r, const unsigned char g, const unsigned char b)
341 {
342 Unshare();
343
344 M_PENDATA->m_colour.Set(r, g, b);
345
346 RealizeResource();
347 }
348
349 void wxPen::SetWidth(int Width)
350 {
351 Unshare();
352
353 M_PENDATA->m_width = Width;
354
355 RealizeResource();
356 }
357
358 void wxPen::SetStyle(int Style)
359 {
360 Unshare();
361
362 M_PENDATA->m_style = Style;
363
364 RealizeResource();
365 }
366
367 void wxPen::SetStipple(const wxBitmap& Stipple)
368 {
369 Unshare();
370
371 M_PENDATA->m_stipple = Stipple;
372 M_PENDATA->m_style = wxSTIPPLE;
373
374 RealizeResource();
375 }
376
377 void wxPen::SetDashes(int nb_dashes, const wxDash *Dash)
378 {
379 Unshare();
380
381 M_PENDATA->m_nbDash = nb_dashes;
382 M_PENDATA->m_dash = (wxDash *)Dash;
383
384 RealizeResource();
385 }
386
387 void wxPen::SetJoin(int Join)
388 {
389 Unshare();
390
391 M_PENDATA->m_join = Join;
392
393 RealizeResource();
394 }
395
396 void wxPen::SetCap(int Cap)
397 {
398 Unshare();
399
400 M_PENDATA->m_cap = Cap;
401
402 RealizeResource();
403 }
404
405 int wx2msPenStyle(int wx_style)
406 {
407 int cstyle;
408 /***
409 #ifdef __WIN32__
410 DWORD vers = GetVersion() ;
411 WORD high = HIWORD(vers) ; // high bit=0 for NT, 1 for Win32s
412 #endif
413 ***/
414 switch (wx_style)
415 {
416 case wxDOT:
417 cstyle = PS_DOT;
418 break;
419 case wxSHORT_DASH:
420 case wxLONG_DASH:
421 cstyle = PS_DASH;
422 break;
423 case wxTRANSPARENT:
424 cstyle = PS_NULL;
425 break;
426 case wxUSER_DASH:
427 // User dash style not supported on Win3.1, sorry...
428 #ifdef __WIN32__
429 // Win32s doesn't have PS_USERSTYLE
430 /***
431 if ((high&0x8000)==0)
432 ***/
433 if (wxGetOsVersion()==wxWINDOWS_NT)
434 cstyle = PS_USERSTYLE ;
435 else
436 cstyle = PS_DOT ; // We must make a choice... This is mine!
437 #else
438 cstyle = PS_DASH ;
439 #endif
440 break ;
441 case wxSOLID:
442 default:
443 cstyle = PS_SOLID;
444 break;
445 }
446 return cstyle;
447 }
448