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)
67 // ----------------------------------------------------------------------------
69 // ----------------------------------------------------------------------------
71 static wxBitmap gs_bmpNoMask
,
79 // ----------------------------------------------------------------------------
81 // ----------------------------------------------------------------------------
83 // Define a new application type, each program should derive a class from wxApp
84 class MyApp
: public wxApp
87 // override base class virtuals
88 // ----------------------------
90 // this one is called on application startup and is a good place for the app
91 // initialization (doing it here and not in the ctor allows to have an error
92 // return: if OnInit() returns false, the application terminates)
93 virtual bool OnInit();
101 // Define a new frame type: this is going to be our main frame
102 class MyFrame
: public wxFrame
106 MyFrame(const wxString
& title
, const wxPoint
& pos
, const wxSize
& size
);
108 // event handlers (these functions should _not_ be virtual)
109 void OnQuit(wxCommandEvent
& event
);
110 void OnAbout(wxCommandEvent
& event
);
111 void OnShow(wxCommandEvent
&event
);
112 void OnOption(wxCommandEvent
&event
);
114 wxColour
SelectColour();
115 void PrepareDC(wxDC
& dc
);
117 int m_backgroundMode
;
118 int m_textureBackground
;
122 int m_xLogicalOrigin
;
123 int m_yLogicalOrigin
;
124 bool m_xAxisReversed
,
126 wxColour m_colourForeground
, // these are _text_ colours
128 wxBrush m_backgroundBrush
;
132 // any class wishing to process wxWindows events must use this macro
133 DECLARE_EVENT_TABLE()
136 // define a scrollable canvas for drawing onto
137 class MyCanvas
: public wxScrolledWindow
140 MyCanvas( MyFrame
*parent
);
142 void OnPaint(wxPaintEvent
&event
);
143 void OnMouseMove(wxMouseEvent
&event
);
145 void Show(ScreenToShow show
) { m_show
= show
; Refresh(); }
148 void DrawTestPoly( int x
, int y
, wxDC
&dc
,int transparent
);
149 void DrawTestLines( int x
, int y
, int width
, wxDC
&dc
);
150 void DrawText(wxDC
& dc
);
151 void DrawImages(wxDC
& dc
);
152 void DrawWithLogicalOps(wxDC
& dc
);
153 void DrawRegions(wxDC
& dc
);
154 void DrawDefault(wxDC
& dc
);
160 wxBitmap m_smile_bmp
;
163 DECLARE_EVENT_TABLE()
166 // ----------------------------------------------------------------------------
168 // ----------------------------------------------------------------------------
170 // IDs for the controls and the menu commands
178 File_ShowDefault
= MenuShow_First
,
185 MenuShow_Last
= File_ShowRegions
,
189 MapMode_Text
= MenuOption_First
,
195 UserScale_StretchHoriz
,
196 UserScale_ShrinkHoriz
,
197 UserScale_StretchVertic
,
198 UserScale_ShrinkVertic
,
204 LogicalOrigin_MoveDown
,
205 LogicalOrigin_MoveUp
,
206 LogicalOrigin_MoveLeft
,
207 LogicalOrigin_MoveRight
,
209 Colour_TextForeground
,
210 Colour_TextBackground
,
212 Colour_BackgroundMode
,
213 Colour_TextureBackgound
,
215 MenuOption_Last
= Colour_TextureBackgound
218 // ----------------------------------------------------------------------------
219 // event tables and other macros for wxWindows
220 // ----------------------------------------------------------------------------
223 // Create a new application object: this macro will allow wxWindows to create
224 // the application object during program execution (it's better than using a
225 // static object for many reasons) and also declares the accessor function
226 // wxGetApp() which will return the reference of the right type (i.e. MyApp and
230 // ============================================================================
232 // ============================================================================
234 // ----------------------------------------------------------------------------
235 // the application class
236 // ----------------------------------------------------------------------------
238 bool MyApp::LoadImages()
244 wxString path
= pathList
.FindValidPath("pat4.bmp");
247 /* 4 colour bitmap */
248 gs_bmp4
.LoadFile(path
, wxBITMAP_TYPE_BMP
);
249 /* turn into mono-bitmap */
250 gs_bmp4_mono
.LoadFile(path
, wxBITMAP_TYPE_BMP
);
251 wxMask
* mask4
= new wxMask(gs_bmp4_mono
, *wxBLACK
);
252 gs_bmp4_mono
.SetMask(mask4
);
254 path
= pathList
.FindValidPath("pat36.bmp");
257 gs_bmp36
.LoadFile(path
, wxBITMAP_TYPE_BMP
);
258 wxMask
* mask36
= new wxMask(gs_bmp36
, *wxBLACK
);
259 gs_bmp36
.SetMask(mask36
);
261 path
= pathList
.FindValidPath("image.bmp");
264 gs_bmpNoMask
.LoadFile(path
, wxBITMAP_TYPE_BMP
);
265 gs_bmpWithMask
.LoadFile(path
, wxBITMAP_TYPE_BMP
);
266 gs_bmpWithColMask
.LoadFile(path
, wxBITMAP_TYPE_BMP
);
268 path
= pathList
.FindValidPath("mask.bmp");
271 gs_bmpMask
.LoadFile(path
, wxBITMAP_TYPE_BMP
);
273 // This is so wrong, it hurts.
274 // gs_bmpMask.SetDepth(1);
275 // wxMask *mask = new wxMask(gs_bmpMask);
277 wxMask
*mask
= new wxMask(gs_bmpMask
, *wxBLACK
);
278 gs_bmpWithMask
.SetMask(mask
);
280 mask
= new wxMask(gs_bmpWithColMask
, *wxWHITE
);
281 gs_bmpWithColMask
.SetMask(mask
);
286 // `Main program' equivalent: the program execution "starts" here
289 // Create the main application window
290 MyFrame
*frame
= new MyFrame("Drawing sample",
291 wxPoint(50, 50), wxSize(550, 340));
293 // Show it and tell the application that it's our main window
299 wxLogError("Can't load one of the bitmap files needed for this sample "
300 "from the current or parent directory, please copy them "
311 // ----------------------------------------------------------------------------
313 // ----------------------------------------------------------------------------
315 // the event tables connect the wxWindows events with the functions (event
316 // handlers) which process them.
317 BEGIN_EVENT_TABLE(MyCanvas
, wxScrolledWindow
)
318 EVT_PAINT (MyCanvas::OnPaint
)
319 EVT_MOTION (MyCanvas::OnMouseMove
)
322 #include "../image/smile.xpm"
324 MyCanvas::MyCanvas( MyFrame
*parent
) : wxScrolledWindow( parent
)
327 m_show
= Show_Default
;
328 m_smile_bmp
= wxBitmap(smile_xpm
);
329 m_std_icon
= wxTheApp
->GetStdIcon(wxICON_INFORMATION
);
332 // Draw a polygon and an overlapping rectangle
333 // If transparent is 1, the fill pattern is made transparent.
334 // If transparent is 2, the fill pattern is made transparent but inversed
335 // If is transparent is 0 the text for and background color will be used to represent/map
336 // the colors of the monochrome bitmap pixels to the fillpattern
338 // I abused the the menu items for setting so called back and fore ground color
339 // just to show how the those colors do influence the fillpatterns just play
340 // with those, and with the code variations are endless using other logical
343 void MyCanvas::DrawTestPoly( int x
, int y
,wxDC
&dc
,int transparent
)
345 wxBrush
* brush4
= new wxBrush(gs_bmp4
);
346 wxBrush
* brush4_mono
= new wxBrush(gs_bmp4_mono
);
347 wxBrush
* brush36
= new wxBrush(gs_bmp36
);
350 todraw
[0].x
=(long)x
+100;
351 todraw
[0].y
=(long)y
+100;
352 todraw
[1].x
=(long)x
+300;
353 todraw
[1].y
=(long)y
+100;
354 todraw
[2].x
=(long)x
+300;
355 todraw
[2].y
=(long)y
+300;
356 todraw
[3].x
=(long)x
+150;
357 todraw
[3].y
=(long)y
+350;
358 todraw
[4].x
=(long)x
+100;
359 todraw
[4].y
=(long)y
+300;
377 dc
.SetLogicalFunction(wxCOPY
);
379 dc
.SetPen( wxPen( "black", 4, wxSOLID
) );
380 dc
.SetBrush( *brush4
);
381 dc
.DrawPolygon(5,todraw
,0,0,wxWINDING_RULE
);
383 dc
.SetPen( wxPen( "red", 4, wxSOLID
) );
384 dc
.SetBrush( *brush36
);
385 dc
.SetTextForeground(*wxCYAN
);
386 dc
.SetTextBackground(m_owner
->m_colourBackground
);
387 dc
.DrawRectangle( x
+10, y
+10, 200, 200 );
389 dc
.SetPen( wxPen( "green", 4, wxSOLID
) );
390 dc
.SetBrush( *brush4_mono
);
391 dc
.SetTextForeground(*wxCYAN
);
392 dc
.SetTextBackground(m_owner
->m_colourBackground
);
393 dc
.DrawRectangle( x
+50, y
+50, 200, 200 );
395 dc
.DrawCircle( x
+400, y
+50, 130 );
397 dc
.SetBrush(wxNullBrush
);
398 dc
.SetPen(wxNullPen
);
401 case 1: //now with transparent fillpatterns
404 wxBitmap
* bmpBlit
= new wxBitmap(600,400);
405 wxMemoryDC
* memDC
= new wxMemoryDC();
406 // wxBrush _clearbrush(*wxGREEN,wxSOLID);
407 wxBrush
_clearbrush(*wxBLACK
,wxSOLID
);
408 memDC
->SelectObject(*bmpBlit
);
409 memDC
->BeginDrawing();
410 memDC
->SetBackground(_clearbrush
);
412 memDC
->SetBackground(wxNullBrush
);
414 memDC
->SetPen( wxPen( "black", 4, wxSOLID
) );
415 memDC
->SetBrush( wxNullBrush
);
416 memDC
->SetBrush( *brush4
);
417 memDC
->SetTextForeground(*wxBLACK
); // 0s --> 0x000000 (black)
418 memDC
->SetTextBackground(*wxWHITE
); // 1s --> 0xFFFFFF (white)
419 memDC
->SetLogicalFunction(wxAND_INVERT
);
421 // BLACK OUT the opaque pixels and leave the rest as is
422 memDC
->DrawPolygon(5,todraw2
,0,0,wxWINDING_RULE
);
424 // Set background and foreground colors for fill pattern
425 //the previous blacked out pixels are now merged with the layer color
426 //while the non blacked out pixels stay as they are.
427 memDC
->SetTextForeground(*wxBLACK
); // 0s --> 0x000000 (black)
429 //now define what will be the color of the fillpattern parts that are not transparent
430 // memDC->SetTextBackground(*wxBLUE);
431 memDC
->SetTextBackground(m_owner
->m_colourForeground
);
432 memDC
->SetLogicalFunction(wxOR
);
435 //don't understand how but the outline is also depending on logicalfunction
436 memDC
->SetPen( wxPen( "red", 4, wxSOLID
) );
437 memDC
->DrawPolygon(5,todraw2
,0,0,wxWINDING_RULE
);
439 memDC
->SetLogicalFunction(wxCOPY
);
441 memDC
->SetPen( wxPen( "black", 4, wxSOLID
) );
442 memDC
->SetBrush( wxNullBrush
);
443 memDC
->SetBrush( *brush36
);
444 memDC
->SetTextForeground(*wxBLACK
); // 0s --> 0x000000 (black)
445 memDC
->SetTextBackground(*wxWHITE
); // 1s --> 0xFFFFFF (white)
446 memDC
->SetLogicalFunction(wxAND_INVERT
);
448 memDC
->DrawRectangle( 10, 10, 200, 200 );
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)
454 //now define what will be the color of the fillpattern parts that are not transparent
455 // memDC->SetTextBackground(*wxRED);
456 memDC
->SetTextBackground(m_owner
->m_colourBackground
);
457 memDC
->SetLogicalFunction(wxOR
);
459 //don't understand how but the outline is also depending on logicalfunction
460 memDC
->SetPen( wxPen( "yellow", 4, wxSOLID
) );
461 memDC
->DrawRectangle( 10, 10, 200, 200 );
463 memDC
->SetBrush(wxNullBrush
);
464 memDC
->SetPen(wxNullPen
);
467 dc
.Blit(x
,y
,600,400,memDC
,0,0,wxCOPY
);
472 case 2: //now with transparent inversed fillpatterns
474 wxBitmap
* bmpBlit
= new wxBitmap(600,400);
475 wxMemoryDC
* memDC
= new wxMemoryDC();
476 wxBrush
_clearbrush(*wxWHITE
,wxSOLID
);
477 memDC
->SelectObject(*bmpBlit
);
478 memDC
->BeginDrawing();
479 memDC
->SetBackground(_clearbrush
);
481 memDC
->SetBackground(wxNullBrush
);
483 memDC
->SetPen( wxPen( "black", 4, wxSOLID
) );
484 memDC
->SetBrush( *brush4
);
485 memDC
->SetTextBackground(*wxBLACK
); // 0s --> 0x000000 (black)
486 memDC
->SetTextForeground(*wxWHITE
); // 1s --> 0xFFFFFF (white)
487 memDC
->SetLogicalFunction(wxAND_INVERT
);
489 // BLACK OUT the opaque pixels and leave the rest as is
490 memDC
->DrawPolygon(5,todraw2
,0,0,wxWINDING_RULE
);
492 // Set background and foreground colors for fill pattern
493 //the previous blacked out pixels are now merged with the layer color
494 //while the non blacked out pixels stay as they are.
495 memDC
->SetTextBackground(*wxBLACK
); // 0s --> 0x000000 (black)
497 //now define what will be the color of the fillpattern parts that are not transparent
498 memDC
->SetTextForeground(m_owner
->m_colourForeground
);
499 memDC
->SetLogicalFunction(wxOR
);
502 //don't understand how but the outline is also depending on logicalfunction
503 memDC
->SetPen( wxPen( "red", 4, wxSOLID
) );
504 memDC
->DrawPolygon(5,todraw2
,0,0,wxWINDING_RULE
);
506 memDC
->SetLogicalFunction(wxCOPY
);
508 memDC
->SetPen( wxPen( "black", 4, wxSOLID
) );
509 memDC
->SetBrush( *brush36
);
510 memDC
->SetTextBackground(*wxBLACK
); // 0s --> 0x000000 (black)
511 memDC
->SetTextForeground(*wxWHITE
); // 1s --> 0xFFFFFF (white)
512 memDC
->SetLogicalFunction(wxAND_INVERT
);
514 memDC
->DrawRectangle( 10,10, 200, 200 );
516 // Set background and foreground colors for fill pattern
517 //the previous blacked out pixels are now merged with the layer color
518 //while the non blacked out pixels stay as they are.
519 memDC
->SetTextBackground(*wxBLACK
); // 0s --> 0x000000 (black)
520 //now define what will be the color of the fillpattern parts that are not transparent
521 memDC
->SetTextForeground(m_owner
->m_colourBackground
);
522 memDC
->SetLogicalFunction(wxOR
);
524 //don't understand how but the outline is also depending on logicalfunction
525 memDC
->SetPen( wxPen( "yellow", 4, wxSOLID
) );
526 memDC
->DrawRectangle( 10, 10, 200, 200 );
528 memDC
->SetBrush(wxNullBrush
);
529 memDC
->SetPen(wxNullPen
);
530 dc
.Blit(x
,y
,600,400,memDC
,0,0,wxCOPY
);
541 void MyCanvas::DrawTestLines( int x
, int y
, int width
, wxDC
&dc
)
543 dc
.SetPen( wxPen( "black", width
, wxSOLID
) );
544 dc
.SetBrush( *wxRED_BRUSH
);
545 dc
.DrawRectangle( x
+10, y
+10, 100, 190 );
547 dc
.SetPen( wxPen( "black", width
, wxSOLID
) );
548 dc
.DrawLine( x
+20, y
+20, 100, y
+20 );
549 dc
.SetPen( wxPen( "black", width
, wxDOT
) );
550 dc
.DrawLine( x
+20, y
+30, 100, y
+30 );
551 dc
.SetPen( wxPen( "black", width
, wxSHORT_DASH
) );
552 dc
.DrawLine( x
+20, y
+40, 100, y
+40 );
553 dc
.SetPen( wxPen( "black", width
, wxLONG_DASH
) );
554 dc
.DrawLine( x
+20, y
+50, 100, y
+50 );
555 dc
.SetPen( wxPen( "black", width
, wxDOT_DASH
) );
556 dc
.DrawLine( x
+20, y
+60, 100, y
+60 );
558 dc
.SetPen( wxPen( "black", width
, wxBDIAGONAL_HATCH
) );
559 dc
.DrawLine( x
+20, y
+70, 100, y
+70 );
560 dc
.SetPen( wxPen( "black", width
, wxCROSSDIAG_HATCH
) );
561 dc
.DrawLine( x
+20, y
+80, 100, y
+80 );
562 dc
.SetPen( wxPen( "black", width
, wxFDIAGONAL_HATCH
) );
563 dc
.DrawLine( x
+20, y
+90, 100, y
+90 );
564 dc
.SetPen( wxPen( "black", width
, wxCROSS_HATCH
) );
565 dc
.DrawLine( x
+20, y
+100, 100, y
+100 );
566 dc
.SetPen( wxPen( "black", width
, wxHORIZONTAL_HATCH
) );
567 dc
.DrawLine( x
+20, y
+110, 100, y
+110 );
568 dc
.SetPen( wxPen( "black", width
, wxVERTICAL_HATCH
) );
569 dc
.DrawLine( x
+20, y
+120, 100, y
+120 );
571 wxPen
ud( "black", width
, wxUSER_DASH
);
574 ud
.SetDashes( 1, dash1
);
575 dc
.DrawLine( x
+20, y
+140, 100, y
+140 );
577 ud
.SetDashes( 1, dash1
);
578 dc
.DrawLine( x
+20, y
+150, 100, y
+150 );
580 ud
.SetDashes( 1, dash1
);
581 dc
.DrawLine( x
+20, y
+160, 100, y
+160 );
583 ud
.SetDashes( 1, dash1
);
584 dc
.DrawLine( x
+20, y
+170, 100, y
+170 );
587 void MyCanvas::DrawDefault(wxDC
& dc
)
590 dc
.DrawCircle(0, 0, 10);
591 #if !(defined __WXGTK__) && !(defined __WXMOTIF__)
592 // not implemented in wxGTK or wxMOTIF :-(
593 dc
.FloodFill(0, 0, wxColour(255, 0, 0));
596 dc
.DrawCheckMark(5, 80, 15, 15);
597 dc
.DrawCheckMark(25, 80, 30, 30);
598 dc
.DrawCheckMark(60, 80, 60, 60);
600 // this is the test for "blitting bitmap into DC damages selected brush" bug
601 wxCoord rectSize
= m_std_icon
.GetWidth() + 10;
603 dc
.SetPen(*wxTRANSPARENT_PEN
);
604 dc
.SetBrush( *wxGREEN_BRUSH
);
605 dc
.DrawRectangle(x
, 10, rectSize
, rectSize
);
606 dc
.DrawBitmap(m_std_icon
, x
+ 5, 15, TRUE
);
608 dc
.DrawRectangle(x
, 10, rectSize
, rectSize
);
609 dc
.DrawIcon(m_std_icon
, x
+ 5, 15);
611 dc
.DrawRectangle(x
, 10, rectSize
, rectSize
);
613 // test for "transparent" bitmap drawing (it intersects with the last
615 //dc.SetBrush( *wxTRANSPARENT_BRUSH );
617 if (m_smile_bmp
.Ok())
618 dc
.DrawBitmap(m_smile_bmp
, x
+ rectSize
- 20, rectSize
- 10, TRUE
);
620 dc
.SetBrush( *wxBLACK_BRUSH
);
621 dc
.DrawRectangle( 0, 160, 1000, 300 );
624 wxBitmap
bitmap(20,70);
626 memdc
.SelectObject( bitmap
);
627 memdc
.SetBrush( *wxBLACK_BRUSH
);
628 memdc
.SetPen( *wxWHITE_PEN
);
629 memdc
.DrawRectangle(0,0,20,70);
630 memdc
.DrawLine( 10,0,10,70 );
633 wxPen pen
= *wxRED_PEN
;
635 memdc
.DrawLine( 10, 5,10, 5 );
636 memdc
.DrawLine( 10,10,11,10 );
637 memdc
.DrawLine( 10,15,12,15 );
638 memdc
.DrawLine( 10,20,13,20 );
641 memdc.SetPen(*wxRED_PEN);
642 memdc.DrawLine( 12, 5,12, 5 );
643 memdc.DrawLine( 12,10,13,10 );
644 memdc.DrawLine( 12,15,14,15 );
645 memdc.DrawLine( 12,20,15,20 );
649 memdc
.DrawLine( 10,25,10,25 );
650 memdc
.DrawLine( 10,30, 9,30 );
651 memdc
.DrawLine( 10,35, 8,35 );
652 memdc
.DrawLine( 10,40, 7,40 );
655 dc
.SetPen(*wxWHITE_PEN
);
656 memdc
.SetLogicalFunction( wxINVERT
);
657 memdc
.SetPen( *wxWHITE_PEN
);
658 memdc
.DrawLine( 10,50,10,50 );
659 memdc
.DrawLine( 10,55,11,55 );
660 memdc
.DrawLine( 10,60,12,60 );
661 memdc
.DrawLine( 10,65,13,65 );
663 memdc
.DrawLine( 12,50,12,50 );
664 memdc
.DrawLine( 12,55,13,55 );
665 memdc
.DrawLine( 12,60,14,60 );
666 memdc
.DrawLine( 12,65,15,65 );
668 memdc
.SelectObject( wxNullBitmap
);
669 dc
.DrawBitmap( bitmap
, 10, 170 );
670 wxImage
image( bitmap
);
671 image
.Rescale( 60,210 );
672 bitmap
= image
.ConvertToBitmap();
673 dc
.DrawBitmap( bitmap
, 50, 170 );
675 // test the rectangle outline drawing - there should be one pixel between
676 // the rect and the lines
677 dc
.SetPen(*wxWHITE_PEN
);
678 dc
.SetBrush( *wxTRANSPARENT_BRUSH
);
679 dc
.DrawRectangle(150, 170, 49, 29);
680 dc
.DrawRectangle(200, 170, 49, 29);
681 dc
.SetPen(*wxWHITE_PEN
);
682 dc
.DrawLine(250, 210, 250, 170);
683 dc
.DrawLine(260, 200, 150, 200);
685 // test the rectangle filled drawing - there should be one pixel between
686 // the rect and the lines
687 dc
.SetPen(*wxTRANSPARENT_PEN
);
688 dc
.SetBrush( *wxWHITE_BRUSH
);
689 dc
.DrawRectangle(300, 170, 49, 29);
690 dc
.DrawRectangle(350, 170, 49, 29);
691 dc
.SetPen(*wxWHITE_PEN
);
692 dc
.DrawLine(400, 170, 400, 210);
693 dc
.DrawLine(300, 200, 410, 200);
695 // a few more tests of this kind
696 dc
.SetPen(*wxRED_PEN
);
697 dc
.SetBrush( *wxWHITE_BRUSH
);
698 dc
.DrawRectangle(300, 220, 1, 1);
699 dc
.DrawRectangle(310, 220, 2, 2);
700 dc
.DrawRectangle(320, 220, 3, 3);
701 dc
.DrawRectangle(330, 220, 4, 4);
703 dc
.SetPen(*wxTRANSPARENT_PEN
);
704 dc
.SetBrush( *wxWHITE_BRUSH
);
705 dc
.DrawRectangle(300, 230, 1, 1);
706 dc
.DrawRectangle(310, 230, 2, 2);
707 dc
.DrawRectangle(320, 230, 3, 3);
708 dc
.DrawRectangle(330, 230, 4, 4);
710 // and now for filled rect with outline
711 dc
.SetPen(*wxRED_PEN
);
712 dc
.SetBrush( *wxWHITE_BRUSH
);
713 dc
.DrawRectangle(500, 170, 49, 29);
714 dc
.DrawRectangle(550, 170, 49, 29);
715 dc
.SetPen(*wxWHITE_PEN
);
716 dc
.DrawLine(600, 170, 600, 210);
717 dc
.DrawLine(500, 200, 610, 200);
719 // test the rectangle outline drawing - there should be one pixel between
720 // the rect and the lines
721 dc
.SetPen(*wxWHITE_PEN
);
722 dc
.SetBrush( *wxTRANSPARENT_BRUSH
);
723 dc
.DrawRoundedRectangle(150, 270, 49, 29, 6);
724 dc
.DrawRoundedRectangle(200, 270, 49, 29, 6);
725 dc
.SetPen(*wxWHITE_PEN
);
726 dc
.DrawLine(250, 270, 250, 310);
727 dc
.DrawLine(150, 300, 260, 300);
729 // test the rectangle filled drawing - there should be one pixel between
730 // the rect and the lines
731 dc
.SetPen(*wxTRANSPARENT_PEN
);
732 dc
.SetBrush( *wxWHITE_BRUSH
);
733 dc
.DrawRoundedRectangle(300, 270, 49, 29, 6);
734 dc
.DrawRoundedRectangle(350, 270, 49, 29, 6);
735 dc
.SetPen(*wxWHITE_PEN
);
736 dc
.DrawLine(400, 270, 400, 310);
737 dc
.DrawLine(300, 300, 410, 300);
739 // Added by JACS to demonstrate bizarre behaviour.
740 // With a size of 70, we get a missing red RHS,
741 // and the hight is too small, so we get yellow
742 // showing. With a size of 40, it draws as expected:
743 // it just shows a white rectangle with red outline.
745 int totalHeight
= 70;
746 wxBitmap
bitmap2(totalWidth
, totalHeight
);
749 memdc2
.SelectObject(bitmap2
);
751 wxBrush
yellowBrush(wxColour(255, 255, 0), wxSOLID
);
752 memdc2
.SetBackground(yellowBrush
);
755 wxPen
yellowPen(wxColour(255, 255, 0), 1, wxSOLID
);
757 // Now draw a white rectangle with red outline. It should
758 // entirely eclipse the yellow background.
759 memdc2
.SetPen(*wxRED_PEN
);
760 memdc2
.SetBrush(*wxWHITE_BRUSH
);
762 memdc2
.DrawRectangle(0, 0, totalWidth
, totalHeight
);
764 memdc2
.SetPen(wxNullPen
);
765 memdc2
.SetBrush(wxNullBrush
);
766 memdc2
.SelectObject(wxNullBitmap
);
768 dc
.DrawBitmap(bitmap2
, 500, 270);
770 // Repeat, but draw directly on dc
771 // Draw a yellow rectangle filling the bitmap
773 x
= 600; int y
= 270;
774 dc
.SetPen(yellowPen
);
775 dc
.SetBrush(yellowBrush
);
776 dc
.DrawRectangle(x
, y
, totalWidth
, totalHeight
);
778 // Now draw a white rectangle with red outline. It should
779 // entirely eclipse the yellow background.
780 dc
.SetPen(*wxRED_PEN
);
781 dc
.SetBrush(*wxWHITE_BRUSH
);
783 dc
.DrawRectangle(x
, y
, totalWidth
, totalHeight
);
786 void MyCanvas::DrawText(wxDC
& dc
)
788 // set underlined font for testing
789 dc
.SetFont( wxFont(12, wxMODERN
, wxNORMAL
, wxNORMAL
, TRUE
) );
790 dc
.DrawText( "This is text", 110, 10 );
791 dc
.DrawRotatedText( "That is text", 20, 10, -45 );
793 dc
.SetFont( *wxNORMAL_FONT
);
796 dc
. SetBackgroundMode(wxTRANSPARENT
);
798 for ( int n
= -180; n
< 180; n
+= 30 )
800 text
.Printf(" %d rotated text", n
);
801 dc
.DrawRotatedText(text
, 400, 400, n
);
804 dc
.SetFont( wxFont( 18, wxSWISS
, wxNORMAL
, wxNORMAL
) );
806 dc
.DrawText( "This is Swiss 18pt text.", 110, 40 );
811 dc
.GetTextExtent( "This is Swiss 18pt text.", &length
, &height
, &descent
);
812 text
.Printf( "Dimensions are length %ld, height %ld, descent %ld", length
, height
, descent
);
813 dc
.DrawText( text
, 110, 80 );
815 text
.Printf( "CharHeight() returns: %d", dc
.GetCharHeight() );
816 dc
.DrawText( text
, 110, 120 );
818 dc
.DrawRectangle( 100, 40, 4, height
);
825 } rasterOperations
[] =
828 { "wxAND_INVERT", wxAND_INVERT
},
829 { "wxAND_REVERSE", wxAND_REVERSE
},
830 { "wxCLEAR", wxCLEAR
},
831 { "wxCOPY", wxCOPY
},
832 { "wxEQUIV", wxEQUIV
},
833 { "wxINVERT", wxINVERT
},
834 { "wxNAND", wxNAND
},
835 { "wxNO_OP", wxNO_OP
},
837 { "wxOR_INVERT", wxOR_INVERT
},
838 { "wxOR_REVERSE", wxOR_REVERSE
},
840 { "wxSRC_INVERT", wxSRC_INVERT
},
844 void MyCanvas::DrawImages(wxDC
& dc
)
846 dc
.DrawText("original image", 0, 0);
847 dc
.DrawBitmap(gs_bmpNoMask
, 0, 20, 0);
848 dc
.DrawText("with colour mask", 0, 100);
849 dc
.DrawBitmap(gs_bmpWithColMask
, 0, 120, TRUE
);
850 dc
.DrawText("the mask image", 0, 200);
851 dc
.DrawBitmap(gs_bmpMask
, 0, 220, 0);
852 dc
.DrawText("masked image", 0, 300);
853 dc
.DrawBitmap(gs_bmpWithMask
, 0, 320, TRUE
);
855 int cx
= gs_bmpWithColMask
.GetWidth(),
856 cy
= gs_bmpWithColMask
.GetHeight();
859 for ( size_t n
= 0; n
< WXSIZEOF(rasterOperations
); n
++ )
861 wxCoord x
= 120 + 150*(n%4
),
864 dc
.DrawText(rasterOperations
[n
].name
, x
, y
- 20);
865 memDC
.SelectObject(gs_bmpWithColMask
);
866 dc
.Blit(x
, y
, cx
, cy
, &memDC
, 0, 0, rasterOperations
[n
].rop
, TRUE
);
870 void MyCanvas::DrawWithLogicalOps(wxDC
& dc
)
872 static const wxCoord w
= 60;
873 static const wxCoord h
= 60;
875 // reuse the text colour here
876 dc
.SetPen(wxPen(m_owner
->m_colourForeground
, 1, wxSOLID
));
877 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
880 for ( n
= 0; n
< WXSIZEOF(rasterOperations
); n
++ )
882 wxCoord x
= 20 + 150*(n%4
),
885 dc
.DrawText(rasterOperations
[n
].name
, x
, y
- 20);
886 dc
.SetLogicalFunction(rasterOperations
[n
].rop
);
887 dc
.DrawRectangle(x
, y
, w
, h
);
888 dc
.DrawLine(x
, y
, x
+ w
, y
+ h
);
889 dc
.DrawLine(x
+ w
, y
, x
, y
+ h
);
892 // now some filled rectangles
893 dc
.SetBrush(wxBrush(m_owner
->m_colourForeground
, wxSOLID
));
895 for ( n
= 0; n
< WXSIZEOF(rasterOperations
); n
++ )
897 wxCoord x
= 20 + 150*(n%4
),
900 dc
.DrawText(rasterOperations
[n
].name
, x
, y
- 20);
901 dc
.SetLogicalFunction(rasterOperations
[n
].rop
);
902 dc
.DrawRectangle(x
, y
, w
, h
);
906 void MyCanvas::DrawRegions(wxDC
& dc
)
908 dc
.SetBrush( *wxWHITE_BRUSH
);
909 dc
.SetPen( *wxTRANSPARENT_PEN
);
910 dc
.DrawRectangle( 10,10,310,310 );
912 dc
.SetClippingRegion( 20,20,100,270 );
914 dc
.SetBrush( *wxRED_BRUSH
);
915 dc
.DrawRectangle( 10,10,310,310 );
917 dc
.SetClippingRegion( 20,20,100,100 );
919 dc
.SetBrush( *wxCYAN_BRUSH
);
920 dc
.DrawRectangle( 10,10,310,310 );
922 dc
.DestroyClippingRegion();
923 dc
.SetClippingRegion( 120,30,100,270 );
925 dc
.SetBrush( *wxGREY_BRUSH
);
926 dc
.DrawRectangle( 10,10,310,310 );
928 if (m_smile_bmp
.Ok())
930 dc
.DrawBitmap( m_smile_bmp
, 140, 20, TRUE
);
931 dc
.DrawBitmap( m_smile_bmp
, 140, 290, TRUE
);
932 dc
.DrawBitmap( m_smile_bmp
, 110, 80, TRUE
);
933 dc
.DrawBitmap( m_smile_bmp
, 210, 80, TRUE
);
937 void MyCanvas::OnPaint(wxPaintEvent
&WXUNUSED(event
))
941 m_owner
->PrepareDC(dc
);
943 dc
.SetBackgroundMode( m_owner
->m_backgroundMode
);
944 if ( m_owner
->m_backgroundBrush
.Ok() )
945 dc
.SetBackground( m_owner
->m_backgroundBrush
);
946 if ( m_owner
->m_colourForeground
.Ok() )
947 dc
.SetTextForeground( m_owner
->m_colourForeground
);
948 if ( m_owner
->m_colourBackground
.Ok() )
949 dc
.SetTextBackground( m_owner
->m_colourBackground
);
951 if ( m_owner
->m_textureBackground
) {
952 if ( ! m_owner
->m_backgroundBrush
.Ok() ) {
953 wxBrush
b(wxColour(0,128,0), wxSOLID
);
960 if ( m_owner
->m_textureBackground
) {
961 dc
.SetPen(*wxMEDIUM_GREY_PEN
);
962 for (int i
=0; i
<200; i
++)
963 dc
.DrawLine(0, i
*10, i
*10, 0);
981 DrawTestLines( 0, 100, 0, dc
);
982 DrawTestLines( 0, 300, 1, dc
);
983 DrawTestLines( 0, 500, 2, dc
);
984 DrawTestLines( 0, 700, 6, dc
);
988 DrawTestPoly( 0, 100, dc
, 0 );
990 DrawTestPoly( 33, 500, dc, 1 );
991 DrawTestPoly( 43, 1000, dc, 2 );
1000 DrawWithLogicalOps(dc
);
1005 void MyCanvas::OnMouseMove(wxMouseEvent
&event
)
1007 wxClientDC
dc(this);
1009 m_owner
->PrepareDC(dc
);
1011 wxPoint pos
= event
.GetPosition();
1012 long x
= dc
.DeviceToLogicalX( pos
.x
);
1013 long y
= dc
.DeviceToLogicalY( pos
.y
);
1015 str
.Printf( "Current mouse position: %d,%d", (int)x
, (int)y
);
1016 m_owner
->SetStatusText( str
);
1019 // ----------------------------------------------------------------------------
1021 // ----------------------------------------------------------------------------
1023 // the event tables connect the wxWindows events with the functions (event
1024 // handlers) which process them. It can be also done at run-time, but for the
1025 // simple menu events like this the static method is much simpler.
1026 BEGIN_EVENT_TABLE(MyFrame
, wxFrame
)
1027 EVT_MENU (File_Quit
, MyFrame::OnQuit
)
1028 EVT_MENU (File_About
, MyFrame::OnAbout
)
1030 EVT_MENU_RANGE(MenuShow_First
, MenuShow_Last
, MyFrame::OnShow
)
1032 EVT_MENU_RANGE(MenuOption_First
, MenuOption_Last
, MyFrame::OnOption
)
1035 // frame constructor
1036 MyFrame::MyFrame(const wxString
& title
, const wxPoint
& pos
, const wxSize
& size
)
1037 : wxFrame((wxFrame
*)NULL
, -1, title
, pos
, size
)
1039 // set the frame icon
1040 SetIcon(wxICON(mondrian
));
1042 wxMenu
*menuFile
= new wxMenu
;
1043 menuFile
->Append(File_ShowDefault
, "&Default screen\tF1");
1044 menuFile
->Append(File_ShowText
, "&Text screen\tF2");
1045 menuFile
->Append(File_ShowLines
, "&Lines screen\tF3");
1046 menuFile
->Append(File_ShowPolygons
, "&Polygons screen\tF4");
1047 menuFile
->Append(File_ShowMask
, "wx&Mask screen\tF5");
1048 menuFile
->Append(File_ShowOps
, "&ROP screen\tF6");
1049 menuFile
->Append(File_ShowRegions
, "Re&gions screen\tF6");
1050 menuFile
->AppendSeparator();
1051 menuFile
->Append(File_About
, "&About...\tCtrl-A", "Show about dialog");
1052 menuFile
->AppendSeparator();
1053 menuFile
->Append(File_Quit
, "E&xit\tAlt-X", "Quit this program");
1055 wxMenu
*menuMapMode
= new wxMenu
;
1056 menuMapMode
->Append( MapMode_Text
, "&TEXT map mode" );
1057 menuMapMode
->Append( MapMode_Lometric
, "&LOMETRIC map mode" );
1058 menuMapMode
->Append( MapMode_Twips
, "T&WIPS map mode" );
1059 menuMapMode
->Append( MapMode_Points
, "&POINTS map mode" );
1060 menuMapMode
->Append( MapMode_Metric
, "&METRIC map mode" );
1062 wxMenu
*menuUserScale
= new wxMenu
;
1063 menuUserScale
->Append( UserScale_StretchHoriz
, "Stretch horizontally\tCtrl-H" );
1064 menuUserScale
->Append( UserScale_ShrinkHoriz
, "Shrink horizontally\tCtrl-G" );
1065 menuUserScale
->Append( UserScale_StretchVertic
, "Stretch vertically\tCtrl-V" );
1066 menuUserScale
->Append( UserScale_ShrinkVertic
, "Shrink vertically\tCtrl-W" );
1067 menuUserScale
->AppendSeparator();
1068 menuUserScale
->Append( UserScale_Restore
, "Restore to normal\tCtrl-0" );
1070 wxMenu
*menuAxis
= new wxMenu
;
1071 menuAxis
->Append( AxisMirror_Horiz
, "Mirror horizontally\tCtrl-M", "", TRUE
);
1072 menuAxis
->Append( AxisMirror_Vertic
, "Mirror vertically\tCtrl-N", "", TRUE
);
1074 wxMenu
*menuLogical
= new wxMenu
;
1075 menuLogical
->Append( LogicalOrigin_MoveDown
, "Move &down\tCtrl-D" );
1076 menuLogical
->Append( LogicalOrigin_MoveUp
, "Move &up\tCtrl-U" );
1077 menuLogical
->Append( LogicalOrigin_MoveLeft
, "Move &right\tCtrl-L" );
1078 menuLogical
->Append( LogicalOrigin_MoveRight
, "Move &left\tCtrl-R" );
1080 wxMenu
*menuColour
= new wxMenu
;
1081 menuColour
->Append( Colour_TextForeground
, "Text foreground..." );
1082 menuColour
->Append( Colour_TextBackground
, "Text background..." );
1083 menuColour
->Append( Colour_Background
, "Background colour..." );
1084 menuColour
->Append( Colour_BackgroundMode
, "Opaque/transparent\tCtrl-B", "", TRUE
);
1085 menuColour
->Append( Colour_TextureBackgound
, "Draw textured background\tCtrl-T", "", TRUE
);
1087 // now append the freshly created menu to the menu bar...
1088 wxMenuBar
*menuBar
= new wxMenuBar
;
1089 menuBar
->Append(menuFile
, "&File");
1090 menuBar
->Append(menuMapMode
, "&MapMode");
1091 menuBar
->Append(menuUserScale
, "&UserScale");
1092 menuBar
->Append(menuAxis
, "&Axis");
1093 menuBar
->Append(menuLogical
, "&LogicalOrigin");
1094 menuBar
->Append(menuColour
, "&Colours");
1096 // ... and attach this menu bar to the frame
1097 SetMenuBar(menuBar
);
1099 // create a status bar just for fun (by default with 1 pane only)
1101 SetStatusText("Welcome to wxWindows!");
1103 m_mapMode
= wxMM_TEXT
;
1106 m_xLogicalOrigin
= 0;
1107 m_yLogicalOrigin
= 0;
1109 m_yAxisReversed
= FALSE
;
1110 m_backgroundMode
= wxSOLID
;
1111 m_colourForeground
= *wxRED
;
1112 m_colourBackground
= *wxBLUE
;
1113 m_textureBackground
= FALSE
;
1115 m_canvas
= new MyCanvas( this );
1116 m_canvas
->SetScrollbars( 10, 10, 100, 240 );
1121 void MyFrame::OnQuit(wxCommandEvent
& WXUNUSED(event
))
1123 // TRUE is to force the frame to close
1127 void MyFrame::OnAbout(wxCommandEvent
& WXUNUSED(event
))
1130 msg
.Printf( wxT("This is the about dialog of the drawing sample.\n")
1131 wxT("This sample tests various primitive drawing functions\n")
1132 wxT("without any tests to prevent flicker.\n")
1133 wxT("Copyright (c) Robert Roebling 1999")
1136 wxMessageBox(msg
, "About Drawing", wxOK
| wxICON_INFORMATION
, this);
1139 void MyFrame::OnShow(wxCommandEvent
& event
)
1141 m_canvas
->Show((ScreenToShow
)(event
.GetInt() - MenuShow_First
));
1144 void MyFrame::OnOption(wxCommandEvent
& event
)
1146 switch (event
.GetInt())
1149 m_mapMode
= wxMM_TEXT
;
1151 case MapMode_Lometric
:
1152 m_mapMode
= wxMM_LOMETRIC
;
1155 m_mapMode
= wxMM_TWIPS
;
1157 case MapMode_Points
:
1158 m_mapMode
= wxMM_POINTS
;
1160 case MapMode_Metric
:
1161 m_mapMode
= wxMM_METRIC
;
1164 case LogicalOrigin_MoveDown
:
1165 m_yLogicalOrigin
+= 10;
1167 case LogicalOrigin_MoveUp
:
1168 m_yLogicalOrigin
-= 10;
1170 case LogicalOrigin_MoveLeft
:
1171 m_xLogicalOrigin
+= 10;
1173 case LogicalOrigin_MoveRight
:
1174 m_xLogicalOrigin
-= 10;
1177 case UserScale_StretchHoriz
:
1178 m_xUserScale
*= 1.10;
1180 case UserScale_ShrinkHoriz
:
1181 m_xUserScale
/= 1.10;
1183 case UserScale_StretchVertic
:
1184 m_yUserScale
*= 1.10;
1186 case UserScale_ShrinkVertic
:
1187 m_yUserScale
/= 1.10;
1189 case UserScale_Restore
:
1194 case AxisMirror_Vertic
:
1195 m_yAxisReversed
= !m_yAxisReversed
;
1197 case AxisMirror_Horiz
:
1198 m_xAxisReversed
= !m_xAxisReversed
;
1201 case Colour_TextForeground
:
1202 m_colourForeground
= SelectColour();
1204 case Colour_TextBackground
:
1205 m_colourBackground
= SelectColour();
1207 case Colour_Background
:
1209 wxColour col
= SelectColour();
1212 m_backgroundBrush
.SetColour(col
);
1216 case Colour_BackgroundMode
:
1217 m_backgroundMode
= m_backgroundMode
== wxSOLID
? wxTRANSPARENT
1221 case Colour_TextureBackgound
:
1222 m_textureBackground
= ! m_textureBackground
;
1230 m_canvas
->Refresh();
1233 void MyFrame::PrepareDC(wxDC
& dc
)
1235 dc
.SetMapMode( m_mapMode
);
1236 dc
.SetUserScale( m_xUserScale
, m_yUserScale
);
1237 dc
.SetLogicalOrigin( m_xLogicalOrigin
, m_yLogicalOrigin
);
1238 dc
.SetAxisOrientation( !m_xAxisReversed
, m_yAxisReversed
);
1241 wxColour
MyFrame::SelectColour()
1245 wxColourDialog
dialog(this, &data
);
1247 if ( dialog
.ShowModal() == wxID_OK
)
1249 col
= dialog
.GetColourData().GetColour();