]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/msw/dc.cpp
fixed TREE_ITEM_MENU generation from right mouse clicks: don't pass WM_RBUTTONDOWN...
[wxWidgets.git] / src / msw / dc.cpp
... / ...
CommitLineData
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$
8// Copyright: (c) Julian Smart
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
12// ===========================================================================
13// declarations
14// ===========================================================================
15
16// ---------------------------------------------------------------------------
17// headers
18// ---------------------------------------------------------------------------
19
20#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
21 #pragma implementation "dc.h"
22#endif
23
24// For compilers that support precompilation, includes "wx.h".
25#include "wx/wxprec.h"
26
27#ifdef __BORLANDC__
28 #pragma hdrstop
29#endif
30
31#ifndef WX_PRECOMP
32 #include "wx/image.h"
33 #include "wx/window.h"
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"
40 #include "wx/log.h"
41 #include "wx/icon.h"
42#endif
43
44#include "wx/sysopt.h"
45#include "wx/dcprint.h"
46#include "wx/module.h"
47#include "wx/dynload.h"
48
49#ifdef wxHAVE_RAW_BITMAP
50#include "wx/rawbmp.h"
51#endif
52
53#include <string.h>
54
55#include "wx/msw/wrapcdlg.h"
56#ifndef __WIN32__
57 #include <print.h>
58#endif
59
60#ifndef AC_SRC_ALPHA
61#define AC_SRC_ALPHA 1
62#endif
63
64/* Quaternary raster codes */
65#ifndef MAKEROP4
66#define MAKEROP4(fore,back) (DWORD)((((back) << 8) & 0xFF000000) | (fore))
67#endif
68
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
79IMPLEMENT_ABSTRACT_CLASS(wxDC, wxDCBase)
80
81// ---------------------------------------------------------------------------
82// constants
83// ---------------------------------------------------------------------------
84
85static const int VIEWPORT_EXTENT = 1000;
86
87static const int MM_POINTS = 9;
88static const int MM_METRIC = 10;
89
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
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
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
116
117// ---------------------------------------------------------------------------
118// private functions
119// ---------------------------------------------------------------------------
120
121// convert degrees to radians
122static inline double DegToRad(double deg) { return (deg * M_PI) / 180.0; }
123
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);
136
137#ifdef wxHAVE_RAW_BITMAP
138// our (limited) AlphaBlend() replacement
139static void
140wxAlphaBlend(HDC hdcDst, int x, int y, int w, int h, const wxBitmap& bmp);
141#endif
142
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;
165
166 DECLARE_NO_COPY_CLASS(wxColourChanger)
167};
168
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 {
176#ifndef __WXWINCE__
177 m_modeOld = ::SetStretchBltMode(m_hdc, mode);
178 if ( !m_modeOld )
179 wxLogLastError(_T("SetStretchBltMode"));
180#else
181 wxUnusedVar(mode);
182#endif
183 }
184
185 ~StretchBltModeChanger()
186 {
187#ifndef __WXWINCE__
188 if ( !::SetStretchBltMode(m_hdc, m_modeOld) )
189 wxLogLastError(_T("SetStretchBltMode"));
190#endif
191 }
192
193private:
194 const HDC m_hdc;
195
196 int m_modeOld;
197
198 DECLARE_NO_COPY_CLASS(StretchBltModeChanger)
199};
200
201// ===========================================================================
202// implementation
203// ===========================================================================
204
205// ----------------------------------------------------------------------------
206// wxColourChanger
207// ----------------------------------------------------------------------------
208
209wxColourChanger::wxColourChanger(wxDC& dc) : m_dc(dc)
210{
211 const wxBrush& brush = dc.GetBrush();
212 if ( brush.Ok() && brush.GetStyle() == wxSTIPPLE_MASK_OPAQUE )
213 {
214 HDC hdc = GetHdcOf(dc);
215 m_colFgOld = ::GetTextColor(hdc);
216 m_colBgOld = ::GetBkColor(hdc);
217
218 // note that Windows convention is opposite to wxWidgets one, this is
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
237 m_changed = true;
238 }
239 else
240 {
241 // nothing done, nothing to undo
242 m_changed = false;
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
259// ---------------------------------------------------------------------------
260// wxDC
261// ---------------------------------------------------------------------------
262
263// Default constructor
264wxDC::wxDC()
265{
266 m_canvas = NULL;
267
268 m_oldBitmap = 0;
269 m_oldPen = 0;
270 m_oldBrush = 0;
271 m_oldFont = 0;
272#if wxUSE_PALETTE
273 m_oldPalette = 0;
274#endif // wxUSE_PALETTE
275
276 m_bOwnsDC = false;
277 m_hDC = 0;
278}
279
280wxDC::~wxDC()
281{
282 if ( m_hDC != 0 )
283 {
284 SelectOldObjects(m_hDC);
285
286 // if we own the HDC, we delete it, otherwise we just release it
287
288 if ( m_bOwnsDC )
289 {
290 ::DeleteDC(GetHdc());
291 }
292 else // we don't own our HDC
293 {
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 }
303 }
304 }
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{
312 if (dc)
313 {
314 if (m_oldBitmap)
315 {
316 ::SelectObject((HDC) dc, (HBITMAP) m_oldBitmap);
317#ifdef __WXDEBUG__
318 if (m_selectedBitmap.Ok())
319 {
320 m_selectedBitmap.SetSelectedInto(NULL);
321 }
322#endif
323 }
324 m_oldBitmap = 0;
325 if (m_oldPen)
326 {
327 ::SelectObject((HDC) dc, (HPEN) m_oldPen);
328 }
329 m_oldPen = 0;
330 if (m_oldBrush)
331 {
332 ::SelectObject((HDC) dc, (HBRUSH) m_oldBrush);
333 }
334 m_oldBrush = 0;
335 if (m_oldFont)
336 {
337 ::SelectObject((HDC) dc, (HFONT) m_oldFont);
338 }
339 m_oldFont = 0;
340
341#if wxUSE_PALETTE
342 if (m_oldPalette)
343 {
344 ::SelectPalette((HDC) dc, (HPALETTE) m_oldPalette, FALSE);
345 }
346 m_oldPalette = 0;
347#endif // wxUSE_PALETTE
348 }
349
350 m_brush = wxNullBrush;
351 m_pen = wxNullPen;
352#if wxUSE_PALETTE
353 m_palette = wxNullPalette;
354#endif // wxUSE_PALETTE
355 m_font = wxNullFont;
356 m_backgroundBrush = wxNullBrush;
357 m_selectedBitmap = wxNullBitmap;
358}
359
360// ---------------------------------------------------------------------------
361// clipping
362// ---------------------------------------------------------------------------
363
364void wxDC::UpdateClipBox()
365{
366 WXMICROWIN_CHECK_HDC
367
368 RECT rect;
369 ::GetClipBox(GetHdc(), &rect);
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);
375}
376
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 {
385 wxDC *self = wxConstCast(this, wxDC);
386 self->UpdateClipBox();
387
388 if ( !m_clipX1 && !m_clipX2 )
389 self->m_clipping = false;
390 }
391
392 wxDCBase::DoGetClippingBox(x, y, w, h);
393}
394
395// common part of DoSetClippingRegion() and DoSetClippingRegionAsRegion()
396void wxDC::SetClippingHrgn(WXHRGN hrgn)
397{
398 wxCHECK_RET( hrgn, wxT("invalid clipping region") );
399
400 WXMICROWIN_CHECK_HDC
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)
405#if defined(__WXWINCE__)
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);
421#else // !WinCE
422 if ( ::ExtSelectClipRgn(GetHdc(), (HRGN)hrgn, RGN_AND) == ERROR )
423 {
424 wxLogLastError(_T("ExtSelectClipRgn"));
425
426 return;
427 }
428#endif // WinCE/!WinCE
429
430 m_clipping = true;
431
432 UpdateClipBox();
433}
434
435void wxDC::DoSetClippingRegion(wxCoord x, wxCoord y, wxCoord w, wxCoord h)
436{
437 // the region coords are always the device ones, so do the translation
438 // manually
439 //
440 // FIXME: possible +/-1 error here, to check!
441 HRGN hrgn = ::CreateRectRgn(LogicalToDeviceX(x),
442 LogicalToDeviceY(y),
443 LogicalToDeviceX(x + w),
444 LogicalToDeviceY(y + h));
445 if ( !hrgn )
446 {
447 wxLogLastError(_T("CreateRectRgn"));
448 }
449 else
450 {
451 SetClippingHrgn((WXHRGN)hrgn);
452
453 ::DeleteObject(hrgn);
454 }
455}
456
457void wxDC::DoSetClippingRegionAsRegion(const wxRegion& region)
458{
459 SetClippingHrgn(region.GetHRGN());
460}
461
462void wxDC::DestroyClippingRegion()
463{
464 WXMICROWIN_CHECK_HDC
465
466 if (m_clipping && m_hDC)
467 {
468 // TODO: this should restore the previous clipping region,
469 // so that OnPaint processing works correctly, and the update
470 // clipping region doesn't get destroyed after the first
471 // DestroyClippingRegion.
472 HRGN rgn = CreateRectRgn(0, 0, 32000, 32000);
473 ::SelectClipRgn(GetHdc(), rgn);
474 ::DeleteObject(rgn);
475 }
476
477 wxDCBase::DestroyClippingRegion();
478}
479
480// ---------------------------------------------------------------------------
481// query capabilities
482// ---------------------------------------------------------------------------
483
484bool wxDC::CanDrawBitmap() const
485{
486 return true;
487}
488
489bool wxDC::CanGetTextExtent() const
490{
491#ifdef __WXMICROWIN__
492 // TODO Extend MicroWindows' GetDeviceCaps function
493 return true;
494#else
495 // What sort of display is it?
496 int technology = ::GetDeviceCaps(GetHdc(), TECHNOLOGY);
497
498 return (technology == DT_RASDISPLAY) || (technology == DT_RASPRINTER);
499#endif
500}
501
502int wxDC::GetDepth() const
503{
504 WXMICROWIN_CHECK_HDC_RET(16)
505
506 return (int)::GetDeviceCaps(GetHdc(), BITSPIXEL);
507}
508
509// ---------------------------------------------------------------------------
510// drawing
511// ---------------------------------------------------------------------------
512
513void wxDC::Clear()
514{
515 WXMICROWIN_CHECK_HDC
516
517 RECT rect;
518 if ( m_canvas )
519 {
520 GetClientRect((HWND) m_canvas->GetHWND(), &rect);
521 }
522 else
523 {
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;
529
530 rect.left = 0; rect.top = 0;
531 rect.right = m_selectedBitmap.GetWidth();
532 rect.bottom = m_selectedBitmap.GetHeight();
533 }
534
535#ifndef __WXWINCE__
536 (void) ::SetMapMode(GetHdc(), MM_TEXT);
537#endif
538
539 DWORD colour = ::GetBkColor(GetHdc());
540 HBRUSH brush = ::CreateSolidBrush(colour);
541 ::FillRect(GetHdc(), &rect, brush);
542 ::DeleteObject(brush);
543
544#ifndef __WXWINCE__
545 int width = DeviceToLogicalXRel(VIEWPORT_EXTENT)*m_signX,
546 height = DeviceToLogicalYRel(VIEWPORT_EXTENT)*m_signY;
547
548 ::SetMapMode(GetHdc(), MM_ANISOTROPIC);
549
550 ::SetViewportExtEx(GetHdc(), VIEWPORT_EXTENT, VIEWPORT_EXTENT, NULL);
551 ::SetWindowExtEx(GetHdc(), width, height, NULL);
552 ::SetViewportOrgEx(GetHdc(), (int)m_deviceOriginX, (int)m_deviceOriginY, NULL);
553 ::SetWindowOrgEx(GetHdc(), (int)m_logicalOriginX, (int)m_logicalOriginY, NULL);
554#endif
555}
556
557bool wxDC::DoFloodFill(wxCoord x, wxCoord y, const wxColour& col, int style)
558{
559#ifdef __WXWINCE__
560 wxUnusedVar(x);
561 wxUnusedVar(y);
562 wxUnusedVar(col);
563 wxUnusedVar(style);
564 return false;
565#else
566
567 WXMICROWIN_CHECK_HDC_RET(false)
568
569 bool success = (0 != ::ExtFloodFill(GetHdc(), XLOG2DEV(x), YLOG2DEV(y),
570 col.GetPixel(),
571 style == wxFLOOD_SURFACE ? FLOODFILLSURFACE
572 : FLOODFILLBORDER) ) ;
573 if (!success)
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 //
587 wxLogLastError(wxT("ExtFloodFill"));
588 }
589
590 CalcBoundingBox(x, y);
591
592 return success;
593#endif
594}
595
596bool wxDC::DoGetPixel(wxCoord x, wxCoord y, wxColour *col) const
597{
598 WXMICROWIN_CHECK_HDC_RET(false)
599
600 wxCHECK_MSG( col, false, _T("NULL colour parameter in wxDC::GetPixel") );
601
602 // get the color of the pixel
603 COLORREF pixelcolor = ::GetPixel(GetHdc(), XLOG2DEV(x), YLOG2DEV(y));
604
605 wxRGBToColour(*col, pixelcolor);
606
607 return true;
608}
609
610void wxDC::DoCrossHair(wxCoord x, wxCoord y)
611{
612 WXMICROWIN_CHECK_HDC
613
614 wxCoord x1 = x-VIEWPORT_EXTENT;
615 wxCoord y1 = y-VIEWPORT_EXTENT;
616 wxCoord x2 = x+VIEWPORT_EXTENT;
617 wxCoord y2 = y+VIEWPORT_EXTENT;
618
619 wxDrawLine(GetHdc(), XLOG2DEV(x1), YLOG2DEV(y), XLOG2DEV(x2), YLOG2DEV(y));
620 wxDrawLine(GetHdc(), XLOG2DEV(x), YLOG2DEV(y1), XLOG2DEV(x), YLOG2DEV(y2));
621
622 CalcBoundingBox(x1, y1);
623 CalcBoundingBox(x2, y2);
624}
625
626void wxDC::DoDrawLine(wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2)
627{
628 WXMICROWIN_CHECK_HDC
629
630 wxDrawLine(GetHdc(), XLOG2DEV(x1), YLOG2DEV(y1), XLOG2DEV(x2), YLOG2DEV(y2));
631
632 CalcBoundingBox(x1, y1);
633 CalcBoundingBox(x2, y2);
634}
635
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)
641{
642#ifdef __WXWINCE__
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 );
649#else
650
651 WXMICROWIN_CHECK_HDC
652
653 wxColourChanger cc(*this); // needed for wxSTIPPLE_MASK_OPAQUE handling
654
655 double dx = xc - x1;
656 double dy = yc - y1;
657 double radius = (double)sqrt(dx*dx+dy*dy);
658 wxCoord r = (wxCoord)radius;
659
660 // treat the special case of full circle separately
661 if ( x1 == x2 && y1 == y2 )
662 {
663 DrawEllipse(xc - r, yc - r, 2*r, 2*r);
664 return;
665 }
666
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)));
674
675 wxCoord xxx1 = (wxCoord) (xxc-ray);
676 wxCoord yyy1 = (wxCoord) (yyc-ray);
677 wxCoord xxx2 = (wxCoord) (xxc+ray);
678 wxCoord yyy2 = (wxCoord) (yyc+ray);
679
680 if ( m_brush.Ok() && m_brush.GetStyle() != wxTRANSPARENT )
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!
687 Pie(GetHdc(),xxx1,yyy1,xxx2+1,yyy2+1, xx1,yy1,xx2,yy2);
688 }
689 else
690 {
691 Arc(GetHdc(),xxx1,yyy1,xxx2,yyy2, xx1,yy1,xx2,yy2);
692 }
693
694 CalcBoundingBox(xc - r, yc - r);
695 CalcBoundingBox(xc + r, yc + r);
696#endif
697}
698
699void wxDC::DoDrawCheckMark(wxCoord x1, wxCoord y1,
700 wxCoord width, wxCoord height)
701{
702 WXMICROWIN_CHECK_HDC
703
704 wxCoord x2 = x1 + width,
705 y2 = y1 + height;
706
707#if defined(__WIN32__) && !defined(__SYMANTEC__) && !defined(__WXMICROWIN__)
708 RECT rect;
709 rect.left = x1;
710 rect.top = y1;
711 rect.right = x2;
712 rect.bottom = y2;
713
714#ifdef __WXWINCE__
715 DrawFrameControl(GetHdc(), &rect, DFC_BUTTON, DFCS_BUTTONCHECK);
716#else
717 DrawFrameControl(GetHdc(), &rect, DFC_MENU, DFCS_MENUCHECK);
718#endif
719#else // Symantec-MicroWin
720 // draw a cross
721 HPEN blackPen = ::CreatePen(PS_SOLID, 1, RGB(0, 0, 0));
722 HPEN whiteBrush = (HPEN)::GetStockObject(WHITE_BRUSH);
723 HPEN hPenOld = (HPEN)::SelectObject(GetHdc(), blackPen);
724 HPEN hBrushOld = (HPEN)::SelectObject(GetHdc(), whiteBrush);
725 ::SetROP2(GetHdc(), R2_COPYPEN);
726 Rectangle(GetHdc(), x1, y1, x2, y2);
727 MoveToEx(GetHdc(), x1, y1, NULL);
728 LineTo(GetHdc(), x2, y2);
729 MoveToEx(GetHdc(), x2, y1, NULL);
730 LineTo(GetHdc(), x1, y2);
731 ::SelectObject(GetHdc(), hPenOld);
732 ::SelectObject(GetHdc(), hBrushOld);
733 ::DeleteObject(blackPen);
734#endif // Win32/Symantec-MicroWin
735
736 CalcBoundingBox(x1, y1);
737 CalcBoundingBox(x2, y2);
738}
739
740void wxDC::DoDrawPoint(wxCoord x, wxCoord y)
741{
742 WXMICROWIN_CHECK_HDC
743
744 COLORREF color = 0x00ffffff;
745 if (m_pen.Ok())
746 {
747 color = m_pen.GetColour().GetPixel();
748 }
749
750 SetPixel(GetHdc(), XLOG2DEV(x), YLOG2DEV(y), color);
751
752 CalcBoundingBox(x, y);
753}
754
755void wxDC::DoDrawPolygon(int n, wxPoint points[], wxCoord xoffset, wxCoord yoffset,int fillStyle)
756{
757 WXMICROWIN_CHECK_HDC
758
759 wxColourChanger cc(*this); // needed for wxSTIPPLE_MASK_OPAQUE handling
760
761 // Do things less efficiently if we have offsets
762 if (xoffset != 0 || yoffset != 0)
763 {
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);
770
771 CalcBoundingBox(cpoints[i].x, cpoints[i].y);
772 }
773#ifndef __WXWINCE__
774 int prev = SetPolyFillMode(GetHdc(),fillStyle==wxODDEVEN_RULE?ALTERNATE:WINDING);
775#else
776 wxUnusedVar(fillStyle);
777#endif
778 (void)Polygon(GetHdc(), cpoints, n);
779#ifndef __WXWINCE__
780 SetPolyFillMode(GetHdc(),prev);
781#endif
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);
789
790#ifndef __WXWINCE__
791 int prev = SetPolyFillMode(GetHdc(),fillStyle==wxODDEVEN_RULE?ALTERNATE:WINDING);
792#endif
793 (void)Polygon(GetHdc(), (POINT*) points, n);
794#ifndef __WXWINCE__
795 SetPolyFillMode(GetHdc(),prev);
796#endif
797 }
798}
799
800void
801wxDC::DoDrawPolyPolygon(int n,
802 int count[],
803 wxPoint points[],
804 wxCoord xoffset,
805 wxCoord yoffset,
806 int fillStyle)
807{
808#ifdef __WXWINCE__
809 wxDCBase::DoDrawPolyPolygon(n, count, points, xoffset, yoffset, fillStyle);
810#else
811 WXMICROWIN_CHECK_HDC
812
813 wxColourChanger cc(*this); // needed for wxSTIPPLE_MASK_OPAQUE handling
814 int i, cnt;
815 for (i = cnt = 0; i < n; i++)
816 cnt += count[i];
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 }
829#ifndef __WXWINCE__
830 int prev = SetPolyFillMode(GetHdc(),fillStyle==wxODDEVEN_RULE?ALTERNATE:WINDING);
831#endif
832 (void)PolyPolygon(GetHdc(), cpoints, count, n);
833#ifndef __WXWINCE__
834 SetPolyFillMode(GetHdc(),prev);
835#endif
836 delete[] cpoints;
837 }
838 else
839 {
840 for (i = 0; i < cnt; i++)
841 CalcBoundingBox(points[i].x, points[i].y);
842
843#ifndef __WXWINCE__
844 int prev = SetPolyFillMode(GetHdc(),fillStyle==wxODDEVEN_RULE?ALTERNATE:WINDING);
845#endif
846 (void)PolyPolygon(GetHdc(), (POINT*) points, count, n);
847#ifndef __WXWINCE__
848 SetPolyFillMode(GetHdc(),prev);
849#endif
850 }
851#endif
852 // __WXWINCE__
853}
854
855void wxDC::DoDrawLines(int n, wxPoint points[], wxCoord xoffset, wxCoord yoffset)
856{
857 WXMICROWIN_CHECK_HDC
858
859 // Do things less efficiently if we have offsets
860 if (xoffset != 0 || yoffset != 0)
861 {
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);
868
869 CalcBoundingBox(cpoints[i].x, cpoints[i].y);
870 }
871 (void)Polyline(GetHdc(), cpoints, n);
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);
879
880 (void)Polyline(GetHdc(), (POINT*) points, n);
881 }
882}
883
884void wxDC::DoDrawRectangle(wxCoord x, wxCoord y, wxCoord width, wxCoord height)
885{
886 WXMICROWIN_CHECK_HDC
887
888 wxColourChanger cc(*this); // needed for wxSTIPPLE_MASK_OPAQUE handling
889
890 wxCoord x2 = x + width;
891 wxCoord y2 = y + height;
892
893 if ((m_logicalFunction == wxCOPY) && (m_pen.GetStyle() == wxTRANSPARENT))
894 {
895 RECT rect;
896 rect.left = XLOG2DEV(x);
897 rect.top = YLOG2DEV(y);
898 rect.right = XLOG2DEV(x2);
899 rect.bottom = YLOG2DEV(y2);
900 (void)FillRect(GetHdc(), &rect, (HBRUSH)m_brush.GetResourceHandle() );
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
906 // to have the same size regardless of which pen is used - adjust
907
908