]> git.saurik.com Git - wxWidgets.git/blame - src/msw/dc.cpp
scrolling to selection
[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 {
395b914e
VZ
394 wxDC *self = wxConstCast(this, wxDC);
395 self->UpdateClipBox();
2e76da54
VZ
396
397 if ( !m_clipX1 && !m_clipX2 )
395b914e 398 self->m_clipping = false;
2e76da54
VZ
399 }
400
f67fe9a4 401 wxDCBase::DoGetClippingBox(x, y, w, h);
2e76da54
VZ
402}
403
5230934a
VZ
404// common part of DoSetClippingRegion() and DoSetClippingRegionAsRegion()
405void wxDC::SetClippingHrgn(WXHRGN hrgn)
2bda0e17 406{
5230934a
VZ
407 wxCHECK_RET( hrgn, wxT("invalid clipping region") );
408
82a306b7 409 WXMICROWIN_CHECK_HDC
5230934a
VZ
410
411 // note that we combine the new clipping region with the existing one: this
412 // is compatible with what the other ports do and is the documented
413 // behaviour now (starting with 2.3.3)
3a5bcc4d 414#if defined(__WXWINCE__)
5230934a
VZ
415 RECT rectClip;
416 if ( !::GetClipBox(GetHdc(), &rectClip) )
417 return;
418
419 HRGN hrgnDest = ::CreateRectRgn(0, 0, 0, 0);
420 HRGN hrgnClipOld = ::CreateRectRgn(rectClip.left, rectClip.top,
421 rectClip.right, rectClip.bottom);
422
423 if ( ::CombineRgn(hrgnDest, hrgnClipOld, (HRGN)hrgn, RGN_AND) != ERROR )
424 {
425 ::SelectClipRgn(GetHdc(), hrgnDest);
426 }
427
428 ::DeleteObject(hrgnClipOld);
429 ::DeleteObject(hrgnDest);
3a5bcc4d 430#else // !WinCE
5230934a
VZ
431 if ( ::ExtSelectClipRgn(GetHdc(), (HRGN)hrgn, RGN_AND) == ERROR )
432 {
433 wxLogLastError(_T("ExtSelectClipRgn"));
434
435 return;
436 }
3a5bcc4d 437#endif // WinCE/!WinCE
d275c7eb 438
beb966c5 439 m_clipping = true;
40a89076 440
5230934a
VZ
441 UpdateClipBox();
442}
443
444void wxDC::DoSetClippingRegion(wxCoord x, wxCoord y, wxCoord w, wxCoord h)
445{
c4218a74
VZ
446 // the region coords are always the device ones, so do the translation
447 // manually
1e6feb95
VZ
448 //
449 // FIXME: possible +/-1 error here, to check!
c4218a74
VZ
450 HRGN hrgn = ::CreateRectRgn(LogicalToDeviceX(x),
451 LogicalToDeviceY(y),
452 LogicalToDeviceX(x + w),
453 LogicalToDeviceY(y + h));
40a89076
VZ
454 if ( !hrgn )
455 {
456 wxLogLastError(_T("CreateRectRgn"));
457 }
458 else
459 {
5230934a 460 SetClippingHrgn((WXHRGN)hrgn);
40a89076 461
5230934a 462 ::DeleteObject(hrgn);
40a89076 463 }
2bda0e17
KB
464}
465
a23fd0e1 466void wxDC::DoSetClippingRegionAsRegion(const wxRegion& region)
a724d789 467{
5230934a 468 SetClippingHrgn(region.GetHRGN());
2bda0e17
KB
469}
470
a23fd0e1 471void wxDC::DestroyClippingRegion()
2bda0e17 472{
82a306b7 473 WXMICROWIN_CHECK_HDC
d275c7eb 474
7bcb11d3
JS
475 if (m_clipping && m_hDC)
476 {
477 // TODO: this should restore the previous clipping region,
5230934a
VZ
478 // so that OnPaint processing works correctly, and the update
479 // clipping region doesn't get destroyed after the first
480 // DestroyClippingRegion.
7bcb11d3 481 HRGN rgn = CreateRectRgn(0, 0, 32000, 32000);
5230934a
VZ
482 ::SelectClipRgn(GetHdc(), rgn);
483 ::DeleteObject(rgn);
7bcb11d3 484 }
1e6feb95 485
2e76da54 486 wxDCBase::DestroyClippingRegion();
2bda0e17
KB
487}
488
a23fd0e1
VZ
489// ---------------------------------------------------------------------------
490// query capabilities
491// ---------------------------------------------------------------------------
492
493bool wxDC::CanDrawBitmap() const
2bda0e17 494{
beb966c5 495 return true;
2bda0e17
KB
496}
497
a23fd0e1 498bool wxDC::CanGetTextExtent() const
2bda0e17 499{
04ef50df
JS
500#ifdef __WXMICROWIN__
501 // TODO Extend MicroWindows' GetDeviceCaps function
beb966c5 502 return true;
04ef50df 503#else
7bcb11d3 504 // What sort of display is it?
a23fd0e1
VZ
505 int technology = ::GetDeviceCaps(GetHdc(), TECHNOLOGY);
506
507 return (technology == DT_RASDISPLAY) || (technology == DT_RASPRINTER);
04ef50df 508#endif
2bda0e17
KB
509}
510
a23fd0e1 511int wxDC::GetDepth() const
2bda0e17 512{
82a306b7 513 WXMICROWIN_CHECK_HDC_RET(16)
d275c7eb 514
a23fd0e1 515 return (int)::GetDeviceCaps(GetHdc(), BITSPIXEL);
2bda0e17
KB
516}
517
a23fd0e1
VZ
518// ---------------------------------------------------------------------------
519// drawing
520// ---------------------------------------------------------------------------
521
522void wxDC::Clear()
2bda0e17 523{
82a306b7 524 WXMICROWIN_CHECK_HDC
d275c7eb 525
7bcb11d3 526 RECT rect;
2506aab6
VZ
527 if ( m_canvas )
528 {
7bcb11d3 529 GetClientRect((HWND) m_canvas->GetHWND(), &rect);
2506aab6
VZ
530 }
531 else
7bcb11d3 532 {
eaeb6a3c
JS
533 // No, I think we should simply ignore this if printing on e.g.
534 // a printer DC.
535 // wxCHECK_RET( m_selectedBitmap.Ok(), wxT("this DC can't be cleared") );
536 if (!m_selectedBitmap.Ok())
537 return;
2506aab6 538
7bcb11d3
JS
539 rect.left = 0; rect.top = 0;
540 rect.right = m_selectedBitmap.GetWidth();
541 rect.bottom = m_selectedBitmap.GetHeight();
542 }
2506aab6 543
4676948b 544#ifndef __WXWINCE__
a23fd0e1 545 (void) ::SetMapMode(GetHdc(), MM_TEXT);
4676948b 546#endif
a23fd0e1 547
1e2081a1
VZ
548 DWORD colour = ::GetBkColor(GetHdc());
549 HBRUSH brush = ::CreateSolidBrush(colour);
550 ::FillRect(GetHdc(), &rect, brush);
551 ::DeleteObject(brush);
552
553 int width = DeviceToLogicalXRel(VIEWPORT_EXTENT)*m_signX,
554 height = DeviceToLogicalYRel(VIEWPORT_EXTENT)*m_signY;
a23fd0e1 555
4676948b 556#ifndef __WXWINCE__
a23fd0e1 557 ::SetMapMode(GetHdc(), MM_ANISOTROPIC);
4676948b 558
a23fd0e1 559 ::SetViewportExtEx(GetHdc(), VIEWPORT_EXTENT, VIEWPORT_EXTENT, NULL);
1e2081a1 560 ::SetWindowExtEx(GetHdc(), width, height, NULL);
a23fd0e1
VZ
561 ::SetViewportOrgEx(GetHdc(), (int)m_deviceOriginX, (int)m_deviceOriginY, NULL);
562 ::SetWindowOrgEx(GetHdc(), (int)m_logicalOriginX, (int)m_logicalOriginY, NULL);
4676948b 563#endif
a23fd0e1
VZ
564}
565
387ebd3e 566bool wxDC::DoFloodFill(wxCoord x, wxCoord y, const wxColour& col, int style)
a23fd0e1 567{
4676948b 568#ifdef __WXWINCE__
beb966c5 569 return false;
4676948b
JS
570#else
571
beb966c5 572 WXMICROWIN_CHECK_HDC_RET(false)
d275c7eb 573
387ebd3e 574 bool success = (0 != ::ExtFloodFill(GetHdc(), XLOG2DEV(x), YLOG2DEV(y),
0bafad0c
VZ
575 col.GetPixel(),
576 style == wxFLOOD_SURFACE ? FLOODFILLSURFACE
387ebd3e
JS
577 : FLOODFILLBORDER) ) ;
578 if (!success)
0bafad0c
VZ
579 {
580 // quoting from the MSDN docs:
581 //
582 // Following are some of the reasons this function might fail:
583 //
584 // * The filling could not be completed.
585 // * The specified point has the boundary color specified by the
586 // crColor parameter (if FLOODFILLBORDER was requested).
587 // * The specified point does not have the color specified by
588 // crColor (if FLOODFILLSURFACE was requested)
589 // * The point is outside the clipping region that is, it is not
590 // visible on the device.
591 //
f6bcfd97 592 wxLogLastError(wxT("ExtFloodFill"));
0bafad0c 593 }
a23fd0e1 594
7bcb11d3 595 CalcBoundingBox(x, y);
419430a0 596
387ebd3e 597 return success;
4676948b 598#endif
2bda0e17
KB
599}
600
72cdf4c9 601bool wxDC::DoGetPixel(wxCoord x, wxCoord y, wxColour *col) const
2bda0e17 602{
beb966c5 603 WXMICROWIN_CHECK_HDC_RET(false)
d275c7eb 604
beb966c5 605 wxCHECK_MSG( col, false, _T("NULL colour parameter in wxDC::GetPixel") );
f6bcfd97 606
7bcb11d3 607 // get the color of the pixel
a23fd0e1 608 COLORREF pixelcolor = ::GetPixel(GetHdc(), XLOG2DEV(x), YLOG2DEV(y));
0bafad0c 609
f6bcfd97 610 wxRGBToColour(*col, pixelcolor);
dc1efb1d 611
beb966c5 612 return true;
2bda0e17
KB
613}
614
72cdf4c9 615void wxDC::DoCrossHair(wxCoord x, wxCoord y)
a23fd0e1 616{
82a306b7 617 WXMICROWIN_CHECK_HDC
d275c7eb 618
72cdf4c9
VZ
619 wxCoord x1 = x-VIEWPORT_EXTENT;
620 wxCoord y1 = y-VIEWPORT_EXTENT;
621 wxCoord x2 = x+VIEWPORT_EXTENT;
622 wxCoord y2 = y+VIEWPORT_EXTENT;
a23fd0e1 623
4676948b
JS
624 wxDrawLine(GetHdc(), XLOG2DEV(x1), YLOG2DEV(y), XLOG2DEV(x2), YLOG2DEV(y));
625 wxDrawLine(GetHdc(), XLOG2DEV(x), YLOG2DEV(y1), XLOG2DEV(x), YLOG2DEV(y2));
a23fd0e1 626
7bcb11d3
JS
627 CalcBoundingBox(x1, y1);
628 CalcBoundingBox(x2, y2);
2bda0e17
KB
629}
630
72cdf4c9 631void wxDC::DoDrawLine(wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2)
2bda0e17 632{
82a306b7 633 WXMICROWIN_CHECK_HDC
d275c7eb 634
4676948b 635 wxDrawLine(GetHdc(), XLOG2DEV(x1), YLOG2DEV(y1), XLOG2DEV(x2), YLOG2DEV(y2));
a23fd0e1 636
7bcb11d3
JS
637 CalcBoundingBox(x1, y1);
638 CalcBoundingBox(x2, y2);
2bda0e17
KB
639}
640
f6bcfd97
BP
641// Draws an arc of a circle, centred on (xc, yc), with starting point (x1, y1)
642// and ending at (x2, y2)
643void wxDC::DoDrawArc(wxCoord x1, wxCoord y1,
644 wxCoord x2, wxCoord y2,
645 wxCoord xc, wxCoord yc)
2bda0e17 646{
4676948b 647#ifdef __WXWINCE__
4f10962b
JS
648 // Slower emulation since WinCE doesn't support Pie and Arc
649 double r = sqrt( (x1-xc)*(x1-xc) + (y1-yc)*(y1-yc) );
650 double sa = acos((x1-xc)/r)/M_PI*180; // between 0 and 180
651 if( y1>yc ) sa = -sa; // below center
652 double ea = atan2(yc-y2, x2-xc)/M_PI*180;
653 DoDrawEllipticArcRot( xc-r, yc-r, 2*r, 2*r, sa, ea );
4676948b
JS
654#else
655
82a306b7 656 WXMICROWIN_CHECK_HDC
d275c7eb 657
f6bcfd97 658 wxColourChanger cc(*this); // needed for wxSTIPPLE_MASK_OPAQUE handling
2d8a5cb1 659
f6bcfd97
BP
660 double dx = xc - x1;
661 double dy = yc - y1;
662 double radius = (double)sqrt(dx*dx+dy*dy);
663 wxCoord r = (wxCoord)radius;
2d8a5cb1 664
f6bcfd97
BP
665 // treat the special case of full circle separately
666 if ( x1 == x2 && y1 == y2 )
7bcb11d3 667 {
f6bcfd97 668 DrawEllipse(xc - r, yc - r, 2*r, 2*r);
a23fd0e1 669 return;
7bcb11d3 670 }
a23fd0e1 671
72cdf4c9
VZ
672 wxCoord xx1 = XLOG2DEV(x1);
673 wxCoord yy1 = YLOG2DEV(y1);
674 wxCoord xx2 = XLOG2DEV(x2);
675 wxCoord yy2 = YLOG2DEV(y2);
676 wxCoord xxc = XLOG2DEV(xc);
677 wxCoord yyc = YLOG2DEV(yc);
678 wxCoord ray = (wxCoord) sqrt(double((xxc-xx1)*(xxc-xx1)+(yyc-yy1)*(yyc-yy1)));
a23fd0e1 679
72cdf4c9
VZ
680 wxCoord xxx1 = (wxCoord) (xxc-ray);
681 wxCoord yyy1 = (wxCoord) (yyc-ray);
682 wxCoord xxx2 = (wxCoord) (xxc+ray);
683 wxCoord yyy2 = (wxCoord) (yyc+ray);
f6bcfd97
BP
684
685 if ( m_brush.Ok() && m_brush.GetStyle() != wxTRANSPARENT )
7bcb11d3
JS
686 {
687 // Have to add 1 to bottom-right corner of rectangle
688 // to make semi-circles look right (crooked line otherwise).
689 // Unfortunately this is not a reliable method, depends
690 // on the size of shape.
691 // TODO: figure out why this happens!
f6bcfd97 692 Pie(GetHdc(),xxx1,yyy1,xxx2+1,yyy2+1, xx1,yy1,xx2,yy2);
7bcb11d3
JS
693 }
694 else
2d8a5cb1 695 {
f6bcfd97 696 Arc(GetHdc(),xxx1,yyy1,xxx2,yyy2, xx1,yy1,xx2,yy2);
2d8a5cb1 697 }
f6bcfd97
BP
698
699 CalcBoundingBox(xc - r, yc - r);
700 CalcBoundingBox(xc + r, yc + r);
4676948b 701#endif
2bda0e17
KB
702}
703
cd9da200
VZ
704void wxDC::DoDrawCheckMark(wxCoord x1, wxCoord y1,
705 wxCoord width, wxCoord height)
706{
82a306b7 707 WXMICROWIN_CHECK_HDC
d275c7eb 708
cd9da200
VZ
709 wxCoord x2 = x1 + width,
710 y2 = y1 + height;
711
1e3c12d7 712#if defined(__WIN32__) && !defined(__SYMANTEC__) && !defined(__WXMICROWIN__)
cd9da200
VZ
713 RECT rect;
714 rect.left = x1;
715 rect.top = y1;
716 rect.right = x2;
717 rect.bottom = y2;
718
4676948b
JS
719#ifdef __WXWINCE__
720 DrawFrameControl(GetHdc(), &rect, DFC_BUTTON, DFCS_BUTTONCHECK);
721#else
cd9da200 722 DrawFrameControl(GetHdc(), &rect, DFC_MENU, DFCS_MENUCHECK);
4676948b 723#endif
3a5bcc4d
VZ
724#else // Symantec-MicroWin
725 // draw a cross
cd9da200
VZ
726 HPEN blackPen = ::CreatePen(PS_SOLID, 1, RGB(0, 0, 0));
727 HPEN whiteBrush = (HPEN)::GetStockObject(WHITE_BRUSH);
e06b9569
JS
728 HPEN hPenOld = (HPEN)::SelectObject(GetHdc(), blackPen);
729 HPEN hBrushOld = (HPEN)::SelectObject(GetHdc(), whiteBrush);
cd9da200
VZ
730 ::SetROP2(GetHdc(), R2_COPYPEN);
731 Rectangle(GetHdc(), x1, y1, x2, y2);
8cb172b4 732 MoveToEx(GetHdc(), x1, y1, NULL);
cd9da200 733 LineTo(GetHdc(), x2, y2);
8cb172b4 734 MoveToEx(GetHdc(), x2, y1, NULL);
cd9da200
VZ
735 LineTo(GetHdc(), x1, y2);
736 ::SelectObject(GetHdc(), hPenOld);
737 ::SelectObject(GetHdc(), hBrushOld);
738 ::DeleteObject(blackPen);
3a5bcc4d 739#endif // Win32/Symantec-MicroWin
cd9da200
VZ
740
741 CalcBoundingBox(x1, y1);
742 CalcBoundingBox(x2, y2);
743}
744
72cdf4c9 745void wxDC::DoDrawPoint(wxCoord x, wxCoord y)
2bda0e17 746{
82a306b7 747 WXMICROWIN_CHECK_HDC
d275c7eb 748
7bcb11d3
JS
749 COLORREF color = 0x00ffffff;
750 if (m_pen.Ok())
751 {
a23fd0e1 752 color = m_pen.GetColour().GetPixel();
7bcb11d3 753 }
a23fd0e1
VZ
754
755 SetPixel(GetHdc(), XLOG2DEV(x), YLOG2DEV(y), color);
756
7bcb11d3 757 CalcBoundingBox(x, y);
2bda0e17
KB
758}
759
72cdf4c9 760void wxDC::DoDrawPolygon(int n, wxPoint points[], wxCoord xoffset, wxCoord yoffset,int fillStyle)
2bda0e17 761{
82a306b7 762 WXMICROWIN_CHECK_HDC
d275c7eb 763
f6bcfd97 764 wxColourChanger cc(*this); // needed for wxSTIPPLE_MASK_OPAQUE handling
de2d2cdc 765
7bcb11d3
JS
766 // Do things less efficiently if we have offsets
767 if (xoffset != 0 || yoffset != 0)
6a6c0a8b 768 {
7bcb11d3
JS
769 POINT *cpoints = new POINT[n];
770 int i;
771 for (i = 0; i < n; i++)
772 {
773 cpoints[i].x = (int)(points[i].x + xoffset);
774 cpoints[i].y = (int)(points[i].y + yoffset);
a23fd0e1 775
7bcb11d3
JS
776 CalcBoundingBox(cpoints[i].x, cpoints[i].y);
777 }
4676948b 778#ifndef __WXWINCE__
a23fd0e1 779 int prev = SetPolyFillMode(GetHdc(),fillStyle==wxODDEVEN_RULE?ALTERNATE:WINDING);
4676948b 780#endif
a23fd0e1 781 (void)Polygon(GetHdc(), cpoints, n);
4676948b 782#ifndef __WXWINCE__
a23fd0e1 783 SetPolyFillMode(GetHdc(),prev);
4676948b 784#endif
7bcb11d3
JS
785 delete[] cpoints;
786 }
787 else
788 {
789 int i;
790 for (i = 0; i < n; i++)
791 CalcBoundingBox(points[i].x, points[i].y);
a23fd0e1 792
4676948b 793#ifndef __WXWINCE__
a23fd0e1 794 int prev = SetPolyFillMode(GetHdc(),fillStyle==wxODDEVEN_RULE?ALTERNATE:WINDING);
4676948b 795#endif
a23fd0e1 796 (void)Polygon(GetHdc(), (POINT*) points, n);
4676948b 797#ifndef __WXWINCE__
a23fd0e1 798 SetPolyFillMode(GetHdc(),prev);
4676948b 799#endif
6a6c0a8b 800 }
2bda0e17
KB
801}
802
6e76b35d
VZ
803void
804wxDC::DoDrawPolyPolygon(int n,
793db755 805 int count[],
6e76b35d
VZ
806 wxPoint points[],
807 wxCoord xoffset,
808 wxCoord yoffset,
809 int fillStyle)
810{
d61c1a6f 811#ifdef __WXWINCE__
95c1ea29 812 wxDCBase::DoDrawPolyPolygon(n, count, points, xoffset, yoffset, fillStyle);
d61c1a6f 813#else
82a306b7 814 WXMICROWIN_CHECK_HDC
6e76b35d
VZ
815
816 wxColourChanger cc(*this); // needed for wxSTIPPLE_MASK_OPAQUE handling
817 int i, cnt;
818 for (i = cnt = 0; i < n; i++)
793db755 819 cnt += count[i];
6e76b35d
VZ
820
821 // Do things less efficiently if we have offsets
822 if (xoffset != 0 || yoffset != 0)
823 {
824 POINT *cpoints = new POINT[cnt];
825 for (i = 0; i < cnt; i++)
826 {
827 cpoints[i].x = (int)(points[i].x + xoffset);
828 cpoints[i].y = (int)(points[i].y + yoffset);
829
830 CalcBoundingBox(cpoints[i].x, cpoints[i].y);
831 }
d61c1a6f 832#ifndef __WXWINCE__
6e76b35d 833 int prev = SetPolyFillMode(GetHdc(),fillStyle==wxODDEVEN_RULE?ALTERNATE:WINDING);
d61c1a6f 834#endif
793db755 835 (void)PolyPolygon(GetHdc(), cpoints, count, n);
d61c1a6f 836#ifndef __WXWINCE__
6e76b35d 837 SetPolyFillMode(GetHdc(),prev);
d61c1a6f 838#endif
6e76b35d
VZ
839 delete[] cpoints;
840 }
841 else
842 {
843 for (i = 0; i < cnt; i++)
844 CalcBoundingBox(points[i].x, points[i].y);
845
d61c1a6f 846#ifndef __WXWINCE__
6e76b35d 847 int prev = SetPolyFillMode(GetHdc(),fillStyle==wxODDEVEN_RULE?ALTERNATE:WINDING);
d61c1a6f 848#endif
793db755 849 (void)PolyPolygon(GetHdc(), (POINT*) points, count, n);
d61c1a6f 850#ifndef __WXWINCE__
6e76b35d 851 SetPolyFillMode(GetHdc(),prev);
d61c1a6f 852#endif
6e76b35d 853 }
d61c1a6f
JS
854#endif
855 // __WXWINCE__
6e76b35d
VZ
856}
857
72cdf4c9 858void wxDC::DoDrawLines(int n, wxPoint points[], wxCoord xoffset, wxCoord yoffset)
2bda0e17 859{
82a306b7 860 WXMICROWIN_CHECK_HDC
d275c7eb 861
7bcb11d3
JS
862 // Do things less efficiently if we have offsets
863 if (xoffset != 0 || yoffset != 0)
6a6c0a8b 864 {
7bcb11d3
JS
865 POINT *cpoints = new POINT[n];
866 int i;
867 for (i = 0; i < n; i++)
868 {
869 cpoints[i].x = (int)(points[i].x + xoffset);
870 cpoints[i].y = (int)(points[i].y + yoffset);
a23fd0e1 871
7bcb11d3
JS
872 CalcBoundingBox(cpoints[i].x, cpoints[i].y);
873 }
a23fd0e1 874 (void)Polyline(GetHdc(), cpoints, n);
7bcb11d3
JS
875 delete[] cpoints;
876 }
877 else
878 {
879 int i;
880 for (i = 0; i < n; i++)
881 CalcBoundingBox(points[i].x, points[i].y);
a23fd0e1
VZ
882
883 (void)Polyline(GetHdc(), (POINT*) points, n);
6a6c0a8b 884 }
2bda0e17
KB
885}
886
72cdf4c9 887void wxDC::DoDrawRectangle(wxCoord x, wxCoord y, wxCoord width, wxCoord height)
2bda0e17 888{
82a306b7 889 WXMICROWIN_CHECK_HDC
d275c7eb 890
f6bcfd97 891 wxColourChanger cc(*this); // needed for wxSTIPPLE_MASK_OPAQUE handling
de2d2cdc 892
72cdf4c9
VZ
893 wxCoord x2 = x + width;
894 wxCoord y2 = y + height;
a23fd0e1 895
5456b916 896 if ((m_logicalFunction == wxCOPY) && (m_pen.GetStyle() == wxTRANSPARENT))
0bafad0c 897 {
7299b1b2 898 RECT rect;
5456b916
RR
899 rect.left = XLOG2DEV(x);
900 rect.top = YLOG2DEV(y);
901 rect.right = XLOG2DEV(x2);
7299b1b2
RD
902 rect.bottom = YLOG2DEV(y2);
903 (void)FillRect(GetHdc(), &rect, (HBRUSH)m_brush.GetResourceHandle() );
5456b916
RR
904 }
905 else
906 {
907 // Windows draws the filled rectangles without outline (i.e. drawn with a
908 // transparent pen) one pixel smaller in both directions and we want them
f6bcfd97 909 // to have the same size regardless of which pen is used - adjust
5456b916
RR
910
911