]>
git.saurik.com Git - wxWidgets.git/blob - src/msw/dc.cpp
1 /////////////////////////////////////////////////////////////////////////////
4 // Author: Julian Smart
8 // Copyright: (c) Julian Smart and Markus Holzem
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
13 #pragma implementation "dc.h"
16 // For compilers that support precompilation, includes "wx.h".
17 #include "wx/wxprec.h"
27 #include "wx/dialog.h"
31 #include "wx/dcprint.h"
32 #include "wx/msw/private.h"
38 #if USE_COMMON_DIALOGS
58 #if !USE_SHARED_LIBRARY
59 IMPLEMENT_ABSTRACT_CLASS(wxDC
, wxObject
)
62 // Declarations local to this file
64 #define YSCALE(y) (yorigin - (y))
66 // #define wx_round(a) (int)((a)+.5)
68 // Default constructor
71 m_minX
= 0; m_minY
= 0; m_maxX
= 0; m_maxY
= 0;
81 m_minX
= 0; m_minY
= 0; m_maxX
= 0; m_maxY
= 0;
86 m_logicalScaleX
= 1.0;
87 m_logicalScaleY
= 1.0;
94 m_mappingMode
= MM_TEXT
;
99 m_windowExtX
= VIEWPORT_EXTENT
;
100 m_windowExtY
= VIEWPORT_EXTENT
;
101 m_logicalFunction
= -1;
103 m_backgroundBrush
= *wxWHITE_BRUSH
;
105 m_textForegroundColour
= *wxBLACK
;
106 m_textBackgroundColour
= *wxWHITE
;
108 m_colour
= wxColourDisplay();
117 SelectOldObjects(m_hDC
);
119 if ( m_canvas
== NULL
)
120 ::DeleteDC((HDC
)m_hDC
);
122 ::ReleaseDC((HWND
)m_canvas
->GetHWND(), (HDC
)m_hDC
);
128 // This will select current objects out of the DC,
129 // which is what you have to do before deleting the
131 void wxDC::SelectOldObjects(WXHDC dc
)
134 wxDebugMsg("wxDC::SelectOldObjects %X\n", this);
141 wxDebugMsg("wxDC::SelectOldObjects: Selecting old HBITMAP %X\n", m_oldBitmap
);
143 ::SelectObject((HDC
) dc
, (HBITMAP
) m_oldBitmap
);
144 if (m_selectedBitmap
.Ok())
146 m_selectedBitmap
.SetSelectedInto(NULL
);
153 wxDebugMsg("wxDC::SelectOldObjects: Selecting old HPEN %X\n", m_oldPen
);
155 ::SelectObject((HDC
) dc
, (HPEN
) m_oldPen
);
161 wxDebugMsg("wxDC::SelectOldObjects: Selecting old HBRUSH %X\n", m_oldBrush
);
163 ::SelectObject((HDC
) dc
, (HBRUSH
) m_oldBrush
);
169 wxDebugMsg("wxDC::SelectOldObjects: Selecting old HFONT %X\n", m_oldFont
);
171 ::SelectObject((HDC
) dc
, (HFONT
) m_oldFont
);
177 wxDebugMsg("wxDC::SelectOldObjects: Selecting old HPALETTE %X\n", m_oldPalette
);
179 ::SelectPalette((HDC
) dc
, (HPALETTE
) m_oldPalette
, TRUE
);
182 wxDebugMsg("wxDC::SelectOldObjects: Done.\n");
187 m_brush
= wxNullBrush
;
189 m_palette
= wxNullPalette
;
191 m_backgroundBrush
= wxNullBrush
;
192 m_selectedBitmap
= wxNullBitmap
;
195 void wxDC::SetClippingRegion(long cx
, long cy
, long cw
, long ch
)
200 m_clipX2
= (int)(cx
+ cw
);
201 m_clipY2
= (int)(cy
+ ch
);
203 DoClipping((WXHDC
) m_hDC
);
206 void wxDC::DoClipping(WXHDC dc
)
208 if (m_clipping
&& dc
)
210 IntersectClipRect((HDC
) dc
, XLOG2DEV(m_clipX1
), YLOG2DEV(m_clipY1
),
211 XLOG2DEV(m_clipX2
), YLOG2DEV(m_clipY2
));
215 void wxDC::DestroyClippingRegion(void)
217 if (m_clipping
&& m_hDC
)
219 HRGN rgn
= CreateRectRgn(0, 0, 32000, 32000);
221 wxDebugMsg("wxDC::DestroyClippingRegion: Selecting HRGN %X\n", rgn
);
223 SelectClipRgn((HDC
) m_hDC
, rgn
);
225 wxDebugMsg("wxDC::DestroyClippingRegion: Deleting HRGN %X\n", rgn
);
232 bool wxDC::CanDrawBitmap(void) const
237 bool wxDC::CanGetTextExtent(void) const
239 // What sort of display is it?
240 int technology
= ::GetDeviceCaps((HDC
) m_hDC
, TECHNOLOGY
);
244 if (technology
!= DT_RASDISPLAY
&& technology
!= DT_RASPRINTER
)
251 void wxDC::SetPalette(const wxPalette
& palette
)
253 // Set the old object temporarily, in case the assignment deletes an object
254 // that's not yet selected out.
257 ::SelectPalette((HDC
) m_hDC
, (HPALETTE
) m_oldPalette
, TRUE
);
261 m_palette
= m_palette
;
265 // Setting a NULL colourmap is a way of restoring
266 // the original colourmap
269 ::SelectPalette((HDC
) m_hDC
, (HPALETTE
) m_oldPalette
, TRUE
);
271 wxDebugMsg("wxDC::SetPalette: set old palette %X\n", m_oldPalette
);
279 if (m_palette
.Ok() && m_palette
.GetHPALETTE())
281 HPALETTE oldPal
= ::SelectPalette((HDC
) m_hDC
, (HPALETTE
) m_palette
.GetHPALETTE(), TRUE
);
283 m_oldPalette
= (WXHPALETTE
) oldPal
;
286 wxDebugMsg("wxDC::SetPalette %X: selected palette %X\n", this, m_palette
.GetHPALETTE());
288 wxDebugMsg("wxDC::SetPalette: oldPal was palette %X\n", oldPal
);
290 wxDebugMsg("wxDC::SetPalette: m_oldPalette is palette %X\n", m_oldPalette
);
292 ::RealizePalette((HDC
) m_hDC
);
296 void wxDC::Clear(void)
300 GetClientRect((HWND
) m_canvas
->GetHWND(), &rect
);
301 else if (m_selectedBitmap
.Ok())
303 rect
.left
= 0; rect
.top
= 0;
304 rect
.right
= m_selectedBitmap
.GetWidth();
305 rect
.bottom
= m_selectedBitmap
.GetHeight();
307 (void) ::SetMapMode((HDC
) m_hDC
, MM_TEXT
);
309 DWORD colour
= GetBkColor((HDC
) m_hDC
);
310 HBRUSH brush
= CreateSolidBrush(colour
);
311 FillRect((HDC
) m_hDC
, &rect
, brush
);
314 ::SetMapMode((HDC
) m_hDC
, MM_ANISOTROPIC
);
315 ::SetViewportExtEx((HDC
) m_hDC
, VIEWPORT_EXTENT
, VIEWPORT_EXTENT
, NULL
);
316 ::SetWindowExtEx((HDC
) m_hDC
, m_windowExtX
, m_windowExtY
, NULL
);
317 ::SetViewportOrgEx((HDC
) m_hDC
, (int)m_deviceOriginX
, (int)m_deviceOriginY
, NULL
);
318 ::SetWindowOrgEx((HDC
) m_hDC
, (int)m_logicalOriginX
, (int)m_logicalOriginY
, NULL
);
321 void wxDC::FloodFill(long x
, long y
, const wxColour
& col
, int style
)
323 (void)ExtFloodFill((HDC
) m_hDC
, XLOG2DEV(x
), YLOG2DEV(y
),
325 style
==wxFLOOD_SURFACE
?
326 FLOODFILLSURFACE
:FLOODFILLBORDER
329 CalcBoundingBox(x
, y
);
332 bool wxDC::GetPixel(long x
, long y
, wxColour
*col
) const
334 // added by steve 29.12.94 (copied from DrawPoint)
335 // returns TRUE for pixels in the color of the current pen
336 // and FALSE for all other pixels colors
337 // if col is non-NULL return the color of the pixel
339 // get the color of the pixel
340 COLORREF pixelcolor
= ::GetPixel((HDC
) m_hDC
, XLOG2DEV(x
), YLOG2DEV(y
));
341 // get the color of the pen
342 COLORREF pencolor
= 0x00ffffff;
345 pencolor
= m_pen
.GetColour().GetPixel() ;
348 // return the color of the pixel
350 col
->Set(GetRValue(pixelcolor
),GetGValue(pixelcolor
),GetBValue(pixelcolor
));
352 // check, if color of the pixels is the same as the color
353 // of the current pen
354 return(pixelcolor
==pencolor
);
357 void wxDC::CrossHair(long x
, long y
)
359 // We suppose that our screen is 2000x2000 max.
365 (void)MoveToEx((HDC
) m_hDC
, XLOG2DEV(x1
), YLOG2DEV(y
), NULL
);
366 (void)LineTo((HDC
) m_hDC
, XLOG2DEV(x2
), YLOG2DEV(y
));
368 (void)MoveToEx((HDC
) m_hDC
, XLOG2DEV(x
), YLOG2DEV(y1
), NULL
);
369 (void)LineTo((HDC
) m_hDC
, XLOG2DEV(x
), YLOG2DEV(y2
));
371 CalcBoundingBox(x1
, y1
);
372 CalcBoundingBox(x2
, y2
);
375 void wxDC::DrawLine(long x1
, long y1
, long x2
, long y2
)
377 (void)MoveToEx((HDC
) m_hDC
, XLOG2DEV(x1
), YLOG2DEV(y1
), NULL
);
378 (void)LineTo((HDC
) m_hDC
, XLOG2DEV(x2
), YLOG2DEV(y2
));
380 /* MATTHEW: [6] New normalization */
381 #if WX_STANDARD_GRAPHICS
382 (void)LineTo((HDC
) m_hDC
, XLOG2DEV(x2
) + 1, YLOG2DEV(y2
));
385 CalcBoundingBox(x1
, y1
);
386 CalcBoundingBox(x2
, y2
);
389 void wxDC::DrawArc(long x1
,long y1
,long x2
,long y2
, long xc
, long yc
)
393 double radius
= (double)sqrt(dx
*dx
+dy
*dy
) ;;
394 if (x1
==x2
&& x2
==y2
)
396 DrawEllipse(xc
,yc
,(double)(radius
*2.0),(double)(radius
*2)) ;
400 long xx1
= XLOG2DEV(x1
) ;
401 long yy1
= YLOG2DEV(y1
) ;
402 long xx2
= XLOG2DEV(x2
) ;
403 long yy2
= YLOG2DEV(y2
) ;
404 long xxc
= XLOG2DEV(xc
) ;
405 long yyc
= YLOG2DEV(yc
) ;
406 long ray
= (long) sqrt(double((xxc
-xx1
)*(xxc
-xx1
)+(yyc
-yy1
)*(yyc
-yy1
))) ;
408 (void)MoveToEx((HDC
) m_hDC
, (int) xx1
, (int) yy1
, NULL
);
409 long xxx1
= (long) (xxc
-ray
);
410 long yyy1
= (long) (yyc
-ray
);
411 long xxx2
= (long) (xxc
+ray
);
412 long yyy2
= (long) (yyc
+ray
);
413 if (m_brush
.Ok() && m_brush
.GetStyle() !=wxTRANSPARENT
)
415 // Have to add 1 to bottom-right corner of rectangle
416 // to make semi-circles look right (crooked line otherwise).
417 // Unfortunately this is not a reliable method, depends
418 // on the size of shape.
419 // TODO: figure out why this happens!
420 Pie((HDC
) m_hDC
,xxx1
,yyy1
,xxx2
+1,yyy2
+1,
424 Arc((HDC
) m_hDC
,xxx1
,yyy1
,xxx2
,yyy2
,
427 CalcBoundingBox((xc
-radius
), (yc
-radius
));
428 CalcBoundingBox((xc
+radius
), (yc
+radius
));
431 void wxDC::DrawPoint(long x
, long y
)
433 COLORREF color
= 0x00ffffff;
436 color
= m_pen
.GetColour().GetPixel() ;
439 SetPixel((HDC
) m_hDC
, XLOG2DEV(x
), YLOG2DEV(y
), color
);
441 CalcBoundingBox(x
, y
);
444 void wxDC::DrawPolygon(int n
, wxPoint points
[], long xoffset
, long yoffset
,int fillStyle
)
446 // Do things less efficiently if we have offsets
447 if (xoffset
!= 0 || yoffset
!= 0)
449 POINT
*cpoints
= new POINT
[n
];
451 for (i
= 0; i
< n
; i
++)
453 cpoints
[i
].x
= (int)(points
[i
].x
+ xoffset
);
454 cpoints
[i
].y
= (int)(points
[i
].y
+ yoffset
);
456 CalcBoundingBox(cpoints
[i
].x
, cpoints
[i
].y
);
458 int prev
= SetPolyFillMode((HDC
) m_hDC
,fillStyle
==wxODDEVEN_RULE
?ALTERNATE
:WINDING
) ;
459 (void)Polygon((HDC
) m_hDC
, cpoints
, n
);
460 SetPolyFillMode((HDC
) m_hDC
,prev
) ;
466 for (i
= 0; i
< n
; i
++)
467 CalcBoundingBox(points
[i
].x
, points
[i
].y
);
469 int prev
= SetPolyFillMode((HDC
) m_hDC
,fillStyle
==wxODDEVEN_RULE
?ALTERNATE
:WINDING
) ;
470 (void)Polygon((HDC
) m_hDC
, (POINT
*) points
, n
);
471 SetPolyFillMode((HDC
) m_hDC
,prev
) ;
475 void wxDC::DrawLines(int n
, wxPoint points
[], long xoffset
, long yoffset
)
477 // Do things less efficiently if we have offsets
478 if (xoffset
!= 0 || yoffset
!= 0)
480 POINT
*cpoints
= new POINT
[n
];
482 for (i
= 0; i
< n
; i
++)
484 cpoints
[i
].x
= (int)(points
[i
].x
+ xoffset
);
485 cpoints
[i
].y
= (int)(points
[i
].y
+ yoffset
);
487 CalcBoundingBox(cpoints
[i
].x
, cpoints
[i
].y
);
489 (void)Polyline((HDC
) m_hDC
, cpoints
, n
);
495 for (i
= 0; i
< n
; i
++)
496 CalcBoundingBox(points
[i
].x
, points
[i
].y
);
498 (void)Polyline((HDC
) m_hDC
, (POINT
*) points
, n
);
502 void wxDC::DrawRectangle(long x
, long y
, long width
, long height
)
505 long y2
= y
+ height
;
507 /* MATTHEW: [6] new normalization */
508 #if WX_STANDARD_GRAPHICS
509 bool do_brush
, do_pen
;
511 do_brush
= m_brush
.Ok() && m_brush
.GetStyle() != wxTRANSPARENT
;
512 do_pen
= m_pen
.Ok() && m_pen
.GetStyle() != wxTRANSPARENT
;
515 HPEN orig_pen
= NULL
;
517 if (do_pen
|| !m_pen
.Ok())
518 orig_pen
= (HPEN
) ::SelectObject((HDC
) m_hDC
, (HPEN
) ::GetStockObject(NULL_PEN
));
520 (void)Rectangle((HDC
) m_hDC
, XLOG2DEV(x
), YLOG2DEV(y
),
521 XLOG2DEV(x2
) + 1, YLOG2DEV(y2
) + 1);
523 if (do_pen
|| !m_pen
.Ok())
524 ::SelectObject((HDC
) m_hDC
, orig_pen
);
527 HBRUSH orig_brush
= NULL
;
529 if (do_brush
|| !m_brush
.Ok())
530 orig_brush
= (HBRUSH
) ::SelectObject((HDC
) m_hDC
, (HBRUSH
) ::GetStockObject(NULL_BRUSH
));
532 (void)Rectangle((HDC
) m_hDC
, XLOG2DEV(x
), YLOG2DEV(y
),
533 XLOG2DEV(x2
), YLOG2DEV(y2
));
535 if (do_brush
|| !m_brush
.Ok())
536 ::SelectObject((HDC
) m_hDC
, orig_brush
);
539 (void)Rectangle((HDC
) m_hDC
, XLOG2DEV(x
), YLOG2DEV(y
), XLOG2DEV(x2
), YLOG2DEV(y2
));
542 CalcBoundingBox(x
, y
);
543 CalcBoundingBox(x2
, y2
);
546 void wxDC::DrawRoundedRectangle(long x
, long y
, long width
, long height
, double radius
)
548 // Now, a negative radius value is interpreted to mean
549 // 'the proportion of the smallest X or Y dimension'
553 double smallest
= 0.0;
558 radius
= (- radius
* smallest
);
562 long y2
= (y
+height
);
564 (void)RoundRect((HDC
) m_hDC
, XLOG2DEV(x
), YLOG2DEV(y
), XLOG2DEV(x2
),
565 YLOG2DEV(y2
), 2*XLOG2DEV(radius
), 2*YLOG2DEV(radius
));
567 CalcBoundingBox(x
, y
);
568 CalcBoundingBox(x2
, y2
);
571 void wxDC::DrawEllipse(long x
, long y
, long width
, long height
)
574 long y2
= (y
+height
);
576 (void)Ellipse((HDC
) m_hDC
, XLOG2DEV(x
), YLOG2DEV(y
), XLOG2DEV(x2
), YLOG2DEV(y2
));
578 CalcBoundingBox(x
, y
);
579 CalcBoundingBox(x2
, y2
);
582 // Chris Breeze 20/5/98: first implementation of DrawEllipticArc on Windows
583 void wxDC::DrawEllipticArc(long x
,long y
,long w
,long h
,double sa
,double ea
)
588 const double deg2rad
= 3.14159265359 / 180.0;
589 int rx1
= XLOG2DEV(x
+w
/2);
590 int ry1
= YLOG2DEV(y
+h
/2);
593 rx1
+= (int)(100.0 * abs(w
) * cos(sa
* deg2rad
));
594 ry1
-= (int)(100.0 * abs(h
) * m_signY
* sin(sa
* deg2rad
));
595 rx2
+= (int)(100.0 * abs(w
) * cos(ea
* deg2rad
));
596 ry2
-= (int)(100.0 * abs(h
) * m_signY
* sin(ea
* deg2rad
));
598 // draw pie with NULL_PEN first and then outline otherwise a line is
599 // drawn from the start and end points to the centre
600 HPEN orig_pen
= (HPEN
) ::SelectObject((HDC
) m_hDC
, (HPEN
) ::GetStockObject(NULL_PEN
));
603 (void)Pie((HDC
) m_hDC
, XLOG2DEV(x
), YLOG2DEV(y
), XLOG2DEV(x2
)+1, YLOG2DEV(y2
)+1,
608 (void)Pie((HDC
) m_hDC
, XLOG2DEV(x
), YLOG2DEV(y
)-1, XLOG2DEV(x2
)+1, YLOG2DEV(y2
),
609 rx1
, ry1
-1, rx2
, ry2
-1);
611 ::SelectObject((HDC
) m_hDC
, orig_pen
);
612 (void)Arc((HDC
) m_hDC
, XLOG2DEV(x
), YLOG2DEV(y
), XLOG2DEV(x2
), YLOG2DEV(y2
),
615 CalcBoundingBox(x
, y
);
616 CalcBoundingBox(x2
, y2
);
619 void wxDC::DrawIcon(const wxIcon
& icon
, long x
, long y
)
621 ::DrawIcon((HDC
) m_hDC
, XLOG2DEV(x
), YLOG2DEV(y
), (HICON
) icon
.GetHICON());
622 CalcBoundingBox(x
, y
);
623 CalcBoundingBox(x
+icon
.GetWidth(), y
+icon
.GetHeight());
626 void wxDC::SetFont(const wxFont
& the_font
)
628 // Set the old object temporarily, in case the assignment deletes an object
629 // that's not yet selected out.
632 ::SelectObject((HDC
) m_hDC
, (HFONT
) m_oldFont
);
641 ::SelectObject((HDC
) m_hDC
, (HFONT
) m_oldFont
);
645 if (m_font
.Ok() && m_font
.GetResourceHandle())
648 wxDebugMsg("wxDC::SetFont: Selecting HFONT %X\n", m_font
.GetResourceHandle());
650 HFONT f
= (HFONT
) ::SelectObject((HDC
) m_hDC
, (HFONT
) m_font
.GetResourceHandle());
653 wxDebugMsg("::SelectObject failed in wxDC::SetFont.");
656 m_oldFont
= (WXHFONT
) f
;
660 void wxDC::SetPen(const wxPen
& pen
)
662 // Set the old object temporarily, in case the assignment deletes an object
663 // that's not yet selected out.
666 ::SelectObject((HDC
) m_hDC
, (HPEN
) m_oldPen
);
675 ::SelectObject((HDC
) m_hDC
, (HPEN
) m_oldPen
);
681 if (m_pen
.GetResourceHandle())
683 HPEN p
= (HPEN
) ::SelectObject((HDC
) m_hDC
, (HPEN
)m_pen
.GetResourceHandle()) ;
685 m_oldPen
= (WXHPEN
) p
;
690 void wxDC::SetBrush(const wxBrush
& brush
)
692 // Set the old object temporarily, in case the assignment deletes an object
693 // that's not yet selected out.
696 ::SelectObject((HDC
) m_hDC
, (HBRUSH
) m_oldBrush
);
705 ::SelectObject((HDC
) m_hDC
, (HBRUSH
) m_oldBrush
);
711 if (m_brush
.GetResourceHandle())
714 b
= (HBRUSH
) ::SelectObject((HDC
) m_hDC
, (HBRUSH
)m_brush
.GetResourceHandle()) ;
716 m_oldBrush
= (WXHBRUSH
) b
;
721 void wxDC::DrawText(const wxString
& text
, long x
, long y
, bool use16bit
)
723 // Should be unnecessary: SetFont should have done this already.
725 if (m_font
.Ok() && m_font
.GetResourceHandle())
728 wxDebugMsg("wxDC::DrawText: Selecting HFONT %X\n", m_font
.GetResourceHandle());
730 HFONT f
= (HFONT
) ::SelectObject((HDC
) m_hDC
, (HFONT
) m_font
.GetResourceHandle());
732 m_oldFont
= (WXHFONT
) f
;
736 if (m_textForegroundColour
.Ok())
737 SetTextColor((HDC
) m_hDC
, m_textForegroundColour
.GetPixel() ) ;
739 DWORD old_background
;
740 if (m_textBackgroundColour
.Ok())
742 old_background
= SetBkColor((HDC
) m_hDC
, m_textBackgroundColour
.GetPixel() ) ;
745 if (m_backgroundMode
== wxTRANSPARENT
)
746 SetBkMode((HDC
) m_hDC
, TRANSPARENT
);
748 SetBkMode((HDC
) m_hDC
, OPAQUE
);
750 (void)TextOut((HDC
) m_hDC
, XLOG2DEV(x
), YLOG2DEV(y
), (char *) (const char *)text
, strlen((const char *)text
));
752 if (m_textBackgroundColour
.Ok())
753 (void)SetBkColor((HDC
) m_hDC
, old_background
);
755 CalcBoundingBox(x
, y
);
758 GetTextExtent(text
, &w
, &h
);
759 CalcBoundingBox((x
+ w
), (y
+ h
));
762 void wxDC::SetBackground(const wxBrush
& brush
)
764 m_backgroundBrush
= brush
;
766 if (!m_backgroundBrush
.Ok())
771 bool customColours
= TRUE
;
772 // If we haven't specified wxUSER_COLOURS, don't allow the panel/dialog box to
773 // change background colours from the control-panel specified colours.
774 if (m_canvas
->IsKindOf(CLASSINFO(wxWindow
)) && ((m_canvas
->GetWindowStyleFlag() & wxUSER_COLOURS
) != wxUSER_COLOURS
))
775 customColours
= FALSE
;
779 if (m_backgroundBrush
.GetStyle()==wxTRANSPARENT
)
781 m_canvas
->m_backgroundTransparent
= TRUE
;
785 m_canvas
->SetBackgroundColour(m_backgroundBrush
.GetColour());
786 m_canvas
->m_backgroundTransparent
= FALSE
;
790 COLORREF new_color
= m_backgroundBrush
.GetColour().GetPixel() ;
792 (void)SetBkColor((HDC
) m_hDC
, new_color
);
796 void wxDC::SetBackgroundMode(int mode
)
798 m_backgroundMode
= mode
;
800 if (m_backgroundMode
== wxTRANSPARENT
)
801 ::SetBkMode((HDC
) m_hDC
, TRANSPARENT
);
803 ::SetBkMode((HDC
) m_hDC
, OPAQUE
);
806 void wxDC::SetLogicalFunction(int function
)
808 m_logicalFunction
= function
;
810 SetRop((WXHDC
) m_hDC
);
813 void wxDC::SetRop(WXHDC dc
)
815 if (!dc
|| m_logicalFunction
< 0)
819 // These may be wrong
820 switch (m_logicalFunction
)
822 // case wxXOR: c_rop = R2_XORPEN; break;
823 case wxXOR
: c_rop
= R2_NOTXORPEN
; break;
824 case wxINVERT
: c_rop
= R2_NOT
; break;
825 case wxOR_REVERSE
: c_rop
= R2_MERGEPENNOT
; break;
826 case wxAND_REVERSE
: c_rop
= R2_MASKPENNOT
; break;
827 case wxCLEAR
: c_rop
= R2_WHITE
; break;
828 case wxSET
: c_rop
= R2_BLACK
; break;
829 case wxSRC_INVERT
: c_rop
= R2_NOTCOPYPEN
; break;
830 case wxOR_INVERT
: c_rop
= R2_MERGENOTPEN
; break;
831 case wxAND
: c_rop
= R2_MASKPEN
; break;
832 case wxOR
: c_rop
= R2_MERGEPEN
; break;
833 case wxAND_INVERT
: c_rop
= R2_MASKNOTPEN
; break;
838 c_rop
= R2_COPYPEN
; break;
840 SetROP2((HDC
) dc
, c_rop
);
843 bool wxDC::StartDoc(const wxString
& message
)
845 if (!this->IsKindOf(CLASSINFO(wxPrinterDC
)))
849 docinfo
.cbSize
= sizeof(DOCINFO
);
850 docinfo
.lpszDocName
= (const char *)message
;
852 if (m_filename
.IsEmpty())
853 docinfo
.lpszOutput
= NULL
;
855 docinfo
.lpszOutput
= (const char *)m_filename
;
857 #if defined(__WIN95__)
858 docinfo
.lpszDatatype
= NULL
;
867 ::StartDoc((HDC
) m_hDC
, &docinfo
);
870 ::StartDocW((HDC
) m_hDC
, &docinfo
);
872 ::StartDocA((HDC
) m_hDC
, &docinfo
);
878 DWORD lastError
= GetLastError();
879 wxDebugMsg("wxDC::StartDoc failed with error: %d\n", lastError
);
884 void wxDC::EndDoc(void)
886 if (!this->IsKindOf(CLASSINFO(wxPrinterDC
)))
888 if (m_hDC
) ::EndDoc((HDC
) m_hDC
);
891 void wxDC::StartPage(void)
893 if (!this->IsKindOf(CLASSINFO(wxPrinterDC
)))
896 ::StartPage((HDC
) m_hDC
);
899 void wxDC::EndPage(void)
901 if (!this->IsKindOf(CLASSINFO(wxPrinterDC
)))
904 ::EndPage((HDC
) m_hDC
);
907 long wxDC::GetCharHeight(void) const
909 TEXTMETRIC lpTextMetric
;
911 GetTextMetrics((HDC
) m_hDC
, &lpTextMetric
);
913 return YDEV2LOGREL(lpTextMetric
.tmHeight
);
916 long wxDC::GetCharWidth(void) const
918 TEXTMETRIC lpTextMetric
;
920 GetTextMetrics((HDC
) m_hDC
, &lpTextMetric
);
922 return XDEV2LOGREL(lpTextMetric
.tmAveCharWidth
);
925 void wxDC::GetTextExtent(const wxString
& string
, long *x
, long *y
,
926 long *descent
, long *externalLeading
, wxFont
*theFont
, bool use16bit
) const
928 wxFont
*fontToUse
= (wxFont
*) theFont
;
930 fontToUse
= (wxFont
*) &m_font
;
935 GetTextExtentPoint((HDC
) m_hDC
, (char *)(const char *) string
, strlen((char *)(const char *) string
), &sizeRect
);
936 GetTextMetrics((HDC
) m_hDC
, &tm
);
938 if (x
) *x
= XDEV2LOGREL(sizeRect
.cx
);
939 if (y
) *y
= YDEV2LOGREL(sizeRect
.cy
);
940 if (descent
) *descent
= tm
.tmDescent
;
941 if (externalLeading
) *externalLeading
= tm
.tmExternalLeading
;
944 void wxDC::SetMapMode(int mode
)
946 m_mappingMode
= mode
;
949 int pixel_height
= 0;
953 pixel_width
= GetDeviceCaps((HDC
) m_hDC
, HORZRES
);
954 pixel_height
= GetDeviceCaps((HDC
) m_hDC
, VERTRES
);
955 mm_width
= GetDeviceCaps((HDC
) m_hDC
, HORZSIZE
);
956 mm_height
= GetDeviceCaps((HDC
) m_hDC
, VERTSIZE
);
958 if ((pixel_width
== 0) || (pixel_height
== 0) || (mm_width
== 0) || (mm_height
== 0))
963 double mm2pixelsX
= pixel_width
/mm_width
;
964 double mm2pixelsY
= pixel_height
/mm_height
;
970 m_logicalScaleX
= (twips2mm
* mm2pixelsX
);
971 m_logicalScaleY
= (twips2mm
* mm2pixelsY
);
976 m_logicalScaleX
= (pt2mm
* mm2pixelsX
);
977 m_logicalScaleY
= (pt2mm
* mm2pixelsY
);
982 m_logicalScaleX
= mm2pixelsX
;
983 m_logicalScaleY
= mm2pixelsY
;
988 m_logicalScaleX
= (mm2pixelsX
/10.0);
989 m_logicalScaleY
= (mm2pixelsY
/10.0);
995 m_logicalScaleX
= 1.0;
996 m_logicalScaleY
= 1.0;
1001 if (::GetMapMode((HDC
) m_hDC
) != MM_ANISOTROPIC
)
1002 ::SetMapMode((HDC
) m_hDC
, MM_ANISOTROPIC
);
1004 SetViewportExtEx((HDC
) m_hDC
, VIEWPORT_EXTENT
, VIEWPORT_EXTENT
, NULL
);
1005 m_windowExtX
= (int)MS_XDEV2LOGREL(VIEWPORT_EXTENT
);
1006 m_windowExtY
= (int)MS_YDEV2LOGREL(VIEWPORT_EXTENT
);
1007 ::SetWindowExtEx((HDC
) m_hDC
, m_windowExtX
, m_windowExtY
, NULL
);
1008 ::SetViewportOrgEx((HDC
) m_hDC
, (int)m_deviceOriginX
, (int)m_deviceOriginY
, NULL
);
1009 ::SetWindowOrgEx((HDC
) m_hDC
, (int)m_logicalOriginX
, (int)m_logicalOriginY
, NULL
);
1012 void wxDC::SetUserScale(double x
, double y
)
1017 SetMapMode(m_mappingMode
);
1020 void wxDC::SetAxisOrientation(bool xLeftRight
, bool yBottomUp
)
1022 m_signX
= xLeftRight
? 1 : -1;
1023 m_signY
= yBottomUp
? -1 : 1;
1025 SetMapMode(m_mappingMode
);
1028 void wxDC::SetSystemScale(double x
, double y
)
1033 SetMapMode(m_mappingMode
);
1036 void wxDC::SetLogicalOrigin(long x
, long y
)
1038 m_logicalOriginX
= x
;
1039 m_logicalOriginY
= y
;
1041 ::SetWindowOrgEx((HDC
) m_hDC
, (int)m_logicalOriginX
, (int)m_logicalOriginY
, NULL
);
1044 void wxDC::SetDeviceOrigin(long x
, long y
)
1046 m_deviceOriginX
= x
;
1047 m_deviceOriginY
= y
;
1049 ::SetViewportOrgEx((HDC
) m_hDC
, (int)m_deviceOriginX
, (int)m_deviceOriginY
, NULL
);
1052 long wxDC::DeviceToLogicalX(long x
) const
1054 return (long) (((x
) - m_deviceOriginX
)/(m_logicalScaleX
*m_userScaleX
*m_signX
*m_systemScaleX
) - m_logicalOriginX
) ;
1057 long wxDC::DeviceToLogicalXRel(long x
) const
1059 return (long) ((x
)/(m_logicalScaleX
*m_userScaleX
*m_signX
*m_systemScaleX
)) ;
1062 long wxDC::DeviceToLogicalY(long y
) const
1064 return (long) (((y
) - m_deviceOriginY
)/(m_logicalScaleY
*m_userScaleY
*m_signY
*m_systemScaleY
) - m_logicalOriginY
) ;
1067 long wxDC::DeviceToLogicalYRel(long y
) const
1069 return (long) ((y
)/(m_logicalScaleY
*m_userScaleY
*m_signY
*m_systemScaleY
)) ;
1072 long wxDC::LogicalToDeviceX(long x
) const
1074 return (long) (floor((x
) - m_logicalOriginX
)*m_logicalScaleX
*m_userScaleX
*m_signX
*m_systemScaleX
+ m_deviceOriginX
) ;
1077 long wxDC::LogicalToDeviceXRel(long x
) const
1079 return (long) (floor(x
)*m_logicalScaleX
*m_userScaleX
*m_signX
*m_systemScaleX
) ;
1082 long wxDC::LogicalToDeviceY(long y
) const
1084 return (long) (floor((y
) - m_logicalOriginY
)*m_logicalScaleY
*m_userScaleY
*m_signY
*m_systemScaleY
+ m_deviceOriginY
);
1087 long wxDC::LogicalToDeviceYRel(long y
) const
1089 return (long) (floor(y
)*m_logicalScaleY
*m_userScaleY
*m_signY
*m_systemScaleY
) ;
1092 // This group of functions may not do any conversion
1093 // if m_scaleGDI is TRUE, since the HDC does the
1094 // conversion automatically.
1096 long wxDC::ImplDeviceToLogicalX(long x
) const
1098 // return (m_scaleGDI ? x : DeviceToLogicalX(x));
1102 long wxDC::ImplDeviceToLogicalY(long y
) const
1104 // return (m_scaleGDI ? y : DeviceToLogicalY(y));
1108 long wxDC::ImplDeviceToLogicalXRel(long x
) const
1110 // return (m_scaleGDI ? x : DeviceToLogicalXRel(x));
1114 long wxDC::ImplDeviceToLogicalYRel(long y
) const
1116 // return (m_scaleGDI ? y : DeviceToLogicalYRel(y));
1120 long wxDC::ImplLogicalToDeviceX(long x
) const
1122 // return (m_scaleGDI ? (floor(double(x))) : LogicalToDeviceX(x));
1126 long wxDC::ImplLogicalToDeviceY(long y
) const
1128 // return (m_scaleGDI ? (floor(double(y))) : LogicalToDeviceY(y));
1132 long wxDC::ImplLogicalToDeviceXRel(long x
) const
1134 // return (m_scaleGDI ? (floor(double(x))) : LogicalToDeviceXRel(x));
1138 long wxDC::ImplLogicalToDeviceYRel(long y
) const
1140 // return (m_scaleGDI ? (floor(double(y))) : LogicalToDeviceYRel(y));
1144 bool wxDC::Blit(long xdest
, long ydest
, long width
, long height
,
1145 wxDC
*source
, long xsrc
, long ysrc
, int rop
, bool useMask
)
1147 long xdest1
= xdest
;
1148 long ydest1
= ydest
;
1152 // Chris Breeze 18/5/98: use text foreground/background colours
1153 // when blitting from 1-bit bitmaps
1154 COLORREF old_textground
= ::GetTextColor((HDC
)m_hDC
);
1155 COLORREF old_background
= ::GetBkColor((HDC
)m_hDC
);
1156 if (m_textForegroundColour
.Ok())
1158 ::SetTextColor((HDC
) m_hDC
, m_textForegroundColour
.GetPixel() ) ;
1160 if (m_textBackgroundColour
.Ok())
1162 ::SetBkColor((HDC
) m_hDC
, m_textBackgroundColour
.GetPixel() ) ;
1165 DWORD dwRop
= rop
== wxCOPY
? SRCCOPY
:
1166 rop
== wxCLEAR
? WHITENESS
:
1167 rop
== wxSET
? BLACKNESS
:
1168 rop
== wxINVERT
? DSTINVERT
:
1169 rop
== wxAND
? MERGECOPY
:
1170 rop
== wxOR
? MERGEPAINT
:
1171 rop
== wxSRC_INVERT
? NOTSRCCOPY
:
1172 rop
== wxXOR
? SRCINVERT
:
1173 rop
== wxOR_REVERSE
? MERGEPAINT
:
1174 rop
== wxAND_REVERSE
? SRCERASE
:
1175 rop
== wxSRC_OR
? SRCPAINT
:
1176 rop
== wxSRC_AND
? SRCAND
:
1180 if (useMask
&& source
->m_selectedBitmap
.Ok() && source
->m_selectedBitmap
.GetMask())
1184 // Not implemented under Win95 (or maybe a specific device?)
1185 if (MaskBlt((HDC
) m_hDC
, xdest1
, ydest1
, (int)width
, (int)height
,
1186 (HDC
) source
->m_hDC
, xsrc1
, ysrc1
, (HBITMAP
) source
->m_selectedBitmap
.GetMask()->GetMaskBitmap(),
1196 HDC dc_mask
= CreateCompatibleDC((HDC
) source
->m_hDC
);
1197 ::SelectObject(dc_mask
, (HBITMAP
) source
->m_selectedBitmap
.GetMask()->GetMaskBitmap());
1198 success
= (BitBlt((HDC
) m_hDC
, xdest1
, ydest1
, (int)width
, (int)height
,
1199 dc_mask
, xsrc1
, ysrc1
, 0x00220326 /* NOTSRCAND */) != 0);
1200 success
= (BitBlt((HDC
) m_hDC
, xdest1
, ydest1
, (int)width
, (int)height
,
1201 (HDC
) source
->m_hDC
, xsrc1
, ysrc1
, SRCPAINT
) != 0);
1202 ::SelectObject(dc_mask
, 0);
1203 ::DeleteDC(dc_mask
);
1205 // New code from Chris Breeze, 15/7/98
1206 // Blit bitmap with mask
1208 if (IsKindOf(CLASSINFO(wxPrinterDC
)))
1210 // If we are printing source colours are screen colours
1211 // not printer colours and so we need copy the bitmap
1214 HDC dc_mask
= ::CreateCompatibleDC((HDC
) source
->m_hDC
);
1215 HDC dc_src
= (HDC
) source
->m_hDC
;
1217 ::SelectObject(dc_mask
, (HBITMAP
) source
->m_selectedBitmap
.GetMask()->GetMaskBitmap());
1218 for (int x
= 0; x
< width
; x
++)
1220 for (int y
= 0; y
< height
; y
++)
1222 COLORREF cref
= ::GetPixel(dc_mask
, x
, y
);
1225 HBRUSH brush
= ::CreateSolidBrush(::GetPixel(dc_src
, x
, y
));
1226 rect
.left
= xdest1
+ x
; rect
.right
= rect
.left
+ 1;
1227 rect
.top
= ydest1
+ y
; rect
.bottom
= rect
.top
+ 1;
1228 ::FillRect((HDC
) m_hDC
, &rect
, brush
);
1229 ::DeleteObject(brush
);
1233 ::SelectObject(dc_mask
, 0);
1234 ::DeleteDC(dc_mask
);
1238 // create a temp buffer bitmap and DCs to access it and the mask
1239 HDC dc_mask
= ::CreateCompatibleDC((HDC
) source
->m_hDC
);
1240 HDC dc_buffer
= ::CreateCompatibleDC((HDC
) m_hDC
);
1241 HBITMAP buffer_bmap
= ::CreateCompatibleBitmap((HDC
) m_hDC
, width
, height
);
1242 ::SelectObject(dc_mask
, (HBITMAP
) source
->m_selectedBitmap
.GetMask()->GetMaskBitmap());
1243 ::SelectObject(dc_buffer
, buffer_bmap
);
1245 // copy dest to buffer
1246 ::BitBlt(dc_buffer
, 0, 0, (int)width
, (int)height
,
1247 (HDC
) m_hDC
, xdest1
, ydest1
, SRCCOPY
);
1249 // copy src to buffer using selected raster op
1250 ::BitBlt(dc_buffer
, 0, 0, (int)width
, (int)height
,
1251 (HDC
) source
->m_hDC
, xsrc1
, ysrc1
, dwRop
);
1253 // set masked area in buffer to BLACK (pixel value 0)
1254 COLORREF prevBkCol
= ::SetBkColor((HDC
) m_hDC
, RGB(255, 255, 255));
1255 COLORREF prevCol
= ::SetTextColor((HDC
) m_hDC
, RGB(0, 0, 0));
1256 ::BitBlt(dc_buffer
, 0, 0, (int)width
, (int)height
,
1257 dc_mask
, xsrc1
, ysrc1
, SRCAND
);
1259 // set unmasked area in dest to BLACK
1260 ::SetBkColor((HDC
) m_hDC
, RGB(0, 0, 0));
1261 ::SetTextColor((HDC
) m_hDC
, RGB(255, 255, 255));
1262 ::BitBlt((HDC
) m_hDC
, xdest1
, ydest1
, (int)width
, (int)height
,
1263 dc_mask
, xsrc1
, ysrc1
, SRCAND
);
1264 ::SetBkColor((HDC
) m_hDC
, prevBkCol
); // restore colours to original values
1265 ::SetTextColor((HDC
) m_hDC
, prevCol
);
1267 // OR buffer to dest
1268 success
= (::BitBlt((HDC
) m_hDC
, xdest1
, ydest1
, (int)width
, (int)height
,
1269 dc_buffer
, 0, 0, SRCPAINT
) != 0);
1271 // tidy up temporary DCs and bitmap
1272 ::SelectObject(dc_mask
, 0);
1273 ::DeleteDC(dc_mask
);
1274 ::SelectObject(dc_buffer
, 0);
1275 ::DeleteDC(dc_buffer
);
1276 ::DeleteObject(buffer_bmap
);
1282 if (IsKindOf(CLASSINFO(wxPrinterDC
)))
1284 // If we are printing source colours are screen colours
1285 // not printer colours and so we need copy the bitmap
1287 HDC dc_src
= (HDC
) source
->m_hDC
;
1289 for (int x
= 0; x
< width
; x
++)
1291 for (int y
= 0; y
< height
; y
++)
1293 HBRUSH brush
= ::CreateSolidBrush(::GetPixel(dc_src
, x
, y
));
1294 rect
.left
= xdest1
+ x
; rect
.right
= rect
.left
+ 1;
1295 rect
.top
= ydest1
+ y
; rect
.bottom
= rect
.top
+ 1;
1296 ::FillRect((HDC
) m_hDC
, &rect
, brush
);
1297 ::DeleteObject(brush
);
1303 success
= (BitBlt((HDC
) m_hDC
, xdest1
, ydest1
, (int)width
, (int)height
, (HDC
) source
->m_hDC
,
1304 xsrc1
, ysrc1
, dwRop
) != 0);
1307 ::SetTextColor((HDC
)m_hDC
, old_textground
);
1308 ::SetBkColor((HDC
)m_hDC
, old_background
);
1313 void wxDC::GetSize(int* width
, int* height
) const
1315 long w
=::GetDeviceCaps((HDC
) m_hDC
,HORZRES
);
1316 long h
=::GetDeviceCaps((HDC
) m_hDC
,VERTRES
);
1321 void wxDC::GetSizeMM(long *width
, long *height
) const
1323 long w
=::GetDeviceCaps((HDC
) m_hDC
,HORZSIZE
);
1324 long h
=::GetDeviceCaps((HDC
) m_hDC
,VERTSIZE
);
1330 #include "xfspline.inc"
1331 #endif // USE_SPLINES
1333 void wxDC::DrawPolygon(wxList
*list
, long xoffset
, long yoffset
,int fillStyle
)
1335 int n
= list
->Number();
1336 wxPoint
*points
= new wxPoint
[n
];
1339 for(wxNode
*node
= list
->First(); node
; node
= node
->Next()) {
1340 wxPoint
*point
= (wxPoint
*)node
->Data();
1341 points
[i
].x
= point
->x
;
1342 points
[i
++].y
= point
->y
;
1344 DrawPolygon(n
, points
, xoffset
, yoffset
,fillStyle
);
1348 void wxDC::DrawLines(wxList
*list
, long xoffset
, long yoffset
)
1350 int n
= list
->Number();
1351 wxPoint
*points
= new wxPoint
[n
];
1354 for(wxNode
*node
= list
->First(); node
; node
= node
->Next()) {
1355 wxPoint
*point
= (wxPoint
*)node
->Data();
1356 points
[i
].x
= point
->x
;
1357 points
[i
++].y
= point
->y
;
1359 DrawLines(n
, points
, xoffset
, yoffset
);
1363 void wxDC::SetTextForeground(const wxColour
& colour
)
1365 m_textForegroundColour
= colour
;
1368 void wxDC::SetTextBackground(const wxColour
& colour
)
1370 m_textBackgroundColour
= colour
;
1374 // Make a 3-point spline
1375 void wxDC::DrawSpline(long x1
, long y1
, long x2
, long y2
, long x3
, long y3
)
1377 wxList
*point_list
= new wxList
;
1379 wxPoint
*point1
= new wxPoint
;
1380 point1
->x
= x1
; point1
->y
= y1
;
1381 point_list
->Append((wxObject
*)point1
);
1383 wxPoint
*point2
= new wxPoint
;
1384 point2
->x
= x2
; point2
->y
= y2
;
1385 point_list
->Append((wxObject
*)point2
);
1387 wxPoint
*point3
= new wxPoint
;
1388 point3
->x
= x3
; point3
->y
= y3
;
1389 point_list
->Append((wxObject
*)point3
);
1391 DrawSpline(point_list
);
1393 for(wxNode
*node
= point_list
->First(); node
; node
= node
->Next()) {
1394 wxPoint
*p
= (wxPoint
*)node
->Data();
1401 // For use by wxWindows only, unless custom units are required.
1402 void wxDC::SetLogicalScale(double x
, double y
)
1404 m_logicalScaleX
= x
;
1405 m_logicalScaleY
= y
;
1408 void wxDC::CalcBoundingBox(long x
, long y
)
1410 if (x
< m_minX
) m_minX
= x
;
1411 if (y
< m_minY
) m_minY
= y
;
1412 if (x
> m_maxX
) m_maxX
= x
;
1413 if (y
> m_maxY
) m_maxY
= y
;
1416 void wxDC::GetClippingBox(long *x
,long *y
,long *w
,long *h
) const
1422 *w
= (m_clipX2
- m_clipX1
) ;
1423 *h
= (m_clipY2
- m_clipY1
) ;
1426 *x
= *y
= *w
= *h
= 0 ;
1429 #if WXWIN_COMPATIBILITY
1430 void wxDC::GetTextExtent(const wxString
& string
, float *x
, float *y
,
1431 float *descent
, float *externalLeading
,
1432 wxFont
*theFont
, bool use16bit
) const
1434 long x1
, y1
, descent1
, externalLeading1
;
1435 GetTextExtent(string
, & x1
, & y1
, & descent1
, & externalLeading1
, theFont
, use16bit
);
1438 *descent
= descent1
;
1439 if (externalLeading
)
1440 *externalLeading
= externalLeading1
;