1 /////////////////////////////////////////////////////////////////////////////
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 #if defined(__GNUG__) && !defined(__APPLE__)
21 #pragma implementation "drawing.cpp"
22 #pragma interface "drawing.cpp"
25 // For compilers that support precompilation, includes "wx/wx.h".
26 #include "wx/wxprec.h"
32 // for all others, include the necessary headers (this file is usually all you
33 // need because it includes almost all "standard" wxWidgets headers
38 #include "wx/colordlg.h"
40 #include "wx/artprov.h"
42 // ----------------------------------------------------------------------------
44 // ----------------------------------------------------------------------------
46 // the application icon
47 #if defined(__WXGTK__) || defined(__WXMOTIF__) || defined(__WXMAC__) || defined(__WXMGL__) || defined(__WXX11__)
48 #include "mondrian.xpm"
51 // ----------------------------------------------------------------------------
53 // ----------------------------------------------------------------------------
55 // what do we show on screen (there are too many shapes to put them all on
56 // screen simultaneously)
70 // ----------------------------------------------------------------------------
72 // ----------------------------------------------------------------------------
74 static wxBitmap
*gs_bmpNoMask
= NULL
,
75 *gs_bmpWithColMask
= NULL
,
77 *gs_bmpWithMask
= NULL
,
82 // ----------------------------------------------------------------------------
84 // ----------------------------------------------------------------------------
86 // Define a new application type, each program should derive a class from wxApp
87 class MyApp
: public wxApp
90 // override base class virtuals
91 // ----------------------------
93 // this one is called on application startup and is a good place for the app
94 // initialization (doing it here and not in the ctor allows to have an error
95 // return: if OnInit() returns false, the application terminates)
96 virtual bool OnInit();
98 virtual int OnExit() { DeleteBitmaps(); return 0; }
101 void DeleteBitmaps();
108 // Define a new frame type: this is going to be our main frame
109 class MyFrame
: public wxFrame
113 MyFrame(const wxString
& title
, const wxPoint
& pos
, const wxSize
& size
);
115 // event handlers (these functions should _not_ be virtual)
116 void OnQuit(wxCommandEvent
& event
);
117 void OnAbout(wxCommandEvent
& event
);
118 void OnClip(wxCommandEvent
& event
);
119 void OnShow(wxCommandEvent
&event
);
120 void OnOption(wxCommandEvent
&event
);
123 wxColour
SelectColour();
124 #endif // wxUSE_COLOURDLG
125 void PrepareDC(wxDC
& dc
);
127 int m_backgroundMode
;
128 int m_textureBackground
;
132 int m_xLogicalOrigin
;
133 int m_yLogicalOrigin
;
134 bool m_xAxisReversed
,
136 wxColour m_colourForeground
, // these are _text_ colours
138 wxBrush m_backgroundBrush
;
142 // any class wishing to process wxWidgets events must use this macro
143 DECLARE_EVENT_TABLE()
146 // define a scrollable canvas for drawing onto
147 class MyCanvas
: public wxScrolledWindow
150 MyCanvas( MyFrame
*parent
);
152 void OnPaint(wxPaintEvent
&event
);
153 void OnMouseMove(wxMouseEvent
&event
);
155 void ToShow(ScreenToShow show
) { m_show
= show
; Refresh(); }
157 // set or remove the clipping region
158 void Clip(bool clip
) { m_clip
= clip
; Refresh(); }
161 void DrawTestLines( int x
, int y
, int width
, wxDC
&dc
);
162 void DrawTestPoly(wxDC
& dc
);
163 void DrawTestBrushes(wxDC
& dc
);
164 void DrawText(wxDC
& dc
);
165 void DrawImages(wxDC
& dc
);
166 void DrawWithLogicalOps(wxDC
& dc
);
167 void DrawRegions(wxDC
& dc
);
168 void DrawCircles(wxDC
& dc
);
169 void DrawDefault(wxDC
& dc
);
171 void DrawRegionsHelper(wxDC
& dc
, wxCoord x
, bool firstTime
);
177 wxBitmap m_smile_bmp
;
181 DECLARE_EVENT_TABLE()
184 // ----------------------------------------------------------------------------
186 // ----------------------------------------------------------------------------
188 // IDs for the controls and the menu commands
196 File_ShowDefault
= MenuShow_First
,
205 MenuShow_Last
= File_ShowCircles
,
211 MapMode_Text
= MenuOption_First
,
217 UserScale_StretchHoriz
,
218 UserScale_ShrinkHoriz
,
219 UserScale_StretchVertic
,
220 UserScale_ShrinkVertic
,
226 LogicalOrigin_MoveDown
,
227 LogicalOrigin_MoveUp
,
228 LogicalOrigin_MoveLeft
,
229 LogicalOrigin_MoveRight
,
231 LogicalOrigin_Restore
,
234 Colour_TextForeground
,
235 Colour_TextBackground
,
237 #endif // wxUSE_COLOURDLG
238 Colour_BackgroundMode
,
239 Colour_TextureBackgound
,
241 MenuOption_Last
= Colour_TextureBackgound
244 // ----------------------------------------------------------------------------
245 // event tables and other macros for wxWidgets
246 // ----------------------------------------------------------------------------
249 // Create a new application object: this macro will allow wxWidgets to create
250 // the application object during program execution (it's better than using a
251 // static object for many reasons) and also declares the accessor function
252 // wxGetApp() which will return the reference of the right type (i.e. MyApp and
256 // ============================================================================
258 // ============================================================================
260 // ----------------------------------------------------------------------------
261 // the application class
262 // ----------------------------------------------------------------------------
264 bool MyApp::LoadImages()
266 gs_bmpNoMask
= new wxBitmap
;
267 gs_bmpWithColMask
= new wxBitmap
;
268 gs_bmpMask
= new wxBitmap
;
269 gs_bmpWithMask
= new wxBitmap
;
270 gs_bmp4
= new wxBitmap
;
271 gs_bmp4_mono
= new wxBitmap
;
272 gs_bmp36
= new wxBitmap
;
275 pathList
.Add(_T("."));
276 pathList
.Add(_T(".."));
278 wxString path
= pathList
.FindValidPath(_T("pat4.bmp"));
282 /* 4 colour bitmap */
283 gs_bmp4
->LoadFile(path
, wxBITMAP_TYPE_BMP
);
284 /* turn into mono-bitmap */
285 gs_bmp4_mono
->LoadFile(path
, wxBITMAP_TYPE_BMP
);
286 wxMask
* mask4
= new wxMask(*gs_bmp4_mono
, *wxBLACK
);
287 gs_bmp4_mono
->SetMask(mask4
);
289 path
= pathList
.FindValidPath(_T("pat36.bmp"));
292 gs_bmp36
->LoadFile(path
, wxBITMAP_TYPE_BMP
);
293 wxMask
* mask36
= new wxMask(*gs_bmp36
, *wxBLACK
);
294 gs_bmp36
->SetMask(mask36
);
296 path
= pathList
.FindValidPath(_T("image.bmp"));
299 gs_bmpNoMask
->LoadFile(path
, wxBITMAP_TYPE_BMP
);
300 gs_bmpWithMask
->LoadFile(path
, wxBITMAP_TYPE_BMP
);
301 gs_bmpWithColMask
->LoadFile(path
, wxBITMAP_TYPE_BMP
);
303 path
= pathList
.FindValidPath(_T("mask.bmp"));
306 gs_bmpMask
->LoadFile(path
, wxBITMAP_TYPE_BMP
);
308 wxMask
*mask
= new wxMask(*gs_bmpMask
, *wxBLACK
);
309 gs_bmpWithMask
->SetMask(mask
);
311 mask
= new wxMask(*gs_bmpWithColMask
, *wxWHITE
);
312 gs_bmpWithColMask
->SetMask(mask
);
317 // `Main program' equivalent: the program execution "starts" here
320 // Create the main application window
321 MyFrame
*frame
= new MyFrame(_T("Drawing sample"),
322 wxPoint(50, 50), wxSize(550, 340));
324 // Show it and tell the application that it's our main window
330 wxLogError(wxT("Can't load one of the bitmap files needed ")
331 wxT("for this sample from the current or parent ")
332 wxT("directory, please copy them there."));
344 void MyApp::DeleteBitmaps()
347 delete gs_bmpWithColMask
;
349 delete gs_bmpWithMask
;
355 gs_bmpWithColMask
= NULL
;
357 gs_bmpWithMask
= NULL
;
363 // ----------------------------------------------------------------------------
365 // ----------------------------------------------------------------------------
367 // the event tables connect the wxWidgets events with the functions (event
368 // handlers) which process them.
369 BEGIN_EVENT_TABLE(MyCanvas
, wxScrolledWindow
)
370 EVT_PAINT (MyCanvas::OnPaint
)
371 EVT_MOTION (MyCanvas::OnMouseMove
)
376 MyCanvas::MyCanvas(MyFrame
*parent
)
377 : wxScrolledWindow(parent
, wxID_ANY
, wxDefaultPosition
, wxDefaultSize
,
378 wxHSCROLL
| wxVSCROLL
| wxNO_FULL_REPAINT_ON_RESIZE
)
381 m_show
= Show_Default
;
382 m_smile_bmp
= wxBitmap(smile_xpm
);
383 m_std_icon
= wxArtProvider::GetIcon(wxART_INFORMATION
);
387 void MyCanvas::DrawTestBrushes(wxDC
& dc
)
389 static const wxCoord WIDTH
= 200;
390 static const wxCoord HEIGHT
= 80;
395 dc
.SetBrush(wxBrush(*wxGREEN
, wxSOLID
));
396 dc
.DrawRectangle(x
, y
, WIDTH
, HEIGHT
);
397 dc
.DrawText(_T("Solid green"), x
+ 10, y
+ 10);
400 dc
.SetBrush(wxBrush(*wxRED
, wxCROSSDIAG_HATCH
));
401 dc
.DrawRectangle(x
, y
, WIDTH
, HEIGHT
);
402 dc
.DrawText(_T("Hatched red"), x
+ 10, y
+ 10);
405 dc
.SetBrush(wxBrush(*gs_bmpMask
));
406 dc
.DrawRectangle(x
, y
, WIDTH
, HEIGHT
);
407 dc
.DrawText(_T("Stipple mono"), x
+ 10, y
+ 10);
410 dc
.SetBrush(wxBrush(*gs_bmpNoMask
));
411 dc
.DrawRectangle(x
, y
, WIDTH
, HEIGHT
);
412 dc
.DrawText(_T("Stipple colour"), x
+ 10, y
+ 10);
415 void MyCanvas::DrawTestPoly(wxDC
& dc
)
417 wxBrush
brushHatch(*wxRED
, wxFDIAGONAL_HATCH
);
418 dc
.SetBrush(brushHatch
);
421 star
[0] = wxPoint(100, 60);
422 star
[1] = wxPoint(60, 150);
423 star
[2] = wxPoint(160, 100);
424 star
[3] = wxPoint(40, 100);
425 star
[4] = wxPoint(140, 150);
427 dc
.DrawText(_T("You should see two (irregular) stars below, the left one ")
428 _T("hatched"), 10, 10);
429 dc
.DrawText(_T("except for the central region and the right ")
430 _T("one entirely hatched"), 10, 30);
431 dc
.DrawText(_T("The third star only has a hatched outline"), 10, 50);
433 dc
.DrawPolygon(WXSIZEOF(star
), star
, 0, 30);
434 dc
.DrawPolygon(WXSIZEOF(star
), star
, 160, 30, wxWINDING_RULE
);
437 star2
[0] = wxPoint(0, 100);
438 star2
[1] = wxPoint(-59, -81);
439 star2
[2] = wxPoint(95, 31);
440 star2
[3] = wxPoint(-95, 31);
441 star2
[4] = wxPoint(59, -81);
442 star2
[5] = wxPoint(0, 80);
443 star2
[6] = wxPoint(-47, -64);
444 star2
[7] = wxPoint(76, 24);
445 star2
[8] = wxPoint(-76, 24);
446 star2
[9] = wxPoint(47, -64);
447 int count
[2] = {5, 5};
449 dc
.DrawPolyPolygon(WXSIZEOF(count
), count
, star2
, 450, 150);
452 void MyCanvas::DrawTestLines( int x
, int y
, int width
, wxDC
&dc
)
454 dc
.SetPen( wxPen( wxT("black"), width
, wxSOLID
) );
455 dc
.SetBrush( *wxRED_BRUSH
);
456 dc
.DrawText(wxString::Format(wxT("Testing lines of width %d"), width
), x
+ 10, y
- 10);
457 dc
.DrawRectangle( x
+10, y
+10, 100, 190 );
459 dc
.DrawText(_T("Solid/dot/short dash/long dash/dot dash"), x
+ 150, y
+ 10);
460 dc
.SetPen( wxPen( wxT("black"), width
, wxSOLID
) );
461 dc
.DrawLine( x
+20, y
+20, 100, y
+20 );
462 dc
.SetPen( wxPen( wxT("black"), width
, wxDOT
) );
463 dc
.DrawLine( x
+20, y
+30, 100, y
+30 );
464 dc
.SetPen( wxPen( wxT("black"), width
, wxSHORT_DASH
) );
465 dc
.DrawLine( x
+20, y
+40, 100, y
+40 );
466 dc
.SetPen( wxPen( wxT("black"), width
, wxLONG_DASH
) );
467 dc
.DrawLine( x
+20, y
+50, 100, y
+50 );
468 dc
.SetPen( wxPen( wxT("black"), width
, wxDOT_DASH
) );
469 dc
.DrawLine( x
+20, y
+60, 100, y
+60 );
471 dc
.DrawText(_T("Misc hatches"), x
+ 150, y
+ 70);
472 dc
.SetPen( wxPen( wxT("black"), width
, wxBDIAGONAL_HATCH
) );
473 dc
.DrawLine( x
+20, y
+70, 100, y
+70 );
474 dc
.SetPen( wxPen( wxT("black"), width
, wxCROSSDIAG_HATCH
) );
475 dc
.DrawLine( x
+20, y
+80, 100, y
+80 );
476 dc
.SetPen( wxPen( wxT("black"), width
, wxFDIAGONAL_HATCH
) );
477 dc
.DrawLine( x
+20, y
+90, 100, y
+90 );
478 dc
.SetPen( wxPen( wxT("black"), width
, wxCROSS_HATCH
) );
479 dc
.DrawLine( x
+20, y
+100, 100, y
+100 );
480 dc
.SetPen( wxPen( wxT("black"), width
, wxHORIZONTAL_HATCH
) );
481 dc
.DrawLine( x
+20, y
+110, 100, y
+110 );
482 dc
.SetPen( wxPen( wxT("black"), width
, wxVERTICAL_HATCH
) );
483 dc
.DrawLine( x
+20, y
+120, 100, y
+120 );
485 dc
.DrawText(_T("User dash"), x
+ 150, y
+ 140);
486 wxPen
ud( wxT("black"), width
, wxUSER_DASH
);
488 dash1
[0] = 8; // Long dash <---------+
489 dash1
[1] = 2; // Short gap |
490 dash1
[2] = 3; // Short dash |
491 dash1
[3] = 2; // Short gap |
492 dash1
[4] = 3; // Short dash |
493 dash1
[5] = 2; // Short gap and repeat +
494 ud
.SetDashes( 6, dash1
);
496 dc
.DrawLine( x
+20, y
+140, 100, y
+140 );
497 dash1
[0] = 5; // Make first dash shorter
498 ud
.SetDashes( 6, dash1
);
500 dc
.DrawLine( x
+20, y
+150, 100, y
+150 );
501 dash1
[2] = 5; // Make second dash longer
502 ud
.SetDashes( 6, dash1
);
504 dc
.DrawLine( x
+20, y
+160, 100, y
+160 );
505 dash1
[4] = 5; // Make third dash longer
506 ud
.SetDashes( 6, dash1
);
508 dc
.DrawLine( x
+20, y
+170, 100, y
+170 );
511 void MyCanvas::DrawDefault(wxDC
& dc
)
514 dc
.DrawCircle(0, 0, 10);
516 //flood fill using brush, starting at 1,1 and replacing whatever colour we find there
517 dc
.SetBrush(wxBrush(wxColour(128,128,0), wxSOLID
));
519 dc
.GetPixel(1,1, &tmpColour
);
520 dc
.FloodFill(1,1, tmpColour
, wxFLOOD_SURFACE
);
522 dc
.DrawCheckMark(5, 80, 15, 15);
523 dc
.DrawCheckMark(25, 80, 30, 30);
524 dc
.DrawCheckMark(60, 80, 60, 60);
526 // this is the test for "blitting bitmap into DC damages selected brush" bug
527 wxCoord rectSize
= m_std_icon
.GetWidth() + 10;
529 dc
.SetPen(*wxTRANSPARENT_PEN
);
530 dc
.SetBrush( *wxGREEN_BRUSH
);
531 dc
.DrawRectangle(x
, 10, rectSize
, rectSize
);
532 dc
.DrawBitmap(m_std_icon
, x
+ 5, 15, true);
534 dc
.DrawRectangle(x
, 10, rectSize
, rectSize
);
535 dc
.DrawIcon(m_std_icon
, x
+ 5, 15);
537 dc
.DrawRectangle(x
, 10, rectSize
, rectSize
);
539 // test for "transparent" bitmap drawing (it intersects with the last
541 //dc.SetBrush( *wxTRANSPARENT_BRUSH );
543 if (m_smile_bmp
.Ok())
544 dc
.DrawBitmap(m_smile_bmp
, x
+ rectSize
- 20, rectSize
- 10, true);
546 dc
.SetBrush( *wxBLACK_BRUSH
);
547 dc
.DrawRectangle( 0, 160, 1000, 300 );
550 wxBitmap
bitmap(20,70);
552 memdc
.SelectObject( bitmap
);
553 memdc
.SetBrush( *wxBLACK_BRUSH
);
554 memdc
.SetPen( *wxWHITE_PEN
);
555 memdc
.DrawRectangle(0,0,20,70);
556 memdc
.DrawLine( 10,0,10,70 );
559 wxPen pen
= *wxRED_PEN
;
561 memdc
.DrawLine( 10, 5,10, 5 );
562 memdc
.DrawLine( 10,10,11,10 );
563 memdc
.DrawLine( 10,15,12,15 );
564 memdc
.DrawLine( 10,20,13,20 );
567 memdc.SetPen(*wxRED_PEN);
568 memdc.DrawLine( 12, 5,12, 5 );
569 memdc.DrawLine( 12,10,13,10 );
570 memdc.DrawLine( 12,15,14,15 );
571 memdc.DrawLine( 12,20,15,20 );
575 memdc
.DrawLine( 10,25,10,25 );
576 memdc
.DrawLine( 10,30, 9,30 );
577 memdc
.DrawLine( 10,35, 8,35 );
578 memdc
.DrawLine( 10,40, 7,40 );
581 dc
.SetPen(*wxWHITE_PEN
);
582 memdc
.SetLogicalFunction( wxINVERT
);
583 memdc
.SetPen( *wxWHITE_PEN
);
584 memdc
.DrawLine( 10,50,10,50 );
585 memdc
.DrawLine( 10,55,11,55 );
586 memdc
.DrawLine( 10,60,12,60 );
587 memdc
.DrawLine( 10,65,13,65 );
589 memdc
.DrawLine( 12,50,12,50 );
590 memdc
.DrawLine( 12,55,13,55 );
591 memdc
.DrawLine( 12,60,14,60 );
592 memdc
.DrawLine( 12,65,15,65 );
594 memdc
.SelectObject( wxNullBitmap
);
595 dc
.DrawBitmap( bitmap
, 10, 170 );
596 wxImage image
= bitmap
.ConvertToImage();
597 image
.Rescale( 60,210 );
598 bitmap
= wxBitmap(image
);
599 dc
.DrawBitmap( bitmap
, 50, 170 );
601 // test the rectangle outline drawing - there should be one pixel between
602 // the rect and the lines
603 dc
.SetPen(*wxWHITE_PEN
);
604 dc
.SetBrush( *wxTRANSPARENT_BRUSH
);
605 dc
.DrawRectangle(150, 170, 49, 29);
606 dc
.DrawRectangle(200, 170, 49, 29);
607 dc
.SetPen(*wxWHITE_PEN
);
608 dc
.DrawLine(250, 210, 250, 170);
609 dc
.DrawLine(260, 200, 150, 200);
611 // test the rectangle filled drawing - there should be one pixel between
612 // the rect and the lines
613 dc
.SetPen(*wxTRANSPARENT_PEN
);
614 dc
.SetBrush( *wxWHITE_BRUSH
);
615 dc
.DrawRectangle(300, 170, 49, 29);
616 dc
.DrawRectangle(350, 170, 49, 29);
617 dc
.SetPen(*wxWHITE_PEN
);
618 dc
.DrawLine(400, 170, 400, 210);
619 dc
.DrawLine(300, 200, 410, 200);
621 // a few more tests of this kind
622 dc
.SetPen(*wxRED_PEN
);
623 dc
.SetBrush( *wxWHITE_BRUSH
);
624 dc
.DrawRectangle(300, 220, 1, 1);
625 dc
.DrawRectangle(310, 220, 2, 2);
626 dc
.DrawRectangle(320, 220, 3, 3);
627 dc
.DrawRectangle(330, 220, 4, 4);
629 dc
.SetPen(*wxTRANSPARENT_PEN
);
630 dc
.SetBrush( *wxWHITE_BRUSH
);
631 dc
.DrawRectangle(300, 230, 1, 1);
632 dc
.DrawRectangle(310, 230, 2, 2);
633 dc
.DrawRectangle(320, 230, 3, 3);
634 dc
.DrawRectangle(330, 230, 4, 4);
636 // and now for filled rect with outline
637 dc
.SetPen(*wxRED_PEN
);
638 dc
.SetBrush( *wxWHITE_BRUSH
);
639 dc
.DrawRectangle(500, 170, 49, 29);
640 dc
.DrawRectangle(550, 170, 49, 29);
641 dc
.SetPen(*wxWHITE_PEN
);
642 dc
.DrawLine(600, 170, 600, 210);
643 dc
.DrawLine(500, 200, 610, 200);
645 // test the rectangle outline drawing - there should be one pixel between
646 // the rect and the lines
647 dc
.SetPen(*wxWHITE_PEN
);
648 dc
.SetBrush( *wxTRANSPARENT_BRUSH
);
649 dc
.DrawRoundedRectangle(150, 270, 49, 29, 6);
650 dc
.DrawRoundedRectangle(200, 270, 49, 29, 6);
651 dc
.SetPen(*wxWHITE_PEN
);
652 dc
.DrawLine(250, 270, 250, 310);
653 dc
.DrawLine(150, 300, 260, 300);
655 // test the rectangle filled drawing - there should be one pixel between
656 // the rect and the lines
657 dc
.SetPen(*wxTRANSPARENT_PEN
);
658 dc
.SetBrush( *wxWHITE_BRUSH
);
659 dc
.DrawRoundedRectangle(300, 270, 49, 29, 6);
660 dc
.DrawRoundedRectangle(350, 270, 49, 29, 6);
661 dc
.SetPen(*wxWHITE_PEN
);
662 dc
.DrawLine(400, 270, 400, 310);
663 dc
.DrawLine(300, 300, 410, 300);
665 // Added by JACS to demonstrate bizarre behaviour.
666 // With a size of 70, we get a missing red RHS,
667 // and the hight is too small, so we get yellow
668 // showing. With a size of 40, it draws as expected:
669 // it just shows a white rectangle with red outline.
671 int totalHeight
= 70;
672 wxBitmap
bitmap2(totalWidth
, totalHeight
);
675 memdc2
.SelectObject(bitmap2
);
677 wxColour
clr(255, 255, 0);
678 wxBrush
yellowBrush(clr
, wxSOLID
);
679 memdc2
.SetBackground(yellowBrush
);
682 wxPen
yellowPen(clr
, 1, wxSOLID
);
684 // Now draw a white rectangle with red outline. It should
685 // entirely eclipse the yellow background.
686 memdc2
.SetPen(*wxRED_PEN
);
687 memdc2
.SetBrush(*wxWHITE_BRUSH
);
689 memdc2
.DrawRectangle(0, 0, totalWidth
, totalHeight
);
691 memdc2
.SetPen(wxNullPen
);
692 memdc2
.SetBrush(wxNullBrush
);
693 memdc2
.SelectObject(wxNullBitmap
);
695 dc
.DrawBitmap(bitmap2
, 500, 270);
697 // Repeat, but draw directly on dc
698 // Draw a yellow rectangle filling the bitmap
700 x
= 600; int y
= 270;
701 dc
.SetPen(yellowPen
);
702 dc
.SetBrush(yellowBrush
);
703 dc
.DrawRectangle(x
, y
, totalWidth
, totalHeight
);
705 // Now draw a white rectangle with red outline. It should
706 // entirely eclipse the yellow background.
707 dc
.SetPen(*wxRED_PEN
);
708 dc
.SetBrush(*wxWHITE_BRUSH
);
710 dc
.DrawRectangle(x
, y
, totalWidth
, totalHeight
);
713 void MyCanvas::DrawText(wxDC
& dc
)
715 // set underlined font for testing
716 dc
.SetFont( wxFont(12, wxMODERN
, wxNORMAL
, wxNORMAL
, true) );
717 dc
.DrawText( _T("This is text"), 110, 10 );
718 dc
.DrawRotatedText( _T("That is text"), 20, 10, -45 );
720 // use wxSWISS_FONT and not wxNORMAL_FONT as the latter can't be rotated
721 // under Win9x (it is not TrueType)
722 dc
.SetFont( *wxSWISS_FONT
);
725 dc
.SetBackgroundMode(wxTRANSPARENT
);
727 for ( int n
= -180; n
< 180; n
+= 30 )
729 text
.Printf(wxT(" %d rotated text"), n
);
730 dc
.DrawRotatedText(text
, 400, 400, n
);
733 dc
.SetFont( wxFont( 18, wxSWISS
, wxNORMAL
, wxNORMAL
) );
735 dc
.DrawText( _T("This is Swiss 18pt text."), 110, 40 );
740 dc
.GetTextExtent( _T("This is Swiss 18pt text."), &length
, &height
, &descent
);
741 text
.Printf( wxT("Dimensions are length %ld, height %ld, descent %ld"), length
, height
, descent
);
742 dc
.DrawText( text
, 110, 80 );
744 text
.Printf( wxT("CharHeight() returns: %d"), dc
.GetCharHeight() );
745 dc
.DrawText( text
, 110, 120 );
747 dc
.DrawRectangle( 100, 40, 4, height
);
749 // test the logical function effect
751 dc
.SetLogicalFunction(wxINVERT
);
752 dc
.DrawText( _T("There should be no text below"), 110, 150 );
753 dc
.DrawRectangle( 110, y
, 100, height
);
755 // twice drawn inverted should result in invisible
757 dc
.DrawText( _T("Invisible text"), 110, y
);
758 dc
.DrawRectangle( 110, y
, 100, height
);
759 dc
.DrawText( _T("Invisible text"), 110, y
);
760 dc
.DrawRectangle( 110, y
, 100, height
);
761 dc
.SetLogicalFunction(wxCOPY
);
764 dc
.DrawRectangle( 110, y
, 100, height
);
765 dc
.DrawText( _T("Visible text"), 110, y
);
772 } rasterOperations
[] =
774 { wxT("wxAND"), wxAND
},
775 { wxT("wxAND_INVERT"), wxAND_INVERT
},
776 { wxT("wxAND_REVERSE"), wxAND_REVERSE
},
777 { wxT("wxCLEAR"), wxCLEAR
},
778 { wxT("wxCOPY"), wxCOPY
},
779 { wxT("wxEQUIV"), wxEQUIV
},
780 { wxT("wxINVERT"), wxINVERT
},
781 { wxT("wxNAND"), wxNAND
},
782 { wxT("wxNO_OP"), wxNO_OP
},
783 { wxT("wxOR"), wxOR
},
784 { wxT("wxOR_INVERT"), wxOR_INVERT
},
785 { wxT("wxOR_REVERSE"), wxOR_REVERSE
},
786 { wxT("wxSET"), wxSET
},
787 { wxT("wxSRC_INVERT"), wxSRC_INVERT
},
788 { wxT("wxXOR"), wxXOR
},
791 void MyCanvas::DrawImages(wxDC
& dc
)
793 dc
.DrawText(_T("original image"), 0, 0);
794 dc
.DrawBitmap(*gs_bmpNoMask
, 0, 20, 0);
795 dc
.DrawText(_T("with colour mask"), 0, 100);
796 dc
.DrawBitmap(*gs_bmpWithColMask
, 0, 120, true);
797 dc
.DrawText(_T("the mask image"), 0, 200);
798 dc
.DrawBitmap(*gs_bmpMask
, 0, 220, 0);
799 dc
.DrawText(_T("masked image"), 0, 300);
800 dc
.DrawBitmap(*gs_bmpWithMask
, 0, 320, true);
802 int cx
= gs_bmpWithColMask
->GetWidth(),
803 cy
= gs_bmpWithColMask
->GetHeight();
806 for ( size_t n
= 0; n
< WXSIZEOF(rasterOperations
); n
++ )
808 wxCoord x
= 120 + 150*(n%4
),
811 dc
.DrawText(rasterOperations
[n
].name
, x
, y
- 20);
812 memDC
.SelectObject(*gs_bmpWithColMask
);
813 dc
.Blit(x
, y
, cx
, cy
, &memDC
, 0, 0, rasterOperations
[n
].rop
, true);
817 void MyCanvas::DrawWithLogicalOps(wxDC
& dc
)
819 static const wxCoord w
= 60;
820 static const wxCoord h
= 60;
822 // reuse the text colour here
823 dc
.SetPen(wxPen(m_owner
->m_colourForeground
, 1, wxSOLID
));
824 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
827 for ( n
= 0; n
< WXSIZEOF(rasterOperations
); n
++ )
829 wxCoord x
= 20 + 150*(n%4
),
832 dc
.DrawText(rasterOperations
[n
].name
, x
, y
- 20);
833 dc
.SetLogicalFunction(rasterOperations
[n
].rop
);
834 dc
.DrawRectangle(x
, y
, w
, h
);
835 dc
.DrawLine(x
, y
, x
+ w
, y
+ h
);
836 dc
.DrawLine(x
+ w
, y
, x
, y
+ h
);
839 // now some filled rectangles
840 dc
.SetBrush(wxBrush(m_owner
->m_colourForeground
, wxSOLID
));
842 for ( n
= 0; n
< WXSIZEOF(rasterOperations
); n
++ )
844 wxCoord x
= 20 + 150*(n%4
),
847 dc
.DrawText(rasterOperations
[n
].name
, x
, y
- 20);
848 dc
.SetLogicalFunction(rasterOperations
[n
].rop
);
849 dc
.DrawRectangle(x
, y
, w
, h
);
853 void MyCanvas::DrawCircles(wxDC
& dc
)
859 dc
.DrawText(_T("Some circles"), 0, y
);
860 dc
.DrawCircle(x
, y
, r
);
861 dc
.DrawCircle(x
+ 2*r
, y
, r
);
862 dc
.DrawCircle(x
+ 4*r
, y
, r
);
865 dc
.DrawText(_T("And ellipses"), 0, y
);
866 dc
.DrawEllipse(x
- r
, y
, 2*r
, r
);
867 dc
.DrawEllipse(x
+ r
, y
, 2*r
, r
);
868 dc
.DrawEllipse(x
+ 3*r
, y
, 2*r
, r
);
871 dc
.DrawText(_T("And arcs"), 0, y
);
872 dc
.DrawArc(x
- r
, y
, x
+ r
, y
, x
, y
);
873 dc
.DrawArc(x
+ 4*r
, y
, x
+ 2*r
, y
, x
+ 3*r
, y
);
874 dc
.DrawArc(x
+ 5*r
, y
, x
+ 5*r
, y
, x
+ 6*r
, y
);
877 dc
.DrawEllipticArc(x
- r
, y
, 2*r
, r
, 0, 90);
878 dc
.DrawEllipticArc(x
+ r
, y
, 2*r
, r
, 90, 180);
879 dc
.DrawEllipticArc(x
+ 3*r
, y
, 2*r
, r
, 180, 270);
880 dc
.DrawEllipticArc(x
+ 5*r
, y
, 2*r
, r
, 270, 360);
883 void MyCanvas::DrawRegions(wxDC
& dc
)
885 dc
.DrawText(_T("You should see a red rect partly covered by a cyan one ")
886 _T("on the left"), 10, 5);
887 dc
.DrawText(_T("and 5 smileys from which 4 are partially clipped on the right"),
888 10, 5 + dc
.GetCharHeight());
889 dc
.DrawText(_T("The second copy should be identical but right part of it ")
890 _T("should be offset by 10 pixels."),
891 10, 5 + 2*dc
.GetCharHeight());
893 DrawRegionsHelper(dc
, 10, true);
894 DrawRegionsHelper(dc
, 350, false);
897 void MyCanvas::DrawRegionsHelper(wxDC
& dc
, wxCoord x
, bool firstTime
)
901 dc
.DestroyClippingRegion();
902 dc
.SetBrush( *wxWHITE_BRUSH
);
903 dc
.SetPen( *wxTRANSPARENT_PEN
);
904 dc
.DrawRectangle( x
, y
, 310, 310 );
906 dc
.SetClippingRegion( x
+ 10, y
+ 10, 100, 270 );
908 dc
.SetBrush( *wxRED_BRUSH
);
909 dc
.DrawRectangle( x
, y
, 310, 310 );
911 dc
.SetClippingRegion( x
+ 10, y
+ 10, 100, 100 );
913 dc
.SetBrush( *wxCYAN_BRUSH
);
914 dc
.DrawRectangle( x
, y
, 310, 310 );
916 dc
.DestroyClippingRegion();
918 wxRegion
region(x
+ 110, y
+ 20, 100, 270);
919 #if !defined(__WXMOTIF__) && !defined(__WXMAC__)
921 region
.Offset(10, 10);
923 dc
.SetClippingRegion(region
);
925 dc
.SetBrush( *wxGREY_BRUSH
);
926 dc
.DrawRectangle( x
, y
, 310, 310 );
928 if (m_smile_bmp
.Ok())
930 dc
.DrawBitmap( m_smile_bmp
, x
+ 150, y
+ 150, true );
931 dc
.DrawBitmap( m_smile_bmp
, x
+ 130, y
+ 10, true );
932 dc
.DrawBitmap( m_smile_bmp
, x
+ 130, y
+ 280, true );
933 dc
.DrawBitmap( m_smile_bmp
, x
+ 100, y
+ 70, true );
934 dc
.DrawBitmap( m_smile_bmp
, x
+ 200, y
+ 70, true );
938 void MyCanvas::OnPaint(wxPaintEvent
&WXUNUSED(event
))
943 m_owner
->PrepareDC(dc
);
945 dc
.SetBackgroundMode( m_owner
->m_backgroundMode
);
946 if ( m_owner
->m_backgroundBrush
.Ok() )
947 dc
.SetBackground( m_owner
->m_backgroundBrush
);
948 if ( m_owner
->m_colourForeground
.Ok() )
949 dc
.SetTextForeground( m_owner
->m_colourForeground
);
950 if ( m_owner
->m_colourBackground
.Ok() )
951 dc
.SetTextBackground( m_owner
->m_colourBackground
);
953 if ( m_owner
->m_textureBackground
) {
954 if ( ! m_owner
->m_backgroundBrush
.Ok() ) {
955 wxColour
clr(0,128,0);
956 wxBrush
b(clr
, wxSOLID
);
962 dc
.SetClippingRegion(100, 100, 100, 100);
966 if ( m_owner
->m_textureBackground
)
968 dc
.SetPen(*wxMEDIUM_GREY_PEN
);
969 for ( int i
= 0; i
< 200; i
++ )
970 dc
.DrawLine(0, i
*10, i
*10, 0);
992 DrawTestLines( 0, 100, 0, dc
);
993 DrawTestLines( 0, 320, 1, dc
);
994 DrawTestLines( 0, 540, 2, dc
);
995 DrawTestLines( 0, 760, 6, dc
);
1011 DrawWithLogicalOps(dc
);
1016 void MyCanvas::OnMouseMove(wxMouseEvent
&event
)
1019 wxClientDC
dc(this);
1021 m_owner
->PrepareDC(dc
);
1023 wxPoint pos
= event
.GetPosition();
1024 long x
= dc
.DeviceToLogicalX( pos
.x
);
1025 long y
= dc
.DeviceToLogicalY( pos
.y
);
1027 str
.Printf( wxT("Current mouse position: %d,%d"), (int)x
, (int)y
);
1028 m_owner
->SetStatusText( str
);
1031 #endif // wxUSE_STATUSBAR
1034 // ----------------------------------------------------------------------------
1036 // ----------------------------------------------------------------------------
1038 // the event tables connect the wxWidgets events with the functions (event
1039 // handlers) which process them. It can be also done at run-time, but for the
1040 // simple menu events like this the static method is much simpler.
1041 BEGIN_EVENT_TABLE(MyFrame
, wxFrame
)
1042 EVT_MENU (File_Quit
, MyFrame::OnQuit
)
1043 EVT_MENU (File_About
, MyFrame::OnAbout
)
1044 EVT_MENU (File_Clip
, MyFrame::OnClip
)
1046 EVT_MENU_RANGE(MenuShow_First
, MenuShow_Last
, MyFrame::OnShow
)
1048 EVT_MENU_RANGE(MenuOption_First
, MenuOption_Last
, MyFrame::OnOption
)
1051 // frame constructor
1052 MyFrame::MyFrame(const wxString
& title
, const wxPoint
& pos
, const wxSize
& size
)
1053 : wxFrame((wxFrame
*)NULL
, wxID_ANY
, title
, pos
, size
,
1054 wxDEFAULT_FRAME_STYLE
| wxNO_FULL_REPAINT_ON_RESIZE
)
1056 // set the frame icon
1057 SetIcon(wxICON(mondrian
));
1059 wxMenu
*menuFile
= new wxMenu
;
1060 menuFile
->Append(File_ShowDefault
, _T("&Default screen\tF1"));
1061 menuFile
->Append(File_ShowText
, _T("&Text screen\tF2"));
1062 menuFile
->Append(File_ShowLines
, _T("&Lines screen\tF3"));
1063 menuFile
->Append(File_ShowBrushes
, _T("&Brushes screen\tF4"));
1064 menuFile
->Append(File_ShowPolygons
, _T("&Polygons screen\tF5"));
1065 menuFile
->Append(File_ShowMask
, _T("&Mask screen\tF6"));
1066 menuFile
->Append(File_ShowOps
, _T("&ROP screen\tF7"));
1067 menuFile
->Append(File_ShowRegions
, _T("Re&gions screen\tF8"));
1068 menuFile
->Append(File_ShowCircles
, _T("&Circles screen\tF9"));
1069 menuFile
->AppendSeparator();
1070 menuFile
->AppendCheckItem(File_Clip
, _T("&Clip\tCtrl-C"), _T("Clip/unclip drawing"));
1071 menuFile
->AppendSeparator();
1072 menuFile
->Append(File_About
, _T("&About...\tCtrl-A"), _T("Show about dialog"));
1073 menuFile
->AppendSeparator();
1074 menuFile
->Append(File_Quit
, _T("E&xit\tAlt-X"), _T("Quit this program"));
1076 wxMenu
*menuMapMode
= new wxMenu
;
1077 menuMapMode
->Append( MapMode_Text
, _T("&TEXT map mode") );
1078 menuMapMode
->Append( MapMode_Lometric
, _T("&LOMETRIC map mode") );
1079 menuMapMode
->Append( MapMode_Twips
, _T("T&WIPS map mode") );
1080 menuMapMode
->Append( MapMode_Points
, _T("&POINTS map mode") );
1081 menuMapMode
->Append( MapMode_Metric
, _T("&METRIC map mode") );
1083 wxMenu
*menuUserScale
= new wxMenu
;
1084 menuUserScale
->Append( UserScale_StretchHoriz
, _T("Stretch &horizontally\tCtrl-H") );
1085 menuUserScale
->Append( UserScale_ShrinkHoriz
, _T("Shrin&k horizontally\tCtrl-G") );
1086 menuUserScale
->Append( UserScale_StretchVertic
, _T("Stretch &vertically\tCtrl-V") );
1087 menuUserScale
->Append( UserScale_ShrinkVertic
, _T("&Shrink vertically\tCtrl-W") );
1088 menuUserScale
->AppendSeparator();
1089 menuUserScale
->Append( UserScale_Restore
, _T("&Restore to normal\tCtrl-0") );
1091 wxMenu
*menuAxis
= new wxMenu
;
1092 menuAxis
->AppendCheckItem( AxisMirror_Horiz
, _T("Mirror horizontally\tCtrl-M") );
1093 menuAxis
->AppendCheckItem( AxisMirror_Vertic
, _T("Mirror vertically\tCtrl-N") );
1095 wxMenu
*menuLogical
= new wxMenu
;
1096 menuLogical
->Append( LogicalOrigin_MoveDown
, _T("Move &down\tCtrl-D") );
1097 menuLogical
->Append( LogicalOrigin_MoveUp
, _T("Move &up\tCtrl-U") );
1098 menuLogical
->Append( LogicalOrigin_MoveLeft
, _T("Move &right\tCtrl-L") );
1099 menuLogical
->Append( LogicalOrigin_MoveRight
, _T("Move &left\tCtrl-R") );
1100 menuLogical
->AppendSeparator();
1101 menuLogical
->Append( LogicalOrigin_Set
, _T("Set to (&100, 100)\tShift-Ctrl-1") );
1102 menuLogical
->Append( LogicalOrigin_Restore
, _T("&Restore to normal\tShift-Ctrl-0") );
1104 wxMenu
*menuColour
= new wxMenu
;
1106 menuColour
->Append( Colour_TextForeground
, _T("Text &foreground...") );
1107 menuColour
->Append( Colour_TextBackground
, _T("Text &background...") );
1108 menuColour
->Append( Colour_Background
, _T("Background &colour...") );
1109 #endif // wxUSE_COLOURDLG
1110 menuColour
->AppendCheckItem( Colour_BackgroundMode
, _T("&Opaque/transparent\tCtrl-B") );
1111 menuColour
->AppendCheckItem( Colour_TextureBackgound
, _T("Draw textured back&ground\tCtrl-T") );
1113 // now append the freshly created menu to the menu bar...
1114 wxMenuBar
*menuBar
= new wxMenuBar
;
1115 menuBar
->Append(menuFile
, _T("&File"));
1116 menuBar
->Append(menuMapMode
, _T("&Mode"));
1117 menuBar
->Append(menuUserScale
, _T("&Scale"));
1118 menuBar
->Append(menuAxis
, _T("&Axis"));
1119 menuBar
->Append(menuLogical
, _T("&Origin"));
1120 menuBar
->Append(menuColour
, _T("&Colours"));
1122 // ... and attach this menu bar to the frame
1123 SetMenuBar(menuBar
);
1127 SetStatusText(_T("Welcome to wxWidgets!"));
1128 #endif // wxUSE_STATUSBAR
1130 m_mapMode
= wxMM_TEXT
;
1133 m_xLogicalOrigin
= 0;
1134 m_yLogicalOrigin
= 0;
1136 m_yAxisReversed
= false;
1137 m_backgroundMode
= wxSOLID
;
1138 m_colourForeground
= *wxRED
;
1139 m_colourBackground
= *wxBLUE
;
1140 m_textureBackground
= false;
1142 m_canvas
= new MyCanvas( this );
1143 m_canvas
->SetScrollbars( 10, 10, 100, 240 );
1148 void MyFrame::OnQuit(wxCommandEvent
& WXUNUSED(event
))
1150 // true is to force the frame to close
1154 void MyFrame::OnAbout(wxCommandEvent
& WXUNUSED(event
))
1157 msg
.Printf( wxT("This is the about dialog of the drawing sample.\n")
1158 wxT("This sample tests various primitive drawing functions\n")
1159 wxT("(without any attempts to prevent flicker).\n")
1160 wxT("Copyright (c) Robert Roebling 1999")
1163 wxMessageBox(msg
, _T("About Drawing"), wxOK
| wxICON_INFORMATION
, this);
1166 void MyFrame::OnClip(wxCommandEvent
& event
)
1168 m_canvas
->Clip(event
.IsChecked());
1171 void MyFrame::OnShow(wxCommandEvent
& event
)
1173 m_canvas
->ToShow((ScreenToShow
)(event
.GetId() - MenuShow_First
));
1176 void MyFrame::OnOption(wxCommandEvent
& event
)
1178 switch (event
.GetId())
1181 m_mapMode
= wxMM_TEXT
;
1183 case MapMode_Lometric
:
1184 m_mapMode
= wxMM_LOMETRIC
;
1187 m_mapMode
= wxMM_TWIPS
;
1189 case MapMode_Points
:
1190 m_mapMode
= wxMM_POINTS
;
1192 case MapMode_Metric
:
1193 m_mapMode
= wxMM_METRIC
;
1196 case LogicalOrigin_MoveDown
:
1197 m_yLogicalOrigin
+= 10;
1199 case LogicalOrigin_MoveUp
:
1200 m_yLogicalOrigin
-= 10;
1202 case LogicalOrigin_MoveLeft
:
1203 m_xLogicalOrigin
+= 10;
1205 case LogicalOrigin_MoveRight
:
1206 m_xLogicalOrigin
-= 10;
1208 case LogicalOrigin_Set
:
1210 m_yLogicalOrigin
= -100;
1212 case LogicalOrigin_Restore
:
1214 m_yLogicalOrigin
= 0;
1217 case UserScale_StretchHoriz
:
1218 m_xUserScale
*= 1.10;
1220 case UserScale_ShrinkHoriz
:
1221 m_xUserScale
/= 1.10;
1223 case UserScale_StretchVertic
:
1224 m_yUserScale
*= 1.10;
1226 case UserScale_ShrinkVertic
:
1227 m_yUserScale
/= 1.10;
1229 case UserScale_Restore
:
1234 case AxisMirror_Vertic
:
1235 m_yAxisReversed
= !m_yAxisReversed
;
1237 case AxisMirror_Horiz
:
1238 m_xAxisReversed
= !m_xAxisReversed
;
1242 case Colour_TextForeground
:
1243 m_colourForeground
= SelectColour();
1245 case Colour_TextBackground
:
1246 m_colourBackground
= SelectColour();
1248 case Colour_Background
:
1250 wxColour col
= SelectColour();
1253 m_backgroundBrush
.SetColour(col
);
1257 #endif // wxUSE_COLOURDLG
1259 case Colour_BackgroundMode
:
1260 m_backgroundMode
= m_backgroundMode
== wxSOLID
? wxTRANSPARENT
1264 case Colour_TextureBackgound
:
1265 m_textureBackground
= ! m_textureBackground
;
1273 m_canvas
->Refresh();
1276 void MyFrame::PrepareDC(wxDC
& dc
)
1278 dc
.SetLogicalOrigin( m_xLogicalOrigin
, m_yLogicalOrigin
);
1279 dc
.SetAxisOrientation( !m_xAxisReversed
, m_yAxisReversed
);
1280 dc
.SetUserScale( m_xUserScale
, m_yUserScale
);
1281 dc
.SetMapMode( m_mapMode
);
1285 wxColour
MyFrame::SelectColour()
1289 wxColourDialog
dialog(this, &data
);
1291 if ( dialog
.ShowModal() == wxID_OK
)
1293 col
= dialog
.GetColourData().GetColour();
1298 #endif // wxUSE_COLOURDLG