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" 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 OnClip(wxCommandEvent
& event
);
119 void OnShow(wxCommandEvent
&event
);
120 void OnOption(wxCommandEvent
&event
);
122 wxColour
SelectColour();
123 void PrepareDC(wxDC
& dc
);
125 int m_backgroundMode
;
126 int m_textureBackground
;
130 int m_xLogicalOrigin
;
131 int m_yLogicalOrigin
;
132 bool m_xAxisReversed
,
134 wxColour m_colourForeground
, // these are _text_ colours
136 wxBrush m_backgroundBrush
;
140 // any class wishing to process wxWindows events must use this macro
141 DECLARE_EVENT_TABLE()
144 // define a scrollable canvas for drawing onto
145 class MyCanvas
: public wxScrolledWindow
148 MyCanvas( MyFrame
*parent
);
150 void OnPaint(wxPaintEvent
&event
);
151 void OnMouseMove(wxMouseEvent
&event
);
153 void Show(ScreenToShow show
) { m_show
= show
; Refresh(); }
155 // set or remove the clipping region
156 void Clip(bool clip
) { m_clip
= clip
; Refresh(); }
159 void DrawTestLines( int x
, int y
, int width
, wxDC
&dc
);
160 void DrawTestPoly(wxDC
& dc
);
161 void DrawTestBrushes(wxDC
& dc
);
162 void DrawText(wxDC
& dc
);
163 void DrawImages(wxDC
& dc
);
164 void DrawWithLogicalOps(wxDC
& dc
);
165 void DrawRegions(wxDC
& dc
);
166 void DrawCircles(wxDC
& dc
);
167 void DrawDefault(wxDC
& dc
);
169 void DrawRegionsHelper(wxDC
& dc
, wxCoord x
, bool firstTime
);
175 wxBitmap m_smile_bmp
;
179 DECLARE_EVENT_TABLE()
182 // ----------------------------------------------------------------------------
184 // ----------------------------------------------------------------------------
186 // IDs for the controls and the menu commands
194 File_ShowDefault
= MenuShow_First
,
203 MenuShow_Last
= File_ShowCircles
,
209 MapMode_Text
= MenuOption_First
,
215 UserScale_StretchHoriz
,
216 UserScale_ShrinkHoriz
,
217 UserScale_StretchVertic
,
218 UserScale_ShrinkVertic
,
224 LogicalOrigin_MoveDown
,
225 LogicalOrigin_MoveUp
,
226 LogicalOrigin_MoveLeft
,
227 LogicalOrigin_MoveRight
,
229 LogicalOrigin_Restore
,
231 Colour_TextForeground
,
232 Colour_TextBackground
,
234 Colour_BackgroundMode
,
235 Colour_TextureBackgound
,
237 MenuOption_Last
= Colour_TextureBackgound
240 // ----------------------------------------------------------------------------
241 // event tables and other macros for wxWindows
242 // ----------------------------------------------------------------------------
245 // Create a new application object: this macro will allow wxWindows to create
246 // the application object during program execution (it's better than using a
247 // static object for many reasons) and also declares the accessor function
248 // wxGetApp() which will return the reference of the right type (i.e. MyApp and
252 // ============================================================================
254 // ============================================================================
256 // ----------------------------------------------------------------------------
257 // the application class
258 // ----------------------------------------------------------------------------
260 bool MyApp::LoadImages()
262 gs_bmpNoMask
= new wxBitmap
;
263 gs_bmpWithColMask
= new wxBitmap
;
264 gs_bmpMask
= new wxBitmap
;
265 gs_bmpWithMask
= new wxBitmap
;
266 gs_bmp4
= new wxBitmap
;
267 gs_bmp4_mono
= new wxBitmap
;
268 gs_bmp36
= new wxBitmap
;
274 wxString path
= pathList
.FindValidPath("pat4.bmp");
278 /* 4 colour bitmap */
279 gs_bmp4
->LoadFile(path
, wxBITMAP_TYPE_BMP
);
280 /* turn into mono-bitmap */
281 gs_bmp4_mono
->LoadFile(path
, wxBITMAP_TYPE_BMP
);
282 wxMask
* mask4
= new wxMask(*gs_bmp4_mono
, *wxBLACK
);
283 gs_bmp4_mono
->SetMask(mask4
);
285 path
= pathList
.FindValidPath("pat36.bmp");
288 gs_bmp36
->LoadFile(path
, wxBITMAP_TYPE_BMP
);
289 wxMask
* mask36
= new wxMask(*gs_bmp36
, *wxBLACK
);
290 gs_bmp36
->SetMask(mask36
);
292 path
= pathList
.FindValidPath("image.bmp");
295 gs_bmpNoMask
->LoadFile(path
, wxBITMAP_TYPE_BMP
);
296 gs_bmpWithMask
->LoadFile(path
, wxBITMAP_TYPE_BMP
);
297 gs_bmpWithColMask
->LoadFile(path
, wxBITMAP_TYPE_BMP
);
299 path
= pathList
.FindValidPath("mask.bmp");
302 gs_bmpMask
->LoadFile(path
, wxBITMAP_TYPE_BMP
);
304 wxMask
*mask
= new wxMask(*gs_bmpMask
, *wxBLACK
);
305 gs_bmpWithMask
->SetMask(mask
);
307 mask
= new wxMask(*gs_bmpWithColMask
, *wxWHITE
);
308 gs_bmpWithColMask
->SetMask(mask
);
313 // `Main program' equivalent: the program execution "starts" here
316 // Create the main application window
317 MyFrame
*frame
= new MyFrame("Drawing sample",
318 wxPoint(50, 50), wxSize(550, 340));
320 // Show it and tell the application that it's our main window
326 wxLogError(wxT("Can't load one of the bitmap files needed ")
327 wxT("for this sample from the current or parent ")
328 wxT("directory, please copy them there."));
340 void MyApp::DeleteBitmaps()
343 delete gs_bmpWithColMask
;
345 delete gs_bmpWithMask
;
351 gs_bmpWithColMask
= NULL
;
353 gs_bmpWithMask
= NULL
;
359 // ----------------------------------------------------------------------------
361 // ----------------------------------------------------------------------------
363 // the event tables connect the wxWindows events with the functions (event
364 // handlers) which process them.
365 BEGIN_EVENT_TABLE(MyCanvas
, wxScrolledWindow
)
366 EVT_PAINT (MyCanvas::OnPaint
)
367 EVT_MOTION (MyCanvas::OnMouseMove
)
372 MyCanvas::MyCanvas(MyFrame
*parent
)
373 : wxScrolledWindow(parent
, -1, wxDefaultPosition
, wxDefaultSize
,
374 wxHSCROLL
| wxVSCROLL
| wxNO_FULL_REPAINT_ON_RESIZE
)
377 m_show
= Show_Default
;
378 m_smile_bmp
= wxBitmap(smile_xpm
);
379 m_std_icon
= wxArtProvider::GetIcon(wxART_INFORMATION
);
383 void MyCanvas::DrawTestBrushes(wxDC
& dc
)
385 static const wxCoord WIDTH
= 200;
386 static const wxCoord HEIGHT
= 80;
391 dc
.SetBrush(wxBrush(*wxGREEN
, wxSOLID
));
392 dc
.DrawRectangle(x
, y
, WIDTH
, HEIGHT
);
393 dc
.DrawText("Solid green", x
+ 10, y
+ 10);
396 dc
.SetBrush(wxBrush(*wxRED
, wxCROSSDIAG_HATCH
));
397 dc
.DrawRectangle(x
, y
, WIDTH
, HEIGHT
);
398 dc
.DrawText("Hatched red", x
+ 10, y
+ 10);
401 dc
.SetBrush(wxBrush(*gs_bmpMask
));
402 dc
.DrawRectangle(x
, y
, WIDTH
, HEIGHT
);
403 dc
.DrawText("Stipple mono", x
+ 10, y
+ 10);
406 dc
.SetBrush(wxBrush(*gs_bmpNoMask
));
407 dc
.DrawRectangle(x
, y
, WIDTH
, HEIGHT
);
408 dc
.DrawText("Stipple colour", x
+ 10, y
+ 10);
411 void MyCanvas::DrawTestPoly(wxDC
& dc
)
413 wxBrush
brushHatch(*wxRED
, wxFDIAGONAL_HATCH
);
414 dc
.SetBrush(brushHatch
);
417 star
[0] = wxPoint(100, 60);
418 star
[1] = wxPoint(60, 150);
419 star
[2] = wxPoint(160, 100);
420 star
[3] = wxPoint(40, 100);
421 star
[4] = wxPoint(140, 150);
423 dc
.DrawText("You should see two (irregular) stars below, the left one "
425 dc
.DrawText("except for the central region and the right "
426 "one entirely hatched", 10, 30);
428 dc
.DrawPolygon(WXSIZEOF(star
), star
);
429 dc
.DrawPolygon(WXSIZEOF(star
), star
, 160, 0, wxWINDING_RULE
);
432 void MyCanvas::DrawTestLines( int x
, int y
, int width
, wxDC
&dc
)
434 dc
.SetPen( wxPen( wxT("black"), width
, wxSOLID
) );
435 dc
.SetBrush( *wxRED_BRUSH
);
436 dc
.DrawText(wxString::Format(wxT("Testing lines of width %d"), width
), x
+ 10, y
- 10);
437 dc
.DrawRectangle( x
+10, y
+10, 100, 190 );
439 dc
.DrawText("Solid/dot/short dash/long dash/dot dash", x
+ 150, y
+ 10);
440 dc
.SetPen( wxPen( wxT("black"), width
, wxSOLID
) );
441 dc
.DrawLine( x
+20, y
+20, 100, y
+20 );
442 dc
.SetPen( wxPen( wxT("black"), width
, wxDOT
) );
443 dc
.DrawLine( x
+20, y
+30, 100, y
+30 );
444 dc
.SetPen( wxPen( wxT("black"), width
, wxSHORT_DASH
) );
445 dc
.DrawLine( x
+20, y
+40, 100, y
+40 );
446 dc
.SetPen( wxPen( wxT("black"), width
, wxLONG_DASH
) );
447 dc
.DrawLine( x
+20, y
+50, 100, y
+50 );
448 dc
.SetPen( wxPen( wxT("black"), width
, wxDOT_DASH
) );
449 dc
.DrawLine( x
+20, y
+60, 100, y
+60 );
451 dc
.DrawText("Misc hatches", x
+ 150, y
+ 70);
452 dc
.SetPen( wxPen( wxT("black"), width
, wxBDIAGONAL_HATCH
) );
453 dc
.DrawLine( x
+20, y
+70, 100, y
+70 );
454 dc
.SetPen( wxPen( wxT("black"), width
, wxCROSSDIAG_HATCH
) );
455 dc
.DrawLine( x
+20, y
+80, 100, y
+80 );
456 dc
.SetPen( wxPen( wxT("black"), width
, wxFDIAGONAL_HATCH
) );
457 dc
.DrawLine( x
+20, y
+90, 100, y
+90 );
458 dc
.SetPen( wxPen( wxT("black"), width
, wxCROSS_HATCH
) );
459 dc
.DrawLine( x
+20, y
+100, 100, y
+100 );
460 dc
.SetPen( wxPen( wxT("black"), width
, wxHORIZONTAL_HATCH
) );
461 dc
.DrawLine( x
+20, y
+110, 100, y
+110 );
462 dc
.SetPen( wxPen( wxT("black"), width
, wxVERTICAL_HATCH
) );
463 dc
.DrawLine( x
+20, y
+120, 100, y
+120 );
465 dc
.DrawText("User dash", x
+ 150, y
+ 140);
466 wxPen
ud( wxT("black"), width
, wxUSER_DASH
);
469 ud
.SetDashes( 1, dash1
);
470 dc
.DrawLine( x
+20, y
+140, 100, y
+140 );
472 ud
.SetDashes( 1, dash1
);
473 dc
.DrawLine( x
+20, y
+150, 100, y
+150 );
475 ud
.SetDashes( 1, dash1
);
476 dc
.DrawLine( x
+20, y
+160, 100, y
+160 );
478 ud
.SetDashes( 1, dash1
);
479 dc
.DrawLine( x
+20, y
+170, 100, y
+170 );
482 void MyCanvas::DrawDefault(wxDC
& dc
)
485 dc
.DrawCircle(0, 0, 10);
487 //flood fill using brush, starting at 1,1 and replacing whatever colour we find there
488 dc
.SetBrush(wxBrush(wxColour(128,128,0), wxSOLID
));
490 dc
.GetPixel(1,1, &tmpColour
);
491 dc
.FloodFill(1,1, tmpColour
, wxFLOOD_SURFACE
);
493 dc
.DrawCheckMark(5, 80, 15, 15);
494 dc
.DrawCheckMark(25, 80, 30, 30);
495 dc
.DrawCheckMark(60, 80, 60, 60);
497 // this is the test for "blitting bitmap into DC damages selected brush" bug
498 wxCoord rectSize
= m_std_icon
.GetWidth() + 10;
500 dc
.SetPen(*wxTRANSPARENT_PEN
);
501 dc
.SetBrush( *wxGREEN_BRUSH
);
502 dc
.DrawRectangle(x
, 10, rectSize
, rectSize
);
503 dc
.DrawBitmap(m_std_icon
, x
+ 5, 15, TRUE
);
505 dc
.DrawRectangle(x
, 10, rectSize
, rectSize
);
506 dc
.DrawIcon(m_std_icon
, x
+ 5, 15);
508 dc
.DrawRectangle(x
, 10, rectSize
, rectSize
);
510 // test for "transparent" bitmap drawing (it intersects with the last
512 //dc.SetBrush( *wxTRANSPARENT_BRUSH );
514 if (m_smile_bmp
.Ok())
515 dc
.DrawBitmap(m_smile_bmp
, x
+ rectSize
- 20, rectSize
- 10, TRUE
);
517 dc
.SetBrush( *wxBLACK_BRUSH
);
518 dc
.DrawRectangle( 0, 160, 1000, 300 );
521 wxBitmap
bitmap(20,70);
523 memdc
.SelectObject( bitmap
);
524 memdc
.SetBrush( *wxBLACK_BRUSH
);
525 memdc
.SetPen( *wxWHITE_PEN
);
526 memdc
.DrawRectangle(0,0,20,70);
527 memdc
.DrawLine( 10,0,10,70 );
530 wxPen pen
= *wxRED_PEN
;
532 memdc
.DrawLine( 10, 5,10, 5 );
533 memdc
.DrawLine( 10,10,11,10 );
534 memdc
.DrawLine( 10,15,12,15 );
535 memdc
.DrawLine( 10,20,13,20 );
538 memdc.SetPen(*wxRED_PEN);
539 memdc.DrawLine( 12, 5,12, 5 );
540 memdc.DrawLine( 12,10,13,10 );
541 memdc.DrawLine( 12,15,14,15 );
542 memdc.DrawLine( 12,20,15,20 );
546 memdc
.DrawLine( 10,25,10,25 );
547 memdc
.DrawLine( 10,30, 9,30 );
548 memdc
.DrawLine( 10,35, 8,35 );
549 memdc
.DrawLine( 10,40, 7,40 );
552 dc
.SetPen(*wxWHITE_PEN
);
553 memdc
.SetLogicalFunction( wxINVERT
);
554 memdc
.SetPen( *wxWHITE_PEN
);
555 memdc
.DrawLine( 10,50,10,50 );
556 memdc
.DrawLine( 10,55,11,55 );
557 memdc
.DrawLine( 10,60,12,60 );
558 memdc
.DrawLine( 10,65,13,65 );
560 memdc
.DrawLine( 12,50,12,50 );
561 memdc
.DrawLine( 12,55,13,55 );
562 memdc
.DrawLine( 12,60,14,60 );
563 memdc
.DrawLine( 12,65,15,65 );
565 memdc
.SelectObject( wxNullBitmap
);
566 dc
.DrawBitmap( bitmap
, 10, 170 );
567 wxImage image
= bitmap
.ConvertToImage();
568 image
.Rescale( 60,210 );
569 bitmap
= wxBitmap(image
);
570 dc
.DrawBitmap( bitmap
, 50, 170 );
572 // test the rectangle outline drawing - there should be one pixel between
573 // the rect and the lines
574 dc
.SetPen(*wxWHITE_PEN
);
575 dc
.SetBrush( *wxTRANSPARENT_BRUSH
);
576 dc
.DrawRectangle(150, 170, 49, 29);
577 dc
.DrawRectangle(200, 170, 49, 29);
578 dc
.SetPen(*wxWHITE_PEN
);
579 dc
.DrawLine(250, 210, 250, 170);
580 dc
.DrawLine(260, 200, 150, 200);
582 // test the rectangle filled drawing - there should be one pixel between
583 // the rect and the lines
584 dc
.SetPen(*wxTRANSPARENT_PEN
);
585 dc
.SetBrush( *wxWHITE_BRUSH
);
586 dc
.DrawRectangle(300, 170, 49, 29);
587 dc
.DrawRectangle(350, 170, 49, 29);
588 dc
.SetPen(*wxWHITE_PEN
);
589 dc
.DrawLine(400, 170, 400, 210);
590 dc
.DrawLine(300, 200, 410, 200);
592 // a few more tests of this kind
593 dc
.SetPen(*wxRED_PEN
);
594 dc
.SetBrush( *wxWHITE_BRUSH
);
595 dc
.DrawRectangle(300, 220, 1, 1);
596 dc
.DrawRectangle(310, 220, 2, 2);
597 dc
.DrawRectangle(320, 220, 3, 3);
598 dc
.DrawRectangle(330, 220, 4, 4);
600 dc
.SetPen(*wxTRANSPARENT_PEN
);
601 dc
.SetBrush( *wxWHITE_BRUSH
);
602 dc
.DrawRectangle(300, 230, 1, 1);
603 dc
.DrawRectangle(310, 230, 2, 2);
604 dc
.DrawRectangle(320, 230, 3, 3);
605 dc
.DrawRectangle(330, 230, 4, 4);
607 // and now for filled rect with outline
608 dc
.SetPen(*wxRED_PEN
);
609 dc
.SetBrush( *wxWHITE_BRUSH
);
610 dc
.DrawRectangle(500, 170, 49, 29);
611 dc
.DrawRectangle(550, 170, 49, 29);
612 dc
.SetPen(*wxWHITE_PEN
);
613 dc
.DrawLine(600, 170, 600, 210);
614 dc
.DrawLine(500, 200, 610, 200);
616 // test the rectangle outline drawing - there should be one pixel between
617 // the rect and the lines
618 dc
.SetPen(*wxWHITE_PEN
);
619 dc
.SetBrush( *wxTRANSPARENT_BRUSH
);
620 dc
.DrawRoundedRectangle(150, 270, 49, 29, 6);
621 dc
.DrawRoundedRectangle(200, 270, 49, 29, 6);
622 dc
.SetPen(*wxWHITE_PEN
);
623 dc
.DrawLine(250, 270, 250, 310);
624 dc
.DrawLine(150, 300, 260, 300);
626 // test the rectangle filled drawing - there should be one pixel between
627 // the rect and the lines
628 dc
.SetPen(*wxTRANSPARENT_PEN
);
629 dc
.SetBrush( *wxWHITE_BRUSH
);
630 dc
.DrawRoundedRectangle(300, 270, 49, 29, 6);
631 dc
.DrawRoundedRectangle(350, 270, 49, 29, 6);
632 dc
.SetPen(*wxWHITE_PEN
);
633 dc
.DrawLine(400, 270, 400, 310);
634 dc
.DrawLine(300, 300, 410, 300);
636 // Added by JACS to demonstrate bizarre behaviour.
637 // With a size of 70, we get a missing red RHS,
638 // and the hight is too small, so we get yellow
639 // showing. With a size of 40, it draws as expected:
640 // it just shows a white rectangle with red outline.
642 int totalHeight
= 70;
643 wxBitmap
bitmap2(totalWidth
, totalHeight
);
646 memdc2
.SelectObject(bitmap2
);
648 wxBrush
yellowBrush(wxColour(255, 255, 0), wxSOLID
);
649 memdc2
.SetBackground(yellowBrush
);
652 wxPen
yellowPen(wxColour(255, 255, 0), 1, wxSOLID
);
654 // Now draw a white rectangle with red outline. It should
655 // entirely eclipse the yellow background.
656 memdc2
.SetPen(*wxRED_PEN
);
657 memdc2
.SetBrush(*wxWHITE_BRUSH
);
659 memdc2
.DrawRectangle(0, 0, totalWidth
, totalHeight
);
661 memdc2
.SetPen(wxNullPen
);
662 memdc2
.SetBrush(wxNullBrush
);
663 memdc2
.SelectObject(wxNullBitmap
);
665 dc
.DrawBitmap(bitmap2
, 500, 270);
667 // Repeat, but draw directly on dc
668 // Draw a yellow rectangle filling the bitmap
670 x
= 600; int y
= 270;
671 dc
.SetPen(yellowPen
);
672 dc
.SetBrush(yellowBrush
);
673 dc
.DrawRectangle(x
, y
, totalWidth
, totalHeight
);
675 // Now draw a white rectangle with red outline. It should
676 // entirely eclipse the yellow background.
677 dc
.SetPen(*wxRED_PEN
);
678 dc
.SetBrush(*wxWHITE_BRUSH
);
680 dc
.DrawRectangle(x
, y
, totalWidth
, totalHeight
);
683 void MyCanvas::DrawText(wxDC
& dc
)
685 // set underlined font for testing
686 dc
.SetFont( wxFont(12, wxMODERN
, wxNORMAL
, wxNORMAL
, TRUE
) );
687 dc
.DrawText( "This is text", 110, 10 );
688 dc
.DrawRotatedText( "That is text", 20, 10, -45 );
690 // use wxSWISS_FONT and not wxNORMAL_FONT as the latter can't be rotated
691 // under Win9x (it is not TrueType)
692 dc
.SetFont( *wxSWISS_FONT
);
695 dc
.SetBackgroundMode(wxTRANSPARENT
);
697 for ( int n
= -180; n
< 180; n
+= 30 )
699 text
.Printf(wxT(" %d rotated text"), n
);
700 dc
.DrawRotatedText(text
, 400, 400, n
);
703 dc
.SetFont( wxFont( 18, wxSWISS
, wxNORMAL
, wxNORMAL
) );
705 dc
.DrawText( "This is Swiss 18pt text.", 110, 40 );
710 dc
.GetTextExtent( "This is Swiss 18pt text.", &length
, &height
, &descent
);
711 text
.Printf( wxT("Dimensions are length %ld, height %ld, descent %ld"), length
, height
, descent
);
712 dc
.DrawText( text
, 110, 80 );
714 text
.Printf( wxT("CharHeight() returns: %d"), dc
.GetCharHeight() );
715 dc
.DrawText( text
, 110, 120 );
717 dc
.DrawRectangle( 100, 40, 4, height
);
719 // test the logical function effect
721 dc
.SetLogicalFunction(wxINVERT
);
722 dc
.DrawText( "There should be no text below", 110, 150 );
723 dc
.DrawRectangle( 110, y
, 100, height
);
725 // twice drawn inverted should result in invisible
727 dc
.DrawText( "Invisible text", 110, y
);
728 dc
.DrawRectangle( 110, y
, 100, height
);
729 dc
.DrawText( "Invisible text", 110, y
);
730 dc
.DrawRectangle( 110, y
, 100, height
);
731 dc
.SetLogicalFunction(wxCOPY
);
734 dc
.DrawRectangle( 110, y
, 100, height
);
735 dc
.DrawText( "Visible text", 110, y
);
742 } rasterOperations
[] =
744 { wxT("wxAND"), wxAND
},
745 { wxT("wxAND_INVERT"), wxAND_INVERT
},
746 { wxT("wxAND_REVERSE"), wxAND_REVERSE
},
747 { wxT("wxCLEAR"), wxCLEAR
},
748 { wxT("wxCOPY"), wxCOPY
},
749 { wxT("wxEQUIV"), wxEQUIV
},
750 { wxT("wxINVERT"), wxINVERT
},
751 { wxT("wxNAND"), wxNAND
},
752 { wxT("wxNO_OP"), wxNO_OP
},
753 { wxT("wxOR"), wxOR
},
754 { wxT("wxOR_INVERT"), wxOR_INVERT
},
755 { wxT("wxOR_REVERSE"), wxOR_REVERSE
},
756 { wxT("wxSET"), wxSET
},
757 { wxT("wxSRC_INVERT"), wxSRC_INVERT
},
758 { wxT("wxXOR"), wxXOR
},
761 void MyCanvas::DrawImages(wxDC
& dc
)
763 dc
.DrawText("original image", 0, 0);
764 dc
.DrawBitmap(*gs_bmpNoMask
, 0, 20, 0);
765 dc
.DrawText("with colour mask", 0, 100);
766 dc
.DrawBitmap(*gs_bmpWithColMask
, 0, 120, TRUE
);
767 dc
.DrawText("the mask image", 0, 200);
768 dc
.DrawBitmap(*gs_bmpMask
, 0, 220, 0);
769 dc
.DrawText("masked image", 0, 300);
770 dc
.DrawBitmap(*gs_bmpWithMask
, 0, 320, TRUE
);
772 int cx
= gs_bmpWithColMask
->GetWidth(),
773 cy
= gs_bmpWithColMask
->GetHeight();
776 for ( size_t n
= 0; n
< WXSIZEOF(rasterOperations
); n
++ )
778 wxCoord x
= 120 + 150*(n%4
),
781 dc
.DrawText(rasterOperations
[n
].name
, x
, y
- 20);
782 memDC
.SelectObject(*gs_bmpWithColMask
);
783 dc
.Blit(x
, y
, cx
, cy
, &memDC
, 0, 0, rasterOperations
[n
].rop
, TRUE
);
787 void MyCanvas::DrawWithLogicalOps(wxDC
& dc
)
789 static const wxCoord w
= 60;
790 static const wxCoord h
= 60;
792 // reuse the text colour here
793 dc
.SetPen(wxPen(m_owner
->m_colourForeground
, 1, wxSOLID
));
794 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
797 for ( n
= 0; n
< WXSIZEOF(rasterOperations
); n
++ )
799 wxCoord x
= 20 + 150*(n%4
),
802 dc
.DrawText(rasterOperations
[n
].name
, x
, y
- 20);
803 dc
.SetLogicalFunction(rasterOperations
[n
].rop
);
804 dc
.DrawRectangle(x
, y
, w
, h
);
805 dc
.DrawLine(x
, y
, x
+ w
, y
+ h
);
806 dc
.DrawLine(x
+ w
, y
, x
, y
+ h
);
809 // now some filled rectangles
810 dc
.SetBrush(wxBrush(m_owner
->m_colourForeground
, wxSOLID
));
812 for ( n
= 0; n
< WXSIZEOF(rasterOperations
); n
++ )
814 wxCoord x
= 20 + 150*(n%4
),
817 dc
.DrawText(rasterOperations
[n
].name
, x
, y
- 20);
818 dc
.SetLogicalFunction(rasterOperations
[n
].rop
);
819 dc
.DrawRectangle(x
, y
, w
, h
);
823 void MyCanvas::DrawCircles(wxDC
& dc
)
829 dc
.DrawText("Some circles", 0, y
);
830 dc
.DrawCircle(x
, y
, r
);
831 dc
.DrawCircle(x
+ 2*r
, y
, r
);
832 dc
.DrawCircle(x
+ 4*r
, y
, r
);
835 dc
.DrawText("And ellipses", 0, y
);
836 dc
.DrawEllipse(x
- r
, y
, 2*r
, r
);
837 dc
.DrawEllipse(x
+ r
, y
, 2*r
, r
);
838 dc
.DrawEllipse(x
+ 3*r
, y
, 2*r
, r
);
841 dc
.DrawText("And arcs", 0, y
);
842 dc
.DrawArc(x
- r
, y
, x
+ r
, y
, x
, y
);
843 dc
.DrawArc(x
+ 4*r
, y
, x
+ 2*r
, y
, x
+ 3*r
, y
);
844 dc
.DrawArc(x
+ 5*r
, y
, x
+ 5*r
, y
, x
+ 6*r
, y
);
847 dc
.DrawEllipticArc(x
- r
, y
, 2*r
, r
, 0, 90);
848 dc
.DrawEllipticArc(x
+ r
, y
, 2*r
, r
, 90, 180);
849 dc
.DrawEllipticArc(x
+ 3*r
, y
, 2*r
, r
, 180, 270);
850 dc
.DrawEllipticArc(x
+ 5*r
, y
, 2*r
, r
, 270, 360);
853 void MyCanvas::DrawRegions(wxDC
& dc
)
855 dc
.DrawText("You should see a red rect partly covered by a cyan one "
856 "on the left", 10, 5);
857 dc
.DrawText("and 5 smileys from which 4 are partially clipped on the right",
858 10, 5 + dc
.GetCharHeight());
859 dc
.DrawText("The second copy should be identical but right part of it "
860 "should be offset by 10 pixels.",
861 10, 5 + 2*dc
.GetCharHeight());
863 DrawRegionsHelper(dc
, 10, TRUE
);
864 DrawRegionsHelper(dc
, 350, FALSE
);
867 void MyCanvas::DrawRegionsHelper(wxDC
& dc
, wxCoord x
, bool firstTime
)
871 dc
.DestroyClippingRegion();
872 dc
.SetBrush( *wxWHITE_BRUSH
);
873 dc
.SetPen( *wxTRANSPARENT_PEN
);
874 dc
.DrawRectangle( x
, y
, 310, 310 );
876 dc
.SetClippingRegion( x
+ 10, y
+ 10, 100, 270 );
878 dc
.SetBrush( *wxRED_BRUSH
);
879 dc
.DrawRectangle( x
, y
, 310, 310 );
881 dc
.SetClippingRegion( x
+ 10, y
+ 10, 100, 100 );
883 dc
.SetBrush( *wxCYAN_BRUSH
);
884 dc
.DrawRectangle( x
, y
, 310, 310 );
886 dc
.DestroyClippingRegion();
888 wxRegion
region(x
+ 110, y
+ 20, 100, 270);
889 #if !defined(__WXMOTIF__) && !defined(__WXMAC__)
891 region
.Offset(10, 10);
893 dc
.SetClippingRegion(region
);
895 dc
.SetBrush( *wxGREY_BRUSH
);
896 dc
.DrawRectangle( x
, y
, 310, 310 );
898 if (m_smile_bmp
.Ok())
900 dc
.DrawBitmap( m_smile_bmp
, x
+ 150, y
+ 150, TRUE
);
901 dc
.DrawBitmap( m_smile_bmp
, x
+ 130, y
+ 10, TRUE
);
902 dc
.DrawBitmap( m_smile_bmp
, x
+ 130, y
+ 280, TRUE
);
903 dc
.DrawBitmap( m_smile_bmp
, x
+ 100, y
+ 70, TRUE
);
904 dc
.DrawBitmap( m_smile_bmp
, x
+ 200, y
+ 70, TRUE
);
908 void MyCanvas::OnPaint(wxPaintEvent
&WXUNUSED(event
))
913 m_owner
->PrepareDC(dc
);
915 dc
.SetBackgroundMode( m_owner
->m_backgroundMode
);
916 if ( m_owner
->m_backgroundBrush
.Ok() )
917 dc
.SetBackground( m_owner
->m_backgroundBrush
);
918 if ( m_owner
->m_colourForeground
.Ok() )
919 dc
.SetTextForeground( m_owner
->m_colourForeground
);
920 if ( m_owner
->m_colourBackground
.Ok() )
921 dc
.SetTextBackground( m_owner
->m_colourBackground
);
923 if ( m_owner
->m_textureBackground
) {
924 if ( ! m_owner
->m_backgroundBrush
.Ok() ) {
925 wxBrush
b(wxColour(0,128,0), wxSOLID
);
931 dc
.SetClippingRegion(100, 100, 100, 100);
935 if ( m_owner
->m_textureBackground
)
937 dc
.SetPen(*wxMEDIUM_GREY_PEN
);
938 for ( int i
= 0; i
< 200; i
++ )
939 dc
.DrawLine(0, i
*10, i
*10, 0);
961 DrawTestLines( 0, 100, 0, dc
);
962 DrawTestLines( 0, 320, 1, dc
);
963 DrawTestLines( 0, 540, 2, dc
);
964 DrawTestLines( 0, 760, 6, dc
);
980 DrawWithLogicalOps(dc
);
985 void MyCanvas::OnMouseMove(wxMouseEvent
&event
)
989 m_owner
->PrepareDC(dc
);
991 wxPoint pos
= event
.GetPosition();
992 long x
= dc
.DeviceToLogicalX( pos
.x
);
993 long y
= dc
.DeviceToLogicalY( pos
.y
);
995 str
.Printf( wxT("Current mouse position: %d,%d"), (int)x
, (int)y
);
996 m_owner
->SetStatusText( str
);
999 // ----------------------------------------------------------------------------
1001 // ----------------------------------------------------------------------------
1003 // the event tables connect the wxWindows events with the functions (event
1004 // handlers) which process them. It can be also done at run-time, but for the
1005 // simple menu events like this the static method is much simpler.
1006 BEGIN_EVENT_TABLE(MyFrame
, wxFrame
)
1007 EVT_MENU (File_Quit
, MyFrame::OnQuit
)
1008 EVT_MENU (File_About
, MyFrame::OnAbout
)
1009 EVT_MENU (File_Clip
, MyFrame::OnClip
)
1011 EVT_MENU_RANGE(MenuShow_First
, MenuShow_Last
, MyFrame::OnShow
)
1013 EVT_MENU_RANGE(MenuOption_First
, MenuOption_Last
, MyFrame::OnOption
)
1016 // frame constructor
1017 MyFrame::MyFrame(const wxString
& title
, const wxPoint
& pos
, const wxSize
& size
)
1018 : wxFrame((wxFrame
*)NULL
, -1, title
, pos
, size
,
1019 wxDEFAULT_FRAME_STYLE
| wxNO_FULL_REPAINT_ON_RESIZE
)
1021 // set the frame icon
1022 SetIcon(wxICON(mondrian
));
1024 wxMenu
*menuFile
= new wxMenu
;
1025 menuFile
->Append(File_ShowDefault
, "&Default screen\tF1");
1026 menuFile
->Append(File_ShowText
, "&Text screen\tF2");
1027 menuFile
->Append(File_ShowLines
, "&Lines screen\tF3");
1028 menuFile
->Append(File_ShowBrushes
, "&Brushes screen\tF4");
1029 menuFile
->Append(File_ShowPolygons
, "&Polygons screen\tF5");
1030 menuFile
->Append(File_ShowMask
, "&Mask screen\tF6");
1031 menuFile
->Append(File_ShowOps
, "&ROP screen\tF7");
1032 menuFile
->Append(File_ShowRegions
, "Re&gions screen\tF8");
1033 menuFile
->Append(File_ShowCircles
, "&Circles screen\tF9");
1034 menuFile
->AppendSeparator();
1035 menuFile
->AppendCheckItem(File_Clip
, "&Clip\tCtrl-C", "Clip/unclip drawing");
1036 menuFile
->AppendSeparator();
1037 menuFile
->Append(File_About
, "&About...\tCtrl-A", "Show about dialog");
1038 menuFile
->AppendSeparator();
1039 menuFile
->Append(File_Quit
, "E&xit\tAlt-X", "Quit this program");
1041 wxMenu
*menuMapMode
= new wxMenu
;
1042 menuMapMode
->Append( MapMode_Text
, "&TEXT map mode" );
1043 menuMapMode
->Append( MapMode_Lometric
, "&LOMETRIC map mode" );
1044 menuMapMode
->Append( MapMode_Twips
, "T&WIPS map mode" );
1045 menuMapMode
->Append( MapMode_Points
, "&POINTS map mode" );
1046 menuMapMode
->Append( MapMode_Metric
, "&METRIC map mode" );
1048 wxMenu
*menuUserScale
= new wxMenu
;
1049 menuUserScale
->Append( UserScale_StretchHoriz
, "Stretch &horizontally\tCtrl-H" );
1050 menuUserScale
->Append( UserScale_ShrinkHoriz
, "Shrin&k horizontally\tCtrl-G" );
1051 menuUserScale
->Append( UserScale_StretchVertic
, "Stretch &vertically\tCtrl-V" );
1052 menuUserScale
->Append( UserScale_ShrinkVertic
, "&Shrink vertically\tCtrl-W" );
1053 menuUserScale
->AppendSeparator();
1054 menuUserScale
->Append( UserScale_Restore
, "&Restore to normal\tCtrl-0" );
1056 wxMenu
*menuAxis
= new wxMenu
;
1057 menuAxis
->Append( AxisMirror_Horiz
, "Mirror horizontally\tCtrl-M", "", TRUE
);
1058 menuAxis
->Append( AxisMirror_Vertic
, "Mirror vertically\tCtrl-N", "", TRUE
);
1060 wxMenu
*menuLogical
= new wxMenu
;
1061 menuLogical
->Append( LogicalOrigin_MoveDown
, "Move &down\tCtrl-D" );
1062 menuLogical
->Append( LogicalOrigin_MoveUp
, "Move &up\tCtrl-U" );
1063 menuLogical
->Append( LogicalOrigin_MoveLeft
, "Move &right\tCtrl-L" );
1064 menuLogical
->Append( LogicalOrigin_MoveRight
, "Move &left\tCtrl-R" );
1065 menuLogical
->AppendSeparator();
1066 menuLogical
->Append( LogicalOrigin_Set
, "Set to (&100, 100)\tShift-Ctrl-1" );
1067 menuLogical
->Append( LogicalOrigin_Restore
, "&Restore to normal\tShift-Ctrl-0" );
1069 wxMenu
*menuColour
= new wxMenu
;
1070 menuColour
->Append( Colour_TextForeground
, "Text &foreground..." );
1071 menuColour
->Append( Colour_TextBackground
, "Text &background..." );
1072 menuColour
->Append( Colour_Background
, "Background &colour..." );
1073 menuColour
->Append( Colour_BackgroundMode
, "&Opaque/transparent\tCtrl-B", "", TRUE
);
1074 menuColour
->Append( Colour_TextureBackgound
, "Draw textured back&ground\tCtrl-T", "", TRUE
);
1076 // now append the freshly created menu to the menu bar...
1077 wxMenuBar
*menuBar
= new wxMenuBar
;
1078 menuBar
->Append(menuFile
, "&File");
1079 menuBar
->Append(menuMapMode
, "&Mode");
1080 menuBar
->Append(menuUserScale
, "&Scale");
1081 menuBar
->Append(menuAxis
, "&Axis");
1082 menuBar
->Append(menuLogical
, "&Origin");
1083 menuBar
->Append(menuColour
, "&Colours");
1085 // ... and attach this menu bar to the frame
1086 SetMenuBar(menuBar
);
1088 // create a status bar just for fun (by default with 1 pane only)
1090 SetStatusText("Welcome to wxWindows!");
1092 m_mapMode
= wxMM_TEXT
;
1095 m_xLogicalOrigin
= 0;
1096 m_yLogicalOrigin
= 0;
1098 m_yAxisReversed
= FALSE
;
1099 m_backgroundMode
= wxSOLID
;
1100 m_colourForeground
= *wxRED
;
1101 m_colourBackground
= *wxBLUE
;
1102 m_textureBackground
= FALSE
;
1104 m_canvas
= new MyCanvas( this );
1105 m_canvas
->SetScrollbars( 10, 10, 100, 240 );
1110 void MyFrame::OnQuit(wxCommandEvent
& WXUNUSED(event
))
1112 // TRUE is to force the frame to close
1116 void MyFrame::OnAbout(wxCommandEvent
& WXUNUSED(event
))
1119 msg
.Printf( wxT("This is the about dialog of the drawing sample.\n")
1120 wxT("This sample tests various primitive drawing functions\n")
1121 wxT("(without any attempts to prevent flicker).\n")
1122 wxT("Copyright (c) Robert Roebling 1999")
1125 wxMessageBox(msg
, "About Drawing", wxOK
| wxICON_INFORMATION
, this);
1128 void MyFrame::OnClip(wxCommandEvent
& event
)
1130 m_canvas
->Clip(event
.IsChecked());
1133 void MyFrame::OnShow(wxCommandEvent
& event
)
1135 m_canvas
->Show((ScreenToShow
)(event
.GetId() - MenuShow_First
));
1138 void MyFrame::OnOption(wxCommandEvent
& event
)
1140 switch (event
.GetId())
1143 m_mapMode
= wxMM_TEXT
;
1145 case MapMode_Lometric
:
1146 m_mapMode
= wxMM_LOMETRIC
;
1149 m_mapMode
= wxMM_TWIPS
;
1151 case MapMode_Points
:
1152 m_mapMode
= wxMM_POINTS
;
1154 case MapMode_Metric
:
1155 m_mapMode
= wxMM_METRIC
;
1158 case LogicalOrigin_MoveDown
:
1159 m_yLogicalOrigin
+= 10;
1161 case LogicalOrigin_MoveUp
:
1162 m_yLogicalOrigin
-= 10;
1164 case LogicalOrigin_MoveLeft
:
1165 m_xLogicalOrigin
+= 10;
1167 case LogicalOrigin_MoveRight
:
1168 m_xLogicalOrigin
-= 10;
1170 case LogicalOrigin_Set
:
1172 m_yLogicalOrigin
= -100;
1174 case LogicalOrigin_Restore
:
1176 m_yLogicalOrigin
= 0;
1179 case UserScale_StretchHoriz
:
1180 m_xUserScale
*= 1.10;
1182 case UserScale_ShrinkHoriz
:
1183 m_xUserScale
/= 1.10;
1185 case UserScale_StretchVertic
:
1186 m_yUserScale
*= 1.10;
1188 case UserScale_ShrinkVertic
:
1189 m_yUserScale
/= 1.10;
1191 case UserScale_Restore
:
1196 case AxisMirror_Vertic
:
1197 m_yAxisReversed
= !m_yAxisReversed
;
1199 case AxisMirror_Horiz
:
1200 m_xAxisReversed
= !m_xAxisReversed
;
1203 case Colour_TextForeground
:
1204 m_colourForeground
= SelectColour();
1206 case Colour_TextBackground
:
1207 m_colourBackground
= SelectColour();
1209 case Colour_Background
:
1211 wxColour col
= SelectColour();
1214 m_backgroundBrush
.SetColour(col
);
1218 case Colour_BackgroundMode
:
1219 m_backgroundMode
= m_backgroundMode
== wxSOLID
? wxTRANSPARENT
1223 case Colour_TextureBackgound
:
1224 m_textureBackground
= ! m_textureBackground
;
1232 m_canvas
->Refresh();
1235 void MyFrame::PrepareDC(wxDC
& dc
)
1237 dc
.SetLogicalOrigin( m_xLogicalOrigin
, m_yLogicalOrigin
);
1238 dc
.SetAxisOrientation( !m_xAxisReversed
, m_yAxisReversed
);
1239 dc
.SetUserScale( m_xUserScale
, m_yUserScale
);
1240 dc
.SetMapMode( m_mapMode
);
1243 wxColour
MyFrame::SelectColour()
1247 wxColourDialog
dialog(this, &data
);
1249 if ( dialog
.ShowModal() == wxID_OK
)
1251 col
= dialog
.GetColourData().GetColour();