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