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"
41 // ----------------------------------------------------------------------------
43 // ----------------------------------------------------------------------------
45 // the application icon
46 #if defined(__WXGTK__) || defined(__WXMOTIF__) || defined(__WXMAC__)
47 #include "mondrian.xpm"
50 // ----------------------------------------------------------------------------
52 // ----------------------------------------------------------------------------
54 // what do we show on screen (there are too many shapes to put them all on
55 // screen simultaneously)
69 // ----------------------------------------------------------------------------
71 // ----------------------------------------------------------------------------
73 static wxBitmap
*gs_bmpNoMask
= NULL
,
74 *gs_bmpWithColMask
= NULL
,
76 *gs_bmpWithMask
= NULL
,
81 // ----------------------------------------------------------------------------
83 // ----------------------------------------------------------------------------
85 // Define a new application type, each program should derive a class from wxApp
86 class MyApp
: public wxApp
89 // override base class virtuals
90 // ----------------------------
92 // this one is called on application startup and is a good place for the app
93 // initialization (doing it here and not in the ctor allows to have an error
94 // return: if OnInit() returns false, the application terminates)
95 virtual bool OnInit();
97 virtual int OnExit() { DeleteBitmaps(); return 0; }
100 void DeleteBitmaps();
107 // Define a new frame type: this is going to be our main frame
108 class MyFrame
: public wxFrame
112 MyFrame(const wxString
& title
, const wxPoint
& pos
, const wxSize
& size
);
114 // event handlers (these functions should _not_ be virtual)
115 void OnQuit(wxCommandEvent
& event
);
116 void OnAbout(wxCommandEvent
& event
);
117 void OnShow(wxCommandEvent
&event
);
118 void OnOption(wxCommandEvent
&event
);
120 wxColour
SelectColour();
121 void PrepareDC(wxDC
& dc
);
123 int m_backgroundMode
;
124 int m_textureBackground
;
128 int m_xLogicalOrigin
;
129 int m_yLogicalOrigin
;
130 bool m_xAxisReversed
,
132 wxColour m_colourForeground
, // these are _text_ colours
134 wxBrush m_backgroundBrush
;
138 // any class wishing to process wxWindows events must use this macro
139 DECLARE_EVENT_TABLE()
142 // define a scrollable canvas for drawing onto
143 class MyCanvas
: public wxScrolledWindow
146 MyCanvas( MyFrame
*parent
);
148 void OnPaint(wxPaintEvent
&event
);
149 void OnMouseMove(wxMouseEvent
&event
);
151 void Show(ScreenToShow show
) { m_show
= show
; Refresh(); }
154 void DrawTestLines( int x
, int y
, int width
, wxDC
&dc
);
155 void DrawTestPoly(wxDC
& dc
);
156 void DrawTestBrushes(wxDC
& dc
);
157 void DrawText(wxDC
& dc
);
158 void DrawImages(wxDC
& dc
);
159 void DrawWithLogicalOps(wxDC
& dc
);
160 void DrawRegions(wxDC
& dc
);
161 void DrawCircles(wxDC
& dc
);
162 void DrawDefault(wxDC
& dc
);
164 void DrawRegionsHelper(wxDC
& dc
, wxCoord x
);
170 wxBitmap m_smile_bmp
;
173 DECLARE_EVENT_TABLE()
176 // ----------------------------------------------------------------------------
178 // ----------------------------------------------------------------------------
180 // IDs for the controls and the menu commands
188 File_ShowDefault
= MenuShow_First
,
197 MenuShow_Last
= File_ShowCircles
,
201 MapMode_Text
= MenuOption_First
,
207 UserScale_StretchHoriz
,
208 UserScale_ShrinkHoriz
,
209 UserScale_StretchVertic
,
210 UserScale_ShrinkVertic
,
216 LogicalOrigin_MoveDown
,
217 LogicalOrigin_MoveUp
,
218 LogicalOrigin_MoveLeft
,
219 LogicalOrigin_MoveRight
,
221 Colour_TextForeground
,
222 Colour_TextBackground
,
224 Colour_BackgroundMode
,
225 Colour_TextureBackgound
,
227 MenuOption_Last
= Colour_TextureBackgound
230 // ----------------------------------------------------------------------------
231 // event tables and other macros for wxWindows
232 // ----------------------------------------------------------------------------
235 // Create a new application object: this macro will allow wxWindows to create
236 // the application object during program execution (it's better than using a
237 // static object for many reasons) and also declares the accessor function
238 // wxGetApp() which will return the reference of the right type (i.e. MyApp and
242 // ============================================================================
244 // ============================================================================
246 // ----------------------------------------------------------------------------
247 // the application class
248 // ----------------------------------------------------------------------------
250 bool MyApp::LoadImages()
252 gs_bmpNoMask
= new wxBitmap
;
253 gs_bmpWithColMask
= new wxBitmap
;
254 gs_bmpMask
= new wxBitmap
;
255 gs_bmpWithMask
= new wxBitmap
;
256 gs_bmp4
= new wxBitmap
;
257 gs_bmp4_mono
= new wxBitmap
;
258 gs_bmp36
= new wxBitmap
;
264 wxString path
= pathList
.FindValidPath("pat4.bmp");
268 /* 4 colour bitmap */
269 gs_bmp4
->LoadFile(path
, wxBITMAP_TYPE_BMP
);
270 /* turn into mono-bitmap */
271 gs_bmp4_mono
->LoadFile(path
, wxBITMAP_TYPE_BMP
);
272 wxMask
* mask4
= new wxMask(*gs_bmp4_mono
, *wxBLACK
);
273 gs_bmp4_mono
->SetMask(mask4
);
275 path
= pathList
.FindValidPath("pat36.bmp");
278 gs_bmp36
->LoadFile(path
, wxBITMAP_TYPE_BMP
);
279 wxMask
* mask36
= new wxMask(*gs_bmp36
, *wxBLACK
);
280 gs_bmp36
->SetMask(mask36
);
282 path
= pathList
.FindValidPath("image.bmp");
285 gs_bmpNoMask
->LoadFile(path
, wxBITMAP_TYPE_BMP
);
286 gs_bmpWithMask
->LoadFile(path
, wxBITMAP_TYPE_BMP
);
287 gs_bmpWithColMask
->LoadFile(path
, wxBITMAP_TYPE_BMP
);
289 path
= pathList
.FindValidPath("mask.bmp");
292 gs_bmpMask
->LoadFile(path
, wxBITMAP_TYPE_BMP
);
294 wxMask
*mask
= new wxMask(*gs_bmpMask
, *wxBLACK
);
295 gs_bmpWithMask
->SetMask(mask
);
297 mask
= new wxMask(*gs_bmpWithColMask
, *wxWHITE
);
298 gs_bmpWithColMask
->SetMask(mask
);
303 // `Main program' equivalent: the program execution "starts" here
306 // Create the main application window
307 MyFrame
*frame
= new MyFrame("Drawing sample",
308 wxPoint(50, 50), wxSize(550, 340));
310 // Show it and tell the application that it's our main window
316 wxLogError(wxT("Can't load one of the bitmap files needed ")
317 wxT("for this sample from the current or parent ")
318 wxT("directory, please copy them there."));
330 void MyApp::DeleteBitmaps()
333 delete gs_bmpWithColMask
;
335 delete gs_bmpWithMask
;
341 gs_bmpWithColMask
= NULL
;
343 gs_bmpWithMask
= NULL
;
349 // ----------------------------------------------------------------------------
351 // ----------------------------------------------------------------------------
353 // the event tables connect the wxWindows events with the functions (event
354 // handlers) which process them.
355 BEGIN_EVENT_TABLE(MyCanvas
, wxScrolledWindow
)
356 EVT_PAINT (MyCanvas::OnPaint
)
357 EVT_MOTION (MyCanvas::OnMouseMove
)
362 MyCanvas::MyCanvas(MyFrame
*parent
)
363 : wxScrolledWindow(parent
, -1, wxDefaultPosition
, wxDefaultSize
,
364 wxHSCROLL
| wxVSCROLL
| wxNO_FULL_REPAINT_ON_RESIZE
)
367 m_show
= Show_Default
;
368 m_smile_bmp
= wxBitmap(smile_xpm
);
369 m_std_icon
= wxTheApp
->GetStdIcon(wxICON_INFORMATION
);
372 void MyCanvas::DrawTestBrushes(wxDC
& dc
)
374 static const wxCoord WIDTH
= 200;
375 static const wxCoord HEIGHT
= 80;
380 dc
.SetBrush(wxBrush(*wxGREEN
, wxSOLID
));
381 dc
.DrawRectangle(x
, y
, WIDTH
, HEIGHT
);
382 dc
.DrawText("Solid green", x
+ 10, y
+ 10);
385 dc
.SetBrush(wxBrush(*wxRED
, wxCROSSDIAG_HATCH
));
386 dc
.DrawRectangle(x
, y
, WIDTH
, HEIGHT
);
387 dc
.DrawText("Hatched red", x
+ 10, y
+ 10);
390 dc
.SetBrush(wxBrush(*gs_bmpMask
));
391 dc
.DrawRectangle(x
, y
, WIDTH
, HEIGHT
);
392 dc
.DrawText("Stipple mono", x
+ 10, y
+ 10);
395 dc
.SetBrush(wxBrush(*gs_bmpNoMask
));
396 dc
.DrawRectangle(x
, y
, WIDTH
, HEIGHT
);
397 dc
.DrawText("Stipple colour", x
+ 10, y
+ 10);
400 void MyCanvas::DrawTestPoly(wxDC
& dc
)
402 wxBrush
brushHatch(*wxRED
, wxFDIAGONAL_HATCH
);
403 dc
.SetBrush(brushHatch
);
406 star
[0] = wxPoint(100, 60);
407 star
[1] = wxPoint(60, 150);
408 star
[2] = wxPoint(160, 100);
409 star
[3] = wxPoint(40, 100);
410 star
[4] = wxPoint(140, 150);
412 dc
.DrawText("You should see two (irregular) stars below, the left one "
414 dc
.DrawText("except for the central region and the right "
415 "one entirely hatched", 10, 30);
417 dc
.DrawPolygon(WXSIZEOF(star
), star
);
418 dc
.DrawPolygon(WXSIZEOF(star
), star
, 160, 0, wxWINDING_RULE
);
421 void MyCanvas::DrawTestLines( int x
, int y
, int width
, wxDC
&dc
)
423 dc
.SetPen( wxPen( wxT("black"), width
, wxSOLID
) );
424 dc
.SetBrush( *wxRED_BRUSH
);
425 dc
.DrawText(wxString::Format(wxT("Testing lines of width %d"), width
), x
+ 10, y
- 10);
426 dc
.DrawRectangle( x
+10, y
+10, 100, 190 );
428 dc
.DrawText("Solid/dot/short dash/long dash/dot dash", x
+ 150, y
+ 10);
429 dc
.SetPen( wxPen( wxT("black"), width
, wxSOLID
) );
430 dc
.DrawLine( x
+20, y
+20, 100, y
+20 );
431 dc
.SetPen( wxPen( wxT("black"), width
, wxDOT
) );
432 dc
.DrawLine( x
+20, y
+30, 100, y
+30 );
433 dc
.SetPen( wxPen( wxT("black"), width
, wxSHORT_DASH
) );
434 dc
.DrawLine( x
+20, y
+40, 100, y
+40 );
435 dc
.SetPen( wxPen( wxT("black"), width
, wxLONG_DASH
) );
436 dc
.DrawLine( x
+20, y
+50, 100, y
+50 );
437 dc
.SetPen( wxPen( wxT("black"), width
, wxDOT_DASH
) );
438 dc
.DrawLine( x
+20, y
+60, 100, y
+60 );
440 dc
.DrawText("Misc hatches", x
+ 150, y
+ 70);
441 dc
.SetPen( wxPen( wxT("black"), width
, wxBDIAGONAL_HATCH
) );
442 dc
.DrawLine( x
+20, y
+70, 100, y
+70 );
443 dc
.SetPen( wxPen( wxT("black"), width
, wxCROSSDIAG_HATCH
) );
444 dc
.DrawLine( x
+20, y
+80, 100, y
+80 );
445 dc
.SetPen( wxPen( wxT("black"), width
, wxFDIAGONAL_HATCH
) );
446 dc
.DrawLine( x
+20, y
+90, 100, y
+90 );
447 dc
.SetPen( wxPen( wxT("black"), width
, wxCROSS_HATCH
) );
448 dc
.DrawLine( x
+20, y
+100, 100, y
+100 );
449 dc
.SetPen( wxPen( wxT("black"), width
, wxHORIZONTAL_HATCH
) );
450 dc
.DrawLine( x
+20, y
+110, 100, y
+110 );
451 dc
.SetPen( wxPen( wxT("black"), width
, wxVERTICAL_HATCH
) );
452 dc
.DrawLine( x
+20, y
+120, 100, y
+120 );
454 dc
.DrawText("User dash", x
+ 150, y
+ 140);
455 wxPen
ud( wxT("black"), width
, wxUSER_DASH
);
458 ud
.SetDashes( 1, dash1
);
459 dc
.DrawLine( x
+20, y
+140, 100, y
+140 );
461 ud
.SetDashes( 1, dash1
);
462 dc
.DrawLine( x
+20, y
+150, 100, y
+150 );
464 ud
.SetDashes( 1, dash1
);
465 dc
.DrawLine( x
+20, y
+160, 100, y
+160 );
467 ud
.SetDashes( 1, dash1
);
468 dc
.DrawLine( x
+20, y
+170, 100, y
+170 );
471 void MyCanvas::DrawDefault(wxDC
& dc
)
474 dc
.DrawCircle(0, 0, 10);
475 #if !(defined __WXGTK__) && !(defined __WXMOTIF__) && !(defined __WXMGL__)
476 // not implemented in wxGTK or wxMOTIF :-(
477 dc
.FloodFill(0, 0, wxColour(255, 0, 0));
480 dc
.DrawCheckMark(5, 80, 15, 15);
481 dc
.DrawCheckMark(25, 80, 30, 30);
482 dc
.DrawCheckMark(60, 80, 60, 60);
484 // this is the test for "blitting bitmap into DC damages selected brush" bug
485 wxCoord rectSize
= m_std_icon
.GetWidth() + 10;
487 dc
.SetPen(*wxTRANSPARENT_PEN
);
488 dc
.SetBrush( *wxGREEN_BRUSH
);
489 dc
.DrawRectangle(x
, 10, rectSize
, rectSize
);
490 dc
.DrawBitmap(m_std_icon
, x
+ 5, 15, TRUE
);
492 dc
.DrawRectangle(x
, 10, rectSize
, rectSize
);
493 dc
.DrawIcon(m_std_icon
, x
+ 5, 15);
495 dc
.DrawRectangle(x
, 10, rectSize
, rectSize
);
497 // test for "transparent" bitmap drawing (it intersects with the last
499 //dc.SetBrush( *wxTRANSPARENT_BRUSH );
501 if (m_smile_bmp
.Ok())
502 dc
.DrawBitmap(m_smile_bmp
, x
+ rectSize
- 20, rectSize
- 10, TRUE
);
504 dc
.SetBrush( *wxBLACK_BRUSH
);
505 dc
.DrawRectangle( 0, 160, 1000, 300 );
508 wxBitmap
bitmap(20,70);
510 memdc
.SelectObject( bitmap
);
511 memdc
.SetBrush( *wxBLACK_BRUSH
);
512 memdc
.SetPen( *wxWHITE_PEN
);
513 memdc
.DrawRectangle(0,0,20,70);
514 memdc
.DrawLine( 10,0,10,70 );
517 wxPen pen
= *wxRED_PEN
;
519 memdc
.DrawLine( 10, 5,10, 5 );
520 memdc
.DrawLine( 10,10,11,10 );
521 memdc
.DrawLine( 10,15,12,15 );
522 memdc
.DrawLine( 10,20,13,20 );
525 memdc.SetPen(*wxRED_PEN);
526 memdc.DrawLine( 12, 5,12, 5 );
527 memdc.DrawLine( 12,10,13,10 );
528 memdc.DrawLine( 12,15,14,15 );
529 memdc.DrawLine( 12,20,15,20 );
533 memdc
.DrawLine( 10,25,10,25 );
534 memdc
.DrawLine( 10,30, 9,30 );
535 memdc
.DrawLine( 10,35, 8,35 );
536 memdc
.DrawLine( 10,40, 7,40 );
539 dc
.SetPen(*wxWHITE_PEN
);
540 memdc
.SetLogicalFunction( wxINVERT
);
541 memdc
.SetPen( *wxWHITE_PEN
);
542 memdc
.DrawLine( 10,50,10,50 );
543 memdc
.DrawLine( 10,55,11,55 );
544 memdc
.DrawLine( 10,60,12,60 );
545 memdc
.DrawLine( 10,65,13,65 );
547 memdc
.DrawLine( 12,50,12,50 );
548 memdc
.DrawLine( 12,55,13,55 );
549 memdc
.DrawLine( 12,60,14,60 );
550 memdc
.DrawLine( 12,65,15,65 );
552 memdc
.SelectObject( wxNullBitmap
);
553 dc
.DrawBitmap( bitmap
, 10, 170 );
554 wxImage
image( bitmap
);
555 image
.Rescale( 60,210 );
556 bitmap
= image
.ConvertToBitmap();
557 dc
.DrawBitmap( bitmap
, 50, 170 );
559 // test the rectangle outline drawing - there should be one pixel between
560 // the rect and the lines
561 dc
.SetPen(*wxWHITE_PEN
);
562 dc
.SetBrush( *wxTRANSPARENT_BRUSH
);
563 dc
.DrawRectangle(150, 170, 49, 29);
564 dc
.DrawRectangle(200, 170, 49, 29);
565 dc
.SetPen(*wxWHITE_PEN
);
566 dc
.DrawLine(250, 210, 250, 170);
567 dc
.DrawLine(260, 200, 150, 200);
569 // test the rectangle filled drawing - there should be one pixel between
570 // the rect and the lines
571 dc
.SetPen(*wxTRANSPARENT_PEN
);
572 dc
.SetBrush( *wxWHITE_BRUSH
);
573 dc
.DrawRectangle(300, 170, 49, 29);
574 dc
.DrawRectangle(350, 170, 49, 29);
575 dc
.SetPen(*wxWHITE_PEN
);
576 dc
.DrawLine(400, 170, 400, 210);
577 dc
.DrawLine(300, 200, 410, 200);
579 // a few more tests of this kind
580 dc
.SetPen(*wxRED_PEN
);
581 dc
.SetBrush( *wxWHITE_BRUSH
);
582 dc
.DrawRectangle(300, 220, 1, 1);
583 dc
.DrawRectangle(310, 220, 2, 2);
584 dc
.DrawRectangle(320, 220, 3, 3);
585 dc
.DrawRectangle(330, 220, 4, 4);
587 dc
.SetPen(*wxTRANSPARENT_PEN
);
588 dc
.SetBrush( *wxWHITE_BRUSH
);
589 dc
.DrawRectangle(300, 230, 1, 1);
590 dc
.DrawRectangle(310, 230, 2, 2);
591 dc
.DrawRectangle(320, 230, 3, 3);
592 dc
.DrawRectangle(330, 230, 4, 4);
594 // and now for filled rect with outline
595 dc
.SetPen(*wxRED_PEN
);
596 dc
.SetBrush( *wxWHITE_BRUSH
);
597 dc
.DrawRectangle(500, 170, 49, 29);
598 dc
.DrawRectangle(550, 170, 49, 29);
599 dc
.SetPen(*wxWHITE_PEN
);
600 dc
.DrawLine(600, 170, 600, 210);
601 dc
.DrawLine(500, 200, 610, 200);
603 // test the rectangle outline drawing - there should be one pixel between
604 // the rect and the lines
605 dc
.SetPen(*wxWHITE_PEN
);
606 dc
.SetBrush( *wxTRANSPARENT_BRUSH
);
607 dc
.DrawRoundedRectangle(150, 270, 49, 29, 6);
608 dc
.DrawRoundedRectangle(200, 270, 49, 29, 6);
609 dc
.SetPen(*wxWHITE_PEN
);
610 dc
.DrawLine(250, 270, 250, 310);
611 dc
.DrawLine(150, 300, 260, 300);
613 // test the rectangle filled drawing - there should be one pixel between
614 // the rect and the lines
615 dc
.SetPen(*wxTRANSPARENT_PEN
);
616 dc
.SetBrush( *wxWHITE_BRUSH
);
617 dc
.DrawRoundedRectangle(300, 270, 49, 29, 6);
618 dc
.DrawRoundedRectangle(350, 270, 49, 29, 6);
619 dc
.SetPen(*wxWHITE_PEN
);
620 dc
.DrawLine(400, 270, 400, 310);
621 dc
.DrawLine(300, 300, 410, 300);
623 // Added by JACS to demonstrate bizarre behaviour.
624 // With a size of 70, we get a missing red RHS,
625 // and the hight is too small, so we get yellow
626 // showing. With a size of 40, it draws as expected:
627 // it just shows a white rectangle with red outline.
629 int totalHeight
= 70;
630 wxBitmap
bitmap2(totalWidth
, totalHeight
);
633 memdc2
.SelectObject(bitmap2
);
635 wxBrush
yellowBrush(wxColour(255, 255, 0), wxSOLID
);
636 memdc2
.SetBackground(yellowBrush
);
639 wxPen
yellowPen(wxColour(255, 255, 0), 1, wxSOLID
);
641 // Now draw a white rectangle with red outline. It should
642 // entirely eclipse the yellow background.
643 memdc2
.SetPen(*wxRED_PEN
);
644 memdc2
.SetBrush(*wxWHITE_BRUSH
);
646 memdc2
.DrawRectangle(0, 0, totalWidth
, totalHeight
);
648 memdc2
.SetPen(wxNullPen
);
649 memdc2
.SetBrush(wxNullBrush
);
650 memdc2
.SelectObject(wxNullBitmap
);
652 dc
.DrawBitmap(bitmap2
, 500, 270);
654 // Repeat, but draw directly on dc
655 // Draw a yellow rectangle filling the bitmap
657 x
= 600; int y
= 270;
658 dc
.SetPen(yellowPen
);
659 dc
.SetBrush(yellowBrush
);
660 dc
.DrawRectangle(x
, y
, totalWidth
, totalHeight
);
662 // Now draw a white rectangle with red outline. It should
663 // entirely eclipse the yellow background.
664 dc
.SetPen(*wxRED_PEN
);
665 dc
.SetBrush(*wxWHITE_BRUSH
);
667 dc
.DrawRectangle(x
, y
, totalWidth
, totalHeight
);
670 void MyCanvas::DrawText(wxDC
& dc
)
672 // set underlined font for testing
673 dc
.SetFont( wxFont(12, wxMODERN
, wxNORMAL
, wxNORMAL
, TRUE
) );
674 dc
.DrawText( "This is text", 110, 10 );
675 dc
.DrawRotatedText( "That is text", 20, 10, -45 );
677 // use wxSWISS_FONT and not wxNORMAL_FONT as the latter can't be rotated
678 // under Win9x (it is not TrueType)
679 dc
.SetFont( *wxSWISS_FONT
);
682 dc
.SetBackgroundMode(wxTRANSPARENT
);
684 for ( int n
= -180; n
< 180; n
+= 30 )
686 text
.Printf(wxT(" %d rotated text"), n
);
687 dc
.DrawRotatedText(text
, 400, 400, n
);
690 dc
.SetFont( wxFont( 18, wxSWISS
, wxNORMAL
, wxNORMAL
) );
692 dc
.DrawText( "This is Swiss 18pt text.", 110, 40 );
697 dc
.GetTextExtent( "This is Swiss 18pt text.", &length
, &height
, &descent
);
698 text
.Printf( wxT("Dimensions are length %ld, height %ld, descent %ld"), length
, height
, descent
);
699 dc
.DrawText( text
, 110, 80 );
701 text
.Printf( wxT("CharHeight() returns: %d"), dc
.GetCharHeight() );
702 dc
.DrawText( text
, 110, 120 );
704 dc
.DrawRectangle( 100, 40, 4, height
);
706 // test the logical function effect
708 dc
.SetLogicalFunction(wxINVERT
);
709 dc
.DrawText( "There should be no text below", 110, 150 );
710 dc
.DrawRectangle( 110, y
, 100, height
);
712 // twice drawn inverted should result in invisible
714 dc
.DrawText( "Invisible text", 110, y
);
715 dc
.DrawRectangle( 110, y
, 100, height
);
716 dc
.DrawText( "Invisible text", 110, y
);
717 dc
.DrawRectangle( 110, y
, 100, height
);
718 dc
.SetLogicalFunction(wxCOPY
);
721 dc
.DrawRectangle( 110, y
, 100, height
);
722 dc
.DrawText( "Visible text", 110, y
);
729 } rasterOperations
[] =
731 { wxT("wxAND"), wxAND
},
732 { wxT("wxAND_INVERT"), wxAND_INVERT
},
733 { wxT("wxAND_REVERSE"), wxAND_REVERSE
},
734 { wxT("wxCLEAR"), wxCLEAR
},
735 { wxT("wxCOPY"), wxCOPY
},
736 { wxT("wxEQUIV"), wxEQUIV
},
737 { wxT("wxINVERT"), wxINVERT
},
738 { wxT("wxNAND"), wxNAND
},
739 { wxT("wxNO_OP"), wxNO_OP
},
740 { wxT("wxOR"), wxOR
},
741 { wxT("wxOR_INVERT"), wxOR_INVERT
},
742 { wxT("wxOR_REVERSE"), wxOR_REVERSE
},
743 { wxT("wxSET"), wxSET
},
744 { wxT("wxSRC_INVERT"), wxSRC_INVERT
},
745 { wxT("wxXOR"), wxXOR
},
748 void MyCanvas::DrawImages(wxDC
& dc
)
750 dc
.DrawText("original image", 0, 0);
751 dc
.DrawBitmap(*gs_bmpNoMask
, 0, 20, 0);
752 dc
.DrawText("with colour mask", 0, 100);
753 dc
.DrawBitmap(*gs_bmpWithColMask
, 0, 120, TRUE
);
754 dc
.DrawText("the mask image", 0, 200);
755 dc
.DrawBitmap(*gs_bmpMask
, 0, 220, 0);
756 dc
.DrawText("masked image", 0, 300);
757 dc
.DrawBitmap(*gs_bmpWithMask
, 0, 320, TRUE
);
759 int cx
= gs_bmpWithColMask
->GetWidth(),
760 cy
= gs_bmpWithColMask
->GetHeight();
763 for ( size_t n
= 0; n
< WXSIZEOF(rasterOperations
); n
++ )
765 wxCoord x
= 120 + 150*(n%4
),
768 dc
.DrawText(rasterOperations
[n
].name
, x
, y
- 20);
769 memDC
.SelectObject(*gs_bmpWithColMask
);
770 dc
.Blit(x
, y
, cx
, cy
, &memDC
, 0, 0, rasterOperations
[n
].rop
, TRUE
);
774 void MyCanvas::DrawWithLogicalOps(wxDC
& dc
)
776 static const wxCoord w
= 60;
777 static const wxCoord h
= 60;
779 // reuse the text colour here
780 dc
.SetPen(wxPen(m_owner
->m_colourForeground
, 1, wxSOLID
));
781 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
784 for ( n
= 0; n
< WXSIZEOF(rasterOperations
); n
++ )
786 wxCoord x
= 20 + 150*(n%4
),
789 dc
.DrawText(rasterOperations
[n
].name
, x
, y
- 20);
790 dc
.SetLogicalFunction(rasterOperations
[n
].rop
);
791 dc
.DrawRectangle(x
, y
, w
, h
);
792 dc
.DrawLine(x
, y
, x
+ w
, y
+ h
);
793 dc
.DrawLine(x
+ w
, y
, x
, y
+ h
);
796 // now some filled rectangles
797 dc
.SetBrush(wxBrush(m_owner
->m_colourForeground
, wxSOLID
));
799 for ( n
= 0; n
< WXSIZEOF(rasterOperations
); n
++ )
801 wxCoord x
= 20 + 150*(n%4
),
804 dc
.DrawText(rasterOperations
[n
].name
, x
, y
- 20);
805 dc
.SetLogicalFunction(rasterOperations
[n
].rop
);
806 dc
.DrawRectangle(x
, y
, w
, h
);
810 void MyCanvas::DrawCircles(wxDC
& dc
)
816 dc
.DrawText("Some circles", 0, y
);
817 dc
.DrawCircle(x
, y
, r
);
818 dc
.DrawCircle(x
+ 2*r
, y
, r
);
819 dc
.DrawCircle(x
+ 4*r
, y
, r
);
822 dc
.DrawText("And ellipses", 0, y
);
823 dc
.DrawEllipse(x
- r
, y
, 2*r
, r
);
824 dc
.DrawEllipse(x
+ r
, y
, 2*r
, r
);
825 dc
.DrawEllipse(x
+ 3*r
, y
, 2*r
, r
);
828 dc
.DrawText("And arcs", 0, y
);
829 dc
.DrawArc(x
- r
, y
, x
+ r
, y
, x
, y
);
830 dc
.DrawArc(x
+ 4*r
, y
, x
+ 2*r
, y
, x
+ 3*r
, y
);
831 dc
.DrawArc(x
+ 5*r
, y
, x
+ 5*r
, y
, x
+ 6*r
, y
);
834 dc
.DrawEllipticArc(x
- r
, y
, 2*r
, r
, 0, 90);
835 dc
.DrawEllipticArc(x
+ r
, y
, 2*r
, r
, 90, 180);
836 dc
.DrawEllipticArc(x
+ 3*r
, y
, 2*r
, r
, 180, 270);
837 dc
.DrawEllipticArc(x
+ 5*r
, y
, 2*r
, r
, 270, 360);
840 void MyCanvas::DrawRegions(wxDC
& dc
)
842 dc
.DrawText("You should see a red rect partly covered by a cyan one "
843 "on the left", 10, 5);
844 dc
.DrawText("and 5 smileys from which 4 are partially clipped on the "
845 "right (2 copies should be identical)",
846 10, 5 + dc
.GetCharHeight());
848 DrawRegionsHelper(dc
, 10);
849 DrawRegionsHelper(dc
, 350);
852 void MyCanvas::DrawRegionsHelper(wxDC
& dc
, wxCoord x
)
854 dc
.DestroyClippingRegion();
855 dc
.SetBrush( *wxWHITE_BRUSH
);
856 dc
.SetPen( *wxTRANSPARENT_PEN
);
857 dc
.DrawRectangle( x
,50,310,310 );
859 dc
.SetClippingRegion( x
+10,60,100,270 );
861 dc
.SetBrush( *wxRED_BRUSH
);
862 dc
.DrawRectangle( x
,50,310,310 );
864 dc
.SetClippingRegion( x
+10,60,100,100 );
866 dc
.SetBrush( *wxCYAN_BRUSH
);
867 dc
.DrawRectangle( x
,50,310,310 );
869 // when drawing the left half, destroy the clipping region, when drawing
870 // the right one - leave it
872 // normally it shouldn't make any difference as SetClippingRegion()
873 // replaces the old clipping region
875 dc
.DestroyClippingRegion();
876 dc
.SetClippingRegion( x
+110,70,100,270 );
878 dc
.SetBrush( *wxGREY_BRUSH
);
879 dc
.DrawRectangle( x
,50,310,310 );
881 if (m_smile_bmp
.Ok())
883 dc
.DrawBitmap( m_smile_bmp
, x
+150, 200, TRUE
);
884 dc
.DrawBitmap( m_smile_bmp
, x
+130, 60, TRUE
);
885 dc
.DrawBitmap( m_smile_bmp
, x
+130, 330, TRUE
);
886 dc
.DrawBitmap( m_smile_bmp
, x
+100, 120, TRUE
);
887 dc
.DrawBitmap( m_smile_bmp
, x
+200, 120, TRUE
);
891 void MyCanvas::OnPaint(wxPaintEvent
&WXUNUSED(event
))
896 m_owner
->PrepareDC(dc
);
898 dc
.SetBackgroundMode( m_owner
->m_backgroundMode
);
899 if ( m_owner
->m_backgroundBrush
.Ok() )
900 dc
.SetBackground( m_owner
->m_backgroundBrush
);
901 if ( m_owner
->m_colourForeground
.Ok() )
902 dc
.SetTextForeground( m_owner
->m_colourForeground
);
903 if ( m_owner
->m_colourBackground
.Ok() )
904 dc
.SetTextBackground( m_owner
->m_colourBackground
);
906 if ( m_owner
->m_textureBackground
) {
907 if ( ! m_owner
->m_backgroundBrush
.Ok() ) {
908 wxBrush
b(wxColour(0,128,0), wxSOLID
);
915 if ( m_owner
->m_textureBackground
) {
916 dc
.SetPen(*wxMEDIUM_GREY_PEN
);
917 for (int i
=0; i
<200; i
++)
918 dc
.DrawLine(0, i
*10, i
*10, 0);
940 DrawTestLines( 0, 100, 0, dc
);
941 DrawTestLines( 0, 320, 1, dc
);
942 DrawTestLines( 0, 540, 2, dc
);
943 DrawTestLines( 0, 760, 6, dc
);
959 DrawWithLogicalOps(dc
);
964 void MyCanvas::OnMouseMove(wxMouseEvent
&event
)
968 m_owner
->PrepareDC(dc
);
970 wxPoint pos
= event
.GetPosition();
971 long x
= dc
.DeviceToLogicalX( pos
.x
);
972 long y
= dc
.DeviceToLogicalY( pos
.y
);
974 str
.Printf( wxT("Current mouse position: %d,%d"), (int)x
, (int)y
);
975 m_owner
->SetStatusText( str
);
978 // ----------------------------------------------------------------------------
980 // ----------------------------------------------------------------------------
982 // the event tables connect the wxWindows events with the functions (event
983 // handlers) which process them. It can be also done at run-time, but for the
984 // simple menu events like this the static method is much simpler.
985 BEGIN_EVENT_TABLE(MyFrame
, wxFrame
)
986 EVT_MENU (File_Quit
, MyFrame::OnQuit
)
987 EVT_MENU (File_About
, MyFrame::OnAbout
)
989 EVT_MENU_RANGE(MenuShow_First
, MenuShow_Last
, MyFrame::OnShow
)
991 EVT_MENU_RANGE(MenuOption_First
, MenuOption_Last
, MyFrame::OnOption
)
995 MyFrame::MyFrame(const wxString
& title
, const wxPoint
& pos
, const wxSize
& size
)
996 : wxFrame((wxFrame
*)NULL
, -1, title
, pos
, size
,
997 wxDEFAULT_FRAME_STYLE
| wxNO_FULL_REPAINT_ON_RESIZE
)
999 // set the frame icon
1000 SetIcon(wxICON(mondrian
));
1002 wxMenu
*menuFile
= new wxMenu
;
1003 menuFile
->Append(File_ShowDefault
, "&Default screen\tF1");
1004 menuFile
->Append(File_ShowText
, "&Text screen\tF2");
1005 menuFile
->Append(File_ShowLines
, "&Lines screen\tF3");
1006 menuFile
->Append(File_ShowBrushes
, "&Brushes screen\tF4");
1007 menuFile
->Append(File_ShowPolygons
, "&Polygons screen\tF5");
1008 menuFile
->Append(File_ShowMask
, "&Mask screen\tF6");
1009 menuFile
->Append(File_ShowOps
, "&ROP screen\tF7");
1010 menuFile
->Append(File_ShowRegions
, "Re&gions screen\tF8");
1011 menuFile
->Append(File_ShowCircles
, "&Circles screen\tF9");
1012 menuFile
->AppendSeparator();
1013 menuFile
->Append(File_About
, "&About...\tCtrl-A", "Show about dialog");
1014 menuFile
->AppendSeparator();
1015 menuFile
->Append(File_Quit
, "E&xit\tAlt-X", "Quit this program");
1017 wxMenu
*menuMapMode
= new wxMenu
;
1018 menuMapMode
->Append( MapMode_Text
, "&TEXT map mode" );
1019 menuMapMode
->Append( MapMode_Lometric
, "&LOMETRIC map mode" );
1020 menuMapMode
->Append( MapMode_Twips
, "T&WIPS map mode" );
1021 menuMapMode
->Append( MapMode_Points
, "&POINTS map mode" );
1022 menuMapMode
->Append( MapMode_Metric
, "&METRIC map mode" );
1024 wxMenu
*menuUserScale
= new wxMenu
;
1025 menuUserScale
->Append( UserScale_StretchHoriz
, "Stretch horizontally\tCtrl-H" );
1026 menuUserScale
->Append( UserScale_ShrinkHoriz
, "Shrink horizontally\tCtrl-G" );
1027 menuUserScale
->Append( UserScale_StretchVertic
, "Stretch vertically\tCtrl-V" );
1028 menuUserScale
->Append( UserScale_ShrinkVertic
, "Shrink vertically\tCtrl-W" );
1029 menuUserScale
->AppendSeparator();
1030 menuUserScale
->Append( UserScale_Restore
, "Restore to normal\tCtrl-0" );
1032 wxMenu
*menuAxis
= new wxMenu
;
1033 menuAxis
->Append( AxisMirror_Horiz
, "Mirror horizontally\tCtrl-M", "", TRUE
);
1034 menuAxis
->Append( AxisMirror_Vertic
, "Mirror vertically\tCtrl-N", "", TRUE
);
1036 wxMenu
*menuLogical
= new wxMenu
;
1037 menuLogical
->Append( LogicalOrigin_MoveDown
, "Move &down\tCtrl-D" );
1038 menuLogical
->Append( LogicalOrigin_MoveUp
, "Move &up\tCtrl-U" );
1039 menuLogical
->Append( LogicalOrigin_MoveLeft
, "Move &right\tCtrl-L" );
1040 menuLogical
->Append( LogicalOrigin_MoveRight
, "Move &left\tCtrl-R" );
1042 wxMenu
*menuColour
= new wxMenu
;
1043 menuColour
->Append( Colour_TextForeground
, "Text foreground..." );
1044 menuColour
->Append( Colour_TextBackground
, "Text background..." );
1045 menuColour
->Append( Colour_Background
, "Background colour..." );
1046 menuColour
->Append( Colour_BackgroundMode
, "Opaque/transparent\tCtrl-B", "", TRUE
);
1047 menuColour
->Append( Colour_TextureBackgound
, "Draw textured background\tCtrl-T", "", TRUE
);
1049 // now append the freshly created menu to the menu bar...
1050 wxMenuBar
*menuBar
= new wxMenuBar
;
1051 menuBar
->Append(menuFile
, "&File");
1052 menuBar
->Append(menuMapMode
, "&MapMode");
1053 menuBar
->Append(menuUserScale
, "&UserScale");
1054 menuBar
->Append(menuAxis
, "&Axis");
1055 menuBar
->Append(menuLogical
, "&LogicalOrigin");
1056 menuBar
->Append(menuColour
, "&Colours");
1058 // ... and attach this menu bar to the frame
1059 SetMenuBar(menuBar
);
1061 // create a status bar just for fun (by default with 1 pane only)
1063 SetStatusText("Welcome to wxWindows!");
1065 m_mapMode
= wxMM_TEXT
;
1068 m_xLogicalOrigin
= 0;
1069 m_yLogicalOrigin
= 0;
1071 m_yAxisReversed
= FALSE
;
1072 m_backgroundMode
= wxSOLID
;
1073 m_colourForeground
= *wxRED
;
1074 m_colourBackground
= *wxBLUE
;
1075 m_textureBackground
= FALSE
;
1077 m_canvas
= new MyCanvas( this );
1078 m_canvas
->SetScrollbars( 10, 10, 100, 240 );
1083 void MyFrame::OnQuit(wxCommandEvent
& WXUNUSED(event
))
1085 // TRUE is to force the frame to close
1089 void MyFrame::OnAbout(wxCommandEvent
& WXUNUSED(event
))
1092 msg
.Printf( wxT("This is the about dialog of the drawing sample.\n")
1093 wxT("This sample tests various primitive drawing functions\n")
1094 wxT("(without any attempts to prevent flicker).\n")
1095 wxT("Copyright (c) Robert Roebling 1999")
1098 wxMessageBox(msg
, "About Drawing", wxOK
| wxICON_INFORMATION
, this);
1101 void MyFrame::OnShow(wxCommandEvent
& event
)
1103 m_canvas
->Show((ScreenToShow
)(event
.GetId() - MenuShow_First
));
1106 void MyFrame::OnOption(wxCommandEvent
& event
)
1108 switch (event
.GetId())
1111 m_mapMode
= wxMM_TEXT
;
1113 case MapMode_Lometric
:
1114 m_mapMode
= wxMM_LOMETRIC
;
1117 m_mapMode
= wxMM_TWIPS
;
1119 case MapMode_Points
:
1120 m_mapMode
= wxMM_POINTS
;
1122 case MapMode_Metric
:
1123 m_mapMode
= wxMM_METRIC
;
1126 case LogicalOrigin_MoveDown
:
1127 m_yLogicalOrigin
+= 10;
1129 case LogicalOrigin_MoveUp
:
1130 m_yLogicalOrigin
-= 10;
1132 case LogicalOrigin_MoveLeft
:
1133 m_xLogicalOrigin
+= 10;
1135 case LogicalOrigin_MoveRight
:
1136 m_xLogicalOrigin
-= 10;
1139 case UserScale_StretchHoriz
:
1140 m_xUserScale
*= 1.10;
1142 case UserScale_ShrinkHoriz
:
1143 m_xUserScale
/= 1.10;
1145 case UserScale_StretchVertic
:
1146 m_yUserScale
*= 1.10;
1148 case UserScale_ShrinkVertic
:
1149 m_yUserScale
/= 1.10;
1151 case UserScale_Restore
:
1156 case AxisMirror_Vertic
:
1157 m_yAxisReversed
= !m_yAxisReversed
;
1159 case AxisMirror_Horiz
:
1160 m_xAxisReversed
= !m_xAxisReversed
;
1163 case Colour_TextForeground
:
1164 m_colourForeground
= SelectColour();
1166 case Colour_TextBackground
:
1167 m_colourBackground
= SelectColour();
1169 case Colour_Background
:
1171 wxColour col
= SelectColour();
1174 m_backgroundBrush
.SetColour(col
);
1178 case Colour_BackgroundMode
:
1179 m_backgroundMode
= m_backgroundMode
== wxSOLID
? wxTRANSPARENT
1183 case Colour_TextureBackgound
:
1184 m_textureBackground
= ! m_textureBackground
;
1192 m_canvas
->Refresh();
1195 void MyFrame::PrepareDC(wxDC
& dc
)
1197 dc
.SetMapMode( m_mapMode
);
1198 dc
.SetUserScale( m_xUserScale
, m_yUserScale
);
1199 dc
.SetLogicalOrigin( m_xLogicalOrigin
, m_yLogicalOrigin
);
1200 dc
.SetAxisOrientation( !m_xAxisReversed
, m_yAxisReversed
);
1203 wxColour
MyFrame::SelectColour()
1207 wxColourDialog
dialog(this, &data
);
1209 if ( dialog
.ShowModal() == wxID_OK
)
1211 col
= dialog
.GetColourData().GetColour();