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)
66 // ----------------------------------------------------------------------------
68 // ----------------------------------------------------------------------------
70 static wxBitmap gs_bmpNoMask
,
77 // ----------------------------------------------------------------------------
79 // ----------------------------------------------------------------------------
81 // Define a new application type, each program should derive a class from wxApp
82 class MyApp
: public wxApp
85 // override base class virtuals
86 // ----------------------------
88 // this one is called on application startup and is a good place for the app
89 // initialization (doing it here and not in the ctor allows to have an error
90 // return: if OnInit() returns false, the application terminates)
91 virtual bool OnInit();
99 // Define a new frame type: this is going to be our main frame
100 class MyFrame
: public wxFrame
104 MyFrame(const wxString
& title
, const wxPoint
& pos
, const wxSize
& size
);
106 // event handlers (these functions should _not_ be virtual)
107 void OnQuit(wxCommandEvent
& event
);
108 void OnAbout(wxCommandEvent
& event
);
109 void OnShow(wxCommandEvent
&event
);
110 void OnOption(wxCommandEvent
&event
);
112 wxColour
SelectColour();
113 void PrepareDC(wxDC
& dc
);
115 int m_backgroundMode
;
116 int m_textureBackground
;
120 int m_xLogicalOrigin
;
121 int m_yLogicalOrigin
;
122 bool m_xAxisReversed
,
124 wxColour m_colourForeground
, // these are _text_ colours
126 wxBrush m_backgroundBrush
;
130 // any class wishing to process wxWindows events must use this macro
131 DECLARE_EVENT_TABLE()
134 // define a scrollable canvas for drawing onto
135 class MyCanvas
: public wxScrolledWindow
138 MyCanvas( MyFrame
*parent
);
140 void OnPaint(wxPaintEvent
&event
);
141 void OnMouseMove(wxMouseEvent
&event
);
143 void Show(ScreenToShow show
) { m_show
= show
; Refresh(); }
146 void DrawTestPoly( int x
, int y
, wxDC
&dc
,int transparent
);
147 void DrawTestLines( int x
, int y
, int width
, wxDC
&dc
);
148 void DrawText(wxDC
& dc
);
149 void DrawImages(wxDC
& dc
);
150 void DrawWithLogicalOps(wxDC
& dc
);
151 void DrawDefault(wxDC
& dc
);
158 DECLARE_EVENT_TABLE()
161 // ----------------------------------------------------------------------------
163 // ----------------------------------------------------------------------------
165 // IDs for the controls and the menu commands
173 File_ShowDefault
= MenuShow_First
,
179 MenuShow_Last
= File_ShowOps
,
183 MapMode_Text
= MenuOption_First
,
189 UserScale_StretchHoriz
,
190 UserScale_ShrinkHoriz
,
191 UserScale_StretchVertic
,
192 UserScale_ShrinkVertic
,
198 LogicalOrigin_MoveDown
,
199 LogicalOrigin_MoveUp
,
200 LogicalOrigin_MoveLeft
,
201 LogicalOrigin_MoveRight
,
203 Colour_TextForeground
,
204 Colour_TextBackground
,
206 Colour_BackgroundMode
,
207 Colour_TextureBackgound
,
209 MenuOption_Last
= Colour_TextureBackgound
212 // ----------------------------------------------------------------------------
213 // event tables and other macros for wxWindows
214 // ----------------------------------------------------------------------------
217 // Create a new application object: this macro will allow wxWindows to create
218 // the application object during program execution (it's better than using a
219 // static object for many reasons) and also declares the accessor function
220 // wxGetApp() which will return the reference of the right type (i.e. MyApp and
224 // ============================================================================
226 // ============================================================================
228 // ----------------------------------------------------------------------------
229 // the application class
230 // ----------------------------------------------------------------------------
232 bool MyApp
::LoadImages()
238 wxString path
= pathList
.FindValidPath("pat4.bmp");
241 gs_bmp4
.LoadFile(path
, wxBITMAP_TYPE_BMP
);
242 wxMask
* mask4
= new wxMask(gs_bmp4
, *wxBLACK
);
243 gs_bmp4
.SetMask(mask4
);
245 path
= pathList
.FindValidPath("pat36.bmp");
248 gs_bmp36
.LoadFile(path
, wxBITMAP_TYPE_BMP
);
249 wxMask
* mask36
= new wxMask(gs_bmp36
, *wxBLACK
);
250 gs_bmp36
.SetMask(mask36
);
252 path
= pathList
.FindValidPath("image.bmp");
255 gs_bmpNoMask
.LoadFile(path
, wxBITMAP_TYPE_BMP
);
256 gs_bmpWithMask
.LoadFile(path
, wxBITMAP_TYPE_BMP
);
257 gs_bmpWithColMask
.LoadFile(path
, wxBITMAP_TYPE_BMP
);
259 path
= pathList
.FindValidPath("mask.bmp");
262 gs_bmpMask
.LoadFile(path
, wxBITMAP_TYPE_BMP
);
264 // This is so wrong, it hurts.
265 // gs_bmpMask.SetDepth(1);
266 // wxMask *mask = new wxMask(gs_bmpMask);
268 wxMask
*mask
= new wxMask(gs_bmpMask
, *wxBLACK
);
269 gs_bmpWithMask
.SetMask(mask
);
271 mask
= new wxMask(gs_bmpWithColMask
, *wxWHITE
);
272 gs_bmpWithColMask
.SetMask(mask
);
277 // `Main program' equivalent: the program execution "starts" here
280 // Create the main application window
281 MyFrame
*frame
= new MyFrame("Drawing sample",
282 wxPoint(50, 50), wxSize(550, 340));
284 // Show it and tell the application that it's our main window
290 wxLogError("Can't load one of the bitmap files needed for this sample "
291 "from the current or parent directory, please copy them "
302 // ----------------------------------------------------------------------------
304 // ----------------------------------------------------------------------------
306 // the event tables connect the wxWindows events with the functions (event
307 // handlers) which process them.
308 BEGIN_EVENT_TABLE(MyCanvas
, wxScrolledWindow
)
309 EVT_PAINT (MyCanvas
::OnPaint
)
310 EVT_MOTION (MyCanvas
::OnMouseMove
)
313 MyCanvas
::MyCanvas( MyFrame
*parent
) : wxScrolledWindow( parent
)
316 m_show
= Show_Default
;
319 //draw a polygon and an overlapping rectangle
320 //is transparent is 1, the fill pattern are made transparent
321 //is transparent is 2, the fill pattern are made transparent but inversed
322 //is transparent is 0 the text for and background color will be used to represent/map
323 //the colors of the monochrome bitmap pixels to the fillpattern
325 //i miss_used the the menu items for setting so called back and fore ground color
326 //just to show how the those colors do influence the fillpatterns
327 //just play with those,
329 //variations are endless using other logical functions
330 void MyCanvas
::DrawTestPoly( int x
, int y
,wxDC
&dc
,int transparent
)
332 wxBrush
* brush4
= new wxBrush(gs_bmp4
);
333 wxBrush
* brush36
= new wxBrush(gs_bmp36
);
336 todraw
[0].x
=(long)x
+100;
337 todraw
[0].y
=(long)y
+100;
338 todraw
[1].x
=(long)x
+300;
339 todraw
[1].y
=(long)y
+100;
340 todraw
[2].x
=(long)x
+300;
341 todraw
[2].y
=(long)y
+300;
342 todraw
[3].x
=(long)x
+150;
343 todraw
[3].y
=(long)y
+350;
344 todraw
[4].x
=(long)x
+100;
345 todraw
[4].y
=(long)y
+300;
363 dc
.SetPen( wxPen( "black", 4, wxSOLID
) );
364 dc
.SetBrush( *brush4
);
365 dc
.SetTextForeground(*wxGREEN
);
366 dc
.SetTextBackground(m_owner
->m_colourForeground
);
367 dc
.SetLogicalFunction(wxCOPY
);
368 dc
.DrawPolygon(5,todraw
,0,0,wxWINDING_RULE
);
370 //don't understand hwo but the outline is also depending on logicalfunction
371 dc
.SetPen( wxPen( "red", 4, wxSOLID
) );
372 dc
.SetBrush( *brush36
);
373 dc
.SetTextForeground(*wxCYAN
);
374 dc
.SetTextBackground(m_owner
->m_colourBackground
);
375 dc
.SetLogicalFunction(wxCOPY
);
376 dc
.DrawRectangle( x
+10, y
+10, 200, 200 );
377 dc
.SetBrush(wxNullBrush
);
378 dc
.SetPen(wxNullPen
);
381 case 1: //now with transparent fillpatterns
384 wxBitmap
* bmpBlit
= new wxBitmap(600,400);
385 wxMemoryDC
* memDC
= new wxMemoryDC();
386 // wxBrush _clearbrush(*wxGREEN,wxSOLID);
387 wxBrush
_clearbrush(*wxBLACK
,wxSOLID
);
388 memDC
->SelectObject(*bmpBlit
);
389 memDC
->BeginDrawing();
390 memDC
->SetBackground(_clearbrush
);
392 memDC
->SetBackground(wxNullBrush
);
394 memDC
->SetPen( wxPen( "black", 4, wxSOLID
) );
395 memDC
->SetBrush( wxNullBrush
);
396 memDC
->SetBrush( *brush4
);
397 memDC
->SetTextForeground(*wxBLACK
); // 0s --> 0x000000 (black)
398 memDC
->SetTextBackground(*wxWHITE
); // 1s --> 0xFFFFFF (white)
399 memDC
->SetLogicalFunction(wxAND_INVERT
);
401 // BLACK OUT the opaque pixels and leave the rest as is
402 memDC
->DrawPolygon(5,todraw2
,0,0,wxWINDING_RULE
);
404 // Set background and foreground colors for fill pattern
405 //the previous blacked out pixels are now merged with the layer color
406 //while the non blacked out pixels stay as they are.
407 memDC
->SetTextForeground(*wxBLACK
); // 0s --> 0x000000 (black)
409 //now define what will be the color of the fillpattern parts that are not transparent
410 // memDC->SetTextBackground(*wxBLUE);
411 memDC
->SetTextBackground(m_owner
->m_colourForeground
);
412 memDC
->SetLogicalFunction(wxOR
);
415 //don't understand how but the outline is also depending on logicalfunction
416 memDC
->SetPen( wxPen( "red", 4, wxSOLID
) );
417 memDC
->DrawPolygon(5,todraw2
,0,0,wxWINDING_RULE
);
419 memDC
->SetLogicalFunction(wxCOPY
);
421 memDC
->SetPen( wxPen( "black", 4, wxSOLID
) );
422 memDC
->SetBrush( wxNullBrush
);
423 memDC
->SetBrush( *brush36
);
424 memDC
->SetTextForeground(*wxBLACK
); // 0s --> 0x000000 (black)
425 memDC
->SetTextBackground(*wxWHITE
); // 1s --> 0xFFFFFF (white)
426 memDC
->SetLogicalFunction(wxAND_INVERT
);
428 memDC
->DrawRectangle( 10, 10, 200, 200 );
430 // Set background and foreground colors for fill pattern
431 //the previous blacked out pixels are now merged with the layer color
432 //while the non blacked out pixels stay as they are.
433 memDC
->SetTextForeground(*wxBLACK
); // 0s --> 0x000000 (black)
434 //now define what will be the color of the fillpattern parts that are not transparent
435 // memDC->SetTextBackground(*wxRED);
436 memDC
->SetTextBackground(m_owner
->m_colourBackground
);
437 memDC
->SetLogicalFunction(wxOR
);
439 //don't understand how but the outline is also depending on logicalfunction
440 memDC
->SetPen( wxPen( "yellow", 4, wxSOLID
) );
441 memDC
->DrawRectangle( 10, 10, 200, 200 );
443 memDC
->SetBrush(wxNullBrush
);
444 memDC
->SetPen(wxNullPen
);
447 dc
.Blit(x
,y
,600,400,memDC
,0,0,wxCOPY
);
452 case 2: //now with transparent inversed fillpatterns
454 wxBitmap
* bmpBlit
= new wxBitmap(600,400);
455 wxMemoryDC
* memDC
= new wxMemoryDC();
456 wxBrush
_clearbrush(*wxWHITE
,wxSOLID
);
457 memDC
->SelectObject(*bmpBlit
);
458 memDC
->BeginDrawing();
459 memDC
->SetBackground(_clearbrush
);
461 memDC
->SetBackground(wxNullBrush
);
463 memDC
->SetPen( wxPen( "black", 4, wxSOLID
) );
464 memDC
->SetBrush( *brush4
);
465 memDC
->SetTextBackground(*wxBLACK
); // 0s --> 0x000000 (black)
466 memDC
->SetTextForeground(*wxWHITE
); // 1s --> 0xFFFFFF (white)
467 memDC
->SetLogicalFunction(wxAND_INVERT
);
469 // BLACK OUT the opaque pixels and leave the rest as is
470 memDC
->DrawPolygon(5,todraw2
,0,0,wxWINDING_RULE
);
472 // Set background and foreground colors for fill pattern
473 //the previous blacked out pixels are now merged with the layer color
474 //while the non blacked out pixels stay as they are.
475 memDC
->SetTextBackground(*wxBLACK
); // 0s --> 0x000000 (black)
477 //now define what will be the color of the fillpattern parts that are not transparent
478 memDC
->SetTextForeground(m_owner
->m_colourForeground
);
479 memDC
->SetLogicalFunction(wxOR
);
482 //don't understand how but the outline is also depending on logicalfunction
483 memDC
->SetPen( wxPen( "red", 4, wxSOLID
) );
484 memDC
->DrawPolygon(5,todraw2
,0,0,wxWINDING_RULE
);
486 memDC
->SetLogicalFunction(wxCOPY
);
488 memDC
->SetPen( wxPen( "black", 4, wxSOLID
) );
489 memDC
->SetBrush( *brush36
);
490 memDC
->SetTextBackground(*wxBLACK
); // 0s --> 0x000000 (black)
491 memDC
->SetTextForeground(*wxWHITE
); // 1s --> 0xFFFFFF (white)
492 memDC
->SetLogicalFunction(wxAND_INVERT
);
494 memDC
->DrawRectangle( 10,10, 200, 200 );
496 // Set background and foreground colors for fill pattern
497 //the previous blacked out pixels are now merged with the layer color
498 //while the non blacked out pixels stay as they are.
499 memDC
->SetTextBackground(*wxBLACK
); // 0s --> 0x000000 (black)
500 //now define what will be the color of the fillpattern parts that are not transparent
501 memDC
->SetTextForeground(m_owner
->m_colourBackground
);
502 memDC
->SetLogicalFunction(wxOR
);
504 //don't understand how but the outline is also depending on logicalfunction
505 memDC
->SetPen( wxPen( "yellow", 4, wxSOLID
) );
506 memDC
->DrawRectangle( 10, 10, 200, 200 );
508 memDC
->SetBrush(wxNullBrush
);
509 memDC
->SetPen(wxNullPen
);
510 dc
.Blit(x
,y
,600,400,memDC
,0,0,wxCOPY
);
520 void MyCanvas
::DrawTestLines( int x
, int y
, int width
, wxDC
&dc
)
522 dc
.SetPen( wxPen( "black", width
, wxSOLID
) );
523 dc
.SetBrush( *wxRED_BRUSH
);
524 dc
.DrawRectangle( x
+10, y
+10, 100, 190 );
526 dc
.SetPen( wxPen( "black", width
, wxSOLID
) );
527 dc
.DrawLine( x
+20, y
+20, 100, y
+20 );
528 dc
.SetPen( wxPen( "black", width
, wxDOT
) );
529 dc
.DrawLine( x
+20, y
+30, 100, y
+30 );
530 dc
.SetPen( wxPen( "black", width
, wxSHORT_DASH
) );
531 dc
.DrawLine( x
+20, y
+40, 100, y
+40 );
532 dc
.SetPen( wxPen( "black", width
, wxLONG_DASH
) );
533 dc
.DrawLine( x
+20, y
+50, 100, y
+50 );
534 dc
.SetPen( wxPen( "black", width
, wxDOT_DASH
) );
535 dc
.DrawLine( x
+20, y
+60, 100, y
+60 );
537 dc
.SetPen( wxPen( "black", width
, wxBDIAGONAL_HATCH
) );
538 dc
.DrawLine( x
+20, y
+70, 100, y
+70 );
539 dc
.SetPen( wxPen( "black", width
, wxCROSSDIAG_HATCH
) );
540 dc
.DrawLine( x
+20, y
+80, 100, y
+80 );
541 dc
.SetPen( wxPen( "black", width
, wxFDIAGONAL_HATCH
) );
542 dc
.DrawLine( x
+20, y
+90, 100, y
+90 );
543 dc
.SetPen( wxPen( "black", width
, wxCROSS_HATCH
) );
544 dc
.DrawLine( x
+20, y
+100, 100, y
+100 );
545 dc
.SetPen( wxPen( "black", width
, wxHORIZONTAL_HATCH
) );
546 dc
.DrawLine( x
+20, y
+110, 100, y
+110 );
547 dc
.SetPen( wxPen( "black", width
, wxVERTICAL_HATCH
) );
548 dc
.DrawLine( x
+20, y
+120, 100, y
+120 );
550 wxPen
ud( "black", width
, wxUSER_DASH
);
553 ud
.SetDashes( 1, dash1
);
554 dc
.DrawLine( x
+20, y
+140, 100, y
+140 );
556 ud
.SetDashes( 1, dash1
);
557 dc
.DrawLine( x
+20, y
+150, 100, y
+150 );
559 ud
.SetDashes( 1, dash1
);
560 dc
.DrawLine( x
+20, y
+160, 100, y
+160 );
562 ud
.SetDashes( 1, dash1
);
563 dc
.DrawLine( x
+20, y
+170, 100, y
+170 );
566 void MyCanvas
::DrawDefault(wxDC
& dc
)
569 dc
.DrawCircle(0, 0, 10);
570 #if !(defined __WXGTK__) && !(defined __WXMOTIF__)
571 // not implemented in wxGTK or wxMOTIF :-(
572 dc
.FloodFill(0, 0, wxColour(255, 0, 0));
575 dc
.DrawIcon( wxICON(mondrian
), 40, 40 );
577 dc
.DrawCheckMark(5, 80, 15, 15);
578 dc
.DrawCheckMark(25, 80, 30, 30);
579 dc
.DrawCheckMark(60, 80, 60, 60);
581 // this is the test for "blitting bitmap into DC damages selected brush"
583 wxIcon icon
= wxTheApp
->GetStdIcon(wxICON_INFORMATION
);
584 wxCoord rectSize
= icon
.GetWidth() + 10;
586 dc
.SetPen(*wxTRANSPARENT_PEN
);
587 dc
.SetBrush( *wxGREEN_BRUSH
);
588 dc
.DrawRectangle(x
, 10, rectSize
, rectSize
);
589 dc
.DrawBitmap(icon
, x
+ 5, 15, TRUE
);
591 dc
.DrawRectangle(x
, 10, rectSize
, rectSize
);
592 dc
.DrawIcon(wxTheApp
->GetStdIcon(wxICON_INFORMATION
), x
+ 5, 15);
594 dc
.DrawRectangle(x
, 10, rectSize
, rectSize
);
596 // test for "transparent" bitmap drawing (it intersects with the last
598 //dc.SetBrush( *wxTRANSPARENT_BRUSH );
599 #include "../image/smile.xpm"
600 wxBitmap
bmp(smile_xpm
);
603 dc
.DrawBitmap(bmp
, x
+ rectSize
- 20, rectSize
- 10, TRUE
);
605 dc
.SetBrush( *wxBLACK_BRUSH
);
606 dc
.DrawRectangle( 0, 160, 1000, 300 );
609 wxBitmap
bitmap(20,70);
611 memdc
.SelectObject( bitmap
);
612 memdc
.SetBrush( *wxBLACK_BRUSH
);
613 memdc
.SetPen( *wxWHITE_PEN
);
614 memdc
.DrawRectangle(0,0,20,70);
615 memdc
.DrawLine( 10,0,10,70 );
618 wxPen pen
= *wxRED_PEN
;
620 memdc
.DrawLine( 10, 5,10, 5 );
621 memdc
.DrawLine( 10,10,11,10 );
622 memdc
.DrawLine( 10,15,12,15 );
623 memdc
.DrawLine( 10,20,13,20 );
626 memdc.SetPen(*wxRED_PEN);
627 memdc.DrawLine( 12, 5,12, 5 );
628 memdc.DrawLine( 12,10,13,10 );
629 memdc.DrawLine( 12,15,14,15 );
630 memdc.DrawLine( 12,20,15,20 );
634 memdc
.DrawLine( 10,25,10,25 );
635 memdc
.DrawLine( 10,30, 9,30 );
636 memdc
.DrawLine( 10,35, 8,35 );
637 memdc
.DrawLine( 10,40, 7,40 );
640 dc
.SetPen(*wxWHITE_PEN
);
641 memdc
.SetLogicalFunction( wxINVERT
);
642 memdc
.SetPen( *wxWHITE_PEN
);
643 memdc
.DrawLine( 10,50,10,50 );
644 memdc
.DrawLine( 10,55,11,55 );
645 memdc
.DrawLine( 10,60,12,60 );
646 memdc
.DrawLine( 10,65,13,65 );
648 memdc
.DrawLine( 12,50,12,50 );
649 memdc
.DrawLine( 12,55,13,55 );
650 memdc
.DrawLine( 12,60,14,60 );
651 memdc
.DrawLine( 12,65,15,65 );
653 memdc
.SelectObject( wxNullBitmap
);
654 dc
.DrawBitmap( bitmap
, 10, 170 );
655 wxImage
image( bitmap
);
656 image
.Rescale( 60,210 );
657 bitmap
= image
.ConvertToBitmap();
658 dc
.DrawBitmap( bitmap
, 50, 170 );
660 // test the rectangle outline drawing - there should be one pixel between
661 // the rect and the lines
662 dc
.SetPen(*wxWHITE_PEN
);
663 dc
.SetBrush( *wxTRANSPARENT_BRUSH
);
664 dc
.DrawRectangle(150, 170, 49, 29);
665 dc
.DrawRectangle(200, 170, 49, 29);
666 dc
.SetPen(*wxWHITE_PEN
);
667 dc
.DrawLine(250, 210, 250, 170);
668 dc
.DrawLine(260, 200, 150, 200);
670 // test the rectangle filled drawing - there should be one pixel between
671 // the rect and the lines
672 dc
.SetPen(*wxTRANSPARENT_PEN
);
673 dc
.SetBrush( *wxWHITE_BRUSH
);
674 dc
.DrawRectangle(300, 170, 49, 29);
675 dc
.DrawRectangle(350, 170, 49, 29);
676 dc
.SetPen(*wxWHITE_PEN
);
677 dc
.DrawLine(400, 170, 400, 210);
678 dc
.DrawLine(300, 200, 410, 200);
680 // a few more tests of this kind
681 dc
.SetPen(*wxRED_PEN
);
682 dc
.SetBrush( *wxWHITE_BRUSH
);
683 dc
.DrawRectangle(300, 220, 1, 1);
684 dc
.DrawRectangle(310, 220, 2, 2);
685 dc
.DrawRectangle(320, 220, 3, 3);
686 dc
.DrawRectangle(330, 220, 4, 4);
688 dc
.SetPen(*wxTRANSPARENT_PEN
);
689 dc
.SetBrush( *wxWHITE_BRUSH
);
690 dc
.DrawRectangle(300, 230, 1, 1);
691 dc
.DrawRectangle(310, 230, 2, 2);
692 dc
.DrawRectangle(320, 230, 3, 3);
693 dc
.DrawRectangle(330, 230, 4, 4);
695 // and now for filled rect with outline
696 dc
.SetPen(*wxRED_PEN
);
697 dc
.SetBrush( *wxWHITE_BRUSH
);
698 dc
.DrawRectangle(500, 170, 49, 29);
699 dc
.DrawRectangle(550, 170, 49, 29);
700 dc
.SetPen(*wxWHITE_PEN
);
701 dc
.DrawLine(600, 170, 600, 210);
702 dc
.DrawLine(500, 200, 610, 200);
704 // test the rectangle outline drawing - there should be one pixel between
705 // the rect and the lines
706 dc
.SetPen(*wxWHITE_PEN
);
707 dc
.SetBrush( *wxTRANSPARENT_BRUSH
);
708 dc
.DrawRoundedRectangle(150, 270, 49, 29, 6);
709 dc
.DrawRoundedRectangle(200, 270, 49, 29, 6);
710 dc
.SetPen(*wxWHITE_PEN
);
711 dc
.DrawLine(250, 270, 250, 310);
712 dc
.DrawLine(150, 300, 260, 300);
714 // test the rectangle filled drawing - there should be one pixel between
715 // the rect and the lines
716 dc
.SetPen(*wxTRANSPARENT_PEN
);
717 dc
.SetBrush( *wxWHITE_BRUSH
);
718 dc
.DrawRoundedRectangle(300, 270, 49, 29, 6);
719 dc
.DrawRoundedRectangle(350, 270, 49, 29, 6);
720 dc
.SetPen(*wxWHITE_PEN
);
721 dc
.DrawLine(400, 270, 400, 310);
722 dc
.DrawLine(300, 300, 410, 300);
724 // Added by JACS to demonstrate bizarre behaviour.
725 // With a size of 70, we get a missing red RHS,
726 // and the hight is too small, so we get yellow
727 // showing. With a size of 40, it draws as expected:
728 // it just shows a white rectangle with red outline.
730 int totalHeight
= 70;
731 wxBitmap
bitmap2(totalWidth
, totalHeight
);
734 memdc2
.SelectObject(bitmap2
);
736 wxBrush
yellowBrush(wxColour(255, 255, 0), wxSOLID
);
737 memdc2
.SetBackground(yellowBrush
);
740 wxPen
yellowPen(wxColour(255, 255, 0), 1, wxSOLID
);
742 // Now draw a white rectangle with red outline. It should
743 // entirely eclipse the yellow background.
744 memdc2
.SetPen(*wxRED_PEN
);
745 memdc2
.SetBrush(*wxWHITE_BRUSH
);
747 memdc2
.DrawRectangle(0, 0, totalWidth
, totalHeight
);
749 memdc2
.SetPen(wxNullPen
);
750 memdc2
.SetBrush(wxNullBrush
);
751 memdc2
.SelectObject(wxNullBitmap
);
753 dc
.DrawBitmap(bitmap2
, 500, 270);
755 // Repeat, but draw directly on dc
756 // Draw a yellow rectangle filling the bitmap
758 x
= 600; int y
= 270;
759 dc
.SetPen(yellowPen
);
760 dc
.SetBrush(yellowBrush
);
761 dc
.DrawRectangle(x
, y
, totalWidth
, totalHeight
);
763 // Now draw a white rectangle with red outline. It should
764 // entirely eclipse the yellow background.
765 dc
.SetPen(*wxRED_PEN
);
766 dc
.SetBrush(*wxWHITE_BRUSH
);
768 dc
.DrawRectangle(x
, y
, totalWidth
, totalHeight
);
771 void MyCanvas
::DrawText(wxDC
& dc
)
773 // set underlined font for testing
774 dc
.SetFont( wxFont(12, wxMODERN
, wxNORMAL
, wxNORMAL
, TRUE
) );
775 dc
.DrawText( "This is text", 110, 10 );
776 dc
.DrawRotatedText( "That is text", 20, 10, -45 );
778 dc
.SetFont( *wxNORMAL_FONT
);
781 dc
. SetBackgroundMode(wxTRANSPARENT
);
783 for ( int n
= -180; n
< 180; n
+= 30 )
785 text
.Printf(" %d rotated text", n
);
786 dc
.DrawRotatedText(text
, 400, 400, n
);
789 dc
.SetFont( wxFont( 18, wxSWISS
, wxNORMAL
, wxNORMAL
) );
791 dc
.DrawText( "This is Swiss 18pt text.", 110, 40 );
796 dc
.GetTextExtent( "This is Swiss 18pt text.", &length
, &height
, &descent
);
797 text
.Printf( "Dimensions are length %ld, height %ld, descent %ld", length
, height
, descent
);
798 dc
.DrawText( text
, 110, 80 );
800 text
.Printf( "CharHeight() returns: %d", dc
.GetCharHeight() );
801 dc
.DrawText( text
, 110, 120 );
803 dc
.DrawRectangle( 100, 40, 4, height
);
810 } rasterOperations
[] =
813 { "wxAND_INVERT", wxAND_INVERT
},
814 { "wxAND_REVERSE", wxAND_REVERSE
},
815 { "wxCLEAR", wxCLEAR
},
816 { "wxCOPY", wxCOPY
},
817 { "wxEQUIV", wxEQUIV
},
818 { "wxINVERT", wxINVERT
},
819 { "wxNAND", wxNAND
},
820 { "wxNO_OP", wxNO_OP
},
822 { "wxOR_INVERT", wxOR_INVERT
},
823 { "wxOR_REVERSE", wxOR_REVERSE
},
825 { "wxSRC_INVERT", wxSRC_INVERT
},
829 void MyCanvas
::DrawImages(wxDC
& dc
)
831 dc
.DrawText("original image", 0, 0);
832 dc
.DrawBitmap(gs_bmpNoMask
, 0, 20, 0);
833 dc
.DrawText("with colour mask", 0, 100);
834 dc
.DrawBitmap(gs_bmpWithColMask
, 0, 120, TRUE
);
835 dc
.DrawText("the mask image", 0, 200);
836 dc
.DrawBitmap(gs_bmpMask
, 0, 220, 0);
837 dc
.DrawText("masked image", 0, 300);
838 dc
.DrawBitmap(gs_bmpWithMask
, 0, 320, TRUE
);
840 int cx
= gs_bmpWithColMask
.GetWidth(),
841 cy
= gs_bmpWithColMask
.GetHeight();
844 for ( size_t n
= 0; n
< WXSIZEOF(rasterOperations
); n
++ )
846 wxCoord x
= 120 + 150*(n
%4),
849 dc
.DrawText(rasterOperations
[n
].name
, x
, y
- 20);
850 memDC
.SelectObject(gs_bmpWithColMask
);
851 dc
.Blit(x
, y
, cx
, cy
, &memDC
, 0, 0, rasterOperations
[n
].rop
, TRUE
);
855 void MyCanvas
::DrawWithLogicalOps(wxDC
& dc
)
857 static const wxCoord w
= 60;
858 static const wxCoord h
= 60;
860 // reuse the text colour here
861 dc
.SetPen(wxPen(m_owner
->m_colourForeground
, 1, wxSOLID
));
862 dc
.SetBrush(*wxTRANSPARENT_BRUSH
);
865 for ( n
= 0; n
< WXSIZEOF(rasterOperations
); n
++ )
867 wxCoord x
= 20 + 150*(n
%4),
870 dc
.DrawText(rasterOperations
[n
].name
, x
, y
- 20);
871 dc
.SetLogicalFunction(rasterOperations
[n
].rop
);
872 dc
.DrawRectangle(x
, y
, w
, h
);
873 dc
.DrawLine(x
, y
, x
+ w
, y
+ h
);
874 dc
.DrawLine(x
+ w
, y
, x
, y
+ h
);
877 // now some filled rectangles
878 dc
.SetBrush(wxBrush(m_owner
->m_colourForeground
, wxSOLID
));
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
);
891 void MyCanvas
::OnPaint(wxPaintEvent
&WXUNUSED(event
))
895 m_owner
->PrepareDC(dc
);
897 dc
.SetBackgroundMode( m_owner
->m_backgroundMode
);
898 if ( m_owner
->m_backgroundBrush
.Ok() )
899 dc
.SetBackground( m_owner
->m_backgroundBrush
);
900 if ( m_owner
->m_colourForeground
.Ok() )
901 dc
.SetTextForeground( m_owner
->m_colourForeground
);
902 if ( m_owner
->m_colourBackground
.Ok() )
903 dc
.SetTextBackground( m_owner
->m_colourBackground
);
905 if ( m_owner
->m_textureBackground
) {
906 if ( ! m_owner
->m_backgroundBrush
.Ok() ) {
907 wxBrush
b(wxColour(0,128,0), wxSOLID
);
914 if ( m_owner
->m_textureBackground
) {
915 dc
.SetPen(*wxMEDIUM_GREY_PEN
);
916 for (int i
=0; i
<200; i
++)
917 dc
.DrawLine(0, i
*10, i
*10, 0);
931 DrawTestLines( 0, 100, 0, dc
);
932 DrawTestLines( 0, 300, 1, dc
);
933 DrawTestLines( 0, 500, 2, dc
);
934 DrawTestLines( 0, 700, 6, dc
);
938 DrawTestPoly( 0, 100, dc
, 0 );
939 DrawTestPoly( 33, 500, dc
, 1 );
940 DrawTestPoly( 43, 1000, dc
, 2 );
948 DrawWithLogicalOps(dc
);
953 void MyCanvas
::OnMouseMove(wxMouseEvent
&event
)
957 m_owner
->PrepareDC(dc
);
959 wxPoint pos
= event
.GetPosition();
960 long x
= dc
.DeviceToLogicalX( pos
.x
);
961 long y
= dc
.DeviceToLogicalY( pos
.y
);
963 str
.Printf( "Current mouse position: %d,%d", (int)x
, (int)y
);
964 m_owner
->SetStatusText( str
);
967 // ----------------------------------------------------------------------------
969 // ----------------------------------------------------------------------------
971 // the event tables connect the wxWindows events with the functions (event
972 // handlers) which process them. It can be also done at run-time, but for the
973 // simple menu events like this the static method is much simpler.
974 BEGIN_EVENT_TABLE(MyFrame
, wxFrame
)
975 EVT_MENU (File_Quit
, MyFrame
::OnQuit
)
976 EVT_MENU (File_About
, MyFrame
::OnAbout
)
978 EVT_MENU_RANGE(MenuShow_First
, MenuShow_Last
, MyFrame
::OnShow
)
980 EVT_MENU_RANGE(MenuOption_First
, MenuOption_Last
, MyFrame
::OnOption
)
984 MyFrame
::MyFrame(const wxString
& title
, const wxPoint
& pos
, const wxSize
& size
)
985 : wxFrame((wxFrame
*)NULL
, -1, title
, pos
, size
)
987 // set the frame icon
988 SetIcon(wxICON(mondrian
));
990 wxMenu
*menuFile
= new wxMenu
;
991 menuFile
->Append(File_ShowDefault
, "&Default screen\tF1");
992 menuFile
->Append(File_ShowText
, "&Text screen\tF2");
993 menuFile
->Append(File_ShowLines
, "&Lines screen\tF3");
994 menuFile
->Append(File_ShowPolygons
, "&Polygons screen\tF4");
995 menuFile
->Append(File_ShowMask
, "wx&Mask screen\tF5");
996 menuFile
->Append(File_ShowOps
, "&ROP screen\tF6");
997 menuFile
->AppendSeparator();
998 menuFile
->Append(File_About
, "&About...\tCtrl-A", "Show about dialog");
999 menuFile
->AppendSeparator();
1000 menuFile
->Append(File_Quit
, "E&xit\tAlt-X", "Quit this program");
1002 wxMenu
*menuMapMode
= new wxMenu
;
1003 menuMapMode
->Append( MapMode_Text
, "&TEXT map mode" );
1004 menuMapMode
->Append( MapMode_Lometric
, "&LOMETRIC map mode" );
1005 menuMapMode
->Append( MapMode_Twips
, "T&WIPS map mode" );
1006 menuMapMode
->Append( MapMode_Points
, "&POINTS map mode" );
1007 menuMapMode
->Append( MapMode_Metric
, "&METRIC map mode" );
1009 wxMenu
*menuUserScale
= new wxMenu
;
1010 menuUserScale
->Append( UserScale_StretchHoriz
, "Stretch horizontally\tCtrl-H" );
1011 menuUserScale
->Append( UserScale_ShrinkHoriz
, "Shrink horizontally\tCtrl-G" );
1012 menuUserScale
->Append( UserScale_StretchVertic
, "Stretch vertically\tCtrl-V" );
1013 menuUserScale
->Append( UserScale_ShrinkVertic
, "Shrink vertically\tCtrl-W" );
1014 menuUserScale
->AppendSeparator();
1015 menuUserScale
->Append( UserScale_Restore
, "Restore to normal\tCtrl-0" );
1017 wxMenu
*menuAxis
= new wxMenu
;
1018 menuAxis
->Append( AxisMirror_Horiz
, "Mirror horizontally\tCtrl-M", "", TRUE
);
1019 menuAxis
->Append( AxisMirror_Vertic
, "Mirror vertically\tCtrl-N", "", TRUE
);
1021 wxMenu
*menuLogical
= new wxMenu
;
1022 menuLogical
->Append( LogicalOrigin_MoveDown
, "Move &down\tCtrl-D" );
1023 menuLogical
->Append( LogicalOrigin_MoveUp
, "Move &up\tCtrl-U" );
1024 menuLogical
->Append( LogicalOrigin_MoveLeft
, "Move &right\tCtrl-L" );
1025 menuLogical
->Append( LogicalOrigin_MoveRight
, "Move &left\tCtrl-R" );
1027 wxMenu
*menuColour
= new wxMenu
;
1028 menuColour
->Append( Colour_TextForeground
, "Text foreground..." );
1029 menuColour
->Append( Colour_TextBackground
, "Text background..." );
1030 menuColour
->Append( Colour_Background
, "Background colour..." );
1031 menuColour
->Append( Colour_BackgroundMode
, "Opaque/transparent\tCtrl-B", "", TRUE
);
1032 menuColour
->Append( Colour_TextureBackgound
, "Draw textured background\tCtrl-T", "", TRUE
);
1034 // now append the freshly created menu to the menu bar...
1035 wxMenuBar
*menuBar
= new wxMenuBar
;
1036 menuBar
->Append(menuFile
, "&File");
1037 menuBar
->Append(menuMapMode
, "&MapMode");
1038 menuBar
->Append(menuUserScale
, "&UserScale");
1039 menuBar
->Append(menuAxis
, "&Axis");
1040 menuBar
->Append(menuLogical
, "&LogicalOrigin");
1041 menuBar
->Append(menuColour
, "&Colours");
1043 // ... and attach this menu bar to the frame
1044 SetMenuBar(menuBar
);
1046 // create a status bar just for fun (by default with 1 pane only)
1048 SetStatusText("Welcome to wxWindows!");
1050 m_mapMode
= wxMM_TEXT
;
1053 m_xLogicalOrigin
= 0;
1054 m_yLogicalOrigin
= 0;
1056 m_yAxisReversed
= FALSE
;
1057 m_backgroundMode
= wxSOLID
;
1058 m_colourForeground
= *wxRED
;
1059 m_colourBackground
= *wxBLUE
;
1060 m_textureBackground
= FALSE
;
1062 m_canvas
= new MyCanvas( this );
1063 m_canvas
->SetScrollbars( 10, 10, 100, 240 );
1068 void MyFrame
::OnQuit(wxCommandEvent
& WXUNUSED(event
))
1070 // TRUE is to force the frame to close
1074 void MyFrame
::OnAbout(wxCommandEvent
& WXUNUSED(event
))
1077 msg
.Printf( wxT("This is the about dialog of the drawing sample.\n")
1078 wxT("This sample tests various primitive drawing functions\n")
1079 wxT("without any tests to prevent flicker.\n")
1080 wxT("Copyright (c) Robert Roebling 1999")
1083 wxMessageBox(msg
, "About Drawing", wxOK
| wxICON_INFORMATION
, this);
1086 void MyFrame
::OnShow(wxCommandEvent
& event
)
1088 m_canvas
->Show((ScreenToShow
)(event
.GetInt() - MenuShow_First
));
1091 void MyFrame
::OnOption(wxCommandEvent
& event
)
1093 switch (event
.GetInt())
1096 m_mapMode
= wxMM_TEXT
;
1098 case MapMode_Lometric
:
1099 m_mapMode
= wxMM_LOMETRIC
;
1102 m_mapMode
= wxMM_TWIPS
;
1104 case MapMode_Points
:
1105 m_mapMode
= wxMM_POINTS
;
1107 case MapMode_Metric
:
1108 m_mapMode
= wxMM_METRIC
;
1111 case LogicalOrigin_MoveDown
:
1112 m_yLogicalOrigin
+= 10;
1114 case LogicalOrigin_MoveUp
:
1115 m_yLogicalOrigin
-= 10;
1117 case LogicalOrigin_MoveLeft
:
1118 m_xLogicalOrigin
+= 10;
1120 case LogicalOrigin_MoveRight
:
1121 m_xLogicalOrigin
-= 10;
1124 case UserScale_StretchHoriz
:
1125 m_xUserScale
*= 1.10;
1127 case UserScale_ShrinkHoriz
:
1128 m_xUserScale
/= 1.10;
1130 case UserScale_StretchVertic
:
1131 m_yUserScale
*= 1.10;
1133 case UserScale_ShrinkVertic
:
1134 m_yUserScale
/= 1.10;
1136 case UserScale_Restore
:
1141 case AxisMirror_Vertic
:
1142 m_yAxisReversed
= !m_yAxisReversed
;
1144 case AxisMirror_Horiz
:
1145 m_xAxisReversed
= !m_xAxisReversed
;
1148 case Colour_TextForeground
:
1149 m_colourForeground
= SelectColour();
1151 case Colour_TextBackground
:
1152 m_colourBackground
= SelectColour();
1154 case Colour_Background
:
1156 wxColour col
= SelectColour();
1159 m_backgroundBrush
.SetColour(col
);
1163 case Colour_BackgroundMode
:
1164 m_backgroundMode
= m_backgroundMode
== wxSOLID ? wxTRANSPARENT
1168 case Colour_TextureBackgound
:
1169 m_textureBackground
= ! m_textureBackground
;
1177 m_canvas
->Refresh();
1180 void MyFrame
::PrepareDC(wxDC
& dc
)
1182 dc
.SetMapMode( m_mapMode
);
1183 dc
.SetUserScale( m_xUserScale
, m_yUserScale
);
1184 dc
.SetLogicalOrigin( m_xLogicalOrigin
, m_yLogicalOrigin
);
1185 dc
.SetAxisOrientation( !m_xAxisReversed
, m_yAxisReversed
);
1188 wxColour MyFrame
::SelectColour()
1192 wxColourDialog
dialog(this, &data
);
1194 if ( dialog
.ShowModal() == wxID_OK
)
1196 col
= dialog
.GetColourData().GetColour();