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
, bool firstTime
);
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 right",
845 10, 5 + dc
.GetCharHeight());
846 dc
.DrawText("The second copy should be identical but right part of it "
847 "should be offset by 10 pixels.",
848 10, 5 + 2*dc
.GetCharHeight());
850 DrawRegionsHelper(dc
, 10, TRUE
);
851 DrawRegionsHelper(dc
, 350, FALSE
);
854 void MyCanvas
::DrawRegionsHelper(wxDC
& dc
, wxCoord x
, bool firstTime
)
858 dc
.DestroyClippingRegion();
859 dc
.SetBrush( *wxWHITE_BRUSH
);
860 dc
.SetPen( *wxTRANSPARENT_PEN
);
861 dc
.DrawRectangle( x
, y
, 310, 310 );
863 dc
.SetClippingRegion( x
+ 10, y
+ 10, 100, 270 );
865 dc
.SetBrush( *wxRED_BRUSH
);
866 dc
.DrawRectangle( x
, y
, 310, 310 );
868 dc
.SetClippingRegion( x
+ 10, y
+ 10, 100, 100 );
870 dc
.SetBrush( *wxCYAN_BRUSH
);
871 dc
.DrawRectangle( x
, y
, 310, 310 );
873 dc
.DestroyClippingRegion();
875 wxRegion
region(x
+ 110, y
+ 20, 100, 270);
877 region
.Offset(10, 10);
879 dc
.SetClippingRegion(region
);
881 dc
.SetBrush( *wxGREY_BRUSH
);
882 dc
.DrawRectangle( x
, y
, 310, 310 );
884 if (m_smile_bmp
.Ok())
886 dc
.DrawBitmap( m_smile_bmp
, x
+ 150, y
+ 150, TRUE
);
887 dc
.DrawBitmap( m_smile_bmp
, x
+ 130, y
+ 10, TRUE
);
888 dc
.DrawBitmap( m_smile_bmp
, x
+ 130, y
+ 280, TRUE
);
889 dc
.DrawBitmap( m_smile_bmp
, x
+ 100, y
+ 70, TRUE
);
890 dc
.DrawBitmap( m_smile_bmp
, x
+ 200, y
+ 70, TRUE
);
894 void MyCanvas
::OnPaint(wxPaintEvent
&WXUNUSED(event
))
899 m_owner
->PrepareDC(dc
);
901 dc
.SetBackgroundMode( m_owner
->m_backgroundMode
);
902 if ( m_owner
->m_backgroundBrush
.Ok() )
903 dc
.SetBackground( m_owner
->m_backgroundBrush
);
904 if ( m_owner
->m_colourForeground
.Ok() )
905 dc
.SetTextForeground( m_owner
->m_colourForeground
);
906 if ( m_owner
->m_colourBackground
.Ok() )
907 dc
.SetTextBackground( m_owner
->m_colourBackground
);
909 if ( m_owner
->m_textureBackground
) {
910 if ( ! m_owner
->m_backgroundBrush
.Ok() ) {
911 wxBrush
b(wxColour(0,128,0), wxSOLID
);
918 if ( m_owner
->m_textureBackground
) {
919 dc
.SetPen(*wxMEDIUM_GREY_PEN
);
920 for (int i
=0; i
<200; i
++)
921 dc
.DrawLine(0, i
*10, i
*10, 0);
943 DrawTestLines( 0, 100, 0, dc
);
944 DrawTestLines( 0, 320, 1, dc
);
945 DrawTestLines( 0, 540, 2, dc
);
946 DrawTestLines( 0, 760, 6, dc
);
962 DrawWithLogicalOps(dc
);
967 void MyCanvas
::OnMouseMove(wxMouseEvent
&event
)
971 m_owner
->PrepareDC(dc
);
973 wxPoint pos
= event
.GetPosition();
974 long x
= dc
.DeviceToLogicalX( pos
.x
);
975 long y
= dc
.DeviceToLogicalY( pos
.y
);
977 str
.Printf( wxT("Current mouse position: %d,%d"), (int)x
, (int)y
);
978 m_owner
->SetStatusText( str
);
981 // ----------------------------------------------------------------------------
983 // ----------------------------------------------------------------------------
985 // the event tables connect the wxWindows events with the functions (event
986 // handlers) which process them. It can be also done at run-time, but for the
987 // simple menu events like this the static method is much simpler.
988 BEGIN_EVENT_TABLE(MyFrame
, wxFrame
)
989 EVT_MENU (File_Quit
, MyFrame
::OnQuit
)
990 EVT_MENU (File_About
, MyFrame
::OnAbout
)
992 EVT_MENU_RANGE(MenuShow_First
, MenuShow_Last
, MyFrame
::OnShow
)
994 EVT_MENU_RANGE(MenuOption_First
, MenuOption_Last
, MyFrame
::OnOption
)
998 MyFrame
::MyFrame(const wxString
& title
, const wxPoint
& pos
, const wxSize
& size
)
999 : wxFrame((wxFrame
*)NULL
, -1, title
, pos
, size
,
1000 wxDEFAULT_FRAME_STYLE
| wxNO_FULL_REPAINT_ON_RESIZE
)
1002 // set the frame icon
1003 SetIcon(wxICON(mondrian
));
1005 wxMenu
*menuFile
= new wxMenu
;
1006 menuFile
->Append(File_ShowDefault
, "&Default screen\tF1");
1007 menuFile
->Append(File_ShowText
, "&Text screen\tF2");
1008 menuFile
->Append(File_ShowLines
, "&Lines screen\tF3");
1009 menuFile
->Append(File_ShowBrushes
, "&Brushes screen\tF4");
1010 menuFile
->Append(File_ShowPolygons
, "&Polygons screen\tF5");
1011 menuFile
->Append(File_ShowMask
, "&Mask screen\tF6");
1012 menuFile
->Append(File_ShowOps
, "&ROP screen\tF7");
1013 menuFile
->Append(File_ShowRegions
, "Re&gions screen\tF8");
1014 menuFile
->Append(File_ShowCircles
, "&Circles screen\tF9");
1015 menuFile
->AppendSeparator();
1016 menuFile
->Append(File_About
, "&About...\tCtrl-A", "Show about dialog");
1017 menuFile
->AppendSeparator();
1018 menuFile
->Append(File_Quit
, "E&xit\tAlt-X", "Quit this program");
1020 wxMenu
*menuMapMode
= new wxMenu
;
1021 menuMapMode
->Append( MapMode_Text
, "&TEXT map mode" );
1022 menuMapMode
->Append( MapMode_Lometric
, "&LOMETRIC map mode" );
1023 menuMapMode
->Append( MapMode_Twips
, "T&WIPS map mode" );
1024 menuMapMode
->Append( MapMode_Points
, "&POINTS map mode" );
1025 menuMapMode
->Append( MapMode_Metric
, "&METRIC map mode" );
1027 wxMenu
*menuUserScale
= new wxMenu
;
1028 menuUserScale
->Append( UserScale_StretchHoriz
, "Stretch horizontally\tCtrl-H" );
1029 menuUserScale
->Append( UserScale_ShrinkHoriz
, "Shrink horizontally\tCtrl-G" );
1030 menuUserScale
->Append( UserScale_StretchVertic
, "Stretch vertically\tCtrl-V" );
1031 menuUserScale
->Append( UserScale_ShrinkVertic
, "Shrink vertically\tCtrl-W" );
1032 menuUserScale
->AppendSeparator();
1033 menuUserScale
->Append( UserScale_Restore
, "Restore to normal\tCtrl-0" );
1035 wxMenu
*menuAxis
= new wxMenu
;
1036 menuAxis
->Append( AxisMirror_Horiz
, "Mirror horizontally\tCtrl-M", "", TRUE
);
1037 menuAxis
->Append( AxisMirror_Vertic
, "Mirror vertically\tCtrl-N", "", TRUE
);
1039 wxMenu
*menuLogical
= new wxMenu
;
1040 menuLogical
->Append( LogicalOrigin_MoveDown
, "Move &down\tCtrl-D" );
1041 menuLogical
->Append( LogicalOrigin_MoveUp
, "Move &up\tCtrl-U" );
1042 menuLogical
->Append( LogicalOrigin_MoveLeft
, "Move &right\tCtrl-L" );
1043 menuLogical
->Append( LogicalOrigin_MoveRight
, "Move &left\tCtrl-R" );
1045 wxMenu
*menuColour
= new wxMenu
;
1046 menuColour
->Append( Colour_TextForeground
, "Text foreground..." );
1047 menuColour
->Append( Colour_TextBackground
, "Text background..." );
1048 menuColour
->Append( Colour_Background
, "Background colour..." );
1049 menuColour
->Append( Colour_BackgroundMode
, "Opaque/transparent\tCtrl-B", "", TRUE
);
1050 menuColour
->Append( Colour_TextureBackgound
, "Draw textured background\tCtrl-T", "", TRUE
);
1052 // now append the freshly created menu to the menu bar...
1053 wxMenuBar
*menuBar
= new wxMenuBar
;
1054 menuBar
->Append(menuFile
, "&File");
1055 menuBar
->Append(menuMapMode
, "&MapMode");
1056 menuBar
->Append(menuUserScale
, "&UserScale");
1057 menuBar
->Append(menuAxis
, "&Axis");
1058 menuBar
->Append(menuLogical
, "&LogicalOrigin");
1059 menuBar
->Append(menuColour
, "&Colours");
1061 // ... and attach this menu bar to the frame
1062 SetMenuBar(menuBar
);
1064 // create a status bar just for fun (by default with 1 pane only)
1066 SetStatusText("Welcome to wxWindows!");
1068 m_mapMode
= wxMM_TEXT
;
1071 m_xLogicalOrigin
= 0;
1072 m_yLogicalOrigin
= 0;
1074 m_yAxisReversed
= FALSE
;
1075 m_backgroundMode
= wxSOLID
;
1076 m_colourForeground
= *wxRED
;
1077 m_colourBackground
= *wxBLUE
;
1078 m_textureBackground
= FALSE
;
1080 m_canvas
= new MyCanvas( this );
1081 m_canvas
->SetScrollbars( 10, 10, 100, 240 );
1086 void MyFrame
::OnQuit(wxCommandEvent
& WXUNUSED(event
))
1088 // TRUE is to force the frame to close
1092 void MyFrame
::OnAbout(wxCommandEvent
& WXUNUSED(event
))
1095 msg
.Printf( wxT("This is the about dialog of the drawing sample.\n")
1096 wxT("This sample tests various primitive drawing functions\n")
1097 wxT("(without any attempts to prevent flicker).\n")
1098 wxT("Copyright (c) Robert Roebling 1999")
1101 wxMessageBox(msg
, "About Drawing", wxOK
| wxICON_INFORMATION
, this);
1104 void MyFrame
::OnShow(wxCommandEvent
& event
)
1106 m_canvas
->Show((ScreenToShow
)(event
.GetId() - MenuShow_First
));
1109 void MyFrame
::OnOption(wxCommandEvent
& event
)
1111 switch (event
.GetId())
1114 m_mapMode
= wxMM_TEXT
;
1116 case MapMode_Lometric
:
1117 m_mapMode
= wxMM_LOMETRIC
;
1120 m_mapMode
= wxMM_TWIPS
;
1122 case MapMode_Points
:
1123 m_mapMode
= wxMM_POINTS
;
1125 case MapMode_Metric
:
1126 m_mapMode
= wxMM_METRIC
;
1129 case LogicalOrigin_MoveDown
:
1130 m_yLogicalOrigin
+= 10;
1132 case LogicalOrigin_MoveUp
:
1133 m_yLogicalOrigin
-= 10;
1135 case LogicalOrigin_MoveLeft
:
1136 m_xLogicalOrigin
+= 10;
1138 case LogicalOrigin_MoveRight
:
1139 m_xLogicalOrigin
-= 10;
1142 case UserScale_StretchHoriz
:
1143 m_xUserScale
*= 1.10;
1145 case UserScale_ShrinkHoriz
:
1146 m_xUserScale
/= 1.10;
1148 case UserScale_StretchVertic
:
1149 m_yUserScale
*= 1.10;
1151 case UserScale_ShrinkVertic
:
1152 m_yUserScale
/= 1.10;
1154 case UserScale_Restore
:
1159 case AxisMirror_Vertic
:
1160 m_yAxisReversed
= !m_yAxisReversed
;
1162 case AxisMirror_Horiz
:
1163 m_xAxisReversed
= !m_xAxisReversed
;
1166 case Colour_TextForeground
:
1167 m_colourForeground
= SelectColour();
1169 case Colour_TextBackground
:
1170 m_colourBackground
= SelectColour();
1172 case Colour_Background
:
1174 wxColour col
= SelectColour();
1177 m_backgroundBrush
.SetColour(col
);
1181 case Colour_BackgroundMode
:
1182 m_backgroundMode
= m_backgroundMode
== wxSOLID ? wxTRANSPARENT
1186 case Colour_TextureBackgound
:
1187 m_textureBackground
= ! m_textureBackground
;
1195 m_canvas
->Refresh();
1198 void MyFrame
::PrepareDC(wxDC
& dc
)
1200 dc
.SetMapMode( m_mapMode
);
1201 dc
.SetUserScale( m_xUserScale
, m_yUserScale
);
1202 dc
.SetLogicalOrigin( m_xLogicalOrigin
, m_yLogicalOrigin
);
1203 dc
.SetAxisOrientation( !m_xAxisReversed
, m_yAxisReversed
);
1206 wxColour MyFrame
::SelectColour()
1210 wxColourDialog
dialog(this, &data
);
1212 if ( dialog
.ShowModal() == wxID_OK
)
1214 col
= dialog
.GetColourData().GetColour();