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