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__) || defined(__WXMGL__) || defined(__WXX11__)
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 LogicalOrigin_Restore
,
223 Colour_TextForeground
,
224 Colour_TextBackground
,
226 Colour_BackgroundMode
,
227 Colour_TextureBackgound
,
229 MenuOption_Last
= Colour_TextureBackgound
232 // ----------------------------------------------------------------------------
233 // event tables and other macros for wxWindows
234 // ----------------------------------------------------------------------------
237 // Create a new application object: this macro will allow wxWindows to create
238 // the application object during program execution (it's better than using a
239 // static object for many reasons) and also declares the accessor function
240 // wxGetApp() which will return the reference of the right type (i.e. MyApp and
244 // ============================================================================
246 // ============================================================================
248 // ----------------------------------------------------------------------------
249 // the application class
250 // ----------------------------------------------------------------------------
252 bool MyApp::LoadImages()
254 gs_bmpNoMask
= new wxBitmap
;
255 gs_bmpWithColMask
= new wxBitmap
;
256 gs_bmpMask
= new wxBitmap
;
257 gs_bmpWithMask
= new wxBitmap
;
258 gs_bmp4
= new wxBitmap
;
259 gs_bmp4_mono
= new wxBitmap
;
260 gs_bmp36
= new wxBitmap
;
266 wxString path
= pathList
.FindValidPath("pat4.bmp");
270 /* 4 colour bitmap */
271 gs_bmp4
->LoadFile(path
, wxBITMAP_TYPE_BMP
);
272 /* turn into mono-bitmap */
273 gs_bmp4_mono
->LoadFile(path
, wxBITMAP_TYPE_BMP
);
274 wxMask
* mask4
= new wxMask(*gs_bmp4_mono
, *wxBLACK
);
275 gs_bmp4_mono
->SetMask(mask4
);
277 path
= pathList
.FindValidPath("pat36.bmp");
280 gs_bmp36
->LoadFile(path
, wxBITMAP_TYPE_BMP
);
281 wxMask
* mask36
= new wxMask(*gs_bmp36
, *wxBLACK
);
282 gs_bmp36
->SetMask(mask36
);
284 path
= pathList
.FindValidPath("image.bmp");
287 gs_bmpNoMask
->LoadFile(path
, wxBITMAP_TYPE_BMP
);
288 gs_bmpWithMask
->LoadFile(path
, wxBITMAP_TYPE_BMP
);
289 gs_bmpWithColMask
->LoadFile(path
, wxBITMAP_TYPE_BMP
);
291 path
= pathList
.FindValidPath("mask.bmp");
294 gs_bmpMask
->LoadFile(path
, wxBITMAP_TYPE_BMP
);
296 wxMask
*mask
= new wxMask(*gs_bmpMask
, *wxBLACK
);
297 gs_bmpWithMask
->SetMask(mask
);
299 mask
= new wxMask(*gs_bmpWithColMask
, *wxWHITE
);
300 gs_bmpWithColMask
->SetMask(mask
);
305 // `Main program' equivalent: the program execution "starts" here
308 // Create the main application window
309 MyFrame
*frame
= new MyFrame("Drawing sample",
310 wxPoint(50, 50), wxSize(550, 340));
312 // Show it and tell the application that it's our main window
318 wxLogError(wxT("Can't load one of the bitmap files needed ")
319 wxT("for this sample from the current or parent ")
320 wxT("directory, please copy them there."));
332 void MyApp::DeleteBitmaps()
335 delete gs_bmpWithColMask
;
337 delete gs_bmpWithMask
;
343 gs_bmpWithColMask
= NULL
;
345 gs_bmpWithMask
= NULL
;
351 // ----------------------------------------------------------------------------
353 // ----------------------------------------------------------------------------
355 // the event tables connect the wxWindows events with the functions (event
356 // handlers) which process them.
357 BEGIN_EVENT_TABLE(MyCanvas
, wxScrolledWindow
)
358 EVT_PAINT (MyCanvas::OnPaint
)
359 EVT_MOTION (MyCanvas::OnMouseMove
)
364 MyCanvas::MyCanvas(MyFrame
*parent
)
365 : wxScrolledWindow(parent
, -1, wxDefaultPosition
, wxDefaultSize
,
366 wxHSCROLL
| wxVSCROLL
| wxNO_FULL_REPAINT_ON_RESIZE
)
369 m_show
= Show_Default
;
370 m_smile_bmp
= wxBitmap(smile_xpm
);
371 m_std_icon
= wxTheApp
->GetStdIcon(wxICON_INFORMATION
);
374 void MyCanvas::DrawTestBrushes(wxDC
& dc
)
376 static const wxCoord WIDTH
= 200;
377 static const wxCoord HEIGHT
= 80;
382 dc
.SetBrush(wxBrush(*wxGREEN
, wxSOLID
));
383 dc
.DrawRectangle(x
, y
, WIDTH
, HEIGHT
);
384 dc
.DrawText("Solid green", x
+ 10, y
+ 10);
387 dc
.SetBrush(wxBrush(*wxRED
, wxCROSSDIAG_HATCH
));
388 dc
.DrawRectangle(x
, y
, WIDTH
, HEIGHT
);
389 dc
.DrawText("Hatched red", x
+ 10, y
+ 10);
392 dc
.SetBrush(wxBrush(*gs_bmpMask
));
393 dc
.DrawRectangle(x
, y
, WIDTH
, HEIGHT
);
394 dc
.DrawText("Stipple mono", x
+ 10, y
+ 10);
397 dc
.SetBrush(wxBrush(*gs_bmpNoMask
));
398 dc
.DrawRectangle(x
, y
, WIDTH
, HEIGHT
);
399 dc
.DrawText("Stipple colour", x
+ 10, y
+ 10);
402 void MyCanvas::DrawTestPoly(wxDC
& dc
)
404 wxBrush
brushHatch(*wxRED
, wxFDIAGONAL_HATCH
);
405 dc
.SetBrush(brushHatch
);
408 star
[0] = wxPoint(100, 60);
409 star
[1] = wxPoint(60, 150);
410 star
[2] = wxPoint(160, 100);
411 star
[3] = wxPoint(40, 100);
412 star
[4] = wxPoint(140, 150);
414 dc
.DrawText("You should see two (irregular) stars below, the left one "
416 dc
.DrawText("except for the central region and the right "
417 "one entirely hatched", 10, 30);
419 dc
.DrawPolygon(WXSIZEOF(star
), star
);
420 dc
.DrawPolygon(WXSIZEOF(star
), star
, 160, 0, wxWINDING_RULE
);
423 void MyCanvas::DrawTestLines( int x
, int y
, int width
, wxDC
&dc
)
425 dc
.SetPen( wxPen( wxT("black"), width
, wxSOLID
) );
426 dc
.SetBrush( *wxRED_BRUSH
);
427 dc
.DrawText(wxString::Format(wxT("Testing lines of width %d"), width
), x
+ 10, y
- 10);
428 dc
.DrawRectangle( x
+10, y
+10, 100, 190 );
430 dc
.DrawText("Solid/dot/short dash/long dash/dot dash", x
+ 150, y
+ 10);
431 dc
.SetPen( wxPen( wxT("black"), width
, wxSOLID
) );
432 dc
.DrawLine( x
+20, y
+20, 100, y
+20 );
433 dc
.SetPen( wxPen( wxT("black"), width
, wxDOT
) );
434 dc
.DrawLine( x
+20, y
+30, 100, y
+30 );
435 dc
.SetPen( wxPen( wxT("black"), width
, wxSHORT_DASH
) );
436 dc
.DrawLine( x
+20, y
+40, 100, y
+40 );
437 dc
.SetPen( wxPen( wxT("black"), width
, wxLONG_DASH
) );
438 dc
.DrawLine( x
+20, y
+50, 100, y
+50 );
439 dc
.SetPen( wxPen( wxT("black"), width
, wxDOT_DASH
) );
440 dc
.DrawLine( x
+20, y
+60, 100, y
+60 );
442 dc
.DrawText("Misc hatches", x
+ 150, y
+ 70);
443 dc
.SetPen( wxPen( wxT("black"), width
, wxBDIAGONAL_HATCH
) );
444 dc
.DrawLine( x
+20, y
+70, 100, y
+70 );
445 dc
.SetPen( wxPen( wxT("black"), width
, wxCROSSDIAG_HATCH
) );
446 dc
.DrawLine( x
+20, y
+80, 100, y
+80 );
447 dc
.SetPen( wxPen( wxT("black"), width
, wxFDIAGONAL_HATCH
) );
448 dc
.DrawLine( x
+20, y
+90, 100, y
+90 );
449 dc
.SetPen( wxPen( wxT("black"), width
, wxCROSS_HATCH
) );
450 dc
.DrawLine( x
+20, y
+100, 100, y
+100 );
451 dc
.SetPen( wxPen( wxT("black"), width
, wxHORIZONTAL_HATCH
) );
452 dc
.DrawLine( x
+20, y
+110, 100, y
+110 );
453 dc
.SetPen( wxPen( wxT("black"), width
, wxVERTICAL_HATCH
) );
454 dc
.DrawLine( x
+20, y
+120, 100, y
+120 );
456 dc
.DrawText("User dash", x
+ 150, y
+ 140);
457 wxPen
ud( wxT("black"), width
, wxUSER_DASH
);
460 ud
.SetDashes( 1, dash1
);
461 dc
.DrawLine( x
+20, y
+140, 100, y
+140 );
463 ud
.SetDashes( 1, dash1
);
464 dc
.DrawLine( x
+20, y
+150, 100, y
+150 );
466 ud
.SetDashes( 1, dash1
);
467 dc
.DrawLine( x
+20, y
+160, 100, y
+160 );
469 ud
.SetDashes( 1, dash1
);
470 dc
.DrawLine( x
+20, y
+170, 100, y
+170 );
473 void MyCanvas::DrawDefault(wxDC
& dc
)
476 dc
.DrawCircle(0, 0, 10);
477 #if !(defined __WXGTK__) && !(defined __WXMOTIF__) && !(defined __WXMGL__)
478 // not implemented in wxGTK or wxMOTIF :-(
479 dc
.FloodFill(0, 0, wxColour(255, 0, 0));
482 dc
.DrawCheckMark(5, 80, 15, 15);
483 dc
.DrawCheckMark(25, 80, 30, 30);
484 dc
.DrawCheckMark(60, 80, 60, 60);
486 // this is the test for "blitting bitmap into DC damages selected brush" bug
487 wxCoord rectSize
= m_std_icon
.GetWidth() + 10;
489 dc
.SetPen(*wxTRANSPARENT_PEN
);
490 dc
.SetBrush( *wxGREEN_BRUSH
);
491 dc
.DrawRectangle(x
, 10, rectSize
, rectSize
);
492 dc
.DrawBitmap(m_std_icon
, x
+ 5, 15, TRUE
);
494 dc
.DrawRectangle(x
, 10, rectSize
, rectSize
);
495 dc
.DrawIcon(m_std_icon
, x
+ 5, 15);
497 dc
.DrawRectangle(x
, 10, rectSize
, rectSize
);
499 // test for "transparent" bitmap drawing (it intersects with the last
501 //dc.SetBrush( *wxTRANSPARENT_BRUSH );
503 if (m_smile_bmp
.Ok())
504 dc
.DrawBitmap(m_smile_bmp
, x
+ rectSize
- 20, rectSize
- 10, TRUE
);
506 dc
.SetBrush( *wxBLACK_BRUSH
);
507 dc
.DrawRectangle( 0, 160, 1000, 300 );
510 wxBitmap
bitmap(20,70);
512 memdc
.SelectObject( bitmap
);
513 memdc
.SetBrush( *wxBLACK_BRUSH
);
514 memdc
.SetPen( *wxWHITE_PEN
);
515 memdc
.DrawRectangle(0,0,20,70);
516 memdc
.DrawLine( 10,0,10,70 );
519 wxPen pen
= *wxRED_PEN
;
521 memdc
.DrawLine( 10, 5,10, 5 );
522 memdc
.DrawLine( 10,10,11,10 );
523 memdc
.DrawLine( 10,15,12,15 );
524 memdc
.DrawLine( 10,20,13,20 );
527 memdc.SetPen(*wxRED_PEN);
528 memdc.DrawLine( 12, 5,12, 5 );
529 memdc.DrawLine( 12,10,13,10 );
530 memdc.DrawLine( 12,15,14,15 );
531 memdc.DrawLine( 12,20,15,20 );
535 memdc
.DrawLine( 10,25,10,25 );
536 memdc
.DrawLine( 10,30, 9,30 );
537 memdc
.DrawLine( 10,35, 8,35 );
538 memdc
.DrawLine( 10,40, 7,40 );
541 dc
.SetPen(*wxWHITE_PEN
);
542 memdc
.SetLogicalFunction( wxINVERT
);
543 memdc
.SetPen( *wxWHITE_PEN
);
544 memdc
.DrawLine( 10,50,10,50 );
545 memdc
.DrawLine( 10,55,11,55 );
546 memdc
.DrawLine( 10,60,12,60 );
547 memdc
.DrawLine( 10,65,13,65 );
549 memdc
.DrawLine( 12,50,12,50 );
550 memdc
.DrawLine( 12,55,13,55 );
551 memdc
.DrawLine( 12,60,14,60 );
552 memdc
.DrawLine( 12,65,15,65 );
554 memdc
.SelectObject( wxNullBitmap
);
555 dc
.DrawBitmap( bitmap
, 10, 170 );
556 wxImage
image( bitmap
);
557 image
.Rescale( 60,210 );
558 bitmap
= image
.ConvertToBitmap();
559 dc
.DrawBitmap( bitmap
, 50, 170 );
561 // test the rectangle outline drawing - there should be one pixel between
562 // the rect and the lines
563 dc
.SetPen(*wxWHITE_PEN
);
564 dc
.SetBrush( *wxTRANSPARENT_BRUSH
);
565 dc
.DrawRectangle(150, 170, 49, 29);
566 dc
.DrawRectangle(200, 170, 49, 29);
567 dc
.SetPen(*wxWHITE_PEN
);
568 dc
.DrawLine(250, 210, 250, 170);
569 dc
.DrawLine(260, 200, 150, 200);
571 // test the rectangle filled drawing - there should be one pixel between
572 // the rect and the lines
573 dc
.SetPen(*wxTRANSPARENT_PEN
);
574 dc
.SetBrush( *wxWHITE_BRUSH
);
575 dc
.DrawRectangle(300, 170, 49, 29);
576 dc
.DrawRectangle(350, 170, 49, 29);
577 dc
.SetPen(*wxWHITE_PEN
);
578 dc
.DrawLine(400, 170, 400, 210);
579 dc
.DrawLine(300, 200, 410, 200);
581 // a few more tests of this kind
582 dc
.SetPen(*wxRED_PEN
);
583 dc
.SetBrush( *wxWHITE_BRUSH
);
584 dc
.DrawRectangle(300, 220, 1, 1);
585 dc
.DrawRectangle(310, 220, 2, 2);
586 dc
.DrawRectangle(320, 220, 3, 3);
587 dc
.DrawRectangle(330, 220, 4, 4);
589 dc
.SetPen(*wxTRANSPARENT_PEN
);
590 dc
.SetBrush( *wxWHITE_BRUSH
);
591 dc
.DrawRectangle(300, 230, 1, 1);
592 dc
.DrawRectangle(310, 230, 2, 2);
593 dc
.DrawRectangle(320, 230, 3, 3);
594 dc
.DrawRectangle(330, 230, 4, 4);
596 // and now for filled rect with outline
597 dc
.SetPen(*wxRED_PEN
);
598 dc
.SetBrush( *wxWHITE_BRUSH
);
599 dc
.DrawRectangle(500, 170, 49, 29);
600 dc
.DrawRectangle(550, 170, 49, 29);
601 dc
.SetPen(*wxWHITE_PEN
);
602 dc
.DrawLine(600, 170, 600, 210);
603 dc
.DrawLine(500, 200, 610, 200);
605 // test the rectangle outline drawing - there should be one pixel between
606 // the rect and the lines
607 dc
.SetPen(*wxWHITE_PEN
);
608 dc
.SetBrush( *wxTRANSPARENT_BRUSH
);
609 dc
.DrawRoundedRectangle(150, 270, 49, 29, 6);
610 dc
.DrawRoundedRectangle(200, 270, 49, 29, 6);
611 dc
.SetPen(*wxWHITE_PEN
);
612 dc
.DrawLine(250, 270, 250, 310);
613 dc
.DrawLine(150, 300, 260, 300);
615 // test the rectangle filled drawing - there should be one pixel between
616 // the rect and the lines
617 dc
.SetPen(*wxTRANSPARENT_PEN
);
618 dc
.SetBrush( *wxWHITE_BRUSH
);
619 dc
.DrawRoundedRectangle(300, 270, 49, 29, 6);
620 dc
.DrawRoundedRectangle(350, 270, 49, 29, 6);
621 dc
.SetPen(*wxWHITE_PEN
);
622 dc
.DrawLine(400, 270, 400, 310);
623 dc
.DrawLine(300, 300, 410, 300);
625 // Added by JACS to demonstrate bizarre behaviour.
626 // With a size of 70, we get a missing red RHS,
627 // and the hight is too small, so we get yellow
628 // showing. With a size of 40, it draws as expected:
629 // it just shows a white rectangle with red outline.
631 int totalHeight
= 70;
632 wxBitmap
bitmap2(totalWidth
, totalHeight
);
635 memdc2
.SelectObject(bitmap2
);
637 wxBrush
yellowBrush(wxColour(255, 255, 0), wxSOLID
);
638 memdc2
.SetBackground(yellowBrush
);
641 wxPen
yellowPen(wxColour(255, 255, 0), 1, wxSOLID
);
643 // Now draw a white rectangle with red outline. It should
644 // entirely eclipse the yellow background.
645 memdc2
.SetPen(*wxRED_PEN
);
646 memdc2
.SetBrush(*wxWHITE_BRUSH
);
648 memdc2
.DrawRectangle(0, 0, totalWidth
, totalHeight
);
650 memdc2
.SetPen(wxNullPen
);
651 memdc2
.SetBrush(wxNullBrush
);
652 memdc2
.SelectObject(wxNullBitmap
);
654 dc
.DrawBitmap(bitmap2
, 500, 270);
656 // Repeat, but draw directly on dc
657 // Draw a yellow rectangle filling the bitmap
659 x
= 600; int y
= 270;
660 dc
.SetPen(yellowPen
);
661 dc
.SetBrush(yellowBrush
);
662 dc
.DrawRectangle(x
, y
, totalWidth
, totalHeight
);
664 // Now draw a white rectangle with red outline. It should
665 // entirely eclipse the yellow background.
666 dc
.SetPen(*wxRED_PEN
);
667 dc
.SetBrush(*wxWHITE_BRUSH
);
669 dc
.DrawRectangle(x
, y
, totalWidth
, totalHeight
);
672 void MyCanvas::DrawText(wxDC
& dc
)
674 // set underlined font for testing
675 dc
.SetFont( wxFont(12, wxMODERN
, wxNORMAL
, wxNORMAL
, TRUE
) );
676 dc
.DrawText( "This is text", 110, 10 );
677 dc
.DrawRotatedText( "That is text", 20, 10, -45 );
679 // use wxSWISS_FONT and not wxNORMAL_FONT as the latter can't be rotated
680 // under Win9x (it is not TrueType)
681 dc
.SetFont( *wxSWISS_FONT
);
684 dc
.SetBackgroundMode(wxTRANSPARENT
);
686 for ( int n
= -180; n
< 180; n
+= 30 )
688 text
.Printf(wxT(" %d rotated text"), n
);
689 dc
.DrawRotatedText(text
, 400, 400, n
);
692 dc
.SetFont( wxFont( 18, wxSWISS
, wxNORMAL
, wxNORMAL
) );
694 dc
.DrawText( "This is Swiss 18pt text.", 110, 40 );
699 dc
.GetTextExtent( "This is Swiss 18pt text.", &length
, &height
, &descent
);
700 text
.Printf( wxT("Dimensions are length %ld, height %ld, descent %ld"), length
, height
, descent
);
701 dc
.DrawText( text
, 110, 80 );
703 text
.Printf( wxT("CharHeight() returns: %d"), dc
.GetCharHeight() );
704 dc
.DrawText( text
, 110, 120 );
706 dc
.DrawRectangle( 100, 40, 4, height
);
708 // test the logical function effect
710 dc
.SetLogicalFunction(wxINVERT
);
711 dc
.DrawText( "There should be no text below", 110, 150 );
712 dc
.DrawRectangle( 110, y
, 100, height
);
714 // twice drawn inverted should result in invisible
716 dc
.DrawText( "Invisible text", 110, y
);
717 dc
.DrawRectangle( 110, y
, 100, height
);
718 dc
.DrawText( "Invisible text", 110, y
);
719 dc
.DrawRectangle( 110, y
, 100, height
);
720 dc
.SetLogicalFunction(wxCOPY
);
723 dc
.DrawRectangle( 110, y
, 100, height
);
724 dc
.DrawText( "Visible text", 110, y
);
731 } rasterOperations
[] =
733 { wxT("wxAND"), wxAND
},
734 { wxT("wxAND_INVERT"), wxAND_INVERT
},
735 { wxT("wxAND_REVERSE"), wxAND_REVERSE
},
736 { wxT("wxCLEAR"), wxCLEAR
},
737 { wxT("wxCOPY"), wxCOPY
},
738 { wxT("wxEQUIV"), wxEQUIV
},
739 { wxT("wxINVERT"), wxINVERT
},
740 { wxT("wxNAND"), wxNAND
},
741 { wxT("wxNO_OP"), wxNO_OP
},
742 { wxT("wxOR"), wxOR
},
743 { wxT("wxOR_INVERT"), wxOR_INVERT
},
744 { wxT("wxOR_REVERSE"), wxOR_REVERSE
},
745 { wxT("wxSET"), wxSET
},
746 { wxT("wxSRC_INVERT"), wxSRC_INVERT
},
747 { wxT("wxXOR"), wxXOR
},
750 void MyCanvas::DrawImages(wxDC
& dc
)
752 dc
.DrawText("original image", 0, 0);
753 dc
.DrawBitmap(*gs_bmpNoMask
, 0, 20, 0);
754 dc
.DrawText("with colour mask", 0, 100);
755 dc
.DrawBitmap(*gs_bmpWithColMask
, 0, 120, TRUE
);
756 dc
.DrawText("the mask image", 0, 200);
757 dc
.DrawBitmap(*gs_bmpMask
, 0, 220, 0);
758 dc
.DrawText("masked image", 0, 300);
759 dc
.DrawBitmap(*gs_bmpWithMask
, 0, 320, TRUE
);
761 int cx
= gs_bmpWithColMask
->GetWidth(),
762 cy
= gs_bmpWithColMask
->GetHeight();
765 for ( size_t n
= 0; n
< WXSIZEOF(rasterOperations
); n
++ )
767 wxCoord x
= 120 + 150*(n%4
),
770 dc
.DrawText(rasterOperations
[n
].name
, x
, y
- 20);
771 memDC
.SelectObject(*gs_bmpWithColMask
);
772 dc
.Blit(x
, y
, cx
, cy
, &memDC
, 0, 0, rasterOperations
[n
].rop
, TRUE
);
776 void MyCanvas::DrawWithLogicalOps(wxDC
& dc
)
778 static const wxCoord w
= 60;
779 static const wxCoord h
= 60;
781 // reuse the text colour here
782 dc
.SetPen(wxPen(m_owner
->m_colourForeground
, 1, wxSOLID
));
783 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
786 for ( n
= 0; n
< WXSIZEOF(rasterOperations
); n
++ )
788 wxCoord x
= 20 + 150*(n%4
),
791 dc
.DrawText(rasterOperations
[n
].name
, x
, y
- 20);
792 dc
.SetLogicalFunction(rasterOperations
[n
].rop
);
793 dc
.DrawRectangle(x
, y
, w
, h
);
794 dc
.DrawLine(x
, y
, x
+ w
, y
+ h
);
795 dc
.DrawLine(x
+ w
, y
, x
, y
+ h
);
798 // now some filled rectangles
799 dc
.SetBrush(wxBrush(m_owner
->m_colourForeground
, wxSOLID
));
801 for ( n
= 0; n
< WXSIZEOF(rasterOperations
); n
++ )
803 wxCoord x
= 20 + 150*(n%4
),
806 dc
.DrawText(rasterOperations
[n
].name
, x
, y
- 20);
807 dc
.SetLogicalFunction(rasterOperations
[n
].rop
);
808 dc
.DrawRectangle(x
, y
, w
, h
);
812 void MyCanvas::DrawCircles(wxDC
& dc
)
818 dc
.DrawText("Some circles", 0, y
);
819 dc
.DrawCircle(x
, y
, r
);
820 dc
.DrawCircle(x
+ 2*r
, y
, r
);
821 dc
.DrawCircle(x
+ 4*r
, y
, r
);
824 dc
.DrawText("And ellipses", 0, y
);
825 dc
.DrawEllipse(x
- r
, y
, 2*r
, r
);
826 dc
.DrawEllipse(x
+ r
, y
, 2*r
, r
);
827 dc
.DrawEllipse(x
+ 3*r
, y
, 2*r
, r
);
830 dc
.DrawText("And arcs", 0, y
);
831 dc
.DrawArc(x
- r
, y
, x
+ r
, y
, x
, y
);
832 dc
.DrawArc(x
+ 4*r
, y
, x
+ 2*r
, y
, x
+ 3*r
, y
);
833 dc
.DrawArc(x
+ 5*r
, y
, x
+ 5*r
, y
, x
+ 6*r
, y
);
836 dc
.DrawEllipticArc(x
- r
, y
, 2*r
, r
, 0, 90);
837 dc
.DrawEllipticArc(x
+ r
, y
, 2*r
, r
, 90, 180);
838 dc
.DrawEllipticArc(x
+ 3*r
, y
, 2*r
, r
, 180, 270);
839 dc
.DrawEllipticArc(x
+ 5*r
, y
, 2*r
, r
, 270, 360);
842 void MyCanvas::DrawRegions(wxDC
& dc
)
844 dc
.DrawText("You should see a red rect partly covered by a cyan one "
845 "on the left", 10, 5);
846 dc
.DrawText("and 5 smileys from which 4 are partially clipped on the right",
847 10, 5 + dc
.GetCharHeight());
848 dc
.DrawText("The second copy should be identical but right part of it "
849 "should be offset by 10 pixels.",
850 10, 5 + 2*dc
.GetCharHeight());
852 DrawRegionsHelper(dc
, 10, TRUE
);
853 DrawRegionsHelper(dc
, 350, FALSE
);
856 void MyCanvas::DrawRegionsHelper(wxDC
& dc
, wxCoord x
, bool firstTime
)
860 dc
.DestroyClippingRegion();
861 dc
.SetBrush( *wxWHITE_BRUSH
);
862 dc
.SetPen( *wxTRANSPARENT_PEN
);
863 dc
.DrawRectangle( x
, y
, 310, 310 );
865 dc
.SetClippingRegion( x
+ 10, y
+ 10, 100, 270 );
867 dc
.SetBrush( *wxRED_BRUSH
);
868 dc
.DrawRectangle( x
, y
, 310, 310 );
870 dc
.SetClippingRegion( x
+ 10, y
+ 10, 100, 100 );
872 dc
.SetBrush( *wxCYAN_BRUSH
);
873 dc
.DrawRectangle( x
, y
, 310, 310 );
875 dc
.DestroyClippingRegion();
877 wxRegion
region(x
+ 110, y
+ 20, 100, 270);
879 region
.Offset(10, 10);
881 dc
.SetClippingRegion(region
);
883 dc
.SetBrush( *wxGREY_BRUSH
);
884 dc
.DrawRectangle( x
, y
, 310, 310 );
886 if (m_smile_bmp
.Ok())
888 dc
.DrawBitmap( m_smile_bmp
, x
+ 150, y
+ 150, TRUE
);
889 dc
.DrawBitmap( m_smile_bmp
, x
+ 130, y
+ 10, TRUE
);
890 dc
.DrawBitmap( m_smile_bmp
, x
+ 130, y
+ 280, TRUE
);
891 dc
.DrawBitmap( m_smile_bmp
, x
+ 100, y
+ 70, TRUE
);
892 dc
.DrawBitmap( m_smile_bmp
, x
+ 200, y
+ 70, TRUE
);
896 void MyCanvas::OnPaint(wxPaintEvent
&WXUNUSED(event
))
901 m_owner
->PrepareDC(dc
);
903 dc
.SetBackgroundMode( m_owner
->m_backgroundMode
);
904 if ( m_owner
->m_backgroundBrush
.Ok() )
905 dc
.SetBackground( m_owner
->m_backgroundBrush
);
906 if ( m_owner
->m_colourForeground
.Ok() )
907 dc
.SetTextForeground( m_owner
->m_colourForeground
);
908 if ( m_owner
->m_colourBackground
.Ok() )
909 dc
.SetTextBackground( m_owner
->m_colourBackground
);
911 if ( m_owner
->m_textureBackground
) {
912 if ( ! m_owner
->m_backgroundBrush
.Ok() ) {
913 wxBrush
b(wxColour(0,128,0), wxSOLID
);
920 if ( m_owner
->m_textureBackground
) {
921 dc
.SetPen(*wxMEDIUM_GREY_PEN
);
922 for (int i
=0; i
<200; i
++)
923 dc
.DrawLine(0, i
*10, i
*10, 0);
945 DrawTestLines( 0, 100, 0, dc
);
946 DrawTestLines( 0, 320, 1, dc
);
947 DrawTestLines( 0, 540, 2, dc
);
948 DrawTestLines( 0, 760, 6, dc
);
964 DrawWithLogicalOps(dc
);
969 void MyCanvas::OnMouseMove(wxMouseEvent
&event
)
973 m_owner
->PrepareDC(dc
);
975 wxPoint pos
= event
.GetPosition();
976 long x
= dc
.DeviceToLogicalX( pos
.x
);
977 long y
= dc
.DeviceToLogicalY( pos
.y
);
979 str
.Printf( wxT("Current mouse position: %d,%d"), (int)x
, (int)y
);
980 m_owner
->SetStatusText( str
);
983 // ----------------------------------------------------------------------------
985 // ----------------------------------------------------------------------------
987 // the event tables connect the wxWindows events with the functions (event
988 // handlers) which process them. It can be also done at run-time, but for the
989 // simple menu events like this the static method is much simpler.
990 BEGIN_EVENT_TABLE(MyFrame
, wxFrame
)
991 EVT_MENU (File_Quit
, MyFrame::OnQuit
)
992 EVT_MENU (File_About
, MyFrame::OnAbout
)
994 EVT_MENU_RANGE(MenuShow_First
, MenuShow_Last
, MyFrame::OnShow
)
996 EVT_MENU_RANGE(MenuOption_First
, MenuOption_Last
, MyFrame::OnOption
)
1000 MyFrame::MyFrame(const wxString
& title
, const wxPoint
& pos
, const wxSize
& size
)
1001 : wxFrame((wxFrame
*)NULL
, -1, title
, pos
, size
,
1002 wxDEFAULT_FRAME_STYLE
| wxNO_FULL_REPAINT_ON_RESIZE
)
1004 // set the frame icon
1005 SetIcon(wxICON(mondrian
));
1007 wxMenu
*menuFile
= new wxMenu
;
1008 menuFile
->Append(File_ShowDefault
, "&Default screen\tF1");
1009 menuFile
->Append(File_ShowText
, "&Text screen\tF2");
1010 menuFile
->Append(File_ShowLines
, "&Lines screen\tF3");
1011 menuFile
->Append(File_ShowBrushes
, "&Brushes screen\tF4");
1012 menuFile
->Append(File_ShowPolygons
, "&Polygons screen\tF5");
1013 menuFile
->Append(File_ShowMask
, "&Mask screen\tF6");
1014 menuFile
->Append(File_ShowOps
, "&ROP screen\tF7");
1015 menuFile
->Append(File_ShowRegions
, "Re&gions screen\tF8");
1016 menuFile
->Append(File_ShowCircles
, "&Circles screen\tF9");
1017 menuFile
->AppendSeparator();
1018 menuFile
->Append(File_About
, "&About...\tCtrl-A", "Show about dialog");
1019 menuFile
->AppendSeparator();
1020 menuFile
->Append(File_Quit
, "E&xit\tAlt-X", "Quit this program");
1022 wxMenu
*menuMapMode
= new wxMenu
;
1023 menuMapMode
->Append( MapMode_Text
, "&TEXT map mode" );
1024 menuMapMode
->Append( MapMode_Lometric
, "&LOMETRIC map mode" );
1025 menuMapMode
->Append( MapMode_Twips
, "T&WIPS map mode" );
1026 menuMapMode
->Append( MapMode_Points
, "&POINTS map mode" );
1027 menuMapMode
->Append( MapMode_Metric
, "&METRIC map mode" );
1029 wxMenu
*menuUserScale
= new wxMenu
;
1030 menuUserScale
->Append( UserScale_StretchHoriz
, "Stretch &horizontally\tCtrl-H" );
1031 menuUserScale
->Append( UserScale_ShrinkHoriz
, "Shrin&k horizontally\tCtrl-G" );
1032 menuUserScale
->Append( UserScale_StretchVertic
, "Stretch &vertically\tCtrl-V" );
1033 menuUserScale
->Append( UserScale_ShrinkVertic
, "&Shrink vertically\tCtrl-W" );
1034 menuUserScale
->AppendSeparator();
1035 menuUserScale
->Append( UserScale_Restore
, "&Restore to normal\tCtrl-0" );
1037 wxMenu
*menuAxis
= new wxMenu
;
1038 menuAxis
->Append( AxisMirror_Horiz
, "Mirror horizontally\tCtrl-M", "", TRUE
);
1039 menuAxis
->Append( AxisMirror_Vertic
, "Mirror vertically\tCtrl-N", "", TRUE
);
1041 wxMenu
*menuLogical
= new wxMenu
;
1042 menuLogical
->Append( LogicalOrigin_MoveDown
, "Move &down\tCtrl-D" );
1043 menuLogical
->Append( LogicalOrigin_MoveUp
, "Move &up\tCtrl-U" );
1044 menuLogical
->Append( LogicalOrigin_MoveLeft
, "Move &right\tCtrl-L" );
1045 menuLogical
->Append( LogicalOrigin_MoveRight
, "Move &left\tCtrl-R" );
1046 menuLogical
->AppendSeparator();
1047 menuLogical
->Append( LogicalOrigin_Set
, "Set to (&100, 100)\tShift-Ctrl-1" );
1048 menuLogical
->Append( LogicalOrigin_Restore
, "&Restore to normal\tShift-Ctrl-0" );
1050 wxMenu
*menuColour
= new wxMenu
;
1051 menuColour
->Append( Colour_TextForeground
, "Text &foreground..." );
1052 menuColour
->Append( Colour_TextBackground
, "Text &background..." );
1053 menuColour
->Append( Colour_Background
, "Background &colour..." );
1054 menuColour
->Append( Colour_BackgroundMode
, "&Opaque/transparent\tCtrl-B", "", TRUE
);
1055 menuColour
->Append( Colour_TextureBackgound
, "Draw textured back&ground\tCtrl-T", "", TRUE
);
1057 // now append the freshly created menu to the menu bar...
1058 wxMenuBar
*menuBar
= new wxMenuBar
;
1059 menuBar
->Append(menuFile
, "&File");
1060 menuBar
->Append(menuMapMode
, "&Mode");
1061 menuBar
->Append(menuUserScale
, "&Scale");
1062 menuBar
->Append(menuAxis
, "&Axis");
1063 menuBar
->Append(menuLogical
, "&Origin");
1064 menuBar
->Append(menuColour
, "&Colours");
1066 // ... and attach this menu bar to the frame
1067 SetMenuBar(menuBar
);
1069 // create a status bar just for fun (by default with 1 pane only)
1071 SetStatusText("Welcome to wxWindows!");
1073 m_mapMode
= wxMM_TEXT
;
1076 m_xLogicalOrigin
= 0;
1077 m_yLogicalOrigin
= 0;
1079 m_yAxisReversed
= FALSE
;
1080 m_backgroundMode
= wxSOLID
;
1081 m_colourForeground
= *wxRED
;
1082 m_colourBackground
= *wxBLUE
;
1083 m_textureBackground
= FALSE
;
1085 m_canvas
= new MyCanvas( this );
1086 m_canvas
->SetScrollbars( 10, 10, 100, 240 );
1091 void MyFrame::OnQuit(wxCommandEvent
& WXUNUSED(event
))
1093 // TRUE is to force the frame to close
1097 void MyFrame::OnAbout(wxCommandEvent
& WXUNUSED(event
))
1100 msg
.Printf( wxT("This is the about dialog of the drawing sample.\n")
1101 wxT("This sample tests various primitive drawing functions\n")
1102 wxT("(without any attempts to prevent flicker).\n")
1103 wxT("Copyright (c) Robert Roebling 1999")
1106 wxMessageBox(msg
, "About Drawing", wxOK
| wxICON_INFORMATION
, this);
1109 void MyFrame::OnShow(wxCommandEvent
& event
)
1111 m_canvas
->Show((ScreenToShow
)(event
.GetId() - MenuShow_First
));
1114 void MyFrame::OnOption(wxCommandEvent
& event
)
1116 switch (event
.GetId())
1119 m_mapMode
= wxMM_TEXT
;
1121 case MapMode_Lometric
:
1122 m_mapMode
= wxMM_LOMETRIC
;
1125 m_mapMode
= wxMM_TWIPS
;
1127 case MapMode_Points
:
1128 m_mapMode
= wxMM_POINTS
;
1130 case MapMode_Metric
:
1131 m_mapMode
= wxMM_METRIC
;
1134 case LogicalOrigin_MoveDown
:
1135 m_yLogicalOrigin
+= 10;
1137 case LogicalOrigin_MoveUp
:
1138 m_yLogicalOrigin
-= 10;
1140 case LogicalOrigin_MoveLeft
:
1141 m_xLogicalOrigin
+= 10;
1143 case LogicalOrigin_MoveRight
:
1144 m_xLogicalOrigin
-= 10;
1146 case LogicalOrigin_Set
:
1148 m_yLogicalOrigin
= -100;
1150 case LogicalOrigin_Restore
:
1152 m_yLogicalOrigin
= 0;
1155 case UserScale_StretchHoriz
:
1156 m_xUserScale
*= 1.10;
1158 case UserScale_ShrinkHoriz
:
1159 m_xUserScale
/= 1.10;
1161 case UserScale_StretchVertic
:
1162 m_yUserScale
*= 1.10;
1164 case UserScale_ShrinkVertic
:
1165 m_yUserScale
/= 1.10;
1167 case UserScale_Restore
:
1172 case AxisMirror_Vertic
:
1173 m_yAxisReversed
= !m_yAxisReversed
;
1175 case AxisMirror_Horiz
:
1176 m_xAxisReversed
= !m_xAxisReversed
;
1179 case Colour_TextForeground
:
1180 m_colourForeground
= SelectColour();
1182 case Colour_TextBackground
:
1183 m_colourBackground
= SelectColour();
1185 case Colour_Background
:
1187 wxColour col
= SelectColour();
1190 m_backgroundBrush
.SetColour(col
);
1194 case Colour_BackgroundMode
:
1195 m_backgroundMode
= m_backgroundMode
== wxSOLID
? wxTRANSPARENT
1199 case Colour_TextureBackgound
:
1200 m_textureBackground
= ! m_textureBackground
;
1208 m_canvas
->Refresh();
1211 void MyFrame::PrepareDC(wxDC
& dc
)
1213 dc
.SetLogicalOrigin( m_xLogicalOrigin
, m_yLogicalOrigin
);
1214 dc
.SetAxisOrientation( !m_xAxisReversed
, m_yAxisReversed
);
1215 dc
.SetUserScale( m_xUserScale
, m_yUserScale
);
1216 dc
.SetMapMode( m_mapMode
);
1219 wxColour
MyFrame::SelectColour()
1223 wxColourDialog
dialog(this, &data
);
1225 if ( dialog
.ShowModal() == wxID_OK
)
1227 col
= dialog
.GetColourData().GetColour();