]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/msw/dc.cpp
Checkable items in wxToolMenuBarTool supported.
[wxWidgets.git] / src / msw / dc.cpp
... / ...
CommitLineData
1/////////////////////////////////////////////////////////////////////////////
2// Name: src/msw/dc.cpp
3// Purpose: wxDC class for MSW port
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// For compilers that support precompilation, includes "wx.h".
21#include "wx/wxprec.h"
22
23#ifdef __BORLANDC__
24 #pragma hdrstop
25#endif
26
27#ifndef WX_PRECOMP
28 #include "wx/image.h"
29 #include "wx/window.h"
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"
36 #include "wx/log.h"
37 #include "wx/icon.h"
38#endif
39
40#include "wx/sysopt.h"
41#include "wx/dcprint.h"
42#include "wx/module.h"
43#include "wx/dynload.h"
44
45#ifdef wxHAVE_RAW_BITMAP
46#include "wx/rawbmp.h"
47#endif
48
49#include <string.h>
50
51#include "wx/msw/wrapcdlg.h"
52#ifndef __WIN32__
53 #include <print.h>
54#endif
55
56#ifndef AC_SRC_ALPHA
57#define AC_SRC_ALPHA 1
58#endif
59
60/* Quaternary raster codes */
61#ifndef MAKEROP4
62#define MAKEROP4(fore,back) (DWORD)((((back) << 8) & 0xFF000000) | (fore))
63#endif
64
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
75IMPLEMENT_ABSTRACT_CLASS(wxDC, wxDCBase)
76
77// ---------------------------------------------------------------------------
78// constants
79// ---------------------------------------------------------------------------
80
81static const int VIEWPORT_EXTENT = 1000;
82
83static const int MM_POINTS = 9;
84static const int MM_METRIC = 10;
85
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
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
101#ifdef __WXWINCE__
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)
106#else
107 #define XLOG2DEV(x) (x)
108 #define YLOG2DEV(y) (y)
109 #define XDEV2LOG(x) (x)
110 #define YDEV2LOG(y) (y)
111#endif
112
113// ---------------------------------------------------------------------------
114// private functions
115// ---------------------------------------------------------------------------
116
117// convert degrees to radians
118static inline double DegToRad(double deg) { return (deg * M_PI) / 180.0; }
119
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,
130 int srcX, int srcY, HDC hdcSrc,
131 const wxBitmap& bmpSrc);
132
133#ifdef wxHAVE_RAW_BITMAP
134
135// our (limited) AlphaBlend() replacement for Windows versions not providing it
136static void
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
141
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;
164
165 DECLARE_NO_COPY_CLASS(wxColourChanger)
166};
167
168// this class saves the old stretch blit mode during its life time
169class StretchBltModeChanger
170{
171public:
172 StretchBltModeChanger(HDC hdc,
173 int WXUNUSED_IN_WINCE(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#endif
181 }
182
183 ~StretchBltModeChanger()
184 {
185#ifndef __WXWINCE__
186 if ( !::SetStretchBltMode(m_hdc, m_modeOld) )
187 wxLogLastError(_T("SetStretchBltMode"));
188#endif
189 }
190
191private:
192 const HDC m_hdc;
193
194 int m_modeOld;
195
196 DECLARE_NO_COPY_CLASS(StretchBltModeChanger)
197};
198
199// ===========================================================================
200// implementation
201// ===========================================================================
202
203// ----------------------------------------------------------------------------
204// wxColourChanger
205// ----------------------------------------------------------------------------
206
207wxColourChanger::wxColourChanger(wxDC& dc) : m_dc(dc)
208{
209 const wxBrush& brush = dc.GetBrush();
210 if ( brush.Ok() && brush.GetStyle() == wxSTIPPLE_MASK_OPAQUE )
211 {
212 HDC hdc = GetHdcOf(dc);
213 m_colFgOld = ::GetTextColor(hdc);
214 m_colBgOld = ::GetBkColor(hdc);
215
216 // note that Windows convention is opposite to wxWidgets one, this is
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
235 m_changed = true;
236 }
237 else
238 {
239 // nothing done, nothing to undo
240 m_changed = false;
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
257// ---------------------------------------------------------------------------
258// wxDC
259// ---------------------------------------------------------------------------
260
261wxDC::~wxDC()
262{
263 if ( m_hDC != 0 )
264 {
265 SelectOldObjects(m_hDC);
266
267 // if we own the HDC, we delete it, otherwise we just release it
268
269 if ( m_bOwnsDC )
270 {
271 ::DeleteDC(GetHdc());
272 }
273 else // we don't own our HDC
274 {
275 if (m_canvas)
276 {
277 ::ReleaseDC(GetHwndOf(m_canvas), GetHdc());
278 }
279 else
280 {
281 // Must have been a wxScreenDC
282 ::ReleaseDC((HWND) NULL, GetHdc());
283 }
284 }
285 }
286}
287
288// This will select current objects out of the DC,
289// which is what you have to do before deleting the
290// DC.
291void wxDC::SelectOldObjects(WXHDC dc)
292{
293 if (dc)
294 {
295 if (m_oldBitmap)
296 {
297 ::SelectObject((HDC) dc, (HBITMAP) m_oldBitmap);
298#ifdef __WXDEBUG__
299 if (m_selectedBitmap.Ok())
300 {
301 m_selectedBitmap.SetSelectedInto(NULL);
302 }
303#endif
304 }
305 m_oldBitmap = 0;
306 if (m_oldPen)
307 {
308 ::SelectObject((HDC) dc, (HPEN) m_oldPen);
309 }
310 m_oldPen = 0;
311 if (m_oldBrush)
312 {
313 ::SelectObject((HDC) dc, (HBRUSH) m_oldBrush);
314 }
315 m_oldBrush = 0;
316 if (m_oldFont)
317 {
318 ::SelectObject((HDC) dc, (HFONT) m_oldFont);
319 }
320 m_oldFont = 0;
321
322#if wxUSE_PALETTE
323 if (m_oldPalette)
324 {
325 ::SelectPalette((HDC) dc, (HPALETTE) m_oldPalette, FALSE);
326 }
327 m_oldPalette = 0;
328#endif // wxUSE_PALETTE
329 }
330
331 m_brush = wxNullBrush;
332 m_pen = wxNullPen;
333#if wxUSE_PALETTE
334 m_palette = wxNullPalette;
335#endif // wxUSE_PALETTE
336 m_font = wxNullFont;
337 m_backgroundBrush = wxNullBrush;
338 m_selectedBitmap = wxNullBitmap;
339}
340
341// ---------------------------------------------------------------------------
342// clipping
343// ---------------------------------------------------------------------------
344
345void wxDC::UpdateClipBox()
346{
347 WXMICROWIN_CHECK_HDC
348
349 RECT rect;
350 ::GetClipBox(GetHdc(), &rect);
351
352 m_clipX1 = (wxCoord) XDEV2LOG(rect.left);
353 m_clipY1 = (wxCoord) YDEV2LOG(rect.top);
354 m_clipX2 = (wxCoord) XDEV2LOG(rect.right);
355 m_clipY2 = (wxCoord) YDEV2LOG(rect.bottom);
356}
357
358void
359wxDC::DoGetClippingBox(wxCoord *x, wxCoord *y, wxCoord *w, wxCoord *h) const
360{
361 // check if we should try to retrieve the clipping region possibly not set
362 // by our SetClippingRegion() but preset by Windows:this can only happen
363 // when we're associated with an existing HDC usign SetHDC(), see there
364 if ( m_clipping && !m_clipX1 && !m_clipX2 )
365 {
366 wxDC *self = wxConstCast(this, wxDC);
367 self->UpdateClipBox();
368
369 if ( !m_clipX1 && !m_clipX2 )
370 self->m_clipping = false;
371 }
372
373 wxDCBase::DoGetClippingBox(x, y, w, h);
374}
375
376// common part of DoSetClippingRegion() and DoSetClippingRegionAsRegion()
377void wxDC::SetClippingHrgn(WXHRGN hrgn)
378{
379 wxCHECK_RET( hrgn, wxT("invalid clipping region") );
380
381 WXMICROWIN_CHECK_HDC
382
383 // note that we combine the new clipping region with the existing one: this
384 // is compatible with what the other ports do and is the documented
385 // behaviour now (starting with 2.3.3)
386#if defined(__WXWINCE__)
387 RECT rectClip;
388 if ( !::GetClipBox(GetHdc(), &rectClip) )
389 return;
390
391 // GetClipBox returns logical coordinates, so transform to device
392 rectClip.left = LogicalToDeviceX(rectClip.left);
393 rectClip.top = LogicalToDeviceY(rectClip.top);
394 rectClip.right = LogicalToDeviceX(rectClip.right);
395 rectClip.bottom = LogicalToDeviceY(rectClip.bottom);
396
397 HRGN hrgnDest = ::CreateRectRgn(0, 0, 0, 0);
398 HRGN hrgnClipOld = ::CreateRectRgn(rectClip.left, rectClip.top,
399 rectClip.right, rectClip.bottom);
400
401 if ( ::CombineRgn(hrgnDest, hrgnClipOld, (HRGN)hrgn, RGN_AND) != ERROR )
402 {
403 ::SelectClipRgn(GetHdc(), hrgnDest);
404 }
405
406 ::DeleteObject(hrgnClipOld);
407 ::DeleteObject(hrgnDest);
408#else // !WinCE
409 if ( ::ExtSelectClipRgn(GetHdc(), (HRGN)hrgn, RGN_AND) == ERROR )
410 {
411 wxLogLastError(_T("ExtSelectClipRgn"));
412
413 return;
414 }
415#endif // WinCE/!WinCE
416
417 m_clipping = true;
418
419 UpdateClipBox();
420}
421
422void wxDC::DoSetClippingRegion(wxCoord x, wxCoord y, wxCoord w, wxCoord h)
423{
424 // the region coords are always the device ones, so do the translation
425 // manually
426 //
427 // FIXME: possible +/-1 error here, to check!
428 HRGN hrgn = ::CreateRectRgn(LogicalToDeviceX(x),
429 LogicalToDeviceY(y),
430 LogicalToDeviceX(x + w),
431 LogicalToDeviceY(y + h));
432 if ( !hrgn )
433 {
434 wxLogLastError(_T("CreateRectRgn"));
435 }
436 else
437 {
438 SetClippingHrgn((WXHRGN)hrgn);
439
440 ::DeleteObject(hrgn);
441 }
442}
443
444void wxDC::DoSetClippingRegionAsRegion(const wxRegion& region)
445{
446 SetClippingHrgn(region.GetHRGN());
447}
448
449void wxDC::DestroyClippingRegion()
450{
451 WXMICROWIN_CHECK_HDC
452
453 if (m_clipping && m_hDC)
454 {
455 // TODO: this should restore the previous clipping region,
456 // so that OnPaint processing works correctly, and the update
457 // clipping region doesn't get destroyed after the first
458 // DestroyClippingRegion.
459 HRGN rgn = CreateRectRgn(0, 0, 32000, 32000);
460 ::SelectClipRgn(GetHdc(), rgn);
461 ::DeleteObject(rgn);
462 }
463
464 wxDCBase::DestroyClippingRegion();
465}
466
467// ---------------------------------------------------------------------------
468// query capabilities
469// ---------------------------------------------------------------------------
470
471bool wxDC::CanDrawBitmap() const
472{
473 return true;
474}
475
476bool wxDC::CanGetTextExtent() const
477{
478#ifdef __WXMICROWIN__
479 // TODO Extend MicroWindows' GetDeviceCaps function
480 return true;
481#else
482 // What sort of display is it?
483 int technology = ::GetDeviceCaps(GetHdc(), TECHNOLOGY);
484
485 return (technology == DT_RASDISPLAY) || (technology == DT_RASPRINTER);
486#endif
487}
488
489int wxDC::GetDepth() const
490{
491 WXMICROWIN_CHECK_HDC_RET(16)
492
493 return (int)::GetDeviceCaps(GetHdc(), BITSPIXEL);
494}
495
496// ---------------------------------------------------------------------------
497// drawing
498// ---------------------------------------------------------------------------
499
500void wxDC::Clear()
501{
502 WXMICROWIN_CHECK_HDC
503
504 RECT rect;
505 if ( m_canvas )
506 {
507 GetClientRect((HWND) m_canvas->GetHWND(), &rect);
508 }
509 else
510 {
511 // No, I think we should simply ignore this if printing on e.g.
512 // a printer DC.
513 // wxCHECK_RET( m_selectedBitmap.Ok(), wxT("this DC can't be cleared") );
514 if (!m_selectedBitmap.Ok())
515 return;
516
517 rect.left = 0; rect.top = 0;
518 rect.right = m_selectedBitmap.GetWidth();
519 rect.bottom = m_selectedBitmap.GetHeight();
520 }
521
522#ifndef __WXWINCE__
523 (void) ::SetMapMode(GetHdc(), MM_TEXT);
524#endif
525
526 DWORD colour = ::GetBkColor(GetHdc());
527 HBRUSH brush = ::CreateSolidBrush(colour);
528 ::FillRect(GetHdc(), &rect, brush);
529 ::DeleteObject(brush);
530
531#ifndef __WXWINCE__
532 int width = DeviceToLogicalXRel(VIEWPORT_EXTENT)*m_signX,
533 height = DeviceToLogicalYRel(VIEWPORT_EXTENT)*m_signY;
534
535 ::SetMapMode(GetHdc(), MM_ANISOTROPIC);
536
537 ::SetViewportExtEx(GetHdc(), VIEWPORT_EXTENT, VIEWPORT_EXTENT, NULL);
538 ::SetWindowExtEx(GetHdc(), width, height, NULL);
539 ::SetViewportOrgEx(GetHdc(), (int)m_deviceOriginX, (int)m_deviceOriginY, NULL);
540 ::SetWindowOrgEx(GetHdc(), (int)m_logicalOriginX, (int)m_logicalOriginY, NULL);
541#endif
542}
543
544bool wxDC::DoFloodFill(wxCoord WXUNUSED_IN_WINCE(x),
545 wxCoord WXUNUSED_IN_WINCE(y),
546 const wxColour& WXUNUSED_IN_WINCE(col),
547 int WXUNUSED_IN_WINCE(style))
548{
549#ifdef __WXWINCE__
550 return false;
551#else
552 WXMICROWIN_CHECK_HDC_RET(false)
553
554 bool success = (0 != ::ExtFloodFill(GetHdc(), XLOG2DEV(x), YLOG2DEV(y),
555 col.GetPixel(),
556 style == wxFLOOD_SURFACE ? FLOODFILLSURFACE
557 : FLOODFILLBORDER) ) ;
558 if (!success)
559 {
560 // quoting from the MSDN docs:
561 //
562 // Following are some of the reasons this function might fail:
563 //
564 // * The filling could not be completed.
565 // * The specified point has the boundary color specified by the
566 // crColor parameter (if FLOODFILLBORDER was requested).
567 // * The specified point does not have the color specified by
568 // crColor (if FLOODFILLSURFACE was requested)
569 // * The point is outside the clipping region that is, it is not
570 // visible on the device.
571 //
572 wxLogLastError(wxT("ExtFloodFill"));
573 }
574
575 CalcBoundingBox(x, y);
576
577 return success;
578#endif
579}
580
581bool wxDC::DoGetPixel(wxCoord x, wxCoord y, wxColour *col) const
582{
583 WXMICROWIN_CHECK_HDC_RET(false)
584
585 wxCHECK_MSG( col, false, _T("NULL colour parameter in wxDC::GetPixel") );
586
587 // get the color of the pixel
588 COLORREF pixelcolor = ::GetPixel(GetHdc(), XLOG2DEV(x), YLOG2DEV(y));
589
590 wxRGBToColour(*col, pixelcolor);
591
592 return true;
593}
594
595void wxDC::DoCrossHair(wxCoord x, wxCoord y)
596{
597 WXMICROWIN_CHECK_HDC
598
599 wxCoord x1 = x-VIEWPORT_EXTENT;
600 wxCoord y1 = y-VIEWPORT_EXTENT;
601 wxCoord x2 = x+VIEWPORT_EXTENT;
602 wxCoord y2 = y+VIEWPORT_EXTENT;
603
604 wxDrawLine(GetHdc(), XLOG2DEV(x1), YLOG2DEV(y), XLOG2DEV(x2), YLOG2DEV(y));
605 wxDrawLine(GetHdc(), XLOG2DEV(x), YLOG2DEV(y1), XLOG2DEV(x), YLOG2DEV(y2));
606
607 CalcBoundingBox(x1, y1);
608 CalcBoundingBox(x2, y2);
609}
610
611void wxDC::DoDrawLine(wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2)
612{
613 WXMICROWIN_CHECK_HDC
614
615 wxDrawLine(GetHdc(), XLOG2DEV(x1), YLOG2DEV(y1), XLOG2DEV(x2), YLOG2DEV(y2));
616
617 CalcBoundingBox(x1, y1);
618 CalcBoundingBox(x2, y2);
619}
620
621// Draws an arc of a circle, centred on (xc, yc), with starting point (x1, y1)
622// and ending at (x2, y2)
623void wxDC::DoDrawArc(wxCoord x1, wxCoord y1,
624 wxCoord x2, wxCoord y2,
625 wxCoord xc, wxCoord yc)
626{
627#ifdef __WXWINCE__
628 // Slower emulation since WinCE doesn't support Pie and Arc
629 double r = sqrt( (x1-xc)*(x1-xc) + (y1-yc)*(y1-yc) );
630 double sa = acos((x1-xc)/r)/M_PI*180; // between 0 and 180
631 if( y1>yc ) sa = -sa; // below center
632 double ea = atan2(yc-y2, x2-xc)/M_PI*180;
633 DoDrawEllipticArcRot( xc-r, yc-r, 2*r, 2*r, sa, ea );
634#else
635
636 WXMICROWIN_CHECK_HDC
637
638 wxColourChanger cc(*this); // needed for wxSTIPPLE_MASK_OPAQUE handling
639
640 double dx = xc - x1;
641 double dy = yc - y1;
642 double radius = (double)sqrt(dx*dx+dy*dy);
643 wxCoord r = (wxCoord)radius;
644
645 // treat the special case of full circle separately
646 if ( x1 == x2 && y1 == y2 )
647 {
648 DrawEllipse(xc - r, yc - r, 2*r, 2*r);
649 return;
650 }
651
652 wxCoord xx1 = XLOG2DEV(x1);
653 wxCoord yy1 = YLOG2DEV(y1);
654 wxCoord xx2 = XLOG2DEV(x2);
655 wxCoord yy2 = YLOG2DEV(y2);
656 wxCoord xxc = XLOG2DEV(xc);
657 wxCoord yyc = YLOG2DEV(yc);
658 wxCoord ray = (wxCoord) sqrt(double((xxc-xx1)*(xxc-xx1)+(yyc-yy1)*(yyc-yy1)));
659
660 wxCoord xxx1 = (wxCoord) (xxc-ray);
661 wxCoord yyy1 = (wxCoord) (yyc-ray);
662 wxCoord xxx2 = (wxCoord) (xxc+ray);
663 wxCoord yyy2 = (wxCoord) (yyc+ray);
664
665 if ( m_brush.Ok() && m_brush.GetStyle() != wxTRANSPARENT )
666 {
667 // Have to add 1 to bottom-right corner of rectangle
668 // to make semi-circles look right (crooked line otherwise).
669 // Unfortunately this is not a reliable method, depends
670 // on the size of shape.
671 // TODO: figure out why this happens!
672 Pie(GetHdc(),xxx1,yyy1,xxx2+1,yyy2+1, xx1,yy1,xx2,yy2);
673 }
674 else
675 {
676 Arc(GetHdc(),xxx1,yyy1,xxx2,yyy2, xx1,yy1,xx2,yy2);
677 }
678
679 CalcBoundingBox(xc - r, yc - r);
680 CalcBoundingBox(xc + r, yc + r);
681#endif
682}
683
684void wxDC::DoDrawCheckMark(wxCoord x1, wxCoord y1,
685 wxCoord width, wxCoord height)
686{
687 WXMICROWIN_CHECK_HDC
688
689 wxCoord x2 = x1 + width,
690 y2 = y1 + height;
691
692#if defined(__WIN32__) && !defined(__SYMANTEC__) && !defined(__WXMICROWIN__)
693 RECT rect;
694 rect.left = x1;
695 rect.top = y1;
696 rect.right = x2;
697 rect.bottom = y2;
698
699#ifdef __WXWINCE__
700 DrawFrameControl(GetHdc(), &rect, DFC_BUTTON, DFCS_BUTTONCHECK);
701#else
702 DrawFrameControl(GetHdc(), &rect, DFC_MENU, DFCS_MENUCHECK);
703#endif
704#else // Symantec-MicroWin
705 // draw a cross
706 HPEN blackPen = ::CreatePen(PS_SOLID, 1, RGB(0, 0, 0));
707 HPEN whiteBrush = (HPEN)::GetStockObject(WHITE_BRUSH);
708 HPEN hPenOld = (HPEN)::SelectObject(GetHdc(), blackPen);
709 HPEN hBrushOld = (HPEN)::SelectObject(GetHdc(), whiteBrush);
710 ::SetROP2(GetHdc(), R2_COPYPEN);
711 Rectangle(GetHdc(), x1, y1, x2, y2);
712 MoveToEx(GetHdc(), x1, y1, NULL);
713 LineTo(GetHdc(), x2, y2);
714 MoveToEx(GetHdc(), x2, y1, NULL);
715 LineTo(GetHdc(), x1, y2);
716 ::SelectObject(GetHdc(), hPenOld);
717 ::SelectObject(GetHdc(), hBrushOld);
718 ::DeleteObject(blackPen);
719#endif // Win32/Symantec-MicroWin
720
721 CalcBoundingBox(x1, y1);
722 CalcBoundingBox(x2, y2);
723}
724
725void wxDC::DoDrawPoint(wxCoord x, wxCoord y)
726{
727 WXMICROWIN_CHECK_HDC
728
729 COLORREF color = 0x00ffffff;
730 if (m_pen.Ok())
731 {
732 color = m_pen.GetColour().GetPixel();
733 }
734
735 SetPixel(GetHdc(), XLOG2DEV(x), YLOG2DEV(y), color);
736
737 CalcBoundingBox(x, y);
738}
739
740void wxDC::DoDrawPolygon(int n,
741 wxPoint points[],
742 wxCoord xoffset,
743 wxCoord yoffset,
744 int WXUNUSED_IN_WINCE(fillStyle))
745{
746 WXMICROWIN_CHECK_HDC
747
748 wxColourChanger cc(*this); // needed for wxSTIPPLE_MASK_OPAQUE handling
749
750 // Do things less efficiently if we have offsets
751 if (xoffset != 0 || yoffset != 0)
752 {
753 POINT *cpoints = new POINT[n];
754 int i;
755 for (i = 0; i < n; i++)
756 {
757 cpoints[i].x = (int)(points[i].x + xoffset);
758 cpoints[i].y = (int)(points[i].y + yoffset);
759
760 CalcBoundingBox(cpoints[i].x, cpoints[i].y);
761 }
762#ifndef __WXWINCE__
763 int prev = SetPolyFillMode(GetHdc(),fillStyle==wxODDEVEN_RULE?ALTERNATE:WINDING);
764#endif
765 (void)Polygon(GetHdc(), cpoints, n);
766#ifndef __WXWINCE__
767 SetPolyFillMode(GetHdc(),prev);
768#endif
769 delete[] cpoints;
770 }
771 else
772 {
773 int i;
774 for (i = 0; i < n; i++)
775 CalcBoundingBox(points[i].x, points[i].y);
776
777#ifndef __WXWINCE__
778 int prev = SetPolyFillMode(GetHdc(),fillStyle==wxODDEVEN_RULE?ALTERNATE:WINDING);
779#endif
780 (void)Polygon(GetHdc(), (POINT*) points, n);
781#ifndef __WXWINCE__
782 SetPolyFillMode(GetHdc(),prev);
783#endif
784 }
785}
786
787void
788wxDC::DoDrawPolyPolygon(int n,
789 int count[],
790 wxPoint points[],
791 wxCoord xoffset,
792 wxCoord yoffset,
793 int fillStyle)
794{
795#ifdef __WXWINCE__
796 wxDCBase::DoDrawPolyPolygon(n, count, points, xoffset, yoffset, fillStyle);
797#else
798 WXMICROWIN_CHECK_HDC
799
800 wxColourChanger cc(*this); // needed for wxSTIPPLE_MASK_OPAQUE handling
801 int i, cnt;
802 for (i = cnt = 0; i < n; i++)
803 cnt += count[i];
804
805 // Do things less efficiently if we have offsets
806 if (xoffset != 0 || yoffset != 0)
807 {
808 POINT *cpoints = new POINT[cnt];
809 for (i = 0; i < cnt; i++)
810 {
811 cpoints[i].x = (int)(points[i].x + xoffset);
812 cpoints[i].y = (int)(points[i].y + yoffset);
813
814 CalcBoundingBox(cpoints[i].x, cpoints[i].y);
815 }
816#ifndef __WXWINCE__
817 int prev = SetPolyFillMode(GetHdc(),fillStyle==wxODDEVEN_RULE?ALTERNATE:WINDING);
818#endif
819 (void)PolyPolygon(GetHdc(), cpoints, count, n);
820#ifndef __WXWINCE__
821 SetPolyFillMode(GetHdc(),prev);
822#endif
823 delete[] cpoints;
824 }
825 else
826 {
827 for (i = 0; i < cnt; i++)
828 CalcBoundingBox(points[i].x, points[i].y);
829
830#ifndef __WXWINCE__
831 int prev = SetPolyFillMode(GetHdc(),fillStyle==wxODDEVEN_RULE?ALTERNATE:WINDING);
832#endif
833 (void)PolyPolygon(GetHdc(), (POINT*) points, count, n);
834#ifndef __WXWINCE__
835 SetPolyFillMode(GetHdc(),prev);
836#endif
837 }
838#endif
839 // __WXWINCE__
840}
841
842void wxDC::DoDrawLines(int n, wxPoint points[], wxCoord xoffset, wxCoord yoffset)
843{
844 WXMICROWIN_CHECK_HDC
845
846 // Do things less efficiently if we have offsets
847 if (xoffset != 0 || yoffset != 0)
848 {
849 POINT *cpoints = new POINT[n];
850 int i;
851 for (i = 0; i < n; i++)
852 {
853 cpoints[i].x = (int)(points[i].x + xoffset);
854 cpoints[i].y = (int)(points[i].y + yoffset);
855
856 CalcBoundingBox(cpoints[i].x, cpoints[i].y);
857 }
858 (void)Polyline(GetHdc(), cpoints, n);
859 delete[] cpoints;
860 }
861 else
862 {
863 int i;
864 for (i = 0; i < n; i++)
865 CalcBoundingBox(points[i].x, points[i].y);
866
867 (void)Polyline(GetHdc(), (POINT*) points, n);
868 }
869}
870
871void wxDC::DoDrawRectangle(wxCoord x, wxCoord y, wxCoord width, wxCoord height)
872{
873 WXMICROWIN_CHECK_HDC
874
875 wxColourChanger cc(*this); // needed for wxSTIPPLE_MASK_OPAQUE handling
876
877 wxCoord x2 = x + width;
878 wxCoord y2 = y + height;
879
880 if ((m_logicalFunction == wxCOPY) && (m_pen.GetStyle() == wxTRANSPARENT))
881 {
882 RECT rect;
883 rect.left = XLOG2DEV(x);
884 rect.top = YLOG2DEV(y);
885 rect.right = XLOG2DEV(x2);
886 rect.bottom = YLOG2DEV(y2);
887 (void)FillRect(GetHdc(), &rect, (HBRUSH)m_brush.GetResourceHandle() );
888 }
889 else
890 {
891 // Windows draws the filled rectangles without outline (i.e. drawn with a
892 // transparent pen) one pixel smaller in both directions and we want them
893 // to have the same size regardless of which pen is used - adjust
894
895