]> git.saurik.com Git - wxWidgets.git/blob - src/msw/dc.cpp
Cured a bad assert in wxStatusBar; #ifdefed oleutils.cpp for VC++ 5.
[wxWidgets.git] / src / msw / dc.cpp
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 #ifdef __GNUG__
13 #pragma implementation "dc.h"
14 #endif
15
16 // For compilers that support precompilation, includes "wx.h".
17 #include "wx/wxprec.h"
18
19 #ifdef __BORLANDC__
20 #pragma hdrstop
21 #endif
22
23 #ifndef WX_PRECOMP
24 #include "wx/frame.h"
25 #include "wx/dc.h"
26 #include "wx/utils.h"
27 #include "wx/dialog.h"
28 #include "wx/app.h"
29 #endif
30
31 #include "wx/dcprint.h"
32 #include "wx/msw/private.h"
33
34 #include <string.h>
35 #include <math.h>
36 #include <fstream.h>
37
38 #if USE_COMMON_DIALOGS
39 #include <commdlg.h>
40 #endif
41
42 #ifndef __WIN32__
43 #include <print.h>
44 #endif
45
46 #ifdef DrawText
47 #undef DrawText
48 #endif
49
50 #ifdef GetCharWidth
51 #undef GetCharWidth
52 #endif
53
54 #ifdef StartDoc
55 #undef StartDoc
56 #endif
57
58 #if !USE_SHARED_LIBRARY
59 IMPLEMENT_ABSTRACT_CLASS(wxDC, wxObject)
60 #endif
61
62 // Declarations local to this file
63
64 #define YSCALE(y) (yorigin - (y))
65
66 // #define wx_round(a) (int)((a)+.5)
67
68 // Default constructor
69 wxDC::wxDC(void)
70 {
71 m_minX = 0; m_minY = 0; m_maxX = 0; m_maxY = 0;
72 m_clipping = FALSE;
73 m_autoSetting = FALSE ;
74
75 m_filename = "";
76 m_canvas = NULL;
77 m_oldBitmap = 0;
78 m_oldPen = 0;
79 m_oldBrush = 0;
80 m_oldFont = 0;
81 m_oldPalette = 0;
82 m_minX = 0; m_minY = 0; m_maxX = 0; m_maxY = 0;
83 m_logicalOriginX = 0;
84 m_logicalOriginY = 0;
85 m_deviceOriginX = 0;
86 m_deviceOriginY = 0;
87 m_logicalScaleX = 1.0;
88 m_logicalScaleY = 1.0;
89 m_userScaleX = 1.0;
90 m_userScaleY = 1.0;
91 m_signX = 1;
92 m_signY = 1;
93 m_systemScaleX = 1.0;
94 m_systemScaleY = 1.0;
95 m_mappingMode = MM_TEXT;
96 m_bOwnsDC = FALSE;
97 m_hDC = 0;
98 m_clipping = FALSE;
99 m_ok = TRUE;
100 m_windowExtX = VIEWPORT_EXTENT;
101 m_windowExtY = VIEWPORT_EXTENT;
102 m_logicalFunction = -1;
103
104 m_backgroundBrush = *wxWHITE_BRUSH;
105
106 m_textForegroundColour = *wxBLACK;
107 m_textBackgroundColour = *wxWHITE;
108
109 m_colour = wxColourDisplay();
110
111 m_hDCCount = 0;
112 }
113
114
115 wxDC::~wxDC(void)
116 {
117 if ( m_hDC != 0 ) {
118 SelectOldObjects(m_hDC);
119 if ( m_bOwnsDC ) {
120 if ( m_canvas == NULL )
121 ::DeleteDC((HDC)m_hDC);
122 else
123 ::ReleaseDC((HWND)m_canvas->GetHWND(), (HDC)m_hDC);
124 }
125 }
126
127 }
128
129 // This will select current objects out of the DC,
130 // which is what you have to do before deleting the
131 // DC.
132 void wxDC::SelectOldObjects(WXHDC dc)
133 {
134 #if DEBUG > 1
135 wxDebugMsg("wxDC::SelectOldObjects %X\n", this);
136 #endif
137 if (dc)
138 {
139 if (m_oldBitmap)
140 {
141 #if DEBUG > 1
142 wxDebugMsg("wxDC::SelectOldObjects: Selecting old HBITMAP %X\n", m_oldBitmap);
143 #endif
144 ::SelectObject((HDC) dc, (HBITMAP) m_oldBitmap);
145 if (m_selectedBitmap.Ok())
146 {
147 m_selectedBitmap.SetSelectedInto(NULL);
148 }
149 }
150 m_oldBitmap = 0 ;
151 if (m_oldPen)
152 {
153 #if DEBUG > 1
154 wxDebugMsg("wxDC::SelectOldObjects: Selecting old HPEN %X\n", m_oldPen);
155 #endif
156 ::SelectObject((HDC) dc, (HPEN) m_oldPen);
157 }
158 m_oldPen = 0 ;
159 if (m_oldBrush)
160 {
161 #if DEBUG > 1
162 wxDebugMsg("wxDC::SelectOldObjects: Selecting old HBRUSH %X\n", m_oldBrush);
163 #endif
164 ::SelectObject((HDC) dc, (HBRUSH) m_oldBrush);
165 }
166 m_oldBrush = 0 ;
167 if (m_oldFont)
168 {
169 #if DEBUG > 1
170 wxDebugMsg("wxDC::SelectOldObjects: Selecting old HFONT %X\n", m_oldFont);
171 #endif
172 ::SelectObject((HDC) dc, (HFONT) m_oldFont);
173 }
174 m_oldFont = 0 ;
175 if (m_oldPalette)
176 {
177 #if DEBUG > 1
178 wxDebugMsg("wxDC::SelectOldObjects: Selecting old HPALETTE %X\n", m_oldPalette);
179 #endif
180 ::SelectPalette((HDC) dc, (HPALETTE) m_oldPalette, TRUE);
181 }
182 #if DEBUG > 1
183 wxDebugMsg("wxDC::SelectOldObjects: Done.\n");
184 #endif
185 m_oldPalette = 0 ;
186 }
187
188 m_brush = wxNullBrush ;
189 m_pen = wxNullPen;
190 m_palette = wxNullPalette;
191 m_font = wxNullFont;
192 m_backgroundBrush = wxNullBrush;
193 m_selectedBitmap = wxNullBitmap;
194 }
195
196 void wxDC::SetClippingRegion(long cx, long cy, long cw, long ch)
197 {
198 m_clipping = TRUE;
199 m_clipX1 = (int)cx;
200 m_clipY1 = (int)cy;
201 m_clipX2 = (int)(cx + cw);
202 m_clipY2 = (int)(cy + ch);
203
204 DoClipping((WXHDC) m_hDC);
205 }
206
207 void wxDC::DoClipping(WXHDC dc)
208 {
209 if (m_clipping && dc)
210 {
211 IntersectClipRect((HDC) dc, XLOG2DEV(m_clipX1), YLOG2DEV(m_clipY1),
212 XLOG2DEV(m_clipX2), YLOG2DEV(m_clipY2));
213 }
214 }
215
216 void wxDC::DestroyClippingRegion(void)
217 {
218 if (m_clipping && m_hDC)
219 {
220 HRGN rgn = CreateRectRgn(0, 0, 32000, 32000);
221 #if DEBUG > 1
222 wxDebugMsg("wxDC::DestroyClippingRegion: Selecting HRGN %X\n", rgn);
223 #endif
224 SelectClipRgn((HDC) m_hDC, rgn);
225 #if DEBUG > 1
226 wxDebugMsg("wxDC::DestroyClippingRegion: Deleting HRGN %X\n", rgn);
227 #endif
228 DeleteObject(rgn);
229 }
230 m_clipping = FALSE;
231 }
232
233 bool wxDC::CanDrawBitmap(void) const
234 {
235 return TRUE;
236 }
237
238 bool wxDC::CanGetTextExtent(void) const
239 {
240 // What sort of display is it?
241 int technology = ::GetDeviceCaps((HDC) m_hDC, TECHNOLOGY);
242
243 bool ok;
244
245 if (technology != DT_RASDISPLAY && technology != DT_RASPRINTER)
246 ok = FALSE;
247 else ok = TRUE;
248
249 return ok;
250 }
251
252 void wxDC::SetPalette(const wxPalette& palette)
253 {
254 // Set the old object temporarily, in case the assignment deletes an object
255 // that's not yet selected out.
256 if (m_oldPalette)
257 {
258 ::SelectPalette((HDC) m_hDC, (HPALETTE) m_oldPalette, TRUE);
259 m_oldPalette = 0;
260 }
261
262 m_palette = m_palette;
263
264 if (!m_palette.Ok())
265 {
266 // Setting a NULL colourmap is a way of restoring
267 // the original colourmap
268 if (m_oldPalette)
269 {
270 ::SelectPalette((HDC) m_hDC, (HPALETTE) m_oldPalette, TRUE);
271 #if DEBUG > 1
272 wxDebugMsg("wxDC::SetPalette: set old palette %X\n", m_oldPalette);
273 #endif
274 m_oldPalette = 0;
275 }
276
277 return;
278 }
279
280 if (m_palette.Ok() && m_palette.GetHPALETTE())
281 {
282 HPALETTE oldPal = ::SelectPalette((HDC) m_hDC, (HPALETTE) m_palette.GetHPALETTE(), TRUE);
283 if (!m_oldPalette)
284 m_oldPalette = (WXHPALETTE) oldPal;
285
286 #if DEBUG > 1
287 wxDebugMsg("wxDC::SetPalette %X: selected palette %X\n", this, m_palette.GetHPALETTE());
288 if (oldPal)
289 wxDebugMsg("wxDC::SetPalette: oldPal was palette %X\n", oldPal);
290 if (m_oldPalette)
291 wxDebugMsg("wxDC::SetPalette: m_oldPalette is palette %X\n", m_oldPalette);
292 #endif
293 ::RealizePalette((HDC) m_hDC);
294 }
295 }
296
297 void wxDC::Clear(void)
298 {
299 RECT rect;
300 if (m_canvas)
301 GetClientRect((HWND) m_canvas->GetHWND(), &rect);
302 else if (m_selectedBitmap.Ok())
303 {
304 rect.left = 0; rect.top = 0;
305 rect.right = m_selectedBitmap.GetWidth();
306 rect.bottom = m_selectedBitmap.GetHeight();
307 }
308 (void) ::SetMapMode((HDC) m_hDC, MM_TEXT);
309
310 DWORD colour = GetBkColor((HDC) m_hDC);
311 HBRUSH brush = CreateSolidBrush(colour);
312 FillRect((HDC) m_hDC, &rect, brush);
313 DeleteObject(brush);
314
315 ::SetMapMode((HDC) m_hDC, MM_ANISOTROPIC);
316 ::SetViewportExtEx((HDC) m_hDC, VIEWPORT_EXTENT, VIEWPORT_EXTENT, NULL);
317 ::SetWindowExtEx((HDC) m_hDC, m_windowExtX, m_windowExtY, NULL);
318 ::SetViewportOrgEx((HDC) m_hDC, (int)m_deviceOriginX, (int)m_deviceOriginY, NULL);
319 ::SetWindowOrgEx((HDC) m_hDC, (int)m_logicalOriginX, (int)m_logicalOriginY, NULL);
320 }
321
322 void wxDC::FloodFill(long x, long y, wxColour *col, int style)
323 {
324 // int xx = (int)x;
325 // int yy = (int)y;
326
327 if (m_brush.Ok() && m_autoSetting)
328 SetBrush(m_brush);
329
330 (void)ExtFloodFill((HDC) m_hDC, XLOG2DEV(x), YLOG2DEV(y),
331 col->GetPixel(),
332 style==wxFLOOD_SURFACE?
333 FLOODFILLSURFACE:FLOODFILLBORDER
334 );
335
336 CalcBoundingBox(x, y);
337 }
338
339 bool wxDC::GetPixel(long x, long y, wxColour *col) const
340 {
341 // added by steve 29.12.94 (copied from DrawPoint)
342 // returns TRUE for pixels in the color of the current pen
343 // and FALSE for all other pixels colors
344 // if col is non-NULL return the color of the pixel
345
346 // get the color of the pixel
347 COLORREF pixelcolor = ::GetPixel((HDC) m_hDC, XLOG2DEV(x), YLOG2DEV(y));
348 // get the color of the pen
349 COLORREF pencolor = 0x00ffffff;
350 if (m_pen.Ok())
351 {
352 pencolor = m_pen.GetColour().GetPixel() ;
353 }
354
355 // return the color of the pixel
356 if(col)
357 col->Set(GetRValue(pixelcolor),GetGValue(pixelcolor),GetBValue(pixelcolor));
358
359 // check, if color of the pixels is the same as the color
360 // of the current pen
361 return(pixelcolor==pencolor);
362 }
363
364 void wxDC::CrossHair(long x, long y)
365 {
366 if (m_pen.Ok() && m_autoSetting)
367 SetPen(m_pen);
368
369 // We suppose that our screen is 2000x2000 max.
370 long x1 = x-2000;
371 long y1 = y-2000;
372 long x2 = x+2000;
373 long y2 = y+2000;
374
375 (void)MoveToEx((HDC) m_hDC, XLOG2DEV(x1), YLOG2DEV(y), NULL);
376 (void)LineTo((HDC) m_hDC, XLOG2DEV(x2), YLOG2DEV(y));
377
378 (void)MoveToEx((HDC) m_hDC, XLOG2DEV(x), YLOG2DEV(y1), NULL);
379 (void)LineTo((HDC) m_hDC, XLOG2DEV(x), YLOG2DEV(y2));
380
381 CalcBoundingBox(x1, y1);
382 CalcBoundingBox(x2, y2);
383 }
384
385 void wxDC::DrawLine(long x1, long y1, long x2, long y2)
386 {
387 // BUGBUG - is this necessary? YES YES YES YEs Yes yes ye....
388 if (m_pen.Ok() && m_autoSetting)
389 SetPen(m_pen);
390
391 (void)MoveToEx((HDC) m_hDC, XLOG2DEV(x1), YLOG2DEV(y1), NULL);
392 (void)LineTo((HDC) m_hDC, XLOG2DEV(x2), YLOG2DEV(y2));
393
394 /* MATTHEW: [6] New normalization */
395 #if WX_STANDARD_GRAPHICS
396 (void)LineTo((HDC) m_hDC, XLOG2DEV(x2) + 1, YLOG2DEV(y2));
397 #endif
398
399 CalcBoundingBox(x1, y1);
400 CalcBoundingBox(x2, y2);
401 }
402
403 void wxDC::DrawArc(long x1,long y1,long x2,long y2,double xc,double yc)
404 {
405 double dx = xc-x1 ;
406 double dy = yc-y1 ;
407 double radius = (double)sqrt(dx*dx+dy*dy) ;;
408 if (x1==x2 && x2==y2)
409 {
410 DrawEllipse(xc,yc,(double)(radius*2.0),(double)(radius*2)) ;
411 return ;
412 }
413
414 // BUGBUG - is this necessary?
415 if (m_pen.Ok() && m_autoSetting)
416 SetPen(m_pen) ;
417
418 long xx1 = XLOG2DEV(x1) ;
419 long yy1 = YLOG2DEV(y1) ;
420 long xx2 = XLOG2DEV(x2) ;
421 long yy2 = YLOG2DEV(y2) ;
422 long xxc = XLOG2DEV(xc) ;
423 long yyc = YLOG2DEV(yc) ;
424 long ray = (long) sqrt(double((xxc-xx1)*(xxc-xx1)+(yyc-yy1)*(yyc-yy1))) ;
425
426 (void)MoveToEx((HDC) m_hDC, (int) xx1, (int) yy1, NULL);
427 long xxx1 = (long) (xxc-ray);
428 long yyy1 = (long) (yyc-ray);
429 long xxx2 = (long) (xxc+ray);
430 long yyy2 = (long) (yyc+ray);
431 if (m_brush.Ok() && m_brush.GetStyle() !=wxTRANSPARENT)
432 {
433 // BUGBUG - is this necessary?
434 if (m_brush.GetStyle()!=wxTRANSPARENT&&m_autoSetting)
435 SetBrush(m_brush) ;
436 Pie((HDC) m_hDC,xxx1,yyy1,xxx2,yyy2,
437 xx1,yy1,xx2,yy2) ;
438 }
439 else
440 Arc((HDC) m_hDC,xxx1,yyy1,xxx2,yyy2,
441 xx1,yy1,xx2,yy2) ;
442
443 CalcBoundingBox((xc-radius), (yc-radius));
444 CalcBoundingBox((xc+radius), (yc+radius));
445 }
446
447 void wxDC::DrawPoint(long x, long y)
448 {
449 // BUGBUG - is this necessary?
450 if (m_pen.Ok() && m_autoSetting)
451 SetPen(m_pen) ;
452
453 COLORREF color = 0x00ffffff;
454 if (m_pen.Ok())
455 {
456 color = m_pen.GetColour().GetPixel() ;
457 }
458
459 SetPixel((HDC) m_hDC, XLOG2DEV(x), YLOG2DEV(y), color);
460
461 CalcBoundingBox(x, y);
462 }
463
464 void wxDC::DrawPolygon(int n, wxPoint points[], long xoffset, long yoffset,int fillStyle)
465 {
466 // BUGBUG - is this necessary?
467 if (m_pen.Ok() && m_autoSetting)
468 SetPen(m_pen) ;
469
470 POINT *cpoints = new POINT[n];
471 int i;
472 for (i = 0; i < n; i++)
473 {
474 cpoints[i].x = (int)(XLOG2DEV(points[i].x + xoffset));
475 cpoints[i].y = (int)(YLOG2DEV(points[i].y + yoffset));
476
477 CalcBoundingBox(points[i].x + xoffset, points[i].y + yoffset);
478 }
479
480 int prev = SetPolyFillMode((HDC) m_hDC,fillStyle==wxODDEVEN_RULE?ALTERNATE:WINDING) ;
481 (void)Polygon((HDC) m_hDC, cpoints, n);
482 SetPolyFillMode((HDC) m_hDC,prev) ;
483
484 delete[] cpoints;
485 }
486
487 void wxDC::DrawLines(int n, wxPoint points[], long xoffset, long yoffset)
488 {
489 // BUGBUG - is this necessary?
490 if (m_pen.Ok() && m_autoSetting)
491 SetPen(m_pen) ;
492
493 POINT *cpoints = new POINT[n];
494 int i;
495 for (i = 0; i < n; i++)
496 {
497 cpoints[i].x = (int)(XLOG2DEV(points[i].x + xoffset));
498 cpoints[i].y = (int)(YLOG2DEV(points[i].y + yoffset));
499
500 CalcBoundingBox(points[i].x + xoffset, points[i].y + yoffset);
501 }
502
503 (void)Polyline((HDC) m_hDC, cpoints, n);
504
505 delete[] cpoints;
506 }
507
508 void wxDC::DrawRectangle(long x, long y, long width, long height)
509 {
510 // BUGBUG - is this necessary?
511 if (m_pen.Ok() && m_autoSetting)
512 SetPen(m_pen) ;
513
514 long x2 = x + width;
515 long y2 = y + height;
516
517 /* MATTHEW: [6] new normalization */
518 #if WX_STANDARD_GRAPHICS
519 bool do_brush, do_pen;
520
521 do_brush = m_brush.Ok() && m_brush.GetStyle() != wxTRANSPARENT;
522 do_pen = m_pen.Ok() && m_pen.GetStyle() != wxTRANSPARENT;
523
524 if (do_brush) {
525 HPEN orig_pen = NULL;
526
527 if (do_pen || !m_pen.Ok())
528 orig_pen = ::SelectObject((HDC) m_hDC, ::GetStockObject(NULL_PEN));
529
530 (void)Rectangle((HDC) m_hDC, XLOG2DEV(x), YLOG2DEV(y),
531 XLOG2DEV(x2) + 1, YLOG2DEV(y2) + 1);
532
533 if (do_pen || !m_pen.Ok())
534 ::SelectObject((HDC) m_hDC , orig_pen);
535 }
536 if (do_pen) {
537 HBRUSH orig_brush = NULL;
538
539 if (do_brush || !m_brush.Ok())
540 orig_brush = ::SelectObject((HDC) m_hDC, ::GetStockObject(NULL_BRUSH));
541
542 (void)Rectangle((HDC) m_hDC, XLOG2DEV(x), YLOG2DEV(y),
543 XLOG2DEV(x2), YLOG2DEV(y2));
544
545 if (do_brush || !m_brush.Ok())
546 ::SelectObject((HDC) m_hDC, orig_brush);
547 }
548 #else
549 (void)Rectangle((HDC) m_hDC, XLOG2DEV(x), YLOG2DEV(y), XLOG2DEV(x2), YLOG2DEV(y2));
550 #endif
551
552 CalcBoundingBox(x, y);
553 CalcBoundingBox(x2, y2);
554 }
555
556 void wxDC::DrawRoundedRectangle(long x, long y, long width, long height, double radius)
557 {
558 // BUGBUG - is this necessary?
559 if (m_pen.Ok() && m_autoSetting)
560 SetPen(m_pen) ;
561
562 // Now, a negative radius value is interpreted to mean
563 // 'the proportion of the smallest X or Y dimension'
564
565 if (radius < 0.0)
566 {
567 double smallest = 0.0;
568 if (width < height)
569 smallest = width;
570 else
571 smallest = height;
572 radius = (- radius * smallest);
573 }
574
575 long x2 = (x+width);
576 long y2 = (y+height);
577
578 (void)RoundRect((HDC) m_hDC, XLOG2DEV(x), YLOG2DEV(y), XLOG2DEV(x2),
579 YLOG2DEV(y2), 2*XLOG2DEV(radius), 2*YLOG2DEV(radius));
580
581 CalcBoundingBox(x, y);
582 CalcBoundingBox(x2, y2);
583 }
584
585 void wxDC::DrawEllipse(long x, long y, long width, long height)
586 {
587 // BUGBUG - is this necessary?
588 if (m_pen.Ok() && m_autoSetting)
589 SetPen(m_pen) ;
590
591 long x2 = (x+width);
592 long y2 = (y+height);
593
594 (void)Ellipse((HDC) m_hDC, XLOG2DEV(x), YLOG2DEV(y), XLOG2DEV(x2), YLOG2DEV(y2));
595
596 CalcBoundingBox(x, y);
597 CalcBoundingBox(x2, y2);
598 }
599
600 // Chris Breeze 20/5/98: first implementation of DrawEllipticArc on Windows
601 void wxDC::DrawEllipticArc(long x,long y,long w,long h,double sa,double ea)
602 {
603 // BUGBUG - is this necessary?
604 if (m_pen.Ok() && m_autoSetting)
605 SetPen(m_pen) ;
606
607 long x2 = (x+w);
608 long y2 = (y+h);
609
610 const double deg2rad = 3.14159265359 / 180.0;
611 int rx1 = XLOG2DEV(x+w/2);
612 int ry1 = YLOG2DEV(y+h/2);
613 int rx2 = rx1;
614 int ry2 = ry1;
615 rx1 += (int)(100.0 * abs(w) * cos(sa * deg2rad));
616 ry1 -= (int)(100.0 * abs(h) * m_signY * sin(sa * deg2rad));
617 rx2 += (int)(100.0 * abs(w) * cos(ea * deg2rad));
618 ry2 -= (int)(100.0 * abs(h) * m_signY * sin(ea * deg2rad));
619
620 // draw pie with NULL_PEN first and then outline otherwise a line is
621 // drawn from the start and end points to the centre
622 HPEN orig_pen = ::SelectObject((HDC) m_hDC, ::GetStockObject(NULL_PEN));
623 if (m_signY > 0)
624 {
625 (void)Pie((HDC) m_hDC, XLOG2DEV(x), YLOG2DEV(y), XLOG2DEV(x2)+1, YLOG2DEV(y2)+1,
626 rx1, ry1, rx2, ry2);
627 }
628 else
629 {
630 (void)Pie((HDC) m_hDC, XLOG2DEV(x), YLOG2DEV(y)-1, XLOG2DEV(x2)+1, YLOG2DEV(y2),
631 rx1, ry1-1, rx2, ry2-1);
632 }
633 ::SelectObject((HDC) m_hDC, orig_pen);
634 (void)Arc((HDC) m_hDC, XLOG2DEV(x), YLOG2DEV(y), XLOG2DEV(x2), YLOG2DEV(y2),
635 rx1, ry1, rx2, ry2);
636
637 CalcBoundingBox(x, y);
638 CalcBoundingBox(x2, y2);
639 }
640
641 void wxDC::DrawIcon(const wxIcon& icon, long x, long y)
642 {
643 ::DrawIcon((HDC) m_hDC, XLOG2DEV(x), YLOG2DEV(y), (HICON) icon.GetHICON());
644 CalcBoundingBox(x, y);
645 CalcBoundingBox(x+icon.GetWidth(), y+icon.GetHeight());
646 }
647
648 void wxDC::SetFont(const wxFont& the_font)
649 {
650 // Set the old object temporarily, in case the assignment deletes an object
651 // that's not yet selected out.
652 if (m_oldFont)
653 {
654 ::SelectObject((HDC) m_hDC, (HFONT) m_oldFont);
655 m_oldFont = 0;
656 }
657
658 m_font = the_font;
659
660 if (!the_font.Ok())
661 {
662 if (m_oldFont)
663 ::SelectObject((HDC) m_hDC, (HFONT) m_oldFont);
664 m_oldFont = 0 ;
665 }
666
667 if (m_font.Ok() && m_font.GetResourceHandle())
668 {
669 #if DEBUG > 1
670 wxDebugMsg("wxDC::SetFont: Selecting HFONT %X\n", m_font.GetResourceHandle());
671 #endif
672 HFONT f = (HFONT) ::SelectObject((HDC) m_hDC, (HFONT) m_font.GetResourceHandle());
673 if (!m_oldFont)
674 m_oldFont = (WXHFONT) f;
675 }
676 }
677
678 void wxDC::SetPen(const wxPen& pen)
679 {
680 // Set the old object temporarily, in case the assignment deletes an object
681 // that's not yet selected out.
682 if (m_oldPen)
683 {
684 ::SelectObject((HDC) m_hDC, (HPEN) m_oldPen);
685 m_oldPen = 0;
686 }
687
688 m_pen = pen;
689
690 if (!m_pen.Ok())
691 {
692 if (m_oldPen)
693 ::SelectObject((HDC) m_hDC, (HPEN) m_oldPen);
694 m_oldPen = 0 ;
695 }
696
697 if (m_pen.Ok())
698 {
699 if (m_pen.GetResourceHandle())
700 {
701 HPEN p = (HPEN) ::SelectObject((HDC) m_hDC, (HPEN)m_pen.GetResourceHandle()) ;
702 if (!m_oldPen)
703 m_oldPen = (WXHPEN) p;
704 }
705 }
706 }
707
708 void wxDC::SetBrush(const wxBrush& brush)
709 {
710 // Set the old object temporarily, in case the assignment deletes an object
711 // that's not yet selected out.
712 if (m_oldBrush)
713 {
714 ::SelectObject((HDC) m_hDC, (HBRUSH) m_oldBrush);
715 m_oldBrush = 0;
716 }
717
718 m_brush = brush;
719
720 if (!m_brush.Ok())
721 {
722 if (m_oldBrush)
723 ::SelectObject((HDC) m_hDC, (HBRUSH) m_oldBrush);
724 m_oldBrush = 0 ;
725 }
726
727 if (m_brush.Ok())
728 {
729 if (m_brush.GetResourceHandle())
730 {
731 HBRUSH b = 0;
732 b = ::SelectObject((HDC) m_hDC, (HBRUSH)m_brush.GetResourceHandle()) ;
733 if (!m_oldBrush)
734 m_oldBrush = (WXHBRUSH) b;
735 }
736 }
737 }
738
739 void wxDC::DrawText(const wxString& text, long x, long y, bool use16bit)
740 {
741 if (m_font.Ok() && m_font.GetResourceHandle())
742 {
743 #if DEBUG > 1
744 wxDebugMsg("wxDC::DrawText: Selecting HFONT %X\n", m_font.GetResourceHandle());
745 #endif
746 HFONT f = ::SelectObject((HDC) m_hDC, (HFONT) m_font.GetResourceHandle());
747 if (!m_oldFont)
748 m_oldFont = (WXHFONT) f;
749 }
750
751 if (m_textForegroundColour.Ok())
752 SetTextColor((HDC) m_hDC, m_textForegroundColour.GetPixel() ) ;
753
754 DWORD old_background;
755 if (m_textBackgroundColour.Ok())
756 {
757 old_background = SetBkColor((HDC) m_hDC, m_textBackgroundColour.GetPixel() ) ;
758 }
759
760 if (m_backgroundMode == wxTRANSPARENT)
761 SetBkMode((HDC) m_hDC, TRANSPARENT);
762 else
763 SetBkMode((HDC) m_hDC, OPAQUE);
764
765 (void)TextOut((HDC) m_hDC, XLOG2DEV(x), YLOG2DEV(y), (char *) (const char *)text, strlen((const char *)text));
766
767 if (m_textBackgroundColour.Ok())
768 (void)SetBkColor((HDC) m_hDC, old_background);
769
770 CalcBoundingBox(x, y);
771
772 long w, h;
773 GetTextExtent(text, &w, &h);
774 CalcBoundingBox((x + w), (y + h));
775 }
776
777 void wxDC::SetBackground(const wxBrush& brush)
778 {
779 m_backgroundBrush = brush;
780
781 if (!m_backgroundBrush.Ok())
782 return;
783
784 if (m_canvas)
785 {
786 bool customColours = TRUE;
787 // If we haven't specified wxUSER_COLOURS, don't allow the panel/dialog box to
788 // change background colours from the control-panel specified colours.
789 if (m_canvas->IsKindOf(CLASSINFO(wxWindow)) && ((m_canvas->GetWindowStyleFlag() & wxUSER_COLOURS) != wxUSER_COLOURS))
790 customColours = FALSE;
791
792 if (customColours)
793 {
794 if (m_backgroundBrush.GetStyle()==wxTRANSPARENT)
795 {
796 m_canvas->m_backgroundTransparent = TRUE;
797 }
798 else
799 {
800 m_canvas->SetBackgroundColour(m_backgroundBrush.GetColour());
801 m_canvas->m_backgroundTransparent = FALSE;
802 }
803 }
804 }
805 COLORREF new_color = m_backgroundBrush.GetColour().GetPixel() ;
806 {
807 (void)SetBkColor((HDC) m_hDC, new_color);
808 }
809 }
810
811 void wxDC::SetBackgroundMode(int mode)
812 {
813 m_backgroundMode = mode;
814
815 if (m_backgroundMode == wxTRANSPARENT)
816 ::SetBkMode((HDC) m_hDC, TRANSPARENT);
817 else
818 ::SetBkMode((HDC) m_hDC, OPAQUE);
819 }
820
821 void wxDC::SetLogicalFunction(int function)
822 {
823 m_logicalFunction = function;
824
825 SetRop((WXHDC) m_hDC);
826 }
827
828 void wxDC::SetRop(WXHDC dc)
829 {
830 if (!dc || m_logicalFunction < 0)
831 return;
832
833 int c_rop;
834 // These may be wrong
835 switch (m_logicalFunction)
836 {
837 // case wxXOR: c_rop = R2_XORPEN; break;
838 case wxXOR: c_rop = R2_NOTXORPEN; break;
839 case wxINVERT: c_rop = R2_NOT; break;
840 case wxOR_REVERSE: c_rop = R2_MERGEPENNOT; break;
841 case wxAND_REVERSE: c_rop = R2_MASKPENNOT; break;
842 case wxCLEAR: c_rop = R2_WHITE; break;
843 case wxSET: c_rop = R2_BLACK; break;
844 case wxSRC_INVERT: c_rop = R2_NOTCOPYPEN; break;
845 case wxOR_INVERT: c_rop = R2_MERGENOTPEN; break;
846 case wxAND: c_rop = R2_MASKPEN; break;
847 case wxOR: c_rop = R2_MERGEPEN; break;
848 case wxAND_INVERT: c_rop = R2_MASKNOTPEN; break;
849 case wxEQUIV:
850 case wxNAND:
851 case wxCOPY:
852 default:
853 c_rop = R2_COPYPEN; break;
854 }
855 SetROP2((HDC) dc, c_rop);
856 }
857
858 bool wxDC::StartDoc(const wxString& message)
859 {
860 if (!this->IsKindOf(CLASSINFO(wxPrinterDC)))
861 return TRUE;
862
863 bool flag = FALSE;
864
865 DOCINFO docinfo;
866 docinfo.cbSize = sizeof(DOCINFO);
867 docinfo.lpszDocName = (const char *)message;
868 docinfo.lpszOutput = (const char *)m_filename;
869 #if defined(__WIN95__)
870 docinfo.lpszDatatype = NULL;
871 docinfo.fwType = 0;
872 #endif
873
874 if (m_hDC) flag = (SP_ERROR !=
875 #ifndef __WIN32__
876 ::StartDoc((HDC) m_hDC, &docinfo));
877 #else
878 #ifdef UNICODE
879 ::StartDocW((HDC) m_hDC, &docinfo));
880 #else
881 ::StartDocA((HDC) m_hDC, &docinfo));
882 #endif
883 #endif
884
885 else flag = FALSE;
886
887 return flag;
888 }
889
890 void wxDC::EndDoc(void)
891 {
892 if (!this->IsKindOf(CLASSINFO(wxPrinterDC)))
893 return;
894 if (m_hDC) ::EndDoc((HDC) m_hDC);
895 }
896
897 void wxDC::StartPage(void)
898 {
899 if (!this->IsKindOf(CLASSINFO(wxPrinterDC)))
900 return;
901 if (m_hDC)
902 ::StartPage((HDC) m_hDC);
903 }
904
905 void wxDC::EndPage(void)
906 {
907 if (!this->IsKindOf(CLASSINFO(wxPrinterDC)))
908 return;
909 if (m_hDC)
910 ::EndPage((HDC) m_hDC);
911 }
912
913 long wxDC::GetCharHeight(void) const
914 {
915 TEXTMETRIC lpTextMetric;
916
917 GetTextMetrics((HDC) m_hDC, &lpTextMetric);
918
919 return YDEV2LOGREL(lpTextMetric.tmHeight);
920 }
921
922 long wxDC::GetCharWidth(void) const
923 {
924 TEXTMETRIC lpTextMetric;
925
926 GetTextMetrics((HDC) m_hDC, &lpTextMetric);
927
928 return XDEV2LOGREL(lpTextMetric.tmAveCharWidth);
929 }
930
931 void wxDC::GetTextExtent(const wxString& string, long *x, long *y,
932 long *descent, long *externalLeading, wxFont *theFont, bool use16bit) const
933 {
934 wxFont *fontToUse = (wxFont*) theFont;
935 if (!fontToUse)
936 fontToUse = (wxFont*) &m_font;
937
938 SIZE sizeRect;
939 TEXTMETRIC tm;
940
941 GetTextExtentPoint((HDC) m_hDC, (char *)(const char *) string, strlen((char *)(const char *) string), &sizeRect);
942 GetTextMetrics((HDC) m_hDC, &tm);
943
944 *x = XDEV2LOGREL(sizeRect.cx);
945 *y = YDEV2LOGREL(sizeRect.cy);
946 if (descent) *descent = tm.tmDescent;
947 if (externalLeading) *externalLeading = tm.tmExternalLeading;
948 }
949
950 void wxDC::SetMapMode(int mode)
951 {
952 m_mappingMode = mode;
953
954 int pixel_width = 0;
955 int pixel_height = 0;
956 int mm_width = 0;
957 int mm_height = 0;
958
959 pixel_width = GetDeviceCaps((HDC) m_hDC, HORZRES);
960 pixel_height = GetDeviceCaps((HDC) m_hDC, VERTRES);
961 mm_width = GetDeviceCaps((HDC) m_hDC, HORZSIZE);
962 mm_height = GetDeviceCaps((HDC) m_hDC, VERTSIZE);
963
964 if ((pixel_width == 0) || (pixel_height == 0) || (mm_width == 0) || (mm_height == 0))
965 {
966 return;
967 }
968
969 double mm2pixelsX = pixel_width/mm_width;
970 double mm2pixelsY = pixel_height/mm_height;
971
972 switch (mode)
973 {
974 case MM_TWIPS:
975 {
976 m_logicalScaleX = (twips2mm * mm2pixelsX);
977 m_logicalScaleY = (twips2mm * mm2pixelsY);
978 break;
979 }
980 case MM_POINTS:
981 {
982 m_logicalScaleX = (pt2mm * mm2pixelsX);
983 m_logicalScaleY = (pt2mm * mm2pixelsY);
984 break;
985 }
986 case MM_METRIC:
987 {
988 m_logicalScaleX = mm2pixelsX;
989 m_logicalScaleY = mm2pixelsY;
990 break;
991 }
992 case MM_LOMETRIC:
993 {
994 m_logicalScaleX = (mm2pixelsX/10.0);
995 m_logicalScaleY = (mm2pixelsY/10.0);
996 break;
997 }
998 default:
999 case MM_TEXT:
1000 {
1001 m_logicalScaleX = 1.0;
1002 m_logicalScaleY = 1.0;
1003 break;
1004 }
1005 }
1006
1007 if (::GetMapMode((HDC) m_hDC) != MM_ANISOTROPIC)
1008 ::SetMapMode((HDC) m_hDC, MM_ANISOTROPIC);
1009
1010 SetViewportExtEx((HDC) m_hDC, VIEWPORT_EXTENT, VIEWPORT_EXTENT, NULL);
1011 m_windowExtX = (int)MS_XDEV2LOGREL(VIEWPORT_EXTENT);
1012 m_windowExtY = (int)MS_YDEV2LOGREL(VIEWPORT_EXTENT);
1013 ::SetWindowExtEx((HDC) m_hDC, m_windowExtX, m_windowExtY, NULL);
1014 ::SetViewportOrgEx((HDC) m_hDC, (int)m_deviceOriginX, (int)m_deviceOriginY, NULL);
1015 ::SetWindowOrgEx((HDC) m_hDC, (int)m_logicalOriginX, (int)m_logicalOriginY, NULL);
1016 }
1017
1018 void wxDC::SetUserScale(double x, double y)
1019 {
1020 m_userScaleX = x;
1021 m_userScaleY = y;
1022
1023 SetMapMode(m_mappingMode);
1024 }
1025
1026 void wxDC::SetAxisOrientation(bool xLeftRight, bool yBottomUp)
1027 {
1028 m_signX = xLeftRight ? 1 : -1;
1029 m_signY = yBottomUp ? -1 : 1;
1030
1031 SetMapMode(m_mappingMode);
1032 }
1033
1034 void wxDC::SetSystemScale(double x, double y)
1035 {
1036 m_systemScaleX = x;
1037 m_systemScaleY = y;
1038
1039 SetMapMode(m_mappingMode);
1040 }
1041
1042 void wxDC::SetLogicalOrigin(long x, long y)
1043 {
1044 m_logicalOriginX = x;
1045 m_logicalOriginY = y;
1046
1047 ::SetWindowOrgEx((HDC) m_hDC, (int)m_logicalOriginX, (int)m_logicalOriginY, NULL);
1048 }
1049
1050 void wxDC::SetDeviceOrigin(long x, long y)
1051 {
1052 m_deviceOriginX = x;
1053 m_deviceOriginY = y;
1054
1055 ::SetViewportOrgEx((HDC) m_hDC, (int)m_deviceOriginX, (int)m_deviceOriginY, NULL);
1056 }
1057
1058 long wxDC::DeviceToLogicalX(long x) const
1059 {
1060 return (long) (((x) - m_deviceOriginX)/(m_logicalScaleX*m_userScaleX*m_signX*m_systemScaleX) - m_logicalOriginX) ;
1061 }
1062
1063 long wxDC::DeviceToLogicalXRel(long x) const
1064 {
1065 return (long) ((x)/(m_logicalScaleX*m_userScaleX*m_signX*m_systemScaleX)) ;
1066 }
1067
1068 long wxDC::DeviceToLogicalY(long y) const
1069 {
1070 return (long) (((y) - m_deviceOriginY)/(m_logicalScaleY*m_userScaleY*m_signY*m_systemScaleY) - m_logicalOriginY) ;
1071 }
1072
1073 long wxDC::DeviceToLogicalYRel(long y) const
1074 {
1075 return (long) ((y)/(m_logicalScaleY*m_userScaleY*m_signY*m_systemScaleY)) ;
1076 }
1077
1078 long wxDC::LogicalToDeviceX(long x) const
1079 {
1080 return (long) (floor((x) - m_logicalOriginX)*m_logicalScaleX*m_userScaleX*m_signX*m_systemScaleX + m_deviceOriginX) ;
1081 }
1082
1083 long wxDC::LogicalToDeviceXRel(long x) const
1084 {
1085 return (long) (floor(x)*m_logicalScaleX*m_userScaleX*m_signX*m_systemScaleX) ;
1086 }
1087
1088 long wxDC::LogicalToDeviceY(long y) const
1089 {
1090 return (long) (floor((y) - m_logicalOriginY)*m_logicalScaleY*m_userScaleY*m_signY*m_systemScaleY + m_deviceOriginY);
1091 }
1092
1093 long wxDC::LogicalToDeviceYRel(long y) const
1094 {
1095 return (long) (floor(y)*m_logicalScaleY*m_userScaleY*m_signY*m_systemScaleY) ;
1096 }
1097
1098 // This group of functions may not do any conversion
1099 // if m_scaleGDI is TRUE, since the HDC does the
1100 // conversion automatically.
1101
1102 long wxDC::ImplDeviceToLogicalX(long x) const
1103 {
1104 // return (m_scaleGDI ? x : DeviceToLogicalX(x));
1105 return x;
1106 }
1107
1108 long wxDC::ImplDeviceToLogicalY(long y) const
1109 {
1110 // return (m_scaleGDI ? y : DeviceToLogicalY(y));
1111 return y;
1112 }
1113
1114 long wxDC::ImplDeviceToLogicalXRel(long x) const
1115 {
1116 // return (m_scaleGDI ? x : DeviceToLogicalXRel(x));
1117 return x;
1118 }
1119
1120 long wxDC::ImplDeviceToLogicalYRel(long y) const
1121 {
1122 // return (m_scaleGDI ? y : DeviceToLogicalYRel(y));
1123 return y;
1124 }
1125
1126 long wxDC::ImplLogicalToDeviceX(long x) const
1127 {
1128 // return (m_scaleGDI ? (floor(double(x))) : LogicalToDeviceX(x));
1129 return x;
1130 }
1131
1132 long wxDC::ImplLogicalToDeviceY(long y) const
1133 {
1134 // return (m_scaleGDI ? (floor(double(y))) : LogicalToDeviceY(y));
1135 return y;
1136 }
1137
1138 long wxDC::ImplLogicalToDeviceXRel(long x) const
1139 {
1140 // return (m_scaleGDI ? (floor(double(x))) : LogicalToDeviceXRel(x));
1141 return x;
1142 }
1143
1144 long wxDC::ImplLogicalToDeviceYRel(long y) const
1145 {
1146 // return (m_scaleGDI ? (floor(double(y))) : LogicalToDeviceYRel(y));
1147 return y;
1148 }
1149
1150 bool wxDC::Blit(long xdest, long ydest, long width, long height,
1151 wxDC *source, long xsrc, long ysrc, int rop, bool useMask)
1152 {
1153 long xdest1 = xdest;
1154 long ydest1 = ydest;
1155 long xsrc1 = xsrc;
1156 long ysrc1 = ysrc;
1157
1158 // Chris Breeze 18/5/98: use text foreground/background colours
1159 // when blitting from 1-bit bitmaps
1160 COLORREF old_textground = ::GetTextColor((HDC)m_hDC);
1161 COLORREF old_background = ::GetBkColor((HDC)m_hDC);
1162 if (m_textForegroundColour.Ok())
1163 {
1164 ::SetTextColor((HDC) m_hDC, m_textForegroundColour.GetPixel() ) ;
1165 }
1166 if (m_textBackgroundColour.Ok())
1167 {
1168 ::SetBkColor((HDC) m_hDC, m_textBackgroundColour.GetPixel() ) ;
1169 }
1170
1171 DWORD dwRop = rop == wxCOPY ? SRCCOPY :
1172 rop == wxCLEAR ? WHITENESS :
1173 rop == wxSET ? BLACKNESS :
1174 rop == wxINVERT ? DSTINVERT :
1175 rop == wxAND ? MERGECOPY :
1176 rop == wxOR ? MERGEPAINT :
1177 rop == wxSRC_INVERT ? NOTSRCCOPY :
1178 rop == wxXOR ? SRCINVERT :
1179 rop == wxOR_REVERSE ? MERGEPAINT :
1180 rop == wxAND_REVERSE ? SRCERASE :
1181 rop == wxSRC_OR ? SRCPAINT :
1182 rop == wxSRC_AND ? SRCAND :
1183 SRCCOPY;
1184
1185 bool success;
1186 if (useMask && source->m_selectedBitmap.Ok() && source->m_selectedBitmap.GetMask())
1187 {
1188
1189 #if 0 // __WIN32__
1190 // Not implemented under Win95 (or maybe a specific device?)
1191 if (MaskBlt((HDC) m_hDC, xdest1, ydest1, (int)width, (int)height,
1192 (HDC) source->m_hDC, xsrc1, ysrc1, (HBITMAP) source->m_selectedBitmap.GetMask()->GetMaskBitmap(),
1193 0, 0, 0xAACC0020))
1194 {
1195 // Success
1196 }
1197 else
1198 #endif
1199 {
1200 // Old code
1201 #if 0
1202 HDC dc_mask = CreateCompatibleDC((HDC) source->m_hDC);
1203 ::SelectObject(dc_mask, (HBITMAP) source->m_selectedBitmap.GetMask()->GetMaskBitmap());
1204 success = (BitBlt((HDC) m_hDC, xdest1, ydest1, (int)width, (int)height,
1205 dc_mask, xsrc1, ysrc1, 0x00220326 /* NOTSRCAND */) != 0);
1206 success = (BitBlt((HDC) m_hDC, xdest1, ydest1, (int)width, (int)height,
1207 (HDC) source->m_hDC, xsrc1, ysrc1, SRCPAINT) != 0);
1208 ::SelectObject(dc_mask, 0);
1209 ::DeleteDC(dc_mask);
1210 #endif
1211 // New code from Chris Breeze, 8/5/98
1212
1213 // create a temp buffer bitmap and DCs to access it and the mask
1214 HDC dc_mask = ::CreateCompatibleDC((HDC) source->m_hDC);
1215 HDC dc_buffer = ::CreateCompatibleDC((HDC) m_hDC);
1216 HBITMAP buffer_bmap = ::CreateCompatibleBitmap((HDC) m_hDC, width, height);
1217 ::SelectObject(dc_mask, (HBITMAP) source->m_selectedBitmap.GetMask()->GetMaskBitmap());
1218 ::SelectObject(dc_buffer, buffer_bmap);
1219
1220 // copy dest to buffer
1221 ::BitBlt(dc_buffer, 0, 0, (int)width, (int)height,
1222 (HDC) m_hDC, xdest1, ydest1, SRCCOPY);
1223
1224 // copy src to buffer using selected raster op
1225 ::BitBlt(dc_buffer, 0, 0, (int)width, (int)height,
1226 (HDC) source->m_hDC, xsrc1, ysrc1, dwRop);
1227
1228 // set masked area in buffer to BLACK (pixel value 0)
1229 COLORREF prevBkCol = ::SetBkColor((HDC) m_hDC, RGB(255, 255, 255));
1230 COLORREF prevCol = ::SetTextColor((HDC) m_hDC, RGB(0, 0, 0));
1231 ::BitBlt(dc_buffer, 0, 0, (int)width, (int)height,
1232 dc_mask, xsrc1, ysrc1, SRCAND);
1233
1234 // set unmasked area in dest to BLACK
1235 ::SetBkColor((HDC) m_hDC, RGB(0, 0, 0));
1236 ::SetTextColor((HDC) m_hDC, RGB(255, 255, 255));
1237 ::BitBlt((HDC) m_hDC, xdest1, ydest1, (int)width, (int)height,
1238 dc_mask, xsrc1, ysrc1, SRCAND);
1239 ::SetBkColor((HDC) m_hDC, prevBkCol); // restore colours to original values
1240 ::SetTextColor((HDC) m_hDC, prevCol);
1241
1242 // OR buffer to dest
1243 success = (::BitBlt((HDC) m_hDC, xdest1, ydest1, (int)width, (int)height,
1244 dc_buffer, 0, 0, SRCPAINT) != 0);
1245
1246 // tidy up temporary DCs and bitmap
1247 ::SelectObject(dc_mask, 0);
1248 ::DeleteDC(dc_mask);
1249 ::SelectObject(dc_buffer, 0);
1250 ::DeleteDC(dc_buffer);
1251 ::DeleteObject(buffer_bmap);
1252 }
1253 }
1254 else
1255 {
1256 success = (BitBlt((HDC) m_hDC, xdest1, ydest1, (int)width, (int)height, (HDC) source->m_hDC,
1257 xsrc1, ysrc1, dwRop) != 0);
1258 }
1259 ::SetTextColor((HDC)m_hDC, old_textground);
1260 ::SetBkColor((HDC)m_hDC, old_background);
1261
1262 return success;
1263 }
1264
1265 void wxDC::GetSize(int* width, int* height) const
1266 {
1267 long w=::GetDeviceCaps((HDC) m_hDC,HORZRES);
1268 long h=::GetDeviceCaps((HDC) m_hDC,VERTRES);
1269 *width = w;
1270 *height = h;
1271 }
1272
1273 void wxDC::GetSizeMM(long *width, long *height) const
1274 {
1275 long w=::GetDeviceCaps((HDC) m_hDC,HORZSIZE);
1276 long h=::GetDeviceCaps((HDC) m_hDC,VERTSIZE);
1277 *width = w;
1278 *height = h;
1279 }
1280
1281 #if USE_SPLINES
1282 #include "xfspline.inc"
1283 #endif // USE_SPLINES
1284
1285 void wxDC::DrawPolygon(wxList *list, long xoffset, long yoffset,int fillStyle)
1286 {
1287 int n = list->Number();
1288 wxPoint *points = new wxPoint[n];
1289
1290 int i = 0;
1291 for(wxNode *node = list->First(); node; node = node->Next()) {
1292 wxPoint *point = (wxPoint *)node->Data();
1293 points[i].x = point->x;
1294 points[i++].y = point->y;
1295 }
1296 DrawPolygon(n, points, xoffset, yoffset,fillStyle);
1297 delete[] points;
1298 }
1299
1300 void wxDC::DrawLines(wxList *list, long xoffset, long yoffset)
1301 {
1302 int n = list->Number();
1303 wxPoint *points = new wxPoint[n];
1304
1305 int i = 0;
1306 for(wxNode *node = list->First(); node; node = node->Next()) {
1307 wxPoint *point = (wxPoint *)node->Data();
1308 points[i].x = point->x;
1309 points[i++].y = point->y;
1310 }
1311 DrawLines(n, points, xoffset, yoffset);
1312 delete []points;
1313 }
1314
1315 void wxDC::SetTextForeground(const wxColour& colour)
1316 {
1317 m_textForegroundColour = colour;
1318 }
1319
1320 void wxDC::SetTextBackground(const wxColour& colour)
1321 {
1322 m_textBackgroundColour = colour;
1323 }
1324
1325 #if USE_SPLINES
1326 // Make a 3-point spline
1327 void wxDC::DrawSpline(long x1, long y1, long x2, long y2, long x3, long y3)
1328 {
1329 wxList *point_list = new wxList;
1330
1331 wxPoint *point1 = new wxPoint;
1332 point1->x = x1; point1->y = y1;
1333 point_list->Append((wxObject*)point1);
1334
1335 wxPoint *point2 = new wxPoint;
1336 point2->x = x2; point2->y = y2;
1337 point_list->Append((wxObject*)point2);
1338
1339 wxPoint *point3 = new wxPoint;
1340 point3->x = x3; point3->y = y3;
1341 point_list->Append((wxObject*)point3);
1342
1343 DrawSpline(point_list);
1344
1345 for(wxNode *node = point_list->First(); node; node = node->Next()) {
1346 wxPoint *p = (wxPoint *)node->Data();
1347 delete p;
1348 }
1349 delete point_list;
1350 }
1351 #endif
1352
1353 // For use by wxWindows only, unless custom units are required.
1354 void wxDC::SetLogicalScale(double x, double y)
1355 {
1356 m_logicalScaleX = x;
1357 m_logicalScaleY = y;
1358 }
1359
1360 void wxDC::CalcBoundingBox(long x, long y)
1361 {
1362 if (x < m_minX) m_minX = x;
1363 if (y < m_minY) m_minY = y;
1364 if (x > m_maxX) m_maxX = x;
1365 if (y > m_maxY) m_maxY = y;
1366 }
1367
1368 void wxDC::GetClippingBox(long *x,long *y,long *w,long *h) const
1369 {
1370 if (m_clipping)
1371 {
1372 *x = m_clipX1 ;
1373 *y = m_clipY1 ;
1374 *w = (m_clipX2 - m_clipX1) ;
1375 *h = (m_clipY2 - m_clipY1) ;
1376 }
1377 else
1378 *x = *y = *w = *h = 0 ;
1379 }
1380
1381 #if WXWIN_COMPATIBILITY
1382 void wxDC::GetTextExtent(const wxString& string, float *x, float *y,
1383 float *descent, float *externalLeading,
1384 wxFont *theFont, bool use16bit) const
1385 {
1386 long x1, y1, descent1, externalLeading1;
1387 GetTextExtent(string, & x1, & y1, & descent1, & externalLeading1, theFont, use16bit);
1388 *x = x1; *y = y1;
1389 if (descent)
1390 *descent = descent1;
1391 if (externalLeading)
1392 *externalLeading = externalLeading1;
1393 }
1394 #endif
1395