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