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 // ----------------------------------------------------------------------------
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" wxWindows 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 OnShow(wxCommandEvent
&event
);
119 void OnOption(wxCommandEvent
&event
);
121 wxColour
SelectColour();
122 void PrepareDC(wxDC
& dc
);
124 int m_backgroundMode
;
125 int m_textureBackground
;
129 int m_xLogicalOrigin
;
130 int m_yLogicalOrigin
;
131 bool m_xAxisReversed
,
133 wxColour m_colourForeground
, // these are _text_ colours
135 wxBrush m_backgroundBrush
;
139 // any class wishing to process wxWindows events must use this macro
140 DECLARE_EVENT_TABLE()
143 // define a scrollable canvas for drawing onto
144 class MyCanvas
: public wxScrolledWindow
147 MyCanvas( MyFrame
*parent
);
149 void OnPaint(wxPaintEvent
&event
);
150 void OnMouseMove(wxMouseEvent
&event
);
152 void Show(ScreenToShow show
) { m_show
= show
; Refresh(); }
155 void DrawTestLines( int x
, int y
, int width
, wxDC
&dc
);
156 void DrawTestPoly(wxDC
& dc
);
157 void DrawTestBrushes(wxDC
& dc
);
158 void DrawText(wxDC
& dc
);
159 void DrawImages(wxDC
& dc
);
160 void DrawWithLogicalOps(wxDC
& dc
);
161 void DrawRegions(wxDC
& dc
);
162 void DrawCircles(wxDC
& dc
);
163 void DrawDefault(wxDC
& dc
);
165 void DrawRegionsHelper(wxDC
& dc
, wxCoord x
, bool firstTime
);
171 wxBitmap m_smile_bmp
;
174 DECLARE_EVENT_TABLE()
177 // ----------------------------------------------------------------------------
179 // ----------------------------------------------------------------------------
181 // IDs for the controls and the menu commands
189 File_ShowDefault
= MenuShow_First
,
198 MenuShow_Last
= File_ShowCircles
,
202 MapMode_Text
= MenuOption_First
,
208 UserScale_StretchHoriz
,
209 UserScale_ShrinkHoriz
,
210 UserScale_StretchVertic
,
211 UserScale_ShrinkVertic
,
217 LogicalOrigin_MoveDown
,
218 LogicalOrigin_MoveUp
,
219 LogicalOrigin_MoveLeft
,
220 LogicalOrigin_MoveRight
,
222 LogicalOrigin_Restore
,
224 Colour_TextForeground
,
225 Colour_TextBackground
,
227 Colour_BackgroundMode
,
228 Colour_TextureBackgound
,
230 MenuOption_Last
= Colour_TextureBackgound
233 // ----------------------------------------------------------------------------
234 // event tables and other macros for wxWindows
235 // ----------------------------------------------------------------------------
238 // Create a new application object: this macro will allow wxWindows to create
239 // the application object during program execution (it's better than using a
240 // static object for many reasons) and also declares the accessor function
241 // wxGetApp() which will return the reference of the right type (i.e. MyApp and
245 // ============================================================================
247 // ============================================================================
249 // ----------------------------------------------------------------------------
250 // the application class
251 // ----------------------------------------------------------------------------
253 bool MyApp::LoadImages()
255 gs_bmpNoMask
= new wxBitmap
;
256 gs_bmpWithColMask
= new wxBitmap
;
257 gs_bmpMask
= new wxBitmap
;
258 gs_bmpWithMask
= new wxBitmap
;
259 gs_bmp4
= new wxBitmap
;
260 gs_bmp4_mono
= new wxBitmap
;
261 gs_bmp36
= new wxBitmap
;
267 wxString path
= pathList
.FindValidPath("pat4.bmp");
271 /* 4 colour bitmap */
272 gs_bmp4
->LoadFile(path
, wxBITMAP_TYPE_BMP
);
273 /* turn into mono-bitmap */
274 gs_bmp4_mono
->LoadFile(path
, wxBITMAP_TYPE_BMP
);
275 wxMask
* mask4
= new wxMask(*gs_bmp4_mono
, *wxBLACK
);
276 gs_bmp4_mono
->SetMask(mask4
);
278 path
= pathList
.FindValidPath("pat36.bmp");
281 gs_bmp36
->LoadFile(path
, wxBITMAP_TYPE_BMP
);
282 wxMask
* mask36
= new wxMask(*gs_bmp36
, *wxBLACK
);
283 gs_bmp36
->SetMask(mask36
);
285 path
= pathList
.FindValidPath("image.bmp");
288 gs_bmpNoMask
->LoadFile(path
, wxBITMAP_TYPE_BMP
);
289 gs_bmpWithMask
->LoadFile(path
, wxBITMAP_TYPE_BMP
);
290 gs_bmpWithColMask
->LoadFile(path
, wxBITMAP_TYPE_BMP
);
292 path
= pathList
.FindValidPath("mask.bmp");
295 gs_bmpMask
->LoadFile(path
, wxBITMAP_TYPE_BMP
);
297 wxMask
*mask
= new wxMask(*gs_bmpMask
, *wxBLACK
);
298 gs_bmpWithMask
->SetMask(mask
);
300 mask
= new wxMask(*gs_bmpWithColMask
, *wxWHITE
);
301 gs_bmpWithColMask
->SetMask(mask
);
306 // `Main program' equivalent: the program execution "starts" here
309 // Create the main application window
310 MyFrame
*frame
= new MyFrame("Drawing sample",
311 wxPoint(50, 50), wxSize(550, 340));
313 // Show it and tell the application that it's our main window
319 wxLogError(wxT("Can't load one of the bitmap files needed ")
320 wxT("for this sample from the current or parent ")
321 wxT("directory, please copy them there."));
333 void MyApp::DeleteBitmaps()
336 delete gs_bmpWithColMask
;
338 delete gs_bmpWithMask
;
344 gs_bmpWithColMask
= NULL
;
346 gs_bmpWithMask
= NULL
;
352 // ----------------------------------------------------------------------------
354 // ----------------------------------------------------------------------------
356 // the event tables connect the wxWindows events with the functions (event
357 // handlers) which process them.
358 BEGIN_EVENT_TABLE(MyCanvas
, wxScrolledWindow
)
359 EVT_PAINT (MyCanvas::OnPaint
)
360 EVT_MOTION (MyCanvas::OnMouseMove
)
365 MyCanvas::MyCanvas(MyFrame
*parent
)
366 : wxScrolledWindow(parent
, -1, wxDefaultPosition
, wxDefaultSize
,
367 wxHSCROLL
| wxVSCROLL
| wxNO_FULL_REPAINT_ON_RESIZE
)
370 m_show
= Show_Default
;
371 m_smile_bmp
= wxBitmap(smile_xpm
);
372 m_std_icon
= wxArtProvider::GetIcon(wxART_INFORMATION
);
375 void MyCanvas::DrawTestBrushes(wxDC
& dc
)
377 static const wxCoord WIDTH
= 200;
378 static const wxCoord HEIGHT
= 80;
383 dc
.SetBrush(wxBrush(*wxGREEN
, wxSOLID
));
384 dc
.DrawRectangle(x
, y
, WIDTH
, HEIGHT
);
385 dc
.DrawText("Solid green", x
+ 10, y
+ 10);
388 dc
.SetBrush(wxBrush(*wxRED
, wxCROSSDIAG_HATCH
));
389 dc
.DrawRectangle(x
, y
, WIDTH
, HEIGHT
);
390 dc
.DrawText("Hatched red", x
+ 10, y
+ 10);
393 dc
.SetBrush(wxBrush(*gs_bmpMask
));
394 dc
.DrawRectangle(x
, y
, WIDTH
, HEIGHT
);
395 dc
.DrawText("Stipple mono", x
+ 10, y
+ 10);
398 dc
.SetBrush(wxBrush(*gs_bmpNoMask
));
399 dc
.DrawRectangle(x
, y
, WIDTH
, HEIGHT
);
400 dc
.DrawText("Stipple colour", x
+ 10, y
+ 10);
403 void MyCanvas::DrawTestPoly(wxDC
& dc
)
405 wxBrush
brushHatch(*wxRED
, wxFDIAGONAL_HATCH
);
406 dc
.SetBrush(brushHatch
);
409 star
[0] = wxPoint(100, 60);
410 star
[1] = wxPoint(60, 150);
411 star
[2] = wxPoint(160, 100);
412 star
[3] = wxPoint(40, 100);
413 star
[4] = wxPoint(140, 150);
415 dc
.DrawText("You should see two (irregular) stars below, the left one "
417 dc
.DrawText("except for the central region and the right "
418 "one entirely hatched", 10, 30);
420 dc
.DrawPolygon(WXSIZEOF(star
), star
);
421 dc
.DrawPolygon(WXSIZEOF(star
), star
, 160, 0, wxWINDING_RULE
);
424 void MyCanvas::DrawTestLines( int x
, int y
, int width
, wxDC
&dc
)
426 dc
.SetPen( wxPen( wxT("black"), width
, wxSOLID
) );
427 dc
.SetBrush( *wxRED_BRUSH
);
428 dc
.DrawText(wxString::Format(wxT("Testing lines of width %d"), width
), x
+ 10, y
- 10);
429 dc
.DrawRectangle( x
+10, y
+10, 100, 190 );
431 dc
.DrawText("Solid/dot/short dash/long dash/dot dash", x
+ 150, y
+ 10);
432 dc
.SetPen( wxPen( wxT("black"), width
, wxSOLID
) );
433 dc
.DrawLine( x
+20, y
+20, 100, y
+20 );
434 dc
.SetPen( wxPen( wxT("black"), width
, wxDOT
) );
435 dc
.DrawLine( x
+20, y
+30, 100, y
+30 );
436 dc
.SetPen( wxPen( wxT("black"), width
, wxSHORT_DASH
) );
437 dc
.DrawLine( x
+20, y
+40, 100, y
+40 );
438 dc
.SetPen( wxPen( wxT("black"), width
, wxLONG_DASH
) );
439 dc
.DrawLine( x
+20, y
+50, 100, y
+50 );
440 dc
.SetPen( wxPen( wxT("black"), width
, wxDOT_DASH
) );
441 dc
.DrawLine( x
+20, y
+60, 100, y
+60 );
443 dc
.DrawText("Misc hatches", x
+ 150, y
+ 70);
444 dc
.SetPen( wxPen( wxT("black"), width
, wxBDIAGONAL_HATCH
) );
445 dc
.DrawLine( x
+20, y
+70, 100, y
+70 );
446 dc
.SetPen( wxPen( wxT("black"), width
, wxCROSSDIAG_HATCH
) );
447 dc
.DrawLine( x
+20, y
+80, 100, y
+80 );
448 dc
.SetPen( wxPen( wxT("black"), width
, wxFDIAGONAL_HATCH
) );
449 dc
.DrawLine( x
+20, y
+90, 100, y
+90 );
450 dc
.SetPen( wxPen( wxT("black"), width
, wxCROSS_HATCH
) );
451 dc
.DrawLine( x
+20, y
+100, 100, y
+100 );
452 dc
.SetPen( wxPen( wxT("black"), width
, wxHORIZONTAL_HATCH
) );
453 dc
.DrawLine( x
+20, y
+110, 100, y
+110 );
454 dc
.SetPen( wxPen( wxT("black"), width
, wxVERTICAL_HATCH
) );
455 dc
.DrawLine( x
+20, y
+120, 100, y
+120 );
457 dc
.DrawText("User dash", x
+ 150, y
+ 140);
458 wxPen
ud( wxT("black"), width
, wxUSER_DASH
);
461 ud
.SetDashes( 1, dash1
);
462 dc
.DrawLine( x
+20, y
+140, 100, y
+140 );
464 ud
.SetDashes( 1, dash1
);
465 dc
.DrawLine( x
+20, y
+150, 100, y
+150 );
467 ud
.SetDashes( 1, dash1
);
468 dc
.DrawLine( x
+20, y
+160, 100, y
+160 );
470 ud
.SetDashes( 1, dash1
);
471 dc
.DrawLine( x
+20, y
+170, 100, y
+170 );
474 void MyCanvas::DrawDefault(wxDC
& dc
)
477 dc
.DrawCircle(0, 0, 10);
479 //flood fill using brush, starting at 1,1 and replacing whatever colour we find there
480 dc
.SetBrush(wxBrush(wxColour(128,128,0), wxSOLID
));
482 dc
.GetPixel(1,1, &tmpColour
);
483 dc
.FloodFill(1,1, tmpColour
, wxFLOOD_SURFACE
);
485 dc
.DrawCheckMark(5, 80, 15, 15);
486 dc
.DrawCheckMark(25, 80, 30, 30);
487 dc
.DrawCheckMark(60, 80, 60, 60);
489 // this is the test for "blitting bitmap into DC damages selected brush" bug
490 wxCoord rectSize
= m_std_icon
.GetWidth() + 10;
492 dc
.SetPen(*wxTRANSPARENT_PEN
);
493 dc
.SetBrush( *wxGREEN_BRUSH
);
494 dc
.DrawRectangle(x
, 10, rectSize
, rectSize
);
495 dc
.DrawBitmap(m_std_icon
, x
+ 5, 15, TRUE
);
497 dc
.DrawRectangle(x
, 10, rectSize
, rectSize
);
498 dc
.DrawIcon(m_std_icon
, x
+ 5, 15);
500 dc
.DrawRectangle(x
, 10, rectSize
, rectSize
);
502 // test for "transparent" bitmap drawing (it intersects with the last
504 //dc.SetBrush( *wxTRANSPARENT_BRUSH );
506 if (m_smile_bmp
.Ok())
507 dc
.DrawBitmap(m_smile_bmp
, x
+ rectSize
- 20, rectSize
- 10, TRUE
);
509 dc
.SetBrush( *wxBLACK_BRUSH
);
510 dc
.DrawRectangle( 0, 160, 1000, 300 );
513 wxBitmap
bitmap(20,70);
515 memdc
.SelectObject( bitmap
);
516 memdc
.SetBrush( *wxBLACK_BRUSH
);
517 memdc
.SetPen( *wxWHITE_PEN
);
518 memdc
.DrawRectangle(0,0,20,70);
519 memdc
.DrawLine( 10,0,10,70 );
522 wxPen pen
= *wxRED_PEN
;
524 memdc
.DrawLine( 10, 5,10, 5 );
525 memdc
.DrawLine( 10,10,11,10 );
526 memdc
.DrawLine( 10,15,12,15 );
527 memdc
.DrawLine( 10,20,13,20 );
530 memdc.SetPen(*wxRED_PEN);
531 memdc.DrawLine( 12, 5,12, 5 );
532 memdc.DrawLine( 12,10,13,10 );
533 memdc.DrawLine( 12,15,14,15 );
534 memdc.DrawLine( 12,20,15,20 );
538 memdc
.DrawLine( 10,25,10,25 );
539 memdc
.DrawLine( 10,30, 9,30 );
540 memdc
.DrawLine( 10,35, 8,35 );
541 memdc
.DrawLine( 10,40, 7,40 );
544 dc
.SetPen(*wxWHITE_PEN
);
545 memdc
.SetLogicalFunction( wxINVERT
);
546 memdc
.SetPen( *wxWHITE_PEN
);
547 memdc
.DrawLine( 10,50,10,50 );
548 memdc
.DrawLine( 10,55,11,55 );
549 memdc
.DrawLine( 10,60,12,60 );
550 memdc
.DrawLine( 10,65,13,65 );
552 memdc
.DrawLine( 12,50,12,50 );
553 memdc
.DrawLine( 12,55,13,55 );
554 memdc
.DrawLine( 12,60,14,60 );
555 memdc
.DrawLine( 12,65,15,65 );
557 memdc
.SelectObject( wxNullBitmap
);
558 dc
.DrawBitmap( bitmap
, 10, 170 );
559 wxImage image
= bitmap
.ConvertToImage();
560 image
.Rescale( 60,210 );
561 bitmap
= wxBitmap(image
);
562 dc
.DrawBitmap( bitmap
, 50, 170 );
564 // test the rectangle outline drawing - there should be one pixel between
565 // the rect and the lines
566 dc
.SetPen(*wxWHITE_PEN
);
567 dc
.SetBrush( *wxTRANSPARENT_BRUSH
);
568 dc
.DrawRectangle(150, 170, 49, 29);
569 dc
.DrawRectangle(200, 170, 49, 29);
570 dc
.SetPen(*wxWHITE_PEN
);
571 dc
.DrawLine(250, 210, 250, 170);
572 dc
.DrawLine(260, 200, 150, 200);
574 // test the rectangle filled drawing - there should be one pixel between
575 // the rect and the lines
576 dc
.SetPen(*wxTRANSPARENT_PEN
);
577 dc
.SetBrush( *wxWHITE_BRUSH
);
578 dc
.DrawRectangle(300, 170, 49, 29);
579 dc
.DrawRectangle(350, 170, 49, 29);
580 dc
.SetPen(*wxWHITE_PEN
);
581 dc
.DrawLine(400, 170, 400, 210);
582 dc
.DrawLine(300, 200, 410, 200);
584 // a few more tests of this kind
585 dc
.SetPen(*wxRED_PEN
);
586 dc
.SetBrush( *wxWHITE_BRUSH
);
587 dc
.DrawRectangle(300, 220, 1, 1);
588 dc
.DrawRectangle(310, 220, 2, 2);
589 dc
.DrawRectangle(320, 220, 3, 3);
590 dc
.DrawRectangle(330, 220, 4, 4);
592 dc
.SetPen(*wxTRANSPARENT_PEN
);
593 dc
.SetBrush( *wxWHITE_BRUSH
);
594 dc
.DrawRectangle(300, 230, 1, 1);
595 dc
.DrawRectangle(310, 230, 2, 2);
596 dc
.DrawRectangle(320, 230, 3, 3);
597 dc
.DrawRectangle(330, 230, 4, 4);
599 // and now for filled rect with outline
600 dc
.SetPen(*wxRED_PEN
);
601 dc
.SetBrush( *wxWHITE_BRUSH
);
602 dc
.DrawRectangle(500, 170, 49, 29);
603 dc
.DrawRectangle(550, 170, 49, 29);
604 dc
.SetPen(*wxWHITE_PEN
);
605 dc
.DrawLine(600, 170, 600, 210);
606 dc
.DrawLine(500, 200, 610, 200);
608 // test the rectangle outline drawing - there should be one pixel between
609 // the rect and the lines
610 dc
.SetPen(*wxWHITE_PEN
);
611 dc
.SetBrush( *wxTRANSPARENT_BRUSH
);
612 dc
.DrawRoundedRectangle(150, 270, 49, 29, 6);
613 dc
.DrawRoundedRectangle(200, 270, 49, 29, 6);
614 dc
.SetPen(*wxWHITE_PEN
);
615 dc
.DrawLine(250, 270, 250, 310);
616 dc
.DrawLine(150, 300, 260, 300);
618 // test the rectangle filled drawing - there should be one pixel between
619 // the rect and the lines
620 dc
.SetPen(*wxTRANSPARENT_PEN
);
621 dc
.SetBrush( *wxWHITE_BRUSH
);
622 dc
.DrawRoundedRectangle(300, 270, 49, 29, 6);
623 dc
.DrawRoundedRectangle(350, 270, 49, 29, 6);
624 dc
.SetPen(*wxWHITE_PEN
);
625 dc
.DrawLine(400, 270, 400, 310);
626 dc
.DrawLine(300, 300, 410, 300);
628 // Added by JACS to demonstrate bizarre behaviour.
629 // With a size of 70, we get a missing red RHS,
630 // and the hight is too small, so we get yellow
631 // showing. With a size of 40, it draws as expected:
632 // it just shows a white rectangle with red outline.
634 int totalHeight
= 70;
635 wxBitmap
bitmap2(totalWidth
, totalHeight
);
638 memdc2
.SelectObject(bitmap2
);
640 wxBrush
yellowBrush(wxColour(255, 255, 0), wxSOLID
);
641 memdc2
.SetBackground(yellowBrush
);
644 wxPen
yellowPen(wxColour(255, 255, 0), 1, wxSOLID
);
646 // Now draw a white rectangle with red outline. It should
647 // entirely eclipse the yellow background.
648 memdc2
.SetPen(*wxRED_PEN
);
649 memdc2
.SetBrush(*wxWHITE_BRUSH
);
651 memdc2
.DrawRectangle(0, 0, totalWidth
, totalHeight
);
653 memdc2
.SetPen(wxNullPen
);
654 memdc2
.SetBrush(wxNullBrush
);
655 memdc2
.SelectObject(wxNullBitmap
);
657 dc
.DrawBitmap(bitmap2
, 500, 270);
659 // Repeat, but draw directly on dc
660 // Draw a yellow rectangle filling the bitmap
662 x
= 600; int y
= 270;
663 dc
.SetPen(yellowPen
);
664 dc
.SetBrush(yellowBrush
);
665 dc
.DrawRectangle(x
, y
, totalWidth
, totalHeight
);
667 // Now draw a white rectangle with red outline. It should
668 // entirely eclipse the yellow background.
669 dc
.SetPen(*wxRED_PEN
);
670 dc
.SetBrush(*wxWHITE_BRUSH
);
672 dc
.DrawRectangle(x
, y
, totalWidth
, totalHeight
);
675 void MyCanvas::DrawText(wxDC
& dc
)
677 // set underlined font for testing
678 dc
.SetFont( wxFont(12, wxMODERN
, wxNORMAL
, wxNORMAL
, TRUE
) );
679 dc
.DrawText( "This is text", 110, 10 );
680 dc
.DrawRotatedText( "That is text", 20, 10, -45 );
682 // use wxSWISS_FONT and not wxNORMAL_FONT as the latter can't be rotated
683 // under Win9x (it is not TrueType)
684 dc
.SetFont( *wxSWISS_FONT
);
687 dc
.SetBackgroundMode(wxTRANSPARENT
);
689 for ( int n
= -180; n
< 180; n
+= 30 )
691 text
.Printf(wxT(" %d rotated text"), n
);
692 dc
.DrawRotatedText(text
, 400, 400, n
);
695 dc
.SetFont( wxFont( 18, wxSWISS
, wxNORMAL
, wxNORMAL
) );
697 dc
.DrawText( "This is Swiss 18pt text.", 110, 40 );
702 dc
.GetTextExtent( "This is Swiss 18pt text.", &length
, &height
, &descent
);
703 text
.Printf( wxT("Dimensions are length %ld, height %ld, descent %ld"), length
, height
, descent
);
704 dc
.DrawText( text
, 110, 80 );
706 text
.Printf( wxT("CharHeight() returns: %d"), dc
.GetCharHeight() );
707 dc
.DrawText( text
, 110, 120 );
709 dc
.DrawRectangle( 100, 40, 4, height
);
711 // test the logical function effect
713 dc
.SetLogicalFunction(wxINVERT
);
714 dc
.DrawText( "There should be no text below", 110, 150 );
715 dc
.DrawRectangle( 110, y
, 100, height
);
717 // twice drawn inverted should result in invisible
719 dc
.DrawText( "Invisible text", 110, y
);
720 dc
.DrawRectangle( 110, y
, 100, height
);
721 dc
.DrawText( "Invisible text", 110, y
);
722 dc
.DrawRectangle( 110, y
, 100, height
);
723 dc
.SetLogicalFunction(wxCOPY
);
726 dc
.DrawRectangle( 110, y
, 100, height
);
727 dc
.DrawText( "Visible text", 110, y
);
734 } rasterOperations
[] =
736 { wxT("wxAND"), wxAND
},
737 { wxT("wxAND_INVERT"), wxAND_INVERT
},
738 { wxT("wxAND_REVERSE"), wxAND_REVERSE
},
739 { wxT("wxCLEAR"), wxCLEAR
},
740 { wxT("wxCOPY"), wxCOPY
},
741 { wxT("wxEQUIV"), wxEQUIV
},
742 { wxT("wxINVERT"), wxINVERT
},
743 { wxT("wxNAND"), wxNAND
},
744 { wxT("wxNO_OP"), wxNO_OP
},
745 { wxT("wxOR"), wxOR
},
746 { wxT("wxOR_INVERT"), wxOR_INVERT
},
747 { wxT("wxOR_REVERSE"), wxOR_REVERSE
},
748 { wxT("wxSET"), wxSET
},
749 { wxT("wxSRC_INVERT"), wxSRC_INVERT
},
750 { wxT("wxXOR"), wxXOR
},
753 void MyCanvas::DrawImages(wxDC
& dc
)
755 dc
.DrawText("original image", 0, 0);
756 dc
.DrawBitmap(*gs_bmpNoMask
, 0, 20, 0);
757 dc
.DrawText("with colour mask", 0, 100);
758 dc
.DrawBitmap(*gs_bmpWithColMask
, 0, 120, TRUE
);
759 dc
.DrawText("the mask image", 0, 200);
760 dc
.DrawBitmap(*gs_bmpMask
, 0, 220, 0);
761 dc
.DrawText("masked image", 0, 300);
762 dc
.DrawBitmap(*gs_bmpWithMask
, 0, 320, TRUE
);
764 int cx
= gs_bmpWithColMask
->GetWidth(),
765 cy
= gs_bmpWithColMask
->GetHeight();
768 for ( size_t n
= 0; n
< WXSIZEOF(rasterOperations
); n
++ )
770 wxCoord x
= 120 + 150*(n%4
),
773 dc
.DrawText(rasterOperations
[n
].name
, x
, y
- 20);
774 memDC
.SelectObject(*gs_bmpWithColMask
);
775 dc
.Blit(x
, y
, cx
, cy
, &memDC
, 0, 0, rasterOperations
[n
].rop
, TRUE
);
779 void MyCanvas::DrawWithLogicalOps(wxDC
& dc
)
781 static const wxCoord w
= 60;
782 static const wxCoord h
= 60;
784 // reuse the text colour here
785 dc
.SetPen(wxPen(m_owner
->m_colourForeground
, 1, wxSOLID
));
786 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
789 for ( n
= 0; n
< WXSIZEOF(rasterOperations
); n
++ )
791 wxCoord x
= 20 + 150*(n%4
),
794 dc
.DrawText(rasterOperations
[n
].name
, x
, y
- 20);
795 dc
.SetLogicalFunction(rasterOperations
[n
].rop
);
796 dc
.DrawRectangle(x
, y
, w
, h
);
797 dc
.DrawLine(x
, y
, x
+ w
, y
+ h
);
798 dc
.DrawLine(x
+ w
, y
, x
, y
+ h
);
801 // now some filled rectangles
802 dc
.SetBrush(wxBrush(m_owner
->m_colourForeground
, wxSOLID
));
804 for ( n
= 0; n
< WXSIZEOF(rasterOperations
); n
++ )
806 wxCoord x
= 20 + 150*(n%4
),
809 dc
.DrawText(rasterOperations
[n
].name
, x
, y
- 20);
810 dc
.SetLogicalFunction(rasterOperations
[n
].rop
);
811 dc
.DrawRectangle(x
, y
, w
, h
);
815 void MyCanvas::DrawCircles(wxDC
& dc
)
821 dc
.DrawText("Some circles", 0, y
);
822 dc
.DrawCircle(x
, y
, r
);
823 dc
.DrawCircle(x
+ 2*r
, y
, r
);
824 dc
.DrawCircle(x
+ 4*r
, y
, r
);
827 dc
.DrawText("And ellipses", 0, y
);
828 dc
.DrawEllipse(x
- r
, y
, 2*r
, r
);
829 dc
.DrawEllipse(x
+ r
, y
, 2*r
, r
);
830 dc
.DrawEllipse(x
+ 3*r
, y
, 2*r
, r
);
833 dc
.DrawText("And arcs", 0, y
);
834 dc
.DrawArc(x
- r
, y
, x
+ r
, y
, x
, y
);
835 dc
.DrawArc(x
+ 4*r
, y
, x
+ 2*r
, y
, x
+ 3*r
, y
);
836 dc
.DrawArc(x
+ 5*r
, y
, x
+ 5*r
, y
, x
+ 6*r
, y
);
839 dc
.DrawEllipticArc(x
- r
, y
, 2*r
, r
, 0, 90);
840 dc
.DrawEllipticArc(x
+ r
, y
, 2*r
, r
, 90, 180);
841 dc
.DrawEllipticArc(x
+ 3*r
, y
, 2*r
, r
, 180, 270);
842 dc
.DrawEllipticArc(x
+ 5*r
, y
, 2*r
, r
, 270, 360);
845 void MyCanvas::DrawRegions(wxDC
& dc
)
847 dc
.DrawText("You should see a red rect partly covered by a cyan one "
848 "on the left", 10, 5);
849 dc
.DrawText("and 5 smileys from which 4 are partially clipped on the right",
850 10, 5 + dc
.GetCharHeight());
851 dc
.DrawText("The second copy should be identical but right part of it "
852 "should be offset by 10 pixels.",
853 10, 5 + 2*dc
.GetCharHeight());
855 DrawRegionsHelper(dc
, 10, TRUE
);
856 DrawRegionsHelper(dc
, 350, FALSE
);
859 void MyCanvas::DrawRegionsHelper(wxDC
& dc
, wxCoord x
, bool firstTime
)
863 dc
.DestroyClippingRegion();
864 dc
.SetBrush( *wxWHITE_BRUSH
);
865 dc
.SetPen( *wxTRANSPARENT_PEN
);
866 dc
.DrawRectangle( x
, y
, 310, 310 );
868 dc
.SetClippingRegion( x
+ 10, y
+ 10, 100, 270 );
870 dc
.SetBrush( *wxRED_BRUSH
);
871 dc
.DrawRectangle( x
, y
, 310, 310 );
873 dc
.SetClippingRegion( x
+ 10, y
+ 10, 100, 100 );
875 dc
.SetBrush( *wxCYAN_BRUSH
);
876 dc
.DrawRectangle( x
, y
, 310, 310 );
878 dc
.DestroyClippingRegion();
880 wxRegion
region(x
+ 110, y
+ 20, 100, 270);
883 region
.Offset(10, 10);
885 dc
.SetClippingRegion(region
);
887 dc
.SetBrush( *wxGREY_BRUSH
);
888 dc
.DrawRectangle( x
, y
, 310, 310 );
890 if (m_smile_bmp
.Ok())
892 dc
.DrawBitmap( m_smile_bmp
, x
+ 150, y
+ 150, TRUE
);
893 dc
.DrawBitmap( m_smile_bmp
, x
+ 130, y
+ 10, TRUE
);
894 dc
.DrawBitmap( m_smile_bmp
, x
+ 130, y
+ 280, TRUE
);
895 dc
.DrawBitmap( m_smile_bmp
, x
+ 100, y
+ 70, TRUE
);
896 dc
.DrawBitmap( m_smile_bmp
, x
+ 200, y
+ 70, TRUE
);
900 void MyCanvas::OnPaint(wxPaintEvent
&WXUNUSED(event
))
905 m_owner
->PrepareDC(dc
);
907 dc
.SetBackgroundMode( m_owner
->m_backgroundMode
);
908 if ( m_owner
->m_backgroundBrush
.Ok() )
909 dc
.SetBackground( m_owner
->m_backgroundBrush
);
910 if ( m_owner
->m_colourForeground
.Ok() )
911 dc
.SetTextForeground( m_owner
->m_colourForeground
);
912 if ( m_owner
->m_colourBackground
.Ok() )
913 dc
.SetTextBackground( m_owner
->m_colourBackground
);
915 if ( m_owner
->m_textureBackground
) {
916 if ( ! m_owner
->m_backgroundBrush
.Ok() ) {
917 wxBrush
b(wxColour(0,128,0), wxSOLID
);
924 if ( m_owner
->m_textureBackground
) {
925 dc
.SetPen(*wxMEDIUM_GREY_PEN
);
926 for (int i
=0; i
<200; i
++)
927 dc
.DrawLine(0, i
*10, i
*10, 0);
949 DrawTestLines( 0, 100, 0, dc
);
950 DrawTestLines( 0, 320, 1, dc
);
951 DrawTestLines( 0, 540, 2, dc
);
952 DrawTestLines( 0, 760, 6, dc
);
968 DrawWithLogicalOps(dc
);
973 void MyCanvas::OnMouseMove(wxMouseEvent
&event
)
977 m_owner
->PrepareDC(dc
);
979 wxPoint pos
= event
.GetPosition();
980 long x
= dc
.DeviceToLogicalX( pos
.x
);
981 long y
= dc
.DeviceToLogicalY( pos
.y
);
983 str
.Printf( wxT("Current mouse position: %d,%d"), (int)x
, (int)y
);
984 m_owner
->SetStatusText( str
);
987 // ----------------------------------------------------------------------------
989 // ----------------------------------------------------------------------------
991 // the event tables connect the wxWindows events with the functions (event
992 // handlers) which process them. It can be also done at run-time, but for the
993 // simple menu events like this the static method is much simpler.
994 BEGIN_EVENT_TABLE(MyFrame
, wxFrame
)
995 EVT_MENU (File_Quit
, MyFrame::OnQuit
)
996 EVT_MENU (File_About
, MyFrame::OnAbout
)
998 EVT_MENU_RANGE(MenuShow_First
, MenuShow_Last
, MyFrame::OnShow
)
1000 EVT_MENU_RANGE(MenuOption_First
, MenuOption_Last
, MyFrame::OnOption
)
1003 // frame constructor
1004 MyFrame::MyFrame(const wxString
& title
, const wxPoint
& pos
, const wxSize
& size
)
1005 : wxFrame((wxFrame
*)NULL
, -1, title
, pos
, size
,
1006 wxDEFAULT_FRAME_STYLE
| wxNO_FULL_REPAINT_ON_RESIZE
)
1008 // set the frame icon
1009 SetIcon(wxICON(mondrian
));
1011 wxMenu
*menuFile
= new wxMenu
;
1012 menuFile
->Append(File_ShowDefault
, "&Default screen\tF1");
1013 menuFile
->Append(File_ShowText
, "&Text screen\tF2");
1014 menuFile
->Append(File_ShowLines
, "&Lines screen\tF3");
1015 menuFile
->Append(File_ShowBrushes
, "&Brushes screen\tF4");
1016 menuFile
->Append(File_ShowPolygons
, "&Polygons screen\tF5");
1017 menuFile
->Append(File_ShowMask
, "&Mask screen\tF6");
1018 menuFile
->Append(File_ShowOps
, "&ROP screen\tF7");
1019 menuFile
->Append(File_ShowRegions
, "Re&gions screen\tF8");
1020 menuFile
->Append(File_ShowCircles
, "&Circles screen\tF9");
1021 menuFile
->AppendSeparator();
1022 menuFile
->Append(File_About
, "&About...\tCtrl-A", "Show about dialog");
1023 menuFile
->AppendSeparator();
1024 menuFile
->Append(File_Quit
, "E&xit\tAlt-X", "Quit this program");
1026 wxMenu
*menuMapMode
= new wxMenu
;
1027 menuMapMode
->Append( MapMode_Text
, "&TEXT map mode" );
1028 menuMapMode
->Append( MapMode_Lometric
, "&LOMETRIC map mode" );
1029 menuMapMode
->Append( MapMode_Twips
, "T&WIPS map mode" );
1030 menuMapMode
->Append( MapMode_Points
, "&POINTS map mode" );
1031 menuMapMode
->Append( MapMode_Metric
, "&METRIC map mode" );
1033 wxMenu
*menuUserScale
= new wxMenu
;
1034 menuUserScale
->Append( UserScale_StretchHoriz
, "Stretch &horizontally\tCtrl-H" );
1035 menuUserScale
->Append( UserScale_ShrinkHoriz
, "Shrin&k horizontally\tCtrl-G" );
1036 menuUserScale
->Append( UserScale_StretchVertic
, "Stretch &vertically\tCtrl-V" );
1037 menuUserScale
->Append( UserScale_ShrinkVertic
, "&Shrink vertically\tCtrl-W" );
1038 menuUserScale
->AppendSeparator();
1039 menuUserScale
->Append( UserScale_Restore
, "&Restore to normal\tCtrl-0" );
1041 wxMenu
*menuAxis
= new wxMenu
;
1042 menuAxis
->Append( AxisMirror_Horiz
, "Mirror horizontally\tCtrl-M", "", TRUE
);
1043 menuAxis
->Append( AxisMirror_Vertic
, "Mirror vertically\tCtrl-N", "", TRUE
);
1045 wxMenu
*menuLogical
= new wxMenu
;
1046 menuLogical
->Append( LogicalOrigin_MoveDown
, "Move &down\tCtrl-D" );
1047 menuLogical
->Append( LogicalOrigin_MoveUp
, "Move &up\tCtrl-U" );
1048 menuLogical
->Append( LogicalOrigin_MoveLeft
, "Move &right\tCtrl-L" );
1049 menuLogical
->Append( LogicalOrigin_MoveRight
, "Move &left\tCtrl-R" );
1050 menuLogical
->AppendSeparator();
1051 menuLogical
->Append( LogicalOrigin_Set
, "Set to (&100, 100)\tShift-Ctrl-1" );
1052 menuLogical
->Append( LogicalOrigin_Restore
, "&Restore to normal\tShift-Ctrl-0" );
1054 wxMenu
*menuColour
= new wxMenu
;
1055 menuColour
->Append( Colour_TextForeground
, "Text &foreground..." );
1056 menuColour
->Append( Colour_TextBackground
, "Text &background..." );
1057 menuColour
->Append( Colour_Background
, "Background &colour..." );
1058 menuColour
->Append( Colour_BackgroundMode
, "&Opaque/transparent\tCtrl-B", "", TRUE
);
1059 menuColour
->Append( Colour_TextureBackgound
, "Draw textured back&ground\tCtrl-T", "", TRUE
);
1061 // now append the freshly created menu to the menu bar...
1062 wxMenuBar
*menuBar
= new wxMenuBar
;
1063 menuBar
->Append(menuFile
, "&File");
1064 menuBar
->Append(menuMapMode
, "&Mode");
1065 menuBar
->Append(menuUserScale
, "&Scale");
1066 menuBar
->Append(menuAxis
, "&Axis");
1067 menuBar
->Append(menuLogical
, "&Origin");
1068 menuBar
->Append(menuColour
, "&Colours");
1070 // ... and attach this menu bar to the frame
1071 SetMenuBar(menuBar
);
1073 // create a status bar just for fun (by default with 1 pane only)
1075 SetStatusText("Welcome to wxWindows!");
1077 m_mapMode
= wxMM_TEXT
;
1080 m_xLogicalOrigin
= 0;
1081 m_yLogicalOrigin
= 0;
1083 m_yAxisReversed
= FALSE
;
1084 m_backgroundMode
= wxSOLID
;
1085 m_colourForeground
= *wxRED
;
1086 m_colourBackground
= *wxBLUE
;
1087 m_textureBackground
= FALSE
;
1089 m_canvas
= new MyCanvas( this );
1090 m_canvas
->SetScrollbars( 10, 10, 100, 240 );
1095 void MyFrame::OnQuit(wxCommandEvent
& WXUNUSED(event
))
1097 // TRUE is to force the frame to close
1101 void MyFrame::OnAbout(wxCommandEvent
& WXUNUSED(event
))
1104 msg
.Printf( wxT("This is the about dialog of the drawing sample.\n")
1105 wxT("This sample tests various primitive drawing functions\n")
1106 wxT("(without any attempts to prevent flicker).\n")
1107 wxT("Copyright (c) Robert Roebling 1999")
1110 wxMessageBox(msg
, "About Drawing", wxOK
| wxICON_INFORMATION
, this);
1113 void MyFrame::OnShow(wxCommandEvent
& event
)
1115 m_canvas
->Show((ScreenToShow
)(event
.GetId() - MenuShow_First
));
1118 void MyFrame::OnOption(wxCommandEvent
& event
)
1120 switch (event
.GetId())
1123 m_mapMode
= wxMM_TEXT
;
1125 case MapMode_Lometric
:
1126 m_mapMode
= wxMM_LOMETRIC
;
1129 m_mapMode
= wxMM_TWIPS
;
1131 case MapMode_Points
:
1132 m_mapMode
= wxMM_POINTS
;
1134 case MapMode_Metric
:
1135 m_mapMode
= wxMM_METRIC
;
1138 case LogicalOrigin_MoveDown
:
1139 m_yLogicalOrigin
+= 10;
1141 case LogicalOrigin_MoveUp
:
1142 m_yLogicalOrigin
-= 10;
1144 case LogicalOrigin_MoveLeft
:
1145 m_xLogicalOrigin
+= 10;
1147 case LogicalOrigin_MoveRight
:
1148 m_xLogicalOrigin
-= 10;
1150 case LogicalOrigin_Set
:
1152 m_yLogicalOrigin
= -100;
1154 case LogicalOrigin_Restore
:
1156 m_yLogicalOrigin
= 0;
1159 case UserScale_StretchHoriz
:
1160 m_xUserScale
*= 1.10;
1162 case UserScale_ShrinkHoriz
:
1163 m_xUserScale
/= 1.10;
1165 case UserScale_StretchVertic
:
1166 m_yUserScale
*= 1.10;
1168 case UserScale_ShrinkVertic
:
1169 m_yUserScale
/= 1.10;
1171 case UserScale_Restore
:
1176 case AxisMirror_Vertic
:
1177 m_yAxisReversed
= !m_yAxisReversed
;
1179 case AxisMirror_Horiz
:
1180 m_xAxisReversed
= !m_xAxisReversed
;
1183 case Colour_TextForeground
:
1184 m_colourForeground
= SelectColour();
1186 case Colour_TextBackground
:
1187 m_colourBackground
= SelectColour();
1189 case Colour_Background
:
1191 wxColour col
= SelectColour();
1194 m_backgroundBrush
.SetColour(col
);
1198 case Colour_BackgroundMode
:
1199 m_backgroundMode
= m_backgroundMode
== wxSOLID
? wxTRANSPARENT
1203 case Colour_TextureBackgound
:
1204 m_textureBackground
= ! m_textureBackground
;
1212 m_canvas
->Refresh();
1215 void MyFrame::PrepareDC(wxDC
& dc
)
1217 dc
.SetLogicalOrigin( m_xLogicalOrigin
, m_yLogicalOrigin
);
1218 dc
.SetAxisOrientation( !m_xAxisReversed
, m_yAxisReversed
);
1219 dc
.SetUserScale( m_xUserScale
, m_yUserScale
);
1220 dc
.SetMapMode( m_mapMode
);
1223 wxColour
MyFrame::SelectColour()
1227 wxColourDialog
dialog(this, &data
);
1229 if ( dialog
.ShowModal() == wxID_OK
)
1231 col
= dialog
.GetColourData().GetColour();