1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: shows and tests wxDC features
4 // Author: Robert Roebling
8 // Copyright: (c) Robert Roebling
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
14 // ============================================================================
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
20 #if defined(__GNUG__) && !defined(__APPLE__)
21 #pragma implementation "drawing.cpp"
22 #pragma interface "drawing.cpp"
25 // For compilers that support precompilation, includes "wx/wx.h".
26 #include "wx/wxprec.h"
32 // for all others, include the necessary headers (this file is usually all you
33 // need because it includes almost all "standard" wxWindows headers
38 #include "wx/colordlg.h"
40 #include "wx/artprov.h"
42 // ----------------------------------------------------------------------------
44 // ----------------------------------------------------------------------------
46 // the application icon
47 #if defined(__WXGTK__) || defined(__WXMOTIF__) || defined(__WXMAC__) || defined(__WXMGL__) || defined(__WXX11__)
48 #include "mondrian.xpm"
51 // ----------------------------------------------------------------------------
53 // ----------------------------------------------------------------------------
55 // what do we show on screen (there are too many shapes to put them all on
56 // screen simultaneously)
70 // ----------------------------------------------------------------------------
72 // ----------------------------------------------------------------------------
74 static wxBitmap
*gs_bmpNoMask
= NULL
,
75 *gs_bmpWithColMask
= NULL
,
77 *gs_bmpWithMask
= NULL
,
82 // ----------------------------------------------------------------------------
84 // ----------------------------------------------------------------------------
86 // Define a new application type, each program should derive a class from wxApp
87 class MyApp
: public wxApp
90 // override base class virtuals
91 // ----------------------------
93 // this one is called on application startup and is a good place for the app
94 // initialization (doing it here and not in the ctor allows to have an error
95 // return: if OnInit() returns false, the application terminates)
96 virtual bool OnInit();
98 virtual int OnExit() { DeleteBitmaps(); return 0; }
101 void DeleteBitmaps();
108 // Define a new frame type: this is going to be our main frame
109 class MyFrame
: public wxFrame
113 MyFrame(const wxString
& title
, const wxPoint
& pos
, const wxSize
& size
);
115 // event handlers (these functions should _not_ be virtual)
116 void OnQuit(wxCommandEvent
& event
);
117 void OnAbout(wxCommandEvent
& event
);
118 void OnClip(wxCommandEvent
& event
);
119 void OnShow(wxCommandEvent
&event
);
120 void OnOption(wxCommandEvent
&event
);
122 wxColour
SelectColour();
123 void PrepareDC(wxDC
& dc
);
125 int m_backgroundMode
;
126 int m_textureBackground
;
130 int m_xLogicalOrigin
;
131 int m_yLogicalOrigin
;
132 bool m_xAxisReversed
,
134 wxColour m_colourForeground
, // these are _text_ colours
136 wxBrush m_backgroundBrush
;
140 // any class wishing to process wxWindows events must use this macro
141 DECLARE_EVENT_TABLE()
144 // define a scrollable canvas for drawing onto
145 class MyCanvas
: public wxScrolledWindow
148 MyCanvas( MyFrame
*parent
);
150 void OnPaint(wxPaintEvent
&event
);
151 void OnMouseMove(wxMouseEvent
&event
);
153 void 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 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
;
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 wxWindows events with the functions (event
364 // handlers) which process them.
365 BEGIN_EVENT_TABLE(MyCanvas
, wxScrolledWindow
)
366 EVT_PAINT (MyCanvas::OnPaint
)
367 EVT_MOTION (MyCanvas::OnMouseMove
)
372 MyCanvas::MyCanvas(MyFrame
*parent
)
373 : wxScrolledWindow(parent
, -1, wxDefaultPosition
, wxDefaultSize
,
374 wxHSCROLL
| wxVSCROLL
| wxNO_FULL_REPAINT_ON_RESIZE
)
377 m_show
= Show_Default
;
378 m_smile_bmp
= wxBitmap(smile_xpm
);
379 m_std_icon
= wxArtProvider::GetIcon(wxART_INFORMATION
);
383 void MyCanvas::DrawTestBrushes(wxDC
& dc
)
385 static const wxCoord WIDTH
= 200;
386 static const wxCoord HEIGHT
= 80;
391 dc
.SetBrush(wxBrush(*wxGREEN
, wxSOLID
));
392 dc
.DrawRectangle(x
, y
, WIDTH
, HEIGHT
);
393 dc
.DrawText(_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);
428 dc
.DrawPolygon(WXSIZEOF(star
), star
);
429 dc
.DrawPolygon(WXSIZEOF(star
), star
, 160, 0, wxWINDING_RULE
);
432 void MyCanvas::DrawTestLines( int x
, int y
, int width
, wxDC
&dc
)
434 dc
.SetPen( wxPen( wxT("black"), width
, wxSOLID
) );
435 dc
.SetBrush( *wxRED_BRUSH
);
436 dc
.DrawText(wxString::Format(wxT("Testing lines of width %d"), width
), x
+ 10, y
- 10);
437 dc
.DrawRectangle( x
+10, y
+10, 100, 190 );
439 dc
.DrawText(_T("Solid/dot/short dash/long dash/dot dash"), x
+ 150, y
+ 10);
440 dc
.SetPen( wxPen( wxT("black"), width
, wxSOLID
) );
441 dc
.DrawLine( x
+20, y
+20, 100, y
+20 );
442 dc
.SetPen( wxPen( wxT("black"), width
, wxDOT
) );
443 dc
.DrawLine( x
+20, y
+30, 100, y
+30 );
444 dc
.SetPen( wxPen( wxT("black"), width
, wxSHORT_DASH
) );
445 dc
.DrawLine( x
+20, y
+40, 100, y
+40 );
446 dc
.SetPen( wxPen( wxT("black"), width
, wxLONG_DASH
) );
447 dc
.DrawLine( x
+20, y
+50, 100, y
+50 );
448 dc
.SetPen( wxPen( wxT("black"), width
, wxDOT_DASH
) );
449 dc
.DrawLine( x
+20, y
+60, 100, y
+60 );
451 dc
.DrawText(_T("Misc hatches"), x
+ 150, y
+ 70);
452 dc
.SetPen( wxPen( wxT("black"), width
, wxBDIAGONAL_HATCH
) );
453 dc
.DrawLine( x
+20, y
+70, 100, y
+70 );
454 dc
.SetPen( wxPen( wxT("black"), width
, wxCROSSDIAG_HATCH
) );
455 dc
.DrawLine( x
+20, y
+80, 100, y
+80 );
456 dc
.SetPen( wxPen( wxT("black"), width
, wxFDIAGONAL_HATCH
) );
457 dc
.DrawLine( x
+20, y
+90, 100, y
+90 );
458 dc
.SetPen( wxPen( wxT("black"), width
, wxCROSS_HATCH
) );
459 dc
.DrawLine( x
+20, y
+100, 100, y
+100 );
460 dc
.SetPen( wxPen( wxT("black"), width
, wxHORIZONTAL_HATCH
) );
461 dc
.DrawLine( x
+20, y
+110, 100, y
+110 );
462 dc
.SetPen( wxPen( wxT("black"), width
, wxVERTICAL_HATCH
) );
463 dc
.DrawLine( x
+20, y
+120, 100, y
+120 );
465 dc
.DrawText(_T("User dash"), x
+ 150, y
+ 140);
466 wxPen
ud( wxT("black"), width
, wxUSER_DASH
);
468 dash1
[0] = 8; // Long dash <---------+
469 dash1
[1] = 2; // Short gap |
470 dash1
[2] = 3; // Short dash |
471 dash1
[3] = 2; // Short gap |
472 dash1
[4] = 3; // Short dash |
473 dash1
[5] = 2; // Short gap and repeat +
474 ud
.SetDashes( 6, dash1
);
476 dc
.DrawLine( x
+20, y
+140, 100, y
+140 );
477 dash1
[0] = 5; // Make first dash shorter
478 ud
.SetDashes( 6, dash1
);
480 dc
.DrawLine( x
+20, y
+150, 100, y
+150 );
481 dash1
[2] = 5; // Make second dash longer
482 ud
.SetDashes( 6, dash1
);
484 dc
.DrawLine( x
+20, y
+160, 100, y
+160 );
485 dash1
[4] = 5; // Make third dash longer
486 ud
.SetDashes( 6, dash1
);
488 dc
.DrawLine( x
+20, y
+170, 100, y
+170 );
491 void MyCanvas::DrawDefault(wxDC
& dc
)
494 dc
.DrawCircle(0, 0, 10);
496 //flood fill using brush, starting at 1,1 and replacing whatever colour we find there
497 dc
.SetBrush(wxBrush(wxColour(128,128,0), wxSOLID
));
499 dc
.GetPixel(1,1, &tmpColour
);
500 dc
.FloodFill(1,1, tmpColour
, wxFLOOD_SURFACE
);
502 dc
.DrawCheckMark(5, 80, 15, 15);
503 dc
.DrawCheckMark(25, 80, 30, 30);
504 dc
.DrawCheckMark(60, 80, 60, 60);
506 // this is the test for "blitting bitmap into DC damages selected brush" bug
507 wxCoord rectSize
= m_std_icon
.GetWidth() + 10;
509 dc
.SetPen(*wxTRANSPARENT_PEN
);
510 dc
.SetBrush( *wxGREEN_BRUSH
);
511 dc
.DrawRectangle(x
, 10, rectSize
, rectSize
);
512 dc
.DrawBitmap(m_std_icon
, x
+ 5, 15, TRUE
);
514 dc
.DrawRectangle(x
, 10, rectSize
, rectSize
);
515 dc
.DrawIcon(m_std_icon
, x
+ 5, 15);
517 dc
.DrawRectangle(x
, 10, rectSize
, rectSize
);
519 // test for "transparent" bitmap drawing (it intersects with the last
521 //dc.SetBrush( *wxTRANSPARENT_BRUSH );
523 if (m_smile_bmp
.Ok())
524 dc
.DrawBitmap(m_smile_bmp
, x
+ rectSize
- 20, rectSize
- 10, TRUE
);
526 dc
.SetBrush( *wxBLACK_BRUSH
);
527 dc
.DrawRectangle( 0, 160, 1000, 300 );
530 wxBitmap
bitmap(20,70);
532 memdc
.SelectObject( bitmap
);
533 memdc
.SetBrush( *wxBLACK_BRUSH
);
534 memdc
.SetPen( *wxWHITE_PEN
);
535 memdc
.DrawRectangle(0,0,20,70);
536 memdc
.DrawLine( 10,0,10,70 );
539 wxPen pen
= *wxRED_PEN
;
541 memdc
.DrawLine( 10, 5,10, 5 );
542 memdc
.DrawLine( 10,10,11,10 );
543 memdc
.DrawLine( 10,15,12,15 );
544 memdc
.DrawLine( 10,20,13,20 );
547 memdc.SetPen(*wxRED_PEN);
548 memdc.DrawLine( 12, 5,12, 5 );
549 memdc.DrawLine( 12,10,13,10 );
550 memdc.DrawLine( 12,15,14,15 );
551 memdc.DrawLine( 12,20,15,20 );
555 memdc
.DrawLine( 10,25,10,25 );
556 memdc
.DrawLine( 10,30, 9,30 );
557 memdc
.DrawLine( 10,35, 8,35 );
558 memdc
.DrawLine( 10,40, 7,40 );
561 dc
.SetPen(*wxWHITE_PEN
);
562 memdc
.SetLogicalFunction( wxINVERT
);
563 memdc
.SetPen( *wxWHITE_PEN
);
564 memdc
.DrawLine( 10,50,10,50 );
565 memdc
.DrawLine( 10,55,11,55 );
566 memdc
.DrawLine( 10,60,12,60 );
567 memdc
.DrawLine( 10,65,13,65 );
569 memdc
.DrawLine( 12,50,12,50 );
570 memdc
.DrawLine( 12,55,13,55 );
571 memdc
.DrawLine( 12,60,14,60 );
572 memdc
.DrawLine( 12,65,15,65 );
574 memdc
.SelectObject( wxNullBitmap
);
575 dc
.DrawBitmap( bitmap
, 10, 170 );
576 wxImage image
= bitmap
.ConvertToImage();
577 image
.Rescale( 60,210 );
578 bitmap
= wxBitmap(image
);
579 dc
.DrawBitmap( bitmap
, 50, 170 );
581 // test the rectangle outline drawing - there should be one pixel between
582 // the rect and the lines
583 dc
.SetPen(*wxWHITE_PEN
);
584 dc
.SetBrush( *wxTRANSPARENT_BRUSH
);
585 dc
.DrawRectangle(150, 170, 49, 29);
586 dc
.DrawRectangle(200, 170, 49, 29);
587 dc
.SetPen(*wxWHITE_PEN
);
588 dc
.DrawLine(250, 210, 250, 170);
589 dc
.DrawLine(260, 200, 150, 200);
591 // test the rectangle filled drawing - there should be one pixel between
592 // the rect and the lines
593 dc
.SetPen(*wxTRANSPARENT_PEN
);
594 dc
.SetBrush( *wxWHITE_BRUSH
);
595 dc
.DrawRectangle(300, 170, 49, 29);
596 dc
.DrawRectangle(350, 170, 49, 29);
597 dc
.SetPen(*wxWHITE_PEN
);
598 dc
.DrawLine(400, 170, 400, 210);
599 dc
.DrawLine(300, 200, 410, 200);
601 // a few more tests of this kind
602 dc
.SetPen(*wxRED_PEN
);
603 dc
.SetBrush( *wxWHITE_BRUSH
);
604 dc
.DrawRectangle(300, 220, 1, 1);
605 dc
.DrawRectangle(310, 220, 2, 2);
606 dc
.DrawRectangle(320, 220, 3, 3);
607 dc
.DrawRectangle(330, 220, 4, 4);
609 dc
.SetPen(*wxTRANSPARENT_PEN
);
610 dc
.SetBrush( *wxWHITE_BRUSH
);
611 dc
.DrawRectangle(300, 230, 1, 1);
612 dc
.DrawRectangle(310, 230, 2, 2);
613 dc
.DrawRectangle(320, 230, 3, 3);
614 dc
.DrawRectangle(330, 230, 4, 4);
616 // and now for filled rect with outline
617 dc
.SetPen(*wxRED_PEN
);
618 dc
.SetBrush( *wxWHITE_BRUSH
);
619 dc
.DrawRectangle(500, 170, 49, 29);
620 dc
.DrawRectangle(550, 170, 49, 29);
621 dc
.SetPen(*wxWHITE_PEN
);
622 dc
.DrawLine(600, 170, 600, 210);
623 dc
.DrawLine(500, 200, 610, 200);
625 // test the rectangle outline drawing - there should be one pixel between
626 // the rect and the lines
627 dc
.SetPen(*wxWHITE_PEN
);
628 dc
.SetBrush( *wxTRANSPARENT_BRUSH
);
629 dc
.DrawRoundedRectangle(150, 270, 49, 29, 6);
630 dc
.DrawRoundedRectangle(200, 270, 49, 29, 6);
631 dc
.SetPen(*wxWHITE_PEN
);
632 dc
.DrawLine(250, 270, 250, 310);
633 dc
.DrawLine(150, 300, 260, 300);
635 // test the rectangle filled drawing - there should be one pixel between
636 // the rect and the lines
637 dc
.SetPen(*wxTRANSPARENT_PEN
);
638 dc
.SetBrush( *wxWHITE_BRUSH
);
639 dc
.DrawRoundedRectangle(300, 270, 49, 29, 6);
640 dc
.DrawRoundedRectangle(350, 270, 49, 29, 6);
641 dc
.SetPen(*wxWHITE_PEN
);
642 dc
.DrawLine(400, 270, 400, 310);
643 dc
.DrawLine(300, 300, 410, 300);
645 // Added by JACS to demonstrate bizarre behaviour.
646 // With a size of 70, we get a missing red RHS,
647 // and the hight is too small, so we get yellow
648 // showing. With a size of 40, it draws as expected:
649 // it just shows a white rectangle with red outline.
651 int totalHeight
= 70;
652 wxBitmap
bitmap2(totalWidth
, totalHeight
);
655 memdc2
.SelectObject(bitmap2
);
657 wxBrush
yellowBrush(wxColour(255, 255, 0), wxSOLID
);
658 memdc2
.SetBackground(yellowBrush
);
661 wxPen
yellowPen(wxColour(255, 255, 0), 1, wxSOLID
);
663 // Now draw a white rectangle with red outline. It should
664 // entirely eclipse the yellow background.
665 memdc2
.SetPen(*wxRED_PEN
);
666 memdc2
.SetBrush(*wxWHITE_BRUSH
);
668 memdc2
.DrawRectangle(0, 0, totalWidth
, totalHeight
);
670 memdc2
.SetPen(wxNullPen
);
671 memdc2
.SetBrush(wxNullBrush
);
672 memdc2
.SelectObject(wxNullBitmap
);
674 dc
.DrawBitmap(bitmap2
, 500, 270);
676 // Repeat, but draw directly on dc
677 // Draw a yellow rectangle filling the bitmap
679 x
= 600; int y
= 270;
680 dc
.SetPen(yellowPen
);
681 dc
.SetBrush(yellowBrush
);
682 dc
.DrawRectangle(x
, y
, totalWidth
, totalHeight
);
684 // Now draw a white rectangle with red outline. It should
685 // entirely eclipse the yellow background.
686 dc
.SetPen(*wxRED_PEN
);
687 dc
.SetBrush(*wxWHITE_BRUSH
);
689 dc
.DrawRectangle(x
, y
, totalWidth
, totalHeight
);
692 void MyCanvas::DrawText(wxDC
& dc
)
694 // set underlined font for testing
695 dc
.SetFont( wxFont(12, wxMODERN
, wxNORMAL
, wxNORMAL
, TRUE
) );
696 dc
.DrawText( _T("This is text"), 110, 10 );
697 dc
.DrawRotatedText( _T("That is text"), 20, 10, -45 );
699 // use wxSWISS_FONT and not wxNORMAL_FONT as the latter can't be rotated
700 // under Win9x (it is not TrueType)
701 dc
.SetFont( *wxSWISS_FONT
);
704 dc
.SetBackgroundMode(wxTRANSPARENT
);
706 for ( int n
= -180; n
< 180; n
+= 30 )
708 text
.Printf(wxT(" %d rotated text"), n
);
709 dc
.DrawRotatedText(text
, 400, 400, n
);
712 dc
.SetFont( wxFont( 18, wxSWISS
, wxNORMAL
, wxNORMAL
) );
714 dc
.DrawText( _T("This is Swiss 18pt text."), 110, 40 );
719 dc
.GetTextExtent( _T("This is Swiss 18pt text."), &length
, &height
, &descent
);
720 text
.Printf( wxT("Dimensions are length %ld, height %ld, descent %ld"), length
, height
, descent
);
721 dc
.DrawText( text
, 110, 80 );
723 text
.Printf( wxT("CharHeight() returns: %d"), dc
.GetCharHeight() );
724 dc
.DrawText( text
, 110, 120 );
726 dc
.DrawRectangle( 100, 40, 4, height
);
728 // test the logical function effect
730 dc
.SetLogicalFunction(wxINVERT
);
731 dc
.DrawText( _T("There should be no text below"), 110, 150 );
732 dc
.DrawRectangle( 110, y
, 100, height
);
734 // twice drawn inverted should result in invisible
736 dc
.DrawText( _T("Invisible text"), 110, y
);
737 dc
.DrawRectangle( 110, y
, 100, height
);
738 dc
.DrawText( _T("Invisible text"), 110, y
);
739 dc
.DrawRectangle( 110, y
, 100, height
);
740 dc
.SetLogicalFunction(wxCOPY
);
743 dc
.DrawRectangle( 110, y
, 100, height
);
744 dc
.DrawText( _T("Visible text"), 110, y
);
751 } rasterOperations
[] =
753 { wxT("wxAND"), wxAND
},
754 { wxT("wxAND_INVERT"), wxAND_INVERT
},
755 { wxT("wxAND_REVERSE"), wxAND_REVERSE
},
756 { wxT("wxCLEAR"), wxCLEAR
},
757 { wxT("wxCOPY"), wxCOPY
},
758 { wxT("wxEQUIV"), wxEQUIV
},
759 { wxT("wxINVERT"), wxINVERT
},
760 { wxT("wxNAND"), wxNAND
},
761 { wxT("wxNO_OP"), wxNO_OP
},
762 { wxT("wxOR"), wxOR
},
763 { wxT("wxOR_INVERT"), wxOR_INVERT
},
764 { wxT("wxOR_REVERSE"), wxOR_REVERSE
},
765 { wxT("wxSET"), wxSET
},
766 { wxT("wxSRC_INVERT"), wxSRC_INVERT
},
767 { wxT("wxXOR"), wxXOR
},
770 void MyCanvas::DrawImages(wxDC
& dc
)
772 dc
.DrawText(_T("original image"), 0, 0);
773 dc
.DrawBitmap(*gs_bmpNoMask
, 0, 20, 0);
774 dc
.DrawText(_T("with colour mask"), 0, 100);
775 dc
.DrawBitmap(*gs_bmpWithColMask
, 0, 120, TRUE
);
776 dc
.DrawText(_T("the mask image"), 0, 200);
777 dc
.DrawBitmap(*gs_bmpMask
, 0, 220, 0);
778 dc
.DrawText(_T("masked image"), 0, 300);
779 dc
.DrawBitmap(*gs_bmpWithMask
, 0, 320, TRUE
);
781 int cx
= gs_bmpWithColMask
->GetWidth(),
782 cy
= gs_bmpWithColMask
->GetHeight();
785 for ( size_t n
= 0; n
< WXSIZEOF(rasterOperations
); n
++ )
787 wxCoord x
= 120 + 150*(n%4
),
790 dc
.DrawText(rasterOperations
[n
].name
, x
, y
- 20);
791 memDC
.SelectObject(*gs_bmpWithColMask
);
792 dc
.Blit(x
, y
, cx
, cy
, &memDC
, 0, 0, rasterOperations
[n
].rop
, TRUE
);
796 void MyCanvas::DrawWithLogicalOps(wxDC
& dc
)
798 static const wxCoord w
= 60;
799 static const wxCoord h
= 60;
801 // reuse the text colour here
802 dc
.SetPen(wxPen(m_owner
->m_colourForeground
, 1, wxSOLID
));
803 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
806 for ( n
= 0; n
< WXSIZEOF(rasterOperations
); n
++ )
808 wxCoord x
= 20 + 150*(n%4
),
811 dc
.DrawText(rasterOperations
[n
].name
, x
, y
- 20);
812 dc
.SetLogicalFunction(rasterOperations
[n
].rop
);
813 dc
.DrawRectangle(x
, y
, w
, h
);
814 dc
.DrawLine(x
, y
, x
+ w
, y
+ h
);
815 dc
.DrawLine(x
+ w
, y
, x
, y
+ h
);
818 // now some filled rectangles
819 dc
.SetBrush(wxBrush(m_owner
->m_colourForeground
, wxSOLID
));
821 for ( n
= 0; n
< WXSIZEOF(rasterOperations
); n
++ )
823 wxCoord x
= 20 + 150*(n%4
),
826 dc
.DrawText(rasterOperations
[n
].name
, x
, y
- 20);
827 dc
.SetLogicalFunction(rasterOperations
[n
].rop
);
828 dc
.DrawRectangle(x
, y
, w
, h
);
832 void MyCanvas::DrawCircles(wxDC
& dc
)
838 dc
.DrawText(_T("Some circles"), 0, y
);
839 dc
.DrawCircle(x
, y
, r
);
840 dc
.DrawCircle(x
+ 2*r
, y
, r
);
841 dc
.DrawCircle(x
+ 4*r
, y
, r
);
844 dc
.DrawText(_T("And ellipses"), 0, y
);
845 dc
.DrawEllipse(x
- r
, y
, 2*r
, r
);
846 dc
.DrawEllipse(x
+ r
, y
, 2*r
, r
);
847 dc
.DrawEllipse(x
+ 3*r
, y
, 2*r
, r
);
850 dc
.DrawText(_T("And arcs"), 0, y
);
851 dc
.DrawArc(x
- r
, y
, x
+ r
, y
, x
, y
);
852 dc
.DrawArc(x
+ 4*r
, y
, x
+ 2*r
, y
, x
+ 3*r
, y
);
853 dc
.DrawArc(x
+ 5*r
, y
, x
+ 5*r
, y
, x
+ 6*r
, y
);
856 dc
.DrawEllipticArc(x
- r
, y
, 2*r
, r
, 0, 90);
857 dc
.DrawEllipticArc(x
+ r
, y
, 2*r
, r
, 90, 180);
858 dc
.DrawEllipticArc(x
+ 3*r
, y
, 2*r
, r
, 180, 270);
859 dc
.DrawEllipticArc(x
+ 5*r
, y
, 2*r
, r
, 270, 360);
862 void MyCanvas::DrawRegions(wxDC
& dc
)
864 dc
.DrawText(_T("You should see a red rect partly covered by a cyan one ")
865 _T("on the left"), 10, 5);
866 dc
.DrawText(_T("and 5 smileys from which 4 are partially clipped on the right"),
867 10, 5 + dc
.GetCharHeight());
868 dc
.DrawText(_T("The second copy should be identical but right part of it ")
869 _T("should be offset by 10 pixels."),
870 10, 5 + 2*dc
.GetCharHeight());
872 DrawRegionsHelper(dc
, 10, TRUE
);
873 DrawRegionsHelper(dc
, 350, FALSE
);
876 void MyCanvas::DrawRegionsHelper(wxDC
& dc
, wxCoord x
, bool firstTime
)
880 dc
.DestroyClippingRegion();
881 dc
.SetBrush( *wxWHITE_BRUSH
);
882 dc
.SetPen( *wxTRANSPARENT_PEN
);
883 dc
.DrawRectangle( x
, y
, 310, 310 );
885 dc
.SetClippingRegion( x
+ 10, y
+ 10, 100, 270 );
887 dc
.SetBrush( *wxRED_BRUSH
);
888 dc
.DrawRectangle( x
, y
, 310, 310 );
890 dc
.SetClippingRegion( x
+ 10, y
+ 10, 100, 100 );
892 dc
.SetBrush( *wxCYAN_BRUSH
);
893 dc
.DrawRectangle( x
, y
, 310, 310 );
895 dc
.DestroyClippingRegion();
897 wxRegion
region(x
+ 110, y
+ 20, 100, 270);
898 #if !defined(__WXMOTIF__) && !defined(__WXMAC__)
900 region
.Offset(10, 10);
902 dc
.SetClippingRegion(region
);
904 dc
.SetBrush( *wxGREY_BRUSH
);
905 dc
.DrawRectangle( x
, y
, 310, 310 );
907 if (m_smile_bmp
.Ok())
909 dc
.DrawBitmap( m_smile_bmp
, x
+ 150, y
+ 150, TRUE
);
910 dc
.DrawBitmap( m_smile_bmp
, x
+ 130, y
+ 10, TRUE
);
911 dc
.DrawBitmap( m_smile_bmp
, x
+ 130, y
+ 280, TRUE
);
912 dc
.DrawBitmap( m_smile_bmp
, x
+ 100, y
+ 70, TRUE
);
913 dc
.DrawBitmap( m_smile_bmp
, x
+ 200, y
+ 70, TRUE
);
917 void MyCanvas::OnPaint(wxPaintEvent
&WXUNUSED(event
))
922 m_owner
->PrepareDC(dc
);
924 dc
.SetBackgroundMode( m_owner
->m_backgroundMode
);
925 if ( m_owner
->m_backgroundBrush
.Ok() )
926 dc
.SetBackground( m_owner
->m_backgroundBrush
);
927 if ( m_owner
->m_colourForeground
.Ok() )
928 dc
.SetTextForeground( m_owner
->m_colourForeground
);
929 if ( m_owner
->m_colourBackground
.Ok() )
930 dc
.SetTextBackground( m_owner
->m_colourBackground
);
932 if ( m_owner
->m_textureBackground
) {
933 if ( ! m_owner
->m_backgroundBrush
.Ok() ) {
934 wxBrush
b(wxColour(0,128,0), wxSOLID
);
940 dc
.SetClippingRegion(100, 100, 100, 100);
944 if ( m_owner
->m_textureBackground
)
946 dc
.SetPen(*wxMEDIUM_GREY_PEN
);
947 for ( int i
= 0; i
< 200; i
++ )
948 dc
.DrawLine(0, i
*10, i
*10, 0);
970 DrawTestLines( 0, 100, 0, dc
);
971 DrawTestLines( 0, 320, 1, dc
);
972 DrawTestLines( 0, 540, 2, dc
);
973 DrawTestLines( 0, 760, 6, dc
);
989 DrawWithLogicalOps(dc
);
994 void MyCanvas::OnMouseMove(wxMouseEvent
&event
)
998 m_owner
->PrepareDC(dc
);
1000 wxPoint pos
= event
.GetPosition();
1001 long x
= dc
.DeviceToLogicalX( pos
.x
);
1002 long y
= dc
.DeviceToLogicalY( pos
.y
);
1004 str
.Printf( wxT("Current mouse position: %d,%d"), (int)x
, (int)y
);
1005 m_owner
->SetStatusText( str
);
1008 // ----------------------------------------------------------------------------
1010 // ----------------------------------------------------------------------------
1012 // the event tables connect the wxWindows events with the functions (event
1013 // handlers) which process them. It can be also done at run-time, but for the
1014 // simple menu events like this the static method is much simpler.
1015 BEGIN_EVENT_TABLE(MyFrame
, wxFrame
)
1016 EVT_MENU (File_Quit
, MyFrame::OnQuit
)
1017 EVT_MENU (File_About
, MyFrame::OnAbout
)
1018 EVT_MENU (File_Clip
, MyFrame::OnClip
)
1020 EVT_MENU_RANGE(MenuShow_First
, MenuShow_Last
, MyFrame::OnShow
)
1022 EVT_MENU_RANGE(MenuOption_First
, MenuOption_Last
, MyFrame::OnOption
)
1025 // frame constructor
1026 MyFrame::MyFrame(const wxString
& title
, const wxPoint
& pos
, const wxSize
& size
)
1027 : wxFrame((wxFrame
*)NULL
, -1, title
, pos
, size
,
1028 wxDEFAULT_FRAME_STYLE
| wxNO_FULL_REPAINT_ON_RESIZE
)
1030 // set the frame icon
1031 SetIcon(wxICON(mondrian
));
1033 wxMenu
*menuFile
= new wxMenu
;
1034 menuFile
->Append(File_ShowDefault
, _T("&Default screen\tF1"));
1035 menuFile
->Append(File_ShowText
, _T("&Text screen\tF2"));
1036 menuFile
->Append(File_ShowLines
, _T("&Lines screen\tF3"));
1037 menuFile
->Append(File_ShowBrushes
, _T("&Brushes screen\tF4"));
1038 menuFile
->Append(File_ShowPolygons
, _T("&Polygons screen\tF5"));
1039 menuFile
->Append(File_ShowMask
, _T("&Mask screen\tF6"));
1040 menuFile
->Append(File_ShowOps
, _T("&ROP screen\tF7"));
1041 menuFile
->Append(File_ShowRegions
, _T("Re&gions screen\tF8"));
1042 menuFile
->Append(File_ShowCircles
, _T("&Circles screen\tF9"));
1043 menuFile
->AppendSeparator();
1044 menuFile
->AppendCheckItem(File_Clip
, _T("&Clip\tCtrl-C"), _T("Clip/unclip drawing"));
1045 menuFile
->AppendSeparator();
1046 menuFile
->Append(File_About
, _T("&About...\tCtrl-A"), _T("Show about dialog"));
1047 menuFile
->AppendSeparator();
1048 menuFile
->Append(File_Quit
, _T("E&xit\tAlt-X"), _T("Quit this program"));
1050 wxMenu
*menuMapMode
= new wxMenu
;
1051 menuMapMode
->Append( MapMode_Text
, _T("&TEXT map mode") );
1052 menuMapMode
->Append( MapMode_Lometric
, _T("&LOMETRIC map mode") );
1053 menuMapMode
->Append( MapMode_Twips
, _T("T&WIPS map mode") );
1054 menuMapMode
->Append( MapMode_Points
, _T("&POINTS map mode") );
1055 menuMapMode
->Append( MapMode_Metric
, _T("&METRIC map mode") );
1057 wxMenu
*menuUserScale
= new wxMenu
;
1058 menuUserScale
->Append( UserScale_StretchHoriz
, _T("Stretch &horizontally\tCtrl-H") );
1059 menuUserScale
->Append( UserScale_ShrinkHoriz
, _T("Shrin&k horizontally\tCtrl-G") );
1060 menuUserScale
->Append( UserScale_StretchVertic
, _T("Stretch &vertically\tCtrl-V") );
1061 menuUserScale
->Append( UserScale_ShrinkVertic
, _T("&Shrink vertically\tCtrl-W") );
1062 menuUserScale
->AppendSeparator();
1063 menuUserScale
->Append( UserScale_Restore
, _T("&Restore to normal\tCtrl-0") );
1065 wxMenu
*menuAxis
= new wxMenu
;
1066 menuAxis
->Append( AxisMirror_Horiz
, _T("Mirror horizontally\tCtrl-M"), _T(""), TRUE
);
1067 menuAxis
->Append( AxisMirror_Vertic
, _T("Mirror vertically\tCtrl-N"), _T(""), TRUE
);
1069 wxMenu
*menuLogical
= new wxMenu
;
1070 menuLogical
->Append( LogicalOrigin_MoveDown
, _T("Move &down\tCtrl-D") );
1071 menuLogical
->Append( LogicalOrigin_MoveUp
, _T("Move &up\tCtrl-U") );
1072 menuLogical
->Append( LogicalOrigin_MoveLeft
, _T("Move &right\tCtrl-L") );
1073 menuLogical
->Append( LogicalOrigin_MoveRight
, _T("Move &left\tCtrl-R") );
1074 menuLogical
->AppendSeparator();
1075 menuLogical
->Append( LogicalOrigin_Set
, _T("Set to (&100, 100)\tShift-Ctrl-1") );
1076 menuLogical
->Append( LogicalOrigin_Restore
, _T("&Restore to normal\tShift-Ctrl-0") );
1078 wxMenu
*menuColour
= new wxMenu
;
1079 menuColour
->Append( Colour_TextForeground
, _T("Text &foreground...") );
1080 menuColour
->Append( Colour_TextBackground
, _T("Text &background...") );
1081 menuColour
->Append( Colour_Background
, _T("Background &colour...") );
1082 menuColour
->Append( Colour_BackgroundMode
, _T("&Opaque/transparent\tCtrl-B"), _T(""), TRUE
);
1083 menuColour
->Append( Colour_TextureBackgound
, _T("Draw textured back&ground\tCtrl-T"), _T(""), TRUE
);
1085 // now append the freshly created menu to the menu bar...
1086 wxMenuBar
*menuBar
= new wxMenuBar
;
1087 menuBar
->Append(menuFile
, _T("&File"));
1088 menuBar
->Append(menuMapMode
, _T("&Mode"));
1089 menuBar
->Append(menuUserScale
, _T("&Scale"));
1090 menuBar
->Append(menuAxis
, _T("&Axis"));
1091 menuBar
->Append(menuLogical
, _T("&Origin"));
1092 menuBar
->Append(menuColour
, _T("&Colours"));
1094 // ... and attach this menu bar to the frame
1095 SetMenuBar(menuBar
);
1097 // create a status bar just for fun (by default with 1 pane only)
1099 SetStatusText(_T("Welcome to wxWindows!"));
1101 m_mapMode
= wxMM_TEXT
;
1104 m_xLogicalOrigin
= 0;
1105 m_yLogicalOrigin
= 0;
1107 m_yAxisReversed
= FALSE
;
1108 m_backgroundMode
= wxSOLID
;
1109 m_colourForeground
= *wxRED
;
1110 m_colourBackground
= *wxBLUE
;
1111 m_textureBackground
= FALSE
;
1113 m_canvas
= new MyCanvas( this );
1114 m_canvas
->SetScrollbars( 10, 10, 100, 240 );
1119 void MyFrame::OnQuit(wxCommandEvent
& WXUNUSED(event
))
1121 // TRUE is to force the frame to close
1125 void MyFrame::OnAbout(wxCommandEvent
& WXUNUSED(event
))
1128 msg
.Printf( wxT("This is the about dialog of the drawing sample.\n")
1129 wxT("This sample tests various primitive drawing functions\n")
1130 wxT("(without any attempts to prevent flicker).\n")
1131 wxT("Copyright (c) Robert Roebling 1999")
1134 wxMessageBox(msg
, _T("About Drawing"), wxOK
| wxICON_INFORMATION
, this);
1137 void MyFrame::OnClip(wxCommandEvent
& event
)
1139 m_canvas
->Clip(event
.IsChecked());
1142 void MyFrame::OnShow(wxCommandEvent
& event
)
1144 m_canvas
->ToShow((ScreenToShow
)(event
.GetId() - MenuShow_First
));
1147 void MyFrame::OnOption(wxCommandEvent
& event
)
1149 switch (event
.GetId())
1152 m_mapMode
= wxMM_TEXT
;
1154 case MapMode_Lometric
:
1155 m_mapMode
= wxMM_LOMETRIC
;
1158 m_mapMode
= wxMM_TWIPS
;
1160 case MapMode_Points
:
1161 m_mapMode
= wxMM_POINTS
;
1163 case MapMode_Metric
:
1164 m_mapMode
= wxMM_METRIC
;
1167 case LogicalOrigin_MoveDown
:
1168 m_yLogicalOrigin
+= 10;
1170 case LogicalOrigin_MoveUp
:
1171 m_yLogicalOrigin
-= 10;
1173 case LogicalOrigin_MoveLeft
:
1174 m_xLogicalOrigin
+= 10;
1176 case LogicalOrigin_MoveRight
:
1177 m_xLogicalOrigin
-= 10;
1179 case LogicalOrigin_Set
:
1181 m_yLogicalOrigin
= -100;
1183 case LogicalOrigin_Restore
:
1185 m_yLogicalOrigin
= 0;
1188 case UserScale_StretchHoriz
:
1189 m_xUserScale
*= 1.10;
1191 case UserScale_ShrinkHoriz
:
1192 m_xUserScale
/= 1.10;
1194 case UserScale_StretchVertic
:
1195 m_yUserScale
*= 1.10;
1197 case UserScale_ShrinkVertic
:
1198 m_yUserScale
/= 1.10;
1200 case UserScale_Restore
:
1205 case AxisMirror_Vertic
:
1206 m_yAxisReversed
= !m_yAxisReversed
;
1208 case AxisMirror_Horiz
:
1209 m_xAxisReversed
= !m_xAxisReversed
;
1212 case Colour_TextForeground
:
1213 m_colourForeground
= SelectColour();
1215 case Colour_TextBackground
:
1216 m_colourBackground
= SelectColour();
1218 case Colour_Background
:
1220 wxColour col
= SelectColour();
1223 m_backgroundBrush
.SetColour(col
);
1227 case Colour_BackgroundMode
:
1228 m_backgroundMode
= m_backgroundMode
== wxSOLID
? wxTRANSPARENT
1232 case Colour_TextureBackgound
:
1233 m_textureBackground
= ! m_textureBackground
;
1241 m_canvas
->Refresh();
1244 void MyFrame::PrepareDC(wxDC
& dc
)
1246 dc
.SetLogicalOrigin( m_xLogicalOrigin
, m_yLogicalOrigin
);
1247 dc
.SetAxisOrientation( !m_xAxisReversed
, m_yAxisReversed
);
1248 dc
.SetUserScale( m_xUserScale
, m_yUserScale
);
1249 dc
.SetMapMode( m_mapMode
);
1252 wxColour
MyFrame::SelectColour()
1256 wxColourDialog
dialog(this, &data
);
1258 if ( dialog
.ShowModal() == wxID_OK
)
1260 col
= dialog
.GetColourData().GetColour();