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__)
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)
68 // ----------------------------------------------------------------------------
70 // ----------------------------------------------------------------------------
72 static wxBitmap
*gs_bmpNoMask
= NULL
,
73 *gs_bmpWithColMask
= NULL
,
75 *gs_bmpWithMask
= NULL
,
80 // ----------------------------------------------------------------------------
82 // ----------------------------------------------------------------------------
84 // Define a new application type, each program should derive a class from wxApp
85 class MyApp
: public wxApp
88 // override base class virtuals
89 // ----------------------------
91 // this one is called on application startup and is a good place for the app
92 // initialization (doing it here and not in the ctor allows to have an error
93 // return: if OnInit() returns false, the application terminates)
94 virtual bool OnInit();
96 virtual int OnExit() { DeleteBitmaps(); return 0; }
106 // Define a new frame type: this is going to be our main frame
107 class MyFrame
: public wxFrame
111 MyFrame(const wxString
& title
, const wxPoint
& pos
, const wxSize
& size
);
113 // event handlers (these functions should _not_ be virtual)
114 void OnQuit(wxCommandEvent
& event
);
115 void OnAbout(wxCommandEvent
& event
);
116 void OnShow(wxCommandEvent
&event
);
117 void OnOption(wxCommandEvent
&event
);
119 wxColour
SelectColour();
120 void PrepareDC(wxDC
& dc
);
122 int m_backgroundMode
;
123 int m_textureBackground
;
127 int m_xLogicalOrigin
;
128 int m_yLogicalOrigin
;
129 bool m_xAxisReversed
,
131 wxColour m_colourForeground
, // these are _text_ colours
133 wxBrush m_backgroundBrush
;
137 // any class wishing to process wxWindows events must use this macro
138 DECLARE_EVENT_TABLE()
141 // define a scrollable canvas for drawing onto
142 class MyCanvas
: public wxScrolledWindow
145 MyCanvas( MyFrame
*parent
);
147 void OnPaint(wxPaintEvent
&event
);
148 void OnMouseMove(wxMouseEvent
&event
);
150 void Show(ScreenToShow show
) { m_show
= show
; Refresh(); }
153 void DrawTestPoly( int x
, int y
, wxDC
&dc
,int transparent
);
154 void DrawTestLines( int x
, int y
, int width
, wxDC
&dc
);
155 void DrawText(wxDC
& dc
);
156 void DrawImages(wxDC
& dc
);
157 void DrawWithLogicalOps(wxDC
& dc
);
158 void DrawRegions(wxDC
& dc
);
159 void DrawCircles(wxDC
& dc
);
160 void DrawDefault(wxDC
& dc
);
166 wxBitmap m_smile_bmp
;
169 DECLARE_EVENT_TABLE()
172 // ----------------------------------------------------------------------------
174 // ----------------------------------------------------------------------------
176 // IDs for the controls and the menu commands
184 File_ShowDefault
= MenuShow_First
,
192 MenuShow_Last
= File_ShowCircles
,
196 MapMode_Text
= MenuOption_First
,
202 UserScale_StretchHoriz
,
203 UserScale_ShrinkHoriz
,
204 UserScale_StretchVertic
,
205 UserScale_ShrinkVertic
,
211 LogicalOrigin_MoveDown
,
212 LogicalOrigin_MoveUp
,
213 LogicalOrigin_MoveLeft
,
214 LogicalOrigin_MoveRight
,
216 Colour_TextForeground
,
217 Colour_TextBackground
,
219 Colour_BackgroundMode
,
220 Colour_TextureBackgound
,
222 MenuOption_Last
= Colour_TextureBackgound
225 // ----------------------------------------------------------------------------
226 // event tables and other macros for wxWindows
227 // ----------------------------------------------------------------------------
230 // Create a new application object: this macro will allow wxWindows to create
231 // the application object during program execution (it's better than using a
232 // static object for many reasons) and also declares the accessor function
233 // wxGetApp() which will return the reference of the right type (i.e. MyApp and
237 // ============================================================================
239 // ============================================================================
241 // ----------------------------------------------------------------------------
242 // the application class
243 // ----------------------------------------------------------------------------
245 bool MyApp::LoadImages()
247 gs_bmpNoMask
= new wxBitmap
;
248 gs_bmpWithColMask
= new wxBitmap
;
249 gs_bmpMask
= new wxBitmap
;
250 gs_bmpWithMask
= new wxBitmap
;
251 gs_bmp4
= new wxBitmap
;
252 gs_bmp4_mono
= new wxBitmap
;
253 gs_bmp36
= new wxBitmap
;
259 wxString path
= pathList
.FindValidPath("pat4.bmp");
263 /* 4 colour bitmap */
264 gs_bmp4
->LoadFile(path
, wxBITMAP_TYPE_BMP
);
265 /* turn into mono-bitmap */
266 gs_bmp4_mono
->LoadFile(path
, wxBITMAP_TYPE_BMP
);
267 wxMask
* mask4
= new wxMask(*gs_bmp4_mono
, *wxBLACK
);
268 gs_bmp4_mono
->SetMask(mask4
);
270 path
= pathList
.FindValidPath("pat36.bmp");
273 gs_bmp36
->LoadFile(path
, wxBITMAP_TYPE_BMP
);
274 wxMask
* mask36
= new wxMask(*gs_bmp36
, *wxBLACK
);
275 gs_bmp36
->SetMask(mask36
);
277 path
= pathList
.FindValidPath("image.bmp");
280 gs_bmpNoMask
->LoadFile(path
, wxBITMAP_TYPE_BMP
);
281 gs_bmpWithMask
->LoadFile(path
, wxBITMAP_TYPE_BMP
);
282 gs_bmpWithColMask
->LoadFile(path
, wxBITMAP_TYPE_BMP
);
284 path
= pathList
.FindValidPath("mask.bmp");
287 gs_bmpMask
->LoadFile(path
, wxBITMAP_TYPE_BMP
);
289 wxMask
*mask
= new wxMask(*gs_bmpMask
, *wxBLACK
);
290 gs_bmpWithMask
->SetMask(mask
);
292 mask
= new wxMask(*gs_bmpWithColMask
, *wxWHITE
);
293 gs_bmpWithColMask
->SetMask(mask
);
298 // `Main program' equivalent: the program execution "starts" here
301 // Create the main application window
302 MyFrame
*frame
= new MyFrame("Drawing sample",
303 wxPoint(50, 50), wxSize(550, 340));
305 // Show it and tell the application that it's our main window
311 wxLogError("Can't load one of the bitmap files needed for this sample "
312 "from the current or parent directory, please copy them "
325 void MyApp::DeleteBitmaps()
328 delete gs_bmpWithColMask
;
330 delete gs_bmpWithMask
;
336 // ----------------------------------------------------------------------------
338 // ----------------------------------------------------------------------------
340 // the event tables connect the wxWindows events with the functions (event
341 // handlers) which process them.
342 BEGIN_EVENT_TABLE(MyCanvas
, wxScrolledWindow
)
343 EVT_PAINT (MyCanvas::OnPaint
)
344 EVT_MOTION (MyCanvas::OnMouseMove
)
347 #include "../image/smile.xpm"
349 MyCanvas::MyCanvas( MyFrame
*parent
) : wxScrolledWindow( parent
)
352 m_show
= Show_Default
;
353 m_smile_bmp
= wxBitmap(smile_xpm
);
354 m_std_icon
= wxTheApp
->GetStdIcon(wxICON_INFORMATION
);
357 // Draw a polygon and an overlapping rectangle
358 // If transparent is 1, the fill pattern is made transparent.
359 // If transparent is 2, the fill pattern is made transparent but inversed
360 // If is transparent is 0 the text for and background color will be used to represent/map
361 // the colors of the monochrome bitmap pixels to the fillpattern
363 // I abused the the menu items for setting so called back and fore ground color
364 // just to show how the those colors do influence the fillpatterns just play
365 // with those, and with the code variations are endless using other logical
368 void MyCanvas::DrawTestPoly( int x
, int y
,wxDC
&dc
,int transparent
)
370 wxBrush
* brush4
= new wxBrush(*gs_bmp4
);
371 wxBrush
* brush4_mono
= new wxBrush(*gs_bmp4_mono
);
372 wxBrush
* brush36
= new wxBrush(*gs_bmp36
);
375 todraw
[0].x
=(long)x
+100;
376 todraw
[0].y
=(long)y
+100;
377 todraw
[1].x
=(long)x
+300;
378 todraw
[1].y
=(long)y
+100;
379 todraw
[2].x
=(long)x
+300;
380 todraw
[2].y
=(long)y
+300;
381 todraw
[3].x
=(long)x
+150;
382 todraw
[3].y
=(long)y
+350;
383 todraw
[4].x
=(long)x
+100;
384 todraw
[4].y
=(long)y
+300;
402 dc
.SetLogicalFunction(wxCOPY
);
404 dc
.SetPen( wxPen( "black", 4, wxSOLID
) );
405 dc
.SetBrush( *brush4
);
406 dc
.DrawPolygon(5,todraw
,0,0,wxWINDING_RULE
);
408 dc
.SetPen( wxPen( "red", 4, wxSOLID
) );
409 dc
.SetBrush( *brush36
);
410 dc
.SetTextForeground(*wxCYAN
);
411 dc
.SetTextBackground(m_owner
->m_colourBackground
);
412 dc
.DrawRectangle( x
+10, y
+10, 200, 200 );
414 dc
.SetPen( wxPen( "green", 4, wxSOLID
) );
415 dc
.SetBrush( *brush4_mono
);
416 dc
.SetTextForeground(*wxCYAN
);
417 dc
.SetTextBackground(m_owner
->m_colourBackground
);
418 dc
.DrawRectangle( x
+50, y
+50, 200, 200 );
420 dc
.DrawCircle( x
+400, y
+50, 130 );
422 dc
.SetBrush(wxNullBrush
);
423 dc
.SetPen(wxNullPen
);
426 case 1: //now with transparent fillpatterns
429 wxBitmap
* bmpBlit
= new wxBitmap(600,400);
430 wxMemoryDC
* memDC
= new wxMemoryDC();
431 // wxBrush _clearbrush(*wxGREEN,wxSOLID);
432 wxBrush
_clearbrush(*wxBLACK
,wxSOLID
);
433 memDC
->SelectObject(*bmpBlit
);
434 memDC
->BeginDrawing();
435 memDC
->SetBackground(_clearbrush
);
437 memDC
->SetBackground(wxNullBrush
);
439 memDC
->SetPen( wxPen( "black", 4, wxSOLID
) );
440 memDC
->SetBrush( wxNullBrush
);
441 memDC
->SetBrush( *brush4
);
442 memDC
->SetTextForeground(*wxBLACK
); // 0s --> 0x000000 (black)
443 memDC
->SetTextBackground(*wxWHITE
); // 1s --> 0xFFFFFF (white)
444 memDC
->SetLogicalFunction(wxAND_INVERT
);
446 // BLACK OUT the opaque pixels and leave the rest as is
447 memDC
->DrawPolygon(5,todraw2
,0,0,wxWINDING_RULE
);
449 // Set background and foreground colors for fill pattern
450 //the previous blacked out pixels are now merged with the layer color
451 //while the non blacked out pixels stay as they are.
452 memDC
->SetTextForeground(*wxBLACK
); // 0s --> 0x000000 (black)
454 //now define what will be the color of the fillpattern parts that are not transparent
455 // memDC->SetTextBackground(*wxBLUE);
456 memDC
->SetTextBackground(m_owner
->m_colourForeground
);
457 memDC
->SetLogicalFunction(wxOR
);
460 //don't understand how but the outline is also depending on logicalfunction
461 memDC
->SetPen( wxPen( "red", 4, wxSOLID
) );
462 memDC
->DrawPolygon(5,todraw2
,0,0,wxWINDING_RULE
);
464 memDC
->SetLogicalFunction(wxCOPY
);
466 memDC
->SetPen( wxPen( "black", 4, wxSOLID
) );
467 memDC
->SetBrush( wxNullBrush
);
468 memDC
->SetBrush( *brush36
);
469 memDC
->SetTextForeground(*wxBLACK
); // 0s --> 0x000000 (black)
470 memDC
->SetTextBackground(*wxWHITE
); // 1s --> 0xFFFFFF (white)
471 memDC
->SetLogicalFunction(wxAND_INVERT
);
473 memDC
->DrawRectangle( 10, 10, 200, 200 );
475 // Set background and foreground colors for fill pattern
476 //the previous blacked out pixels are now merged with the layer color
477 //while the non blacked out pixels stay as they are.
478 memDC
->SetTextForeground(*wxBLACK
); // 0s --> 0x000000 (black)
479 //now define what will be the color of the fillpattern parts that are not transparent
480 // memDC->SetTextBackground(*wxRED);
481 memDC
->SetTextBackground(m_owner
->m_colourBackground
);
482 memDC
->SetLogicalFunction(wxOR
);
484 //don't understand how but the outline is also depending on logicalfunction
485 memDC
->SetPen( wxPen( "yellow", 4, wxSOLID
) );
486 memDC
->DrawRectangle( 10, 10, 200, 200 );
488 memDC
->SetBrush(wxNullBrush
);
489 memDC
->SetPen(wxNullPen
);
492 dc
.Blit(x
,y
,600,400,memDC
,0,0,wxCOPY
);
497 case 2: //now with transparent inversed fillpatterns
499 wxBitmap
* bmpBlit
= new wxBitmap(600,400);
500 wxMemoryDC
* memDC
= new wxMemoryDC();
501 wxBrush
_clearbrush(*wxWHITE
,wxSOLID
);
502 memDC
->SelectObject(*bmpBlit
);
503 memDC
->BeginDrawing();
504 memDC
->SetBackground(_clearbrush
);
506 memDC
->SetBackground(wxNullBrush
);
508 memDC
->SetPen( wxPen( "black", 4, wxSOLID
) );
509 memDC
->SetBrush( *brush4
);
510 memDC
->SetTextBackground(*wxBLACK
); // 0s --> 0x000000 (black)
511 memDC
->SetTextForeground(*wxWHITE
); // 1s --> 0xFFFFFF (white)
512 memDC
->SetLogicalFunction(wxAND_INVERT
);
514 // BLACK OUT the opaque pixels and leave the rest as is
515 memDC
->DrawPolygon(5,todraw2
,0,0,wxWINDING_RULE
);
517 // Set background and foreground colors for fill pattern
518 //the previous blacked out pixels are now merged with the layer color
519 //while the non blacked out pixels stay as they are.
520 memDC
->SetTextBackground(*wxBLACK
); // 0s --> 0x000000 (black)
522 //now define what will be the color of the fillpattern parts that are not transparent
523 memDC
->SetTextForeground(m_owner
->m_colourForeground
);
524 memDC
->SetLogicalFunction(wxOR
);
527 //don't understand how but the outline is also depending on logicalfunction
528 memDC
->SetPen( wxPen( "red", 4, wxSOLID
) );
529 memDC
->DrawPolygon(5,todraw2
,0,0,wxWINDING_RULE
);
531 memDC
->SetLogicalFunction(wxCOPY
);
533 memDC
->SetPen( wxPen( "black", 4, wxSOLID
) );
534 memDC
->SetBrush( *brush36
);
535 memDC
->SetTextBackground(*wxBLACK
); // 0s --> 0x000000 (black)
536 memDC
->SetTextForeground(*wxWHITE
); // 1s --> 0xFFFFFF (white)
537 memDC
->SetLogicalFunction(wxAND_INVERT
);
539 memDC
->DrawRectangle( 10,10, 200, 200 );
541 // Set background and foreground colors for fill pattern
542 //the previous blacked out pixels are now merged with the layer color
543 //while the non blacked out pixels stay as they are.
544 memDC
->SetTextBackground(*wxBLACK
); // 0s --> 0x000000 (black)
545 //now define what will be the color of the fillpattern parts that are not transparent
546 memDC
->SetTextForeground(m_owner
->m_colourBackground
);
547 memDC
->SetLogicalFunction(wxOR
);
549 //don't understand how but the outline is also depending on logicalfunction
550 memDC
->SetPen( wxPen( "yellow", 4, wxSOLID
) );
551 memDC
->DrawRectangle( 10, 10, 200, 200 );
553 memDC
->SetBrush(wxNullBrush
);
554 memDC
->SetPen(wxNullPen
);
555 dc
.Blit(x
,y
,600,400,memDC
,0,0,wxCOPY
);
566 void MyCanvas::DrawTestLines( int x
, int y
, int width
, wxDC
&dc
)
568 dc
.SetPen( wxPen( "black", width
, wxSOLID
) );
569 dc
.SetBrush( *wxRED_BRUSH
);
570 dc
.DrawText(wxString::Format("Testing lines of width %d", width
), x
+ 10, y
- 10);
571 dc
.DrawRectangle( x
+10, y
+10, 100, 190 );
573 dc
.DrawText("Solid/dot/short dash/long dash/dot dash", x
+ 150, y
+ 10);
574 dc
.SetPen( wxPen( "black", width
, wxSOLID
) );
575 dc
.DrawLine( x
+20, y
+20, 100, y
+20 );
576 dc
.SetPen( wxPen( "black", width
, wxDOT
) );
577 dc
.DrawLine( x
+20, y
+30, 100, y
+30 );
578 dc
.SetPen( wxPen( "black", width
, wxSHORT_DASH
) );
579 dc
.DrawLine( x
+20, y
+40, 100, y
+40 );
580 dc
.SetPen( wxPen( "black", width
, wxLONG_DASH
) );
581 dc
.DrawLine( x
+20, y
+50, 100, y
+50 );
582 dc
.SetPen( wxPen( "black", width
, wxDOT_DASH
) );
583 dc
.DrawLine( x
+20, y
+60, 100, y
+60 );
585 dc
.DrawText("Misc hatches", x
+ 150, y
+ 70);
586 dc
.SetPen( wxPen( "black", width
, wxBDIAGONAL_HATCH
) );
587 dc
.DrawLine( x
+20, y
+70, 100, y
+70 );
588 dc
.SetPen( wxPen( "black", width
, wxCROSSDIAG_HATCH
) );
589 dc
.DrawLine( x
+20, y
+80, 100, y
+80 );
590 dc
.SetPen( wxPen( "black", width
, wxFDIAGONAL_HATCH
) );
591 dc
.DrawLine( x
+20, y
+90, 100, y
+90 );
592 dc
.SetPen( wxPen( "black", width
, wxCROSS_HATCH
) );
593 dc
.DrawLine( x
+20, y
+100, 100, y
+100 );
594 dc
.SetPen( wxPen( "black", width
, wxHORIZONTAL_HATCH
) );
595 dc
.DrawLine( x
+20, y
+110, 100, y
+110 );
596 dc
.SetPen( wxPen( "black", width
, wxVERTICAL_HATCH
) );
597 dc
.DrawLine( x
+20, y
+120, 100, y
+120 );
599 dc
.DrawText("User dash", x
+ 150, y
+ 140);
600 wxPen
ud( "black", width
, wxUSER_DASH
);
603 ud
.SetDashes( 1, dash1
);
604 dc
.DrawLine( x
+20, y
+140, 100, y
+140 );
606 ud
.SetDashes( 1, dash1
);
607 dc
.DrawLine( x
+20, y
+150, 100, y
+150 );
609 ud
.SetDashes( 1, dash1
);
610 dc
.DrawLine( x
+20, y
+160, 100, y
+160 );
612 ud
.SetDashes( 1, dash1
);
613 dc
.DrawLine( x
+20, y
+170, 100, y
+170 );
616 void MyCanvas::DrawDefault(wxDC
& dc
)
619 dc
.DrawCircle(0, 0, 10);
620 #if !(defined __WXGTK__) && !(defined __WXMOTIF__)
621 // not implemented in wxGTK or wxMOTIF :-(
622 dc
.FloodFill(0, 0, wxColour(255, 0, 0));
625 dc
.DrawCheckMark(5, 80, 15, 15);
626 dc
.DrawCheckMark(25, 80, 30, 30);
627 dc
.DrawCheckMark(60, 80, 60, 60);
629 // this is the test for "blitting bitmap into DC damages selected brush" bug
630 wxCoord rectSize
= m_std_icon
.GetWidth() + 10;
632 dc
.SetPen(*wxTRANSPARENT_PEN
);
633 dc
.SetBrush( *wxGREEN_BRUSH
);
634 dc
.DrawRectangle(x
, 10, rectSize
, rectSize
);
635 dc
.DrawBitmap(m_std_icon
, x
+ 5, 15, TRUE
);
637 dc
.DrawRectangle(x
, 10, rectSize
, rectSize
);
638 dc
.DrawIcon(m_std_icon
, x
+ 5, 15);
640 dc
.DrawRectangle(x
, 10, rectSize
, rectSize
);
642 // test for "transparent" bitmap drawing (it intersects with the last
644 //dc.SetBrush( *wxTRANSPARENT_BRUSH );
646 if (m_smile_bmp
.Ok())
647 dc
.DrawBitmap(m_smile_bmp
, x
+ rectSize
- 20, rectSize
- 10, TRUE
);
649 dc
.SetBrush( *wxBLACK_BRUSH
);
650 dc
.DrawRectangle( 0, 160, 1000, 300 );
653 wxBitmap
bitmap(20,70);
655 memdc
.SelectObject( bitmap
);
656 memdc
.SetBrush( *wxBLACK_BRUSH
);
657 memdc
.SetPen( *wxWHITE_PEN
);
658 memdc
.DrawRectangle(0,0,20,70);
659 memdc
.DrawLine( 10,0,10,70 );
662 wxPen pen
= *wxRED_PEN
;
664 memdc
.DrawLine( 10, 5,10, 5 );
665 memdc
.DrawLine( 10,10,11,10 );
666 memdc
.DrawLine( 10,15,12,15 );
667 memdc
.DrawLine( 10,20,13,20 );
670 memdc.SetPen(*wxRED_PEN);
671 memdc.DrawLine( 12, 5,12, 5 );
672 memdc.DrawLine( 12,10,13,10 );
673 memdc.DrawLine( 12,15,14,15 );
674 memdc.DrawLine( 12,20,15,20 );
678 memdc
.DrawLine( 10,25,10,25 );
679 memdc
.DrawLine( 10,30, 9,30 );
680 memdc
.DrawLine( 10,35, 8,35 );
681 memdc
.DrawLine( 10,40, 7,40 );
684 dc
.SetPen(*wxWHITE_PEN
);
685 memdc
.SetLogicalFunction( wxINVERT
);
686 memdc
.SetPen( *wxWHITE_PEN
);
687 memdc
.DrawLine( 10,50,10,50 );
688 memdc
.DrawLine( 10,55,11,55 );
689 memdc
.DrawLine( 10,60,12,60 );
690 memdc
.DrawLine( 10,65,13,65 );
692 memdc
.DrawLine( 12,50,12,50 );
693 memdc
.DrawLine( 12,55,13,55 );
694 memdc
.DrawLine( 12,60,14,60 );
695 memdc
.DrawLine( 12,65,15,65 );
697 memdc
.SelectObject( wxNullBitmap
);
698 dc
.DrawBitmap( bitmap
, 10, 170 );
699 wxImage
image( bitmap
);
700 image
.Rescale( 60,210 );
701 bitmap
= image
.ConvertToBitmap();
702 dc
.DrawBitmap( bitmap
, 50, 170 );
704 // test the rectangle outline drawing - there should be one pixel between
705 // the rect and the lines
706 dc
.SetPen(*wxWHITE_PEN
);
707 dc
.SetBrush( *wxTRANSPARENT_BRUSH
);
708 dc
.DrawRectangle(150, 170, 49, 29);
709 dc
.DrawRectangle(200, 170, 49, 29);
710 dc
.SetPen(*wxWHITE_PEN
);
711 dc
.DrawLine(250, 210, 250, 170);
712 dc
.DrawLine(260, 200, 150, 200);
714 // test the rectangle filled drawing - there should be one pixel between
715 // the rect and the lines
716 dc
.SetPen(*wxTRANSPARENT_PEN
);
717 dc
.SetBrush( *wxWHITE_BRUSH
);
718 dc
.DrawRectangle(300, 170, 49, 29);
719 dc
.DrawRectangle(350, 170, 49, 29);
720 dc
.SetPen(*wxWHITE_PEN
);
721 dc
.DrawLine(400, 170, 400, 210);
722 dc
.DrawLine(300, 200, 410, 200);
724 // a few more tests of this kind
725 dc
.SetPen(*wxRED_PEN
);
726 dc
.SetBrush( *wxWHITE_BRUSH
);
727 dc
.DrawRectangle(300, 220, 1, 1);
728 dc
.DrawRectangle(310, 220, 2, 2);
729 dc
.DrawRectangle(320, 220, 3, 3);
730 dc
.DrawRectangle(330, 220, 4, 4);
732 dc
.SetPen(*wxTRANSPARENT_PEN
);
733 dc
.SetBrush( *wxWHITE_BRUSH
);
734 dc
.DrawRectangle(300, 230, 1, 1);
735 dc
.DrawRectangle(310, 230, 2, 2);
736 dc
.DrawRectangle(320, 230, 3, 3);
737 dc
.DrawRectangle(330, 230, 4, 4);
739 // and now for filled rect with outline
740 dc
.SetPen(*wxRED_PEN
);
741 dc
.SetBrush( *wxWHITE_BRUSH
);
742 dc
.DrawRectangle(500, 170, 49, 29);
743 dc
.DrawRectangle(550, 170, 49, 29);
744 dc
.SetPen(*wxWHITE_PEN
);
745 dc
.DrawLine(600, 170, 600, 210);
746 dc
.DrawLine(500, 200, 610, 200);
748 // test the rectangle outline drawing - there should be one pixel between
749 // the rect and the lines
750 dc
.SetPen(*wxWHITE_PEN
);
751 dc
.SetBrush( *wxTRANSPARENT_BRUSH
);
752 dc
.DrawRoundedRectangle(150, 270, 49, 29, 6);
753 dc
.DrawRoundedRectangle(200, 270, 49, 29, 6);
754 dc
.SetPen(*wxWHITE_PEN
);
755 dc
.DrawLine(250, 270, 250, 310);
756 dc
.DrawLine(150, 300, 260, 300);
758 // test the rectangle filled drawing - there should be one pixel between
759 // the rect and the lines
760 dc
.SetPen(*wxTRANSPARENT_PEN
);
761 dc
.SetBrush( *wxWHITE_BRUSH
);
762 dc
.DrawRoundedRectangle(300, 270, 49, 29, 6);
763 dc
.DrawRoundedRectangle(350, 270, 49, 29, 6);
764 dc
.SetPen(*wxWHITE_PEN
);
765 dc
.DrawLine(400, 270, 400, 310);
766 dc
.DrawLine(300, 300, 410, 300);
768 // Added by JACS to demonstrate bizarre behaviour.
769 // With a size of 70, we get a missing red RHS,
770 // and the hight is too small, so we get yellow
771 // showing. With a size of 40, it draws as expected:
772 // it just shows a white rectangle with red outline.
774 int totalHeight
= 70;
775 wxBitmap
bitmap2(totalWidth
, totalHeight
);
778 memdc2
.SelectObject(bitmap2
);
780 wxBrush
yellowBrush(wxColour(255, 255, 0), wxSOLID
);
781 memdc2
.SetBackground(yellowBrush
);
784 wxPen
yellowPen(wxColour(255, 255, 0), 1, wxSOLID
);
786 // Now draw a white rectangle with red outline. It should
787 // entirely eclipse the yellow background.
788 memdc2
.SetPen(*wxRED_PEN
);
789 memdc2
.SetBrush(*wxWHITE_BRUSH
);
791 memdc2
.DrawRectangle(0, 0, totalWidth
, totalHeight
);
793 memdc2
.SetPen(wxNullPen
);
794 memdc2
.SetBrush(wxNullBrush
);
795 memdc2
.SelectObject(wxNullBitmap
);
797 dc
.DrawBitmap(bitmap2
, 500, 270);
799 // Repeat, but draw directly on dc
800 // Draw a yellow rectangle filling the bitmap
802 x
= 600; int y
= 270;
803 dc
.SetPen(yellowPen
);
804 dc
.SetBrush(yellowBrush
);
805 dc
.DrawRectangle(x
, y
, totalWidth
, totalHeight
);
807 // Now draw a white rectangle with red outline. It should
808 // entirely eclipse the yellow background.
809 dc
.SetPen(*wxRED_PEN
);
810 dc
.SetBrush(*wxWHITE_BRUSH
);
812 dc
.DrawRectangle(x
, y
, totalWidth
, totalHeight
);
815 void MyCanvas::DrawText(wxDC
& dc
)
817 // set underlined font for testing
818 dc
.SetFont( wxFont(12, wxMODERN
, wxNORMAL
, wxNORMAL
, TRUE
) );
819 dc
.DrawText( "This is text", 110, 10 );
820 dc
.DrawRotatedText( "That is text", 20, 10, -45 );
822 dc
.SetFont( *wxNORMAL_FONT
);
825 dc
.SetBackgroundMode(wxTRANSPARENT
);
827 for ( int n
= -180; n
< 180; n
+= 30 )
829 text
.Printf(" %d rotated text", n
);
830 dc
.DrawRotatedText(text
, 400, 400, n
);
833 dc
.SetFont( wxFont( 18, wxSWISS
, wxNORMAL
, wxNORMAL
) );
835 dc
.DrawText( "This is Swiss 18pt text.", 110, 40 );
840 dc
.GetTextExtent( "This is Swiss 18pt text.", &length
, &height
, &descent
);
841 text
.Printf( "Dimensions are length %ld, height %ld, descent %ld", length
, height
, descent
);
842 dc
.DrawText( text
, 110, 80 );
844 text
.Printf( "CharHeight() returns: %d", dc
.GetCharHeight() );
845 dc
.DrawText( text
, 110, 120 );
847 dc
.DrawRectangle( 100, 40, 4, height
);
849 // test the logical function effect
851 dc
.SetLogicalFunction(wxINVERT
);
852 dc
.DrawText( "There should be no text below", 110, 150 );
853 dc
.DrawRectangle( 110, y
, 100, height
);
855 // twice drawn inverted should result in invisible
857 dc
.DrawText( "Invisible text", 110, y
);
858 dc
.DrawRectangle( 110, y
, 100, height
);
859 dc
.DrawText( "Invisible text", 110, y
);
860 dc
.DrawRectangle( 110, y
, 100, height
);
861 dc
.SetLogicalFunction(wxCOPY
);
864 dc
.DrawRectangle( 110, y
, 100, height
);
865 dc
.DrawText( "Visible text", 110, y
);
872 } rasterOperations
[] =
875 { "wxAND_INVERT", wxAND_INVERT
},
876 { "wxAND_REVERSE", wxAND_REVERSE
},
877 { "wxCLEAR", wxCLEAR
},
878 { "wxCOPY", wxCOPY
},
879 { "wxEQUIV", wxEQUIV
},
880 { "wxINVERT", wxINVERT
},
881 { "wxNAND", wxNAND
},
882 { "wxNO_OP", wxNO_OP
},
884 { "wxOR_INVERT", wxOR_INVERT
},
885 { "wxOR_REVERSE", wxOR_REVERSE
},
887 { "wxSRC_INVERT", wxSRC_INVERT
},
891 void MyCanvas::DrawImages(wxDC
& dc
)
893 dc
.DrawText("original image", 0, 0);
894 dc
.DrawBitmap(*gs_bmpNoMask
, 0, 20, 0);
895 dc
.DrawText("with colour mask", 0, 100);
896 dc
.DrawBitmap(*gs_bmpWithColMask
, 0, 120, TRUE
);
897 dc
.DrawText("the mask image", 0, 200);
898 dc
.DrawBitmap(*gs_bmpMask
, 0, 220, 0);
899 dc
.DrawText("masked image", 0, 300);
900 dc
.DrawBitmap(*gs_bmpWithMask
, 0, 320, TRUE
);
902 int cx
= gs_bmpWithColMask
->GetWidth(),
903 cy
= gs_bmpWithColMask
->GetHeight();
906 for ( size_t n
= 0; n
< WXSIZEOF(rasterOperations
); n
++ )
908 wxCoord x
= 120 + 150*(n%4
),
911 dc
.DrawText(rasterOperations
[n
].name
, x
, y
- 20);
912 memDC
.SelectObject(*gs_bmpWithColMask
);
913 dc
.Blit(x
, y
, cx
, cy
, &memDC
, 0, 0, rasterOperations
[n
].rop
, TRUE
);
917 void MyCanvas::DrawWithLogicalOps(wxDC
& dc
)
919 static const wxCoord w
= 60;
920 static const wxCoord h
= 60;
922 // reuse the text colour here
923 dc
.SetPen(wxPen(m_owner
->m_colourForeground
, 1, wxSOLID
));
924 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
927 for ( n
= 0; n
< WXSIZEOF(rasterOperations
); n
++ )
929 wxCoord x
= 20 + 150*(n%4
),
932 dc
.DrawText(rasterOperations
[n
].name
, x
, y
- 20);
933 dc
.SetLogicalFunction(rasterOperations
[n
].rop
);
934 dc
.DrawRectangle(x
, y
, w
, h
);
935 dc
.DrawLine(x
, y
, x
+ w
, y
+ h
);
936 dc
.DrawLine(x
+ w
, y
, x
, y
+ h
);
939 // now some filled rectangles
940 dc
.SetBrush(wxBrush(m_owner
->m_colourForeground
, wxSOLID
));
942 for ( n
= 0; n
< WXSIZEOF(rasterOperations
); n
++ )
944 wxCoord x
= 20 + 150*(n%4
),
947 dc
.DrawText(rasterOperations
[n
].name
, x
, y
- 20);
948 dc
.SetLogicalFunction(rasterOperations
[n
].rop
);
949 dc
.DrawRectangle(x
, y
, w
, h
);
953 void MyCanvas::DrawCircles(wxDC
& dc
)
959 dc
.DrawText("Some circles", 0, y
);
960 dc
.DrawCircle(x
, y
, r
);
961 dc
.DrawCircle(x
+ 2*r
, y
, r
);
962 dc
.DrawCircle(x
+ 4*r
, y
, r
);
965 dc
.DrawText("And ellipses", 0, y
);
966 dc
.DrawEllipse(x
- r
, y
, 2*r
, r
);
967 dc
.DrawEllipse(x
+ r
, y
, 2*r
, r
);
968 dc
.DrawEllipse(x
+ 3*r
, y
, 2*r
, r
);
971 dc
.DrawText("And arcs", 0, y
);
972 dc
.DrawArc(x
- r
, y
, x
+ r
, y
, x
, y
);
973 dc
.DrawArc(x
+ 4*r
, y
, x
+ 2*r
, y
, x
+ 3*r
, y
);
974 dc
.DrawArc(x
+ 5*r
, y
, x
+ 5*r
, y
, x
+ 6*r
, y
);
977 dc
.DrawEllipticArc(x
- r
, y
, 2*r
, r
, 0, 90);
978 dc
.DrawEllipticArc(x
+ r
, y
, 2*r
, r
, 90, 180);
979 dc
.DrawEllipticArc(x
+ 3*r
, y
, 2*r
, r
, 180, 270);
980 dc
.DrawEllipticArc(x
+ 5*r
, y
, 2*r
, r
, 270, 360);
983 void MyCanvas::DrawRegions(wxDC
& dc
)
985 dc
.SetBrush( *wxWHITE_BRUSH
);
986 dc
.SetPen( *wxTRANSPARENT_PEN
);
987 dc
.DrawRectangle( 10,10,310,310 );
989 dc
.SetClippingRegion( 20,20,100,270 );
991 dc
.SetBrush( *wxRED_BRUSH
);
992 dc
.DrawRectangle( 10,10,310,310 );
994 dc
.SetClippingRegion( 20,20,100,100 );
996 dc
.SetBrush( *wxCYAN_BRUSH
);
997 dc
.DrawRectangle( 10,10,310,310 );
999 dc
.DestroyClippingRegion();
1000 dc
.SetClippingRegion( 120,30,100,270 );
1002 dc
.SetBrush( *wxGREY_BRUSH
);
1003 dc
.DrawRectangle( 10,10,310,310 );
1005 if (m_smile_bmp
.Ok())
1007 dc
.DrawBitmap( m_smile_bmp
, 140, 20, TRUE
);
1008 dc
.DrawBitmap( m_smile_bmp
, 140, 290, TRUE
);
1009 dc
.DrawBitmap( m_smile_bmp
, 110, 80, TRUE
);
1010 dc
.DrawBitmap( m_smile_bmp
, 210, 80, TRUE
);
1014 void MyCanvas::OnPaint(wxPaintEvent
&WXUNUSED(event
))
1018 m_owner
->PrepareDC(dc
);
1020 dc
.SetBackgroundMode( m_owner
->m_backgroundMode
);
1021 if ( m_owner
->m_backgroundBrush
.Ok() )
1022 dc
.SetBackground( m_owner
->m_backgroundBrush
);
1023 if ( m_owner
->m_colourForeground
.Ok() )
1024 dc
.SetTextForeground( m_owner
->m_colourForeground
);
1025 if ( m_owner
->m_colourBackground
.Ok() )
1026 dc
.SetTextBackground( m_owner
->m_colourBackground
);
1028 if ( m_owner
->m_textureBackground
) {
1029 if ( ! m_owner
->m_backgroundBrush
.Ok() ) {
1030 wxBrush
b(wxColour(0,128,0), wxSOLID
);
1031 dc
.SetBackground(b
);
1037 if ( m_owner
->m_textureBackground
) {
1038 dc
.SetPen(*wxMEDIUM_GREY_PEN
);
1039 for (int i
=0; i
<200; i
++)
1040 dc
.DrawLine(0, i
*10, i
*10, 0);
1062 DrawTestLines( 0, 100, 0, dc
);
1063 DrawTestLines( 0, 320, 1, dc
);
1064 DrawTestLines( 0, 540, 2, dc
);
1065 DrawTestLines( 0, 760, 6, dc
);
1069 DrawTestPoly( 0, 100, dc
, 0 );
1071 DrawTestPoly( 33, 500, dc, 1 );
1072 DrawTestPoly( 43, 1000, dc, 2 );
1081 DrawWithLogicalOps(dc
);
1086 void MyCanvas::OnMouseMove(wxMouseEvent
&event
)
1088 wxClientDC
dc(this);
1090 m_owner
->PrepareDC(dc
);
1092 wxPoint pos
= event
.GetPosition();
1093 long x
= dc
.DeviceToLogicalX( pos
.x
);
1094 long y
= dc
.DeviceToLogicalY( pos
.y
);
1096 str
.Printf( "Current mouse position: %d,%d", (int)x
, (int)y
);
1097 m_owner
->SetStatusText( str
);
1100 // ----------------------------------------------------------------------------
1102 // ----------------------------------------------------------------------------
1104 // the event tables connect the wxWindows events with the functions (event
1105 // handlers) which process them. It can be also done at run-time, but for the
1106 // simple menu events like this the static method is much simpler.
1107 BEGIN_EVENT_TABLE(MyFrame
, wxFrame
)
1108 EVT_MENU (File_Quit
, MyFrame::OnQuit
)
1109 EVT_MENU (File_About
, MyFrame::OnAbout
)
1111 EVT_MENU_RANGE(MenuShow_First
, MenuShow_Last
, MyFrame::OnShow
)
1113 EVT_MENU_RANGE(MenuOption_First
, MenuOption_Last
, MyFrame::OnOption
)
1116 // frame constructor
1117 MyFrame::MyFrame(const wxString
& title
, const wxPoint
& pos
, const wxSize
& size
)
1118 : wxFrame((wxFrame
*)NULL
, -1, title
, pos
, size
)
1120 // set the frame icon
1121 SetIcon(wxICON(mondrian
));
1123 wxMenu
*menuFile
= new wxMenu
;
1124 menuFile
->Append(File_ShowDefault
, "&Default screen\tF1");
1125 menuFile
->Append(File_ShowText
, "&Text screen\tF2");
1126 menuFile
->Append(File_ShowLines
, "&Lines screen\tF3");
1127 menuFile
->Append(File_ShowPolygons
, "&Polygons screen\tF4");
1128 menuFile
->Append(File_ShowMask
, "wx&Mask screen\tF5");
1129 menuFile
->Append(File_ShowOps
, "&ROP screen\tF6");
1130 menuFile
->Append(File_ShowRegions
, "Re&gions screen\tF7");
1131 menuFile
->Append(File_ShowCircles
, "&Circles screen\tF8");
1132 menuFile
->AppendSeparator();
1133 menuFile
->Append(File_About
, "&About...\tCtrl-A", "Show about dialog");
1134 menuFile
->AppendSeparator();
1135 menuFile
->Append(File_Quit
, "E&xit\tAlt-X", "Quit this program");
1137 wxMenu
*menuMapMode
= new wxMenu
;
1138 menuMapMode
->Append( MapMode_Text
, "&TEXT map mode" );
1139 menuMapMode
->Append( MapMode_Lometric
, "&LOMETRIC map mode" );
1140 menuMapMode
->Append( MapMode_Twips
, "T&WIPS map mode" );
1141 menuMapMode
->Append( MapMode_Points
, "&POINTS map mode" );
1142 menuMapMode
->Append( MapMode_Metric
, "&METRIC map mode" );
1144 wxMenu
*menuUserScale
= new wxMenu
;
1145 menuUserScale
->Append( UserScale_StretchHoriz
, "Stretch horizontally\tCtrl-H" );
1146 menuUserScale
->Append( UserScale_ShrinkHoriz
, "Shrink horizontally\tCtrl-G" );
1147 menuUserScale
->Append( UserScale_StretchVertic
, "Stretch vertically\tCtrl-V" );
1148 menuUserScale
->Append( UserScale_ShrinkVertic
, "Shrink vertically\tCtrl-W" );
1149 menuUserScale
->AppendSeparator();
1150 menuUserScale
->Append( UserScale_Restore
, "Restore to normal\tCtrl-0" );
1152 wxMenu
*menuAxis
= new wxMenu
;
1153 menuAxis
->Append( AxisMirror_Horiz
, "Mirror horizontally\tCtrl-M", "", TRUE
);
1154 menuAxis
->Append( AxisMirror_Vertic
, "Mirror vertically\tCtrl-N", "", TRUE
);
1156 wxMenu
*menuLogical
= new wxMenu
;
1157 menuLogical
->Append( LogicalOrigin_MoveDown
, "Move &down\tCtrl-D" );
1158 menuLogical
->Append( LogicalOrigin_MoveUp
, "Move &up\tCtrl-U" );
1159 menuLogical
->Append( LogicalOrigin_MoveLeft
, "Move &right\tCtrl-L" );
1160 menuLogical
->Append( LogicalOrigin_MoveRight
, "Move &left\tCtrl-R" );
1162 wxMenu
*menuColour
= new wxMenu
;
1163 menuColour
->Append( Colour_TextForeground
, "Text foreground..." );
1164 menuColour
->Append( Colour_TextBackground
, "Text background..." );
1165 menuColour
->Append( Colour_Background
, "Background colour..." );
1166 menuColour
->Append( Colour_BackgroundMode
, "Opaque/transparent\tCtrl-B", "", TRUE
);
1167 menuColour
->Append( Colour_TextureBackgound
, "Draw textured background\tCtrl-T", "", TRUE
);
1169 // now append the freshly created menu to the menu bar...
1170 wxMenuBar
*menuBar
= new wxMenuBar
;
1171 menuBar
->Append(menuFile
, "&File");
1172 menuBar
->Append(menuMapMode
, "&MapMode");
1173 menuBar
->Append(menuUserScale
, "&UserScale");
1174 menuBar
->Append(menuAxis
, "&Axis");
1175 menuBar
->Append(menuLogical
, "&LogicalOrigin");
1176 menuBar
->Append(menuColour
, "&Colours");
1178 // ... and attach this menu bar to the frame
1179 SetMenuBar(menuBar
);
1181 // create a status bar just for fun (by default with 1 pane only)
1183 SetStatusText("Welcome to wxWindows!");
1185 m_mapMode
= wxMM_TEXT
;
1188 m_xLogicalOrigin
= 0;
1189 m_yLogicalOrigin
= 0;
1191 m_yAxisReversed
= FALSE
;
1192 m_backgroundMode
= wxSOLID
;
1193 m_colourForeground
= *wxRED
;
1194 m_colourBackground
= *wxBLUE
;
1195 m_textureBackground
= FALSE
;
1197 m_canvas
= new MyCanvas( this );
1198 m_canvas
->SetScrollbars( 10, 10, 100, 240 );
1203 void MyFrame::OnQuit(wxCommandEvent
& WXUNUSED(event
))
1205 // TRUE is to force the frame to close
1209 void MyFrame::OnAbout(wxCommandEvent
& WXUNUSED(event
))
1212 msg
.Printf( wxT("This is the about dialog of the drawing sample.\n")
1213 wxT("This sample tests various primitive drawing functions\n")
1214 wxT("without any tests to prevent flicker.\n")
1215 wxT("Copyright (c) Robert Roebling 1999")
1218 wxMessageBox(msg
, "About Drawing", wxOK
| wxICON_INFORMATION
, this);
1221 void MyFrame::OnShow(wxCommandEvent
& event
)
1223 m_canvas
->Show((ScreenToShow
)(event
.GetInt() - MenuShow_First
));
1226 void MyFrame::OnOption(wxCommandEvent
& event
)
1228 switch (event
.GetInt())
1231 m_mapMode
= wxMM_TEXT
;
1233 case MapMode_Lometric
:
1234 m_mapMode
= wxMM_LOMETRIC
;
1237 m_mapMode
= wxMM_TWIPS
;
1239 case MapMode_Points
:
1240 m_mapMode
= wxMM_POINTS
;
1242 case MapMode_Metric
:
1243 m_mapMode
= wxMM_METRIC
;
1246 case LogicalOrigin_MoveDown
:
1247 m_yLogicalOrigin
+= 10;
1249 case LogicalOrigin_MoveUp
:
1250 m_yLogicalOrigin
-= 10;
1252 case LogicalOrigin_MoveLeft
:
1253 m_xLogicalOrigin
+= 10;
1255 case LogicalOrigin_MoveRight
:
1256 m_xLogicalOrigin
-= 10;
1259 case UserScale_StretchHoriz
:
1260 m_xUserScale
*= 1.10;
1262 case UserScale_ShrinkHoriz
:
1263 m_xUserScale
/= 1.10;
1265 case UserScale_StretchVertic
:
1266 m_yUserScale
*= 1.10;
1268 case UserScale_ShrinkVertic
:
1269 m_yUserScale
/= 1.10;
1271 case UserScale_Restore
:
1276 case AxisMirror_Vertic
:
1277 m_yAxisReversed
= !m_yAxisReversed
;
1279 case AxisMirror_Horiz
:
1280 m_xAxisReversed
= !m_xAxisReversed
;
1283 case Colour_TextForeground
:
1284 m_colourForeground
= SelectColour();
1286 case Colour_TextBackground
:
1287 m_colourBackground
= SelectColour();
1289 case Colour_Background
:
1291 wxColour col
= SelectColour();
1294 m_backgroundBrush
.SetColour(col
);
1298 case Colour_BackgroundMode
:
1299 m_backgroundMode
= m_backgroundMode
== wxSOLID
? wxTRANSPARENT
1303 case Colour_TextureBackgound
:
1304 m_textureBackground
= ! m_textureBackground
;
1312 m_canvas
->Refresh();
1315 void MyFrame::PrepareDC(wxDC
& dc
)
1317 dc
.SetMapMode( m_mapMode
);
1318 dc
.SetUserScale( m_xUserScale
, m_yUserScale
);
1319 dc
.SetLogicalOrigin( m_xLogicalOrigin
, m_yLogicalOrigin
);
1320 dc
.SetAxisOrientation( !m_xAxisReversed
, m_yAxisReversed
);
1323 wxColour
MyFrame::SelectColour()
1327 wxColourDialog
dialog(this, &data
);
1329 if ( dialog
.ShowModal() == wxID_OK
)
1331 col
= dialog
.GetColourData().GetColour();