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: pen.cpp 44818 2007-03-15 09:40:24Z JS $ 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 30static int wx2msPenStyle(int wx_style); 31 32IMPLEMENT_DYNAMIC_CLASS(wxPen, wxGDIObject) 33 34wxPenRefData::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 45wxPenRefData::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 58wxPenRefData::~wxPenRefData() 59{ 60 if ( m_hPen ) 61 ::DeleteObject((HPEN) m_hPen); 62} 63 64// Pens 65 66wxPen::wxPen() 67{ 68} 69 70wxPen::~wxPen() 71{ 72} 73 74// Should implement Create 75wxPen::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 92wxPen::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 109bool 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 249WXHANDLE wxPen::GetResourceHandle() const 250{ 251 if ( !M_PENDATA ) 252 return 0; 253 else 254 return (WXHANDLE)M_PENDATA->m_hPen; 255} 256 257bool 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 268bool wxPen::IsFree() const 269{ 270 return (M_PENDATA && M_PENDATA->m_hPen == 0); 271} 272 273void 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 288void wxPen::SetColour(const wxColour& col) 289{ 290 Unshare(); 291 292 M_PENDATA->m_colour = col; 293 294 RealizeResource(); 295} 296 297void 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 306void wxPen::SetWidth(int Width) 307{ 308 Unshare(); 309 310 M_PENDATA->m_width = Width; 311 312 RealizeResource(); 313} 314 315void wxPen::SetStyle(int Style) 316{ 317 Unshare(); 318 319 M_PENDATA->m_style = Style; 320 321 RealizeResource(); 322} 323 324void 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 334void 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 344void wxPen::SetJoin(int Join) 345{ 346 Unshare(); 347 348 M_PENDATA->m_join = Join; 349 350 RealizeResource(); 351} 352 353void wxPen::SetCap(int Cap) 354{ 355 Unshare(); 356 357 M_PENDATA->m_cap = Cap; 358 359 RealizeResource(); 360} 361 362int 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} 388