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