1 /////////////////////////////////////////////////////////////////////////////
2 // Name:        shaped.cpp
3 // Purpose:     Shaped Window sample
4 // Author:      Robin Dunn
5 // Modified by:
6 // Created:     28-Mar-2003
7 // Copyright:   (c) Robin Dunn
8 // Licence:     wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
10 
11 // ============================================================================
12 // declarations
13 // ============================================================================
14 
15 // ----------------------------------------------------------------------------
16 // headers
17 // ----------------------------------------------------------------------------
18 
19 // For compilers that support precompilation, includes "wx/wx.h".
20 #include "wx/wxprec.h"
21 
22 #ifdef __BORLANDC__
23     #pragma hdrstop
24 #endif
25 
26 // for all others, include the necessary headers
27 #ifndef WX_PRECOMP
28     #include "wx/app.h"
29     #include "wx/log.h"
30     #include "wx/frame.h"
31     #include "wx/panel.h"
32     #include "wx/stattext.h"
33     #include "wx/menu.h"
34     #include "wx/layout.h"
35     #include "wx/msgdlg.h"
36     #include "wx/image.h"
37 #endif
38 
39 #include "wx/dcclient.h"
40 #include "wx/graphics.h"
41 #include "wx/image.h"
42 
43 #ifndef wxHAS_IMAGES_IN_RESOURCES
44     #include "../sample.xpm"
45 #endif
46 
47 // ----------------------------------------------------------------------------
48 // constants
49 // ----------------------------------------------------------------------------
50 
51 // menu ids
52 enum
53 {
54     Show_Shaped = 100,
55     Show_Transparent,
56 
57     // must be consecutive and in the same order as wxShowEffect enum elements
58     Show_Effect_First,
59     Show_Effect_Roll = Show_Effect_First,
60     Show_Effect_Slide,
61     Show_Effect_Blend,
62     Show_Effect_Expand,
63     Show_Effect_Last = Show_Effect_Expand
64 };
65 
66 // ----------------------------------------------------------------------------
67 // private classes
68 // ----------------------------------------------------------------------------
69 
70 // Define a new application type, each program should derive a class from wxApp
71 class MyApp : public wxApp
72 {
73 public:
74     // override base class virtuals
75     // ----------------------------
76 
77     // this one is called on application startup and is a good place for the app
78     // initialization (doing it here and not in the ctor allows to have an error
79     // return: if OnInit() returns false, the application terminates)
80     virtual bool OnInit();
81 };
82 
83 
84 // Main frame just contains the menu items invoking the other tests
85 class MainFrame : public wxFrame
86 {
87 public:
88     MainFrame();
89 
90 private:
91     void OnShowShaped(wxCommandEvent& event);
92     void OnShowTransparent(wxCommandEvent& event);
93     void OnShowEffect(wxCommandEvent& event);
94     void OnExit(wxCommandEvent& event);
95 
96     wxDECLARE_EVENT_TABLE();
97 };
98 
99 // Define a new frame type: this is going to the frame showing the
100 // effect of wxFRAME_SHAPED
101 class ShapedFrame : public wxFrame
102 {
103 public:
104     // ctor(s)
105     ShapedFrame(wxFrame *parent);
106     void SetWindowShape();
107 
108     // event handlers (these functions should _not_ be virtual)
109     void OnDoubleClick(wxMouseEvent& evt);
110     void OnLeftDown(wxMouseEvent& evt);
111     void OnLeftUp(wxMouseEvent& evt);
112     void OnMouseMove(wxMouseEvent& evt);
113     void OnExit(wxMouseEvent& evt);
114     void OnPaint(wxPaintEvent& evt);
115 
116 private:
117     enum ShapeKind
118     {
119         Shape_None,
120         Shape_Star,
121 #if wxUSE_GRAPHICS_CONTEXT
122         Shape_Circle,
123 #endif // wxUSE_GRAPHICS_CONTEXT
124         Shape_Max
125     } m_shapeKind;
126 
127     wxBitmap m_bmp;
128     wxPoint  m_delta;
129 
130     // any class wishing to process wxWidgets events must use this macro
131     wxDECLARE_EVENT_TABLE();
132 };
133 
134 // Define a new frame type: this is going to the frame showing the
135 // effect of wxWindow::SetTransparent and of
136 // wxWindow::SetBackgroundStyle(wxBG_STYLE_TRANSPARENT)
137 class SeeThroughFrame : public wxFrame
138 {
139 public:
140     void Create();
141 
142 private:
143     // event handlers (these functions should _not_ be virtual)
144     void OnDoubleClick(wxMouseEvent& evt);
145     void OnPaint(wxPaintEvent& evt);
146 
147     // any class wishing to process wxWidgets events must use this macro
148     wxDECLARE_EVENT_TABLE();
149 };
150 
151 class EffectFrame : public wxFrame
152 {
153 public:
EffectFrame(wxWindow * parent,wxShowEffect effect,unsigned timeout=1000)154     EffectFrame(wxWindow *parent,
155                 wxShowEffect effect,
156                 // TODO: add menu command to the main frame to allow changing
157                 //       these parameters
158                 unsigned timeout = 1000)
159         : wxFrame(parent, wxID_ANY,
160                   wxString::Format("Frame shown with %s effect",
161                                    GetEffectName(effect)),
162                   wxDefaultPosition, wxSize(450, 300)),
163           m_effect(effect),
164           m_timeout(timeout)
165     {
166         new wxStaticText(this, wxID_ANY,
167                          wxString::Format("Effect: %s", GetEffectName(effect)),
168                          wxPoint(20, 20));
169         new wxStaticText(this, wxID_ANY,
170                          wxString::Format("Timeout: %ums", m_timeout),
171                          wxPoint(20, 60));
172 
173         ShowWithEffect(m_effect, m_timeout);
174 
175         Connect(wxEVT_CLOSE_WINDOW, wxCloseEventHandler(EffectFrame::OnClose));
176     }
177 
178 private:
GetEffectName(wxShowEffect effect)179     static const char *GetEffectName(wxShowEffect effect)
180     {
181         static const char *names[] =
182         {
183             "none",
184             "roll to left",
185             "roll to right",
186             "roll to top",
187             "roll to bottom",
188             "slide to left",
189             "slide to right",
190             "slide to top",
191             "slide to bottom",
192             "fade",
193             "expand",
194         };
195         wxCOMPILE_TIME_ASSERT( WXSIZEOF(names) == wxSHOW_EFFECT_MAX,
196                                 EffectNamesMismatch );
197 
198         return names[effect];
199     }
200 
OnClose(wxCloseEvent & event)201     void OnClose(wxCloseEvent& event)
202     {
203         HideWithEffect(m_effect, m_timeout);
204 
205         event.Skip();
206     }
207 
208     wxShowEffect m_effect;
209     unsigned m_timeout;
210 };
211 
212 // ============================================================================
213 // implementation
214 // ============================================================================
215 
216 // ----------------------------------------------------------------------------
217 // the application class
218 // ----------------------------------------------------------------------------
219 
IMPLEMENT_APP(MyApp)220 IMPLEMENT_APP(MyApp)
221 
222 // `Main program' equivalent: the program execution "starts" here
223 bool MyApp::OnInit()
224 {
225     if ( !wxApp::OnInit() )
226         return false;
227 
228     wxInitAllImageHandlers();
229 
230     new MainFrame;
231 
232     // success: wxApp::OnRun() will be called which will enter the main message
233     // loop and the application will run. If we returned false here, the
234     // application would exit immediately.
235     return true;
236 }
237 
238 // ----------------------------------------------------------------------------
239 // main frame
240 // ----------------------------------------------------------------------------
241 
wxBEGIN_EVENT_TABLE(MainFrame,wxFrame)242 wxBEGIN_EVENT_TABLE(MainFrame, wxFrame)
243     EVT_MENU(Show_Shaped, MainFrame::OnShowShaped)
244     EVT_MENU(Show_Transparent, MainFrame::OnShowTransparent)
245     EVT_MENU_RANGE(Show_Effect_First, Show_Effect_Last, MainFrame::OnShowEffect)
246     EVT_MENU(wxID_EXIT, MainFrame::OnExit)
247 wxEND_EVENT_TABLE()
248 
249 MainFrame::MainFrame()
250          : wxFrame(NULL, wxID_ANY, "wxWidgets Shaped Sample",
251                    wxDefaultPosition, wxSize(200, 100))
252 {
253     SetIcon(wxICON(sample));
254 
255     wxMenuBar * const mbar = new wxMenuBar;
256     wxMenu * const menuFrames = new wxMenu;
257     menuFrames->Append(Show_Shaped, "Show &shaped window\tCtrl-S");
258     menuFrames->Append(Show_Transparent, "Show &transparent window\tCtrl-T");
259     menuFrames->AppendSeparator();
260     menuFrames->Append(Show_Effect_Roll, "Show &rolled effect\tCtrl-R");
261     menuFrames->Append(Show_Effect_Slide, "Show s&lide effect\tCtrl-L");
262     menuFrames->Append(Show_Effect_Blend, "Show &fade effect\tCtrl-F");
263     menuFrames->Append(Show_Effect_Expand, "Show &expand effect\tCtrl-E");
264     menuFrames->AppendSeparator();
265     menuFrames->Append(wxID_EXIT, "E&xit");
266 
267     mbar->Append(menuFrames, "&Show");
268     SetMenuBar(mbar);
269 
270     Show();
271 }
272 
OnShowShaped(wxCommandEvent & WXUNUSED (event))273 void MainFrame::OnShowShaped(wxCommandEvent& WXUNUSED(event))
274 {
275     ShapedFrame *shapedFrame = new ShapedFrame(this);
276     shapedFrame->Show(true);
277 }
278 
OnShowTransparent(wxCommandEvent & WXUNUSED (event))279 void MainFrame::OnShowTransparent(wxCommandEvent& WXUNUSED(event))
280 {
281     if (IsTransparentBackgroundSupported())
282     {
283         SeeThroughFrame *seeThroughFrame = new SeeThroughFrame;
284         seeThroughFrame->Create();
285         seeThroughFrame->Show(true);
286     }
287     else
288         wxMessageBox(wxS("transparent window requires a composited screen"));
289 }
290 
OnShowEffect(wxCommandEvent & event)291 void MainFrame::OnShowEffect(wxCommandEvent& event)
292 {
293     int effect = event.GetId();
294     static wxDirection direction = wxLEFT;
295     direction = (wxDirection)(((int)direction)<< 1);
296     if ( direction > wxDOWN )
297         direction = wxLEFT ;
298 
299     wxShowEffect eff;
300     switch ( effect )
301     {
302         case Show_Effect_Roll:
303             switch ( direction )
304             {
305                 case wxLEFT:
306                     eff = wxSHOW_EFFECT_ROLL_TO_LEFT;
307                     break;
308                 case wxRIGHT:
309                     eff = wxSHOW_EFFECT_ROLL_TO_RIGHT;
310                     break;
311                 case wxTOP:
312                     eff = wxSHOW_EFFECT_ROLL_TO_TOP;
313                     break;
314                 case wxBOTTOM:
315                     eff = wxSHOW_EFFECT_ROLL_TO_BOTTOM;
316                     break;
317                 default:
318                     wxFAIL_MSG( "invalid direction" );
319                     return;
320             }
321             break;
322         case Show_Effect_Slide:
323             switch ( direction )
324             {
325                 case wxLEFT:
326                     eff = wxSHOW_EFFECT_SLIDE_TO_LEFT;
327                     break;
328                 case wxRIGHT:
329                     eff = wxSHOW_EFFECT_SLIDE_TO_RIGHT;
330                     break;
331                 case wxTOP:
332                     eff = wxSHOW_EFFECT_SLIDE_TO_TOP;
333                     break;
334                 case wxBOTTOM:
335                     eff = wxSHOW_EFFECT_SLIDE_TO_BOTTOM;
336                     break;
337                 default:
338                     wxFAIL_MSG( "invalid direction" );
339                     return;
340             }
341             break;
342 
343         case Show_Effect_Blend:
344             eff = wxSHOW_EFFECT_BLEND;
345             break;
346 
347         case Show_Effect_Expand:
348             eff = wxSHOW_EFFECT_EXPAND;
349             break;
350 
351         default:
352             wxFAIL_MSG( "invalid effect" );
353             return;
354     }
355 
356     new EffectFrame(this,  eff, 1000);
357 }
358 
OnExit(wxCommandEvent & WXUNUSED (event))359 void MainFrame::OnExit(wxCommandEvent& WXUNUSED(event))
360 {
361     Close();
362 }
363 
364 // ----------------------------------------------------------------------------
365 // shaped frame
366 // ----------------------------------------------------------------------------
367 
wxBEGIN_EVENT_TABLE(ShapedFrame,wxFrame)368 wxBEGIN_EVENT_TABLE(ShapedFrame, wxFrame)
369     EVT_LEFT_DCLICK(ShapedFrame::OnDoubleClick)
370     EVT_LEFT_DOWN(ShapedFrame::OnLeftDown)
371     EVT_LEFT_UP(ShapedFrame::OnLeftUp)
372     EVT_MOTION(ShapedFrame::OnMouseMove)
373     EVT_RIGHT_UP(ShapedFrame::OnExit)
374     EVT_PAINT(ShapedFrame::OnPaint)
375 wxEND_EVENT_TABLE()
376 
377 
378 // frame constructor
379 ShapedFrame::ShapedFrame(wxFrame *parent)
380        : wxFrame(parent, wxID_ANY, wxEmptyString,
381                   wxDefaultPosition, wxSize(100, 100),
382                   0
383                   | wxFRAME_SHAPED
384                   | wxSIMPLE_BORDER
385                   | wxFRAME_NO_TASKBAR
386                   | wxSTAY_ON_TOP
387             )
388 {
389     m_shapeKind = Shape_Star;
390     m_bmp = wxBitmap(wxT("star.png"), wxBITMAP_TYPE_PNG);
391     SetSize(wxSize(m_bmp.GetWidth(), m_bmp.GetHeight()));
392     SetToolTip(wxT("Right-click to close, double click to cycle shape"));
393     SetWindowShape();
394 }
395 
SetWindowShape()396 void ShapedFrame::SetWindowShape()
397 {
398     switch ( m_shapeKind )
399     {
400         case Shape_None:
401             SetShape(wxRegion());
402             break;
403 
404         case Shape_Star:
405             SetShape(wxRegion(m_bmp, *wxWHITE));
406             break;
407 
408 #if wxUSE_GRAPHICS_CONTEXT
409         case Shape_Circle:
410             {
411                 wxGraphicsPath
412                     path = wxGraphicsRenderer::GetDefaultRenderer()->CreatePath();
413                 path.AddCircle(m_bmp.GetWidth()/2, m_bmp.GetHeight()/2, 30);
414                 SetShape(path);
415             }
416             break;
417 #endif // wxUSE_GRAPHICS_CONTEXT
418 
419         case Shape_Max:
420             wxFAIL_MSG( "invalid shape kind" );
421             break;
422     }
423 }
424 
OnDoubleClick(wxMouseEvent & WXUNUSED (evt))425 void ShapedFrame::OnDoubleClick(wxMouseEvent& WXUNUSED(evt))
426 {
427     m_shapeKind = static_cast<ShapeKind>((m_shapeKind + 1) % Shape_Max);
428     SetWindowShape();
429 }
430 
OnLeftDown(wxMouseEvent & evt)431 void ShapedFrame::OnLeftDown(wxMouseEvent& evt)
432 {
433     CaptureMouse();
434     wxPoint pos = ClientToScreen(evt.GetPosition());
435     wxPoint origin = GetPosition();
436     int dx =  pos.x - origin.x;
437     int dy = pos.y - origin.y;
438     m_delta = wxPoint(dx, dy);
439 }
440 
OnLeftUp(wxMouseEvent & WXUNUSED (evt))441 void ShapedFrame::OnLeftUp(wxMouseEvent& WXUNUSED(evt))
442 {
443     if (HasCapture())
444     {
445         ReleaseMouse();
446     }
447 }
448 
OnMouseMove(wxMouseEvent & evt)449 void ShapedFrame::OnMouseMove(wxMouseEvent& evt)
450 {
451     wxPoint pt = evt.GetPosition();
452     if (evt.Dragging() && evt.LeftIsDown())
453     {
454         wxPoint pos = ClientToScreen(pt);
455         Move(wxPoint(pos.x - m_delta.x, pos.y - m_delta.y));
456     }
457 }
458 
OnExit(wxMouseEvent & WXUNUSED (evt))459 void ShapedFrame::OnExit(wxMouseEvent& WXUNUSED(evt))
460 {
461     Close();
462 }
463 
OnPaint(wxPaintEvent & WXUNUSED (evt))464 void ShapedFrame::OnPaint(wxPaintEvent& WXUNUSED(evt))
465 {
466     wxPaintDC dc(this);
467     dc.DrawBitmap(m_bmp, 0, 0, true);
468 }
469 
470 // ----------------------------------------------------------------------------
471 // see-through frame
472 // ----------------------------------------------------------------------------
473 
wxBEGIN_EVENT_TABLE(SeeThroughFrame,wxFrame)474 wxBEGIN_EVENT_TABLE(SeeThroughFrame, wxFrame)
475     EVT_LEFT_DCLICK(SeeThroughFrame::OnDoubleClick)
476     EVT_PAINT(SeeThroughFrame::OnPaint)
477 wxEND_EVENT_TABLE()
478 
479 void SeeThroughFrame::Create()
480 {
481     SetBackgroundStyle(wxBG_STYLE_TRANSPARENT);
482     wxFrame::Create(NULL, wxID_ANY, "Transparency test: double click here",
483            wxPoint(100, 30), wxSize(300, 300),
484            wxDEFAULT_FRAME_STYLE |
485            wxFULL_REPAINT_ON_RESIZE |
486            wxSTAY_ON_TOP);
487     SetBackgroundColour(*wxWHITE);
488 }
489 
490 // Paints a grid of varying hue and alpha
OnPaint(wxPaintEvent & WXUNUSED (evt))491 void SeeThroughFrame::OnPaint(wxPaintEvent& WXUNUSED(evt))
492 {
493     wxPaintDC dc(this);
494     dc.SetPen(wxNullPen);
495 
496     int xcount = 8;
497     int ycount = 8;
498 
499     float xstep = 1. / xcount;
500     float ystep = 1. / ycount;
501 
502     int width = GetClientSize().GetWidth();
503     int height = GetClientSize().GetHeight();
504 
505     for ( float x = 0.; x < 1.; x += xstep )
506     {
507         for ( float y = 0.; y < 1.; y += ystep )
508         {
509             wxImage::RGBValue v = wxImage::HSVtoRGB(wxImage::HSVValue(x, 1., 1.));
510             dc.SetBrush(wxBrush(wxColour(v.red, v.green, v.blue,
511                                 (int)(255*(1. - y)))));
512             int x1 = (int)(x * width);
513             int y1 = (int)(y * height);
514             int x2 = (int)((x + xstep) * width);
515             int y2 = (int)((y + ystep) * height);
516             dc.DrawRectangle(x1, y1, x2 - x1, y2 - y1);
517         }
518     }
519 }
520 
OnDoubleClick(wxMouseEvent & WXUNUSED (evt))521 void SeeThroughFrame::OnDoubleClick(wxMouseEvent& WXUNUSED(evt))
522 {
523     SetBackgroundStyle(wxBG_STYLE_PAINT);
524     SetTransparent(255);
525     SetTitle("Opaque");
526 
527     Refresh();
528 }
529 
530