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
= new wxBrush(*wxBLACK
,wxFDIAGONAL_HATCH
);
372 wxBrush
* brush4_mono
= new wxBrush(*gs_bmp4_mono
);
373 wxBrush
* brush36
= new wxBrush(*gs_bmp36
);
376 todraw
[0].x
=(long)x
+100;
377 todraw
[0].y
=(long)y
+100;
378 todraw
[1].x
=(long)x
+300;
379 todraw
[1].y
=(long)y
+100;
380 todraw
[2].x
=(long)x
+300;
381 todraw
[2].y
=(long)y
+300;
382 todraw
[3].x
=(long)x
+150;
383 todraw
[3].y
=(long)y
+350;
384 todraw
[4].x
=(long)x
+100;
385 todraw
[4].y
=(long)y
+300;
403 dc
.SetLogicalFunction(wxCOPY
);
405 dc
.SetPen( wxPen( "black", 4, wxSOLID
) );
406 dc
.SetBrush( *brush4
);
407 dc
.DrawPolygon(5,todraw
,0,0,wxWINDING_RULE
);
409 dc
.SetPen( wxPen( "red", 4, wxSOLID
) );
410 dc
.SetBrush( *brush36
);
411 dc
.SetTextForeground(*wxCYAN
);
412 dc
.SetTextBackground(m_owner
->m_colourBackground
);
413 dc
.DrawRectangle( x
+10, y
+10, 200, 200 );
415 dc
.SetPen( wxPen( "green", 4, wxSOLID
) );
416 dc
.SetBrush( *brush4_mono
);
417 dc
.SetTextForeground(*wxCYAN
);
418 dc
.SetTextBackground(m_owner
->m_colourBackground
);
419 dc
.DrawRectangle( x
+50, y
+50, 200, 200 );
421 dc
.DrawCircle( x
+400, y
+50, 130 );
423 dc
.SetBrush(wxNullBrush
);
424 dc
.SetPen(wxNullPen
);
427 case 1: //now with transparent fillpatterns
430 wxBitmap
* bmpBlit
= new wxBitmap(600,400);
431 wxMemoryDC
* memDC
= new wxMemoryDC();
432 // wxBrush _clearbrush(*wxGREEN,wxSOLID);
433 wxBrush
_clearbrush(*wxBLACK
,wxSOLID
);
434 memDC
->SelectObject(*bmpBlit
);
435 memDC
->BeginDrawing();
436 memDC
->SetBackground(_clearbrush
);
438 memDC
->SetBackground(wxNullBrush
);
440 memDC
->SetPen( wxPen( "black", 4, wxSOLID
) );
441 memDC
->SetBrush( wxNullBrush
);
442 memDC
->SetBrush( *brush4
);
443 memDC
->SetTextForeground(*wxBLACK
); // 0s --> 0x000000 (black)
444 memDC
->SetTextBackground(*wxWHITE
); // 1s --> 0xFFFFFF (white)
445 memDC
->SetLogicalFunction(wxAND_INVERT
);
447 // BLACK OUT the opaque pixels and leave the rest as is
448 memDC
->DrawPolygon(5,todraw2
,0,0,wxWINDING_RULE
);
450 // Set background and foreground colors for fill pattern
451 //the previous blacked out pixels are now merged with the layer color
452 //while the non blacked out pixels stay as they are.
453 memDC
->SetTextForeground(*wxBLACK
); // 0s --> 0x000000 (black)
455 //now define what will be the color of the fillpattern parts that are not transparent
456 // memDC->SetTextBackground(*wxBLUE);
457 memDC
->SetTextBackground(m_owner
->m_colourForeground
);
458 memDC
->SetLogicalFunction(wxOR
);
461 //don't understand how but the outline is also depending on logicalfunction
462 memDC
->SetPen( wxPen( "red", 4, wxSOLID
) );
463 memDC
->DrawPolygon(5,todraw2
,0,0,wxWINDING_RULE
);
465 memDC
->SetLogicalFunction(wxCOPY
);
467 memDC
->SetPen( wxPen( "black", 4, wxSOLID
) );
468 memDC
->SetBrush( wxNullBrush
);
469 memDC
->SetBrush( *brush36
);
470 memDC
->SetTextForeground(*wxBLACK
); // 0s --> 0x000000 (black)
471 memDC
->SetTextBackground(*wxWHITE
); // 1s --> 0xFFFFFF (white)
472 memDC
->SetLogicalFunction(wxAND_INVERT
);
474 memDC
->DrawRectangle( 10, 10, 200, 200 );
476 // Set background and foreground colors for fill pattern
477 //the previous blacked out pixels are now merged with the layer color
478 //while the non blacked out pixels stay as they are.
479 memDC
->SetTextForeground(*wxBLACK
); // 0s --> 0x000000 (black)
480 //now define what will be the color of the fillpattern parts that are not transparent
481 // memDC->SetTextBackground(*wxRED);
482 memDC
->SetTextBackground(m_owner
->m_colourBackground
);
483 memDC
->SetLogicalFunction(wxOR
);
485 //don't understand how but the outline is also depending on logicalfunction
486 memDC
->SetPen( wxPen( "yellow", 4, wxSOLID
) );
487 memDC
->DrawRectangle( 10, 10, 200, 200 );
489 memDC
->SetBrush(wxNullBrush
);
490 memDC
->SetPen(wxNullPen
);
493 dc
.Blit(x
,y
,600,400,memDC
,0,0,wxCOPY
);
498 case 2: //now with transparent inversed fillpatterns
500 wxBitmap
* bmpBlit
= new wxBitmap(600,400);
501 wxMemoryDC
* memDC
= new wxMemoryDC();
502 wxBrush
_clearbrush(*wxWHITE
,wxSOLID
);
503 memDC
->SelectObject(*bmpBlit
);
504 memDC
->BeginDrawing();
505 memDC
->SetBackground(_clearbrush
);
507 memDC
->SetBackground(wxNullBrush
);
509 memDC
->SetPen( wxPen( "black", 4, wxSOLID
) );
510 memDC
->SetBrush( *brush4
);
511 memDC
->SetTextBackground(*wxBLACK
); // 0s --> 0x000000 (black)
512 memDC
->SetTextForeground(*wxWHITE
); // 1s --> 0xFFFFFF (white)
513 memDC
->SetLogicalFunction(wxAND_INVERT
);
515 // BLACK OUT the opaque pixels and leave the rest as is
516 memDC
->DrawPolygon(5,todraw2
,0,0,wxWINDING_RULE
);
518 // Set background and foreground colors for fill pattern
519 //the previous blacked out pixels are now merged with the layer color
520 //while the non blacked out pixels stay as they are.
521 memDC
->SetTextBackground(*wxBLACK
); // 0s --> 0x000000 (black)
523 //now define what will be the color of the fillpattern parts that are not transparent
524 memDC
->SetTextForeground(m_owner
->m_colourForeground
);
525 memDC
->SetLogicalFunction(wxOR
);
528 //don't understand how but the outline is also depending on logicalfunction
529 memDC
->SetPen( wxPen( "red", 4, wxSOLID
) );
530 memDC
->DrawPolygon(5,todraw2
,0,0,wxWINDING_RULE
);
532 memDC
->SetLogicalFunction(wxCOPY
);
534 memDC
->SetPen( wxPen( "black", 4, wxSOLID
) );
535 memDC
->SetBrush( *brush36
);
536 memDC
->SetTextBackground(*wxBLACK
); // 0s --> 0x000000 (black)
537 memDC
->SetTextForeground(*wxWHITE
); // 1s --> 0xFFFFFF (white)
538 memDC
->SetLogicalFunction(wxAND_INVERT
);
540 memDC
->DrawRectangle( 10,10, 200, 200 );
542 // Set background and foreground colors for fill pattern
543 //the previous blacked out pixels are now merged with the layer color
544 //while the non blacked out pixels stay as they are.
545 memDC
->SetTextBackground(*wxBLACK
); // 0s --> 0x000000 (black)
546 //now define what will be the color of the fillpattern parts that are not transparent
547 memDC
->SetTextForeground(m_owner
->m_colourBackground
);
548 memDC
->SetLogicalFunction(wxOR
);
550 //don't understand how but the outline is also depending on logicalfunction
551 memDC
->SetPen( wxPen( "yellow", 4, wxSOLID
) );
552 memDC
->DrawRectangle( 10, 10, 200, 200 );
554 memDC
->SetBrush(wxNullBrush
);
555 memDC
->SetPen(wxNullPen
);
556 dc
.Blit(x
,y
,600,400,memDC
,0,0,wxCOPY
);
567 void MyCanvas::DrawTestLines( int x
, int y
, int width
, wxDC
&dc
)
569 dc
.SetPen( wxPen( "black", width
, wxSOLID
) );
570 dc
.SetBrush( *wxRED_BRUSH
);
571 dc
.DrawText(wxString::Format("Testing lines of width %d", width
), x
+ 10, y
- 10);
572 dc
.DrawRectangle( x
+10, y
+10, 100, 190 );
574 dc
.DrawText("Solid/dot/short dash/long dash/dot dash", x
+ 150, y
+ 10);
575 dc
.SetPen( wxPen( "black", width
, wxSOLID
) );
576 dc
.DrawLine( x
+20, y
+20, 100, y
+20 );
577 dc
.SetPen( wxPen( "black", width
, wxDOT
) );
578 dc
.DrawLine( x
+20, y
+30, 100, y
+30 );
579 dc
.SetPen( wxPen( "black", width
, wxSHORT_DASH
) );
580 dc
.DrawLine( x
+20, y
+40, 100, y
+40 );
581 dc
.SetPen( wxPen( "black", width
, wxLONG_DASH
) );
582 dc
.DrawLine( x
+20, y
+50, 100, y
+50 );
583 dc
.SetPen( wxPen( "black", width
, wxDOT_DASH
) );
584 dc
.DrawLine( x
+20, y
+60, 100, y
+60 );
586 dc
.DrawText("Misc hatches", x
+ 150, y
+ 70);
587 dc
.SetPen( wxPen( "black", width
, wxBDIAGONAL_HATCH
) );
588 dc
.DrawLine( x
+20, y
+70, 100, y
+70 );
589 dc
.SetPen( wxPen( "black", width
, wxCROSSDIAG_HATCH
) );
590 dc
.DrawLine( x
+20, y
+80, 100, y
+80 );
591 dc
.SetPen( wxPen( "black", width
, wxFDIAGONAL_HATCH
) );
592 dc
.DrawLine( x
+20, y
+90, 100, y
+90 );
593 dc
.SetPen( wxPen( "black", width
, wxCROSS_HATCH
) );
594 dc
.DrawLine( x
+20, y
+100, 100, y
+100 );
595 dc
.SetPen( wxPen( "black", width
, wxHORIZONTAL_HATCH
) );
596 dc
.DrawLine( x
+20, y
+110, 100, y
+110 );
597 dc
.SetPen( wxPen( "black", width
, wxVERTICAL_HATCH
) );
598 dc
.DrawLine( x
+20, y
+120, 100, y
+120 );
600 dc
.DrawText("User dash", x
+ 150, y
+ 140);
601 wxPen
ud( "black", width
, wxUSER_DASH
);
604 ud
.SetDashes( 1, dash1
);
605 dc
.DrawLine( x
+20, y
+140, 100, y
+140 );
607 ud
.SetDashes( 1, dash1
);
608 dc
.DrawLine( x
+20, y
+150, 100, y
+150 );
610 ud
.SetDashes( 1, dash1
);
611 dc
.DrawLine( x
+20, y
+160, 100, y
+160 );
613 ud
.SetDashes( 1, dash1
);
614 dc
.DrawLine( x
+20, y
+170, 100, y
+170 );
617 void MyCanvas::DrawDefault(wxDC
& dc
)
620 dc
.DrawCircle(0, 0, 10);
621 #if !(defined __WXGTK__) && !(defined __WXMOTIF__)
622 // not implemented in wxGTK or wxMOTIF :-(
623 dc
.FloodFill(0, 0, wxColour(255, 0, 0));
626 dc
.DrawCheckMark(5, 80, 15, 15);
627 dc
.DrawCheckMark(25, 80, 30, 30);
628 dc
.DrawCheckMark(60, 80, 60, 60);
630 // this is the test for "blitting bitmap into DC damages selected brush" bug
631 wxCoord rectSize
= m_std_icon
.GetWidth() + 10;
633 dc
.SetPen(*wxTRANSPARENT_PEN
);
634 dc
.SetBrush( *wxGREEN_BRUSH
);
635 dc
.DrawRectangle(x
, 10, rectSize
, rectSize
);
636 dc
.DrawBitmap(m_std_icon
, x
+ 5, 15, TRUE
);
638 dc
.DrawRectangle(x
, 10, rectSize
, rectSize
);
639 dc
.DrawIcon(m_std_icon
, x
+ 5, 15);
641 dc
.DrawRectangle(x
, 10, rectSize
, rectSize
);
643 // test for "transparent" bitmap drawing (it intersects with the last
645 //dc.SetBrush( *wxTRANSPARENT_BRUSH );
647 if (m_smile_bmp
.Ok())
648 dc
.DrawBitmap(m_smile_bmp
, x
+ rectSize
- 20, rectSize
- 10, TRUE
);
650 dc
.SetBrush( *wxBLACK_BRUSH
);
651 dc
.DrawRectangle( 0, 160, 1000, 300 );
654 wxBitmap
bitmap(20,70);
656 memdc
.SelectObject( bitmap
);
657 memdc
.SetBrush( *wxBLACK_BRUSH
);
658 memdc
.SetPen( *wxWHITE_PEN
);
659 memdc
.DrawRectangle(0,0,20,70);
660 memdc
.DrawLine( 10,0,10,70 );
663 wxPen pen
= *wxRED_PEN
;
665 memdc
.DrawLine( 10, 5,10, 5 );
666 memdc
.DrawLine( 10,10,11,10 );
667 memdc
.DrawLine( 10,15,12,15 );
668 memdc
.DrawLine( 10,20,13,20 );
671 memdc.SetPen(*wxRED_PEN);
672 memdc.DrawLine( 12, 5,12, 5 );
673 memdc.DrawLine( 12,10,13,10 );
674 memdc.DrawLine( 12,15,14,15 );
675 memdc.DrawLine( 12,20,15,20 );
679 memdc
.DrawLine( 10,25,10,25 );
680 memdc
.DrawLine( 10,30, 9,30 );
681 memdc
.DrawLine( 10,35, 8,35 );
682 memdc
.DrawLine( 10,40, 7,40 );
685 dc
.SetPen(*wxWHITE_PEN
);
686 memdc
.SetLogicalFunction( wxINVERT
);
687 memdc
.SetPen( *wxWHITE_PEN
);
688 memdc
.DrawLine( 10,50,10,50 );
689 memdc
.DrawLine( 10,55,11,55 );
690 memdc
.DrawLine( 10,60,12,60 );
691 memdc
.DrawLine( 10,65,13,65 );
693 memdc
.DrawLine( 12,50,12,50 );
694 memdc
.DrawLine( 12,55,13,55 );
695 memdc
.DrawLine( 12,60,14,60 );
696 memdc
.DrawLine( 12,65,15,65 );
698 memdc
.SelectObject( wxNullBitmap
);
699 dc
.DrawBitmap( bitmap
, 10, 170 );
700 wxImage
image( bitmap
);
701 image
.Rescale( 60,210 );
702 bitmap
= image
.ConvertToBitmap();
703 dc
.DrawBitmap( bitmap
, 50, 170 );
705 // test the rectangle outline drawing - there should be one pixel between
706 // the rect and the lines
707 dc
.SetPen(*wxWHITE_PEN
);
708 dc
.SetBrush( *wxTRANSPARENT_BRUSH
);
709 dc
.DrawRectangle(150, 170, 49, 29);
710 dc
.DrawRectangle(200, 170, 49, 29);
711 dc
.SetPen(*wxWHITE_PEN
);
712 dc
.DrawLine(250, 210, 250, 170);
713 dc
.DrawLine(260, 200, 150, 200);
715 // test the rectangle filled drawing - there should be one pixel between
716 // the rect and the lines
717 dc
.SetPen(*wxTRANSPARENT_PEN
);
718 dc
.SetBrush( *wxWHITE_BRUSH
);
719 dc
.DrawRectangle(300, 170, 49, 29);
720 dc
.DrawRectangle(350, 170, 49, 29);
721 dc
.SetPen(*wxWHITE_PEN
);
722 dc
.DrawLine(400, 170, 400, 210);
723 dc
.DrawLine(300, 200, 410, 200);
725 // a few more tests of this kind
726 dc
.SetPen(*wxRED_PEN
);
727 dc
.SetBrush( *wxWHITE_BRUSH
);
728 dc
.DrawRectangle(300, 220, 1, 1);
729 dc
.DrawRectangle(310, 220, 2, 2);
730 dc
.DrawRectangle(320, 220, 3, 3);
731 dc
.DrawRectangle(330, 220, 4, 4);
733 dc
.SetPen(*wxTRANSPARENT_PEN
);
734 dc
.SetBrush( *wxWHITE_BRUSH
);
735 dc
.DrawRectangle(300, 230, 1, 1);
736 dc
.DrawRectangle(310, 230, 2, 2);
737 dc
.DrawRectangle(320, 230, 3, 3);
738 dc
.DrawRectangle(330, 230, 4, 4);
740 // and now for filled rect with outline
741 dc
.SetPen(*wxRED_PEN
);
742 dc
.SetBrush( *wxWHITE_BRUSH
);
743 dc
.DrawRectangle(500, 170, 49, 29);
744 dc
.DrawRectangle(550, 170, 49, 29);
745 dc
.SetPen(*wxWHITE_PEN
);
746 dc
.DrawLine(600, 170, 600, 210);
747 dc
.DrawLine(500, 200, 610, 200);
749 // test the rectangle outline drawing - there should be one pixel between
750 // the rect and the lines
751 dc
.SetPen(*wxWHITE_PEN
);
752 dc
.SetBrush( *wxTRANSPARENT_BRUSH
);
753 dc
.DrawRoundedRectangle(150, 270, 49, 29, 6);
754 dc
.DrawRoundedRectangle(200, 270, 49, 29, 6);
755 dc
.SetPen(*wxWHITE_PEN
);
756 dc
.DrawLine(250, 270, 250, 310);
757 dc
.DrawLine(150, 300, 260, 300);
759 // test the rectangle filled drawing - there should be one pixel between
760 // the rect and the lines
761 dc
.SetPen(*wxTRANSPARENT_PEN
);
762 dc
.SetBrush( *wxWHITE_BRUSH
);
763 dc
.DrawRoundedRectangle(300, 270, 49, 29, 6);
764 dc
.DrawRoundedRectangle(350, 270, 49, 29, 6);
765 dc
.SetPen(*wxWHITE_PEN
);
766 dc
.DrawLine(400, 270, 400, 310);
767 dc
.DrawLine(300, 300, 410, 300);
769 // Added by JACS to demonstrate bizarre behaviour.
770 // With a size of 70, we get a missing red RHS,
771 // and the hight is too small, so we get yellow
772 // showing. With a size of 40, it draws as expected:
773 // it just shows a white rectangle with red outline.
775 int totalHeight
= 70;
776 wxBitmap
bitmap2(totalWidth
, totalHeight
);
779 memdc2
.SelectObject(bitmap2
);
781 wxBrush
yellowBrush(wxColour(255, 255, 0), wxSOLID
);
782 memdc2
.SetBackground(yellowBrush
);
785 wxPen
yellowPen(wxColour(255, 255, 0), 1, wxSOLID
);
787 // Now draw a white rectangle with red outline. It should
788 // entirely eclipse the yellow background.
789 memdc2
.SetPen(*wxRED_PEN
);
790 memdc2
.SetBrush(*wxWHITE_BRUSH
);
792 memdc2
.DrawRectangle(0, 0, totalWidth
, totalHeight
);
794 memdc2
.SetPen(wxNullPen
);
795 memdc2
.SetBrush(wxNullBrush
);
796 memdc2
.SelectObject(wxNullBitmap
);
798 dc
.DrawBitmap(bitmap2
, 500, 270);
800 // Repeat, but draw directly on dc
801 // Draw a yellow rectangle filling the bitmap
803 x
= 600; int y
= 270;
804 dc
.SetPen(yellowPen
);
805 dc
.SetBrush(yellowBrush
);
806 dc
.DrawRectangle(x
, y
, totalWidth
, totalHeight
);
808 // Now draw a white rectangle with red outline. It should
809 // entirely eclipse the yellow background.
810 dc
.SetPen(*wxRED_PEN
);
811 dc
.SetBrush(*wxWHITE_BRUSH
);
813 dc
.DrawRectangle(x
, y
, totalWidth
, totalHeight
);
816 void MyCanvas::DrawText(wxDC
& dc
)
818 // set underlined font for testing
819 dc
.SetFont( wxFont(12, wxMODERN
, wxNORMAL
, wxNORMAL
, TRUE
) );
820 dc
.DrawText( "This is text", 110, 10 );
821 dc
.DrawRotatedText( "That is text", 20, 10, -45 );
823 dc
.SetFont( *wxNORMAL_FONT
);
826 dc
.SetBackgroundMode(wxTRANSPARENT
);
828 for ( int n
= -180; n
< 180; n
+= 30 )
830 text
.Printf(" %d rotated text", n
);
831 dc
.DrawRotatedText(text
, 400, 400, n
);
834 dc
.SetFont( wxFont( 18, wxSWISS
, wxNORMAL
, wxNORMAL
) );
836 dc
.DrawText( "This is Swiss 18pt text.", 110, 40 );
841 dc
.GetTextExtent( "This is Swiss 18pt text.", &length
, &height
, &descent
);
842 text
.Printf( "Dimensions are length %ld, height %ld, descent %ld", length
, height
, descent
);
843 dc
.DrawText( text
, 110, 80 );
845 text
.Printf( "CharHeight() returns: %d", dc
.GetCharHeight() );
846 dc
.DrawText( text
, 110, 120 );
848 dc
.DrawRectangle( 100, 40, 4, height
);
850 // test the logical function effect
852 dc
.SetLogicalFunction(wxINVERT
);
853 dc
.DrawText( "There should be no text below", 110, 150 );
854 dc
.DrawRectangle( 110, y
, 100, height
);
856 // twice drawn inverted should result in invisible
858 dc
.DrawText( "Invisible text", 110, y
);
859 dc
.DrawRectangle( 110, y
, 100, height
);
860 dc
.DrawText( "Invisible text", 110, y
);
861 dc
.DrawRectangle( 110, y
, 100, height
);
862 dc
.SetLogicalFunction(wxCOPY
);
865 dc
.DrawRectangle( 110, y
, 100, height
);
866 dc
.DrawText( "Visible text", 110, y
);
873 } rasterOperations
[] =
876 { "wxAND_INVERT", wxAND_INVERT
},
877 { "wxAND_REVERSE", wxAND_REVERSE
},
878 { "wxCLEAR", wxCLEAR
},
879 { "wxCOPY", wxCOPY
},
880 { "wxEQUIV", wxEQUIV
},
881 { "wxINVERT", wxINVERT
},
882 { "wxNAND", wxNAND
},
883 { "wxNO_OP", wxNO_OP
},
885 { "wxOR_INVERT", wxOR_INVERT
},
886 { "wxOR_REVERSE", wxOR_REVERSE
},
888 { "wxSRC_INVERT", wxSRC_INVERT
},
892 void MyCanvas::DrawImages(wxDC
& dc
)
894 dc
.DrawText("original image", 0, 0);
895 dc
.DrawBitmap(*gs_bmpNoMask
, 0, 20, 0);
896 dc
.DrawText("with colour mask", 0, 100);
897 dc
.DrawBitmap(*gs_bmpWithColMask
, 0, 120, TRUE
);
898 dc
.DrawText("the mask image", 0, 200);
899 dc
.DrawBitmap(*gs_bmpMask
, 0, 220, 0);
900 dc
.DrawText("masked image", 0, 300);
901 dc
.DrawBitmap(*gs_bmpWithMask
, 0, 320, TRUE
);
903 int cx
= gs_bmpWithColMask
->GetWidth(),
904 cy
= gs_bmpWithColMask
->GetHeight();
907 for ( size_t n
= 0; n
< WXSIZEOF(rasterOperations
); n
++ )
909 wxCoord x
= 120 + 150*(n%4
),
912 dc
.DrawText(rasterOperations
[n
].name
, x
, y
- 20);
913 memDC
.SelectObject(*gs_bmpWithColMask
);
914 dc
.Blit(x
, y
, cx
, cy
, &memDC
, 0, 0, rasterOperations
[n
].rop
, TRUE
);
918 void MyCanvas::DrawWithLogicalOps(wxDC
& dc
)
920 static const wxCoord w
= 60;
921 static const wxCoord h
= 60;
923 // reuse the text colour here
924 dc
.SetPen(wxPen(m_owner
->m_colourForeground
, 1, wxSOLID
));
925 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
928 for ( n
= 0; n
< WXSIZEOF(rasterOperations
); n
++ )
930 wxCoord x
= 20 + 150*(n%4
),
933 dc
.DrawText(rasterOperations
[n
].name
, x
, y
- 20);
934 dc
.SetLogicalFunction(rasterOperations
[n
].rop
);
935 dc
.DrawRectangle(x
, y
, w
, h
);
936 dc
.DrawLine(x
, y
, x
+ w
, y
+ h
);
937 dc
.DrawLine(x
+ w
, y
, x
, y
+ h
);
940 // now some filled rectangles
941 dc
.SetBrush(wxBrush(m_owner
->m_colourForeground
, wxSOLID
));
943 for ( n
= 0; n
< WXSIZEOF(rasterOperations
); n
++ )
945 wxCoord x
= 20 + 150*(n%4
),
948 dc
.DrawText(rasterOperations
[n
].name
, x
, y
- 20);
949 dc
.SetLogicalFunction(rasterOperations
[n
].rop
);
950 dc
.DrawRectangle(x
, y
, w
, h
);
954 void MyCanvas::DrawCircles(wxDC
& dc
)
960 dc
.DrawText("Some circles", 0, y
);
961 dc
.DrawCircle(x
, y
, r
);
962 dc
.DrawCircle(x
+ 2*r
, y
, r
);
963 dc
.DrawCircle(x
+ 4*r
, y
, r
);
966 dc
.DrawText("And ellipses", 0, y
);
967 dc
.DrawEllipse(x
- r
, y
, 2*r
, r
);
968 dc
.DrawEllipse(x
+ r
, y
, 2*r
, r
);
969 dc
.DrawEllipse(x
+ 3*r
, y
, 2*r
, r
);
972 dc
.DrawText("And arcs", 0, y
);
973 dc
.DrawArc(x
- r
, y
, x
+ r
, y
, x
, y
);
974 dc
.DrawArc(x
+ 4*r
, y
, x
+ 2*r
, y
, x
+ 3*r
, y
);
975 dc
.DrawArc(x
+ 5*r
, y
, x
+ 5*r
, y
, x
+ 6*r
, y
);
978 dc
.DrawEllipticArc(x
- r
, y
, 2*r
, r
, 0, 90);
979 dc
.DrawEllipticArc(x
+ r
, y
, 2*r
, r
, 90, 180);
980 dc
.DrawEllipticArc(x
+ 3*r
, y
, 2*r
, r
, 180, 270);
981 dc
.DrawEllipticArc(x
+ 5*r
, y
, 2*r
, r
, 270, 360);
984 void MyCanvas::DrawRegions(wxDC
& dc
)
986 dc
.SetBrush( *wxWHITE_BRUSH
);
987 dc
.SetPen( *wxTRANSPARENT_PEN
);
988 dc
.DrawRectangle( 10,10,310,310 );
990 dc
.SetClippingRegion( 20,20,100,270 );
992 dc
.SetBrush( *wxRED_BRUSH
);
993 dc
.DrawRectangle( 10,10,310,310 );
995 dc
.SetClippingRegion( 20,20,100,100 );
997 dc
.SetBrush( *wxCYAN_BRUSH
);
998 dc
.DrawRectangle( 10,10,310,310 );
1000 dc
.DestroyClippingRegion();
1001 dc
.SetClippingRegion( 120,30,100,270 );
1003 dc
.SetBrush( *wxGREY_BRUSH
);
1004 dc
.DrawRectangle( 10,10,310,310 );
1006 if (m_smile_bmp
.Ok())
1008 dc
.DrawBitmap( m_smile_bmp
, 140, 20, TRUE
);
1009 dc
.DrawBitmap( m_smile_bmp
, 140, 290, TRUE
);
1010 dc
.DrawBitmap( m_smile_bmp
, 110, 80, TRUE
);
1011 dc
.DrawBitmap( m_smile_bmp
, 210, 80, TRUE
);
1015 void MyCanvas::OnPaint(wxPaintEvent
&WXUNUSED(event
))
1020 m_owner
->PrepareDC(dc
);
1022 dc
.SetBackgroundMode( m_owner
->m_backgroundMode
);
1023 if ( m_owner
->m_backgroundBrush
.Ok() )
1024 dc
.SetBackground( m_owner
->m_backgroundBrush
);
1025 if ( m_owner
->m_colourForeground
.Ok() )
1026 dc
.SetTextForeground( m_owner
->m_colourForeground
);
1027 if ( m_owner
->m_colourBackground
.Ok() )
1028 dc
.SetTextBackground( m_owner
->m_colourBackground
);
1030 if ( m_owner
->m_textureBackground
) {
1031 if ( ! m_owner
->m_backgroundBrush
.Ok() ) {
1032 wxBrush
b(wxColour(0,128,0), wxSOLID
);
1033 dc
.SetBackground(b
);
1039 if ( m_owner
->m_textureBackground
) {
1040 dc
.SetPen(*wxMEDIUM_GREY_PEN
);
1041 for (int i
=0; i
<200; i
++)
1042 dc
.DrawLine(0, i
*10, i
*10, 0);
1064 DrawTestLines( 0, 100, 0, dc
);
1065 DrawTestLines( 0, 320, 1, dc
);
1066 DrawTestLines( 0, 540, 2, dc
);
1067 DrawTestLines( 0, 760, 6, dc
);
1071 DrawTestPoly( 0, 100, dc
, 0 );
1073 DrawTestPoly( 33, 500, dc, 1 );
1074 DrawTestPoly( 43, 1000, dc, 2 );
1083 DrawWithLogicalOps(dc
);
1088 dc
.SetPen( *wxBLACK_PEN
);
1089 dc
.DrawLine( 0,0,100,100 );
1095 void MyCanvas::OnMouseMove(wxMouseEvent
&event
)
1097 wxClientDC
dc(this);
1099 m_owner
->PrepareDC(dc
);
1101 wxPoint pos
= event
.GetPosition();
1102 long x
= dc
.DeviceToLogicalX( pos
.x
);
1103 long y
= dc
.DeviceToLogicalY( pos
.y
);
1105 str
.Printf( "Current mouse position: %d,%d", (int)x
, (int)y
);
1106 m_owner
->SetStatusText( str
);
1109 // ----------------------------------------------------------------------------
1111 // ----------------------------------------------------------------------------
1113 // the event tables connect the wxWindows events with the functions (event
1114 // handlers) which process them. It can be also done at run-time, but for the
1115 // simple menu events like this the static method is much simpler.
1116 BEGIN_EVENT_TABLE(MyFrame
, wxFrame
)
1117 EVT_MENU (File_Quit
, MyFrame::OnQuit
)
1118 EVT_MENU (File_About
, MyFrame::OnAbout
)
1120 EVT_MENU_RANGE(MenuShow_First
, MenuShow_Last
, MyFrame::OnShow
)
1122 EVT_MENU_RANGE(MenuOption_First
, MenuOption_Last
, MyFrame::OnOption
)
1125 // frame constructor
1126 MyFrame::MyFrame(const wxString
& title
, const wxPoint
& pos
, const wxSize
& size
)
1127 : wxFrame((wxFrame
*)NULL
, -1, title
, pos
, size
)
1129 // set the frame icon
1130 SetIcon(wxICON(mondrian
));
1132 wxMenu
*menuFile
= new wxMenu
;
1133 menuFile
->Append(File_ShowDefault
, "&Default screen\tF1");
1134 menuFile
->Append(File_ShowText
, "&Text screen\tF2");
1135 menuFile
->Append(File_ShowLines
, "&Lines screen\tF3");
1136 menuFile
->Append(File_ShowPolygons
, "&Polygons screen\tF4");
1137 menuFile
->Append(File_ShowMask
, "wx&Mask screen\tF5");
1138 menuFile
->Append(File_ShowOps
, "&ROP screen\tF6");
1139 menuFile
->Append(File_ShowRegions
, "Re&gions screen\tF7");
1140 menuFile
->Append(File_ShowCircles
, "&Circles screen\tF8");
1141 menuFile
->AppendSeparator();
1142 menuFile
->Append(File_About
, "&About...\tCtrl-A", "Show about dialog");
1143 menuFile
->AppendSeparator();
1144 menuFile
->Append(File_Quit
, "E&xit\tAlt-X", "Quit this program");
1146 wxMenu
*menuMapMode
= new wxMenu
;
1147 menuMapMode
->Append( MapMode_Text
, "&TEXT map mode" );
1148 menuMapMode
->Append( MapMode_Lometric
, "&LOMETRIC map mode" );
1149 menuMapMode
->Append( MapMode_Twips
, "T&WIPS map mode" );
1150 menuMapMode
->Append( MapMode_Points
, "&POINTS map mode" );
1151 menuMapMode
->Append( MapMode_Metric
, "&METRIC map mode" );
1153 wxMenu
*menuUserScale
= new wxMenu
;
1154 menuUserScale
->Append( UserScale_StretchHoriz
, "Stretch horizontally\tCtrl-H" );
1155 menuUserScale
->Append( UserScale_ShrinkHoriz
, "Shrink horizontally\tCtrl-G" );
1156 menuUserScale
->Append( UserScale_StretchVertic
, "Stretch vertically\tCtrl-V" );
1157 menuUserScale
->Append( UserScale_ShrinkVertic
, "Shrink vertically\tCtrl-W" );
1158 menuUserScale
->AppendSeparator();
1159 menuUserScale
->Append( UserScale_Restore
, "Restore to normal\tCtrl-0" );
1161 wxMenu
*menuAxis
= new wxMenu
;
1162 menuAxis
->Append( AxisMirror_Horiz
, "Mirror horizontally\tCtrl-M", "", TRUE
);
1163 menuAxis
->Append( AxisMirror_Vertic
, "Mirror vertically\tCtrl-N", "", TRUE
);
1165 wxMenu
*menuLogical
= new wxMenu
;
1166 menuLogical
->Append( LogicalOrigin_MoveDown
, "Move &down\tCtrl-D" );
1167 menuLogical
->Append( LogicalOrigin_MoveUp
, "Move &up\tCtrl-U" );
1168 menuLogical
->Append( LogicalOrigin_MoveLeft
, "Move &right\tCtrl-L" );
1169 menuLogical
->Append( LogicalOrigin_MoveRight
, "Move &left\tCtrl-R" );
1171 wxMenu
*menuColour
= new wxMenu
;
1172 menuColour
->Append( Colour_TextForeground
, "Text foreground..." );
1173 menuColour
->Append( Colour_TextBackground
, "Text background..." );
1174 menuColour
->Append( Colour_Background
, "Background colour..." );
1175 menuColour
->Append( Colour_BackgroundMode
, "Opaque/transparent\tCtrl-B", "", TRUE
);
1176 menuColour
->Append( Colour_TextureBackgound
, "Draw textured background\tCtrl-T", "", TRUE
);
1178 // now append the freshly created menu to the menu bar...
1179 wxMenuBar
*menuBar
= new wxMenuBar
;
1180 menuBar
->Append(menuFile
, "&File");
1181 menuBar
->Append(menuMapMode
, "&MapMode");
1182 menuBar
->Append(menuUserScale
, "&UserScale");
1183 menuBar
->Append(menuAxis
, "&Axis");
1184 menuBar
->Append(menuLogical
, "&LogicalOrigin");
1185 menuBar
->Append(menuColour
, "&Colours");
1187 // ... and attach this menu bar to the frame
1188 SetMenuBar(menuBar
);
1190 // create a status bar just for fun (by default with 1 pane only)
1192 SetStatusText("Welcome to wxWindows!");
1194 m_mapMode
= wxMM_TEXT
;
1197 m_xLogicalOrigin
= 0;
1198 m_yLogicalOrigin
= 0;
1200 m_yAxisReversed
= FALSE
;
1201 m_backgroundMode
= wxSOLID
;
1202 m_colourForeground
= *wxRED
;
1203 m_colourBackground
= *wxBLUE
;
1204 m_textureBackground
= FALSE
;
1206 m_canvas
= new MyCanvas( this );
1207 m_canvas
->SetScrollbars( 10, 10, 100, 240 );
1212 void MyFrame::OnQuit(wxCommandEvent
& WXUNUSED(event
))
1214 // TRUE is to force the frame to close
1218 void MyFrame::OnAbout(wxCommandEvent
& WXUNUSED(event
))
1221 msg
.Printf( wxT("This is the about dialog of the drawing sample.\n")
1222 wxT("This sample tests various primitive drawing functions\n")
1223 wxT("without any tests to prevent flicker.\n")
1224 wxT("Copyright (c) Robert Roebling 1999")
1227 wxMessageBox(msg
, "About Drawing", wxOK
| wxICON_INFORMATION
, this);
1230 void MyFrame::OnShow(wxCommandEvent
& event
)
1232 m_canvas
->Show((ScreenToShow
)(event
.GetId() - MenuShow_First
));
1235 void MyFrame::OnOption(wxCommandEvent
& event
)
1237 switch (event
.GetId())
1240 m_mapMode
= wxMM_TEXT
;
1242 case MapMode_Lometric
:
1243 m_mapMode
= wxMM_LOMETRIC
;
1246 m_mapMode
= wxMM_TWIPS
;
1248 case MapMode_Points
:
1249 m_mapMode
= wxMM_POINTS
;
1251 case MapMode_Metric
:
1252 m_mapMode
= wxMM_METRIC
;
1255 case LogicalOrigin_MoveDown
:
1256 m_yLogicalOrigin
+= 10;
1258 case LogicalOrigin_MoveUp
:
1259 m_yLogicalOrigin
-= 10;
1261 case LogicalOrigin_MoveLeft
:
1262 m_xLogicalOrigin
+= 10;
1264 case LogicalOrigin_MoveRight
:
1265 m_xLogicalOrigin
-= 10;
1268 case UserScale_StretchHoriz
:
1269 m_xUserScale
*= 1.10;
1271 case UserScale_ShrinkHoriz
:
1272 m_xUserScale
/= 1.10;
1274 case UserScale_StretchVertic
:
1275 m_yUserScale
*= 1.10;
1277 case UserScale_ShrinkVertic
:
1278 m_yUserScale
/= 1.10;
1280 case UserScale_Restore
:
1285 case AxisMirror_Vertic
:
1286 m_yAxisReversed
= !m_yAxisReversed
;
1288 case AxisMirror_Horiz
:
1289 m_xAxisReversed
= !m_xAxisReversed
;
1292 case Colour_TextForeground
:
1293 m_colourForeground
= SelectColour();
1295 case Colour_TextBackground
:
1296 m_colourBackground
= SelectColour();
1298 case Colour_Background
:
1300 wxColour col
= SelectColour();
1303 m_backgroundBrush
.SetColour(col
);
1307 case Colour_BackgroundMode
:
1308 m_backgroundMode
= m_backgroundMode
== wxSOLID
? wxTRANSPARENT
1312 case Colour_TextureBackgound
:
1313 m_textureBackground
= ! m_textureBackground
;
1321 m_canvas
->Refresh();
1324 void MyFrame::PrepareDC(wxDC
& dc
)
1326 dc
.SetMapMode( m_mapMode
);
1327 dc
.SetUserScale( m_xUserScale
, m_yUserScale
);
1328 dc
.SetLogicalOrigin( m_xLogicalOrigin
, m_yLogicalOrigin
);
1329 dc
.SetAxisOrientation( !m_xAxisReversed
, m_yAxisReversed
);
1332 wxColour
MyFrame::SelectColour()
1336 wxColourDialog
dialog(this, &data
);
1338 if ( dialog
.ShowModal() == wxID_OK
)
1340 col
= dialog
.GetColourData().GetColour();