1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: shows and tests wxDC features
4 // Author: Robert Roebling
8 // Copyright: (c) Robert Roebling
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
14 // ============================================================================
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
20 #if defined(__GNUG__) && !defined(__APPLE__)
21 #pragma implementation "drawing.cpp"
22 #pragma interface "drawing.cpp"
25 // For compilers that support precompilation, includes "wx/wx.h".
26 #include "wx/wxprec.h"
32 // for all others, include the necessary headers (this file is usually all you
33 // need because it includes almost all "standard" wxWidgets 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 wxWidgets 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 ToShow(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 wxWidgets
242 // ----------------------------------------------------------------------------
245 // Create a new application object: this macro will allow wxWidgets 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
;
271 pathList
.Add(_T("."));
272 pathList
.Add(_T(".."));
274 wxString path
= pathList
.FindValidPath(_T("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(_T("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(_T("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(_T("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(_T("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 wxWidgets 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
, wxID_ANY
, wxDefaultPosition
, wxDefaultSize
,
374 wxHSCROLL
| wxVSCROLL
| wxNO_FULL_REPAINT_ON_RESIZE
)
377 m_show
= Show_Default
;
378 m_smile_bmp
= wxBitmap(smile_xpm
);
379 m_std_icon
= wxArtProvider::GetIcon(wxART_INFORMATION
);
383 void MyCanvas::DrawTestBrushes(wxDC
& dc
)
385 static const wxCoord WIDTH
= 200;
386 static const wxCoord HEIGHT
= 80;
391 dc
.SetBrush(wxBrush(*wxGREEN
, wxSOLID
));
392 dc
.DrawRectangle(x
, y
, WIDTH
, HEIGHT
);
393 dc
.DrawText(_T("Solid green"), x
+ 10, y
+ 10);
396 dc
.SetBrush(wxBrush(*wxRED
, wxCROSSDIAG_HATCH
));
397 dc
.DrawRectangle(x
, y
, WIDTH
, HEIGHT
);
398 dc
.DrawText(_T("Hatched red"), x
+ 10, y
+ 10);
401 dc
.SetBrush(wxBrush(*gs_bmpMask
));
402 dc
.DrawRectangle(x
, y
, WIDTH
, HEIGHT
);
403 dc
.DrawText(_T("Stipple mono"), x
+ 10, y
+ 10);
406 dc
.SetBrush(wxBrush(*gs_bmpNoMask
));
407 dc
.DrawRectangle(x
, y
, WIDTH
, HEIGHT
);
408 dc
.DrawText(_T("Stipple colour"), x
+ 10, y
+ 10);
411 void MyCanvas::DrawTestPoly(wxDC
& dc
)
413 wxBrush
brushHatch(*wxRED
, wxFDIAGONAL_HATCH
);
414 dc
.SetBrush(brushHatch
);
417 star
[0] = wxPoint(100, 60);
418 star
[1] = wxPoint(60, 150);
419 star
[2] = wxPoint(160, 100);
420 star
[3] = wxPoint(40, 100);
421 star
[4] = wxPoint(140, 150);
423 dc
.DrawText(_T("You should see two (irregular) stars below, the left one ")
424 _T("hatched"), 10, 10);
425 dc
.DrawText(_T("except for the central region and the right ")
426 _T("one entirely hatched"), 10, 30);
427 dc
.DrawText(_T("The third star only has a hatched outline"), 10, 50);
429 dc
.DrawPolygon(WXSIZEOF(star
), star
, 0, 30);
430 dc
.DrawPolygon(WXSIZEOF(star
), star
, 160, 30, wxWINDING_RULE
);
433 star2
[0] = wxPoint(0, 100);
434 star2
[1] = wxPoint(-59, -81);
435 star2
[2] = wxPoint(95, 31);
436 star2
[3] = wxPoint(-95, 31);
437 star2
[4] = wxPoint(59, -81);
438 star2
[5] = wxPoint(0, 80);
439 star2
[6] = wxPoint(-47, -64);
440 star2
[7] = wxPoint(76, 24);
441 star2
[8] = wxPoint(-76, 24);
442 star2
[9] = wxPoint(47, -64);
443 int count
[2] = {5, 5};
445 dc
.DrawPolyPolygon(WXSIZEOF(count
), count
, star2
, 450, 150);
448 void MyCanvas::DrawTestLines( int x
, int y
, int width
, wxDC
&dc
)
450 dc
.SetPen( wxPen( wxT("black"), width
, wxSOLID
) );
451 dc
.SetBrush( *wxRED_BRUSH
);
452 dc
.DrawText(wxString::Format(wxT("Testing lines of width %d"), width
), x
+ 10, y
- 10);
453 dc
.DrawRectangle( x
+10, y
+10, 100, 190 );
455 dc
.DrawText(_T("Solid/dot/short dash/long dash/dot dash"), x
+ 150, y
+ 10);
456 dc
.SetPen( wxPen( wxT("black"), width
, wxSOLID
) );
457 dc
.DrawLine( x
+20, y
+20, 100, y
+20 );
458 dc
.SetPen( wxPen( wxT("black"), width
, wxDOT
) );
459 dc
.DrawLine( x
+20, y
+30, 100, y
+30 );
460 dc
.SetPen( wxPen( wxT("black"), width
, wxSHORT_DASH
) );
461 dc
.DrawLine( x
+20, y
+40, 100, y
+40 );
462 dc
.SetPen( wxPen( wxT("black"), width
, wxLONG_DASH
) );
463 dc
.DrawLine( x
+20, y
+50, 100, y
+50 );
464 dc
.SetPen( wxPen( wxT("black"), width
, wxDOT_DASH
) );
465 dc
.DrawLine( x
+20, y
+60, 100, y
+60 );
467 dc
.DrawText(_T("Misc hatches"), x
+ 150, y
+ 70);
468 dc
.SetPen( wxPen( wxT("black"), width
, wxBDIAGONAL_HATCH
) );
469 dc
.DrawLine( x
+20, y
+70, 100, y
+70 );
470 dc
.SetPen( wxPen( wxT("black"), width
, wxCROSSDIAG_HATCH
) );
471 dc
.DrawLine( x
+20, y
+80, 100, y
+80 );
472 dc
.SetPen( wxPen( wxT("black"), width
, wxFDIAGONAL_HATCH
) );
473 dc
.DrawLine( x
+20, y
+90, 100, y
+90 );
474 dc
.SetPen( wxPen( wxT("black"), width
, wxCROSS_HATCH
) );
475 dc
.DrawLine( x
+20, y
+100, 100, y
+100 );
476 dc
.SetPen( wxPen( wxT("black"), width
, wxHORIZONTAL_HATCH
) );
477 dc
.DrawLine( x
+20, y
+110, 100, y
+110 );
478 dc
.SetPen( wxPen( wxT("black"), width
, wxVERTICAL_HATCH
) );
479 dc
.DrawLine( x
+20, y
+120, 100, y
+120 );
481 dc
.DrawText(_T("User dash"), x
+ 150, y
+ 140);
482 wxPen
ud( wxT("black"), width
, wxUSER_DASH
);
484 dash1
[0] = 8; // Long dash <---------+
485 dash1
[1] = 2; // Short gap |
486 dash1
[2] = 3; // Short dash |
487 dash1
[3] = 2; // Short gap |
488 dash1
[4] = 3; // Short dash |
489 dash1
[5] = 2; // Short gap and repeat +
490 ud
.SetDashes( 6, dash1
);
492 dc
.DrawLine( x
+20, y
+140, 100, y
+140 );
493 dash1
[0] = 5; // Make first dash shorter
494 ud
.SetDashes( 6, dash1
);
496 dc
.DrawLine( x
+20, y
+150, 100, y
+150 );
497 dash1
[2] = 5; // Make second dash longer
498 ud
.SetDashes( 6, dash1
);
500 dc
.DrawLine( x
+20, y
+160, 100, y
+160 );
501 dash1
[4] = 5; // Make third dash longer
502 ud
.SetDashes( 6, dash1
);
504 dc
.DrawLine( x
+20, y
+170, 100, y
+170 );
507 void MyCanvas::DrawDefault(wxDC
& dc
)
510 dc
.DrawCircle(0, 0, 10);
512 //flood fill using brush, starting at 1,1 and replacing whatever colour we find there
513 dc
.SetBrush(wxBrush(wxColour(128,128,0), wxSOLID
));
515 dc
.GetPixel(1,1, &tmpColour
);
516 dc
.FloodFill(1,1, tmpColour
, wxFLOOD_SURFACE
);
518 dc
.DrawCheckMark(5, 80, 15, 15);
519 dc
.DrawCheckMark(25, 80, 30, 30);
520 dc
.DrawCheckMark(60, 80, 60, 60);
522 // this is the test for "blitting bitmap into DC damages selected brush" bug
523 wxCoord rectSize
= m_std_icon
.GetWidth() + 10;
525 dc
.SetPen(*wxTRANSPARENT_PEN
);
526 dc
.SetBrush( *wxGREEN_BRUSH
);
527 dc
.DrawRectangle(x
, 10, rectSize
, rectSize
);
528 dc
.DrawBitmap(m_std_icon
, x
+ 5, 15, true);
530 dc
.DrawRectangle(x
, 10, rectSize
, rectSize
);
531 dc
.DrawIcon(m_std_icon
, x
+ 5, 15);
533 dc
.DrawRectangle(x
, 10, rectSize
, rectSize
);
535 // test for "transparent" bitmap drawing (it intersects with the last
537 //dc.SetBrush( *wxTRANSPARENT_BRUSH );
539 if (m_smile_bmp
.Ok())
540 dc
.DrawBitmap(m_smile_bmp
, x
+ rectSize
- 20, rectSize
- 10, true);
542 dc
.SetBrush( *wxBLACK_BRUSH
);
543 dc
.DrawRectangle( 0, 160, 1000, 300 );
546 wxBitmap
bitmap(20,70);
548 memdc
.SelectObject( bitmap
);
549 memdc
.SetBrush( *wxBLACK_BRUSH
);
550 memdc
.SetPen( *wxWHITE_PEN
);
551 memdc
.DrawRectangle(0,0,20,70);
552 memdc
.DrawLine( 10,0,10,70 );
555 wxPen pen
= *wxRED_PEN
;
557 memdc
.DrawLine( 10, 5,10, 5 );
558 memdc
.DrawLine( 10,10,11,10 );
559 memdc
.DrawLine( 10,15,12,15 );
560 memdc
.DrawLine( 10,20,13,20 );
563 memdc.SetPen(*wxRED_PEN);
564 memdc.DrawLine( 12, 5,12, 5 );
565 memdc.DrawLine( 12,10,13,10 );
566 memdc.DrawLine( 12,15,14,15 );
567 memdc.DrawLine( 12,20,15,20 );
571 memdc
.DrawLine( 10,25,10,25 );
572 memdc
.DrawLine( 10,30, 9,30 );
573 memdc
.DrawLine( 10,35, 8,35 );
574 memdc
.DrawLine( 10,40, 7,40 );
577 dc
.SetPen(*wxWHITE_PEN
);
578 memdc
.SetLogicalFunction( wxINVERT
);
579 memdc
.SetPen( *wxWHITE_PEN
);
580 memdc
.DrawLine( 10,50,10,50 );
581 memdc
.DrawLine( 10,55,11,55 );
582 memdc
.DrawLine( 10,60,12,60 );
583 memdc
.DrawLine( 10,65,13,65 );
585 memdc
.DrawLine( 12,50,12,50 );
586 memdc
.DrawLine( 12,55,13,55 );
587 memdc
.DrawLine( 12,60,14,60 );
588 memdc
.DrawLine( 12,65,15,65 );
590 memdc
.SelectObject( wxNullBitmap
);
591 dc
.DrawBitmap( bitmap
, 10, 170 );
592 wxImage image
= bitmap
.ConvertToImage();
593 image
.Rescale( 60,210 );
594 bitmap
= wxBitmap(image
);
595 dc
.DrawBitmap( bitmap
, 50, 170 );
597 // test the rectangle outline drawing - there should be one pixel between
598 // the rect and the lines
599 dc
.SetPen(*wxWHITE_PEN
);
600 dc
.SetBrush( *wxTRANSPARENT_BRUSH
);
601 dc
.DrawRectangle(150, 170, 49, 29);
602 dc
.DrawRectangle(200, 170, 49, 29);
603 dc
.SetPen(*wxWHITE_PEN
);
604 dc
.DrawLine(250, 210, 250, 170);
605 dc
.DrawLine(260, 200, 150, 200);
607 // test the rectangle filled drawing - there should be one pixel between
608 // the rect and the lines
609 dc
.SetPen(*wxTRANSPARENT_PEN
);
610 dc
.SetBrush( *wxWHITE_BRUSH
);
611 dc
.DrawRectangle(300, 170, 49, 29);
612 dc
.DrawRectangle(350, 170, 49, 29);
613 dc
.SetPen(*wxWHITE_PEN
);
614 dc
.DrawLine(400, 170, 400, 210);
615 dc
.DrawLine(300, 200, 410, 200);
617 // a few more tests of this kind
618 dc
.SetPen(*wxRED_PEN
);
619 dc
.SetBrush( *wxWHITE_BRUSH
);
620 dc
.DrawRectangle(300, 220, 1, 1);
621 dc
.DrawRectangle(310, 220, 2, 2);
622 dc
.DrawRectangle(320, 220, 3, 3);
623 dc
.DrawRectangle(330, 220, 4, 4);
625 dc
.SetPen(*wxTRANSPARENT_PEN
);
626 dc
.SetBrush( *wxWHITE_BRUSH
);
627 dc
.DrawRectangle(300, 230, 1, 1);
628 dc
.DrawRectangle(310, 230, 2, 2);
629 dc
.DrawRectangle(320, 230, 3, 3);
630 dc
.DrawRectangle(330, 230, 4, 4);
632 // and now for filled rect with outline
633 dc
.SetPen(*wxRED_PEN
);
634 dc
.SetBrush( *wxWHITE_BRUSH
);
635 dc
.DrawRectangle(500, 170, 49, 29);
636 dc
.DrawRectangle(550, 170, 49, 29);
637 dc
.SetPen(*wxWHITE_PEN
);
638 dc
.DrawLine(600, 170, 600, 210);
639 dc
.DrawLine(500, 200, 610, 200);
641 // test the rectangle outline drawing - there should be one pixel between
642 // the rect and the lines
643 dc
.SetPen(*wxWHITE_PEN
);
644 dc
.SetBrush( *wxTRANSPARENT_BRUSH
);
645 dc
.DrawRoundedRectangle(150, 270, 49, 29, 6);
646 dc
.DrawRoundedRectangle(200, 270, 49, 29, 6);
647 dc
.SetPen(*wxWHITE_PEN
);
648 dc
.DrawLine(250, 270, 250, 310);
649 dc
.DrawLine(150, 300, 260, 300);
651 // test the rectangle filled drawing - there should be one pixel between
652 // the rect and the lines
653 dc
.SetPen(*wxTRANSPARENT_PEN
);
654 dc
.SetBrush( *wxWHITE_BRUSH
);
655 dc
.DrawRoundedRectangle(300, 270, 49, 29, 6);
656 dc
.DrawRoundedRectangle(350, 270, 49, 29, 6);
657 dc
.SetPen(*wxWHITE_PEN
);
658 dc
.DrawLine(400, 270, 400, 310);
659 dc
.DrawLine(300, 300, 410, 300);
661 // Added by JACS to demonstrate bizarre behaviour.
662 // With a size of 70, we get a missing red RHS,
663 // and the hight is too small, so we get yellow
664 // showing. With a size of 40, it draws as expected:
665 // it just shows a white rectangle with red outline.
667 int totalHeight
= 70;
668 wxBitmap
bitmap2(totalWidth
, totalHeight
);
671 memdc2
.SelectObject(bitmap2
);
673 wxBrush
yellowBrush(wxColour(255, 255, 0), wxSOLID
);
674 memdc2
.SetBackground(yellowBrush
);
677 wxPen
yellowPen(wxColour(255, 255, 0), 1, wxSOLID
);
679 // Now draw a white rectangle with red outline. It should
680 // entirely eclipse the yellow background.
681 memdc2
.SetPen(*wxRED_PEN
);
682 memdc2
.SetBrush(*wxWHITE_BRUSH
);
684 memdc2
.DrawRectangle(0, 0, totalWidth
, totalHeight
);
686 memdc2
.SetPen(wxNullPen
);
687 memdc2
.SetBrush(wxNullBrush
);
688 memdc2
.SelectObject(wxNullBitmap
);
690 dc
.DrawBitmap(bitmap2
, 500, 270);
692 // Repeat, but draw directly on dc
693 // Draw a yellow rectangle filling the bitmap
695 x
= 600; int y
= 270;
696 dc
.SetPen(yellowPen
);
697 dc
.SetBrush(yellowBrush
);
698 dc
.DrawRectangle(x
, y
, totalWidth
, totalHeight
);
700 // Now draw a white rectangle with red outline. It should
701 // entirely eclipse the yellow background.
702 dc
.SetPen(*wxRED_PEN
);
703 dc
.SetBrush(*wxWHITE_BRUSH
);
705 dc
.DrawRectangle(x
, y
, totalWidth
, totalHeight
);
708 void MyCanvas::DrawText(wxDC
& dc
)
710 // set underlined font for testing
711 dc
.SetFont( wxFont(12, wxMODERN
, wxNORMAL
, wxNORMAL
, true) );
712 dc
.DrawText( _T("This is text"), 110, 10 );
713 dc
.DrawRotatedText( _T("That is text"), 20, 10, -45 );
715 // use wxSWISS_FONT and not wxNORMAL_FONT as the latter can't be rotated
716 // under Win9x (it is not TrueType)
717 dc
.SetFont( *wxSWISS_FONT
);
720 dc
.SetBackgroundMode(wxTRANSPARENT
);
722 for ( int n
= -180; n
< 180; n
+= 30 )
724 text
.Printf(wxT(" %d rotated text"), n
);
725 dc
.DrawRotatedText(text
, 400, 400, n
);
728 dc
.SetFont( wxFont( 18, wxSWISS
, wxNORMAL
, wxNORMAL
) );
730 dc
.DrawText( _T("This is Swiss 18pt text."), 110, 40 );
735 dc
.GetTextExtent( _T("This is Swiss 18pt text."), &length
, &height
, &descent
);
736 text
.Printf( wxT("Dimensions are length %ld, height %ld, descent %ld"), length
, height
, descent
);
737 dc
.DrawText( text
, 110, 80 );
739 text
.Printf( wxT("CharHeight() returns: %d"), dc
.GetCharHeight() );
740 dc
.DrawText( text
, 110, 120 );
742 dc
.DrawRectangle( 100, 40, 4, height
);
744 // test the logical function effect
746 dc
.SetLogicalFunction(wxINVERT
);
747 dc
.DrawText( _T("There should be no text below"), 110, 150 );
748 dc
.DrawRectangle( 110, y
, 100, height
);
750 // twice drawn inverted should result in invisible
752 dc
.DrawText( _T("Invisible text"), 110, y
);
753 dc
.DrawRectangle( 110, y
, 100, height
);
754 dc
.DrawText( _T("Invisible text"), 110, y
);
755 dc
.DrawRectangle( 110, y
, 100, height
);
756 dc
.SetLogicalFunction(wxCOPY
);
759 dc
.DrawRectangle( 110, y
, 100, height
);
760 dc
.DrawText( _T("Visible text"), 110, y
);
767 } rasterOperations
[] =
769 { wxT("wxAND"), wxAND
},
770 { wxT("wxAND_INVERT"), wxAND_INVERT
},
771 { wxT("wxAND_REVERSE"), wxAND_REVERSE
},
772 { wxT("wxCLEAR"), wxCLEAR
},
773 { wxT("wxCOPY"), wxCOPY
},
774 { wxT("wxEQUIV"), wxEQUIV
},
775 { wxT("wxINVERT"), wxINVERT
},
776 { wxT("wxNAND"), wxNAND
},
777 { wxT("wxNO_OP"), wxNO_OP
},
778 { wxT("wxOR"), wxOR
},
779 { wxT("wxOR_INVERT"), wxOR_INVERT
},
780 { wxT("wxOR_REVERSE"), wxOR_REVERSE
},
781 { wxT("wxSET"), wxSET
},
782 { wxT("wxSRC_INVERT"), wxSRC_INVERT
},
783 { wxT("wxXOR"), wxXOR
},
786 void MyCanvas::DrawImages(wxDC
& dc
)
788 dc
.DrawText(_T("original image"), 0, 0);
789 dc
.DrawBitmap(*gs_bmpNoMask
, 0, 20, 0);
790 dc
.DrawText(_T("with colour mask"), 0, 100);
791 dc
.DrawBitmap(*gs_bmpWithColMask
, 0, 120, true);
792 dc
.DrawText(_T("the mask image"), 0, 200);
793 dc
.DrawBitmap(*gs_bmpMask
, 0, 220, 0);
794 dc
.DrawText(_T("masked image"), 0, 300);
795 dc
.DrawBitmap(*gs_bmpWithMask
, 0, 320, true);
797 int cx
= gs_bmpWithColMask
->GetWidth(),
798 cy
= gs_bmpWithColMask
->GetHeight();
801 for ( size_t n
= 0; n
< WXSIZEOF(rasterOperations
); n
++ )
803 wxCoord x
= 120 + 150*(n%4
),
806 dc
.DrawText(rasterOperations
[n
].name
, x
, y
- 20);
807 memDC
.SelectObject(*gs_bmpWithColMask
);
808 dc
.Blit(x
, y
, cx
, cy
, &memDC
, 0, 0, rasterOperations
[n
].rop
, true);
812 void MyCanvas::DrawWithLogicalOps(wxDC
& dc
)
814 static const wxCoord w
= 60;
815 static const wxCoord h
= 60;
817 // reuse the text colour here
818 dc
.SetPen(wxPen(m_owner
->m_colourForeground
, 1, wxSOLID
));
819 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
822 for ( n
= 0; n
< WXSIZEOF(rasterOperations
); n
++ )
824 wxCoord x
= 20 + 150*(n%4
),
827 dc
.DrawText(rasterOperations
[n
].name
, x
, y
- 20);
828 dc
.SetLogicalFunction(rasterOperations
[n
].rop
);
829 dc
.DrawRectangle(x
, y
, w
, h
);
830 dc
.DrawLine(x
, y
, x
+ w
, y
+ h
);
831 dc
.DrawLine(x
+ w
, y
, x
, y
+ h
);
834 // now some filled rectangles
835 dc
.SetBrush(wxBrush(m_owner
->m_colourForeground
, wxSOLID
));
837 for ( n
= 0; n
< WXSIZEOF(rasterOperations
); n
++ )
839 wxCoord x
= 20 + 150*(n%4
),
842 dc
.DrawText(rasterOperations
[n
].name
, x
, y
- 20);
843 dc
.SetLogicalFunction(rasterOperations
[n
].rop
);
844 dc
.DrawRectangle(x
, y
, w
, h
);
848 void MyCanvas::DrawCircles(wxDC
& dc
)
854 dc
.DrawText(_T("Some circles"), 0, y
);
855 dc
.DrawCircle(x
, y
, r
);
856 dc
.DrawCircle(x
+ 2*r
, y
, r
);
857 dc
.DrawCircle(x
+ 4*r
, y
, r
);
860 dc
.DrawText(_T("And ellipses"), 0, y
);
861 dc
.DrawEllipse(x
- r
, y
, 2*r
, r
);
862 dc
.DrawEllipse(x
+ r
, y
, 2*r
, r
);
863 dc
.DrawEllipse(x
+ 3*r
, y
, 2*r
, r
);
866 dc
.DrawText(_T("And arcs"), 0, y
);
867 dc
.DrawArc(x
- r
, y
, x
+ r
, y
, x
, y
);
868 dc
.DrawArc(x
+ 4*r
, y
, x
+ 2*r
, y
, x
+ 3*r
, y
);
869 dc
.DrawArc(x
+ 5*r
, y
, x
+ 5*r
, y
, x
+ 6*r
, y
);
872 dc
.DrawEllipticArc(x
- r
, y
, 2*r
, r
, 0, 90);
873 dc
.DrawEllipticArc(x
+ r
, y
, 2*r
, r
, 90, 180);
874 dc
.DrawEllipticArc(x
+ 3*r
, y
, 2*r
, r
, 180, 270);
875 dc
.DrawEllipticArc(x
+ 5*r
, y
, 2*r
, r
, 270, 360);
878 void MyCanvas::DrawRegions(wxDC
& dc
)
880 dc
.DrawText(_T("You should see a red rect partly covered by a cyan one ")
881 _T("on the left"), 10, 5);
882 dc
.DrawText(_T("and 5 smileys from which 4 are partially clipped on the right"),
883 10, 5 + dc
.GetCharHeight());
884 dc
.DrawText(_T("The second copy should be identical but right part of it ")
885 _T("should be offset by 10 pixels."),
886 10, 5 + 2*dc
.GetCharHeight());
888 DrawRegionsHelper(dc
, 10, true);
889 DrawRegionsHelper(dc
, 350, false);
892 void MyCanvas::DrawRegionsHelper(wxDC
& dc
, wxCoord x
, bool firstTime
)
896 dc
.DestroyClippingRegion();
897 dc
.SetBrush( *wxWHITE_BRUSH
);
898 dc
.SetPen( *wxTRANSPARENT_PEN
);
899 dc
.DrawRectangle( x
, y
, 310, 310 );
901 dc
.SetClippingRegion( x
+ 10, y
+ 10, 100, 270 );
903 dc
.SetBrush( *wxRED_BRUSH
);
904 dc
.DrawRectangle( x
, y
, 310, 310 );
906 dc
.SetClippingRegion( x
+ 10, y
+ 10, 100, 100 );
908 dc
.SetBrush( *wxCYAN_BRUSH
);
909 dc
.DrawRectangle( x
, y
, 310, 310 );
911 dc
.DestroyClippingRegion();
913 wxRegion
region(x
+ 110, y
+ 20, 100, 270);
914 #if !defined(__WXMOTIF__) && !defined(__WXMAC__)
916 region
.Offset(10, 10);
918 dc
.SetClippingRegion(region
);
920 dc
.SetBrush( *wxGREY_BRUSH
);
921 dc
.DrawRectangle( x
, y
, 310, 310 );
923 if (m_smile_bmp
.Ok())
925 dc
.DrawBitmap( m_smile_bmp
, x
+ 150, y
+ 150, true );
926 dc
.DrawBitmap( m_smile_bmp
, x
+ 130, y
+ 10, true );
927 dc
.DrawBitmap( m_smile_bmp
, x
+ 130, y
+ 280, true );
928 dc
.DrawBitmap( m_smile_bmp
, x
+ 100, y
+ 70, true );
929 dc
.DrawBitmap( m_smile_bmp
, x
+ 200, y
+ 70, true );
933 void MyCanvas::OnPaint(wxPaintEvent
&WXUNUSED(event
))
938 m_owner
->PrepareDC(dc
);
940 dc
.SetBackgroundMode( m_owner
->m_backgroundMode
);
941 if ( m_owner
->m_backgroundBrush
.Ok() )
942 dc
.SetBackground( m_owner
->m_backgroundBrush
);
943 if ( m_owner
->m_colourForeground
.Ok() )
944 dc
.SetTextForeground( m_owner
->m_colourForeground
);
945 if ( m_owner
->m_colourBackground
.Ok() )
946 dc
.SetTextBackground( m_owner
->m_colourBackground
);
948 if ( m_owner
->m_textureBackground
) {
949 if ( ! m_owner
->m_backgroundBrush
.Ok() ) {
950 wxBrush
b(wxColour(0,128,0), wxSOLID
);
956 dc
.SetClippingRegion(100, 100, 100, 100);
960 if ( m_owner
->m_textureBackground
)
962 dc
.SetPen(*wxMEDIUM_GREY_PEN
);
963 for ( int i
= 0; i
< 200; i
++ )
964 dc
.DrawLine(0, i
*10, i
*10, 0);
986 DrawTestLines( 0, 100, 0, dc
);
987 DrawTestLines( 0, 320, 1, dc
);
988 DrawTestLines( 0, 540, 2, dc
);
989 DrawTestLines( 0, 760, 6, dc
);
1005 DrawWithLogicalOps(dc
);
1010 void MyCanvas::OnMouseMove(wxMouseEvent
&event
)
1012 wxClientDC
dc(this);
1014 m_owner
->PrepareDC(dc
);
1016 wxPoint pos
= event
.GetPosition();
1017 long x
= dc
.DeviceToLogicalX( pos
.x
);
1018 long y
= dc
.DeviceToLogicalY( pos
.y
);
1020 str
.Printf( wxT("Current mouse position: %d,%d"), (int)x
, (int)y
);
1021 m_owner
->SetStatusText( str
);
1024 // ----------------------------------------------------------------------------
1026 // ----------------------------------------------------------------------------
1028 // the event tables connect the wxWidgets events with the functions (event
1029 // handlers) which process them. It can be also done at run-time, but for the
1030 // simple menu events like this the static method is much simpler.
1031 BEGIN_EVENT_TABLE(MyFrame
, wxFrame
)
1032 EVT_MENU (File_Quit
, MyFrame::OnQuit
)
1033 EVT_MENU (File_About
, MyFrame::OnAbout
)
1034 EVT_MENU (File_Clip
, MyFrame::OnClip
)
1036 EVT_MENU_RANGE(MenuShow_First
, MenuShow_Last
, MyFrame::OnShow
)
1038 EVT_MENU_RANGE(MenuOption_First
, MenuOption_Last
, MyFrame::OnOption
)
1041 // frame constructor
1042 MyFrame::MyFrame(const wxString
& title
, const wxPoint
& pos
, const wxSize
& size
)
1043 : wxFrame((wxFrame
*)NULL
, wxID_ANY
, title
, pos
, size
,
1044 wxDEFAULT_FRAME_STYLE
| wxNO_FULL_REPAINT_ON_RESIZE
)
1046 // set the frame icon
1047 SetIcon(wxICON(mondrian
));
1049 wxMenu
*menuFile
= new wxMenu
;
1050 menuFile
->Append(File_ShowDefault
, _T("&Default screen\tF1"));
1051 menuFile
->Append(File_ShowText
, _T("&Text screen\tF2"));
1052 menuFile
->Append(File_ShowLines
, _T("&Lines screen\tF3"));
1053 menuFile
->Append(File_ShowBrushes
, _T("&Brushes screen\tF4"));
1054 menuFile
->Append(File_ShowPolygons
, _T("&Polygons screen\tF5"));
1055 menuFile
->Append(File_ShowMask
, _T("&Mask screen\tF6"));
1056 menuFile
->Append(File_ShowOps
, _T("&ROP screen\tF7"));
1057 menuFile
->Append(File_ShowRegions
, _T("Re&gions screen\tF8"));
1058 menuFile
->Append(File_ShowCircles
, _T("&Circles screen\tF9"));
1059 menuFile
->AppendSeparator();
1060 menuFile
->AppendCheckItem(File_Clip
, _T("&Clip\tCtrl-C"), _T("Clip/unclip drawing"));
1061 menuFile
->AppendSeparator();
1062 menuFile
->Append(File_About
, _T("&About...\tCtrl-A"), _T("Show about dialog"));
1063 menuFile
->AppendSeparator();
1064 menuFile
->Append(File_Quit
, _T("E&xit\tAlt-X"), _T("Quit this program"));
1066 wxMenu
*menuMapMode
= new wxMenu
;
1067 menuMapMode
->Append( MapMode_Text
, _T("&TEXT map mode") );
1068 menuMapMode
->Append( MapMode_Lometric
, _T("&LOMETRIC map mode") );
1069 menuMapMode
->Append( MapMode_Twips
, _T("T&WIPS map mode") );
1070 menuMapMode
->Append( MapMode_Points
, _T("&POINTS map mode") );
1071 menuMapMode
->Append( MapMode_Metric
, _T("&METRIC map mode") );
1073 wxMenu
*menuUserScale
= new wxMenu
;
1074 menuUserScale
->Append( UserScale_StretchHoriz
, _T("Stretch &horizontally\tCtrl-H") );
1075 menuUserScale
->Append( UserScale_ShrinkHoriz
, _T("Shrin&k horizontally\tCtrl-G") );
1076 menuUserScale
->Append( UserScale_StretchVertic
, _T("Stretch &vertically\tCtrl-V") );
1077 menuUserScale
->Append( UserScale_ShrinkVertic
, _T("&Shrink vertically\tCtrl-W") );
1078 menuUserScale
->AppendSeparator();
1079 menuUserScale
->Append( UserScale_Restore
, _T("&Restore to normal\tCtrl-0") );
1081 wxMenu
*menuAxis
= new wxMenu
;
1082 menuAxis
->Append( AxisMirror_Horiz
, _T("Mirror horizontally\tCtrl-M"), _T(""), true );
1083 menuAxis
->Append( AxisMirror_Vertic
, _T("Mirror vertically\tCtrl-N"), _T(""), true );
1085 wxMenu
*menuLogical
= new wxMenu
;
1086 menuLogical
->Append( LogicalOrigin_MoveDown
, _T("Move &down\tCtrl-D") );
1087 menuLogical
->Append( LogicalOrigin_MoveUp
, _T("Move &up\tCtrl-U") );
1088 menuLogical
->Append( LogicalOrigin_MoveLeft
, _T("Move &right\tCtrl-L") );
1089 menuLogical
->Append( LogicalOrigin_MoveRight
, _T("Move &left\tCtrl-R") );
1090 menuLogical
->AppendSeparator();
1091 menuLogical
->Append( LogicalOrigin_Set
, _T("Set to (&100, 100)\tShift-Ctrl-1") );
1092 menuLogical
->Append( LogicalOrigin_Restore
, _T("&Restore to normal\tShift-Ctrl-0") );
1094 wxMenu
*menuColour
= new wxMenu
;
1095 menuColour
->Append( Colour_TextForeground
, _T("Text &foreground...") );
1096 menuColour
->Append( Colour_TextBackground
, _T("Text &background...") );
1097 menuColour
->Append( Colour_Background
, _T("Background &colour...") );
1098 menuColour
->Append( Colour_BackgroundMode
, _T("&Opaque/transparent\tCtrl-B"), _T(""), true );
1099 menuColour
->Append( Colour_TextureBackgound
, _T("Draw textured back&ground\tCtrl-T"), _T(""), true);
1101 // now append the freshly created menu to the menu bar...
1102 wxMenuBar
*menuBar
= new wxMenuBar
;
1103 menuBar
->Append(menuFile
, _T("&File"));
1104 menuBar
->Append(menuMapMode
, _T("&Mode"));
1105 menuBar
->Append(menuUserScale
, _T("&Scale"));
1106 menuBar
->Append(menuAxis
, _T("&Axis"));
1107 menuBar
->Append(menuLogical
, _T("&Origin"));
1108 menuBar
->Append(menuColour
, _T("&Colours"));
1110 // ... and attach this menu bar to the frame
1111 SetMenuBar(menuBar
);
1113 // create a status bar just for fun (by default with 1 pane only)
1115 SetStatusText(_T("Welcome to wxWidgets!"));
1117 m_mapMode
= wxMM_TEXT
;
1120 m_xLogicalOrigin
= 0;
1121 m_yLogicalOrigin
= 0;
1123 m_yAxisReversed
= false;
1124 m_backgroundMode
= wxSOLID
;
1125 m_colourForeground
= *wxRED
;
1126 m_colourBackground
= *wxBLUE
;
1127 m_textureBackground
= false;
1129 m_canvas
= new MyCanvas( this );
1130 m_canvas
->SetScrollbars( 10, 10, 100, 240 );
1135 void MyFrame::OnQuit(wxCommandEvent
& WXUNUSED(event
))
1137 // true is to force the frame to close
1141 void MyFrame::OnAbout(wxCommandEvent
& WXUNUSED(event
))
1144 msg
.Printf( wxT("This is the about dialog of the drawing sample.\n")
1145 wxT("This sample tests various primitive drawing functions\n")
1146 wxT("(without any attempts to prevent flicker).\n")
1147 wxT("Copyright (c) Robert Roebling 1999")
1150 wxMessageBox(msg
, _T("About Drawing"), wxOK
| wxICON_INFORMATION
, this);
1153 void MyFrame::OnClip(wxCommandEvent
& event
)
1155 m_canvas
->Clip(event
.IsChecked());
1158 void MyFrame::OnShow(wxCommandEvent
& event
)
1160 m_canvas
->ToShow((ScreenToShow
)(event
.GetId() - MenuShow_First
));
1163 void MyFrame::OnOption(wxCommandEvent
& event
)
1165 switch (event
.GetId())
1168 m_mapMode
= wxMM_TEXT
;
1170 case MapMode_Lometric
:
1171 m_mapMode
= wxMM_LOMETRIC
;
1174 m_mapMode
= wxMM_TWIPS
;
1176 case MapMode_Points
:
1177 m_mapMode
= wxMM_POINTS
;
1179 case MapMode_Metric
:
1180 m_mapMode
= wxMM_METRIC
;
1183 case LogicalOrigin_MoveDown
:
1184 m_yLogicalOrigin
+= 10;
1186 case LogicalOrigin_MoveUp
:
1187 m_yLogicalOrigin
-= 10;
1189 case LogicalOrigin_MoveLeft
:
1190 m_xLogicalOrigin
+= 10;
1192 case LogicalOrigin_MoveRight
:
1193 m_xLogicalOrigin
-= 10;
1195 case LogicalOrigin_Set
:
1197 m_yLogicalOrigin
= -100;
1199 case LogicalOrigin_Restore
:
1201 m_yLogicalOrigin
= 0;
1204 case UserScale_StretchHoriz
:
1205 m_xUserScale
*= 1.10;
1207 case UserScale_ShrinkHoriz
:
1208 m_xUserScale
/= 1.10;
1210 case UserScale_StretchVertic
:
1211 m_yUserScale
*= 1.10;
1213 case UserScale_ShrinkVertic
:
1214 m_yUserScale
/= 1.10;
1216 case UserScale_Restore
:
1221 case AxisMirror_Vertic
:
1222 m_yAxisReversed
= !m_yAxisReversed
;
1224 case AxisMirror_Horiz
:
1225 m_xAxisReversed
= !m_xAxisReversed
;
1228 case Colour_TextForeground
:
1229 m_colourForeground
= SelectColour();
1231 case Colour_TextBackground
:
1232 m_colourBackground
= SelectColour();
1234 case Colour_Background
:
1236 wxColour col
= SelectColour();
1239 m_backgroundBrush
.SetColour(col
);
1243 case Colour_BackgroundMode
:
1244 m_backgroundMode
= m_backgroundMode
== wxSOLID
? wxTRANSPARENT
1248 case Colour_TextureBackgound
:
1249 m_textureBackground
= ! m_textureBackground
;
1257 m_canvas
->Refresh();
1260 void MyFrame::PrepareDC(wxDC
& dc
)
1262 dc
.SetLogicalOrigin( m_xLogicalOrigin
, m_yLogicalOrigin
);
1263 dc
.SetAxisOrientation( !m_xAxisReversed
, m_yAxisReversed
);
1264 dc
.SetUserScale( m_xUserScale
, m_yUserScale
);
1265 dc
.SetMapMode( m_mapMode
);
1268 wxColour
MyFrame::SelectColour()
1272 wxColourDialog
dialog(this, &data
);
1274 if ( dialog
.ShowModal() == wxID_OK
)
1276 col
= dialog
.GetColourData().GetColour();