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