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