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