]>
git.saurik.com Git - wxWidgets.git/blob - src/msw/pen.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/msw/pen.cpp
4 // Author: Julian Smart
5 // Modified by: Vadim Zeitlin: refactored wxPen code to wxPenRefData
8 // Copyright: (c) Julian Smart
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
14 // ============================================================================
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
20 // For compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
30 #include "wx/bitmap.h"
34 #include "wx/msw/private.h"
36 #define M_PENDATA ((wxPenRefData*)m_refData)
38 // Win32 has ExtCreatePen() but WinCE doesn't
39 #if !defined(__WXMICROWIN__) && !defined(__WXWINCE__)
40 #define wxHAVE_EXT_CREATE_PEN
43 // ----------------------------------------------------------------------------
44 // wxPenRefData: contains information about an HPEN and its handle
45 // ----------------------------------------------------------------------------
47 class WXDLLEXPORT wxPenRefData
: public wxGDIRefData
54 wxPenRefData(const wxPenRefData
& data
);
55 wxPenRefData(const wxColour
& col
, int width
, int style
);
56 wxPenRefData(const wxBitmap
& stipple
, int width
);
57 virtual ~wxPenRefData();
59 bool operator==(const wxPenRefData
& data
) const
61 // we intentionally don't compare m_hPen fields here
62 return m_style
== data
.m_style
&&
63 m_width
== data
.m_width
&&
64 m_join
== data
.m_join
&&
65 m_cap
== data
.m_cap
&&
66 m_colour
== data
.m_colour
&&
67 (m_style
!= wxSTIPPLE
|| m_stipple
.IsSameAs(data
.m_stipple
)) &&
68 (m_style
!= wxUSER_DASH
||
69 (m_nbDash
== data
.m_nbDash
&&
70 memcmp(m_dash
, data
.m_dash
, m_nbDash
*sizeof(wxDash
)) == 0));
74 // accessors and setters
75 // ---------------------
77 wxColour
& GetColour() const { return wx_const_cast(wxColour
&, m_colour
); }
78 int GetWidth() const { return m_width
; }
79 int GetStyle() const { return m_style
; }
80 int GetJoin() const { return m_join
; }
81 int GetCap() const { return m_cap
; }
82 wxDash
* GetDash() const { return m_dash
; }
83 int GetDashCount() const { return m_nbDash
; }
84 wxBitmap
* GetStipple() const { return wx_const_cast(wxBitmap
*, &m_stipple
); }
86 void SetColour(const wxColour
& col
) { Free(); m_colour
= col
; }
87 void SetWidth(int width
) { Free(); m_width
= width
; }
88 void SetStyle(int style
) { Free(); m_style
= style
; }
89 void SetStipple(const wxBitmap
& stipple
)
97 void SetDashes(int nb_dashes
, const wxDash
*dash
)
101 m_nbDash
= nb_dashes
;
102 m_dash
= wx_const_cast(wxDash
*, dash
);
105 void SetJoin(int join
) { Free(); m_join
= join
; }
106 void SetCap(int cap
) { Free(); m_cap
= cap
; }
112 // create the HPEN if we don't have it yet
115 // get the HPEN creating it on demand
116 WXHPEN
GetHPEN() const;
118 // return true if we have a valid HPEN
119 bool HasHPEN() const { return m_hPen
!= 0; }
121 // return true if we had a valid handle before, false otherwise
125 // initialize the fields which have reasonable default values
127 // doesn't initialize m_width and m_style which must be initialize in ctor
130 m_join
= wxJOIN_ROUND
;
147 DECLARE_NO_ASSIGN_CLASS(wxPenRefData
)
150 // ============================================================================
152 // ============================================================================
154 // ----------------------------------------------------------------------------
155 // wxPenRefData ctors/dtor
156 // ----------------------------------------------------------------------------
158 wxPenRefData::wxPenRefData()
166 wxPenRefData::wxPenRefData(const wxPenRefData
& data
)
169 m_style
= data
.m_style
;
170 m_width
= data
.m_width
;
171 m_join
= data
.m_join
;
173 m_nbDash
= data
.m_nbDash
;
174 m_dash
= data
.m_dash
;
175 m_colour
= data
.m_colour
;
179 wxPenRefData::wxPenRefData(const wxColour
& col
, int width
, int style
)
189 wxPenRefData::wxPenRefData(const wxBitmap
& stipple
, int width
)
199 wxPenRefData::~wxPenRefData()
202 ::DeleteObject(m_hPen
);
205 // ----------------------------------------------------------------------------
206 // wxPenRefData HPEN management
207 // ----------------------------------------------------------------------------
209 #ifdef wxHAVE_EXT_CREATE_PEN
211 static int ConvertPenStyle(int style
)
232 wxFAIL_MSG( _T("unknown pen style") );
236 case wxBDIAGONAL_HATCH
:
237 case wxCROSSDIAG_HATCH
:
238 case wxFDIAGONAL_HATCH
:
240 case wxHORIZONTAL_HATCH
:
241 case wxVERTICAL_HATCH
:
247 static int ConvertJoinStyle(int join
)
252 return PS_JOIN_BEVEL
;
255 return PS_JOIN_MITER
;
258 wxFAIL_MSG( _T("unknown pen join style") );
262 return PS_JOIN_ROUND
;
266 static int ConvertCapStyle(int cap
)
270 case wxCAP_PROJECTING
:
271 return PS_ENDCAP_SQUARE
;
274 return PS_ENDCAP_FLAT
;
277 wxFAIL_MSG( _T("unknown pen cap style") );
281 return PS_ENDCAP_ROUND
;
285 #endif // wxHAVE_EXT_CREATE_PEN
287 bool wxPenRefData::Alloc()
292 if ( m_style
== wxTRANSPARENT
)
294 m_hPen
= (HPEN
)::GetStockObject(NULL_PEN
);
298 const COLORREF col
= m_colour
.GetPixel();
300 #ifdef wxHAVE_EXT_CREATE_PEN
301 // Only NT can display dashed or dotted lines with width > 1
302 static const int os
= wxGetOsVersion();
303 if ( os
!= wxOS_WINDOWS_NT
&&
305 m_style
== wxLONG_DASH
||
306 m_style
== wxSHORT_DASH
||
307 m_style
== wxDOT_DASH
||
308 m_style
== wxUSER_DASH
) &&
314 // check if it's a standard kind of pen which can be created with just
316 if ( m_join
== wxJOIN_ROUND
&&
317 m_cap
== wxCAP_ROUND
&&
318 m_style
!= wxUSER_DASH
&&
319 m_style
!= wxSTIPPLE
&&
320 (m_width
<= 1 || m_style
== wxSOLID
) )
321 #endif // !wxHAVE_EXT_CREATE_PEN
323 m_hPen
= ::CreatePen(ConvertPenStyle(m_style
), m_width
, col
);
325 #ifdef wxHAVE_EXT_CREATE_PEN
326 else // need to use ExtCreatePen()
328 DWORD styleMSW
= PS_GEOMETRIC
|
329 ConvertPenStyle(m_style
) |
330 ConvertJoinStyle(m_join
) |
331 ConvertCapStyle(m_cap
);
337 lb
.lbStyle
= BS_PATTERN
;
338 lb
.lbHatch
= (LONG
)m_stipple
.GetHBITMAP();
341 case wxBDIAGONAL_HATCH
:
342 lb
.lbStyle
= BS_HATCHED
;
343 lb
.lbHatch
= HS_BDIAGONAL
;
346 case wxCROSSDIAG_HATCH
:
347 lb
.lbStyle
= BS_HATCHED
;
348 lb
.lbHatch
= HS_DIAGCROSS
;
351 case wxFDIAGONAL_HATCH
:
352 lb
.lbStyle
= BS_HATCHED
;
353 lb
.lbHatch
= HS_FDIAGONAL
;
357 lb
.lbStyle
= BS_HATCHED
;
358 lb
.lbHatch
= HS_CROSS
;
361 case wxHORIZONTAL_HATCH
:
362 lb
.lbStyle
= BS_HATCHED
;
363 lb
.lbHatch
= HS_HORIZONTAL
;
366 case wxVERTICAL_HATCH
:
367 lb
.lbStyle
= BS_HATCHED
;
368 lb
.lbHatch
= HS_VERTICAL
;
372 lb
.lbStyle
= BS_SOLID
;
374 // this should be unnecessary (it's unused) but suppresses the
375 // Purify messages about uninitialized memory read
384 if ( m_style
== wxUSER_DASH
&& m_nbDash
&& m_dash
)
386 dash
= new DWORD
[m_nbDash
];
387 int rw
= m_width
> 1 ? m_width
: 1;
388 for ( int i
= 0; i
< m_nbDash
; i
++ )
389 dash
[i
] = m_dash
[i
] * rw
;
396 m_hPen
= ::ExtCreatePen(styleMSW
, m_width
, &lb
, m_nbDash
, (LPDWORD
)dash
);
400 #endif // wxHAVE_EXT_CREATE_PEN
405 bool wxPenRefData::Free()
410 ::DeleteObject(m_hPen
);
416 WXHPEN
wxPenRefData::GetHPEN() const
419 wx_const_cast(wxPenRefData
*, this)->Alloc();
421 return (WXHPEN
)m_hPen
;
424 // ----------------------------------------------------------------------------
426 // ----------------------------------------------------------------------------
428 IMPLEMENT_DYNAMIC_CLASS(wxPen
, wxGDIObject
)
430 wxPen::wxPen(const wxColour
& col
, int width
, int style
)
432 m_refData
= new wxPenRefData(col
, width
, style
);
435 wxPen::wxPen(const wxBitmap
& stipple
, int width
)
437 m_refData
= new wxPenRefData(stipple
, width
);
440 bool wxPen::operator==(const wxPen
& pen
) const
443 penData
= wx_static_cast(const wxPenRefData
*, pen
.m_refData
);
445 // an invalid pen is only equal to another invalid pen
446 return m_refData
? penData
&& *M_PENDATA
== *penData
: !penData
;
449 bool wxPen::RealizeResource()
451 return M_PENDATA
&& M_PENDATA
->Alloc();
454 WXHANDLE
wxPen::GetResourceHandle() const
456 return M_PENDATA
? M_PENDATA
->GetHPEN() : 0;
459 bool wxPen::FreeResource(bool WXUNUSED(force
))
461 return M_PENDATA
&& M_PENDATA
->Free();
464 bool wxPen::IsFree() const
466 return M_PENDATA
&& !M_PENDATA
->HasHPEN();
469 wxObjectRefData
* wxPen::CreateRefData() const
471 return new wxPenRefData
;
474 wxObjectRefData
* wxPen::CloneRefData(const wxObjectRefData
* data
) const
476 return new wxPenRefData(*wx_static_cast(const wxPenRefData
*, data
));
479 void wxPen::SetColour(const wxColour
& col
)
483 M_PENDATA
->SetColour(col
);
486 void wxPen::SetColour(unsigned char r
, unsigned char g
, unsigned char b
)
488 SetColour(wxColour(r
, g
, b
));
491 void wxPen::SetWidth(int width
)
495 M_PENDATA
->SetWidth(width
);
498 void wxPen::SetStyle(int style
)
502 M_PENDATA
->SetStyle(style
);
505 void wxPen::SetStipple(const wxBitmap
& stipple
)
509 M_PENDATA
->SetStipple(stipple
);
512 void wxPen::SetDashes(int nb_dashes
, const wxDash
*dash
)
516 M_PENDATA
->SetDashes(nb_dashes
, dash
);
519 void wxPen::SetJoin(int join
)
523 M_PENDATA
->SetJoin(join
);
526 void wxPen::SetCap(int cap
)
530 M_PENDATA
->SetCap(cap
);
533 wxColour
& wxPen::GetColour() const
535 return m_refData
? M_PENDATA
->GetColour() : wxNullColour
;
538 int wxPen::GetWidth() const
540 return m_refData
? M_PENDATA
->GetWidth() : 0;
543 int wxPen::GetStyle() const
545 return m_refData
? M_PENDATA
->GetStyle() : 0;
548 int wxPen::GetJoin() const
550 return m_refData
? M_PENDATA
->GetJoin() : 0;
553 int wxPen::GetCap() const
555 return m_refData
? M_PENDATA
->GetCap() : 0;
558 int wxPen::GetDashes(wxDash
** ptr
) const
566 *ptr
= M_PENDATA
->GetDash();
567 return M_PENDATA
->GetDashCount();
570 wxDash
* wxPen::GetDash() const
572 return m_refData
? M_PENDATA
->GetDash() : NULL
;
575 int wxPen::GetDashCount() const
577 return m_refData
? M_PENDATA
->GetDashCount() : 0;
580 wxBitmap
* wxPen::GetStipple() const
582 return m_refData
? M_PENDATA
->GetStipple() : NULL
;