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