1 /////////////////////////////////////////////////////////////////////////////
2 // Name: samples/drawing/drawing.cpp
3 // Purpose: shows and tests wxDC features
4 // Author: Robert Roebling
8 // Copyright: (c) Robert Roebling
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
14 // ============================================================================
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
20 // For compilers that support precompilation, includes "wx/wx.h".
21 #include "wx/wxprec.h"
27 // for all others, include the necessary headers (this file is usually all you
28 // need because it includes almost all "standard" wxWidgets headers
33 #include "wx/colordlg.h"
35 #include "wx/artprov.h"
37 #define wxTEST_GRAPHICS 1
40 #include "wx/graphics.h"
41 #if wxUSE_GRAPHICS_CONTEXT == 0
42 #undef wxTEST_GRAPHICS
43 #define wxTEST_GRAPHICS 0
46 #undef wxUSE_GRAPHICS_CONTEXT
47 #define wxUSE_GRAPHICS_CONTEXT 0
50 // ----------------------------------------------------------------------------
52 // ----------------------------------------------------------------------------
54 // the application icon
55 #if defined(__WXGTK__) || defined(__WXMOTIF__) || defined(__WXMAC__) || defined(__WXMGL__) || defined(__WXX11__)
56 #include "mondrian.xpm"
59 // ----------------------------------------------------------------------------
61 // ----------------------------------------------------------------------------
63 // what do we show on screen (there are too many shapes to put them all on
64 // screen simultaneously)
78 #if wxUSE_GRAPHICS_CONTEXT
86 // ----------------------------------------------------------------------------
88 // ----------------------------------------------------------------------------
90 static wxBitmap
*gs_bmpNoMask
= NULL
,
91 *gs_bmpWithColMask
= NULL
,
93 *gs_bmpWithMask
= NULL
,
98 // ----------------------------------------------------------------------------
100 // ----------------------------------------------------------------------------
102 // Define a new application type, each program should derive a class from wxApp
103 class MyApp
: public wxApp
106 // override base class virtuals
107 // ----------------------------
109 // this one is called on application startup and is a good place for the app
110 // initialization (doing it here and not in the ctor allows to have an error
111 // return: if OnInit() returns false, the application terminates)
112 virtual bool OnInit();
114 virtual int OnExit() { DeleteBitmaps(); return 0; }
117 void DeleteBitmaps();
124 // Define a new frame type: this is going to be our main frame
125 class MyFrame
: public wxFrame
129 MyFrame(const wxString
& title
, const wxPoint
& pos
, const wxSize
& size
);
131 // event handlers (these functions should _not_ be virtual)
132 void OnQuit(wxCommandEvent
& event
);
133 void OnAbout(wxCommandEvent
& event
);
134 void OnClip(wxCommandEvent
& event
);
135 #if wxUSE_GRAPHICS_CONTEXT
136 void OnGraphicContext(wxCommandEvent
& event
);
138 void OnShow(wxCommandEvent
&event
);
139 void OnOption(wxCommandEvent
&event
);
142 wxColour
SelectColour();
143 #endif // wxUSE_COLOURDLG
144 void PrepareDC(wxDC
& dc
);
146 int m_backgroundMode
;
147 int m_textureBackground
;
151 int m_xLogicalOrigin
;
152 int m_yLogicalOrigin
;
153 bool m_xAxisReversed
,
155 wxColour m_colourForeground
, // these are _text_ colours
157 wxBrush m_backgroundBrush
;
161 // any class wishing to process wxWidgets events must use this macro
162 DECLARE_EVENT_TABLE()
165 // define a scrollable canvas for drawing onto
166 class MyCanvas
: public wxScrolledWindow
169 MyCanvas( MyFrame
*parent
);
171 void OnPaint(wxPaintEvent
&event
);
172 void OnMouseMove(wxMouseEvent
&event
);
174 void ToShow(ScreenToShow show
) { m_show
= show
; Refresh(); }
176 // set or remove the clipping region
177 void Clip(bool clip
) { m_clip
= clip
; Refresh(); }
178 #if wxUSE_GRAPHICS_CONTEXT
179 void UseGraphicContext(bool use
) { m_useContext
= use
; Refresh(); }
189 void DrawTestLines( int x
, int y
, int width
, wxDC
&dc
);
190 void DrawTestPoly(wxDC
& dc
);
191 void DrawTestBrushes(wxDC
& dc
);
192 void DrawText(wxDC
& dc
);
193 void DrawImages(wxDC
& dc
, DrawMode mode
);
194 void DrawWithLogicalOps(wxDC
& dc
);
195 #if wxUSE_GRAPHICS_CONTEXT
196 void DrawAlpha(wxDC
& dc
);
197 void DrawGraphics(wxGraphicsContext
* gc
);
199 void DrawRegions(wxDC
& dc
);
200 void DrawCircles(wxDC
& dc
);
201 void DrawSplines(wxDC
& dc
);
202 void DrawDefault(wxDC
& dc
);
203 void DrawGradients(wxDC
& dc
);
205 void DrawRegionsHelper(wxDC
& dc
, wxCoord x
, bool firstTime
);
211 wxBitmap m_smile_bmp
;
214 #if wxUSE_GRAPHICS_CONTEXT
218 DECLARE_EVENT_TABLE()
221 // ----------------------------------------------------------------------------
223 // ----------------------------------------------------------------------------
225 // IDs for the controls and the menu commands
229 File_Quit
= wxID_EXIT
,
230 File_About
= wxID_ABOUT
,
232 MenuShow_First
= wxID_HIGHEST
,
233 File_ShowDefault
= MenuShow_First
,
239 File_ShowMaskStretch
,
244 #if wxUSE_GRAPHICS_CONTEXT
249 MenuShow_Last
= File_ShowGradients
,
252 #if wxUSE_GRAPHICS_CONTEXT
258 MapMode_Text
= MenuOption_First
,
264 UserScale_StretchHoriz
,
265 UserScale_ShrinkHoriz
,
266 UserScale_StretchVertic
,
267 UserScale_ShrinkVertic
,
273 LogicalOrigin_MoveDown
,
274 LogicalOrigin_MoveUp
,
275 LogicalOrigin_MoveLeft
,
276 LogicalOrigin_MoveRight
,
278 LogicalOrigin_Restore
,
281 Colour_TextForeground
,
282 Colour_TextBackground
,
284 #endif // wxUSE_COLOURDLG
285 Colour_BackgroundMode
,
286 Colour_TextureBackgound
,
288 MenuOption_Last
= Colour_TextureBackgound
291 // ----------------------------------------------------------------------------
292 // event tables and other macros for wxWidgets
293 // ----------------------------------------------------------------------------
296 // Create a new application object: this macro will allow wxWidgets to create
297 // the application object during program execution (it's better than using a
298 // static object for many reasons) and also declares the accessor function
299 // wxGetApp() which will return the reference of the right type (i.e. MyApp and
303 // ============================================================================
305 // ============================================================================
307 // ----------------------------------------------------------------------------
308 // the application class
309 // ----------------------------------------------------------------------------
311 bool MyApp::LoadImages()
313 gs_bmpNoMask
= new wxBitmap
;
314 gs_bmpWithColMask
= new wxBitmap
;
315 gs_bmpMask
= new wxBitmap
;
316 gs_bmpWithMask
= new wxBitmap
;
317 gs_bmp4
= new wxBitmap
;
318 gs_bmp4_mono
= new wxBitmap
;
319 gs_bmp36
= new wxBitmap
;
322 pathList
.Add(_T("."));
323 pathList
.Add(_T(".."));
324 pathList
.Add(_T("../.."));
326 wxString path
= pathList
.FindValidPath(_T("pat4.bmp"));
330 /* 4 colour bitmap */
331 gs_bmp4
->LoadFile(path
, wxBITMAP_TYPE_BMP
);
332 /* turn into mono-bitmap */
333 gs_bmp4_mono
->LoadFile(path
, wxBITMAP_TYPE_BMP
);
334 wxMask
* mask4
= new wxMask(*gs_bmp4_mono
, *wxBLACK
);
335 gs_bmp4_mono
->SetMask(mask4
);
337 path
= pathList
.FindValidPath(_T("pat36.bmp"));
340 gs_bmp36
->LoadFile(path
, wxBITMAP_TYPE_BMP
);
341 wxMask
* mask36
= new wxMask(*gs_bmp36
, *wxBLACK
);
342 gs_bmp36
->SetMask(mask36
);
344 path
= pathList
.FindValidPath(_T("image.bmp"));
347 gs_bmpNoMask
->LoadFile(path
, wxBITMAP_TYPE_BMP
);
348 gs_bmpWithMask
->LoadFile(path
, wxBITMAP_TYPE_BMP
);
349 gs_bmpWithColMask
->LoadFile(path
, wxBITMAP_TYPE_BMP
);
351 path
= pathList
.FindValidPath(_T("mask.bmp"));
354 gs_bmpMask
->LoadFile(path
, wxBITMAP_TYPE_BMP
);
356 wxMask
*mask
= new wxMask(*gs_bmpMask
, *wxBLACK
);
357 gs_bmpWithMask
->SetMask(mask
);
359 mask
= new wxMask(*gs_bmpWithColMask
, *wxWHITE
);
360 gs_bmpWithColMask
->SetMask(mask
);
365 // `Main program' equivalent: the program execution "starts" here
368 if ( !wxApp::OnInit() )
371 // Create the main application window
372 MyFrame
*frame
= new MyFrame(_T("Drawing sample"),
373 wxPoint(50, 50), wxSize(550, 340));
375 // Show it and tell the application that it's our main window
381 wxLogError(wxT("Can't load one of the bitmap files needed ")
382 wxT("for this sample from the current or parent ")
383 wxT("directory, please copy them there."));
395 void MyApp::DeleteBitmaps()
398 delete gs_bmpWithColMask
;
400 delete gs_bmpWithMask
;
406 gs_bmpWithColMask
= NULL
;
408 gs_bmpWithMask
= NULL
;
414 // ----------------------------------------------------------------------------
416 // ----------------------------------------------------------------------------
418 // the event tables connect the wxWidgets events with the functions (event
419 // handlers) which process them.
420 BEGIN_EVENT_TABLE(MyCanvas
, wxScrolledWindow
)
421 EVT_PAINT (MyCanvas::OnPaint
)
422 EVT_MOTION (MyCanvas::OnMouseMove
)
427 MyCanvas::MyCanvas(MyFrame
*parent
)
428 : wxScrolledWindow(parent
, wxID_ANY
, wxDefaultPosition
, wxDefaultSize
,
429 wxHSCROLL
| wxVSCROLL
| wxNO_FULL_REPAINT_ON_RESIZE
)
432 m_show
= Show_Default
;
433 m_smile_bmp
= wxBitmap(smile_xpm
);
434 m_std_icon
= wxArtProvider::GetIcon(wxART_INFORMATION
);
436 #if wxUSE_GRAPHICS_CONTEXT
437 m_useContext
= false;
441 void MyCanvas::DrawTestBrushes(wxDC
& dc
)
443 static const wxCoord WIDTH
= 200;
444 static const wxCoord HEIGHT
= 80;
449 dc
.SetBrush(wxBrush(*wxGREEN
, wxSOLID
));
450 dc
.DrawRectangle(x
, y
, WIDTH
, HEIGHT
);
451 dc
.DrawText(_T("Solid green"), x
+ 10, y
+ 10);
454 dc
.SetBrush(wxBrush(*wxRED
, wxCROSSDIAG_HATCH
));
455 dc
.DrawRectangle(x
, y
, WIDTH
, HEIGHT
);
456 dc
.DrawText(_T("Hatched red"), x
+ 10, y
+ 10);
459 dc
.SetBrush(wxBrush(*gs_bmpMask
));
460 dc
.DrawRectangle(x
, y
, WIDTH
, HEIGHT
);
461 dc
.DrawText(_T("Stipple mono"), x
+ 10, y
+ 10);
464 dc
.SetBrush(wxBrush(*gs_bmpNoMask
));
465 dc
.DrawRectangle(x
, y
, WIDTH
, HEIGHT
);
466 dc
.DrawText(_T("Stipple colour"), x
+ 10, y
+ 10);
469 void MyCanvas::DrawTestPoly(wxDC
& dc
)
471 wxBrush
brushHatch(*wxRED
, wxFDIAGONAL_HATCH
);
472 dc
.SetBrush(brushHatch
);
475 star
[0] = wxPoint(100, 60);
476 star
[1] = wxPoint(60, 150);
477 star
[2] = wxPoint(160, 100);
478 star
[3] = wxPoint(40, 100);
479 star
[4] = wxPoint(140, 150);
481 dc
.DrawText(_T("You should see two (irregular) stars below, the left one ")
482 _T("hatched"), 10, 10);
483 dc
.DrawText(_T("except for the central region and the right ")
484 _T("one entirely hatched"), 10, 30);
485 dc
.DrawText(_T("The third star only has a hatched outline"), 10, 50);
487 dc
.DrawPolygon(WXSIZEOF(star
), star
, 0, 30);
488 dc
.DrawPolygon(WXSIZEOF(star
), star
, 160, 30, wxWINDING_RULE
);
491 star2
[0] = wxPoint(0, 100);
492 star2
[1] = wxPoint(-59, -81);
493 star2
[2] = wxPoint(95, 31);
494 star2
[3] = wxPoint(-95, 31);
495 star2
[4] = wxPoint(59, -81);
496 star2
[5] = wxPoint(0, 80);
497 star2
[6] = wxPoint(-47, -64);
498 star2
[7] = wxPoint(76, 24);
499 star2
[8] = wxPoint(-76, 24);
500 star2
[9] = wxPoint(47, -64);
501 int count
[2] = {5, 5};
503 dc
.DrawPolyPolygon(WXSIZEOF(count
), count
, star2
, 450, 150);
506 void MyCanvas::DrawTestLines( int x
, int y
, int width
, wxDC
&dc
)
508 dc
.SetPen( wxPen( wxT("black"), width
, wxSOLID
) );
509 dc
.SetBrush( *wxRED_BRUSH
);
510 dc
.DrawText(wxString::Format(wxT("Testing lines of width %d"), width
), x
+ 10, y
- 10);
511 dc
.DrawRectangle( x
+10, y
+10, 100, 190 );
513 dc
.DrawText(_T("Solid/dot/short dash/long dash/dot dash"), x
+ 150, y
+ 10);
514 dc
.SetPen( wxPen( wxT("black"), width
, wxSOLID
) );
515 dc
.DrawLine( x
+20, y
+20, 100, y
+20 );
516 dc
.SetPen( wxPen( wxT("black"), width
, wxDOT
) );
517 dc
.DrawLine( x
+20, y
+30, 100, y
+30 );
518 dc
.SetPen( wxPen( wxT("black"), width
, wxSHORT_DASH
) );
519 dc
.DrawLine( x
+20, y
+40, 100, y
+40 );
520 dc
.SetPen( wxPen( wxT("black"), width
, wxLONG_DASH
) );
521 dc
.DrawLine( x
+20, y
+50, 100, y
+50 );
522 dc
.SetPen( wxPen( wxT("black"), width
, wxDOT_DASH
) );
523 dc
.DrawLine( x
+20, y
+60, 100, y
+60 );
525 dc
.DrawText(_T("Misc hatches"), x
+ 150, y
+ 70);
526 dc
.SetPen( wxPen( wxT("black"), width
, wxBDIAGONAL_HATCH
) );
527 dc
.DrawLine( x
+20, y
+70, 100, y
+70 );
528 dc
.SetPen( wxPen( wxT("black"), width
, wxCROSSDIAG_HATCH
) );
529 dc
.DrawLine( x
+20, y
+80, 100, y
+80 );
530 dc
.SetPen( wxPen( wxT("black"), width
, wxFDIAGONAL_HATCH
) );
531 dc
.DrawLine( x
+20, y
+90, 100, y
+90 );
532 dc
.SetPen( wxPen( wxT("black"), width
, wxCROSS_HATCH
) );
533 dc
.DrawLine( x
+20, y
+100, 100, y
+100 );
534 dc
.SetPen( wxPen( wxT("black"), width
, wxHORIZONTAL_HATCH
) );
535 dc
.DrawLine( x
+20, y
+110, 100, y
+110 );
536 dc
.SetPen( wxPen( wxT("black"), width
, wxVERTICAL_HATCH
) );
537 dc
.DrawLine( x
+20, y
+120, 100, y
+120 );
539 dc
.DrawText(_T("User dash"), x
+ 150, y
+ 140);
540 wxPen
ud( wxT("black"), width
, wxUSER_DASH
);
542 dash1
[0] = 8; // Long dash <---------+
543 dash1
[1] = 2; // Short gap |
544 dash1
[2] = 3; // Short dash |
545 dash1
[3] = 2; // Short gap |
546 dash1
[4] = 3; // Short dash |
547 dash1
[5] = 2; // Short gap and repeat +
548 ud
.SetDashes( 6, dash1
);
550 dc
.DrawLine( x
+20, y
+140, 100, y
+140 );
551 dash1
[0] = 5; // Make first dash shorter
552 ud
.SetDashes( 6, dash1
);
554 dc
.DrawLine( x
+20, y
+150, 100, y
+150 );
555 dash1
[2] = 5; // Make second dash longer
556 ud
.SetDashes( 6, dash1
);
558 dc
.DrawLine( x
+20, y
+160, 100, y
+160 );
559 dash1
[4] = 5; // Make third dash longer
560 ud
.SetDashes( 6, dash1
);
562 dc
.DrawLine( x
+20, y
+170, 100, y
+170 );
565 void MyCanvas::DrawDefault(wxDC
& dc
)
568 dc
.DrawCircle(0, 0, 10);
570 #if !defined(wxMAC_USE_CORE_GRAPHICS) || !wxMAC_USE_CORE_GRAPHICS
571 // GetPixel and FloodFill not supported by Mac OS X CoreGraphics
572 // (FloodFill uses Blit from a non-wxMemoryDC)
573 //flood fill using brush, starting at 1,1 and replacing whatever colour we find there
574 dc
.SetBrush(wxBrush(wxColour(128,128,0), wxSOLID
));
577 dc
.GetPixel(1,1, &tmpColour
);
578 dc
.FloodFill(1,1, tmpColour
, wxFLOOD_SURFACE
);
581 dc
.DrawCheckMark(5, 80, 15, 15);
582 dc
.DrawCheckMark(25, 80, 30, 30);
583 dc
.DrawCheckMark(60, 80, 60, 60);
585 // this is the test for "blitting bitmap into DC damages selected brush" bug
586 wxCoord rectSize
= m_std_icon
.GetWidth() + 10;
588 dc
.SetPen(*wxTRANSPARENT_PEN
);
589 dc
.SetBrush( *wxGREEN_BRUSH
);
590 dc
.DrawRectangle(x
, 10, rectSize
, rectSize
);
591 dc
.DrawBitmap(m_std_icon
, x
+ 5, 15, true);
593 dc
.DrawRectangle(x
, 10, rectSize
, rectSize
);
594 dc
.DrawIcon(m_std_icon
, x
+ 5, 15);
596 dc
.DrawRectangle(x
, 10, rectSize
, rectSize
);
598 // test for "transparent" bitmap drawing (it intersects with the last
600 //dc.SetBrush( *wxTRANSPARENT_BRUSH );
602 if (m_smile_bmp
.Ok())
603 dc
.DrawBitmap(m_smile_bmp
, x
+ rectSize
- 20, rectSize
- 10, true);
605 dc
.SetBrush( *wxBLACK_BRUSH
);
606 dc
.DrawRectangle( 0, 160, 1000, 300 );
609 wxBitmap
bitmap(20,70);
611 memdc
.SelectObject( bitmap
);
612 memdc
.SetBrush( *wxBLACK_BRUSH
);
613 memdc
.SetPen( *wxWHITE_PEN
);
614 memdc
.DrawRectangle(0,0,20,70);
615 memdc
.DrawLine( 10,0,10,70 );
618 wxPen pen
= *wxRED_PEN
;
620 memdc
.DrawLine( 10, 5,10, 5 );
621 memdc
.DrawLine( 10,10,11,10 );
622 memdc
.DrawLine( 10,15,12,15 );
623 memdc
.DrawLine( 10,20,13,20 );
626 memdc.SetPen(*wxRED_PEN);
627 memdc.DrawLine( 12, 5,12, 5 );
628 memdc.DrawLine( 12,10,13,10 );
629 memdc.DrawLine( 12,15,14,15 );
630 memdc.DrawLine( 12,20,15,20 );
634 memdc
.DrawLine( 10,25,10,25 );
635 memdc
.DrawLine( 10,30, 9,30 );
636 memdc
.DrawLine( 10,35, 8,35 );
637 memdc
.DrawLine( 10,40, 7,40 );
640 dc
.SetPen(*wxWHITE_PEN
);
641 memdc
.SetLogicalFunction( wxINVERT
);
642 memdc
.SetPen( *wxWHITE_PEN
);
643 memdc
.DrawLine( 10,50,10,50 );
644 memdc
.DrawLine( 10,55,11,55 );
645 memdc
.DrawLine( 10,60,12,60 );
646 memdc
.DrawLine( 10,65,13,65 );
648 memdc
.DrawLine( 12,50,12,50 );
649 memdc
.DrawLine( 12,55,13,55 );
650 memdc
.DrawLine( 12,60,14,60 );
651 memdc
.DrawLine( 12,65,15,65 );
653 memdc
.SelectObject( wxNullBitmap
);
654 dc
.DrawBitmap( bitmap
, 10, 170 );
655 wxImage image
= bitmap
.ConvertToImage();
656 image
.Rescale( 60,210 );
657 bitmap
= wxBitmap(image
);
658 dc
.DrawBitmap( bitmap
, 50, 170 );
660 // test the rectangle outline drawing - there should be one pixel between
661 // the rect and the lines
662 dc
.SetPen(*wxWHITE_PEN
);
663 dc
.SetBrush( *wxTRANSPARENT_BRUSH
);
664 dc
.DrawRectangle(150, 170, 49, 29);
665 dc
.DrawRectangle(200, 170, 49, 29);
666 dc
.SetPen(*wxWHITE_PEN
);
667 dc
.DrawLine(250, 210, 250, 170);
668 dc
.DrawLine(260, 200, 150, 200);
670 // test the rectangle filled drawing - there should be one pixel between
671 // the rect and the lines
672 dc
.SetPen(*wxTRANSPARENT_PEN
);
673 dc
.SetBrush( *wxWHITE_BRUSH
);
674 dc
.DrawRectangle(300, 170, 49, 29);
675 dc
.DrawRectangle(350, 170, 49, 29);
676 dc
.SetPen(*wxWHITE_PEN
);
677 dc
.DrawLine(400, 170, 400, 210);
678 dc
.DrawLine(300, 200, 410, 200);
680 // a few more tests of this kind
681 dc
.SetPen(*wxRED_PEN
);
682 dc
.SetBrush( *wxWHITE_BRUSH
);
683 dc
.DrawRectangle(300, 220, 1, 1);
684 dc
.DrawRectangle(310, 220, 2, 2);
685 dc
.DrawRectangle(320, 220, 3, 3);
686 dc
.DrawRectangle(330, 220, 4, 4);
688 dc
.SetPen(*wxTRANSPARENT_PEN
);
689 dc
.SetBrush( *wxWHITE_BRUSH
);
690 dc
.DrawRectangle(300, 230, 1, 1);
691 dc
.DrawRectangle(310, 230, 2, 2);
692 dc
.DrawRectangle(320, 230, 3, 3);
693 dc
.DrawRectangle(330, 230, 4, 4);
695 // and now for filled rect with outline
696 dc
.SetPen(*wxRED_PEN
);
697 dc
.SetBrush( *wxWHITE_BRUSH
);
698 dc
.DrawRectangle(500, 170, 49, 29);
699 dc
.DrawRectangle(550, 170, 49, 29);
700 dc
.SetPen(*wxWHITE_PEN
);
701 dc
.DrawLine(600, 170, 600, 210);
702 dc
.DrawLine(500, 200, 610, 200);
704 // test the rectangle outline drawing - there should be one pixel between
705 // the rect and the lines
706 dc
.SetPen(*wxWHITE_PEN
);
707 dc
.SetBrush( *wxTRANSPARENT_BRUSH
);
708 dc
.DrawRoundedRectangle(150, 270, 49, 29, 6);
709 dc
.DrawRoundedRectangle(200, 270, 49, 29, 6);
710 dc
.SetPen(*wxWHITE_PEN
);
711 dc
.DrawLine(250, 270, 250, 310);
712 dc
.DrawLine(150, 300, 260, 300);
714 // test the rectangle filled drawing - there should be one pixel between
715 // the rect and the lines
716 dc
.SetPen(*wxTRANSPARENT_PEN
);
717 dc
.SetBrush( *wxWHITE_BRUSH
);
718 dc
.DrawRoundedRectangle(300, 270, 49, 29, 6);
719 dc
.DrawRoundedRectangle(350, 270, 49, 29, 6);
720 dc
.SetPen(*wxWHITE_PEN
);
721 dc
.DrawLine(400, 270, 400, 310);
722 dc
.DrawLine(300, 300, 410, 300);
724 // Added by JACS to demonstrate bizarre behaviour.
725 // With a size of 70, we get a missing red RHS,
726 // and the height is too small, so we get yellow
727 // showing. With a size of 40, it draws as expected:
728 // it just shows a white rectangle with red outline.
730 int totalHeight
= 70;
731 wxBitmap
bitmap2(totalWidth
, totalHeight
);
734 memdc2
.SelectObject(bitmap2
);
736 wxColour
clr(255, 255, 0);
737 wxBrush
yellowBrush(clr
, wxSOLID
);
738 memdc2
.SetBackground(yellowBrush
);
741 wxPen
yellowPen(clr
, 1, wxSOLID
);
743 // Now draw a white rectangle with red outline. It should
744 // entirely eclipse the yellow background.
745 memdc2
.SetPen(*wxRED_PEN
);
746 memdc2
.SetBrush(*wxWHITE_BRUSH
);
748 memdc2
.DrawRectangle(0, 0, totalWidth
, totalHeight
);
750 memdc2
.SetPen(wxNullPen
);
751 memdc2
.SetBrush(wxNullBrush
);
752 memdc2
.SelectObject(wxNullBitmap
);
754 dc
.DrawBitmap(bitmap2
, 500, 270);
756 // Repeat, but draw directly on dc
757 // Draw a yellow rectangle filling the bitmap
759 x
= 600; int y
= 270;
760 dc
.SetPen(yellowPen
);
761 dc
.SetBrush(yellowBrush
);
762 dc
.DrawRectangle(x
, y
, totalWidth
, totalHeight
);
764 // Now draw a white rectangle with red outline. It should
765 // entirely eclipse the yellow background.
766 dc
.SetPen(*wxRED_PEN
);
767 dc
.SetBrush(*wxWHITE_BRUSH
);
769 dc
.DrawRectangle(x
, y
, totalWidth
, totalHeight
);
772 void MyCanvas::DrawText(wxDC
& dc
)
774 // set underlined font for testing
775 dc
.SetFont( wxFont(12, wxMODERN
, wxNORMAL
, wxNORMAL
, true) );
776 dc
.DrawText( _T("This is text"), 110, 10 );
777 dc
.DrawRotatedText( _T("That is text"), 20, 10, -45 );
779 // use wxSWISS_FONT and not wxNORMAL_FONT as the latter can't be rotated
780 // under Win9x (it is not TrueType)
781 dc
.SetFont( *wxSWISS_FONT
);
784 dc
.SetBackgroundMode(wxTRANSPARENT
);
786 for ( int n
= -180; n
< 180; n
+= 30 )
788 text
.Printf(wxT(" %d rotated text"), n
);
789 dc
.DrawRotatedText(text
, 400, 400, n
);
792 dc
.SetFont( wxFont( 18, wxSWISS
, wxNORMAL
, wxNORMAL
) );
794 dc
.DrawText( _T("This is Swiss 18pt text."), 110, 40 );
799 dc
.GetTextExtent( _T("This is Swiss 18pt text."), &length
, &height
, &descent
);
800 text
.Printf( wxT("Dimensions are length %ld, height %ld, descent %ld"), length
, height
, descent
);
801 dc
.DrawText( text
, 110, 80 );
803 text
.Printf( wxT("CharHeight() returns: %d"), dc
.GetCharHeight() );
804 dc
.DrawText( text
, 110, 120 );
806 dc
.DrawRectangle( 100, 40, 4, height
);
808 // test the logical function effect
810 dc
.SetLogicalFunction(wxINVERT
);
811 dc
.DrawText( _T("There should be no text below"), 110, 150 );
812 dc
.DrawRectangle( 110, y
, 100, height
);
814 // twice drawn inverted should result in invisible
816 dc
.DrawText( _T("Invisible text"), 110, y
);
817 dc
.DrawRectangle( 110, y
, 100, height
);
818 dc
.DrawText( _T("Invisible text"), 110, y
);
819 dc
.DrawRectangle( 110, y
, 100, height
);
820 dc
.SetLogicalFunction(wxCOPY
);
823 dc
.DrawRectangle( 110, y
, 100, height
);
824 dc
.DrawText( _T("Visible text"), 110, y
);
831 } rasterOperations
[] =
833 { wxT("wxAND"), wxAND
},
834 { wxT("wxAND_INVERT"), wxAND_INVERT
},
835 { wxT("wxAND_REVERSE"), wxAND_REVERSE
},
836 { wxT("wxCLEAR"), wxCLEAR
},
837 { wxT("wxCOPY"), wxCOPY
},
838 { wxT("wxEQUIV"), wxEQUIV
},
839 { wxT("wxINVERT"), wxINVERT
},
840 { wxT("wxNAND"), wxNAND
},
841 { wxT("wxNO_OP"), wxNO_OP
},
842 { wxT("wxOR"), wxOR
},
843 { wxT("wxOR_INVERT"), wxOR_INVERT
},
844 { wxT("wxOR_REVERSE"), wxOR_REVERSE
},
845 { wxT("wxSET"), wxSET
},
846 { wxT("wxSRC_INVERT"), wxSRC_INVERT
},
847 { wxT("wxXOR"), wxXOR
},
850 void MyCanvas::DrawImages(wxDC
& dc
, DrawMode mode
)
852 dc
.DrawText(_T("original image"), 0, 0);
853 dc
.DrawBitmap(*gs_bmpNoMask
, 0, 20, 0);
854 dc
.DrawText(_T("with colour mask"), 0, 100);
855 dc
.DrawBitmap(*gs_bmpWithColMask
, 0, 120, true);
856 dc
.DrawText(_T("the mask image"), 0, 200);
857 dc
.DrawBitmap(*gs_bmpMask
, 0, 220, 0);
858 dc
.DrawText(_T("masked image"), 0, 300);
859 dc
.DrawBitmap(*gs_bmpWithMask
, 0, 320, true);
861 int cx
= gs_bmpWithColMask
->GetWidth(),
862 cy
= gs_bmpWithColMask
->GetHeight();
865 for ( size_t n
= 0; n
< WXSIZEOF(rasterOperations
); n
++ )
867 wxCoord x
= 120 + 150*(n%4
),
870 dc
.DrawText(rasterOperations
[n
].name
, x
, y
- 20);
871 memDC
.SelectObject(*gs_bmpWithColMask
);
872 if ( mode
== Draw_Stretch
)
874 dc
.StretchBlit(x
, y
, cx
, cy
, &memDC
, 0, 0, cx
/2, cy
/2,
875 rasterOperations
[n
].rop
, true);
879 dc
.Blit(x
, y
, cx
, cy
, &memDC
, 0, 0, rasterOperations
[n
].rop
, true);
884 void MyCanvas::DrawWithLogicalOps(wxDC
& dc
)
886 static const wxCoord w
= 60;
887 static const wxCoord h
= 60;
889 // reuse the text colour here
890 dc
.SetPen(wxPen(m_owner
->m_colourForeground
, 1, wxSOLID
));
891 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
894 for ( n
= 0; n
< WXSIZEOF(rasterOperations
); n
++ )
896 wxCoord x
= 20 + 150*(n%4
),
899 dc
.DrawText(rasterOperations
[n
].name
, x
, y
- 20);
900 dc
.SetLogicalFunction(rasterOperations
[n
].rop
);
901 dc
.DrawRectangle(x
, y
, w
, h
);
902 dc
.DrawLine(x
, y
, x
+ w
, y
+ h
);
903 dc
.DrawLine(x
+ w
, y
, x
, y
+ h
);
906 // now some filled rectangles
907 dc
.SetBrush(wxBrush(m_owner
->m_colourForeground
, wxSOLID
));
909 for ( n
= 0; n
< WXSIZEOF(rasterOperations
); n
++ )
911 wxCoord x
= 20 + 150*(n%4
),
914 dc
.DrawText(rasterOperations
[n
].name
, x
, y
- 20);
915 dc
.SetLogicalFunction(rasterOperations
[n
].rop
);
916 dc
.DrawRectangle(x
, y
, w
, h
);
920 #if wxUSE_GRAPHICS_CONTEXT
922 void MyCanvas::DrawAlpha(wxDC
& no_dc
)
924 void MyCanvas::DrawAlpha(wxDC
& dc
)
932 wxDouble margin
= 20 ;
933 wxDouble width
= 180 ;
934 wxDouble radius
= 30 ;
936 dc
.SetPen( wxPen( wxColour( 128, 0, 0, 255 ),12, wxSOLID
));
937 dc
.SetBrush( wxBrush( wxColour( 255, 0, 0, 255),wxSOLID
));
939 wxRect
r(margin
,margin
+width
*0.66,width
,width
) ;
941 dc
.DrawRoundedRectangle( r
.x
, r
.y
, r
.width
, r
.width
, radius
) ;
943 dc
.SetPen( wxPen( wxColour( 0, 0, 128, 255 ),12, wxSOLID
));
944 dc
.SetBrush( wxBrush( wxColour( 0, 0, 255, 255),wxSOLID
));
946 r
.Offset( width
* 0.8 , - width
* 0.66 ) ;
948 dc
.DrawRoundedRectangle( r
.x
, r
.y
, r
.width
, r
.width
, radius
) ;
950 dc
.SetPen( wxPen( wxColour( 128, 128, 0, 255 ),12, wxSOLID
));
951 dc
.SetBrush( wxBrush( wxColour( 192, 192, 0, 255),wxSOLID
));
953 r
.Offset( width
* 0.8 , width
*0.5 ) ;
955 dc
.DrawRoundedRectangle( r
.x
, r
.y
, r
.width
, r
.width
, radius
) ;
957 dc
.SetPen( *wxTRANSPARENT_PEN
) ;
958 dc
.SetBrush( wxBrush( wxColour(255,255,128,128) ) );
959 dc
.DrawRoundedRectangle( 0 , margin
+ width
/ 2 , width
* 3 , 100 , radius
) ;
961 dc
.SetTextForeground( wxColour(255,255,0,128) );
962 dc
.SetFont( wxFont( 40, wxFONTFAMILY_SWISS
, wxFONTSTYLE_ITALIC
, wxFONTWEIGHT_NORMAL
) );
963 dc
.DrawText( wxT("Hello!"), 120, 80 );
968 #if wxUSE_GRAPHICS_CONTEXT
970 const int BASE
= 80.0;
971 const int BASE2
= BASE
/2;
972 const int BASE4
= BASE
/4;
974 static inline double DegToRad(double deg
) { return (deg
* M_PI
) / 180.0; }
977 // modeled along Robin Dunn's GraphicsContext.py sample
979 void MyCanvas::DrawGraphics(wxGraphicsContext
* gc
)
981 wxFont font
= wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT
);
982 gc
->SetFont(font
,*wxBLACK
);
984 // make a path that contains a circle and some lines, centered at 0,0
985 wxGraphicsPath path
= gc
->CreatePath() ;
986 path
.AddCircle( 0, 0, BASE2
);
987 path
.MoveToPoint(0, -BASE2
);
988 path
.AddLineToPoint(0, BASE2
);
989 path
.MoveToPoint(-BASE2
, 0);
990 path
.AddLineToPoint(BASE2
, 0);
992 path
.AddRectangle(-BASE4
, -BASE4
/2, BASE2
, BASE4
);
994 // Now use that path to demonstrate various capbilites of the grpahics context
995 gc
->PushState(); // save current translation/scale/other state
996 gc
->Translate(60, 75); // reposition the context origin
998 gc
->SetPen(wxPen("navy", 1));
999 gc
->SetBrush(wxBrush("pink"));
1001 for( int i
= 0 ; i
< 3 ; ++i
)
1007 label
= "StrokePath";
1017 gc
->GetTextExtent(label
, &w
, &h
, NULL
, NULL
);
1018 gc
->DrawText(label
, -w
/2, -BASE2
-h
-4);
1022 gc
->StrokePath(path
);
1031 gc
->Translate(2*BASE
, 0);
1034 gc
->PopState(); // restore saved state
1035 gc
->PushState(); // save it again
1036 gc
->Translate(60, 200); // offset to the lower part of the window
1038 gc
->DrawText("Scale", 0, -BASE2
);
1039 gc
->Translate(0, 20);
1041 gc
->SetBrush(wxBrush(wxColour(178, 34, 34, 128)));// 128 == half transparent
1042 for( int i
= 0 ; i
< 8 ; ++i
)
1044 gc
->Scale(1.08, 1.08); // increase scale by 8%
1049 gc
->PopState(); // restore saved state
1050 gc
->PushState(); // save it again
1051 gc
->Translate(400, 200);
1053 gc
->DrawText("Rotate", 0, -BASE2
);
1055 // Move the origin over to the next location
1056 gc
->Translate(0, 75);
1058 // draw our path again, rotating it about the central point,
1059 // and changing colors as we go
1060 for ( int angle
= 0 ; angle
< 360 ; angle
+= 30 )
1062 gc
->PushState(); // save this new current state so we can
1063 // pop back to it at the end of the loop
1064 wxImage::RGBValue val
= wxImage::HSVtoRGB(wxImage::HSVValue(float(angle
)/360, 1, 1));
1065 gc
->SetBrush(wxBrush(wxColour(val
.red
, val
.green
, val
.blue
, 64)));
1066 gc
->SetPen(wxPen(wxColour(val
.red
, val
.green
, val
.blue
, 128)));
1068 // use translate to artfully reposition each drawn path
1069 gc
->Translate(1.5 * BASE2
* cos(DegToRad(angle
)),
1070 1.5 * BASE2
* sin(DegToRad(angle
)));
1072 // use Rotate to rotate the path
1073 gc
->Rotate(DegToRad(angle
));
1083 void MyCanvas::DrawCircles(wxDC
& dc
)
1089 dc
.SetPen( *wxRED_PEN
);
1090 dc
.SetBrush( *wxGREEN_BRUSH
);
1092 dc
.DrawText(_T("Some circles"), 0, y
);
1093 dc
.DrawCircle(x
, y
, r
);
1094 dc
.DrawCircle(x
+ 2*r
, y
, r
);
1095 dc
.DrawCircle(x
+ 4*r
, y
, r
);
1098 dc
.DrawText(_T("And ellipses"), 0, y
);
1099 dc
.DrawEllipse(x
- r
, y
, 2*r
, r
);
1100 dc
.DrawEllipse(x
+ r
, y
, 2*r
, r
);
1101 dc
.DrawEllipse(x
+ 3*r
, y
, 2*r
, r
);
1104 dc
.DrawText(_T("And arcs"), 0, y
);
1105 dc
.DrawArc(x
- r
, y
, x
+ r
, y
, x
, y
);
1106 dc
.DrawArc(x
+ 4*r
, y
, x
+ 2*r
, y
, x
+ 3*r
, y
);
1107 dc
.DrawArc(x
+ 5*r
, y
, x
+ 5*r
, y
, x
+ 6*r
, y
);
1110 dc
.DrawEllipticArc(x
- r
, y
, 2*r
, r
, 0, 90);
1111 dc
.DrawEllipticArc(x
+ r
, y
, 2*r
, r
, 90, 180);
1112 dc
.DrawEllipticArc(x
+ 3*r
, y
, 2*r
, r
, 180, 270);
1113 dc
.DrawEllipticArc(x
+ 5*r
, y
, 2*r
, r
, 270, 360);
1115 // same as above, just transparent brush
1117 dc
.SetPen( *wxRED_PEN
);
1118 dc
.SetBrush( *wxTRANSPARENT_BRUSH
);
1121 dc
.DrawText(_T("Some circles"), 0, y
);
1122 dc
.DrawCircle(x
, y
, r
);
1123 dc
.DrawCircle(x
+ 2*r
, y
, r
);
1124 dc
.DrawCircle(x
+ 4*r
, y
, r
);
1127 dc
.DrawText(_T("And ellipses"), 0, y
);
1128 dc
.DrawEllipse(x
- r
, y
, 2*r
, r
);
1129 dc
.DrawEllipse(x
+ r
, y
, 2*r
, r
);
1130 dc
.DrawEllipse(x
+ 3*r
, y
, 2*r
, r
);
1133 dc
.DrawText(_T("And arcs"), 0, y
);
1134 dc
.DrawArc(x
- r
, y
, x
+ r
, y
, x
, y
);
1135 dc
.DrawArc(x
+ 4*r
, y
, x
+ 2*r
, y
, x
+ 3*r
, y
);
1136 dc
.DrawArc(x
+ 5*r
, y
, x
+ 5*r
, y
, x
+ 6*r
, y
);
1139 dc
.DrawEllipticArc(x
- r
, y
, 2*r
, r
, 0, 90);
1140 dc
.DrawEllipticArc(x
+ r
, y
, 2*r
, r
, 90, 180);
1141 dc
.DrawEllipticArc(x
+ 3*r
, y
, 2*r
, r
, 180, 270);
1142 dc
.DrawEllipticArc(x
+ 5*r
, y
, 2*r
, r
, 270, 360);
1146 void MyCanvas::DrawSplines(wxDC
& dc
)
1149 dc
.DrawText(_T("Some splines"), 10, 5);
1151 // values are hardcoded rather than randomly generated
1152 // so the output can be compared between native
1153 // implementations on platforms with different random
1157 const wxPoint
center( R
+ 20, R
+ 20 );
1158 const int angles
[7] = { 0, 10, 33, 77, 13, 145, 90 };
1159 const int radii
[5] = { 100 , 59, 85, 33, 90 };
1163 // background spline calculation
1164 unsigned int radius_pos
= 0;
1165 unsigned int angle_pos
= 0;
1167 for ( int i
= 0; i
< n
; i
++ )
1169 angle
+= angles
[ angle_pos
];
1170 int r
= R
* radii
[ radius_pos
] / 100;
1171 pts
[ i
].x
= center
.x
+ (wxCoord
)( r
* cos( M_PI
* angle
/ 180.0) );
1172 pts
[ i
].y
= center
.y
+ (wxCoord
)( r
* sin( M_PI
* angle
/ 180.0) );
1175 if ( angle_pos
>= WXSIZEOF(angles
) ) angle_pos
= 0;
1178 if ( radius_pos
>= WXSIZEOF(radii
) ) radius_pos
= 0;
1181 // background spline drawing
1182 dc
.SetPen(*wxRED_PEN
);
1183 dc
.DrawSpline(WXSIZEOF(pts
), pts
);
1185 // less detailed spline calculation
1186 wxPoint letters
[4][5];
1188 letters
[0][0] = wxPoint( 0,1); // O O
1189 letters
[0][1] = wxPoint( 1,3); // * *
1190 letters
[0][2] = wxPoint( 2,2); // * O *
1191 letters
[0][3] = wxPoint( 3,3); // * * * *
1192 letters
[0][4] = wxPoint( 4,1); // O O
1194 letters
[1][0] = wxPoint( 5,1); // O*O
1195 letters
[1][1] = wxPoint( 6,1); // *
1196 letters
[1][2] = wxPoint( 7,2); // O
1197 letters
[1][3] = wxPoint( 8,3); // *
1198 letters
[1][4] = wxPoint( 9,3); // O*O
1200 letters
[2][0] = wxPoint( 5,3); // O*O
1201 letters
[2][1] = wxPoint( 6,3); // *
1202 letters
[2][2] = wxPoint( 7,2); // O
1203 letters
[2][3] = wxPoint( 8,1); // *
1204 letters
[2][4] = wxPoint( 9,1); // O*O
1206 letters
[3][0] = wxPoint(10,0); // O O
1207 letters
[3][1] = wxPoint(11,3); // * *
1208 letters
[3][2] = wxPoint(12,1); // * O *
1209 letters
[3][3] = wxPoint(13,3); // * * * *
1210 letters
[3][4] = wxPoint(14,0); // O O
1212 const int dx
= 2 * R
/ letters
[3][4].x
;
1213 const int h
[4] = { -R
/2, 0, R
/4, R
/2 };
1215 for ( int m
= 0; m
< 4; m
++ )
1217 for ( int n
= 0; n
< 5; n
++ )
1219 letters
[m
][n
].x
= center
.x
- R
+ letters
[m
][n
].x
* dx
;
1220 letters
[m
][n
].y
= center
.y
+ h
[ letters
[m
][n
].y
];
1223 dc
.SetPen( wxPen( wxT("blue"), 1, wxDOT
) );
1224 dc
.DrawLines(5, letters
[m
]);
1225 dc
.SetPen( wxPen( wxT("black"), 4, wxSOLID
) );
1226 dc
.DrawSpline(5, letters
[m
]);
1230 dc
.DrawText(_T("Splines not supported."), 10, 5);
1234 void MyCanvas::DrawGradients(wxDC
& dc
)
1236 static const int TEXT_HEIGHT
= 15;
1239 wxRect
r(10, 10, 50, 50);
1240 dc
.DrawText(_T("wxRIGHT"), r
.x
, r
.y
);
1241 r
.Offset(0, TEXT_HEIGHT
);
1242 dc
.GradientFillLinear(r
, *wxWHITE
, *wxBLUE
, wxRIGHT
);
1244 r
.Offset(0, r
.height
+ 10);
1245 dc
.DrawText(_T("wxLEFT"), r
.x
, r
.y
);
1246 r
.Offset(0, TEXT_HEIGHT
);
1247 dc
.GradientFillLinear(r
, *wxWHITE
, *wxBLUE
, wxLEFT
);
1249 r
.Offset(0, r
.height
+ 10);
1250 dc
.DrawText(_T("wxDOWN"), r
.x
, r
.y
);
1251 r
.Offset(0, TEXT_HEIGHT
);
1252 dc
.GradientFillLinear(r
, *wxWHITE
, *wxBLUE
, wxDOWN
);
1254 r
.Offset(0, r
.height
+ 10);
1255 dc
.DrawText(_T("wxUP"), r
.x
, r
.y
);
1256 r
.Offset(0, TEXT_HEIGHT
);
1257 dc
.GradientFillLinear(r
, *wxWHITE
, *wxBLUE
, wxUP
);
1261 r
= wxRect(200, 10, 50, 50);
1262 dc
.DrawText(_T("Blue inside"), r
.x
, r
.y
);
1263 r
.Offset(0, TEXT_HEIGHT
);
1264 dc
.GradientFillConcentric(r
, *wxBLUE
, *wxWHITE
);
1266 r
.Offset(0, r
.height
+ 10);
1267 dc
.DrawText(_T("White inside"), r
.x
, r
.y
);
1268 r
.Offset(0, TEXT_HEIGHT
);
1269 dc
.GradientFillConcentric(r
, *wxWHITE
, *wxBLUE
);
1271 r
.Offset(0, r
.height
+ 10);
1272 dc
.DrawText(_T("Blue in top left corner"), r
.x
, r
.y
);
1273 r
.Offset(0, TEXT_HEIGHT
);
1274 dc
.GradientFillConcentric(r
, *wxBLUE
, *wxWHITE
, wxPoint(0, 0));
1276 r
.Offset(0, r
.height
+ 10);
1277 dc
.DrawText(_T("Blue in bottom right corner"), r
.x
, r
.y
);
1278 r
.Offset(0, TEXT_HEIGHT
);
1279 dc
.GradientFillConcentric(r
, *wxBLUE
, *wxWHITE
, wxPoint(r
.width
, r
.height
));
1281 // check that the area filled by the gradient is exactly the interior of
1285 dc
.DrawText("The interior should be filled but", r
.x
, r
.y
);
1287 dc
.DrawText(" the red border should remain visible:", r
.x
, r
.y
);
1298 dc
.SetPen(wxPen(wxColour(255, 0, 0)));
1299 dc
.DrawRectangle(r
);
1301 dc
.GradientFillLinear(r
, wxColour(0,255,0), wxColour(0,0,0), wxNORTH
);
1302 dc
.DrawRectangle(r2
);
1304 dc
.GradientFillLinear(r2
, wxColour(0,0,0), wxColour(0,255,0), wxSOUTH
);
1305 dc
.DrawRectangle(r3
);
1307 dc
.GradientFillLinear(r3
, wxColour(0,255,0), wxColour(0,0,0), wxEAST
);
1308 dc
.DrawRectangle(r4
);
1310 dc
.GradientFillLinear(r4
, wxColour(0,0,0), wxColour(0,255,0), wxWEST
);
1313 void MyCanvas::DrawRegions(wxDC
& dc
)
1315 dc
.DrawText(_T("You should see a red rect partly covered by a cyan one ")
1316 _T("on the left"), 10, 5);
1317 dc
.DrawText(_T("and 5 smileys from which 4 are partially clipped on the right"),
1318 10, 5 + dc
.GetCharHeight());
1319 dc
.DrawText(_T("The second copy should be identical but right part of it ")
1320 _T("should be offset by 10 pixels."),
1321 10, 5 + 2*dc
.GetCharHeight());
1323 DrawRegionsHelper(dc
, 10, true);
1324 DrawRegionsHelper(dc
, 350, false);
1327 void MyCanvas::DrawRegionsHelper(wxDC
& dc
, wxCoord x
, bool firstTime
)
1331 dc
.DestroyClippingRegion();
1332 dc
.SetBrush( *wxWHITE_BRUSH
);
1333 dc
.SetPen( *wxTRANSPARENT_PEN
);
1334 dc
.DrawRectangle( x
, y
, 310, 310 );
1336 dc
.SetClippingRegion( x
+ 10, y
+ 10, 100, 270 );
1338 dc
.SetBrush( *wxRED_BRUSH
);
1339 dc
.DrawRectangle( x
, y
, 310, 310 );
1341 dc
.SetClippingRegion( x
+ 10, y
+ 10, 100, 100 );
1343 dc
.SetBrush( *wxCYAN_BRUSH
);
1344 dc
.DrawRectangle( x
, y
, 310, 310 );
1346 dc
.DestroyClippingRegion();
1348 wxRegion
region(x
+ 110, y
+ 20, 100, 270);
1349 #if !defined(__WXMOTIF__) && !defined(__WXMAC__)
1351 region
.Offset(10, 10);
1353 dc
.SetClippingRegion(region
);
1355 dc
.SetBrush( *wxGREY_BRUSH
);
1356 dc
.DrawRectangle( x
, y
, 310, 310 );
1358 if (m_smile_bmp
.Ok())
1360 dc
.DrawBitmap( m_smile_bmp
, x
+ 150, y
+ 150, true );
1361 dc
.DrawBitmap( m_smile_bmp
, x
+ 130, y
+ 10, true );
1362 dc
.DrawBitmap( m_smile_bmp
, x
+ 130, y
+ 280, true );
1363 dc
.DrawBitmap( m_smile_bmp
, x
+ 100, y
+ 70, true );
1364 dc
.DrawBitmap( m_smile_bmp
, x
+ 200, y
+ 70, true );
1368 void MyCanvas::OnPaint(wxPaintEvent
&WXUNUSED(event
))
1370 wxPaintDC
pdc(this);
1372 #if wxUSE_GRAPHICS_CONTEXT
1374 wxDC
&dc
= m_useContext
? (wxDC
&) gdc
: (wxDC
&) pdc
;
1381 m_owner
->PrepareDC(dc
);
1383 dc
.SetBackgroundMode( m_owner
->m_backgroundMode
);
1384 if ( m_owner
->m_backgroundBrush
.Ok() )
1385 dc
.SetBackground( m_owner
->m_backgroundBrush
);
1386 if ( m_owner
->m_colourForeground
.Ok() )
1387 dc
.SetTextForeground( m_owner
->m_colourForeground
);
1388 if ( m_owner
->m_colourBackground
.Ok() )
1389 dc
.SetTextBackground( m_owner
->m_colourBackground
);
1391 if ( m_owner
->m_textureBackground
) {
1392 if ( ! m_owner
->m_backgroundBrush
.Ok() ) {
1393 wxColour
clr(0,128,0);
1394 wxBrush
b(clr
, wxSOLID
);
1395 dc
.SetBackground(b
);
1400 dc
.SetClippingRegion(100, 100, 100, 100);
1404 if ( m_owner
->m_textureBackground
)
1406 dc
.SetPen(*wxMEDIUM_GREY_PEN
);
1407 for ( int i
= 0; i
< 200; i
++ )
1408 dc
.DrawLine(0, i
*10, i
*10, 0);
1434 DrawTestLines( 0, 100, 0, dc
);
1435 DrawTestLines( 0, 320, 1, dc
);
1436 DrawTestLines( 0, 540, 2, dc
);
1437 DrawTestLines( 0, 760, 6, dc
);
1441 DrawTestBrushes(dc
);
1449 DrawImages(dc
, Draw_Normal
);
1452 case Show_Mask_Stretch
:
1453 DrawImages(dc
, Draw_Stretch
);
1457 DrawWithLogicalOps(dc
);
1460 #if wxUSE_GRAPHICS_CONTEXT
1465 DrawGraphics(gdc
.GetGraphicsContext());
1478 void MyCanvas::OnMouseMove(wxMouseEvent
&event
)
1481 wxClientDC
dc(this);
1483 m_owner
->PrepareDC(dc
);
1485 wxPoint pos
= event
.GetPosition();
1486 long x
= dc
.DeviceToLogicalX( pos
.x
);
1487 long y
= dc
.DeviceToLogicalY( pos
.y
);
1489 str
.Printf( wxT("Current mouse position: %d,%d"), (int)x
, (int)y
);
1490 m_owner
->SetStatusText( str
);
1493 #endif // wxUSE_STATUSBAR
1496 // ----------------------------------------------------------------------------
1498 // ----------------------------------------------------------------------------
1500 // the event tables connect the wxWidgets events with the functions (event
1501 // handlers) which process them. It can be also done at run-time, but for the
1502 // simple menu events like this the static method is much simpler.
1503 BEGIN_EVENT_TABLE(MyFrame
, wxFrame
)
1504 EVT_MENU (File_Quit
, MyFrame::OnQuit
)
1505 EVT_MENU (File_About
, MyFrame::OnAbout
)
1506 EVT_MENU (File_Clip
, MyFrame::OnClip
)
1507 #if wxUSE_GRAPHICS_CONTEXT
1508 EVT_MENU (File_GraphicContext
, MyFrame::OnGraphicContext
)
1511 EVT_MENU_RANGE(MenuShow_First
, MenuShow_Last
, MyFrame::OnShow
)
1513 EVT_MENU_RANGE(MenuOption_First
, MenuOption_Last
, MyFrame::OnOption
)
1516 // frame constructor
1517 MyFrame::MyFrame(const wxString
& title
, const wxPoint
& pos
, const wxSize
& size
)
1518 : wxFrame((wxFrame
*)NULL
, wxID_ANY
, title
, pos
, size
,
1519 wxDEFAULT_FRAME_STYLE
| wxNO_FULL_REPAINT_ON_RESIZE
)
1521 // set the frame icon
1522 SetIcon(wxICON(mondrian
));
1524 wxMenu
*menuFile
= new wxMenu
;
1525 menuFile
->Append(File_ShowDefault
, _T("&Default screen\tF1"));
1526 menuFile
->Append(File_ShowText
, _T("&Text screen\tF2"));
1527 menuFile
->Append(File_ShowLines
, _T("&Lines screen\tF3"));
1528 menuFile
->Append(File_ShowBrushes
, _T("&Brushes screen\tF4"));
1529 menuFile
->Append(File_ShowPolygons
, _T("&Polygons screen\tF5"));
1530 menuFile
->Append(File_ShowMask
, _T("&Mask screen\tF6"));
1531 menuFile
->Append(File_ShowMaskStretch
, _T("1/&2 scaled mask\tShift-F6"));
1532 menuFile
->Append(File_ShowOps
, _T("&ROP screen\tF7"));
1533 menuFile
->Append(File_ShowRegions
, _T("Re&gions screen\tF8"));
1534 menuFile
->Append(File_ShowCircles
, _T("&Circles screen\tF9"));
1535 #if wxUSE_GRAPHICS_CONTEXT
1536 menuFile
->Append(File_ShowAlpha
, _T("&Alpha screen\tF10"));
1538 menuFile
->Append(File_ShowSplines
, _T("&Splines screen\tF11"));
1539 menuFile
->Append(File_ShowGradients
, _T("&Gradients screen\tF12"));
1540 #if wxUSE_GRAPHICS_CONTEXT
1541 menuFile
->Append(File_ShowGraphics
, _T("&Graphics screen\tF13"));
1543 menuFile
->AppendSeparator();
1544 menuFile
->AppendCheckItem(File_Clip
, _T("&Clip\tCtrl-C"), _T("Clip/unclip drawing"));
1545 #if wxUSE_GRAPHICS_CONTEXT
1546 menuFile
->AppendCheckItem(File_GraphicContext
, _T("&Use GraphicContext\tCtrl-Y"), _T("Use GraphicContext"));
1548 menuFile
->AppendSeparator();
1549 menuFile
->Append(File_About
, _T("&About...\tCtrl-A"), _T("Show about dialog"));
1550 menuFile
->AppendSeparator();
1551 menuFile
->Append(File_Quit
, _T("E&xit\tAlt-X"), _T("Quit this program"));
1553 wxMenu
*menuMapMode
= new wxMenu
;
1554 menuMapMode
->Append( MapMode_Text
, _T("&TEXT map mode") );
1555 menuMapMode
->Append( MapMode_Lometric
, _T("&LOMETRIC map mode") );
1556 menuMapMode
->Append( MapMode_Twips
, _T("T&WIPS map mode") );
1557 menuMapMode
->Append( MapMode_Points
, _T("&POINTS map mode") );
1558 menuMapMode
->Append( MapMode_Metric
, _T("&METRIC map mode") );
1560 wxMenu
*menuUserScale
= new wxMenu
;
1561 menuUserScale
->Append( UserScale_StretchHoriz
, _T("Stretch &horizontally\tCtrl-H") );
1562 menuUserScale
->Append( UserScale_ShrinkHoriz
, _T("Shrin&k horizontally\tCtrl-G") );
1563 menuUserScale
->Append( UserScale_StretchVertic
, _T("Stretch &vertically\tCtrl-V") );
1564 menuUserScale
->Append( UserScale_ShrinkVertic
, _T("&Shrink vertically\tCtrl-W") );
1565 menuUserScale
->AppendSeparator();
1566 menuUserScale
->Append( UserScale_Restore
, _T("&Restore to normal\tCtrl-0") );
1568 wxMenu
*menuAxis
= new wxMenu
;
1569 menuAxis
->AppendCheckItem( AxisMirror_Horiz
, _T("Mirror horizontally\tCtrl-M") );
1570 menuAxis
->AppendCheckItem( AxisMirror_Vertic
, _T("Mirror vertically\tCtrl-N") );
1572 wxMenu
*menuLogical
= new wxMenu
;
1573 menuLogical
->Append( LogicalOrigin_MoveDown
, _T("Move &down\tCtrl-D") );
1574 menuLogical
->Append( LogicalOrigin_MoveUp
, _T("Move &up\tCtrl-U") );
1575 menuLogical
->Append( LogicalOrigin_MoveLeft
, _T("Move &right\tCtrl-L") );
1576 menuLogical
->Append( LogicalOrigin_MoveRight
, _T("Move &left\tCtrl-R") );
1577 menuLogical
->AppendSeparator();
1578 menuLogical
->Append( LogicalOrigin_Set
, _T("Set to (&100, 100)\tShift-Ctrl-1") );
1579 menuLogical
->Append( LogicalOrigin_Restore
, _T("&Restore to normal\tShift-Ctrl-0") );
1581 wxMenu
*menuColour
= new wxMenu
;
1583 menuColour
->Append( Colour_TextForeground
, _T("Text &foreground...") );
1584 menuColour
->Append( Colour_TextBackground
, _T("Text &background...") );
1585 menuColour
->Append( Colour_Background
, _T("Background &colour...") );
1586 #endif // wxUSE_COLOURDLG
1587 menuColour
->AppendCheckItem( Colour_BackgroundMode
, _T("&Opaque/transparent\tCtrl-B") );
1588 menuColour
->AppendCheckItem( Colour_TextureBackgound
, _T("Draw textured back&ground\tCtrl-T") );
1590 // now append the freshly created menu to the menu bar...
1591 wxMenuBar
*menuBar
= new wxMenuBar
;
1592 menuBar
->Append(menuFile
, _T("&File"));
1593 menuBar
->Append(menuMapMode
, _T("&Mode"));
1594 menuBar
->Append(menuUserScale
, _T("&Scale"));
1595 menuBar
->Append(menuAxis
, _T("&Axis"));
1596 menuBar
->Append(menuLogical
, _T("&Origin"));
1597 menuBar
->Append(menuColour
, _T("&Colours"));
1599 // ... and attach this menu bar to the frame
1600 SetMenuBar(menuBar
);
1604 SetStatusText(_T("Welcome to wxWidgets!"));
1605 #endif // wxUSE_STATUSBAR
1607 m_mapMode
= wxMM_TEXT
;
1610 m_xLogicalOrigin
= 0;
1611 m_yLogicalOrigin
= 0;
1613 m_yAxisReversed
= false;
1614 m_backgroundMode
= wxSOLID
;
1615 m_colourForeground
= *wxRED
;
1616 m_colourBackground
= *wxBLUE
;
1617 m_textureBackground
= false;
1619 m_canvas
= new MyCanvas( this );
1620 m_canvas
->SetScrollbars( 10, 10, 100, 240 );
1625 void MyFrame::OnQuit(wxCommandEvent
& WXUNUSED(event
))
1627 // true is to force the frame to close
1631 void MyFrame::OnAbout(wxCommandEvent
& WXUNUSED(event
))
1634 msg
.Printf( wxT("This is the about dialog of the drawing sample.\n")
1635 wxT("This sample tests various primitive drawing functions\n")
1636 wxT("(without any attempts to prevent flicker).\n")
1637 wxT("Copyright (c) Robert Roebling 1999")
1640 wxMessageBox(msg
, _T("About Drawing"), wxOK
| wxICON_INFORMATION
, this);
1643 void MyFrame::OnClip(wxCommandEvent
& event
)
1645 m_canvas
->Clip(event
.IsChecked());
1648 #if wxUSE_GRAPHICS_CONTEXT
1649 void MyFrame::OnGraphicContext(wxCommandEvent
& event
)
1651 m_canvas
->UseGraphicContext(event
.IsChecked());
1655 void MyFrame::OnShow(wxCommandEvent
& event
)
1657 m_canvas
->ToShow((ScreenToShow
)(event
.GetId() - MenuShow_First
));
1660 void MyFrame::OnOption(wxCommandEvent
& event
)
1662 switch (event
.GetId())
1665 m_mapMode
= wxMM_TEXT
;
1667 case MapMode_Lometric
:
1668 m_mapMode
= wxMM_LOMETRIC
;
1671 m_mapMode
= wxMM_TWIPS
;
1673 case MapMode_Points
:
1674 m_mapMode
= wxMM_POINTS
;
1676 case MapMode_Metric
:
1677 m_mapMode
= wxMM_METRIC
;
1680 case LogicalOrigin_MoveDown
:
1681 m_yLogicalOrigin
+= 10;
1683 case LogicalOrigin_MoveUp
:
1684 m_yLogicalOrigin
-= 10;
1686 case LogicalOrigin_MoveLeft
:
1687 m_xLogicalOrigin
+= 10;
1689 case LogicalOrigin_MoveRight
:
1690 m_xLogicalOrigin
-= 10;
1692 case LogicalOrigin_Set
:
1694 m_yLogicalOrigin
= -100;
1696 case LogicalOrigin_Restore
:
1698 m_yLogicalOrigin
= 0;
1701 case UserScale_StretchHoriz
:
1702 m_xUserScale
*= 1.10;
1704 case UserScale_ShrinkHoriz
:
1705 m_xUserScale
/= 1.10;
1707 case UserScale_StretchVertic
:
1708 m_yUserScale
*= 1.10;
1710 case UserScale_ShrinkVertic
:
1711 m_yUserScale
/= 1.10;
1713 case UserScale_Restore
:
1718 case AxisMirror_Vertic
:
1719 m_yAxisReversed
= !m_yAxisReversed
;
1721 case AxisMirror_Horiz
:
1722 m_xAxisReversed
= !m_xAxisReversed
;
1726 case Colour_TextForeground
:
1727 m_colourForeground
= SelectColour();
1729 case Colour_TextBackground
:
1730 m_colourBackground
= SelectColour();
1732 case Colour_Background
:
1734 wxColour col
= SelectColour();
1737 m_backgroundBrush
.SetColour(col
);
1741 #endif // wxUSE_COLOURDLG
1743 case Colour_BackgroundMode
:
1744 m_backgroundMode
= m_backgroundMode
== wxSOLID
? wxTRANSPARENT
1748 case Colour_TextureBackgound
:
1749 m_textureBackground
= ! m_textureBackground
;
1757 m_canvas
->Refresh();
1760 void MyFrame::PrepareDC(wxDC
& dc
)
1762 dc
.SetLogicalOrigin( m_xLogicalOrigin
, m_yLogicalOrigin
);
1763 dc
.SetAxisOrientation( !m_xAxisReversed
, m_yAxisReversed
);
1764 dc
.SetUserScale( m_xUserScale
, m_yUserScale
);
1765 dc
.SetMapMode( m_mapMode
);
1769 wxColour
MyFrame::SelectColour()
1773 wxColourDialog
dialog(this, &data
);
1775 if ( dialog
.ShowModal() == wxID_OK
)
1777 col
= dialog
.GetColourData().GetColour();
1782 #endif // wxUSE_COLOURDLG