]> git.saurik.com Git - wxWidgets.git/blame - src/msw/dc.cpp
correction for compilation with ProjectBuilder
[wxWidgets.git] / src / msw / dc.cpp
CommitLineData
2bda0e17
KB
1/////////////////////////////////////////////////////////////////////////////
2// Name: dc.cpp
3// Purpose: wxDC class
4// Author: Julian Smart
5// Modified by:
6// Created: 01/02/97
7// RCS-ID: $Id$
8// Copyright: (c) Julian Smart and Markus Holzem
fd3f686c 9// Licence: wxWindows licence
2bda0e17
KB
10/////////////////////////////////////////////////////////////////////////////
11
a23fd0e1
VZ
12// ===========================================================================
13// declarations
14// ===========================================================================
15
16// ---------------------------------------------------------------------------
17// headers
18// ---------------------------------------------------------------------------
19
2bda0e17 20#ifdef __GNUG__
a23fd0e1 21 #pragma implementation "dc.h"
2bda0e17
KB
22#endif
23
24// For compilers that support precompilation, includes "wx.h".
25#include "wx/wxprec.h"
26
27#ifdef __BORLANDC__
a23fd0e1 28 #pragma hdrstop
2bda0e17
KB
29#endif
30
31#ifndef WX_PRECOMP
4286a5b5 32 #include "wx/window.h"
a23fd0e1
VZ
33 #include "wx/dc.h"
34 #include "wx/utils.h"
35 #include "wx/dialog.h"
36 #include "wx/app.h"
37 #include "wx/bitmap.h"
38 #include "wx/dcmemory.h"
0c589ad0 39 #include "wx/log.h"
4286a5b5 40 #include "wx/icon.h"
2bda0e17
KB
41#endif
42
0cbff120 43#include "wx/sysopt.h"
2bda0e17 44#include "wx/dcprint.h"
aef94d68 45#include "wx/module.h"
2bda0e17
KB
46
47#include <string.h>
48#include <math.h>
2bda0e17 49
a58a12e9
VZ
50#include "wx/msw/private.h" // needs to be before #include <commdlg.h>
51
c67d6888 52#if wxUSE_COMMON_DIALOGS && !defined(__WXMICROWIN__)
a23fd0e1 53 #include <commdlg.h>
2bda0e17
KB
54#endif
55
56#ifndef __WIN32__
a23fd0e1 57 #include <print.h>
2bda0e17
KB
58#endif
59
5acb7b3e 60IMPLEMENT_ABSTRACT_CLASS(wxDC, wxDCBase)
2bda0e17 61
a23fd0e1
VZ
62// ---------------------------------------------------------------------------
63// constants
64// ---------------------------------------------------------------------------
65
42e69d6b
VZ
66static const int VIEWPORT_EXTENT = 1000;
67
68static const int MM_POINTS = 9;
69static const int MM_METRIC = 10;
a23fd0e1 70
4314ec48
VZ
71// usually this is defined in math.h
72#ifndef M_PI
73 static const double M_PI = 3.14159265358979323846;
74#endif // M_PI
75
4aff28fc
VZ
76// ROPs which don't have standard names (see "Ternary Raster Operations" in the
77// MSDN docs for how this and other numbers in wxDC::Blit() are obtained)
78#define DSTCOPY 0x00AA0029 // a.k.a. NOP operation
79
4314ec48
VZ
80// ---------------------------------------------------------------------------
81// private functions
82// ---------------------------------------------------------------------------
83
84// convert degrees to radians
85static inline double DegToRad(double deg) { return (deg * M_PI) / 180.0; }
86
f6bcfd97
BP
87// ----------------------------------------------------------------------------
88// private classes
89// ----------------------------------------------------------------------------
90
91// instead of duplicating the same code which sets and then restores text
92// colours in each wxDC method working with wxSTIPPLE_MASK_OPAQUE brushes,
93// encapsulate this in a small helper class
94
95// wxColourChanger: changes the text colours in the ctor if required and
96// restores them in the dtor
97class wxColourChanger
98{
99public:
100 wxColourChanger(wxDC& dc);
101 ~wxColourChanger();
102
103private:
104 wxDC& m_dc;
105
106 COLORREF m_colFgOld, m_colBgOld;
107
108 bool m_changed;
109};
110
a23fd0e1
VZ
111// ===========================================================================
112// implementation
113// ===========================================================================
114
f6bcfd97
BP
115// ----------------------------------------------------------------------------
116// wxColourChanger
117// ----------------------------------------------------------------------------
118
119wxColourChanger::wxColourChanger(wxDC& dc) : m_dc(dc)
120{
121 if ( dc.GetBrush().GetStyle() == wxSTIPPLE_MASK_OPAQUE )
122 {
123 HDC hdc = GetHdcOf(dc);
124 m_colFgOld = ::GetTextColor(hdc);
125 m_colBgOld = ::GetBkColor(hdc);
126
127 // note that Windows convention is opposite to wxWindows one, this is
128 // why text colour becomes the background one and vice versa
129 const wxColour& colFg = dc.GetTextForeground();
130 if ( colFg.Ok() )
131 {
132 ::SetBkColor(hdc, colFg.GetPixel());
133 }
134
135 const wxColour& colBg = dc.GetTextBackground();
136 if ( colBg.Ok() )
137 {
138 ::SetTextColor(hdc, colBg.GetPixel());
139 }
140
141 SetBkMode(hdc,
142 dc.GetBackgroundMode() == wxTRANSPARENT ? TRANSPARENT
143 : OPAQUE);
144
145 // flag which telsl us to undo changes in the dtor
146 m_changed = TRUE;
147 }
148 else
149 {
150 // nothing done, nothing to undo
151 m_changed = FALSE;
152 }
153}
154
155wxColourChanger::~wxColourChanger()
156{
157 if ( m_changed )
158 {
159 // restore the colours we changed
160 HDC hdc = GetHdcOf(m_dc);
161
162 ::SetBkMode(hdc, TRANSPARENT);
163 ::SetTextColor(hdc, m_colFgOld);
164 ::SetBkColor(hdc, m_colBgOld);
165 }
166}
167
a23fd0e1
VZ
168// ---------------------------------------------------------------------------
169// wxDC
170// ---------------------------------------------------------------------------
2bda0e17
KB
171
172// Default constructor
a23fd0e1 173wxDC::wxDC()
2bda0e17 174{
7bcb11d3 175 m_canvas = NULL;
a23fd0e1 176
7bcb11d3
JS
177 m_oldBitmap = 0;
178 m_oldPen = 0;
179 m_oldBrush = 0;
180 m_oldFont = 0;
d275c7eb 181#if wxUSE_PALETTE
7bcb11d3 182 m_oldPalette = 0;
d275c7eb 183#endif // wxUSE_PALETTE
a23fd0e1 184
7bcb11d3
JS
185 m_bOwnsDC = FALSE;
186 m_hDC = 0;
a23fd0e1 187
7bcb11d3
JS
188 m_windowExtX = VIEWPORT_EXTENT;
189 m_windowExtY = VIEWPORT_EXTENT;
2bda0e17
KB
190}
191
192
a23fd0e1 193wxDC::~wxDC()
2bda0e17 194{
7ba4fbeb
VZ
195 if ( m_hDC != 0 )
196 {
7bcb11d3 197 SelectOldObjects(m_hDC);
7ba4fbeb
VZ
198
199 // if we own the HDC, we delete it, otherwise we just release it
200
201 if ( m_bOwnsDC )
202 {
203 ::DeleteDC(GetHdc());
7bcb11d3 204 }
7ba4fbeb
VZ
205 else // we don't own our HDC
206 {
db400410
JS
207 if (m_canvas)
208 {
209 ::ReleaseDC(GetHwndOf(m_canvas), GetHdc());
210 }
211 else
212 {
213 // Must have been a wxScreenDC
214 ::ReleaseDC((HWND) NULL, GetHdc());
215 }
7ba4fbeb
VZ
216 }
217 }
2bda0e17
KB
218}
219
220// This will select current objects out of the DC,
221// which is what you have to do before deleting the
222// DC.
223void wxDC::SelectOldObjects(WXHDC dc)
224{
7bcb11d3 225 if (dc)
2bda0e17 226 {
7bcb11d3
JS
227 if (m_oldBitmap)
228 {
229 ::SelectObject((HDC) dc, (HBITMAP) m_oldBitmap);
230 if (m_selectedBitmap.Ok())
231 {
232 m_selectedBitmap.SetSelectedInto(NULL);
233 }
234 }
a23fd0e1 235 m_oldBitmap = 0;
7bcb11d3
JS
236 if (m_oldPen)
237 {
238 ::SelectObject((HDC) dc, (HPEN) m_oldPen);
239 }
a23fd0e1 240 m_oldPen = 0;
7bcb11d3
JS
241 if (m_oldBrush)
242 {
243 ::SelectObject((HDC) dc, (HBRUSH) m_oldBrush);
244 }
a23fd0e1 245 m_oldBrush = 0;
7bcb11d3
JS
246 if (m_oldFont)
247 {
248 ::SelectObject((HDC) dc, (HFONT) m_oldFont);
249 }
a23fd0e1 250 m_oldFont = 0;
d275c7eb
VZ
251
252#if wxUSE_PALETTE
7bcb11d3
JS
253 if (m_oldPalette)
254 {
19193a2c 255 ::SelectPalette((HDC) dc, (HPALETTE) m_oldPalette, FALSE);
7bcb11d3 256 }
a23fd0e1 257 m_oldPalette = 0;
d275c7eb 258#endif // wxUSE_PALETTE
2bda0e17 259 }
a23fd0e1
VZ
260
261 m_brush = wxNullBrush;
7bcb11d3 262 m_pen = wxNullPen;
d275c7eb 263#if wxUSE_PALETTE
7bcb11d3 264 m_palette = wxNullPalette;
d275c7eb 265#endif // wxUSE_PALETTE
7bcb11d3
JS
266 m_font = wxNullFont;
267 m_backgroundBrush = wxNullBrush;
268 m_selectedBitmap = wxNullBitmap;
2bda0e17
KB
269}
270
a23fd0e1
VZ
271// ---------------------------------------------------------------------------
272// clipping
273// ---------------------------------------------------------------------------
274
1e6feb95
VZ
275void wxDC::UpdateClipBox()
276{
5adad466
JS
277#ifdef __WXMICROWIN__
278 if (!GetHDC()) return;
279#endif
d275c7eb 280
1e6feb95 281 RECT rect;
5230934a 282 ::GetClipBox(GetHdc(), &rect);
1e6feb95
VZ
283
284 m_clipX1 = (wxCoord) XDEV2LOG(rect.left);
285 m_clipY1 = (wxCoord) YDEV2LOG(rect.top);
286 m_clipX2 = (wxCoord) XDEV2LOG(rect.right);
287 m_clipY2 = (wxCoord) YDEV2LOG(rect.bottom);
f547e9bb
RL
288}
289
5230934a
VZ
290// common part of DoSetClippingRegion() and DoSetClippingRegionAsRegion()
291void wxDC::SetClippingHrgn(WXHRGN hrgn)
2bda0e17 292{
5230934a
VZ
293 wxCHECK_RET( hrgn, wxT("invalid clipping region") );
294
5adad466 295#ifdef __WXMICROWIN__
5230934a
VZ
296 if (!GetHdc()) return;
297#endif // __WXMICROWIN__
298
299 // note that we combine the new clipping region with the existing one: this
300 // is compatible with what the other ports do and is the documented
301 // behaviour now (starting with 2.3.3)
302#ifdef __WIN16__
303 RECT rectClip;
304 if ( !::GetClipBox(GetHdc(), &rectClip) )
305 return;
306
307 HRGN hrgnDest = ::CreateRectRgn(0, 0, 0, 0);
308 HRGN hrgnClipOld = ::CreateRectRgn(rectClip.left, rectClip.top,
309 rectClip.right, rectClip.bottom);
310
311 if ( ::CombineRgn(hrgnDest, hrgnClipOld, (HRGN)hrgn, RGN_AND) != ERROR )
312 {
313 ::SelectClipRgn(GetHdc(), hrgnDest);
314 }
315
316 ::DeleteObject(hrgnClipOld);
317 ::DeleteObject(hrgnDest);
318#else // Win32
319 if ( ::ExtSelectClipRgn(GetHdc(), (HRGN)hrgn, RGN_AND) == ERROR )
320 {
321 wxLogLastError(_T("ExtSelectClipRgn"));
322
323 return;
324 }
325#endif // Win16/32
d275c7eb 326
7bcb11d3 327 m_clipping = TRUE;
40a89076 328
5230934a
VZ
329 UpdateClipBox();
330}
331
332void wxDC::DoSetClippingRegion(wxCoord x, wxCoord y, wxCoord w, wxCoord h)
333{
c4218a74
VZ
334 // the region coords are always the device ones, so do the translation
335 // manually
1e6feb95
VZ
336 //
337 // FIXME: possible +/-1 error here, to check!
c4218a74
VZ
338 HRGN hrgn = ::CreateRectRgn(LogicalToDeviceX(x),
339 LogicalToDeviceY(y),
340 LogicalToDeviceX(x + w),
341 LogicalToDeviceY(y + h));
40a89076
VZ
342 if ( !hrgn )
343 {
344 wxLogLastError(_T("CreateRectRgn"));
345 }
346 else
347 {
5230934a 348 SetClippingHrgn((WXHRGN)hrgn);
40a89076 349
5230934a 350 ::DeleteObject(hrgn);
40a89076 351 }
2bda0e17
KB
352}
353
a23fd0e1 354void wxDC::DoSetClippingRegionAsRegion(const wxRegion& region)
a724d789 355{
5230934a 356 SetClippingHrgn(region.GetHRGN());
2bda0e17
KB
357}
358
a23fd0e1 359void wxDC::DestroyClippingRegion()
2bda0e17 360{
5adad466
JS
361#ifdef __WXMICROWIN__
362 if (!GetHDC()) return;
363#endif
d275c7eb 364
7bcb11d3
JS
365 if (m_clipping && m_hDC)
366 {
367 // TODO: this should restore the previous clipping region,
5230934a
VZ
368 // so that OnPaint processing works correctly, and the update
369 // clipping region doesn't get destroyed after the first
370 // DestroyClippingRegion.
7bcb11d3 371 HRGN rgn = CreateRectRgn(0, 0, 32000, 32000);
5230934a
VZ
372 ::SelectClipRgn(GetHdc(), rgn);
373 ::DeleteObject(rgn);
7bcb11d3 374 }
1e6feb95 375
7bcb11d3 376 m_clipping = FALSE;
2bda0e17
KB
377}
378
a23fd0e1
VZ
379// ---------------------------------------------------------------------------
380// query capabilities
381// ---------------------------------------------------------------------------
382
383bool wxDC::CanDrawBitmap() const
2bda0e17 384{
7bcb11d3 385 return TRUE;
2bda0e17
KB
386}
387
a23fd0e1 388bool wxDC::CanGetTextExtent() const
2bda0e17 389{
04ef50df
JS
390#ifdef __WXMICROWIN__
391 // TODO Extend MicroWindows' GetDeviceCaps function
392 return TRUE;
393#else
7bcb11d3 394 // What sort of display is it?
a23fd0e1
VZ
395 int technology = ::GetDeviceCaps(GetHdc(), TECHNOLOGY);
396
397 return (technology == DT_RASDISPLAY) || (technology == DT_RASPRINTER);
04ef50df 398#endif
2bda0e17
KB
399}
400
a23fd0e1 401int wxDC::GetDepth() const
2bda0e17 402{
5adad466
JS
403#ifdef __WXMICROWIN__
404 if (!GetHDC()) return 16;
405#endif
d275c7eb 406
a23fd0e1 407 return (int)::GetDeviceCaps(GetHdc(), BITSPIXEL);
2bda0e17
KB
408}
409
a23fd0e1
VZ
410// ---------------------------------------------------------------------------
411// drawing
412// ---------------------------------------------------------------------------
413
414void wxDC::Clear()
2bda0e17 415{
5adad466
JS
416#ifdef __WXMICROWIN__
417 if (!GetHDC()) return;
418#endif
d275c7eb 419
7bcb11d3 420 RECT rect;
2506aab6
VZ
421 if ( m_canvas )
422 {
7bcb11d3 423 GetClientRect((HWND) m_canvas->GetHWND(), &rect);
2506aab6
VZ
424 }
425 else
7bcb11d3 426 {
eaeb6a3c
JS
427 // No, I think we should simply ignore this if printing on e.g.
428 // a printer DC.
429 // wxCHECK_RET( m_selectedBitmap.Ok(), wxT("this DC can't be cleared") );
430 if (!m_selectedBitmap.Ok())
431 return;
2506aab6 432
7bcb11d3
JS
433 rect.left = 0; rect.top = 0;
434 rect.right = m_selectedBitmap.GetWidth();
435 rect.bottom = m_selectedBitmap.GetHeight();
436 }
2506aab6 437
a23fd0e1
VZ
438 (void) ::SetMapMode(GetHdc(), MM_TEXT);
439
440 DWORD colour = GetBkColor(GetHdc());
7bcb11d3 441 HBRUSH brush = CreateSolidBrush(colour);
a23fd0e1 442 FillRect(GetHdc(), &rect, brush);
7bcb11d3 443 DeleteObject(brush);
a23fd0e1
VZ
444
445 ::SetMapMode(GetHdc(), MM_ANISOTROPIC);
446 ::SetViewportExtEx(GetHdc(), VIEWPORT_EXTENT, VIEWPORT_EXTENT, NULL);
447 ::SetWindowExtEx(GetHdc(), m_windowExtX, m_windowExtY, NULL);
448 ::SetViewportOrgEx(GetHdc(), (int)m_deviceOriginX, (int)m_deviceOriginY, NULL);
449 ::SetWindowOrgEx(GetHdc(), (int)m_logicalOriginX, (int)m_logicalOriginY, NULL);
450}
451
72cdf4c9 452void wxDC::DoFloodFill(wxCoord x, wxCoord y, const wxColour& col, int style)
a23fd0e1 453{
5adad466
JS
454#ifdef __WXMICROWIN__
455 if (!GetHDC()) return;
456#endif
d275c7eb 457
0bafad0c
VZ
458 if ( !::ExtFloodFill(GetHdc(), XLOG2DEV(x), YLOG2DEV(y),
459 col.GetPixel(),
460 style == wxFLOOD_SURFACE ? FLOODFILLSURFACE
461 : FLOODFILLBORDER) )
462 {
463 // quoting from the MSDN docs:
464 //
465 // Following are some of the reasons this function might fail:
466 //
467 // * The filling could not be completed.
468 // * The specified point has the boundary color specified by the
469 // crColor parameter (if FLOODFILLBORDER was requested).
470 // * The specified point does not have the color specified by
471 // crColor (if FLOODFILLSURFACE was requested)
472 // * The point is outside the clipping region that is, it is not
473 // visible on the device.
474 //
f6bcfd97 475 wxLogLastError(wxT("ExtFloodFill"));
0bafad0c 476 }
a23fd0e1 477
7bcb11d3 478 CalcBoundingBox(x, y);
2bda0e17
KB
479}
480
72cdf4c9 481bool wxDC::DoGetPixel(wxCoord x, wxCoord y, wxColour *col) const
2bda0e17 482{
5adad466
JS
483#ifdef __WXMICROWIN__
484 if (!GetHDC()) return FALSE;
485#endif
d275c7eb 486
f6bcfd97
BP
487 wxCHECK_MSG( col, FALSE, _T("NULL colour parameter in wxDC::GetPixel") );
488
7bcb11d3 489 // get the color of the pixel
a23fd0e1 490 COLORREF pixelcolor = ::GetPixel(GetHdc(), XLOG2DEV(x), YLOG2DEV(y));
0bafad0c 491
f6bcfd97 492 wxRGBToColour(*col, pixelcolor);
dc1efb1d
JS
493
494 return TRUE;
2bda0e17
KB
495}
496
72cdf4c9 497void wxDC::DoCrossHair(wxCoord x, wxCoord y)
a23fd0e1 498{
5adad466
JS
499#ifdef __WXMICROWIN__
500 if (!GetHDC()) return;
501#endif
d275c7eb 502
72cdf4c9
VZ
503 wxCoord x1 = x-VIEWPORT_EXTENT;
504 wxCoord y1 = y-VIEWPORT_EXTENT;
505 wxCoord x2 = x+VIEWPORT_EXTENT;
506 wxCoord y2 = y+VIEWPORT_EXTENT;
a23fd0e1
VZ
507
508 (void)MoveToEx(GetHdc(), XLOG2DEV(x1), YLOG2DEV(y), NULL);
509 (void)LineTo(GetHdc(), XLOG2DEV(x2), YLOG2DEV(y));
510
511 (void)MoveToEx(GetHdc(), XLOG2DEV(x), YLOG2DEV(y1), NULL);
512 (void)LineTo(GetHdc(), XLOG2DEV(x), YLOG2DEV(y2));
513
7bcb11d3
JS
514 CalcBoundingBox(x1, y1);
515 CalcBoundingBox(x2, y2);
2bda0e17
KB
516}
517
72cdf4c9 518void wxDC::DoDrawLine(wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2)
2bda0e17 519{
5adad466
JS
520#ifdef __WXMICROWIN__
521 if (!GetHDC()) return;
522#endif
d275c7eb 523
a23fd0e1
VZ
524 (void)MoveToEx(GetHdc(), XLOG2DEV(x1), YLOG2DEV(y1), NULL);
525 (void)LineTo(GetHdc(), XLOG2DEV(x2), YLOG2DEV(y2));
526
058939fc
JS
527 // Normalization: Windows doesn't draw the last point of the line.
528 // But apparently neither does GTK+, so we take it out again.
529// (void)LineTo(GetHdc(), XLOG2DEV(x2) + 1, YLOG2DEV(y2));
a23fd0e1 530
7bcb11d3
JS
531 CalcBoundingBox(x1, y1);
532 CalcBoundingBox(x2, y2);
2bda0e17
KB
533}
534
f6bcfd97
BP
535// Draws an arc of a circle, centred on (xc, yc), with starting point (x1, y1)
536// and ending at (x2, y2)
537void wxDC::DoDrawArc(wxCoord x1, wxCoord y1,
538 wxCoord x2, wxCoord y2,
539 wxCoord xc, wxCoord yc)
2bda0e17 540{
5adad466
JS
541#ifdef __WXMICROWIN__
542 if (!GetHDC()) return;
543#endif
d275c7eb 544
f6bcfd97 545 wxColourChanger cc(*this); // needed for wxSTIPPLE_MASK_OPAQUE handling
2d8a5cb1 546
f6bcfd97
BP
547 double dx = xc - x1;
548 double dy = yc - y1;
549 double radius = (double)sqrt(dx*dx+dy*dy);
550 wxCoord r = (wxCoord)radius;
2d8a5cb1 551
f6bcfd97
BP
552 // treat the special case of full circle separately
553 if ( x1 == x2 && y1 == y2 )
7bcb11d3 554 {
f6bcfd97 555 DrawEllipse(xc - r, yc - r, 2*r, 2*r);
a23fd0e1 556 return;
7bcb11d3 557 }
a23fd0e1 558
72cdf4c9
VZ
559 wxCoord xx1 = XLOG2DEV(x1);
560 wxCoord yy1 = YLOG2DEV(y1);
561 wxCoord xx2 = XLOG2DEV(x2);
562 wxCoord yy2 = YLOG2DEV(y2);
563 wxCoord xxc = XLOG2DEV(xc);
564 wxCoord yyc = YLOG2DEV(yc);
565 wxCoord ray = (wxCoord) sqrt(double((xxc-xx1)*(xxc-xx1)+(yyc-yy1)*(yyc-yy1)));
a23fd0e1 566
72cdf4c9
VZ
567 wxCoord xxx1 = (wxCoord) (xxc-ray);
568 wxCoord yyy1 = (wxCoord) (yyc-ray);
569 wxCoord xxx2 = (wxCoord) (xxc+ray);
570 wxCoord yyy2 = (wxCoord) (yyc+ray);
f6bcfd97
BP
571
572 if ( m_brush.Ok() && m_brush.GetStyle() != wxTRANSPARENT )
7bcb11d3
JS
573 {
574 // Have to add 1 to bottom-right corner of rectangle
575 // to make semi-circles look right (crooked line otherwise).
576 // Unfortunately this is not a reliable method, depends
577 // on the size of shape.
578 // TODO: figure out why this happens!
f6bcfd97 579 Pie(GetHdc(),xxx1,yyy1,xxx2+1,yyy2+1, xx1,yy1,xx2,yy2);
7bcb11d3
JS
580 }
581 else
2d8a5cb1 582 {
f6bcfd97 583 Arc(GetHdc(),xxx1,yyy1,xxx2,yyy2, xx1,yy1,xx2,yy2);
2d8a5cb1 584 }
f6bcfd97
BP
585
586 CalcBoundingBox(xc - r, yc - r);
587 CalcBoundingBox(xc + r, yc + r);
2bda0e17
KB
588}
589
cd9da200
VZ
590void wxDC::DoDrawCheckMark(wxCoord x1, wxCoord y1,
591 wxCoord width, wxCoord height)
592{
5adad466
JS
593#ifdef __WXMICROWIN__
594 if (!GetHDC()) return;
595#endif
d275c7eb 596
cd9da200
VZ
597 wxCoord x2 = x1 + width,
598 y2 = y1 + height;
599
04ef50df 600#if defined(__WIN32__) && !defined(__SC__) && !defined(__WXMICROWIN__)
cd9da200
VZ
601 RECT rect;
602 rect.left = x1;
603 rect.top = y1;
604 rect.right = x2;
605 rect.bottom = y2;
606
607 DrawFrameControl(GetHdc(), &rect, DFC_MENU, DFCS_MENUCHECK);
608#else // Win16
609 // In WIN16, draw a cross
610 HPEN blackPen = ::CreatePen(PS_SOLID, 1, RGB(0, 0, 0));
611 HPEN whiteBrush = (HPEN)::GetStockObject(WHITE_BRUSH);
e06b9569
JS
612 HPEN hPenOld = (HPEN)::SelectObject(GetHdc(), blackPen);
613 HPEN hBrushOld = (HPEN)::SelectObject(GetHdc(), whiteBrush);
cd9da200
VZ
614 ::SetROP2(GetHdc(), R2_COPYPEN);
615 Rectangle(GetHdc(), x1, y1, x2, y2);
8cb172b4 616 MoveToEx(GetHdc(), x1, y1, NULL);
cd9da200 617 LineTo(GetHdc(), x2, y2);
8cb172b4 618 MoveToEx(GetHdc(), x2, y1, NULL);
cd9da200
VZ
619 LineTo(GetHdc(), x1, y2);
620 ::SelectObject(GetHdc(), hPenOld);
621 ::SelectObject(GetHdc(), hBrushOld);
622 ::DeleteObject(blackPen);
623#endif // Win32/16
624
625 CalcBoundingBox(x1, y1);
626 CalcBoundingBox(x2, y2);
627}
628
72cdf4c9 629void wxDC::DoDrawPoint(wxCoord x, wxCoord y)
2bda0e17 630{
5adad466
JS
631#ifdef __WXMICROWIN__
632 if (!GetHDC()) return;
633#endif
d275c7eb 634
7bcb11d3
JS
635 COLORREF color = 0x00ffffff;
636 if (m_pen.Ok())
637 {
a23fd0e1 638 color = m_pen.GetColour().GetPixel();
7bcb11d3 639 }
a23fd0e1
VZ
640
641 SetPixel(GetHdc(), XLOG2DEV(x), YLOG2DEV(y), color);
642
7bcb11d3 643 CalcBoundingBox(x, y);
2bda0e17
KB
644}
645
72cdf4c9 646void wxDC::DoDrawPolygon(int n, wxPoint points[], wxCoord xoffset, wxCoord yoffset,int fillStyle)
2bda0e17 647{
5adad466
JS
648#ifdef __WXMICROWIN__
649 if (!GetHDC()) return;
650#endif
d275c7eb 651
f6bcfd97 652 wxColourChanger cc(*this); // needed for wxSTIPPLE_MASK_OPAQUE handling
de2d2cdc 653
7bcb11d3
JS
654 // Do things less efficiently if we have offsets
655 if (xoffset != 0 || yoffset != 0)
6a6c0a8b 656 {
7bcb11d3
JS
657 POINT *cpoints = new POINT[n];
658 int i;
659 for (i = 0; i < n; i++)
660 {
661 cpoints[i].x = (int)(points[i].x + xoffset);
662 cpoints[i].y = (int)(points[i].y + yoffset);
a23fd0e1 663
7bcb11d3
JS
664 CalcBoundingBox(cpoints[i].x, cpoints[i].y);
665 }
a23fd0e1
VZ
666 int prev = SetPolyFillMode(GetHdc(),fillStyle==wxODDEVEN_RULE?ALTERNATE:WINDING);
667 (void)Polygon(GetHdc(), cpoints, n);
668 SetPolyFillMode(GetHdc(),prev);
7bcb11d3
JS
669 delete[] cpoints;
670 }
671 else
672 {
673 int i;
674 for (i = 0; i < n; i++)
675 CalcBoundingBox(points[i].x, points[i].y);
a23fd0e1
VZ
676
677 int prev = SetPolyFillMode(GetHdc(),fillStyle==wxODDEVEN_RULE?ALTERNATE:WINDING);
678 (void)Polygon(GetHdc(), (POINT*) points, n);
679 SetPolyFillMode(GetHdc(),prev);
6a6c0a8b 680 }
2bda0e17
KB
681}
682
72cdf4c9 683void wxDC::DoDrawLines(int n, wxPoint points[], wxCoord xoffset, wxCoord yoffset)
2bda0e17 684{
5adad466
JS
685#ifdef __WXMICROWIN__
686 if (!GetHDC()) return;
687#endif
d275c7eb 688
7bcb11d3
JS
689 // Do things less efficiently if we have offsets
690 if (xoffset != 0 || yoffset != 0)
6a6c0a8b 691 {
7bcb11d3
JS
692 POINT *cpoints = new POINT[n];
693 int i;
694 for (i = 0; i < n; i++)
695 {
696 cpoints[i].x = (int)(points[i].x + xoffset);
697 cpoints[i].y = (int)(points[i].y + yoffset);
a23fd0e1 698
7bcb11d3
JS
699 CalcBoundingBox(cpoints[i].x, cpoints[i].y);
700 }
a23fd0e1 701 (void)Polyline(GetHdc(), cpoints, n);
7bcb11d3
JS
702 delete[] cpoints;
703 }
704 else
705 {
706 int i;
707 for (i = 0; i < n; i++)
708 CalcBoundingBox(points[i].x, points[i].y);
a23fd0e1
VZ
709
710 (void)Polyline(GetHdc(), (POINT*) points, n);
6a6c0a8b 711 }
2bda0e17
KB
712}
713
72cdf4c9 714void wxDC::DoDrawRectangle(wxCoord x, wxCoord y, wxCoord width, wxCoord height)
2bda0e17 715{
5adad466
JS
716#ifdef __WXMICROWIN__
717 if (!GetHDC()) return;
718#endif
d275c7eb 719
f6bcfd97 720 wxColourChanger cc(*this); // needed for wxSTIPPLE_MASK_OPAQUE handling
de2d2cdc 721
72cdf4c9
VZ
722 wxCoord x2 = x + width;
723 wxCoord y2 = y + height;
a23fd0e1 724
5456b916 725 if ((m_logicalFunction == wxCOPY) && (m_pen.GetStyle() == wxTRANSPARENT))
0bafad0c 726 {
7299b1b2 727 RECT rect;
5456b916
RR
728 rect.left = XLOG2DEV(x);
729 rect.top = YLOG2DEV(y);
730 rect.right = XLOG2DEV(x2);
7299b1b2
RD
731 rect.bottom = YLOG2DEV(y2);
732 (void)FillRect(GetHdc(), &rect, (HBRUSH)m_brush.GetResourceHandle() );
5456b916
RR
733 }
734 else
735 {
736 // Windows draws the filled rectangles without outline (i.e. drawn with a
737 // transparent pen) one pixel smaller in both directions and we want them
f6bcfd97 738 // to have the same size regardless of which pen is used - adjust
5456b916
RR
739
740