]> git.saurik.com Git - wxWidgets.git/blame - src/msw/pen.cpp
minor bug fixes
[wxWidgets.git] / src / msw / pen.cpp
CommitLineData
2bda0e17
KB
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
36IMPLEMENT_DYNAMIC_CLASS(wxPen, wxGDIObject)
37#endif
38
e4a81a2e 39wxPenRefData::wxPenRefData()
2bda0e17 40{
2bda0e17
KB
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
b823f5a1
JS
50wxPenRefData::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
e4a81a2e 62wxPenRefData::~wxPenRefData()
2bda0e17
KB
63{
64 if ( m_hPen )
65 ::DeleteObject((HPEN) m_hPen);
66}
67
68// Pens
69
e4a81a2e 70wxPen::wxPen()
2bda0e17 71{
c45a644e 72 if (wxThePenList)
2bda0e17
KB
73 wxThePenList->AddPen(this);
74}
75
76wxPen::~wxPen()
77{
78 if (wxThePenList)
79 wxThePenList->RemovePen(this);
80}
81
82// Should implement Create
debe6624 83wxPen::wxPen(const wxColour& col, int Width, int Style)
2bda0e17
KB
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
debe6624 126wxPen::wxPen(const wxBitmap& stipple, int Width)
2bda0e17 127{
c45a644e 128 m_refData = new wxPenRefData;
2bda0e17
KB
129
130// M_PENDATA->m_colour = col;
c45a644e
RR
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 ;
2bda0e17 139
c45a644e 140 RealizeResource();
2bda0e17 141
c45a644e
RR
142 if (wxThePenList)
143 wxThePenList->AddPen(this);
2bda0e17
KB
144}
145
e4a81a2e 146bool wxPen::RealizeResource()
2bda0e17 147{
c45a644e
RR
148 if (M_PENDATA && (M_PENDATA->m_hPen == 0))
149 {
150 if (M_PENDATA->m_style==wxTRANSPARENT)
151 {
152 M_PENDATA->m_hPen = (WXHPEN) ::GetStockObject(NULL_PEN);
153 return TRUE;
154 }
155
156 COLORREF ms_colour = 0;
157 ms_colour = M_PENDATA->m_colour.GetPixel();
158
159 // Join style, Cap style, Pen Stippling only on Win32.
160 // Currently no time to find equivalent on Win3.1, sorry
161 // [if such equiv exist!!]
2bda0e17 162#ifdef __WIN32__
c45a644e
RR
163 if (M_PENDATA->m_join==wxJOIN_ROUND &&
164 M_PENDATA->m_cap==wxCAP_ROUND &&
165 M_PENDATA->m_style!=wxUSER_DASH &&
166 M_PENDATA->m_style!=wxSTIPPLE &&
167 M_PENDATA->m_width <= 1)
168 {
169 M_PENDATA->m_hPen =
170 (WXHPEN) CreatePen( wx2msPenStyle(M_PENDATA->m_style),
171 M_PENDATA->m_width,
172 ms_colour );
173 }
174 else
175 {
176 DWORD ms_style = PS_GEOMETRIC | wx2msPenStyle(M_PENDATA->m_style);
177
178 switch(M_PENDATA->m_join)
179 {
180 case wxJOIN_BEVEL: ms_style |= PS_JOIN_BEVEL; break;
181 case wxJOIN_MITER: ms_style |= PS_JOIN_MITER; break;
182 default:
183 case wxJOIN_ROUND: ms_style |= PS_JOIN_ROUND; break;
184 }
185
186 switch(M_PENDATA->m_cap)
187 {
188 case wxCAP_PROJECTING: ms_style |= PS_ENDCAP_SQUARE; break;
189 case wxCAP_BUTT: ms_style |= PS_ENDCAP_FLAT; break;
190 default:
191 case wxCAP_ROUND: ms_style |= PS_ENDCAP_ROUND; break;
192 }
193
194 LOGBRUSH logb;
195
196 switch(M_PENDATA->m_style)
197 {
198 case wxSTIPPLE:
199 logb.lbStyle = BS_PATTERN ;
200 if (M_PENDATA->m_stipple.Ok())
201 logb.lbHatch = (LONG)M_PENDATA->m_stipple.GetHBITMAP();
202 else
203 logb.lbHatch = (LONG)0;
204 break;
205 case wxBDIAGONAL_HATCH:
206 logb.lbStyle = BS_HATCHED;
207 logb.lbHatch = HS_BDIAGONAL;
208 break;
209 case wxCROSSDIAG_HATCH:
210 logb.lbStyle = BS_HATCHED;
211 logb.lbHatch = HS_DIAGCROSS;
212 break;
213 case wxFDIAGONAL_HATCH:
214 logb.lbStyle = BS_HATCHED;
215 logb.lbHatch = HS_FDIAGONAL;
216 break;
217 case wxCROSS_HATCH:
218 logb.lbStyle = BS_HATCHED;
219 logb.lbHatch = HS_CROSS;
220 break;
221 case wxHORIZONTAL_HATCH:
222 logb.lbStyle = BS_HATCHED;
223 logb.lbHatch = HS_HORIZONTAL;
224 break;
225 case wxVERTICAL_HATCH:
226 logb.lbStyle = BS_HATCHED;
227 logb.lbHatch = HS_VERTICAL;
228 break;
229 default:
230 logb.lbStyle = BS_SOLID;
61ba49f2 231#ifdef __WXDEBUG__
c45a644e
RR
232 // this should be unnecessary (it's unused) but suppresses the Purigy
233 // messages about uninitialized memory read
234 logb.lbHatch = 0;
61ba49f2 235#endif
c45a644e
RR
236 break;
237 }
238
239 logb.lbColor = ms_colour;
240
241 wxDash *real_dash;
242 if (M_PENDATA->m_style==wxUSER_DASH && M_PENDATA->m_nbDash && M_PENDATA->m_dash)
243 {
244 real_dash = new wxDash[M_PENDATA->m_nbDash];
245 int i;
246 for (i=0; i<M_PENDATA->m_nbDash; i++)
247 real_dash[i] = M_PENDATA->m_dash[i] * M_PENDATA->m_width;
248 }
249 else
250 {
251 real_dash = 0;
252 }
253
254 // Win32s doesn't have ExtCreatePen function...
255 if (wxGetOsVersion()==wxWINDOWS_NT || wxGetOsVersion()==wxWIN95)
256 {
257 M_PENDATA->m_hPen =
258 (WXHPEN) ExtCreatePen( ms_style,
259 M_PENDATA->m_width,
260 &logb,
261 M_PENDATA->m_style==wxUSER_DASH
262 ? M_PENDATA->m_nbDash
263 : 0,
264 (const DWORD*)real_dash );
265 }
266 else
267 {
268 M_PENDATA->m_hPen =
269 (WXHPEN) CreatePen( wx2msPenStyle(M_PENDATA->m_style),
270 M_PENDATA->m_width,
271 ms_colour );
272 }
273
274 if (real_dash)
275 delete [] real_dash;
276 }
2bda0e17 277#else
c45a644e
RR
278 M_PENDATA->m_hPen =
279 (WXHPEN) CreatePen( wx2msPenStyle(M_PENDATA->m_style),
280 M_PENDATA->m_width,
281 ms_colour );
2bda0e17 282#endif
b2aef89b 283#ifdef WXDEBUG_CREATE
c45a644e
RR
284 if (M_PENDATA->m_hPen==0)
285 wxError("Cannot create pen","Internal error") ;
2bda0e17 286#endif
c45a644e
RR
287 return TRUE;
288 }
289 return FALSE;
2bda0e17
KB
290}
291
e4a81a2e 292WXHANDLE wxPen::GetResourceHandle()
2bda0e17
KB
293{
294 if ( !M_PENDATA )
295 return 0;
296 else
1e7fd311 297 return (WXHANDLE)M_PENDATA->m_hPen;
2bda0e17
KB
298}
299
300bool wxPen::FreeResource(bool force)
301{
302 if (M_PENDATA && (M_PENDATA->m_hPen != 0))
303 {
304 DeleteObject((HPEN) M_PENDATA->m_hPen);
305 M_PENDATA->m_hPen = 0;
306 return TRUE;
307 }
308 else return FALSE;
309}
310
e4a81a2e 311bool wxPen::IsFree() const
2bda0e17 312{
b823f5a1 313 return (M_PENDATA && M_PENDATA->m_hPen == 0);
2bda0e17 314}
2bda0e17 315
b823f5a1 316void wxPen::Unshare()
2bda0e17 317{
b823f5a1
JS
318 // Don't change shared data
319 if (!m_refData)
320 {
321 m_refData = new wxPenRefData();
322 }
323 else
324 {
325 wxPenRefData* ref = new wxPenRefData(*(wxPenRefData*)m_refData);
326 UnRef();
327 m_refData = ref;
328 }
2bda0e17
KB
329}
330
331void wxPen::SetColour(const wxColour& col)
332{
b823f5a1 333 Unshare();
2bda0e17 334
b823f5a1 335 M_PENDATA->m_colour = col;
2bda0e17 336
2bda0e17
KB
337 RealizeResource();
338}
339
e4a81a2e 340void wxPen::SetColour(unsigned char r, unsigned char g, unsigned char b)
2bda0e17 341{
b823f5a1 342 Unshare();
2bda0e17 343
b823f5a1 344 M_PENDATA->m_colour.Set(r, g, b);
2bda0e17 345
2bda0e17
KB
346 RealizeResource();
347}
348
debe6624 349void wxPen::SetWidth(int Width)
2bda0e17 350{
b823f5a1 351 Unshare();
2bda0e17 352
b823f5a1 353 M_PENDATA->m_width = Width;
2bda0e17 354
2bda0e17
KB
355 RealizeResource();
356}
357
debe6624 358void wxPen::SetStyle(int Style)
2bda0e17 359{
b823f5a1 360 Unshare();
2bda0e17 361
b823f5a1 362 M_PENDATA->m_style = Style;
2bda0e17 363
2bda0e17
KB
364 RealizeResource();
365}
366
367void wxPen::SetStipple(const wxBitmap& Stipple)
368{
b823f5a1 369 Unshare();
2bda0e17 370
b823f5a1
JS
371 M_PENDATA->m_stipple = Stipple;
372 M_PENDATA->m_style = wxSTIPPLE;
2bda0e17 373
2bda0e17
KB
374 RealizeResource();
375}
376
debe6624 377void wxPen::SetDashes(int nb_dashes, const wxDash *Dash)
2bda0e17 378{
b823f5a1 379 Unshare();
2bda0e17 380
b823f5a1
JS
381 M_PENDATA->m_nbDash = nb_dashes;
382 M_PENDATA->m_dash = (wxDash *)Dash;
2bda0e17 383
2bda0e17
KB
384 RealizeResource();
385}
386
debe6624 387void wxPen::SetJoin(int Join)
2bda0e17 388{
b823f5a1 389 Unshare();
2bda0e17 390
b823f5a1 391 M_PENDATA->m_join = Join;
2bda0e17 392
2bda0e17
KB
393 RealizeResource();
394}
395
debe6624 396void wxPen::SetCap(int Cap)
2bda0e17 397{
b823f5a1 398 Unshare();
2bda0e17 399
b823f5a1 400 M_PENDATA->m_cap = Cap;
2bda0e17 401
2bda0e17
KB
402 RealizeResource();
403}
404
405int wx2msPenStyle(int wx_style)
406{
c45a644e
RR
407 int cstyle;
408 switch (wx_style)
409 {
410 case wxDOT:
411 cstyle = PS_DOT;
412 break;
413
414 case wxDOT_DASH:
415 cstyle = PS_DASHDOT;
416 break;
417
418 case wxSHORT_DASH:
419 case wxLONG_DASH:
420 cstyle = PS_DASH;
421 break;
422
423 case wxTRANSPARENT:
424 cstyle = PS_NULL;
425 break;
426
427 case wxUSER_DASH:
2bda0e17 428#ifdef __WIN32__
c45a644e
RR
429 // Win32s doesn't have PS_USERSTYLE
430 if (wxGetOsVersion()==wxWINDOWS_NT || wxGetOsVersion()==wxWIN95)
431 cstyle = PS_USERSTYLE;
432 else
433 cstyle = PS_DOT; // We must make a choice... This is mine!
2bda0e17 434#else
c45a644e 435 cstyle = PS_DASH;
2bda0e17 436#endif
c45a644e
RR
437 break;
438 case wxSOLID:
439 default:
440 cstyle = PS_SOLID;
441 break;
442 }
443 return cstyle;
2bda0e17
KB
444}
445