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