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 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
);
382 void MyCanvas::DrawTestBrushes(wxDC
& dc
)
384 static const wxCoord WIDTH
= 200;
385 static const wxCoord HEIGHT
= 80;
390 dc
.SetBrush(wxBrush(*wxGREEN
, wxSOLID
));
391 dc
.DrawRectangle(x
, y
, WIDTH
, HEIGHT
);
392 dc
.DrawText("Solid green", x
+ 10, y
+ 10);
395 dc
.SetBrush(wxBrush(*wxRED
, wxCROSSDIAG_HATCH
));
396 dc
.DrawRectangle(x
, y
, WIDTH
, HEIGHT
);
397 dc
.DrawText("Hatched red", x
+ 10, y
+ 10);
400 dc
.SetBrush(wxBrush(*gs_bmpMask
));
401 dc
.DrawRectangle(x
, y
, WIDTH
, HEIGHT
);
402 dc
.DrawText("Stipple mono", x
+ 10, y
+ 10);
405 dc
.SetBrush(wxBrush(*gs_bmpNoMask
));
406 dc
.DrawRectangle(x
, y
, WIDTH
, HEIGHT
);
407 dc
.DrawText("Stipple colour", x
+ 10, y
+ 10);
410 void MyCanvas::DrawTestPoly(wxDC
& dc
)
412 wxBrush
brushHatch(*wxRED
, wxFDIAGONAL_HATCH
);
413 dc
.SetBrush(brushHatch
);
416 star
[0] = wxPoint(100, 60);
417 star
[1] = wxPoint(60, 150);
418 star
[2] = wxPoint(160, 100);
419 star
[3] = wxPoint(40, 100);
420 star
[4] = wxPoint(140, 150);
422 dc
.DrawText("You should see two (irregular) stars below, the left one "
424 dc
.DrawText("except for the central region and the right "
425 "one entirely hatched", 10, 30);
427 dc
.DrawPolygon(WXSIZEOF(star
), star
);
428 dc
.DrawPolygon(WXSIZEOF(star
), star
, 160, 0, wxWINDING_RULE
);
431 void MyCanvas::DrawTestLines( int x
, int y
, int width
, wxDC
&dc
)
433 dc
.SetPen( wxPen( wxT("black"), width
, wxSOLID
) );
434 dc
.SetBrush( *wxRED_BRUSH
);
435 dc
.DrawText(wxString::Format(wxT("Testing lines of width %d"), width
), x
+ 10, y
- 10);
436 dc
.DrawRectangle( x
+10, y
+10, 100, 190 );
438 dc
.DrawText("Solid/dot/short dash/long dash/dot dash", x
+ 150, y
+ 10);
439 dc
.SetPen( wxPen( wxT("black"), width
, wxSOLID
) );
440 dc
.DrawLine( x
+20, y
+20, 100, y
+20 );
441 dc
.SetPen( wxPen( wxT("black"), width
, wxDOT
) );
442 dc
.DrawLine( x
+20, y
+30, 100, y
+30 );
443 dc
.SetPen( wxPen( wxT("black"), width
, wxSHORT_DASH
) );
444 dc
.DrawLine( x
+20, y
+40, 100, y
+40 );
445 dc
.SetPen( wxPen( wxT("black"), width
, wxLONG_DASH
) );
446 dc
.DrawLine( x
+20, y
+50, 100, y
+50 );
447 dc
.SetPen( wxPen( wxT("black"), width
, wxDOT_DASH
) );
448 dc
.DrawLine( x
+20, y
+60, 100, y
+60 );
450 dc
.DrawText("Misc hatches", x
+ 150, y
+ 70);
451 dc
.SetPen( wxPen( wxT("black"), width
, wxBDIAGONAL_HATCH
) );
452 dc
.DrawLine( x
+20, y
+70, 100, y
+70 );
453 dc
.SetPen( wxPen( wxT("black"), width
, wxCROSSDIAG_HATCH
) );
454 dc
.DrawLine( x
+20, y
+80, 100, y
+80 );
455 dc
.SetPen( wxPen( wxT("black"), width
, wxFDIAGONAL_HATCH
) );
456 dc
.DrawLine( x
+20, y
+90, 100, y
+90 );
457 dc
.SetPen( wxPen( wxT("black"), width
, wxCROSS_HATCH
) );
458 dc
.DrawLine( x
+20, y
+100, 100, y
+100 );
459 dc
.SetPen( wxPen( wxT("black"), width
, wxHORIZONTAL_HATCH
) );
460 dc
.DrawLine( x
+20, y
+110, 100, y
+110 );
461 dc
.SetPen( wxPen( wxT("black"), width
, wxVERTICAL_HATCH
) );
462 dc
.DrawLine( x
+20, y
+120, 100, y
+120 );
464 dc
.DrawText("User dash", x
+ 150, y
+ 140);
465 wxPen
ud( wxT("black"), width
, wxUSER_DASH
);
468 ud
.SetDashes( 1, dash1
);
469 dc
.DrawLine( x
+20, y
+140, 100, y
+140 );
471 ud
.SetDashes( 1, dash1
);
472 dc
.DrawLine( x
+20, y
+150, 100, y
+150 );
474 ud
.SetDashes( 1, dash1
);
475 dc
.DrawLine( x
+20, y
+160, 100, y
+160 );
477 ud
.SetDashes( 1, dash1
);
478 dc
.DrawLine( x
+20, y
+170, 100, y
+170 );
481 void MyCanvas::DrawDefault(wxDC
& dc
)
484 dc
.DrawCircle(0, 0, 10);
486 //flood fill using brush, starting at 1,1 and replacing whatever colour we find there
487 dc
.SetBrush(wxBrush(wxColour(128,128,0), wxSOLID
));
489 dc
.GetPixel(1,1, &tmpColour
);
490 dc
.FloodFill(1,1, tmpColour
, wxFLOOD_SURFACE
);
492 dc
.DrawCheckMark(5, 80, 15, 15);
493 dc
.DrawCheckMark(25, 80, 30, 30);
494 dc
.DrawCheckMark(60, 80, 60, 60);
496 // this is the test for "blitting bitmap into DC damages selected brush" bug
497 wxCoord rectSize
= m_std_icon
.GetWidth() + 10;
499 dc
.SetPen(*wxTRANSPARENT_PEN
);
500 dc
.SetBrush( *wxGREEN_BRUSH
);
501 dc
.DrawRectangle(x
, 10, rectSize
, rectSize
);
502 dc
.DrawBitmap(m_std_icon
, x
+ 5, 15, TRUE
);
504 dc
.DrawRectangle(x
, 10, rectSize
, rectSize
);
505 dc
.DrawIcon(m_std_icon
, x
+ 5, 15);
507 dc
.DrawRectangle(x
, 10, rectSize
, rectSize
);
509 // test for "transparent" bitmap drawing (it intersects with the last
511 //dc.SetBrush( *wxTRANSPARENT_BRUSH );
513 if (m_smile_bmp
.Ok())
514 dc
.DrawBitmap(m_smile_bmp
, x
+ rectSize
- 20, rectSize
- 10, TRUE
);
516 dc
.SetBrush( *wxBLACK_BRUSH
);
517 dc
.DrawRectangle( 0, 160, 1000, 300 );
520 wxBitmap
bitmap(20,70);
522 memdc
.SelectObject( bitmap
);
523 memdc
.SetBrush( *wxBLACK_BRUSH
);
524 memdc
.SetPen( *wxWHITE_PEN
);
525 memdc
.DrawRectangle(0,0,20,70);
526 memdc
.DrawLine( 10,0,10,70 );
529 wxPen pen
= *wxRED_PEN
;
531 memdc
.DrawLine( 10, 5,10, 5 );
532 memdc
.DrawLine( 10,10,11,10 );
533 memdc
.DrawLine( 10,15,12,15 );
534 memdc
.DrawLine( 10,20,13,20 );
537 memdc.SetPen(*wxRED_PEN);
538 memdc.DrawLine( 12, 5,12, 5 );
539 memdc.DrawLine( 12,10,13,10 );
540 memdc.DrawLine( 12,15,14,15 );
541 memdc.DrawLine( 12,20,15,20 );
545 memdc
.DrawLine( 10,25,10,25 );
546 memdc
.DrawLine( 10,30, 9,30 );
547 memdc
.DrawLine( 10,35, 8,35 );
548 memdc
.DrawLine( 10,40, 7,40 );
551 dc
.SetPen(*wxWHITE_PEN
);
552 memdc
.SetLogicalFunction( wxINVERT
);
553 memdc
.SetPen( *wxWHITE_PEN
);
554 memdc
.DrawLine( 10,50,10,50 );
555 memdc
.DrawLine( 10,55,11,55 );
556 memdc
.DrawLine( 10,60,12,60 );
557 memdc
.DrawLine( 10,65,13,65 );
559 memdc
.DrawLine( 12,50,12,50 );
560 memdc
.DrawLine( 12,55,13,55 );
561 memdc
.DrawLine( 12,60,14,60 );
562 memdc
.DrawLine( 12,65,15,65 );
564 memdc
.SelectObject( wxNullBitmap
);
565 dc
.DrawBitmap( bitmap
, 10, 170 );
566 wxImage image
= bitmap
.ConvertToImage();
567 image
.Rescale( 60,210 );
568 bitmap
= wxBitmap(image
);
569 dc
.DrawBitmap( bitmap
, 50, 170 );
571 // test the rectangle outline drawing - there should be one pixel between
572 // the rect and the lines
573 dc
.SetPen(*wxWHITE_PEN
);
574 dc
.SetBrush( *wxTRANSPARENT_BRUSH
);
575 dc
.DrawRectangle(150, 170, 49, 29);
576 dc
.DrawRectangle(200, 170, 49, 29);
577 dc
.SetPen(*wxWHITE_PEN
);
578 dc
.DrawLine(250, 210, 250, 170);
579 dc
.DrawLine(260, 200, 150, 200);
581 // test the rectangle filled drawing - there should be one pixel between
582 // the rect and the lines
583 dc
.SetPen(*wxTRANSPARENT_PEN
);
584 dc
.SetBrush( *wxWHITE_BRUSH
);
585 dc
.DrawRectangle(300, 170, 49, 29);
586 dc
.DrawRectangle(350, 170, 49, 29);
587 dc
.SetPen(*wxWHITE_PEN
);
588 dc
.DrawLine(400, 170, 400, 210);
589 dc
.DrawLine(300, 200, 410, 200);
591 // a few more tests of this kind
592 dc
.SetPen(*wxRED_PEN
);
593 dc
.SetBrush( *wxWHITE_BRUSH
);
594 dc
.DrawRectangle(300, 220, 1, 1);
595 dc
.DrawRectangle(310, 220, 2, 2);
596 dc
.DrawRectangle(320, 220, 3, 3);
597 dc
.DrawRectangle(330, 220, 4, 4);
599 dc
.SetPen(*wxTRANSPARENT_PEN
);
600 dc
.SetBrush( *wxWHITE_BRUSH
);
601 dc
.DrawRectangle(300, 230, 1, 1);
602 dc
.DrawRectangle(310, 230, 2, 2);
603 dc
.DrawRectangle(320, 230, 3, 3);
604 dc
.DrawRectangle(330, 230, 4, 4);
606 // and now for filled rect with outline
607 dc
.SetPen(*wxRED_PEN
);
608 dc
.SetBrush( *wxWHITE_BRUSH
);
609 dc
.DrawRectangle(500, 170, 49, 29);
610 dc
.DrawRectangle(550, 170, 49, 29);
611 dc
.SetPen(*wxWHITE_PEN
);
612 dc
.DrawLine(600, 170, 600, 210);
613 dc
.DrawLine(500, 200, 610, 200);
615 // test the rectangle outline drawing - there should be one pixel between
616 // the rect and the lines
617 dc
.SetPen(*wxWHITE_PEN
);
618 dc
.SetBrush( *wxTRANSPARENT_BRUSH
);
619 dc
.DrawRoundedRectangle(150, 270, 49, 29, 6);
620 dc
.DrawRoundedRectangle(200, 270, 49, 29, 6);
621 dc
.SetPen(*wxWHITE_PEN
);
622 dc
.DrawLine(250, 270, 250, 310);
623 dc
.DrawLine(150, 300, 260, 300);
625 // test the rectangle filled drawing - there should be one pixel between
626 // the rect and the lines
627 dc
.SetPen(*wxTRANSPARENT_PEN
);
628 dc
.SetBrush( *wxWHITE_BRUSH
);
629 dc
.DrawRoundedRectangle(300, 270, 49, 29, 6);
630 dc
.DrawRoundedRectangle(350, 270, 49, 29, 6);
631 dc
.SetPen(*wxWHITE_PEN
);
632 dc
.DrawLine(400, 270, 400, 310);
633 dc
.DrawLine(300, 300, 410, 300);
635 // Added by JACS to demonstrate bizarre behaviour.
636 // With a size of 70, we get a missing red RHS,
637 // and the hight is too small, so we get yellow
638 // showing. With a size of 40, it draws as expected:
639 // it just shows a white rectangle with red outline.
641 int totalHeight
= 70;
642 wxBitmap
bitmap2(totalWidth
, totalHeight
);
645 memdc2
.SelectObject(bitmap2
);
647 wxBrush
yellowBrush(wxColour(255, 255, 0), wxSOLID
);
648 memdc2
.SetBackground(yellowBrush
);
651 wxPen
yellowPen(wxColour(255, 255, 0), 1, wxSOLID
);
653 // Now draw a white rectangle with red outline. It should
654 // entirely eclipse the yellow background.
655 memdc2
.SetPen(*wxRED_PEN
);
656 memdc2
.SetBrush(*wxWHITE_BRUSH
);
658 memdc2
.DrawRectangle(0, 0, totalWidth
, totalHeight
);
660 memdc2
.SetPen(wxNullPen
);
661 memdc2
.SetBrush(wxNullBrush
);
662 memdc2
.SelectObject(wxNullBitmap
);
664 dc
.DrawBitmap(bitmap2
, 500, 270);
666 // Repeat, but draw directly on dc
667 // Draw a yellow rectangle filling the bitmap
669 x
= 600; int y
= 270;
670 dc
.SetPen(yellowPen
);
671 dc
.SetBrush(yellowBrush
);
672 dc
.DrawRectangle(x
, y
, totalWidth
, totalHeight
);
674 // Now draw a white rectangle with red outline. It should
675 // entirely eclipse the yellow background.
676 dc
.SetPen(*wxRED_PEN
);
677 dc
.SetBrush(*wxWHITE_BRUSH
);
679 dc
.DrawRectangle(x
, y
, totalWidth
, totalHeight
);
682 void MyCanvas::DrawText(wxDC
& dc
)
684 // set underlined font for testing
685 dc
.SetFont( wxFont(12, wxMODERN
, wxNORMAL
, wxNORMAL
, TRUE
) );
686 dc
.DrawText( "This is text", 110, 10 );
687 dc
.DrawRotatedText( "That is text", 20, 10, -45 );
689 // use wxSWISS_FONT and not wxNORMAL_FONT as the latter can't be rotated
690 // under Win9x (it is not TrueType)
691 dc
.SetFont( *wxSWISS_FONT
);
694 dc
.SetBackgroundMode(wxTRANSPARENT
);
696 for ( int n
= -180; n
< 180; n
+= 30 )
698 text
.Printf(wxT(" %d rotated text"), n
);
699 dc
.DrawRotatedText(text
, 400, 400, n
);
702 dc
.SetFont( wxFont( 18, wxSWISS
, wxNORMAL
, wxNORMAL
) );
704 dc
.DrawText( "This is Swiss 18pt text.", 110, 40 );
709 dc
.GetTextExtent( "This is Swiss 18pt text.", &length
, &height
, &descent
);
710 text
.Printf( wxT("Dimensions are length %ld, height %ld, descent %ld"), length
, height
, descent
);
711 dc
.DrawText( text
, 110, 80 );
713 text
.Printf( wxT("CharHeight() returns: %d"), dc
.GetCharHeight() );
714 dc
.DrawText( text
, 110, 120 );
716 dc
.DrawRectangle( 100, 40, 4, height
);
718 // test the logical function effect
720 dc
.SetLogicalFunction(wxINVERT
);
721 dc
.DrawText( "There should be no text below", 110, 150 );
722 dc
.DrawRectangle( 110, y
, 100, height
);
724 // twice drawn inverted should result in invisible
726 dc
.DrawText( "Invisible text", 110, y
);
727 dc
.DrawRectangle( 110, y
, 100, height
);
728 dc
.DrawText( "Invisible text", 110, y
);
729 dc
.DrawRectangle( 110, y
, 100, height
);
730 dc
.SetLogicalFunction(wxCOPY
);
733 dc
.DrawRectangle( 110, y
, 100, height
);
734 dc
.DrawText( "Visible text", 110, y
);
741 } rasterOperations
[] =
743 { wxT("wxAND"), wxAND
},
744 { wxT("wxAND_INVERT"), wxAND_INVERT
},
745 { wxT("wxAND_REVERSE"), wxAND_REVERSE
},
746 { wxT("wxCLEAR"), wxCLEAR
},
747 { wxT("wxCOPY"), wxCOPY
},
748 { wxT("wxEQUIV"), wxEQUIV
},
749 { wxT("wxINVERT"), wxINVERT
},
750 { wxT("wxNAND"), wxNAND
},
751 { wxT("wxNO_OP"), wxNO_OP
},
752 { wxT("wxOR"), wxOR
},
753 { wxT("wxOR_INVERT"), wxOR_INVERT
},
754 { wxT("wxOR_REVERSE"), wxOR_REVERSE
},
755 { wxT("wxSET"), wxSET
},
756 { wxT("wxSRC_INVERT"), wxSRC_INVERT
},
757 { wxT("wxXOR"), wxXOR
},
760 void MyCanvas::DrawImages(wxDC
& dc
)
762 dc
.DrawText("original image", 0, 0);
763 dc
.DrawBitmap(*gs_bmpNoMask
, 0, 20, 0);
764 dc
.DrawText("with colour mask", 0, 100);
765 dc
.DrawBitmap(*gs_bmpWithColMask
, 0, 120, TRUE
);
766 dc
.DrawText("the mask image", 0, 200);
767 dc
.DrawBitmap(*gs_bmpMask
, 0, 220, 0);
768 dc
.DrawText("masked image", 0, 300);
769 dc
.DrawBitmap(*gs_bmpWithMask
, 0, 320, TRUE
);
771 int cx
= gs_bmpWithColMask
->GetWidth(),
772 cy
= gs_bmpWithColMask
->GetHeight();
775 for ( size_t n
= 0; n
< WXSIZEOF(rasterOperations
); n
++ )
777 wxCoord x
= 120 + 150*(n%4
),
780 dc
.DrawText(rasterOperations
[n
].name
, x
, y
- 20);
781 memDC
.SelectObject(*gs_bmpWithColMask
);
782 dc
.Blit(x
, y
, cx
, cy
, &memDC
, 0, 0, rasterOperations
[n
].rop
, TRUE
);
786 void MyCanvas::DrawWithLogicalOps(wxDC
& dc
)
788 static const wxCoord w
= 60;
789 static const wxCoord h
= 60;
791 // reuse the text colour here
792 dc
.SetPen(wxPen(m_owner
->m_colourForeground
, 1, wxSOLID
));
793 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
796 for ( n
= 0; n
< WXSIZEOF(rasterOperations
); n
++ )
798 wxCoord x
= 20 + 150*(n%4
),
801 dc
.DrawText(rasterOperations
[n
].name
, x
, y
- 20);
802 dc
.SetLogicalFunction(rasterOperations
[n
].rop
);
803 dc
.DrawRectangle(x
, y
, w
, h
);
804 dc
.DrawLine(x
, y
, x
+ w
, y
+ h
);
805 dc
.DrawLine(x
+ w
, y
, x
, y
+ h
);
808 // now some filled rectangles
809 dc
.SetBrush(wxBrush(m_owner
->m_colourForeground
, wxSOLID
));
811 for ( n
= 0; n
< WXSIZEOF(rasterOperations
); n
++ )
813 wxCoord x
= 20 + 150*(n%4
),
816 dc
.DrawText(rasterOperations
[n
].name
, x
, y
- 20);
817 dc
.SetLogicalFunction(rasterOperations
[n
].rop
);
818 dc
.DrawRectangle(x
, y
, w
, h
);
822 void MyCanvas::DrawCircles(wxDC
& dc
)
828 dc
.DrawText("Some circles", 0, y
);
829 dc
.DrawCircle(x
, y
, r
);
830 dc
.DrawCircle(x
+ 2*r
, y
, r
);
831 dc
.DrawCircle(x
+ 4*r
, y
, r
);
834 dc
.DrawText("And ellipses", 0, y
);
835 dc
.DrawEllipse(x
- r
, y
, 2*r
, r
);
836 dc
.DrawEllipse(x
+ r
, y
, 2*r
, r
);
837 dc
.DrawEllipse(x
+ 3*r
, y
, 2*r
, r
);
840 dc
.DrawText("And arcs", 0, y
);
841 dc
.DrawArc(x
- r
, y
, x
+ r
, y
, x
, y
);
842 dc
.DrawArc(x
+ 4*r
, y
, x
+ 2*r
, y
, x
+ 3*r
, y
);
843 dc
.DrawArc(x
+ 5*r
, y
, x
+ 5*r
, y
, x
+ 6*r
, y
);
846 dc
.DrawEllipticArc(x
- r
, y
, 2*r
, r
, 0, 90);
847 dc
.DrawEllipticArc(x
+ r
, y
, 2*r
, r
, 90, 180);
848 dc
.DrawEllipticArc(x
+ 3*r
, y
, 2*r
, r
, 180, 270);
849 dc
.DrawEllipticArc(x
+ 5*r
, y
, 2*r
, r
, 270, 360);
852 void MyCanvas::DrawRegions(wxDC
& dc
)
854 dc
.DrawText("You should see a red rect partly covered by a cyan one "
855 "on the left", 10, 5);
856 dc
.DrawText("and 5 smileys from which 4 are partially clipped on the right",
857 10, 5 + dc
.GetCharHeight());
858 dc
.DrawText("The second copy should be identical but right part of it "
859 "should be offset by 10 pixels.",
860 10, 5 + 2*dc
.GetCharHeight());
862 DrawRegionsHelper(dc
, 10, TRUE
);
863 DrawRegionsHelper(dc
, 350, FALSE
);
866 void MyCanvas::DrawRegionsHelper(wxDC
& dc
, wxCoord x
, bool firstTime
)
870 dc
.DestroyClippingRegion();
871 dc
.SetBrush( *wxWHITE_BRUSH
);
872 dc
.SetPen( *wxTRANSPARENT_PEN
);
873 dc
.DrawRectangle( x
, y
, 310, 310 );
875 dc
.SetClippingRegion( x
+ 10, y
+ 10, 100, 270 );
877 dc
.SetBrush( *wxRED_BRUSH
);
878 dc
.DrawRectangle( x
, y
, 310, 310 );
880 dc
.SetClippingRegion( x
+ 10, y
+ 10, 100, 100 );
882 dc
.SetBrush( *wxCYAN_BRUSH
);
883 dc
.DrawRectangle( x
, y
, 310, 310 );
885 dc
.DestroyClippingRegion();
887 wxRegion
region(x
+ 110, y
+ 20, 100, 270);
888 #if !defined(__WXMOTIF__) && !defined(__WXMAC__)
890 region
.Offset(10, 10);
892 dc
.SetClippingRegion(region
);
894 dc
.SetBrush( *wxGREY_BRUSH
);
895 dc
.DrawRectangle( x
, y
, 310, 310 );
897 if (m_smile_bmp
.Ok())
899 dc
.DrawBitmap( m_smile_bmp
, x
+ 150, y
+ 150, TRUE
);
900 dc
.DrawBitmap( m_smile_bmp
, x
+ 130, y
+ 10, TRUE
);
901 dc
.DrawBitmap( m_smile_bmp
, x
+ 130, y
+ 280, TRUE
);
902 dc
.DrawBitmap( m_smile_bmp
, x
+ 100, y
+ 70, TRUE
);
903 dc
.DrawBitmap( m_smile_bmp
, x
+ 200, y
+ 70, TRUE
);
907 void MyCanvas::OnPaint(wxPaintEvent
&WXUNUSED(event
))
912 m_owner
->PrepareDC(dc
);
914 dc
.SetBackgroundMode( m_owner
->m_backgroundMode
);
915 if ( m_owner
->m_backgroundBrush
.Ok() )
916 dc
.SetBackground( m_owner
->m_backgroundBrush
);
917 if ( m_owner
->m_colourForeground
.Ok() )
918 dc
.SetTextForeground( m_owner
->m_colourForeground
);
919 if ( m_owner
->m_colourBackground
.Ok() )
920 dc
.SetTextBackground( m_owner
->m_colourBackground
);
922 if ( m_owner
->m_textureBackground
) {
923 if ( ! m_owner
->m_backgroundBrush
.Ok() ) {
924 wxBrush
b(wxColour(0,128,0), wxSOLID
);
930 dc
.SetClippingRegion(100, 100, 100, 100);
934 if ( m_owner
->m_textureBackground
)
936 dc
.SetPen(*wxMEDIUM_GREY_PEN
);
937 for ( int i
= 0; i
< 200; i
++ )
938 dc
.DrawLine(0, i
*10, i
*10, 0);
960 DrawTestLines( 0, 100, 0, dc
);
961 DrawTestLines( 0, 320, 1, dc
);
962 DrawTestLines( 0, 540, 2, dc
);
963 DrawTestLines( 0, 760, 6, dc
);
979 DrawWithLogicalOps(dc
);
984 void MyCanvas::OnMouseMove(wxMouseEvent
&event
)
988 m_owner
->PrepareDC(dc
);
990 wxPoint pos
= event
.GetPosition();
991 long x
= dc
.DeviceToLogicalX( pos
.x
);
992 long y
= dc
.DeviceToLogicalY( pos
.y
);
994 str
.Printf( wxT("Current mouse position: %d,%d"), (int)x
, (int)y
);
995 m_owner
->SetStatusText( str
);
998 // ----------------------------------------------------------------------------
1000 // ----------------------------------------------------------------------------
1002 // the event tables connect the wxWindows events with the functions (event
1003 // handlers) which process them. It can be also done at run-time, but for the
1004 // simple menu events like this the static method is much simpler.
1005 BEGIN_EVENT_TABLE(MyFrame
, wxFrame
)
1006 EVT_MENU (File_Quit
, MyFrame::OnQuit
)
1007 EVT_MENU (File_About
, MyFrame::OnAbout
)
1008 EVT_MENU (File_Clip
, MyFrame::OnClip
)
1010 EVT_MENU_RANGE(MenuShow_First
, MenuShow_Last
, MyFrame::OnShow
)
1012 EVT_MENU_RANGE(MenuOption_First
, MenuOption_Last
, MyFrame::OnOption
)
1015 // frame constructor
1016 MyFrame::MyFrame(const wxString
& title
, const wxPoint
& pos
, const wxSize
& size
)
1017 : wxFrame((wxFrame
*)NULL
, -1, title
, pos
, size
,
1018 wxDEFAULT_FRAME_STYLE
| wxNO_FULL_REPAINT_ON_RESIZE
)
1020 // set the frame icon
1021 SetIcon(wxICON(mondrian
));
1023 wxMenu
*menuFile
= new wxMenu
;
1024 menuFile
->Append(File_ShowDefault
, "&Default screen\tF1");
1025 menuFile
->Append(File_ShowText
, "&Text screen\tF2");
1026 menuFile
->Append(File_ShowLines
, "&Lines screen\tF3");
1027 menuFile
->Append(File_ShowBrushes
, "&Brushes screen\tF4");
1028 menuFile
->Append(File_ShowPolygons
, "&Polygons screen\tF5");
1029 menuFile
->Append(File_ShowMask
, "&Mask screen\tF6");
1030 menuFile
->Append(File_ShowOps
, "&ROP screen\tF7");
1031 menuFile
->Append(File_ShowRegions
, "Re&gions screen\tF8");
1032 menuFile
->Append(File_ShowCircles
, "&Circles screen\tF9");
1033 menuFile
->AppendSeparator();
1034 menuFile
->AppendCheckItem(File_Clip
, "&Clip\tCtrl-C", "Clip/unclip drawing");
1035 menuFile
->AppendSeparator();
1036 menuFile
->Append(File_About
, "&About...\tCtrl-A", "Show about dialog");
1037 menuFile
->AppendSeparator();
1038 menuFile
->Append(File_Quit
, "E&xit\tAlt-X", "Quit this program");
1040 wxMenu
*menuMapMode
= new wxMenu
;
1041 menuMapMode
->Append( MapMode_Text
, "&TEXT map mode" );
1042 menuMapMode
->Append( MapMode_Lometric
, "&LOMETRIC map mode" );
1043 menuMapMode
->Append( MapMode_Twips
, "T&WIPS map mode" );
1044 menuMapMode
->Append( MapMode_Points
, "&POINTS map mode" );
1045 menuMapMode
->Append( MapMode_Metric
, "&METRIC map mode" );
1047 wxMenu
*menuUserScale
= new wxMenu
;
1048 menuUserScale
->Append( UserScale_StretchHoriz
, "Stretch &horizontally\tCtrl-H" );
1049 menuUserScale
->Append( UserScale_ShrinkHoriz
, "Shrin&k horizontally\tCtrl-G" );
1050 menuUserScale
->Append( UserScale_StretchVertic
, "Stretch &vertically\tCtrl-V" );
1051 menuUserScale
->Append( UserScale_ShrinkVertic
, "&Shrink vertically\tCtrl-W" );
1052 menuUserScale
->AppendSeparator();
1053 menuUserScale
->Append( UserScale_Restore
, "&Restore to normal\tCtrl-0" );
1055 wxMenu
*menuAxis
= new wxMenu
;
1056 menuAxis
->Append( AxisMirror_Horiz
, "Mirror horizontally\tCtrl-M", "", TRUE
);
1057 menuAxis
->Append( AxisMirror_Vertic
, "Mirror vertically\tCtrl-N", "", TRUE
);
1059 wxMenu
*menuLogical
= new wxMenu
;
1060 menuLogical
->Append( LogicalOrigin_MoveDown
, "Move &down\tCtrl-D" );
1061 menuLogical
->Append( LogicalOrigin_MoveUp
, "Move &up\tCtrl-U" );
1062 menuLogical
->Append( LogicalOrigin_MoveLeft
, "Move &right\tCtrl-L" );
1063 menuLogical
->Append( LogicalOrigin_MoveRight
, "Move &left\tCtrl-R" );
1064 menuLogical
->AppendSeparator();
1065 menuLogical
->Append( LogicalOrigin_Set
, "Set to (&100, 100)\tShift-Ctrl-1" );
1066 menuLogical
->Append( LogicalOrigin_Restore
, "&Restore to normal\tShift-Ctrl-0" );
1068 wxMenu
*menuColour
= new wxMenu
;
1069 menuColour
->Append( Colour_TextForeground
, "Text &foreground..." );
1070 menuColour
->Append( Colour_TextBackground
, "Text &background..." );
1071 menuColour
->Append( Colour_Background
, "Background &colour..." );
1072 menuColour
->Append( Colour_BackgroundMode
, "&Opaque/transparent\tCtrl-B", "", TRUE
);
1073 menuColour
->Append( Colour_TextureBackgound
, "Draw textured back&ground\tCtrl-T", "", TRUE
);
1075 // now append the freshly created menu to the menu bar...
1076 wxMenuBar
*menuBar
= new wxMenuBar
;
1077 menuBar
->Append(menuFile
, "&File");
1078 menuBar
->Append(menuMapMode
, "&Mode");
1079 menuBar
->Append(menuUserScale
, "&Scale");
1080 menuBar
->Append(menuAxis
, "&Axis");
1081 menuBar
->Append(menuLogical
, "&Origin");
1082 menuBar
->Append(menuColour
, "&Colours");
1084 // ... and attach this menu bar to the frame
1085 SetMenuBar(menuBar
);
1087 // create a status bar just for fun (by default with 1 pane only)
1089 SetStatusText("Welcome to wxWindows!");
1091 m_mapMode
= wxMM_TEXT
;
1094 m_xLogicalOrigin
= 0;
1095 m_yLogicalOrigin
= 0;
1097 m_yAxisReversed
= FALSE
;
1098 m_backgroundMode
= wxSOLID
;
1099 m_colourForeground
= *wxRED
;
1100 m_colourBackground
= *wxBLUE
;
1101 m_textureBackground
= FALSE
;
1103 m_canvas
= new MyCanvas( this );
1104 m_canvas
->SetScrollbars( 10, 10, 100, 240 );
1109 void MyFrame::OnQuit(wxCommandEvent
& WXUNUSED(event
))
1111 // TRUE is to force the frame to close
1115 void MyFrame::OnAbout(wxCommandEvent
& WXUNUSED(event
))
1118 msg
.Printf( wxT("This is the about dialog of the drawing sample.\n")
1119 wxT("This sample tests various primitive drawing functions\n")
1120 wxT("(without any attempts to prevent flicker).\n")
1121 wxT("Copyright (c) Robert Roebling 1999")
1124 wxMessageBox(msg
, "About Drawing", wxOK
| wxICON_INFORMATION
, this);
1127 void MyFrame::OnClip(wxCommandEvent
& event
)
1129 m_canvas
->Clip(event
.IsChecked());
1132 void MyFrame::OnShow(wxCommandEvent
& event
)
1134 m_canvas
->Show((ScreenToShow
)(event
.GetId() - MenuShow_First
));
1137 void MyFrame::OnOption(wxCommandEvent
& event
)
1139 switch (event
.GetId())
1142 m_mapMode
= wxMM_TEXT
;
1144 case MapMode_Lometric
:
1145 m_mapMode
= wxMM_LOMETRIC
;
1148 m_mapMode
= wxMM_TWIPS
;
1150 case MapMode_Points
:
1151 m_mapMode
= wxMM_POINTS
;
1153 case MapMode_Metric
:
1154 m_mapMode
= wxMM_METRIC
;
1157 case LogicalOrigin_MoveDown
:
1158 m_yLogicalOrigin
+= 10;
1160 case LogicalOrigin_MoveUp
:
1161 m_yLogicalOrigin
-= 10;
1163 case LogicalOrigin_MoveLeft
:
1164 m_xLogicalOrigin
+= 10;
1166 case LogicalOrigin_MoveRight
:
1167 m_xLogicalOrigin
-= 10;
1169 case LogicalOrigin_Set
:
1171 m_yLogicalOrigin
= -100;
1173 case LogicalOrigin_Restore
:
1175 m_yLogicalOrigin
= 0;
1178 case UserScale_StretchHoriz
:
1179 m_xUserScale
*= 1.10;
1181 case UserScale_ShrinkHoriz
:
1182 m_xUserScale
/= 1.10;
1184 case UserScale_StretchVertic
:
1185 m_yUserScale
*= 1.10;
1187 case UserScale_ShrinkVertic
:
1188 m_yUserScale
/= 1.10;
1190 case UserScale_Restore
:
1195 case AxisMirror_Vertic
:
1196 m_yAxisReversed
= !m_yAxisReversed
;
1198 case AxisMirror_Horiz
:
1199 m_xAxisReversed
= !m_xAxisReversed
;
1202 case Colour_TextForeground
:
1203 m_colourForeground
= SelectColour();
1205 case Colour_TextBackground
:
1206 m_colourBackground
= SelectColour();
1208 case Colour_Background
:
1210 wxColour col
= SelectColour();
1213 m_backgroundBrush
.SetColour(col
);
1217 case Colour_BackgroundMode
:
1218 m_backgroundMode
= m_backgroundMode
== wxSOLID
? wxTRANSPARENT
1222 case Colour_TextureBackgound
:
1223 m_textureBackground
= ! m_textureBackground
;
1231 m_canvas
->Refresh();
1234 void MyFrame::PrepareDC(wxDC
& dc
)
1236 dc
.SetLogicalOrigin( m_xLogicalOrigin
, m_yLogicalOrigin
);
1237 dc
.SetAxisOrientation( !m_xAxisReversed
, m_yAxisReversed
);
1238 dc
.SetUserScale( m_xUserScale
, m_yUserScale
);
1239 dc
.SetMapMode( m_mapMode
);
1242 wxColour
MyFrame::SelectColour()
1246 wxColourDialog
dialog(this, &data
);
1248 if ( dialog
.ShowModal() == wxID_OK
)
1250 col
= dialog
.GetColourData().GetColour();