]> git.saurik.com Git - wxWidgets.git/blame - src/msw/dc.cpp
fixed spurious assert failure in wxMenuBar::Insert
[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;
d275c7eb 181#if wxUSE_PALETTE
7bcb11d3 182 m_oldPalette = 0;
d275c7eb 183#endif // wxUSE_PALETTE
a23fd0e1 184
7bcb11d3
JS
185 m_bOwnsDC = FALSE;
186 m_hDC = 0;
a23fd0e1 187
7bcb11d3
JS
188 m_windowExtX = VIEWPORT_EXTENT;
189 m_windowExtY = VIEWPORT_EXTENT;
2bda0e17
KB
190}
191
192
a23fd0e1 193wxDC::~wxDC()
2bda0e17 194{
7ba4fbeb
VZ
195 if ( m_hDC != 0 )
196 {
7bcb11d3 197 SelectOldObjects(m_hDC);
7ba4fbeb
VZ
198
199 // if we own the HDC, we delete it, otherwise we just release it
200
201 if ( m_bOwnsDC )
202 {
203 ::DeleteDC(GetHdc());
7bcb11d3 204 }
7ba4fbeb
VZ
205 else // we don't own our HDC
206 {
db400410
JS
207 if (m_canvas)
208 {
209 ::ReleaseDC(GetHwndOf(m_canvas), GetHdc());
210 }
211 else
212 {
213 // Must have been a wxScreenDC
214 ::ReleaseDC((HWND) NULL, GetHdc());
215 }
7ba4fbeb
VZ
216 }
217 }
2bda0e17
KB
218}
219
220// This will select current objects out of the DC,
221// which is what you have to do before deleting the
222// DC.
223void wxDC::SelectOldObjects(WXHDC dc)
224{
7bcb11d3 225 if (dc)
2bda0e17 226 {
7bcb11d3
JS
227 if (m_oldBitmap)
228 {
229 ::SelectObject((HDC) dc, (HBITMAP) m_oldBitmap);
230 if (m_selectedBitmap.Ok())
231 {
232 m_selectedBitmap.SetSelectedInto(NULL);
233 }
234 }
a23fd0e1 235 m_oldBitmap = 0;
7bcb11d3
JS
236 if (m_oldPen)
237 {
238 ::SelectObject((HDC) dc, (HPEN) m_oldPen);
239 }
a23fd0e1 240 m_oldPen = 0;
7bcb11d3
JS
241 if (m_oldBrush)
242 {
243 ::SelectObject((HDC) dc, (HBRUSH) m_oldBrush);
244 }
a23fd0e1 245 m_oldBrush = 0;
7bcb11d3
JS
246 if (m_oldFont)
247 {
248 ::SelectObject((HDC) dc, (HFONT) m_oldFont);
249 }
a23fd0e1 250 m_oldFont = 0;
d275c7eb
VZ
251
252#if wxUSE_PALETTE
7bcb11d3
JS
253 if (m_oldPalette)
254 {
255 ::SelectPalette((HDC) dc, (HPALETTE) m_oldPalette, TRUE);
256 }
a23fd0e1 257 m_oldPalette = 0;
d275c7eb 258#endif // wxUSE_PALETTE
2bda0e17 259 }
a23fd0e1
VZ
260
261 m_brush = wxNullBrush;
7bcb11d3 262 m_pen = wxNullPen;
d275c7eb 263#if wxUSE_PALETTE
7bcb11d3 264 m_palette = wxNullPalette;
d275c7eb 265#endif // wxUSE_PALETTE
7bcb11d3
JS
266 m_font = wxNullFont;
267 m_backgroundBrush = wxNullBrush;
268 m_selectedBitmap = wxNullBitmap;
2bda0e17
KB
269}
270
a23fd0e1
VZ
271// ---------------------------------------------------------------------------
272// clipping
273// ---------------------------------------------------------------------------
274
1e6feb95
VZ
275void wxDC::UpdateClipBox()
276{
5adad466
JS
277#ifdef __WXMICROWIN__
278 if (!GetHDC()) return;
279#endif
d275c7eb 280
1e6feb95
VZ
281 RECT rect;
282 GetClipBox(GetHdc(), &rect);
283
284 m_clipX1 = (wxCoord) XDEV2LOG(rect.left);
285 m_clipY1 = (wxCoord) YDEV2LOG(rect.top);
286 m_clipX2 = (wxCoord) XDEV2LOG(rect.right);
287 m_clipY2 = (wxCoord) YDEV2LOG(rect.bottom);
f547e9bb
RL
288}
289
c4218a74 290void wxDC::DoSetClippingRegion(wxCoord x, wxCoord y, wxCoord w, wxCoord h)
2bda0e17 291{
5adad466
JS
292#ifdef __WXMICROWIN__
293 if (!GetHDC()) return;
294#endif
d275c7eb 295
7bcb11d3 296 m_clipping = TRUE;
40a89076 297
c4218a74
VZ
298 // the region coords are always the device ones, so do the translation
299 // manually
1e6feb95
VZ
300 //
301 // FIXME: possible +/-1 error here, to check!
c4218a74
VZ
302 HRGN hrgn = ::CreateRectRgn(LogicalToDeviceX(x),
303 LogicalToDeviceY(y),
304 LogicalToDeviceX(x + w),
305 LogicalToDeviceY(y + h));
40a89076
VZ
306 if ( !hrgn )
307 {
308 wxLogLastError(_T("CreateRectRgn"));
309 }
310 else
311 {
312 if ( ::SelectClipRgn(GetHdc(), hrgn) == ERROR )
313 {
314 wxLogLastError(_T("SelectClipRgn"));
315 }
7ecf5ac7 316 DeleteObject(hrgn);
40a89076 317
1e6feb95 318 UpdateClipBox();
40a89076 319 }
2bda0e17
KB
320}
321
a23fd0e1 322void wxDC::DoSetClippingRegionAsRegion(const wxRegion& region)
a724d789 323{
5adad466
JS
324#ifdef __WXMICROWIN__
325 if (!GetHDC()) return;
326#endif
d275c7eb 327
1e6feb95 328 wxCHECK_RET( GetHrgnOf(region), wxT("invalid clipping region") );
a23fd0e1 329
7bcb11d3 330 m_clipping = TRUE;
a23fd0e1 331
1e6d9499 332#ifdef __WIN16__
1e6feb95
VZ
333 SelectClipRgn(GetHdc(), GetHrgnOf(region));
334#else // Win32
335 ExtSelectClipRgn(GetHdc(), GetHrgnOf(region), RGN_AND);
336#endif // Win16/32
a724d789 337
1e6feb95 338 UpdateClipBox();
2bda0e17
KB
339}
340
a23fd0e1 341void wxDC::DestroyClippingRegion()
2bda0e17 342{
5adad466
JS
343#ifdef __WXMICROWIN__
344 if (!GetHDC()) return;
345#endif
d275c7eb 346
7bcb11d3
JS
347 if (m_clipping && m_hDC)
348 {
349 // TODO: this should restore the previous clipping region,
350 // so that OnPaint processing works correctly, and the update clipping region
351 // doesn't get destroyed after the first DestroyClippingRegion.
352 HRGN rgn = CreateRectRgn(0, 0, 32000, 32000);
a23fd0e1 353 SelectClipRgn(GetHdc(), rgn);
7bcb11d3
JS
354 DeleteObject(rgn);
355 }
1e6feb95 356
7bcb11d3 357 m_clipping = FALSE;
2bda0e17
KB
358}
359
a23fd0e1
VZ
360// ---------------------------------------------------------------------------
361// query capabilities
362// ---------------------------------------------------------------------------
363
364bool wxDC::CanDrawBitmap() const
2bda0e17 365{
7bcb11d3 366 return TRUE;
2bda0e17
KB
367}
368
a23fd0e1 369bool wxDC::CanGetTextExtent() const
2bda0e17 370{
04ef50df
JS
371#ifdef __WXMICROWIN__
372 // TODO Extend MicroWindows' GetDeviceCaps function
373 return TRUE;
374#else
7bcb11d3 375 // What sort of display is it?
a23fd0e1
VZ
376 int technology = ::GetDeviceCaps(GetHdc(), TECHNOLOGY);
377
378 return (technology == DT_RASDISPLAY) || (technology == DT_RASPRINTER);
04ef50df 379#endif
2bda0e17
KB
380}
381
a23fd0e1 382int wxDC::GetDepth() const
2bda0e17 383{
5adad466
JS
384#ifdef __WXMICROWIN__
385 if (!GetHDC()) return 16;
386#endif
d275c7eb 387
a23fd0e1 388 return (int)::GetDeviceCaps(GetHdc(), BITSPIXEL);
2bda0e17
KB
389}
390
a23fd0e1
VZ
391// ---------------------------------------------------------------------------
392// drawing
393// ---------------------------------------------------------------------------
394
395void wxDC::Clear()
2bda0e17 396{
5adad466
JS
397#ifdef __WXMICROWIN__
398 if (!GetHDC()) return;
399#endif
d275c7eb 400
7bcb11d3 401 RECT rect;
2506aab6
VZ
402 if ( m_canvas )
403 {
7bcb11d3 404 GetClientRect((HWND) m_canvas->GetHWND(), &rect);
2506aab6
VZ
405 }
406 else
7bcb11d3 407 {
eaeb6a3c
JS
408 // No, I think we should simply ignore this if printing on e.g.
409 // a printer DC.
410 // wxCHECK_RET( m_selectedBitmap.Ok(), wxT("this DC can't be cleared") );
411 if (!m_selectedBitmap.Ok())
412 return;
2506aab6 413
7bcb11d3
JS
414 rect.left = 0; rect.top = 0;
415 rect.right = m_selectedBitmap.GetWidth();
416 rect.bottom = m_selectedBitmap.GetHeight();
417 }
2506aab6 418
a23fd0e1
VZ
419 (void) ::SetMapMode(GetHdc(), MM_TEXT);
420
421 DWORD colour = GetBkColor(GetHdc());
7bcb11d3 422 HBRUSH brush = CreateSolidBrush(colour);
a23fd0e1 423 FillRect(GetHdc(), &rect, brush);
7bcb11d3 424 DeleteObject(brush);
a23fd0e1
VZ
425
426 ::SetMapMode(GetHdc(), MM_ANISOTROPIC);
427 ::SetViewportExtEx(GetHdc(), VIEWPORT_EXTENT, VIEWPORT_EXTENT, NULL);
428 ::SetWindowExtEx(GetHdc(), m_windowExtX, m_windowExtY, NULL);
429 ::SetViewportOrgEx(GetHdc(), (int)m_deviceOriginX, (int)m_deviceOriginY, NULL);
430 ::SetWindowOrgEx(GetHdc(), (int)m_logicalOriginX, (int)m_logicalOriginY, NULL);
431}
432
72cdf4c9 433void wxDC::DoFloodFill(wxCoord x, wxCoord y, const wxColour& col, int style)
a23fd0e1 434{
5adad466
JS
435#ifdef __WXMICROWIN__
436 if (!GetHDC()) return;
437#endif
d275c7eb 438
0bafad0c
VZ
439 if ( !::ExtFloodFill(GetHdc(), XLOG2DEV(x), YLOG2DEV(y),
440 col.GetPixel(),
441 style == wxFLOOD_SURFACE ? FLOODFILLSURFACE
442 : FLOODFILLBORDER) )
443 {
444 // quoting from the MSDN docs:
445 //
446 // Following are some of the reasons this function might fail:
447 //
448 // * The filling could not be completed.
449 // * The specified point has the boundary color specified by the
450 // crColor parameter (if FLOODFILLBORDER was requested).
451 // * The specified point does not have the color specified by
452 // crColor (if FLOODFILLSURFACE was requested)
453 // * The point is outside the clipping region that is, it is not
454 // visible on the device.
455 //
f6bcfd97 456 wxLogLastError(wxT("ExtFloodFill"));
0bafad0c 457 }
a23fd0e1 458
7bcb11d3 459 CalcBoundingBox(x, y);
2bda0e17
KB
460}
461
72cdf4c9 462bool wxDC::DoGetPixel(wxCoord x, wxCoord y, wxColour *col) const
2bda0e17 463{
5adad466
JS
464#ifdef __WXMICROWIN__
465 if (!GetHDC()) return FALSE;
466#endif
d275c7eb 467
f6bcfd97
BP
468 wxCHECK_MSG( col, FALSE, _T("NULL colour parameter in wxDC::GetPixel") );
469
7bcb11d3 470 // get the color of the pixel
a23fd0e1 471 COLORREF pixelcolor = ::GetPixel(GetHdc(), XLOG2DEV(x), YLOG2DEV(y));
0bafad0c 472
f6bcfd97 473 wxRGBToColour(*col, pixelcolor);
dc1efb1d
JS
474
475 return TRUE;
2bda0e17
KB
476}
477
72cdf4c9 478void wxDC::DoCrossHair(wxCoord x, wxCoord y)
a23fd0e1 479{
5adad466
JS
480#ifdef __WXMICROWIN__
481 if (!GetHDC()) return;
482#endif
d275c7eb 483
72cdf4c9
VZ
484 wxCoord x1 = x-VIEWPORT_EXTENT;
485 wxCoord y1 = y-VIEWPORT_EXTENT;
486 wxCoord x2 = x+VIEWPORT_EXTENT;
487 wxCoord y2 = y+VIEWPORT_EXTENT;
a23fd0e1
VZ
488
489 (void)MoveToEx(GetHdc(), XLOG2DEV(x1), YLOG2DEV(y), NULL);
490 (void)LineTo(GetHdc(), XLOG2DEV(x2), YLOG2DEV(y));
491
492 (void)MoveToEx(GetHdc(), XLOG2DEV(x), YLOG2DEV(y1), NULL);
493 (void)LineTo(GetHdc(), XLOG2DEV(x), YLOG2DEV(y2));
494
7bcb11d3
JS
495 CalcBoundingBox(x1, y1);
496 CalcBoundingBox(x2, y2);
2bda0e17
KB
497}
498
72cdf4c9 499void wxDC::DoDrawLine(wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2)
2bda0e17 500{
5adad466
JS
501#ifdef __WXMICROWIN__
502 if (!GetHDC()) return;
503#endif
d275c7eb 504
a23fd0e1
VZ
505 (void)MoveToEx(GetHdc(), XLOG2DEV(x1), YLOG2DEV(y1), NULL);
506 (void)LineTo(GetHdc(), XLOG2DEV(x2), YLOG2DEV(y2));
507
058939fc
JS
508 // Normalization: Windows doesn't draw the last point of the line.
509 // But apparently neither does GTK+, so we take it out again.
510// (void)LineTo(GetHdc(), XLOG2DEV(x2) + 1, YLOG2DEV(y2));
a23fd0e1 511
7bcb11d3
JS
512 CalcBoundingBox(x1, y1);
513 CalcBoundingBox(x2, y2);
2bda0e17
KB
514}
515
f6bcfd97
BP
516// Draws an arc of a circle, centred on (xc, yc), with starting point (x1, y1)
517// and ending at (x2, y2)
518void wxDC::DoDrawArc(wxCoord x1, wxCoord y1,
519 wxCoord x2, wxCoord y2,
520 wxCoord xc, wxCoord yc)
2bda0e17 521{
5adad466
JS
522#ifdef __WXMICROWIN__
523 if (!GetHDC()) return;
524#endif
d275c7eb 525
f6bcfd97 526 wxColourChanger cc(*this); // needed for wxSTIPPLE_MASK_OPAQUE handling
2d8a5cb1 527
f6bcfd97
BP
528 double dx = xc - x1;
529 double dy = yc - y1;
530 double radius = (double)sqrt(dx*dx+dy*dy);
531 wxCoord r = (wxCoord)radius;
2d8a5cb1 532
f6bcfd97
BP
533 // treat the special case of full circle separately
534 if ( x1 == x2 && y1 == y2 )
7bcb11d3 535 {
f6bcfd97 536 DrawEllipse(xc - r, yc - r, 2*r, 2*r);
a23fd0e1 537 return;
7bcb11d3 538 }
a23fd0e1 539
72cdf4c9
VZ
540 wxCoord xx1 = XLOG2DEV(x1);
541 wxCoord yy1 = YLOG2DEV(y1);
542 wxCoord xx2 = XLOG2DEV(x2);
543 wxCoord yy2 = YLOG2DEV(y2);
544 wxCoord xxc = XLOG2DEV(xc);
545 wxCoord yyc = YLOG2DEV(yc);
546 wxCoord ray = (wxCoord) sqrt(double((xxc-xx1)*(xxc-xx1)+(yyc-yy1)*(yyc-yy1)));
a23fd0e1 547
72cdf4c9
VZ
548 wxCoord xxx1 = (wxCoord) (xxc-ray);
549 wxCoord yyy1 = (wxCoord) (yyc-ray);
550 wxCoord xxx2 = (wxCoord) (xxc+ray);
551 wxCoord yyy2 = (wxCoord) (yyc+ray);
f6bcfd97
BP
552
553 if ( m_brush.Ok() && m_brush.GetStyle() != wxTRANSPARENT )
7bcb11d3
JS
554 {
555 // Have to add 1 to bottom-right corner of rectangle
556 // to make semi-circles look right (crooked line otherwise).
557 // Unfortunately this is not a reliable method, depends
558 // on the size of shape.
559 // TODO: figure out why this happens!
f6bcfd97 560 Pie(GetHdc(),xxx1,yyy1,xxx2+1,yyy2+1, xx1,yy1,xx2,yy2);
7bcb11d3
JS
561 }
562 else
2d8a5cb1 563 {
f6bcfd97 564 Arc(GetHdc(),xxx1,yyy1,xxx2,yyy2, xx1,yy1,xx2,yy2);
2d8a5cb1 565 }
f6bcfd97
BP
566
567 CalcBoundingBox(xc - r, yc - r);
568 CalcBoundingBox(xc + r, yc + r);
2bda0e17
KB
569}
570
cd9da200
VZ
571void wxDC::DoDrawCheckMark(wxCoord x1, wxCoord y1,
572 wxCoord width, wxCoord height)
573{
5adad466
JS
574#ifdef __WXMICROWIN__
575 if (!GetHDC()) return;
576#endif
d275c7eb 577
cd9da200
VZ
578 wxCoord x2 = x1 + width,
579 y2 = y1 + height;
580
04ef50df 581#if defined(__WIN32__) && !defined(__SC__) && !defined(__WXMICROWIN__)
cd9da200
VZ
582 RECT rect;
583 rect.left = x1;
584 rect.top = y1;
585 rect.right = x2;
586 rect.bottom = y2;
587
588 DrawFrameControl(GetHdc(), &rect, DFC_MENU, DFCS_MENUCHECK);
589#else // Win16
590 // In WIN16, draw a cross
591 HPEN blackPen = ::CreatePen(PS_SOLID, 1, RGB(0, 0, 0));
592 HPEN whiteBrush = (HPEN)::GetStockObject(WHITE_BRUSH);
e06b9569
JS
593 HPEN hPenOld = (HPEN)::SelectObject(GetHdc(), blackPen);
594 HPEN hBrushOld = (HPEN)::SelectObject(GetHdc(), whiteBrush);
cd9da200
VZ
595 ::SetROP2(GetHdc(), R2_COPYPEN);
596 Rectangle(GetHdc(), x1, y1, x2, y2);
8cb172b4 597 MoveToEx(GetHdc(), x1, y1, NULL);
cd9da200 598 LineTo(GetHdc(), x2, y2);
8cb172b4 599 MoveToEx(GetHdc(), x2, y1, NULL);
cd9da200
VZ
600 LineTo(GetHdc(), x1, y2);
601 ::SelectObject(GetHdc(), hPenOld);
602 ::SelectObject(GetHdc(), hBrushOld);
603 ::DeleteObject(blackPen);
604#endif // Win32/16
605
606 CalcBoundingBox(x1, y1);
607 CalcBoundingBox(x2, y2);
608}
609
72cdf4c9 610void wxDC::DoDrawPoint(wxCoord x, wxCoord y)
2bda0e17 611{
5adad466
JS
612#ifdef __WXMICROWIN__
613 if (!GetHDC()) return;
614#endif
d275c7eb 615
7bcb11d3
JS
616 COLORREF color = 0x00ffffff;
617 if (m_pen.Ok())
618 {
a23fd0e1 619 color = m_pen.GetColour().GetPixel();
7bcb11d3 620 }
a23fd0e1
VZ
621
622 SetPixel(GetHdc(), XLOG2DEV(x), YLOG2DEV(y), color);
623
7bcb11d3 624 CalcBoundingBox(x, y);
2bda0e17
KB
625}
626
72cdf4c9 627void wxDC::DoDrawPolygon(int n, wxPoint points[], wxCoord xoffset, wxCoord yoffset,int fillStyle)
2bda0e17 628{
5adad466
JS
629#ifdef __WXMICROWIN__
630 if (!GetHDC()) return;
631#endif
d275c7eb 632
f6bcfd97 633 wxColourChanger cc(*this); // needed for wxSTIPPLE_MASK_OPAQUE handling
de2d2cdc 634
7bcb11d3
JS
635 // Do things less efficiently if we have offsets
636 if (xoffset != 0 || yoffset != 0)
6a6c0a8b 637 {
7bcb11d3
JS
638 POINT *cpoints = new POINT[n];
639 int i;
640 for (i = 0; i < n; i++)
641 {
642 cpoints[i].x = (int)(points[i].x + xoffset);
643 cpoints[i].y = (int)(points[i].y + yoffset);
a23fd0e1 644
7bcb11d3
JS
645 CalcBoundingBox(cpoints[i].x, cpoints[i].y);
646 }
a23fd0e1
VZ
647 int prev = SetPolyFillMode(GetHdc(),fillStyle==wxODDEVEN_RULE?ALTERNATE:WINDING);
648 (void)Polygon(GetHdc(), cpoints, n);
649 SetPolyFillMode(GetHdc(),prev);
7bcb11d3
JS
650 delete[] cpoints;
651 }
652 else
653 {
654 int i;
655 for (i = 0; i < n; i++)
656 CalcBoundingBox(points[i].x, points[i].y);
a23fd0e1
VZ
657
658 int prev = SetPolyFillMode(GetHdc(),fillStyle==wxODDEVEN_RULE?ALTERNATE:WINDING);
659 (void)Polygon(GetHdc(), (POINT*) points, n);
660 SetPolyFillMode(GetHdc(),prev);
6a6c0a8b 661 }
2bda0e17
KB
662}
663
72cdf4c9 664void wxDC::DoDrawLines(int n, wxPoint points[], wxCoord xoffset, wxCoord yoffset)
2bda0e17 665{
5adad466
JS
666#ifdef __WXMICROWIN__
667 if (!GetHDC()) return;
668#endif
d275c7eb 669
7bcb11d3
JS
670 // Do things less efficiently if we have offsets
671 if (xoffset != 0 || yoffset != 0)
6a6c0a8b 672 {
7bcb11d3
JS
673 POINT *cpoints = new POINT[n];
674 int i;
675 for (i = 0; i < n; i++)
676 {
677 cpoints[i].x = (int)(points[i].x + xoffset);
678 cpoints[i].y = (int)(points[i].y + yoffset);
a23fd0e1 679
7bcb11d3
JS
680 CalcBoundingBox(cpoints[i].x, cpoints[i].y);
681 }
a23fd0e1 682 (void)Polyline(GetHdc(), cpoints, n);
7bcb11d3
JS
683 delete[] cpoints;
684 }
685 else
686 {
687 int i;
688 for (i = 0; i < n; i++)
689 CalcBoundingBox(points[i].x, points[i].y);
a23fd0e1
VZ
690
691 (void)Polyline(GetHdc(), (POINT*) points, n);
6a6c0a8b 692 }
2bda0e17
KB
693}
694
72cdf4c9 695void wxDC::DoDrawRectangle(wxCoord x, wxCoord y, wxCoord width, wxCoord height)
2bda0e17 696{
5adad466
JS
697#ifdef __WXMICROWIN__
698 if (!GetHDC()) return;
699#endif
d275c7eb 700
f6bcfd97 701 wxColourChanger cc(*this); // needed for wxSTIPPLE_MASK_OPAQUE handling
de2d2cdc 702
72cdf4c9
VZ
703 wxCoord x2 = x + width;
704 wxCoord y2 = y + height;
a23fd0e1 705
5456b916 706 if ((m_logicalFunction == wxCOPY) && (m_pen.GetStyle() == wxTRANSPARENT))
0bafad0c 707 {
7299b1b2 708 RECT rect;
5456b916
RR
709 rect.left = XLOG2DEV(x);
710 rect.top = YLOG2DEV(y);
711 rect.right = XLOG2DEV(x2);
7299b1b2
RD
712 rect.bottom = YLOG2DEV(y2);
713 (void)FillRect(GetHdc(), &rect, (HBRUSH)m_brush.GetResourceHandle() );
5456b916
RR
714 }
715 else
716 {
717 // Windows draws the filled rectangles without outline (i.e. drawn with a
718 // transparent pen) one pixel smaller in both directions and we want them
f6bcfd97 719 // to have the same size regardless of which pen is used - adjust
5456b916
RR
720
721