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
,
78 // ----------------------------------------------------------------------------
80 // ----------------------------------------------------------------------------
82 // Define a new application type, each program should derive a class from wxApp
83 class MyApp
: public wxApp
86 // override base class virtuals
87 // ----------------------------
89 // this one is called on application startup and is a good place for the app
90 // initialization (doing it here and not in the ctor allows to have an error
91 // return: if OnInit() returns false, the application terminates)
92 virtual bool OnInit();
100 // Define a new frame type: this is going to be our main frame
101 class MyFrame
: public wxFrame
105 MyFrame(const wxString
& title
, const wxPoint
& pos
, const wxSize
& size
);
107 // event handlers (these functions should _not_ be virtual)
108 void OnQuit(wxCommandEvent
& event
);
109 void OnAbout(wxCommandEvent
& event
);
110 void OnShow(wxCommandEvent
&event
);
111 void OnOption(wxCommandEvent
&event
);
113 wxColour
SelectColour();
114 void PrepareDC(wxDC
& dc
);
116 int m_backgroundMode
;
117 int m_textureBackground
;
121 int m_xLogicalOrigin
;
122 int m_yLogicalOrigin
;
123 bool m_xAxisReversed
,
125 wxColour m_colourForeground
, // these are _text_ colours
127 wxBrush m_backgroundBrush
;
131 // any class wishing to process wxWindows events must use this macro
132 DECLARE_EVENT_TABLE()
135 // define a scrollable canvas for drawing onto
136 class MyCanvas
: public wxScrolledWindow
139 MyCanvas( MyFrame
*parent
);
141 void OnPaint(wxPaintEvent
&event
);
142 void OnMouseMove(wxMouseEvent
&event
);
144 void Show(ScreenToShow show
) { m_show
= show
; Refresh(); }
147 void DrawTestPoly( int x
, int y
, wxDC
&dc
,int transparent
);
148 void DrawTestLines( int x
, int y
, int width
, wxDC
&dc
);
149 void DrawText(wxDC
& dc
);
150 void DrawImages(wxDC
& dc
);
151 void DrawWithLogicalOps(wxDC
& dc
);
152 void DrawRegions(wxDC
& dc
);
153 void DrawDefault(wxDC
& dc
);
159 wxBitmap m_smile_bmp
;
162 DECLARE_EVENT_TABLE()
165 // ----------------------------------------------------------------------------
167 // ----------------------------------------------------------------------------
169 // IDs for the controls and the menu commands
177 File_ShowDefault
= MenuShow_First
,
184 MenuShow_Last
= File_ShowRegions
,
188 MapMode_Text
= MenuOption_First
,
194 UserScale_StretchHoriz
,
195 UserScale_ShrinkHoriz
,
196 UserScale_StretchVertic
,
197 UserScale_ShrinkVertic
,
203 LogicalOrigin_MoveDown
,
204 LogicalOrigin_MoveUp
,
205 LogicalOrigin_MoveLeft
,
206 LogicalOrigin_MoveRight
,
208 Colour_TextForeground
,
209 Colour_TextBackground
,
211 Colour_BackgroundMode
,
212 Colour_TextureBackgound
,
214 MenuOption_Last
= Colour_TextureBackgound
217 // ----------------------------------------------------------------------------
218 // event tables and other macros for wxWindows
219 // ----------------------------------------------------------------------------
222 // Create a new application object: this macro will allow wxWindows to create
223 // the application object during program execution (it's better than using a
224 // static object for many reasons) and also declares the accessor function
225 // wxGetApp() which will return the reference of the right type (i.e. MyApp and
229 // ============================================================================
231 // ============================================================================
233 // ----------------------------------------------------------------------------
234 // the application class
235 // ----------------------------------------------------------------------------
237 bool MyApp::LoadImages()
243 wxString path
= pathList
.FindValidPath("pat4.bmp");
246 gs_bmp4
.LoadFile(path
, wxBITMAP_TYPE_BMP
);
247 wxMask
* mask4
= new wxMask(gs_bmp4
, *wxBLACK
);
248 gs_bmp4
.SetMask(mask4
);
250 path
= pathList
.FindValidPath("pat36.bmp");
253 gs_bmp36
.LoadFile(path
, wxBITMAP_TYPE_BMP
);
254 wxMask
* mask36
= new wxMask(gs_bmp36
, *wxBLACK
);
255 gs_bmp36
.SetMask(mask36
);
257 path
= pathList
.FindValidPath("image.bmp");
260 gs_bmpNoMask
.LoadFile(path
, wxBITMAP_TYPE_BMP
);
261 gs_bmpWithMask
.LoadFile(path
, wxBITMAP_TYPE_BMP
);
262 gs_bmpWithColMask
.LoadFile(path
, wxBITMAP_TYPE_BMP
);
264 path
= pathList
.FindValidPath("mask.bmp");
267 gs_bmpMask
.LoadFile(path
, wxBITMAP_TYPE_BMP
);
269 // This is so wrong, it hurts.
270 // gs_bmpMask.SetDepth(1);
271 // wxMask *mask = new wxMask(gs_bmpMask);
273 wxMask
*mask
= new wxMask(gs_bmpMask
, *wxBLACK
);
274 gs_bmpWithMask
.SetMask(mask
);
276 mask
= new wxMask(gs_bmpWithColMask
, *wxWHITE
);
277 gs_bmpWithColMask
.SetMask(mask
);
282 // `Main program' equivalent: the program execution "starts" here
285 // Create the main application window
286 MyFrame
*frame
= new MyFrame("Drawing sample",
287 wxPoint(50, 50), wxSize(550, 340));
289 // Show it and tell the application that it's our main window
295 wxLogError("Can't load one of the bitmap files needed for this sample "
296 "from the current or parent directory, please copy them "
307 // ----------------------------------------------------------------------------
309 // ----------------------------------------------------------------------------
311 // the event tables connect the wxWindows events with the functions (event
312 // handlers) which process them.
313 BEGIN_EVENT_TABLE(MyCanvas
, wxScrolledWindow
)
314 EVT_PAINT (MyCanvas::OnPaint
)
315 EVT_MOTION (MyCanvas::OnMouseMove
)
318 #include "../image/smile.xpm"
320 MyCanvas::MyCanvas( MyFrame
*parent
) : wxScrolledWindow( parent
)
323 m_show
= Show_Default
;
324 m_smile_bmp
= wxBitmap(smile_xpm
);
325 m_std_icon
= wxTheApp
->GetStdIcon(wxICON_INFORMATION
);
328 //draw a polygon and an overlapping rectangle
329 //is transparent is 1, the fill pattern are made transparent
330 //is transparent is 2, the fill pattern are made transparent but inversed
331 //is transparent is 0 the text for and background color will be used to represent/map
332 //the colors of the monochrome bitmap pixels to the fillpattern
334 //i miss_used the the menu items for setting so called back and fore ground color
335 //just to show how the those colors do influence the fillpatterns
336 //just play with those,
338 //variations are endless using other logical functions
339 void MyCanvas::DrawTestPoly( int x
, int y
,wxDC
&dc
,int transparent
)
341 wxBrush
* brush4
= new wxBrush(gs_bmp4
);
342 wxBrush
* brush36
= new wxBrush(gs_bmp36
);
345 todraw
[0].x
=(long)x
+100;
346 todraw
[0].y
=(long)y
+100;
347 todraw
[1].x
=(long)x
+300;
348 todraw
[1].y
=(long)y
+100;
349 todraw
[2].x
=(long)x
+300;
350 todraw
[2].y
=(long)y
+300;
351 todraw
[3].x
=(long)x
+150;
352 todraw
[3].y
=(long)y
+350;
353 todraw
[4].x
=(long)x
+100;
354 todraw
[4].y
=(long)y
+300;
372 dc
.SetPen( wxPen( "black", 4, wxSOLID
) );
373 dc
.SetBrush( *brush4
);
374 dc
.SetTextForeground(*wxGREEN
);
375 dc
.SetTextBackground(m_owner
->m_colourForeground
);
376 dc
.SetLogicalFunction(wxCOPY
);
377 dc
.DrawPolygon(5,todraw
,0,0,wxWINDING_RULE
);
379 //don't understand hwo but the outline is also depending on logicalfunction
380 dc
.SetPen( wxPen( "red", 4, wxSOLID
) );
381 dc
.SetBrush( *brush36
);
382 dc
.SetTextForeground(*wxCYAN
);
383 dc
.SetTextBackground(m_owner
->m_colourBackground
);
384 dc
.SetLogicalFunction(wxCOPY
);
385 dc
.DrawRectangle( x
+10, y
+10, 200, 200 );
386 dc
.SetBrush(wxNullBrush
);
387 dc
.SetPen(wxNullPen
);
390 case 1: //now with transparent fillpatterns
393 wxBitmap
* bmpBlit
= new wxBitmap(600,400);
394 wxMemoryDC
* memDC
= new wxMemoryDC();
395 // wxBrush _clearbrush(*wxGREEN,wxSOLID);
396 wxBrush
_clearbrush(*wxBLACK
,wxSOLID
);
397 memDC
->SelectObject(*bmpBlit
);
398 memDC
->BeginDrawing();
399 memDC
->SetBackground(_clearbrush
);
401 memDC
->SetBackground(wxNullBrush
);
403 memDC
->SetPen( wxPen( "black", 4, wxSOLID
) );
404 memDC
->SetBrush( wxNullBrush
);
405 memDC
->SetBrush( *brush4
);
406 memDC
->SetTextForeground(*wxBLACK
); // 0s --> 0x000000 (black)
407 memDC
->SetTextBackground(*wxWHITE
); // 1s --> 0xFFFFFF (white)
408 memDC
->SetLogicalFunction(wxAND_INVERT
);
410 // BLACK OUT the opaque pixels and leave the rest as is
411 memDC
->DrawPolygon(5,todraw2
,0,0,wxWINDING_RULE
);
413 // Set background and foreground colors for fill pattern
414 //the previous blacked out pixels are now merged with the layer color
415 //while the non blacked out pixels stay as they are.
416 memDC
->SetTextForeground(*wxBLACK
); // 0s --> 0x000000 (black)
418 //now define what will be the color of the fillpattern parts that are not transparent
419 // memDC->SetTextBackground(*wxBLUE);
420 memDC
->SetTextBackground(m_owner
->m_colourForeground
);
421 memDC
->SetLogicalFunction(wxOR
);
424 //don't understand how but the outline is also depending on logicalfunction
425 memDC
->SetPen( wxPen( "red", 4, wxSOLID
) );
426 memDC
->DrawPolygon(5,todraw2
,0,0,wxWINDING_RULE
);
428 memDC
->SetLogicalFunction(wxCOPY
);
430 memDC
->SetPen( wxPen( "black", 4, wxSOLID
) );
431 memDC
->SetBrush( wxNullBrush
);
432 memDC
->SetBrush( *brush36
);
433 memDC
->SetTextForeground(*wxBLACK
); // 0s --> 0x000000 (black)
434 memDC
->SetTextBackground(*wxWHITE
); // 1s --> 0xFFFFFF (white)
435 memDC
->SetLogicalFunction(wxAND_INVERT
);
437 memDC
->DrawRectangle( 10, 10, 200, 200 );
439 // Set background and foreground colors for fill pattern
440 //the previous blacked out pixels are now merged with the layer color
441 //while the non blacked out pixels stay as they are.
442 memDC
->SetTextForeground(*wxBLACK
); // 0s --> 0x000000 (black)
443 //now define what will be the color of the fillpattern parts that are not transparent
444 // memDC->SetTextBackground(*wxRED);
445 memDC
->SetTextBackground(m_owner
->m_colourBackground
);
446 memDC
->SetLogicalFunction(wxOR
);
448 //don't understand how but the outline is also depending on logicalfunction
449 memDC
->SetPen( wxPen( "yellow", 4, wxSOLID
) );
450 memDC
->DrawRectangle( 10, 10, 200, 200 );
452 memDC
->SetBrush(wxNullBrush
);
453 memDC
->SetPen(wxNullPen
);
456 dc
.Blit(x
,y
,600,400,memDC
,0,0,wxCOPY
);
461 case 2: //now with transparent inversed fillpatterns
463 wxBitmap
* bmpBlit
= new wxBitmap(600,400);
464 wxMemoryDC
* memDC
= new wxMemoryDC();
465 wxBrush
_clearbrush(*wxWHITE
,wxSOLID
);
466 memDC
->SelectObject(*bmpBlit
);
467 memDC
->BeginDrawing();
468 memDC
->SetBackground(_clearbrush
);
470 memDC
->SetBackground(wxNullBrush
);
472 memDC
->SetPen( wxPen( "black", 4, wxSOLID
) );
473 memDC
->SetBrush( *brush4
);
474 memDC
->SetTextBackground(*wxBLACK
); // 0s --> 0x000000 (black)
475 memDC
->SetTextForeground(*wxWHITE
); // 1s --> 0xFFFFFF (white)
476 memDC
->SetLogicalFunction(wxAND_INVERT
);
478 // BLACK OUT the opaque pixels and leave the rest as is
479 memDC
->DrawPolygon(5,todraw2
,0,0,wxWINDING_RULE
);
481 // Set background and foreground colors for fill pattern
482 //the previous blacked out pixels are now merged with the layer color
483 //while the non blacked out pixels stay as they are.
484 memDC
->SetTextBackground(*wxBLACK
); // 0s --> 0x000000 (black)
486 //now define what will be the color of the fillpattern parts that are not transparent
487 memDC
->SetTextForeground(m_owner
->m_colourForeground
);
488 memDC
->SetLogicalFunction(wxOR
);
491 //don't understand how but the outline is also depending on logicalfunction
492 memDC
->SetPen( wxPen( "red", 4, wxSOLID
) );
493 memDC
->DrawPolygon(5,todraw2
,0,0,wxWINDING_RULE
);
495 memDC
->SetLogicalFunction(wxCOPY
);
497 memDC
->SetPen( wxPen( "black", 4, wxSOLID
) );
498 memDC
->SetBrush( *brush36
);
499 memDC
->SetTextBackground(*wxBLACK
); // 0s --> 0x000000 (black)
500 memDC
->SetTextForeground(*wxWHITE
); // 1s --> 0xFFFFFF (white)
501 memDC
->SetLogicalFunction(wxAND_INVERT
);
503 memDC
->DrawRectangle( 10,10, 200, 200 );
505 // Set background and foreground colors for fill pattern
506 //the previous blacked out pixels are now merged with the layer color
507 //while the non blacked out pixels stay as they are.
508 memDC
->SetTextBackground(*wxBLACK
); // 0s --> 0x000000 (black)
509 //now define what will be the color of the fillpattern parts that are not transparent
510 memDC
->SetTextForeground(m_owner
->m_colourBackground
);
511 memDC
->SetLogicalFunction(wxOR
);
513 //don't understand how but the outline is also depending on logicalfunction
514 memDC
->SetPen( wxPen( "yellow", 4, wxSOLID
) );
515 memDC
->DrawRectangle( 10, 10, 200, 200 );
517 memDC
->SetBrush(wxNullBrush
);
518 memDC
->SetPen(wxNullPen
);
519 dc
.Blit(x
,y
,600,400,memDC
,0,0,wxCOPY
);
529 void MyCanvas::DrawTestLines( int x
, int y
, int width
, wxDC
&dc
)
531 dc
.SetPen( wxPen( "black", width
, wxSOLID
) );
532 dc
.SetBrush( *wxRED_BRUSH
);
533 dc
.DrawRectangle( x
+10, y
+10, 100, 190 );
535 dc
.SetPen( wxPen( "black", width
, wxSOLID
) );
536 dc
.DrawLine( x
+20, y
+20, 100, y
+20 );
537 dc
.SetPen( wxPen( "black", width
, wxDOT
) );
538 dc
.DrawLine( x
+20, y
+30, 100, y
+30 );
539 dc
.SetPen( wxPen( "black", width
, wxSHORT_DASH
) );
540 dc
.DrawLine( x
+20, y
+40, 100, y
+40 );
541 dc
.SetPen( wxPen( "black", width
, wxLONG_DASH
) );
542 dc
.DrawLine( x
+20, y
+50, 100, y
+50 );
543 dc
.SetPen( wxPen( "black", width
, wxDOT_DASH
) );
544 dc
.DrawLine( x
+20, y
+60, 100, y
+60 );
546 dc
.SetPen( wxPen( "black", width
, wxBDIAGONAL_HATCH
) );
547 dc
.DrawLine( x
+20, y
+70, 100, y
+70 );
548 dc
.SetPen( wxPen( "black", width
, wxCROSSDIAG_HATCH
) );
549 dc
.DrawLine( x
+20, y
+80, 100, y
+80 );
550 dc
.SetPen( wxPen( "black", width
, wxFDIAGONAL_HATCH
) );
551 dc
.DrawLine( x
+20, y
+90, 100, y
+90 );
552 dc
.SetPen( wxPen( "black", width
, wxCROSS_HATCH
) );
553 dc
.DrawLine( x
+20, y
+100, 100, y
+100 );
554 dc
.SetPen( wxPen( "black", width
, wxHORIZONTAL_HATCH
) );
555 dc
.DrawLine( x
+20, y
+110, 100, y
+110 );
556 dc
.SetPen( wxPen( "black", width
, wxVERTICAL_HATCH
) );
557 dc
.DrawLine( x
+20, y
+120, 100, y
+120 );
559 wxPen
ud( "black", width
, wxUSER_DASH
);
562 ud
.SetDashes( 1, dash1
);
563 dc
.DrawLine( x
+20, y
+140, 100, y
+140 );
565 ud
.SetDashes( 1, dash1
);
566 dc
.DrawLine( x
+20, y
+150, 100, y
+150 );
568 ud
.SetDashes( 1, dash1
);
569 dc
.DrawLine( x
+20, y
+160, 100, y
+160 );
571 ud
.SetDashes( 1, dash1
);
572 dc
.DrawLine( x
+20, y
+170, 100, y
+170 );
575 void MyCanvas::DrawDefault(wxDC
& dc
)
578 dc
.DrawCircle(0, 0, 10);
579 #if !(defined __WXGTK__) && !(defined __WXMOTIF__)
580 // not implemented in wxGTK or wxMOTIF :-(
581 dc
.FloodFill(0, 0, wxColour(255, 0, 0));
584 dc
.DrawCheckMark(5, 80, 15, 15);
585 dc
.DrawCheckMark(25, 80, 30, 30);
586 dc
.DrawCheckMark(60, 80, 60, 60);
588 // this is the test for "blitting bitmap into DC damages selected brush" bug
589 wxCoord rectSize
= m_std_icon
.GetWidth() + 10;
591 dc
.SetPen(*wxTRANSPARENT_PEN
);
592 dc
.SetBrush( *wxGREEN_BRUSH
);
593 dc
.DrawRectangle(x
, 10, rectSize
, rectSize
);
594 dc
.DrawBitmap(m_std_icon
, x
+ 5, 15, TRUE
);
596 dc
.DrawRectangle(x
, 10, rectSize
, rectSize
);
597 dc
.DrawIcon(m_std_icon
, x
+ 5, 15);
599 dc
.DrawRectangle(x
, 10, rectSize
, rectSize
);
601 // test for "transparent" bitmap drawing (it intersects with the last
603 //dc.SetBrush( *wxTRANSPARENT_BRUSH );
605 if (m_smile_bmp
.Ok())
606 dc
.DrawBitmap(m_smile_bmp
, x
+ rectSize
- 20, rectSize
- 10, TRUE
);
608 dc
.SetBrush( *wxBLACK_BRUSH
);
609 dc
.DrawRectangle( 0, 160, 1000, 300 );
612 wxBitmap
bitmap(20,70);
614 memdc
.SelectObject( bitmap
);
615 memdc
.SetBrush( *wxBLACK_BRUSH
);
616 memdc
.SetPen( *wxWHITE_PEN
);
617 memdc
.DrawRectangle(0,0,20,70);
618 memdc
.DrawLine( 10,0,10,70 );
621 wxPen pen
= *wxRED_PEN
;
623 memdc
.DrawLine( 10, 5,10, 5 );
624 memdc
.DrawLine( 10,10,11,10 );
625 memdc
.DrawLine( 10,15,12,15 );
626 memdc
.DrawLine( 10,20,13,20 );
629 memdc.SetPen(*wxRED_PEN);
630 memdc.DrawLine( 12, 5,12, 5 );
631 memdc.DrawLine( 12,10,13,10 );
632 memdc.DrawLine( 12,15,14,15 );
633 memdc.DrawLine( 12,20,15,20 );
637 memdc
.DrawLine( 10,25,10,25 );
638 memdc
.DrawLine( 10,30, 9,30 );
639 memdc
.DrawLine( 10,35, 8,35 );
640 memdc
.DrawLine( 10,40, 7,40 );
643 dc
.SetPen(*wxWHITE_PEN
);
644 memdc
.SetLogicalFunction( wxINVERT
);
645 memdc
.SetPen( *wxWHITE_PEN
);
646 memdc
.DrawLine( 10,50,10,50 );
647 memdc
.DrawLine( 10,55,11,55 );
648 memdc
.DrawLine( 10,60,12,60 );
649 memdc
.DrawLine( 10,65,13,65 );
651 memdc
.DrawLine( 12,50,12,50 );
652 memdc
.DrawLine( 12,55,13,55 );
653 memdc
.DrawLine( 12,60,14,60 );
654 memdc
.DrawLine( 12,65,15,65 );
656 memdc
.SelectObject( wxNullBitmap
);
657 dc
.DrawBitmap( bitmap
, 10, 170 );
658 wxImage
image( bitmap
);
659 image
.Rescale( 60,210 );
660 bitmap
= image
.ConvertToBitmap();
661 dc
.DrawBitmap( bitmap
, 50, 170 );
663 // test the rectangle outline drawing - there should be one pixel between
664 // the rect and the lines
665 dc
.SetPen(*wxWHITE_PEN
);
666 dc
.SetBrush( *wxTRANSPARENT_BRUSH
);
667 dc
.DrawRectangle(150, 170, 49, 29);
668 dc
.DrawRectangle(200, 170, 49, 29);
669 dc
.SetPen(*wxWHITE_PEN
);
670 dc
.DrawLine(250, 210, 250, 170);
671 dc
.DrawLine(260, 200, 150, 200);
673 // test the rectangle filled drawing - there should be one pixel between
674 // the rect and the lines
675 dc
.SetPen(*wxTRANSPARENT_PEN
);
676 dc
.SetBrush( *wxWHITE_BRUSH
);
677 dc
.DrawRectangle(300, 170, 49, 29);
678 dc
.DrawRectangle(350, 170, 49, 29);
679 dc
.SetPen(*wxWHITE_PEN
);
680 dc
.DrawLine(400, 170, 400, 210);
681 dc
.DrawLine(300, 200, 410, 200);
683 // a few more tests of this kind
684 dc
.SetPen(*wxRED_PEN
);
685 dc
.SetBrush( *wxWHITE_BRUSH
);
686 dc
.DrawRectangle(300, 220, 1, 1);
687 dc
.DrawRectangle(310, 220, 2, 2);
688 dc
.DrawRectangle(320, 220, 3, 3);
689 dc
.DrawRectangle(330, 220, 4, 4);
691 dc
.SetPen(*wxTRANSPARENT_PEN
);
692 dc
.SetBrush( *wxWHITE_BRUSH
);
693 dc
.DrawRectangle(300, 230, 1, 1);
694 dc
.DrawRectangle(310, 230, 2, 2);
695 dc
.DrawRectangle(320, 230, 3, 3);
696 dc
.DrawRectangle(330, 230, 4, 4);
698 // and now for filled rect with outline
699 dc
.SetPen(*wxRED_PEN
);
700 dc
.SetBrush( *wxWHITE_BRUSH
);
701 dc
.DrawRectangle(500, 170, 49, 29);
702 dc
.DrawRectangle(550, 170, 49, 29);
703 dc
.SetPen(*wxWHITE_PEN
);
704 dc
.DrawLine(600, 170, 600, 210);
705 dc
.DrawLine(500, 200, 610, 200);
707 // test the rectangle outline drawing - there should be one pixel between
708 // the rect and the lines
709 dc
.SetPen(*wxWHITE_PEN
);
710 dc
.SetBrush( *wxTRANSPARENT_BRUSH
);
711 dc
.DrawRoundedRectangle(150, 270, 49, 29, 6);
712 dc
.DrawRoundedRectangle(200, 270, 49, 29, 6);
713 dc
.SetPen(*wxWHITE_PEN
);
714 dc
.DrawLine(250, 270, 250, 310);
715 dc
.DrawLine(150, 300, 260, 300);
717 // test the rectangle filled drawing - there should be one pixel between
718 // the rect and the lines
719 dc
.SetPen(*wxTRANSPARENT_PEN
);
720 dc
.SetBrush( *wxWHITE_BRUSH
);
721 dc
.DrawRoundedRectangle(300, 270, 49, 29, 6);
722 dc
.DrawRoundedRectangle(350, 270, 49, 29, 6);
723 dc
.SetPen(*wxWHITE_PEN
);
724 dc
.DrawLine(400, 270, 400, 310);
725 dc
.DrawLine(300, 300, 410, 300);
727 // Added by JACS to demonstrate bizarre behaviour.
728 // With a size of 70, we get a missing red RHS,
729 // and the hight is too small, so we get yellow
730 // showing. With a size of 40, it draws as expected:
731 // it just shows a white rectangle with red outline.
733 int totalHeight
= 70;
734 wxBitmap
bitmap2(totalWidth
, totalHeight
);
737 memdc2
.SelectObject(bitmap2
);
739 wxBrush
yellowBrush(wxColour(255, 255, 0), wxSOLID
);
740 memdc2
.SetBackground(yellowBrush
);
743 wxPen
yellowPen(wxColour(255, 255, 0), 1, wxSOLID
);
745 // Now draw a white rectangle with red outline. It should
746 // entirely eclipse the yellow background.
747 memdc2
.SetPen(*wxRED_PEN
);
748 memdc2
.SetBrush(*wxWHITE_BRUSH
);
750 memdc2
.DrawRectangle(0, 0, totalWidth
, totalHeight
);
752 memdc2
.SetPen(wxNullPen
);
753 memdc2
.SetBrush(wxNullBrush
);
754 memdc2
.SelectObject(wxNullBitmap
);
756 dc
.DrawBitmap(bitmap2
, 500, 270);
758 // Repeat, but draw directly on dc
759 // Draw a yellow rectangle filling the bitmap
761 x
= 600; int y
= 270;
762 dc
.SetPen(yellowPen
);
763 dc
.SetBrush(yellowBrush
);
764 dc
.DrawRectangle(x
, y
, totalWidth
, totalHeight
);
766 // Now draw a white rectangle with red outline. It should
767 // entirely eclipse the yellow background.
768 dc
.SetPen(*wxRED_PEN
);
769 dc
.SetBrush(*wxWHITE_BRUSH
);
771 dc
.DrawRectangle(x
, y
, totalWidth
, totalHeight
);
774 void MyCanvas::DrawText(wxDC
& dc
)
776 // set underlined font for testing
777 dc
.SetFont( wxFont(12, wxMODERN
, wxNORMAL
, wxNORMAL
, TRUE
) );
778 dc
.DrawText( "This is text", 110, 10 );
779 dc
.DrawRotatedText( "That is text", 20, 10, -45 );
781 dc
.SetFont( *wxNORMAL_FONT
);
784 dc
. SetBackgroundMode(wxTRANSPARENT
);
786 for ( int n
= -180; n
< 180; n
+= 30 )
788 text
.Printf(" %d rotated text", n
);
789 dc
.DrawRotatedText(text
, 400, 400, n
);
792 dc
.SetFont( wxFont( 18, wxSWISS
, wxNORMAL
, wxNORMAL
) );
794 dc
.DrawText( "This is Swiss 18pt text.", 110, 40 );
799 dc
.GetTextExtent( "This is Swiss 18pt text.", &length
, &height
, &descent
);
800 text
.Printf( "Dimensions are length %ld, height %ld, descent %ld", length
, height
, descent
);
801 dc
.DrawText( text
, 110, 80 );
803 text
.Printf( "CharHeight() returns: %d", dc
.GetCharHeight() );
804 dc
.DrawText( text
, 110, 120 );
806 dc
.DrawRectangle( 100, 40, 4, height
);
813 } rasterOperations
[] =
816 { "wxAND_INVERT", wxAND_INVERT
},
817 { "wxAND_REVERSE", wxAND_REVERSE
},
818 { "wxCLEAR", wxCLEAR
},
819 { "wxCOPY", wxCOPY
},
820 { "wxEQUIV", wxEQUIV
},
821 { "wxINVERT", wxINVERT
},
822 { "wxNAND", wxNAND
},
823 { "wxNO_OP", wxNO_OP
},
825 { "wxOR_INVERT", wxOR_INVERT
},
826 { "wxOR_REVERSE", wxOR_REVERSE
},
828 { "wxSRC_INVERT", wxSRC_INVERT
},
832 void MyCanvas::DrawImages(wxDC
& dc
)
834 dc
.DrawText("original image", 0, 0);
835 dc
.DrawBitmap(gs_bmpNoMask
, 0, 20, 0);
836 dc
.DrawText("with colour mask", 0, 100);
837 dc
.DrawBitmap(gs_bmpWithColMask
, 0, 120, TRUE
);
838 dc
.DrawText("the mask image", 0, 200);
839 dc
.DrawBitmap(gs_bmpMask
, 0, 220, 0);
840 dc
.DrawText("masked image", 0, 300);
841 dc
.DrawBitmap(gs_bmpWithMask
, 0, 320, TRUE
);
843 int cx
= gs_bmpWithColMask
.GetWidth(),
844 cy
= gs_bmpWithColMask
.GetHeight();
847 for ( size_t n
= 0; n
< WXSIZEOF(rasterOperations
); n
++ )
849 wxCoord x
= 120 + 150*(n%4
),
852 dc
.DrawText(rasterOperations
[n
].name
, x
, y
- 20);
853 memDC
.SelectObject(gs_bmpWithColMask
);
854 dc
.Blit(x
, y
, cx
, cy
, &memDC
, 0, 0, rasterOperations
[n
].rop
, TRUE
);
858 void MyCanvas::DrawWithLogicalOps(wxDC
& dc
)
860 static const wxCoord w
= 60;
861 static const wxCoord h
= 60;
863 // reuse the text colour here
864 dc
.SetPen(wxPen(m_owner
->m_colourForeground
, 1, wxSOLID
));
865 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
868 for ( n
= 0; n
< WXSIZEOF(rasterOperations
); n
++ )
870 wxCoord x
= 20 + 150*(n%4
),
873 dc
.DrawText(rasterOperations
[n
].name
, x
, y
- 20);
874 dc
.SetLogicalFunction(rasterOperations
[n
].rop
);
875 dc
.DrawRectangle(x
, y
, w
, h
);
876 dc
.DrawLine(x
, y
, x
+ w
, y
+ h
);
877 dc
.DrawLine(x
+ w
, y
, x
, y
+ h
);
880 // now some filled rectangles
881 dc
.SetBrush(wxBrush(m_owner
->m_colourForeground
, wxSOLID
));
883 for ( n
= 0; n
< WXSIZEOF(rasterOperations
); n
++ )
885 wxCoord x
= 20 + 150*(n%4
),
888 dc
.DrawText(rasterOperations
[n
].name
, x
, y
- 20);
889 dc
.SetLogicalFunction(rasterOperations
[n
].rop
);
890 dc
.DrawRectangle(x
, y
, w
, h
);
894 void MyCanvas::DrawRegions(wxDC
& dc
)
896 dc
.SetBrush( *wxWHITE_BRUSH
);
897 dc
.SetPen( *wxTRANSPARENT_PEN
);
898 dc
.DrawRectangle( 10,10,310,310 );
900 wxRegion
region( 20,20,100,270 );
901 dc
.SetClippingRegion( region
);
903 dc
.SetBrush( *wxRED_BRUSH
);
904 dc
.DrawRectangle( 10,10,310,310 );
906 region
= wxRegion( 120,30,100,270 );
907 dc
.SetClippingRegion( region
);
909 dc
.SetBrush( *wxGREY_BRUSH
);
910 dc
.DrawRectangle( 10,10,310,310 );
912 if (m_smile_bmp
.Ok())
914 dc
.DrawBitmap( m_smile_bmp
, 140, 20, TRUE
);
915 dc
.DrawBitmap( m_smile_bmp
, 140, 290, TRUE
);
916 dc
.DrawBitmap( m_smile_bmp
, 110, 80, TRUE
);
917 dc
.DrawBitmap( m_smile_bmp
, 210, 80, TRUE
);
921 void MyCanvas::OnPaint(wxPaintEvent
&WXUNUSED(event
))
925 m_owner
->PrepareDC(dc
);
927 dc
.SetBackgroundMode( m_owner
->m_backgroundMode
);
928 if ( m_owner
->m_backgroundBrush
.Ok() )
929 dc
.SetBackground( m_owner
->m_backgroundBrush
);
930 if ( m_owner
->m_colourForeground
.Ok() )
931 dc
.SetTextForeground( m_owner
->m_colourForeground
);
932 if ( m_owner
->m_colourBackground
.Ok() )
933 dc
.SetTextBackground( m_owner
->m_colourBackground
);
935 if ( m_owner
->m_textureBackground
) {
936 if ( ! m_owner
->m_backgroundBrush
.Ok() ) {
937 wxBrush
b(wxColour(0,128,0), wxSOLID
);
944 if ( m_owner
->m_textureBackground
) {
945 dc
.SetPen(*wxMEDIUM_GREY_PEN
);
946 for (int i
=0; i
<200; i
++)
947 dc
.DrawLine(0, i
*10, i
*10, 0);
965 DrawTestLines( 0, 100, 0, dc
);
966 DrawTestLines( 0, 300, 1, dc
);
967 DrawTestLines( 0, 500, 2, dc
);
968 DrawTestLines( 0, 700, 6, dc
);
972 DrawTestPoly( 0, 100, dc
, 0 );
973 DrawTestPoly( 33, 500, dc
, 1 );
974 DrawTestPoly( 43, 1000, dc
, 2 );
982 DrawWithLogicalOps(dc
);
987 void MyCanvas::OnMouseMove(wxMouseEvent
&event
)
991 m_owner
->PrepareDC(dc
);
993 wxPoint pos
= event
.GetPosition();
994 long x
= dc
.DeviceToLogicalX( pos
.x
);
995 long y
= dc
.DeviceToLogicalY( pos
.y
);
997 str
.Printf( "Current mouse position: %d,%d", (int)x
, (int)y
);
998 m_owner
->SetStatusText( str
);
1001 // ----------------------------------------------------------------------------
1003 // ----------------------------------------------------------------------------
1005 // the event tables connect the wxWindows events with the functions (event
1006 // handlers) which process them. It can be also done at run-time, but for the
1007 // simple menu events like this the static method is much simpler.
1008 BEGIN_EVENT_TABLE(MyFrame
, wxFrame
)
1009 EVT_MENU (File_Quit
, MyFrame::OnQuit
)
1010 EVT_MENU (File_About
, MyFrame::OnAbout
)
1012 EVT_MENU_RANGE(MenuShow_First
, MenuShow_Last
, MyFrame::OnShow
)
1014 EVT_MENU_RANGE(MenuOption_First
, MenuOption_Last
, MyFrame::OnOption
)
1017 // frame constructor
1018 MyFrame::MyFrame(const wxString
& title
, const wxPoint
& pos
, const wxSize
& size
)
1019 : wxFrame((wxFrame
*)NULL
, -1, title
, pos
, size
)
1021 // set the frame icon
1022 SetIcon(wxICON(mondrian
));
1024 wxMenu
*menuFile
= new wxMenu
;
1025 menuFile
->Append(File_ShowDefault
, "&Default screen\tF1");
1026 menuFile
->Append(File_ShowText
, "&Text screen\tF2");
1027 menuFile
->Append(File_ShowLines
, "&Lines screen\tF3");
1028 menuFile
->Append(File_ShowPolygons
, "&Polygons screen\tF4");
1029 menuFile
->Append(File_ShowMask
, "wx&Mask screen\tF5");
1030 menuFile
->Append(File_ShowOps
, "&ROP screen\tF6");
1031 menuFile
->Append(File_ShowRegions
, "Re&gions screen\tF6");
1032 menuFile
->AppendSeparator();
1033 menuFile
->Append(File_About
, "&About...\tCtrl-A", "Show about dialog");
1034 menuFile
->AppendSeparator();
1035 menuFile
->Append(File_Quit
, "E&xit\tAlt-X", "Quit this program");
1037 wxMenu
*menuMapMode
= new wxMenu
;
1038 menuMapMode
->Append( MapMode_Text
, "&TEXT map mode" );
1039 menuMapMode
->Append( MapMode_Lometric
, "&LOMETRIC map mode" );
1040 menuMapMode
->Append( MapMode_Twips
, "T&WIPS map mode" );
1041 menuMapMode
->Append( MapMode_Points
, "&POINTS map mode" );
1042 menuMapMode
->Append( MapMode_Metric
, "&METRIC map mode" );
1044 wxMenu
*menuUserScale
= new wxMenu
;
1045 menuUserScale
->Append( UserScale_StretchHoriz
, "Stretch horizontally\tCtrl-H" );
1046 menuUserScale
->Append( UserScale_ShrinkHoriz
, "Shrink horizontally\tCtrl-G" );
1047 menuUserScale
->Append( UserScale_StretchVertic
, "Stretch vertically\tCtrl-V" );
1048 menuUserScale
->Append( UserScale_ShrinkVertic
, "Shrink vertically\tCtrl-W" );
1049 menuUserScale
->AppendSeparator();
1050 menuUserScale
->Append( UserScale_Restore
, "Restore to normal\tCtrl-0" );
1052 wxMenu
*menuAxis
= new wxMenu
;
1053 menuAxis
->Append( AxisMirror_Horiz
, "Mirror horizontally\tCtrl-M", "", TRUE
);
1054 menuAxis
->Append( AxisMirror_Vertic
, "Mirror vertically\tCtrl-N", "", TRUE
);
1056 wxMenu
*menuLogical
= new wxMenu
;
1057 menuLogical
->Append( LogicalOrigin_MoveDown
, "Move &down\tCtrl-D" );
1058 menuLogical
->Append( LogicalOrigin_MoveUp
, "Move &up\tCtrl-U" );
1059 menuLogical
->Append( LogicalOrigin_MoveLeft
, "Move &right\tCtrl-L" );
1060 menuLogical
->Append( LogicalOrigin_MoveRight
, "Move &left\tCtrl-R" );
1062 wxMenu
*menuColour
= new wxMenu
;
1063 menuColour
->Append( Colour_TextForeground
, "Text foreground..." );
1064 menuColour
->Append( Colour_TextBackground
, "Text background..." );
1065 menuColour
->Append( Colour_Background
, "Background colour..." );
1066 menuColour
->Append( Colour_BackgroundMode
, "Opaque/transparent\tCtrl-B", "", TRUE
);
1067 menuColour
->Append( Colour_TextureBackgound
, "Draw textured background\tCtrl-T", "", TRUE
);
1069 // now append the freshly created menu to the menu bar...
1070 wxMenuBar
*menuBar
= new wxMenuBar
;
1071 menuBar
->Append(menuFile
, "&File");
1072 menuBar
->Append(menuMapMode
, "&MapMode");
1073 menuBar
->Append(menuUserScale
, "&UserScale");
1074 menuBar
->Append(menuAxis
, "&Axis");
1075 menuBar
->Append(menuLogical
, "&LogicalOrigin");
1076 menuBar
->Append(menuColour
, "&Colours");
1078 // ... and attach this menu bar to the frame
1079 SetMenuBar(menuBar
);
1081 // create a status bar just for fun (by default with 1 pane only)
1083 SetStatusText("Welcome to wxWindows!");
1085 m_mapMode
= wxMM_TEXT
;
1088 m_xLogicalOrigin
= 0;
1089 m_yLogicalOrigin
= 0;
1091 m_yAxisReversed
= FALSE
;
1092 m_backgroundMode
= wxSOLID
;
1093 m_colourForeground
= *wxRED
;
1094 m_colourBackground
= *wxBLUE
;
1095 m_textureBackground
= FALSE
;
1097 m_canvas
= new MyCanvas( this );
1098 m_canvas
->SetScrollbars( 10, 10, 100, 240 );
1103 void MyFrame::OnQuit(wxCommandEvent
& WXUNUSED(event
))
1105 // TRUE is to force the frame to close
1109 void MyFrame::OnAbout(wxCommandEvent
& WXUNUSED(event
))
1112 msg
.Printf( wxT("This is the about dialog of the drawing sample.\n")
1113 wxT("This sample tests various primitive drawing functions\n")
1114 wxT("without any tests to prevent flicker.\n")
1115 wxT("Copyright (c) Robert Roebling 1999")
1118 wxMessageBox(msg
, "About Drawing", wxOK
| wxICON_INFORMATION
, this);
1121 void MyFrame::OnShow(wxCommandEvent
& event
)
1123 m_canvas
->Show((ScreenToShow
)(event
.GetInt() - MenuShow_First
));
1126 void MyFrame::OnOption(wxCommandEvent
& event
)
1128 switch (event
.GetInt())
1131 m_mapMode
= wxMM_TEXT
;
1133 case MapMode_Lometric
:
1134 m_mapMode
= wxMM_LOMETRIC
;
1137 m_mapMode
= wxMM_TWIPS
;
1139 case MapMode_Points
:
1140 m_mapMode
= wxMM_POINTS
;
1142 case MapMode_Metric
:
1143 m_mapMode
= wxMM_METRIC
;
1146 case LogicalOrigin_MoveDown
:
1147 m_yLogicalOrigin
+= 10;
1149 case LogicalOrigin_MoveUp
:
1150 m_yLogicalOrigin
-= 10;
1152 case LogicalOrigin_MoveLeft
:
1153 m_xLogicalOrigin
+= 10;
1155 case LogicalOrigin_MoveRight
:
1156 m_xLogicalOrigin
-= 10;
1159 case UserScale_StretchHoriz
:
1160 m_xUserScale
*= 1.10;
1162 case UserScale_ShrinkHoriz
:
1163 m_xUserScale
/= 1.10;
1165 case UserScale_StretchVertic
:
1166 m_yUserScale
*= 1.10;
1168 case UserScale_ShrinkVertic
:
1169 m_yUserScale
/= 1.10;
1171 case UserScale_Restore
:
1176 case AxisMirror_Vertic
:
1177 m_yAxisReversed
= !m_yAxisReversed
;
1179 case AxisMirror_Horiz
:
1180 m_xAxisReversed
= !m_xAxisReversed
;
1183 case Colour_TextForeground
:
1184 m_colourForeground
= SelectColour();
1186 case Colour_TextBackground
:
1187 m_colourBackground
= SelectColour();
1189 case Colour_Background
:
1191 wxColour col
= SelectColour();
1194 m_backgroundBrush
.SetColour(col
);
1198 case Colour_BackgroundMode
:
1199 m_backgroundMode
= m_backgroundMode
== wxSOLID
? wxTRANSPARENT
1203 case Colour_TextureBackgound
:
1204 m_textureBackground
= ! m_textureBackground
;
1212 m_canvas
->Refresh();
1215 void MyFrame::PrepareDC(wxDC
& dc
)
1217 dc
.SetMapMode( m_mapMode
);
1218 dc
.SetUserScale( m_xUserScale
, m_yUserScale
);
1219 dc
.SetLogicalOrigin( m_xLogicalOrigin
, m_yLogicalOrigin
);
1220 dc
.SetAxisOrientation( !m_xAxisReversed
, m_yAxisReversed
);
1223 wxColour
MyFrame::SelectColour()
1227 wxColourDialog
dialog(this, &data
);
1229 if ( dialog
.ShowModal() == wxID_OK
)
1231 col
= dialog
.GetColourData().GetColour();