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
);
157 wxBitmap m_smile_bmp
;
160 DECLARE_EVENT_TABLE()
163 // ----------------------------------------------------------------------------
165 // ----------------------------------------------------------------------------
167 // IDs for the controls and the menu commands
175 File_ShowDefault
= MenuShow_First
,
181 MenuShow_Last
= File_ShowOps
,
185 MapMode_Text
= MenuOption_First
,
191 UserScale_StretchHoriz
,
192 UserScale_ShrinkHoriz
,
193 UserScale_StretchVertic
,
194 UserScale_ShrinkVertic
,
200 LogicalOrigin_MoveDown
,
201 LogicalOrigin_MoveUp
,
202 LogicalOrigin_MoveLeft
,
203 LogicalOrigin_MoveRight
,
205 Colour_TextForeground
,
206 Colour_TextBackground
,
208 Colour_BackgroundMode
,
209 Colour_TextureBackgound
,
211 MenuOption_Last
= Colour_TextureBackgound
214 // ----------------------------------------------------------------------------
215 // event tables and other macros for wxWindows
216 // ----------------------------------------------------------------------------
219 // Create a new application object: this macro will allow wxWindows to create
220 // the application object during program execution (it's better than using a
221 // static object for many reasons) and also declares the accessor function
222 // wxGetApp() which will return the reference of the right type (i.e. MyApp and
226 // ============================================================================
228 // ============================================================================
230 // ----------------------------------------------------------------------------
231 // the application class
232 // ----------------------------------------------------------------------------
234 bool MyApp::LoadImages()
240 wxString path
= pathList
.FindValidPath("pat4.bmp");
243 gs_bmp4
.LoadFile(path
, wxBITMAP_TYPE_BMP
);
244 wxMask
* mask4
= new wxMask(gs_bmp4
, *wxBLACK
);
245 gs_bmp4
.SetMask(mask4
);
247 path
= pathList
.FindValidPath("pat36.bmp");
250 gs_bmp36
.LoadFile(path
, wxBITMAP_TYPE_BMP
);
251 wxMask
* mask36
= new wxMask(gs_bmp36
, *wxBLACK
);
252 gs_bmp36
.SetMask(mask36
);
254 path
= pathList
.FindValidPath("image.bmp");
257 gs_bmpNoMask
.LoadFile(path
, wxBITMAP_TYPE_BMP
);
258 gs_bmpWithMask
.LoadFile(path
, wxBITMAP_TYPE_BMP
);
259 gs_bmpWithColMask
.LoadFile(path
, wxBITMAP_TYPE_BMP
);
261 path
= pathList
.FindValidPath("mask.bmp");
264 gs_bmpMask
.LoadFile(path
, wxBITMAP_TYPE_BMP
);
266 // This is so wrong, it hurts.
267 // gs_bmpMask.SetDepth(1);
268 // wxMask *mask = new wxMask(gs_bmpMask);
270 wxMask
*mask
= new wxMask(gs_bmpMask
, *wxBLACK
);
271 gs_bmpWithMask
.SetMask(mask
);
273 mask
= new wxMask(gs_bmpWithColMask
, *wxWHITE
);
274 gs_bmpWithColMask
.SetMask(mask
);
279 // `Main program' equivalent: the program execution "starts" here
282 // Create the main application window
283 MyFrame
*frame
= new MyFrame("Drawing sample",
284 wxPoint(50, 50), wxSize(550, 340));
286 // Show it and tell the application that it's our main window
292 wxLogError("Can't load one of the bitmap files needed for this sample "
293 "from the current or parent directory, please copy them "
304 // ----------------------------------------------------------------------------
306 // ----------------------------------------------------------------------------
308 // the event tables connect the wxWindows events with the functions (event
309 // handlers) which process them.
310 BEGIN_EVENT_TABLE(MyCanvas
, wxScrolledWindow
)
311 EVT_PAINT (MyCanvas::OnPaint
)
312 EVT_MOTION (MyCanvas::OnMouseMove
)
315 #include "../image/smile.xpm"
317 MyCanvas::MyCanvas( MyFrame
*parent
) : wxScrolledWindow( parent
)
320 m_show
= Show_Default
;
321 m_smile_bmp
= wxBitmap(smile_xpm
);
322 m_std_icon
= wxTheApp
->GetStdIcon(wxICON_INFORMATION
);
325 //draw a polygon and an overlapping rectangle
326 //is transparent is 1, the fill pattern are made transparent
327 //is transparent is 2, the fill pattern are made transparent but inversed
328 //is transparent is 0 the text for and background color will be used to represent/map
329 //the colors of the monochrome bitmap pixels to the fillpattern
331 //i miss_used the the menu items for setting so called back and fore ground color
332 //just to show how the those colors do influence the fillpatterns
333 //just play with those,
335 //variations are endless using other logical functions
336 void MyCanvas::DrawTestPoly( int x
, int y
,wxDC
&dc
,int transparent
)
338 wxBrush
* brush4
= new wxBrush(gs_bmp4
);
339 wxBrush
* brush36
= new wxBrush(gs_bmp36
);
342 todraw
[0].x
=(long)x
+100;
343 todraw
[0].y
=(long)y
+100;
344 todraw
[1].x
=(long)x
+300;
345 todraw
[1].y
=(long)y
+100;
346 todraw
[2].x
=(long)x
+300;
347 todraw
[2].y
=(long)y
+300;
348 todraw
[3].x
=(long)x
+150;
349 todraw
[3].y
=(long)y
+350;
350 todraw
[4].x
=(long)x
+100;
351 todraw
[4].y
=(long)y
+300;
369 dc
.SetPen( wxPen( "black", 4, wxSOLID
) );
370 dc
.SetBrush( *brush4
);
371 dc
.SetTextForeground(*wxGREEN
);
372 dc
.SetTextBackground(m_owner
->m_colourForeground
);
373 dc
.SetLogicalFunction(wxCOPY
);
374 dc
.DrawPolygon(5,todraw
,0,0,wxWINDING_RULE
);
376 //don't understand hwo but the outline is also depending on logicalfunction
377 dc
.SetPen( wxPen( "red", 4, wxSOLID
) );
378 dc
.SetBrush( *brush36
);
379 dc
.SetTextForeground(*wxCYAN
);
380 dc
.SetTextBackground(m_owner
->m_colourBackground
);
381 dc
.SetLogicalFunction(wxCOPY
);
382 dc
.DrawRectangle( x
+10, y
+10, 200, 200 );
383 dc
.SetBrush(wxNullBrush
);
384 dc
.SetPen(wxNullPen
);
387 case 1: //now with transparent fillpatterns
390 wxBitmap
* bmpBlit
= new wxBitmap(600,400);
391 wxMemoryDC
* memDC
= new wxMemoryDC();
392 // wxBrush _clearbrush(*wxGREEN,wxSOLID);
393 wxBrush
_clearbrush(*wxBLACK
,wxSOLID
);
394 memDC
->SelectObject(*bmpBlit
);
395 memDC
->BeginDrawing();
396 memDC
->SetBackground(_clearbrush
);
398 memDC
->SetBackground(wxNullBrush
);
400 memDC
->SetPen( wxPen( "black", 4, wxSOLID
) );
401 memDC
->SetBrush( wxNullBrush
);
402 memDC
->SetBrush( *brush4
);
403 memDC
->SetTextForeground(*wxBLACK
); // 0s --> 0x000000 (black)
404 memDC
->SetTextBackground(*wxWHITE
); // 1s --> 0xFFFFFF (white)
405 memDC
->SetLogicalFunction(wxAND_INVERT
);
407 // BLACK OUT the opaque pixels and leave the rest as is
408 memDC
->DrawPolygon(5,todraw2
,0,0,wxWINDING_RULE
);
410 // Set background and foreground colors for fill pattern
411 //the previous blacked out pixels are now merged with the layer color
412 //while the non blacked out pixels stay as they are.
413 memDC
->SetTextForeground(*wxBLACK
); // 0s --> 0x000000 (black)
415 //now define what will be the color of the fillpattern parts that are not transparent
416 // memDC->SetTextBackground(*wxBLUE);
417 memDC
->SetTextBackground(m_owner
->m_colourForeground
);
418 memDC
->SetLogicalFunction(wxOR
);
421 //don't understand how but the outline is also depending on logicalfunction
422 memDC
->SetPen( wxPen( "red", 4, wxSOLID
) );
423 memDC
->DrawPolygon(5,todraw2
,0,0,wxWINDING_RULE
);
425 memDC
->SetLogicalFunction(wxCOPY
);
427 memDC
->SetPen( wxPen( "black", 4, wxSOLID
) );
428 memDC
->SetBrush( wxNullBrush
);
429 memDC
->SetBrush( *brush36
);
430 memDC
->SetTextForeground(*wxBLACK
); // 0s --> 0x000000 (black)
431 memDC
->SetTextBackground(*wxWHITE
); // 1s --> 0xFFFFFF (white)
432 memDC
->SetLogicalFunction(wxAND_INVERT
);
434 memDC
->DrawRectangle( 10, 10, 200, 200 );
436 // Set background and foreground colors for fill pattern
437 //the previous blacked out pixels are now merged with the layer color
438 //while the non blacked out pixels stay as they are.
439 memDC
->SetTextForeground(*wxBLACK
); // 0s --> 0x000000 (black)
440 //now define what will be the color of the fillpattern parts that are not transparent
441 // memDC->SetTextBackground(*wxRED);
442 memDC
->SetTextBackground(m_owner
->m_colourBackground
);
443 memDC
->SetLogicalFunction(wxOR
);
445 //don't understand how but the outline is also depending on logicalfunction
446 memDC
->SetPen( wxPen( "yellow", 4, wxSOLID
) );
447 memDC
->DrawRectangle( 10, 10, 200, 200 );
449 memDC
->SetBrush(wxNullBrush
);
450 memDC
->SetPen(wxNullPen
);
453 dc
.Blit(x
,y
,600,400,memDC
,0,0,wxCOPY
);
458 case 2: //now with transparent inversed fillpatterns
460 wxBitmap
* bmpBlit
= new wxBitmap(600,400);
461 wxMemoryDC
* memDC
= new wxMemoryDC();
462 wxBrush
_clearbrush(*wxWHITE
,wxSOLID
);
463 memDC
->SelectObject(*bmpBlit
);
464 memDC
->BeginDrawing();
465 memDC
->SetBackground(_clearbrush
);
467 memDC
->SetBackground(wxNullBrush
);
469 memDC
->SetPen( wxPen( "black", 4, wxSOLID
) );
470 memDC
->SetBrush( *brush4
);
471 memDC
->SetTextBackground(*wxBLACK
); // 0s --> 0x000000 (black)
472 memDC
->SetTextForeground(*wxWHITE
); // 1s --> 0xFFFFFF (white)
473 memDC
->SetLogicalFunction(wxAND_INVERT
);
475 // BLACK OUT the opaque pixels and leave the rest as is
476 memDC
->DrawPolygon(5,todraw2
,0,0,wxWINDING_RULE
);
478 // Set background and foreground colors for fill pattern
479 //the previous blacked out pixels are now merged with the layer color
480 //while the non blacked out pixels stay as they are.
481 memDC
->SetTextBackground(*wxBLACK
); // 0s --> 0x000000 (black)
483 //now define what will be the color of the fillpattern parts that are not transparent
484 memDC
->SetTextForeground(m_owner
->m_colourForeground
);
485 memDC
->SetLogicalFunction(wxOR
);
488 //don't understand how but the outline is also depending on logicalfunction
489 memDC
->SetPen( wxPen( "red", 4, wxSOLID
) );
490 memDC
->DrawPolygon(5,todraw2
,0,0,wxWINDING_RULE
);
492 memDC
->SetLogicalFunction(wxCOPY
);
494 memDC
->SetPen( wxPen( "black", 4, wxSOLID
) );
495 memDC
->SetBrush( *brush36
);
496 memDC
->SetTextBackground(*wxBLACK
); // 0s --> 0x000000 (black)
497 memDC
->SetTextForeground(*wxWHITE
); // 1s --> 0xFFFFFF (white)
498 memDC
->SetLogicalFunction(wxAND_INVERT
);
500 memDC
->DrawRectangle( 10,10, 200, 200 );
502 // Set background and foreground colors for fill pattern
503 //the previous blacked out pixels are now merged with the layer color
504 //while the non blacked out pixels stay as they are.
505 memDC
->SetTextBackground(*wxBLACK
); // 0s --> 0x000000 (black)
506 //now define what will be the color of the fillpattern parts that are not transparent
507 memDC
->SetTextForeground(m_owner
->m_colourBackground
);
508 memDC
->SetLogicalFunction(wxOR
);
510 //don't understand how but the outline is also depending on logicalfunction
511 memDC
->SetPen( wxPen( "yellow", 4, wxSOLID
) );
512 memDC
->DrawRectangle( 10, 10, 200, 200 );
514 memDC
->SetBrush(wxNullBrush
);
515 memDC
->SetPen(wxNullPen
);
516 dc
.Blit(x
,y
,600,400,memDC
,0,0,wxCOPY
);
526 void MyCanvas::DrawTestLines( int x
, int y
, int width
, wxDC
&dc
)
528 dc
.SetPen( wxPen( "black", width
, wxSOLID
) );
529 dc
.SetBrush( *wxRED_BRUSH
);
530 dc
.DrawRectangle( x
+10, y
+10, 100, 190 );
532 dc
.SetPen( wxPen( "black", width
, wxSOLID
) );
533 dc
.DrawLine( x
+20, y
+20, 100, y
+20 );
534 dc
.SetPen( wxPen( "black", width
, wxDOT
) );
535 dc
.DrawLine( x
+20, y
+30, 100, y
+30 );
536 dc
.SetPen( wxPen( "black", width
, wxSHORT_DASH
) );
537 dc
.DrawLine( x
+20, y
+40, 100, y
+40 );
538 dc
.SetPen( wxPen( "black", width
, wxLONG_DASH
) );
539 dc
.DrawLine( x
+20, y
+50, 100, y
+50 );
540 dc
.SetPen( wxPen( "black", width
, wxDOT_DASH
) );
541 dc
.DrawLine( x
+20, y
+60, 100, y
+60 );
543 dc
.SetPen( wxPen( "black", width
, wxBDIAGONAL_HATCH
) );
544 dc
.DrawLine( x
+20, y
+70, 100, y
+70 );
545 dc
.SetPen( wxPen( "black", width
, wxCROSSDIAG_HATCH
) );
546 dc
.DrawLine( x
+20, y
+80, 100, y
+80 );
547 dc
.SetPen( wxPen( "black", width
, wxFDIAGONAL_HATCH
) );
548 dc
.DrawLine( x
+20, y
+90, 100, y
+90 );
549 dc
.SetPen( wxPen( "black", width
, wxCROSS_HATCH
) );
550 dc
.DrawLine( x
+20, y
+100, 100, y
+100 );
551 dc
.SetPen( wxPen( "black", width
, wxHORIZONTAL_HATCH
) );
552 dc
.DrawLine( x
+20, y
+110, 100, y
+110 );
553 dc
.SetPen( wxPen( "black", width
, wxVERTICAL_HATCH
) );
554 dc
.DrawLine( x
+20, y
+120, 100, y
+120 );
556 wxPen
ud( "black", width
, wxUSER_DASH
);
559 ud
.SetDashes( 1, dash1
);
560 dc
.DrawLine( x
+20, y
+140, 100, y
+140 );
562 ud
.SetDashes( 1, dash1
);
563 dc
.DrawLine( x
+20, y
+150, 100, y
+150 );
565 ud
.SetDashes( 1, dash1
);
566 dc
.DrawLine( x
+20, y
+160, 100, y
+160 );
568 ud
.SetDashes( 1, dash1
);
569 dc
.DrawLine( x
+20, y
+170, 100, y
+170 );
572 void MyCanvas::DrawDefault(wxDC
& dc
)
575 dc
.DrawCircle(0, 0, 10);
576 #if !(defined __WXGTK__) && !(defined __WXMOTIF__)
577 // not implemented in wxGTK or wxMOTIF :-(
578 dc
.FloodFill(0, 0, wxColour(255, 0, 0));
581 dc
.DrawIcon( wxICON(mondrian
), 40, 40 );
583 dc
.DrawCheckMark(5, 80, 15, 15);
584 dc
.DrawCheckMark(25, 80, 30, 30);
585 dc
.DrawCheckMark(60, 80, 60, 60);
587 // this is the test for "blitting bitmap into DC damages selected brush" bug
588 wxIcon m_std_icon
= wxTheApp
->GetStdIcon(wxICON_INFORMATION
);
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::OnPaint(wxPaintEvent
&WXUNUSED(event
))
898 m_owner
->PrepareDC(dc
);
900 dc
.SetBackgroundMode( m_owner
->m_backgroundMode
);
901 if ( m_owner
->m_backgroundBrush
.Ok() )
902 dc
.SetBackground( m_owner
->m_backgroundBrush
);
903 if ( m_owner
->m_colourForeground
.Ok() )
904 dc
.SetTextForeground( m_owner
->m_colourForeground
);
905 if ( m_owner
->m_colourBackground
.Ok() )
906 dc
.SetTextBackground( m_owner
->m_colourBackground
);
908 if ( m_owner
->m_textureBackground
) {
909 if ( ! m_owner
->m_backgroundBrush
.Ok() ) {
910 wxBrush
b(wxColour(0,128,0), wxSOLID
);
917 if ( m_owner
->m_textureBackground
) {
918 dc
.SetPen(*wxMEDIUM_GREY_PEN
);
919 for (int i
=0; i
<200; i
++)
920 dc
.DrawLine(0, i
*10, i
*10, 0);
934 DrawTestLines( 0, 100, 0, dc
);
935 DrawTestLines( 0, 300, 1, dc
);
936 DrawTestLines( 0, 500, 2, dc
);
937 DrawTestLines( 0, 700, 6, dc
);
941 DrawTestPoly( 0, 100, dc
, 0 );
942 DrawTestPoly( 33, 500, dc
, 1 );
943 DrawTestPoly( 43, 1000, dc
, 2 );
951 DrawWithLogicalOps(dc
);
956 void MyCanvas::OnMouseMove(wxMouseEvent
&event
)
960 m_owner
->PrepareDC(dc
);
962 wxPoint pos
= event
.GetPosition();
963 long x
= dc
.DeviceToLogicalX( pos
.x
);
964 long y
= dc
.DeviceToLogicalY( pos
.y
);
966 str
.Printf( "Current mouse position: %d,%d", (int)x
, (int)y
);
967 m_owner
->SetStatusText( str
);
970 // ----------------------------------------------------------------------------
972 // ----------------------------------------------------------------------------
974 // the event tables connect the wxWindows events with the functions (event
975 // handlers) which process them. It can be also done at run-time, but for the
976 // simple menu events like this the static method is much simpler.
977 BEGIN_EVENT_TABLE(MyFrame
, wxFrame
)
978 EVT_MENU (File_Quit
, MyFrame::OnQuit
)
979 EVT_MENU (File_About
, MyFrame::OnAbout
)
981 EVT_MENU_RANGE(MenuShow_First
, MenuShow_Last
, MyFrame::OnShow
)
983 EVT_MENU_RANGE(MenuOption_First
, MenuOption_Last
, MyFrame::OnOption
)
987 MyFrame::MyFrame(const wxString
& title
, const wxPoint
& pos
, const wxSize
& size
)
988 : wxFrame((wxFrame
*)NULL
, -1, title
, pos
, size
)
990 // set the frame icon
991 SetIcon(wxICON(mondrian
));
993 wxMenu
*menuFile
= new wxMenu
;
994 menuFile
->Append(File_ShowDefault
, "&Default screen\tF1");
995 menuFile
->Append(File_ShowText
, "&Text screen\tF2");
996 menuFile
->Append(File_ShowLines
, "&Lines screen\tF3");
997 menuFile
->Append(File_ShowPolygons
, "&Polygons screen\tF4");
998 menuFile
->Append(File_ShowMask
, "wx&Mask screen\tF5");
999 menuFile
->Append(File_ShowOps
, "&ROP screen\tF6");
1000 menuFile
->AppendSeparator();
1001 menuFile
->Append(File_About
, "&About...\tCtrl-A", "Show about dialog");
1002 menuFile
->AppendSeparator();
1003 menuFile
->Append(File_Quit
, "E&xit\tAlt-X", "Quit this program");
1005 wxMenu
*menuMapMode
= new wxMenu
;
1006 menuMapMode
->Append( MapMode_Text
, "&TEXT map mode" );
1007 menuMapMode
->Append( MapMode_Lometric
, "&LOMETRIC map mode" );
1008 menuMapMode
->Append( MapMode_Twips
, "T&WIPS map mode" );
1009 menuMapMode
->Append( MapMode_Points
, "&POINTS map mode" );
1010 menuMapMode
->Append( MapMode_Metric
, "&METRIC map mode" );
1012 wxMenu
*menuUserScale
= new wxMenu
;
1013 menuUserScale
->Append( UserScale_StretchHoriz
, "Stretch horizontally\tCtrl-H" );
1014 menuUserScale
->Append( UserScale_ShrinkHoriz
, "Shrink horizontally\tCtrl-G" );
1015 menuUserScale
->Append( UserScale_StretchVertic
, "Stretch vertically\tCtrl-V" );
1016 menuUserScale
->Append( UserScale_ShrinkVertic
, "Shrink vertically\tCtrl-W" );
1017 menuUserScale
->AppendSeparator();
1018 menuUserScale
->Append( UserScale_Restore
, "Restore to normal\tCtrl-0" );
1020 wxMenu
*menuAxis
= new wxMenu
;
1021 menuAxis
->Append( AxisMirror_Horiz
, "Mirror horizontally\tCtrl-M", "", TRUE
);
1022 menuAxis
->Append( AxisMirror_Vertic
, "Mirror vertically\tCtrl-N", "", TRUE
);
1024 wxMenu
*menuLogical
= new wxMenu
;
1025 menuLogical
->Append( LogicalOrigin_MoveDown
, "Move &down\tCtrl-D" );
1026 menuLogical
->Append( LogicalOrigin_MoveUp
, "Move &up\tCtrl-U" );
1027 menuLogical
->Append( LogicalOrigin_MoveLeft
, "Move &right\tCtrl-L" );
1028 menuLogical
->Append( LogicalOrigin_MoveRight
, "Move &left\tCtrl-R" );
1030 wxMenu
*menuColour
= new wxMenu
;
1031 menuColour
->Append( Colour_TextForeground
, "Text foreground..." );
1032 menuColour
->Append( Colour_TextBackground
, "Text background..." );
1033 menuColour
->Append( Colour_Background
, "Background colour..." );
1034 menuColour
->Append( Colour_BackgroundMode
, "Opaque/transparent\tCtrl-B", "", TRUE
);
1035 menuColour
->Append( Colour_TextureBackgound
, "Draw textured background\tCtrl-T", "", TRUE
);
1037 // now append the freshly created menu to the menu bar...
1038 wxMenuBar
*menuBar
= new wxMenuBar
;
1039 menuBar
->Append(menuFile
, "&File");
1040 menuBar
->Append(menuMapMode
, "&MapMode");
1041 menuBar
->Append(menuUserScale
, "&UserScale");
1042 menuBar
->Append(menuAxis
, "&Axis");
1043 menuBar
->Append(menuLogical
, "&LogicalOrigin");
1044 menuBar
->Append(menuColour
, "&Colours");
1046 // ... and attach this menu bar to the frame
1047 SetMenuBar(menuBar
);
1049 // create a status bar just for fun (by default with 1 pane only)
1051 SetStatusText("Welcome to wxWindows!");
1053 m_mapMode
= wxMM_TEXT
;
1056 m_xLogicalOrigin
= 0;
1057 m_yLogicalOrigin
= 0;
1059 m_yAxisReversed
= FALSE
;
1060 m_backgroundMode
= wxSOLID
;
1061 m_colourForeground
= *wxRED
;
1062 m_colourBackground
= *wxBLUE
;
1063 m_textureBackground
= FALSE
;
1065 m_canvas
= new MyCanvas( this );
1066 m_canvas
->SetScrollbars( 10, 10, 100, 240 );
1071 void MyFrame::OnQuit(wxCommandEvent
& WXUNUSED(event
))
1073 // TRUE is to force the frame to close
1077 void MyFrame::OnAbout(wxCommandEvent
& WXUNUSED(event
))
1080 msg
.Printf( wxT("This is the about dialog of the drawing sample.\n")
1081 wxT("This sample tests various primitive drawing functions\n")
1082 wxT("without any tests to prevent flicker.\n")
1083 wxT("Copyright (c) Robert Roebling 1999")
1086 wxMessageBox(msg
, "About Drawing", wxOK
| wxICON_INFORMATION
, this);
1089 void MyFrame::OnShow(wxCommandEvent
& event
)
1091 m_canvas
->Show((ScreenToShow
)(event
.GetInt() - MenuShow_First
));
1094 void MyFrame::OnOption(wxCommandEvent
& event
)
1096 switch (event
.GetInt())
1099 m_mapMode
= wxMM_TEXT
;
1101 case MapMode_Lometric
:
1102 m_mapMode
= wxMM_LOMETRIC
;
1105 m_mapMode
= wxMM_TWIPS
;
1107 case MapMode_Points
:
1108 m_mapMode
= wxMM_POINTS
;
1110 case MapMode_Metric
:
1111 m_mapMode
= wxMM_METRIC
;
1114 case LogicalOrigin_MoveDown
:
1115 m_yLogicalOrigin
+= 10;
1117 case LogicalOrigin_MoveUp
:
1118 m_yLogicalOrigin
-= 10;
1120 case LogicalOrigin_MoveLeft
:
1121 m_xLogicalOrigin
+= 10;
1123 case LogicalOrigin_MoveRight
:
1124 m_xLogicalOrigin
-= 10;
1127 case UserScale_StretchHoriz
:
1128 m_xUserScale
*= 1.10;
1130 case UserScale_ShrinkHoriz
:
1131 m_xUserScale
/= 1.10;
1133 case UserScale_StretchVertic
:
1134 m_yUserScale
*= 1.10;
1136 case UserScale_ShrinkVertic
:
1137 m_yUserScale
/= 1.10;
1139 case UserScale_Restore
:
1144 case AxisMirror_Vertic
:
1145 m_yAxisReversed
= !m_yAxisReversed
;
1147 case AxisMirror_Horiz
:
1148 m_xAxisReversed
= !m_xAxisReversed
;
1151 case Colour_TextForeground
:
1152 m_colourForeground
= SelectColour();
1154 case Colour_TextBackground
:
1155 m_colourBackground
= SelectColour();
1157 case Colour_Background
:
1159 wxColour col
= SelectColour();
1162 m_backgroundBrush
.SetColour(col
);
1166 case Colour_BackgroundMode
:
1167 m_backgroundMode
= m_backgroundMode
== wxSOLID
? wxTRANSPARENT
1171 case Colour_TextureBackgound
:
1172 m_textureBackground
= ! m_textureBackground
;
1180 m_canvas
->Refresh();
1183 void MyFrame::PrepareDC(wxDC
& dc
)
1185 dc
.SetMapMode( m_mapMode
);
1186 dc
.SetUserScale( m_xUserScale
, m_yUserScale
);
1187 dc
.SetLogicalOrigin( m_xLogicalOrigin
, m_yLogicalOrigin
);
1188 dc
.SetAxisOrientation( !m_xAxisReversed
, m_yAxisReversed
);
1191 wxColour
MyFrame::SelectColour()
1195 wxColourDialog
dialog(this, &data
);
1197 if ( dialog
.ShowModal() == wxID_OK
)
1199 col
= dialog
.GetColourData().GetColour();