don't use wxApp::GetStdIcon
[wxWidgets.git] / samples / drawing / drawing.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: drawing.cpp
3 // Purpose: shows and tests wxDC features
4 // Author: Robert Roebling
5 // Modified by:
6 // Created: 04/01/98
7 // RCS-ID: $Id$
8 // Copyright: (c) Robert Roebling
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 // ============================================================================
13 // declarations
14 // ============================================================================
15
16 // ----------------------------------------------------------------------------
17 // headers
18 // ----------------------------------------------------------------------------
19
20 #ifdef __GNUG__
21 #pragma implementation "drawing.cpp"
22 #pragma interface "drawing.cpp"
23 #endif
24
25 // For compilers that support precompilation, includes "wx/wx.h".
26 #include "wx/wxprec.h"
27
28 #ifdef __BORLANDC__
29 #pragma hdrstop
30 #endif
31
32 // for all others, include the necessary headers (this file is usually all you
33 // need because it includes almost all "standard" wxWindows headers
34 #ifndef WX_PRECOMP
35 #include "wx/wx.h"
36 #endif
37
38 #include "wx/colordlg.h"
39 #include "wx/image.h"
40 #include "wx/artprov.h"
41
42 // ----------------------------------------------------------------------------
43 // ressources
44 // ----------------------------------------------------------------------------
45
46 // the application icon
47 #if defined(__WXGTK__) || defined(__WXMOTIF__) || defined(__WXMAC__) || defined(__WXMGL__) || defined(__WXX11__)
48 #include "mondrian.xpm"
49 #endif
50
51 // ----------------------------------------------------------------------------
52 // constants
53 // ----------------------------------------------------------------------------
54
55 // what do we show on screen (there are too many shapes to put them all on
56 // screen simultaneously)
57 enum ScreenToShow
58 {
59 Show_Default,
60 Show_Text,
61 Show_Lines,
62 Show_Brushes,
63 Show_Polygons,
64 Show_Mask,
65 Show_Ops,
66 Show_Regions,
67 Show_Circles
68 };
69
70 // ----------------------------------------------------------------------------
71 // global variables
72 // ----------------------------------------------------------------------------
73
74 static wxBitmap *gs_bmpNoMask = NULL,
75 *gs_bmpWithColMask = NULL,
76 *gs_bmpMask = NULL,
77 *gs_bmpWithMask = NULL,
78 *gs_bmp4 = NULL,
79 *gs_bmp4_mono = NULL,
80 *gs_bmp36 = NULL;
81
82 // ----------------------------------------------------------------------------
83 // private classes
84 // ----------------------------------------------------------------------------
85
86 // Define a new application type, each program should derive a class from wxApp
87 class MyApp : public wxApp
88 {
89 public:
90 // override base class virtuals
91 // ----------------------------
92
93 // this one is called on application startup and is a good place for the app
94 // initialization (doing it here and not in the ctor allows to have an error
95 // return: if OnInit() returns false, the application terminates)
96 virtual bool OnInit();
97
98 virtual int OnExit() { DeleteBitmaps(); return 0; }
99
100 protected:
101 void DeleteBitmaps();
102
103 bool LoadImages();
104 };
105
106 class MyCanvas;
107
108 // Define a new frame type: this is going to be our main frame
109 class MyFrame : public wxFrame
110 {
111 public:
112 // ctor(s)
113 MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size);
114
115 // event handlers (these functions should _not_ be virtual)
116 void OnQuit(wxCommandEvent& event);
117 void OnAbout(wxCommandEvent& event);
118 void OnShow(wxCommandEvent &event);
119 void OnOption(wxCommandEvent &event);
120
121 wxColour SelectColour();
122 void PrepareDC(wxDC& dc);
123
124 int m_backgroundMode;
125 int m_textureBackground;
126 int m_mapMode;
127 double m_xUserScale;
128 double m_yUserScale;
129 int m_xLogicalOrigin;
130 int m_yLogicalOrigin;
131 bool m_xAxisReversed,
132 m_yAxisReversed;
133 wxColour m_colourForeground, // these are _text_ colours
134 m_colourBackground;
135 wxBrush m_backgroundBrush;
136 MyCanvas *m_canvas;
137
138 private:
139 // any class wishing to process wxWindows events must use this macro
140 DECLARE_EVENT_TABLE()
141 };
142
143 // define a scrollable canvas for drawing onto
144 class MyCanvas: public wxScrolledWindow
145 {
146 public:
147 MyCanvas( MyFrame *parent );
148
149 void OnPaint(wxPaintEvent &event);
150 void OnMouseMove(wxMouseEvent &event);
151
152 void Show(ScreenToShow show) { m_show = show; Refresh(); }
153
154 protected:
155 void DrawTestLines( int x, int y, int width, wxDC &dc );
156 void DrawTestPoly(wxDC& dc);
157 void DrawTestBrushes(wxDC& dc);
158 void DrawText(wxDC& dc);
159 void DrawImages(wxDC& dc);
160 void DrawWithLogicalOps(wxDC& dc);
161 void DrawRegions(wxDC& dc);
162 void DrawCircles(wxDC& dc);
163 void DrawDefault(wxDC& dc);
164
165 void DrawRegionsHelper(wxDC& dc, wxCoord x, bool firstTime);
166
167 private:
168 MyFrame *m_owner;
169
170 ScreenToShow m_show;
171 wxBitmap m_smile_bmp;
172 wxIcon m_std_icon;
173
174 DECLARE_EVENT_TABLE()
175 };
176
177 // ----------------------------------------------------------------------------
178 // constants
179 // ----------------------------------------------------------------------------
180
181 // IDs for the controls and the menu commands
182 enum
183 {
184 // menu items
185 File_Quit = 1,
186 File_About,
187
188 MenuShow_First,
189 File_ShowDefault = MenuShow_First,
190 File_ShowText,
191 File_ShowLines,
192 File_ShowBrushes,
193 File_ShowPolygons,
194 File_ShowMask,
195 File_ShowOps,
196 File_ShowRegions,
197 File_ShowCircles,
198 MenuShow_Last = File_ShowCircles,
199
200 MenuOption_First,
201
202 MapMode_Text = MenuOption_First,
203 MapMode_Lometric,
204 MapMode_Twips,
205 MapMode_Points,
206 MapMode_Metric,
207
208 UserScale_StretchHoriz,
209 UserScale_ShrinkHoriz,
210 UserScale_StretchVertic,
211 UserScale_ShrinkVertic,
212 UserScale_Restore,
213
214 AxisMirror_Horiz,
215 AxisMirror_Vertic,
216
217 LogicalOrigin_MoveDown,
218 LogicalOrigin_MoveUp,
219 LogicalOrigin_MoveLeft,
220 LogicalOrigin_MoveRight,
221 LogicalOrigin_Set,
222 LogicalOrigin_Restore,
223
224 Colour_TextForeground,
225 Colour_TextBackground,
226 Colour_Background,
227 Colour_BackgroundMode,
228 Colour_TextureBackgound,
229
230 MenuOption_Last = Colour_TextureBackgound
231 };
232
233 // ----------------------------------------------------------------------------
234 // event tables and other macros for wxWindows
235 // ----------------------------------------------------------------------------
236
237
238 // Create a new application object: this macro will allow wxWindows to create
239 // the application object during program execution (it's better than using a
240 // static object for many reasons) and also declares the accessor function
241 // wxGetApp() which will return the reference of the right type (i.e. MyApp and
242 // not wxApp)
243 IMPLEMENT_APP(MyApp)
244
245 // ============================================================================
246 // implementation
247 // ============================================================================
248
249 // ----------------------------------------------------------------------------
250 // the application class
251 // ----------------------------------------------------------------------------
252
253 bool MyApp::LoadImages()
254 {
255 gs_bmpNoMask = new wxBitmap;
256 gs_bmpWithColMask = new wxBitmap;
257 gs_bmpMask = new wxBitmap;
258 gs_bmpWithMask = new wxBitmap;
259 gs_bmp4 = new wxBitmap;
260 gs_bmp4_mono = new wxBitmap;
261 gs_bmp36 = new wxBitmap;
262
263 wxPathList pathList;
264 pathList.Add(".");
265 pathList.Add("..");
266
267 wxString path = pathList.FindValidPath("pat4.bmp");
268 if ( !path )
269 return FALSE;
270
271 /* 4 colour bitmap */
272 gs_bmp4->LoadFile(path, wxBITMAP_TYPE_BMP);
273 /* turn into mono-bitmap */
274 gs_bmp4_mono->LoadFile(path, wxBITMAP_TYPE_BMP);
275 wxMask* mask4 = new wxMask(*gs_bmp4_mono, *wxBLACK);
276 gs_bmp4_mono->SetMask(mask4);
277
278 path = pathList.FindValidPath("pat36.bmp");
279 if ( !path )
280 return FALSE;
281 gs_bmp36->LoadFile(path, wxBITMAP_TYPE_BMP);
282 wxMask* mask36 = new wxMask(*gs_bmp36, *wxBLACK);
283 gs_bmp36->SetMask(mask36);
284
285 path = pathList.FindValidPath("image.bmp");
286 if ( !path )
287 return FALSE;
288 gs_bmpNoMask->LoadFile(path, wxBITMAP_TYPE_BMP);
289 gs_bmpWithMask->LoadFile(path, wxBITMAP_TYPE_BMP);
290 gs_bmpWithColMask->LoadFile(path, wxBITMAP_TYPE_BMP);
291
292 path = pathList.FindValidPath("mask.bmp");
293 if ( !path )
294 return FALSE;
295 gs_bmpMask->LoadFile(path, wxBITMAP_TYPE_BMP);
296
297 wxMask *mask = new wxMask(*gs_bmpMask, *wxBLACK);
298 gs_bmpWithMask->SetMask(mask);
299
300 mask = new wxMask(*gs_bmpWithColMask, *wxWHITE);
301 gs_bmpWithColMask->SetMask(mask);
302
303 return TRUE;
304 }
305
306 // `Main program' equivalent: the program execution "starts" here
307 bool MyApp::OnInit()
308 {
309 // Create the main application window
310 MyFrame *frame = new MyFrame("Drawing sample",
311 wxPoint(50, 50), wxSize(550, 340));
312
313 // Show it and tell the application that it's our main window
314 frame->Show(TRUE);
315 SetTopWindow(frame);
316
317 if ( !LoadImages() )
318 {
319 wxLogError(wxT("Can't load one of the bitmap files needed ")
320 wxT("for this sample from the current or parent ")
321 wxT("directory, please copy them there."));
322
323 // stop here
324 DeleteBitmaps();
325
326 return FALSE;
327 }
328
329 // ok, continue
330 return TRUE;
331 }
332
333 void MyApp::DeleteBitmaps()
334 {
335 delete gs_bmpNoMask;
336 delete gs_bmpWithColMask;
337 delete gs_bmpMask;
338 delete gs_bmpWithMask;
339 delete gs_bmp4;
340 delete gs_bmp4_mono;
341 delete gs_bmp36;
342
343 gs_bmpNoMask = NULL;
344 gs_bmpWithColMask = NULL;
345 gs_bmpMask = NULL;
346 gs_bmpWithMask = NULL;
347 gs_bmp4 = NULL;
348 gs_bmp4_mono = NULL;
349 gs_bmp36 = NULL;
350 }
351
352 // ----------------------------------------------------------------------------
353 // MyCanvas
354 // ----------------------------------------------------------------------------
355
356 // the event tables connect the wxWindows events with the functions (event
357 // handlers) which process them.
358 BEGIN_EVENT_TABLE(MyCanvas, wxScrolledWindow)
359 EVT_PAINT (MyCanvas::OnPaint)
360 EVT_MOTION (MyCanvas::OnMouseMove)
361 END_EVENT_TABLE()
362
363 #include "smile.xpm"
364
365 MyCanvas::MyCanvas(MyFrame *parent)
366 : wxScrolledWindow(parent, -1, wxDefaultPosition, wxDefaultSize,
367 wxHSCROLL | wxVSCROLL | wxNO_FULL_REPAINT_ON_RESIZE)
368 {
369 m_owner = parent;
370 m_show = Show_Default;
371 m_smile_bmp = wxBitmap(smile_xpm);
372 m_std_icon = wxArtProvider::GetIcon(wxART_INFORMATION);
373 }
374
375 void MyCanvas::DrawTestBrushes(wxDC& dc)
376 {
377 static const wxCoord WIDTH = 200;
378 static const wxCoord HEIGHT = 80;
379
380 wxCoord x = 10,
381 y = 10;
382
383 dc.SetBrush(wxBrush(*wxGREEN, wxSOLID));
384 dc.DrawRectangle(x, y, WIDTH, HEIGHT);
385 dc.DrawText("Solid green", x + 10, y + 10);
386
387 y += HEIGHT;
388 dc.SetBrush(wxBrush(*wxRED, wxCROSSDIAG_HATCH));
389 dc.DrawRectangle(x, y, WIDTH, HEIGHT);
390 dc.DrawText("Hatched red", x + 10, y + 10);
391
392 y += HEIGHT;
393 dc.SetBrush(wxBrush(*gs_bmpMask));
394 dc.DrawRectangle(x, y, WIDTH, HEIGHT);
395 dc.DrawText("Stipple mono", x + 10, y + 10);
396
397 y += HEIGHT;
398 dc.SetBrush(wxBrush(*gs_bmpNoMask));
399 dc.DrawRectangle(x, y, WIDTH, HEIGHT);
400 dc.DrawText("Stipple colour", x + 10, y + 10);
401 }
402
403 void MyCanvas::DrawTestPoly(wxDC& dc)
404 {
405 wxBrush brushHatch(*wxRED, wxFDIAGONAL_HATCH);
406 dc.SetBrush(brushHatch);
407
408 wxPoint star[5];
409 star[0] = wxPoint(100, 60);
410 star[1] = wxPoint(60, 150);
411 star[2] = wxPoint(160, 100);
412 star[3] = wxPoint(40, 100);
413 star[4] = wxPoint(140, 150);
414
415 dc.DrawText("You should see two (irregular) stars below, the left one "
416 "hatched", 10, 10);
417 dc.DrawText("except for the central region and the right "
418 "one entirely hatched", 10, 30);
419
420 dc.DrawPolygon(WXSIZEOF(star), star);
421 dc.DrawPolygon(WXSIZEOF(star), star, 160, 0, wxWINDING_RULE);
422 }
423
424 void MyCanvas::DrawTestLines( int x, int y, int width, wxDC &dc )
425 {
426 dc.SetPen( wxPen( wxT("black"), width, wxSOLID) );
427 dc.SetBrush( *wxRED_BRUSH );
428 dc.DrawText(wxString::Format(wxT("Testing lines of width %d"), width), x + 10, y - 10);
429 dc.DrawRectangle( x+10, y+10, 100, 190 );
430
431 dc.DrawText("Solid/dot/short dash/long dash/dot dash", x + 150, y + 10);
432 dc.SetPen( wxPen( wxT("black"), width, wxSOLID) );
433 dc.DrawLine( x+20, y+20, 100, y+20 );
434 dc.SetPen( wxPen( wxT("black"), width, wxDOT) );
435 dc.DrawLine( x+20, y+30, 100, y+30 );
436 dc.SetPen( wxPen( wxT("black"), width, wxSHORT_DASH) );
437 dc.DrawLine( x+20, y+40, 100, y+40 );
438 dc.SetPen( wxPen( wxT("black"), width, wxLONG_DASH) );
439 dc.DrawLine( x+20, y+50, 100, y+50 );
440 dc.SetPen( wxPen( wxT("black"), width, wxDOT_DASH) );
441 dc.DrawLine( x+20, y+60, 100, y+60 );
442
443 dc.DrawText("Misc hatches", x + 150, y + 70);
444 dc.SetPen( wxPen( wxT("black"), width, wxBDIAGONAL_HATCH) );
445 dc.DrawLine( x+20, y+70, 100, y+70 );
446 dc.SetPen( wxPen( wxT("black"), width, wxCROSSDIAG_HATCH) );
447 dc.DrawLine( x+20, y+80, 100, y+80 );
448 dc.SetPen( wxPen( wxT("black"), width, wxFDIAGONAL_HATCH) );
449 dc.DrawLine( x+20, y+90, 100, y+90 );
450 dc.SetPen( wxPen( wxT("black"), width, wxCROSS_HATCH) );
451 dc.DrawLine( x+20, y+100, 100, y+100 );
452 dc.SetPen( wxPen( wxT("black"), width, wxHORIZONTAL_HATCH) );
453 dc.DrawLine( x+20, y+110, 100, y+110 );
454 dc.SetPen( wxPen( wxT("black"), width, wxVERTICAL_HATCH) );
455 dc.DrawLine( x+20, y+120, 100, y+120 );
456
457 dc.DrawText("User dash", x + 150, y + 140);
458 wxPen ud( wxT("black"), width, wxUSER_DASH );
459 wxDash dash1[1];
460 dash1[0] = 0;
461 ud.SetDashes( 1, dash1 );
462 dc.DrawLine( x+20, y+140, 100, y+140 );
463 dash1[0] = 1;
464 ud.SetDashes( 1, dash1 );
465 dc.DrawLine( x+20, y+150, 100, y+150 );
466 dash1[0] = 2;
467 ud.SetDashes( 1, dash1 );
468 dc.DrawLine( x+20, y+160, 100, y+160 );
469 dash1[0] = 0x7F;
470 ud.SetDashes( 1, dash1 );
471 dc.DrawLine( x+20, y+170, 100, y+170 );
472 }
473
474 void MyCanvas::DrawDefault(wxDC& dc)
475 {
476 // mark the origin
477 dc.DrawCircle(0, 0, 10);
478 #if !(defined __WXGTK__) && !(defined __WXX11__) && !(defined __WXMOTIF__) && !(defined __WXMGL__)
479 // not implemented in wxGTK or wxMOTIF or wxX11 :-(
480 dc.FloodFill(0, 0, wxColour(255, 0, 0));
481 #endif //
482
483 dc.DrawCheckMark(5, 80, 15, 15);
484 dc.DrawCheckMark(25, 80, 30, 30);
485 dc.DrawCheckMark(60, 80, 60, 60);
486
487 // this is the test for "blitting bitmap into DC damages selected brush" bug
488 wxCoord rectSize = m_std_icon.GetWidth() + 10;
489 wxCoord x = 100;
490 dc.SetPen(*wxTRANSPARENT_PEN);
491 dc.SetBrush( *wxGREEN_BRUSH );
492 dc.DrawRectangle(x, 10, rectSize, rectSize);
493 dc.DrawBitmap(m_std_icon, x + 5, 15, TRUE);
494 x += rectSize + 10;
495 dc.DrawRectangle(x, 10, rectSize, rectSize);
496 dc.DrawIcon(m_std_icon, x + 5, 15);
497 x += rectSize + 10;
498 dc.DrawRectangle(x, 10, rectSize, rectSize);
499
500 // test for "transparent" bitmap drawing (it intersects with the last
501 // rectangle above)
502 //dc.SetBrush( *wxTRANSPARENT_BRUSH );
503
504 if (m_smile_bmp.Ok())
505 dc.DrawBitmap(m_smile_bmp, x + rectSize - 20, rectSize - 10, TRUE);
506
507 dc.SetBrush( *wxBLACK_BRUSH );
508 dc.DrawRectangle( 0, 160, 1000, 300 );
509
510 // draw lines
511 wxBitmap bitmap(20,70);
512 wxMemoryDC memdc;
513 memdc.SelectObject( bitmap );
514 memdc.SetBrush( *wxBLACK_BRUSH );
515 memdc.SetPen( *wxWHITE_PEN );
516 memdc.DrawRectangle(0,0,20,70);
517 memdc.DrawLine( 10,0,10,70 );
518
519 // to the right
520 wxPen pen = *wxRED_PEN;
521 memdc.SetPen(pen);
522 memdc.DrawLine( 10, 5,10, 5 );
523 memdc.DrawLine( 10,10,11,10 );
524 memdc.DrawLine( 10,15,12,15 );
525 memdc.DrawLine( 10,20,13,20 );
526
527 /*
528 memdc.SetPen(*wxRED_PEN);
529 memdc.DrawLine( 12, 5,12, 5 );
530 memdc.DrawLine( 12,10,13,10 );
531 memdc.DrawLine( 12,15,14,15 );
532 memdc.DrawLine( 12,20,15,20 );
533 */
534
535 // same to the left
536 memdc.DrawLine( 10,25,10,25 );
537 memdc.DrawLine( 10,30, 9,30 );
538 memdc.DrawLine( 10,35, 8,35 );
539 memdc.DrawLine( 10,40, 7,40 );
540
541 // XOR draw lines
542 dc.SetPen(*wxWHITE_PEN);
543 memdc.SetLogicalFunction( wxINVERT );
544 memdc.SetPen( *wxWHITE_PEN );
545 memdc.DrawLine( 10,50,10,50 );
546 memdc.DrawLine( 10,55,11,55 );
547 memdc.DrawLine( 10,60,12,60 );
548 memdc.DrawLine( 10,65,13,65 );
549
550 memdc.DrawLine( 12,50,12,50 );
551 memdc.DrawLine( 12,55,13,55 );
552 memdc.DrawLine( 12,60,14,60 );
553 memdc.DrawLine( 12,65,15,65 );
554
555 memdc.SelectObject( wxNullBitmap );
556 dc.DrawBitmap( bitmap, 10, 170 );
557 wxImage image = bitmap.ConvertToImage();
558 image.Rescale( 60,210 );
559 bitmap = wxBitmap(image);
560 dc.DrawBitmap( bitmap, 50, 170 );
561
562 // test the rectangle outline drawing - there should be one pixel between
563 // the rect and the lines
564 dc.SetPen(*wxWHITE_PEN);
565 dc.SetBrush( *wxTRANSPARENT_BRUSH );
566 dc.DrawRectangle(150, 170, 49, 29);
567 dc.DrawRectangle(200, 170, 49, 29);
568 dc.SetPen(*wxWHITE_PEN);
569 dc.DrawLine(250, 210, 250, 170);
570 dc.DrawLine(260, 200, 150, 200);
571
572 // test the rectangle filled drawing - there should be one pixel between
573 // the rect and the lines
574 dc.SetPen(*wxTRANSPARENT_PEN);
575 dc.SetBrush( *wxWHITE_BRUSH );
576 dc.DrawRectangle(300, 170, 49, 29);
577 dc.DrawRectangle(350, 170, 49, 29);
578 dc.SetPen(*wxWHITE_PEN);
579 dc.DrawLine(400, 170, 400, 210);
580 dc.DrawLine(300, 200, 410, 200);
581
582 // a few more tests of this kind
583 dc.SetPen(*wxRED_PEN);
584 dc.SetBrush( *wxWHITE_BRUSH );
585 dc.DrawRectangle(300, 220, 1, 1);
586 dc.DrawRectangle(310, 220, 2, 2);
587 dc.DrawRectangle(320, 220, 3, 3);
588 dc.DrawRectangle(330, 220, 4, 4);
589
590 dc.SetPen(*wxTRANSPARENT_PEN);
591 dc.SetBrush( *wxWHITE_BRUSH );
592 dc.DrawRectangle(300, 230, 1, 1);
593 dc.DrawRectangle(310, 230, 2, 2);
594 dc.DrawRectangle(320, 230, 3, 3);
595 dc.DrawRectangle(330, 230, 4, 4);
596
597 // and now for filled rect with outline
598 dc.SetPen(*wxRED_PEN);
599 dc.SetBrush( *wxWHITE_BRUSH );
600 dc.DrawRectangle(500, 170, 49, 29);
601 dc.DrawRectangle(550, 170, 49, 29);
602 dc.SetPen(*wxWHITE_PEN);
603 dc.DrawLine(600, 170, 600, 210);
604 dc.DrawLine(500, 200, 610, 200);
605
606 // test the rectangle outline drawing - there should be one pixel between
607 // the rect and the lines
608 dc.SetPen(*wxWHITE_PEN);
609 dc.SetBrush( *wxTRANSPARENT_BRUSH );
610 dc.DrawRoundedRectangle(150, 270, 49, 29, 6);
611 dc.DrawRoundedRectangle(200, 270, 49, 29, 6);
612 dc.SetPen(*wxWHITE_PEN);
613 dc.DrawLine(250, 270, 250, 310);
614 dc.DrawLine(150, 300, 260, 300);
615
616 // test the rectangle filled drawing - there should be one pixel between
617 // the rect and the lines
618 dc.SetPen(*wxTRANSPARENT_PEN);
619 dc.SetBrush( *wxWHITE_BRUSH );
620 dc.DrawRoundedRectangle(300, 270, 49, 29, 6);
621 dc.DrawRoundedRectangle(350, 270, 49, 29, 6);
622 dc.SetPen(*wxWHITE_PEN);
623 dc.DrawLine(400, 270, 400, 310);
624 dc.DrawLine(300, 300, 410, 300);
625
626 // Added by JACS to demonstrate bizarre behaviour.
627 // With a size of 70, we get a missing red RHS,
628 // and the hight is too small, so we get yellow
629 // showing. With a size of 40, it draws as expected:
630 // it just shows a white rectangle with red outline.
631 int totalWidth = 70;
632 int totalHeight = 70;
633 wxBitmap bitmap2(totalWidth, totalHeight);
634
635 wxMemoryDC memdc2;
636 memdc2.SelectObject(bitmap2);
637
638 wxBrush yellowBrush(wxColour(255, 255, 0), wxSOLID);
639 memdc2.SetBackground(yellowBrush);
640 memdc2.Clear();
641
642 wxPen yellowPen(wxColour(255, 255, 0), 1, wxSOLID);
643
644 // Now draw a white rectangle with red outline. It should
645 // entirely eclipse the yellow background.
646 memdc2.SetPen(*wxRED_PEN);
647 memdc2.SetBrush(*wxWHITE_BRUSH);
648
649 memdc2.DrawRectangle(0, 0, totalWidth, totalHeight);
650
651 memdc2.SetPen(wxNullPen);
652 memdc2.SetBrush(wxNullBrush);
653 memdc2.SelectObject(wxNullBitmap);
654
655 dc.DrawBitmap(bitmap2, 500, 270);
656
657 // Repeat, but draw directly on dc
658 // Draw a yellow rectangle filling the bitmap
659
660 x = 600; int y = 270;
661 dc.SetPen(yellowPen);
662 dc.SetBrush(yellowBrush);
663 dc.DrawRectangle(x, y, totalWidth, totalHeight);
664
665 // Now draw a white rectangle with red outline. It should
666 // entirely eclipse the yellow background.
667 dc.SetPen(*wxRED_PEN);
668 dc.SetBrush(*wxWHITE_BRUSH);
669
670 dc.DrawRectangle(x, y, totalWidth, totalHeight);
671 }
672
673 void MyCanvas::DrawText(wxDC& dc)
674 {
675 // set underlined font for testing
676 dc.SetFont( wxFont(12, wxMODERN, wxNORMAL, wxNORMAL, TRUE) );
677 dc.DrawText( "This is text", 110, 10 );
678 dc.DrawRotatedText( "That is text", 20, 10, -45 );
679
680 // use wxSWISS_FONT and not wxNORMAL_FONT as the latter can't be rotated
681 // under Win9x (it is not TrueType)
682 dc.SetFont( *wxSWISS_FONT );
683
684 wxString text;
685 dc.SetBackgroundMode(wxTRANSPARENT);
686
687 for ( int n = -180; n < 180; n += 30 )
688 {
689 text.Printf(wxT(" %d rotated text"), n);
690 dc.DrawRotatedText(text , 400, 400, n);
691 }
692
693 dc.SetFont( wxFont( 18, wxSWISS, wxNORMAL, wxNORMAL ) );
694
695 dc.DrawText( "This is Swiss 18pt text.", 110, 40 );
696
697 long length;
698 long height;
699 long descent;
700 dc.GetTextExtent( "This is Swiss 18pt text.", &length, &height, &descent );
701 text.Printf( wxT("Dimensions are length %ld, height %ld, descent %ld"), length, height, descent );
702 dc.DrawText( text, 110, 80 );
703
704 text.Printf( wxT("CharHeight() returns: %d"), dc.GetCharHeight() );
705 dc.DrawText( text, 110, 120 );
706
707 dc.DrawRectangle( 100, 40, 4, height );
708
709 // test the logical function effect
710 wxCoord y = 150;
711 dc.SetLogicalFunction(wxINVERT);
712 dc.DrawText( "There should be no text below", 110, 150 );
713 dc.DrawRectangle( 110, y, 100, height );
714
715 // twice drawn inverted should result in invisible
716 y += height;
717 dc.DrawText( "Invisible text", 110, y );
718 dc.DrawRectangle( 110, y, 100, height );
719 dc.DrawText( "Invisible text", 110, y );
720 dc.DrawRectangle( 110, y, 100, height );
721 dc.SetLogicalFunction(wxCOPY);
722
723 y += height;
724 dc.DrawRectangle( 110, y, 100, height );
725 dc.DrawText( "Visible text", 110, y );
726 }
727
728 static const struct
729 {
730 const wxChar *name;
731 int rop;
732 } rasterOperations[] =
733 {
734 { wxT("wxAND"), wxAND },
735 { wxT("wxAND_INVERT"), wxAND_INVERT },
736 { wxT("wxAND_REVERSE"), wxAND_REVERSE },
737 { wxT("wxCLEAR"), wxCLEAR },
738 { wxT("wxCOPY"), wxCOPY },
739 { wxT("wxEQUIV"), wxEQUIV },
740 { wxT("wxINVERT"), wxINVERT },
741 { wxT("wxNAND"), wxNAND },
742 { wxT("wxNO_OP"), wxNO_OP },
743 { wxT("wxOR"), wxOR },
744 { wxT("wxOR_INVERT"), wxOR_INVERT },
745 { wxT("wxOR_REVERSE"), wxOR_REVERSE },
746 { wxT("wxSET"), wxSET },
747 { wxT("wxSRC_INVERT"), wxSRC_INVERT },
748 { wxT("wxXOR"), wxXOR },
749 };
750
751 void MyCanvas::DrawImages(wxDC& dc)
752 {
753 dc.DrawText("original image", 0, 0);
754 dc.DrawBitmap(*gs_bmpNoMask, 0, 20, 0);
755 dc.DrawText("with colour mask", 0, 100);
756 dc.DrawBitmap(*gs_bmpWithColMask, 0, 120, TRUE);
757 dc.DrawText("the mask image", 0, 200);
758 dc.DrawBitmap(*gs_bmpMask, 0, 220, 0);
759 dc.DrawText("masked image", 0, 300);
760 dc.DrawBitmap(*gs_bmpWithMask, 0, 320, TRUE);
761
762 int cx = gs_bmpWithColMask->GetWidth(),
763 cy = gs_bmpWithColMask->GetHeight();
764
765 wxMemoryDC memDC;
766 for ( size_t n = 0; n < WXSIZEOF(rasterOperations); n++ )
767 {
768 wxCoord x = 120 + 150*(n%4),
769 y = 20 + 100*(n/4);
770
771 dc.DrawText(rasterOperations[n].name, x, y - 20);
772 memDC.SelectObject(*gs_bmpWithColMask);
773 dc.Blit(x, y, cx, cy, &memDC, 0, 0, rasterOperations[n].rop, TRUE);
774 }
775 }
776
777 void MyCanvas::DrawWithLogicalOps(wxDC& dc)
778 {
779 static const wxCoord w = 60;
780 static const wxCoord h = 60;
781
782 // reuse the text colour here
783 dc.SetPen(wxPen(m_owner->m_colourForeground, 1, wxSOLID));
784 dc.SetBrush(*wxTRANSPARENT_BRUSH);
785
786 size_t n;
787 for ( n = 0; n < WXSIZEOF(rasterOperations); n++ )
788 {
789 wxCoord x = 20 + 150*(n%4),
790 y = 20 + 100*(n/4);
791
792 dc.DrawText(rasterOperations[n].name, x, y - 20);
793 dc.SetLogicalFunction(rasterOperations[n].rop);
794 dc.DrawRectangle(x, y, w, h);
795 dc.DrawLine(x, y, x + w, y + h);
796 dc.DrawLine(x + w, y, x, y + h);
797 }
798
799 // now some filled rectangles
800 dc.SetBrush(wxBrush(m_owner->m_colourForeground, wxSOLID));
801
802 for ( n = 0; n < WXSIZEOF(rasterOperations); n++ )
803 {
804 wxCoord x = 20 + 150*(n%4),
805 y = 500 + 100*(n/4);
806
807 dc.DrawText(rasterOperations[n].name, x, y - 20);
808 dc.SetLogicalFunction(rasterOperations[n].rop);
809 dc.DrawRectangle(x, y, w, h);
810 }
811 }
812
813 void MyCanvas::DrawCircles(wxDC& dc)
814 {
815 int x = 100,
816 y = 100,
817 r = 20;
818
819 dc.DrawText("Some circles", 0, y);
820 dc.DrawCircle(x, y, r);
821 dc.DrawCircle(x + 2*r, y, r);
822 dc.DrawCircle(x + 4*r, y, r);
823
824 y += 2*r;
825 dc.DrawText("And ellipses", 0, y);
826 dc.DrawEllipse(x - r, y, 2*r, r);
827 dc.DrawEllipse(x + r, y, 2*r, r);
828 dc.DrawEllipse(x + 3*r, y, 2*r, r);
829
830 y += 2*r;
831 dc.DrawText("And arcs", 0, y);
832 dc.DrawArc(x - r, y, x + r, y, x, y);
833 dc.DrawArc(x + 4*r, y, x + 2*r, y, x + 3*r, y);
834 dc.DrawArc(x + 5*r, y, x + 5*r, y, x + 6*r, y);
835
836 y += 2*r;
837 dc.DrawEllipticArc(x - r, y, 2*r, r, 0, 90);
838 dc.DrawEllipticArc(x + r, y, 2*r, r, 90, 180);
839 dc.DrawEllipticArc(x + 3*r, y, 2*r, r, 180, 270);
840 dc.DrawEllipticArc(x + 5*r, y, 2*r, r, 270, 360);
841 }
842
843 void MyCanvas::DrawRegions(wxDC& dc)
844 {
845 dc.DrawText("You should see a red rect partly covered by a cyan one "
846 "on the left", 10, 5);
847 dc.DrawText("and 5 smileys from which 4 are partially clipped on the right",
848 10, 5 + dc.GetCharHeight());
849 dc.DrawText("The second copy should be identical but right part of it "
850 "should be offset by 10 pixels.",
851 10, 5 + 2*dc.GetCharHeight());
852
853 DrawRegionsHelper(dc, 10, TRUE);
854 DrawRegionsHelper(dc, 350, FALSE);
855 }
856
857 void MyCanvas::DrawRegionsHelper(wxDC& dc, wxCoord x, bool firstTime)
858 {
859 wxCoord y = 100;
860
861 dc.DestroyClippingRegion();
862 dc.SetBrush( *wxWHITE_BRUSH );
863 dc.SetPen( *wxTRANSPARENT_PEN );
864 dc.DrawRectangle( x, y, 310, 310 );
865
866 dc.SetClippingRegion( x + 10, y + 10, 100, 270 );
867
868 dc.SetBrush( *wxRED_BRUSH );
869 dc.DrawRectangle( x, y, 310, 310 );
870
871 dc.SetClippingRegion( x + 10, y + 10, 100, 100 );
872
873 dc.SetBrush( *wxCYAN_BRUSH );
874 dc.DrawRectangle( x, y, 310, 310 );
875
876 dc.DestroyClippingRegion();
877
878 wxRegion region(x + 110, y + 20, 100, 270);
879 if ( !firstTime )
880 region.Offset(10, 10);
881
882 dc.SetClippingRegion(region);
883
884 dc.SetBrush( *wxGREY_BRUSH );
885 dc.DrawRectangle( x, y, 310, 310 );
886
887 if (m_smile_bmp.Ok())
888 {
889 dc.DrawBitmap( m_smile_bmp, x + 150, y + 150, TRUE );
890 dc.DrawBitmap( m_smile_bmp, x + 130, y + 10, TRUE );
891 dc.DrawBitmap( m_smile_bmp, x + 130, y + 280, TRUE );
892 dc.DrawBitmap( m_smile_bmp, x + 100, y + 70, TRUE );
893 dc.DrawBitmap( m_smile_bmp, x + 200, y + 70, TRUE );
894 }
895 }
896
897 void MyCanvas::OnPaint(wxPaintEvent &WXUNUSED(event))
898 {
899 wxPaintDC dc(this);
900 PrepareDC(dc);
901
902 m_owner->PrepareDC(dc);
903
904 dc.SetBackgroundMode( m_owner->m_backgroundMode );
905 if ( m_owner->m_backgroundBrush.Ok() )
906 dc.SetBackground( m_owner->m_backgroundBrush );
907 if ( m_owner->m_colourForeground.Ok() )
908 dc.SetTextForeground( m_owner->m_colourForeground );
909 if ( m_owner->m_colourBackground.Ok() )
910 dc.SetTextBackground( m_owner->m_colourBackground );
911
912 if ( m_owner->m_textureBackground) {
913 if ( ! m_owner->m_backgroundBrush.Ok() ) {
914 wxBrush b(wxColour(0,128,0), wxSOLID);
915 dc.SetBackground(b);
916 }
917 }
918
919 dc.Clear();
920
921 if ( m_owner->m_textureBackground) {
922 dc.SetPen(*wxMEDIUM_GREY_PEN);
923 for (int i=0; i<200; i++)
924 dc.DrawLine(0, i*10, i*10, 0);
925 }
926
927 switch ( m_show )
928 {
929 case Show_Default:
930 DrawDefault(dc);
931 break;
932
933 case Show_Circles:
934 DrawCircles(dc);
935 break;
936
937 case Show_Regions:
938 DrawRegions(dc);
939 break;
940
941 case Show_Text:
942 DrawText(dc);
943 break;
944
945 case Show_Lines:
946 DrawTestLines( 0, 100, 0, dc );
947 DrawTestLines( 0, 320, 1, dc );
948 DrawTestLines( 0, 540, 2, dc );
949 DrawTestLines( 0, 760, 6, dc );
950 break;
951
952 case Show_Brushes:
953 DrawTestBrushes(dc);
954 break;
955
956 case Show_Polygons:
957 DrawTestPoly(dc);
958 break;
959
960 case Show_Mask:
961 DrawImages(dc);
962 break;
963
964 case Show_Ops:
965 DrawWithLogicalOps(dc);
966 break;
967 }
968 }
969
970 void MyCanvas::OnMouseMove(wxMouseEvent &event)
971 {
972 wxClientDC dc(this);
973 PrepareDC(dc);
974 m_owner->PrepareDC(dc);
975
976 wxPoint pos = event.GetPosition();
977 long x = dc.DeviceToLogicalX( pos.x );
978 long y = dc.DeviceToLogicalY( pos.y );
979 wxString str;
980 str.Printf( wxT("Current mouse position: %d,%d"), (int)x, (int)y );
981 m_owner->SetStatusText( str );
982 }
983
984 // ----------------------------------------------------------------------------
985 // MyFrame
986 // ----------------------------------------------------------------------------
987
988 // the event tables connect the wxWindows events with the functions (event
989 // handlers) which process them. It can be also done at run-time, but for the
990 // simple menu events like this the static method is much simpler.
991 BEGIN_EVENT_TABLE(MyFrame, wxFrame)
992 EVT_MENU (File_Quit, MyFrame::OnQuit)
993 EVT_MENU (File_About, MyFrame::OnAbout)
994
995 EVT_MENU_RANGE(MenuShow_First, MenuShow_Last, MyFrame::OnShow)
996
997 EVT_MENU_RANGE(MenuOption_First, MenuOption_Last, MyFrame::OnOption)
998 END_EVENT_TABLE()
999
1000 // frame constructor
1001 MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size)
1002 : wxFrame((wxFrame *)NULL, -1, title, pos, size,
1003 wxDEFAULT_FRAME_STYLE | wxNO_FULL_REPAINT_ON_RESIZE)
1004 {
1005 // set the frame icon
1006 SetIcon(wxICON(mondrian));
1007
1008 wxMenu *menuFile = new wxMenu;
1009 menuFile->Append(File_ShowDefault, "&Default screen\tF1");
1010 menuFile->Append(File_ShowText, "&Text screen\tF2");
1011 menuFile->Append(File_ShowLines, "&Lines screen\tF3");
1012 menuFile->Append(File_ShowBrushes, "&Brushes screen\tF4");
1013 menuFile->Append(File_ShowPolygons, "&Polygons screen\tF5");
1014 menuFile->Append(File_ShowMask, "&Mask screen\tF6");
1015 menuFile->Append(File_ShowOps, "&ROP screen\tF7");
1016 menuFile->Append(File_ShowRegions, "Re&gions screen\tF8");
1017 menuFile->Append(File_ShowCircles, "&Circles screen\tF9");
1018 menuFile->AppendSeparator();
1019 menuFile->Append(File_About, "&About...\tCtrl-A", "Show about dialog");
1020 menuFile->AppendSeparator();
1021 menuFile->Append(File_Quit, "E&xit\tAlt-X", "Quit this program");
1022
1023 wxMenu *menuMapMode = new wxMenu;
1024 menuMapMode->Append( MapMode_Text, "&TEXT map mode" );
1025 menuMapMode->Append( MapMode_Lometric, "&LOMETRIC map mode" );
1026 menuMapMode->Append( MapMode_Twips, "T&WIPS map mode" );
1027 menuMapMode->Append( MapMode_Points, "&POINTS map mode" );
1028 menuMapMode->Append( MapMode_Metric, "&METRIC map mode" );
1029
1030 wxMenu *menuUserScale = new wxMenu;
1031 menuUserScale->Append( UserScale_StretchHoriz, "Stretch &horizontally\tCtrl-H" );
1032 menuUserScale->Append( UserScale_ShrinkHoriz, "Shrin&k horizontally\tCtrl-G" );
1033 menuUserScale->Append( UserScale_StretchVertic, "Stretch &vertically\tCtrl-V" );
1034 menuUserScale->Append( UserScale_ShrinkVertic, "&Shrink vertically\tCtrl-W" );
1035 menuUserScale->AppendSeparator();
1036 menuUserScale->Append( UserScale_Restore, "&Restore to normal\tCtrl-0" );
1037
1038 wxMenu *menuAxis = new wxMenu;
1039 menuAxis->Append( AxisMirror_Horiz, "Mirror horizontally\tCtrl-M", "", TRUE );
1040 menuAxis->Append( AxisMirror_Vertic, "Mirror vertically\tCtrl-N", "", TRUE );
1041
1042 wxMenu *menuLogical = new wxMenu;
1043 menuLogical->Append( LogicalOrigin_MoveDown, "Move &down\tCtrl-D" );
1044 menuLogical->Append( LogicalOrigin_MoveUp, "Move &up\tCtrl-U" );
1045 menuLogical->Append( LogicalOrigin_MoveLeft, "Move &right\tCtrl-L" );
1046 menuLogical->Append( LogicalOrigin_MoveRight, "Move &left\tCtrl-R" );
1047 menuLogical->AppendSeparator();
1048 menuLogical->Append( LogicalOrigin_Set, "Set to (&100, 100)\tShift-Ctrl-1" );
1049 menuLogical->Append( LogicalOrigin_Restore, "&Restore to normal\tShift-Ctrl-0" );
1050
1051 wxMenu *menuColour = new wxMenu;
1052 menuColour->Append( Colour_TextForeground, "Text &foreground..." );
1053 menuColour->Append( Colour_TextBackground, "Text &background..." );
1054 menuColour->Append( Colour_Background, "Background &colour..." );
1055 menuColour->Append( Colour_BackgroundMode, "&Opaque/transparent\tCtrl-B", "", TRUE );
1056 menuColour->Append( Colour_TextureBackgound, "Draw textured back&ground\tCtrl-T", "", TRUE);
1057
1058 // now append the freshly created menu to the menu bar...
1059 wxMenuBar *menuBar = new wxMenuBar;
1060 menuBar->Append(menuFile, "&File");
1061 menuBar->Append(menuMapMode, "&Mode");
1062 menuBar->Append(menuUserScale, "&Scale");
1063 menuBar->Append(menuAxis, "&Axis");
1064 menuBar->Append(menuLogical, "&Origin");
1065 menuBar->Append(menuColour, "&Colours");
1066
1067 // ... and attach this menu bar to the frame
1068 SetMenuBar(menuBar);
1069
1070 // create a status bar just for fun (by default with 1 pane only)
1071 CreateStatusBar(2);
1072 SetStatusText("Welcome to wxWindows!");
1073
1074 m_mapMode = wxMM_TEXT;
1075 m_xUserScale = 1.0;
1076 m_yUserScale = 1.0;
1077 m_xLogicalOrigin = 0;
1078 m_yLogicalOrigin = 0;
1079 m_xAxisReversed =
1080 m_yAxisReversed = FALSE;
1081 m_backgroundMode = wxSOLID;
1082 m_colourForeground = *wxRED;
1083 m_colourBackground = *wxBLUE;
1084 m_textureBackground = FALSE;
1085
1086 m_canvas = new MyCanvas( this );
1087 m_canvas->SetScrollbars( 10, 10, 100, 240 );
1088 }
1089
1090 // event handlers
1091
1092 void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
1093 {
1094 // TRUE is to force the frame to close
1095 Close(TRUE);
1096 }
1097
1098 void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
1099 {
1100 wxString msg;
1101 msg.Printf( wxT("This is the about dialog of the drawing sample.\n")
1102 wxT("This sample tests various primitive drawing functions\n")
1103 wxT("(without any attempts to prevent flicker).\n")
1104 wxT("Copyright (c) Robert Roebling 1999")
1105 );
1106
1107 wxMessageBox(msg, "About Drawing", wxOK | wxICON_INFORMATION, this);
1108 }
1109
1110 void MyFrame::OnShow(wxCommandEvent& event)
1111 {
1112 m_canvas->Show((ScreenToShow)(event.GetId() - MenuShow_First));
1113 }
1114
1115 void MyFrame::OnOption(wxCommandEvent& event)
1116 {
1117 switch (event.GetId())
1118 {
1119 case MapMode_Text:
1120 m_mapMode = wxMM_TEXT;
1121 break;
1122 case MapMode_Lometric:
1123 m_mapMode = wxMM_LOMETRIC;
1124 break;
1125 case MapMode_Twips:
1126 m_mapMode = wxMM_TWIPS;
1127 break;
1128 case MapMode_Points:
1129 m_mapMode = wxMM_POINTS;
1130 break;
1131 case MapMode_Metric:
1132 m_mapMode = wxMM_METRIC;
1133 break;
1134
1135 case LogicalOrigin_MoveDown:
1136 m_yLogicalOrigin += 10;
1137 break;
1138 case LogicalOrigin_MoveUp:
1139 m_yLogicalOrigin -= 10;
1140 break;
1141 case LogicalOrigin_MoveLeft:
1142 m_xLogicalOrigin += 10;
1143 break;
1144 case LogicalOrigin_MoveRight:
1145 m_xLogicalOrigin -= 10;
1146 break;
1147 case LogicalOrigin_Set:
1148 m_xLogicalOrigin =
1149 m_yLogicalOrigin = -100;
1150 break;
1151 case LogicalOrigin_Restore:
1152 m_xLogicalOrigin =
1153 m_yLogicalOrigin = 0;
1154 break;
1155
1156 case UserScale_StretchHoriz:
1157 m_xUserScale *= 1.10;
1158 break;
1159 case UserScale_ShrinkHoriz:
1160 m_xUserScale /= 1.10;
1161 break;
1162 case UserScale_StretchVertic:
1163 m_yUserScale *= 1.10;
1164 break;
1165 case UserScale_ShrinkVertic:
1166 m_yUserScale /= 1.10;
1167 break;
1168 case UserScale_Restore:
1169 m_xUserScale =
1170 m_yUserScale = 1.0;
1171 break;
1172
1173 case AxisMirror_Vertic:
1174 m_yAxisReversed = !m_yAxisReversed;
1175 break;
1176 case AxisMirror_Horiz:
1177 m_xAxisReversed = !m_xAxisReversed;
1178 break;
1179
1180 case Colour_TextForeground:
1181 m_colourForeground = SelectColour();
1182 break;
1183 case Colour_TextBackground:
1184 m_colourBackground = SelectColour();
1185 break;
1186 case Colour_Background:
1187 {
1188 wxColour col = SelectColour();
1189 if ( col.Ok() )
1190 {
1191 m_backgroundBrush.SetColour(col);
1192 }
1193 }
1194 break;
1195 case Colour_BackgroundMode:
1196 m_backgroundMode = m_backgroundMode == wxSOLID ? wxTRANSPARENT
1197 : wxSOLID;
1198 break;
1199
1200 case Colour_TextureBackgound:
1201 m_textureBackground = ! m_textureBackground;
1202 break;
1203
1204 default:
1205 // skip Refresh()
1206 return;
1207 }
1208
1209 m_canvas->Refresh();
1210 }
1211
1212 void MyFrame::PrepareDC(wxDC& dc)
1213 {
1214 dc.SetLogicalOrigin( m_xLogicalOrigin, m_yLogicalOrigin );
1215 dc.SetAxisOrientation( !m_xAxisReversed, m_yAxisReversed );
1216 dc.SetUserScale( m_xUserScale, m_yUserScale );
1217 dc.SetMapMode( m_mapMode );
1218 }
1219
1220 wxColour MyFrame::SelectColour()
1221 {
1222 wxColour col;
1223 wxColourData data;
1224 wxColourDialog dialog(this, &data);
1225
1226 if ( dialog.ShowModal() == wxID_OK )
1227 {
1228 col = dialog.GetColourData().GetColour();
1229 }
1230
1231 return col;
1232 }