1 /////////////////////////////////////////////////////////////////////////////
2 // Name:        display.cpp
3 // Purpose:     wxWidgets sample showing the features of wxDisplay class
4 // Author:      Vadim Zeitlin
5 // Modified by: Ryan Norton & Brian Victor
6 // Created:     23.02.03
7 // Copyright:   (c) Vadim Zeitlin <vadim@wxwidgets.org>
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 
23 // for all others, include the necessary headers explicitly
24 #ifndef WX_PRECOMP
25     #include "wx/wx.h"
26 #endif
27 
28 #include "wx/artprov.h"
29 #include "wx/bookctrl.h"
30 #include "wx/sysopt.h"
31 
32 #include "wx/display.h"
33 
34 
35 // the application icon (under Windows it is in resources)
36 #ifndef wxHAS_IMAGES_IN_RESOURCES
37     #include "../sample.xpm"
38 #endif
39 
40 // ----------------------------------------------------------------------------
41 // private classes
42 // ----------------------------------------------------------------------------
43 
44 // Define a new application type, each program should derive a class from wxApp
45 class MyApp : public wxApp
46 {
47 public:
48     // override base class virtuals
49     // ----------------------------
50 
51     // this one is called on application startup and is a good place for the app
52     // initialization (doing it here and not in the ctor allows to have an error
53     // return: if OnInit() returns false, the application terminates)
54     virtual bool OnInit() wxOVERRIDE;
55 };
56 
57 // Define a new frame type: this is going to be our main frame
58 class MyFrame : public wxFrame
59 {
60 public:
61     // ctor(s)
62     MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size,
63             long style = wxDEFAULT_FRAME_STYLE);
64 
65     // event handlers (these functions should _not_ be virtual)
66     void OnQuit(wxCommandEvent& event);
67     void OnFromPoint(wxCommandEvent& event);
68     void OnFullScreen(wxCommandEvent& event);
69     void OnAbout(wxCommandEvent& event);
70 
71 #if wxUSE_DISPLAY
72     void OnChangeMode(wxCommandEvent& event);
73     void OnResetMode(wxCommandEvent& event);
74 
75     void OnDisplayChanged(wxDisplayChangedEvent& event);
76 #endif // wxUSE_DISPLAY
77 
78     void OnLeftClick(wxMouseEvent& event);
79 
80 private:
81     // Fill m_book with the information about all the displays.
82     void PopuplateWithDisplayInfo();
83 
84 #if wxUSE_DISPLAY
85     // convert video mode to textual description
86     wxString VideoModeToText(const wxVideoMode& mode);
87 #endif // wxUSE_DISPLAY
88 
89     // GUI controls
90     wxBookCtrl *m_book;
91 
92     // any class wishing to process wxWidgets events must use this macro
93     wxDECLARE_EVENT_TABLE();
94 };
95 
96 #if wxUSE_DISPLAY
97 // Client data class for the choice control containing the video modes
98 class MyVideoModeClientData : public wxClientData
99 {
100 public:
MyVideoModeClientData(const wxVideoMode & m)101     MyVideoModeClientData(const wxVideoMode& m) : mode(m) { }
102 
103     const wxVideoMode mode;
104 };
105 #endif // wxUSE_DISPLAY
106 
107 // ----------------------------------------------------------------------------
108 // constants
109 // ----------------------------------------------------------------------------
110 
111 // IDs for the controls and the menu commands
112 enum
113 {
114     // menu items
115     Display_FromPoint = wxID_HIGHEST + 1,
116     Display_FullScreen,
117 
118     // controls
119     Display_ChangeMode,
120     Display_ResetMode,
121     Display_CurrentMode,
122 
123 
124     // it is important for the id corresponding to the "About" command to have
125     // this standard value as otherwise it won't be handled properly under Mac
126     // (where it is special and put into the "Apple" menu)
127     Display_Quit = wxID_EXIT,
128     Display_About = wxID_ABOUT
129 };
130 
131 // ----------------------------------------------------------------------------
132 // event tables and other macros for wxWidgets
133 // ----------------------------------------------------------------------------
134 
135 // the event tables connect the wxWidgets events with the functions (event
136 // handlers) which process them. It can be also done at run-time, but for the
137 // simple menu events like this the static method is much simpler.
138 wxBEGIN_EVENT_TABLE(MyFrame, wxFrame)
139     EVT_MENU(Display_Quit,  MyFrame::OnQuit)
140     EVT_MENU(Display_FromPoint,  MyFrame::OnFromPoint)
141     EVT_MENU(Display_FullScreen, MyFrame::OnFullScreen)
142     EVT_MENU(Display_About, MyFrame::OnAbout)
143 
144 #if wxUSE_DISPLAY
145     EVT_CHOICE(Display_ChangeMode, MyFrame::OnChangeMode)
146     EVT_BUTTON(Display_ResetMode, MyFrame::OnResetMode)
147 
148     EVT_DISPLAY_CHANGED(MyFrame::OnDisplayChanged)
149 #endif // wxUSE_DISPLAY
150 
151     EVT_LEFT_UP(MyFrame::OnLeftClick)
152 wxEND_EVENT_TABLE()
153 
154 // Create a new application object: this macro will allow wxWidgets to create
155 // the application object during program execution (it's better than using a
156 // static object for many reasons) and also declares the accessor function
157 // wxGetApp() which will return the reference of the right type (i.e. MyApp and
158 // not wxApp)
159 wxIMPLEMENT_APP(MyApp);
160 
161 // ============================================================================
162 // implementation
163 // ============================================================================
164 
165 // ----------------------------------------------------------------------------
166 // the application class
167 // ----------------------------------------------------------------------------
168 
169 // 'Main program' equivalent: the program execution "starts" here
OnInit()170 bool MyApp::OnInit()
171 {
172     if ( !wxApp::OnInit() )
173         return false;
174 
175     // create the main application window
176     MyFrame *frame = new MyFrame(_("Display wxWidgets Sample"),
177                                  wxDefaultPosition, wxDefaultSize);
178 
179     // and show it (the frames, unlike simple controls, are not shown when
180     // created initially)
181     frame->Show();
182 
183     // success: wxApp::OnRun() will be called which will enter the main message
184     // loop and the application will run. If we returned false here, the
185     // application would exit immediately.
186     return true;
187 }
188 
189 // ----------------------------------------------------------------------------
190 // main frame
191 // ----------------------------------------------------------------------------
192 
193 // frame constructor
MyFrame(const wxString & title,const wxPoint & pos,const wxSize & size,long style)194 MyFrame::MyFrame(const wxString& title, const wxPoint& pos, const wxSize& size, long style)
195        : wxFrame(NULL, wxID_ANY, title, pos, size, style)
196 {
197     // set the frame icon
198     SetIcon(wxICON(sample));
199 
200 #if wxUSE_MENUS
201     // create a menu bar
202     wxMenu *menuDisplay = new wxMenu;
203     menuDisplay->Append(Display_FromPoint, _("Find from &point..."));
204     menuDisplay->AppendSeparator();
205     wxMenuItem* const
206         itemFullScreen = new wxMenuItem(menuDisplay,
207                                         Display_FullScreen,
208                                         _("Full &screen\tF12"));
209     itemFullScreen->SetBitmap(
210             wxArtProvider::GetBitmap(wxART_FULL_SCREEN, wxART_MENU)
211         );
212     menuDisplay->Append(itemFullScreen);
213     menuDisplay->AppendSeparator();
214     menuDisplay->Append(Display_Quit, _("E&xit\tAlt-X"), _("Quit this program"));
215 
216     // the "About" item should be in the help menu
217     wxMenu *helpMenu = new wxMenu;
218     helpMenu->Append(Display_About, _("&About\tF1"), _("Show about dialog"));
219 
220     // now append the freshly created menu to the menu bar...
221     wxMenuBar *menuBar = new wxMenuBar();
222     menuBar->Append(menuDisplay, _("&Display"));
223     menuBar->Append(helpMenu, _("&Help"));
224 
225     EnableFullScreenView();
226 
227     // ... and attach this menu bar to the frame
228     SetMenuBar(menuBar);
229 #endif // wxUSE_MENUS
230 
231 #if wxUSE_STATUSBAR
232     // create status bar
233     CreateStatusBar();
234 #endif // wxUSE_STATUSBAR
235 
236     // create child controls
237     m_book = new wxBookCtrl(this, wxID_ANY);
238     PopuplateWithDisplayInfo();
239 }
240 
PopuplateWithDisplayInfo()241 void MyFrame::PopuplateWithDisplayInfo()
242 {
243     const size_t countDpy = wxDisplay::GetCount();
244     for ( size_t nDpy = 0; nDpy < countDpy; nDpy++ )
245     {
246         wxDisplay display(nDpy);
247 
248         wxWindow *page = new wxPanel(m_book, wxID_ANY);
249 
250         // create 2 column flex grid sizer with growable 2nd column
251         wxFlexGridSizer *sizer = new wxFlexGridSizer(2, 10, 20);
252         sizer->AddGrowableCol(1);
253 
254         const wxRect r(display.GetGeometry());
255         sizer->Add(new wxStaticText(page, wxID_ANY, "Origin: "));
256         sizer->Add(new wxStaticText
257                        (
258                         page,
259                         wxID_ANY,
260                         wxString::Format("(%d, %d)",
261                                          r.x, r.y)
262                        ));
263 
264         sizer->Add(new wxStaticText(page, wxID_ANY, "Size: "));
265         sizer->Add(new wxStaticText
266                        (
267                         page,
268                         wxID_ANY,
269                         wxString::Format("(%d, %d)",
270                                          r.width, r.height)
271                        ));
272 
273         const wxRect rc(display.GetClientArea());
274         sizer->Add(new wxStaticText(page, wxID_ANY, "Client area: "));
275         sizer->Add(new wxStaticText
276                        (
277                         page,
278                         wxID_ANY,
279                         wxString::Format("(%d, %d)-(%d, %d)",
280                                          rc.x, rc.y, rc.width, rc.height)
281                        ));
282 
283         sizer->Add(new wxStaticText(page, wxID_ANY, "Resolution: "));
284         const wxSize ppi = display.GetPPI();
285         sizer->Add(new wxStaticText(page, wxID_ANY,
286                                     wxString::Format("%d*%d", ppi.x, ppi.y)));
287 
288         sizer->Add(new wxStaticText(page, wxID_ANY, "Depth: "));
289         sizer->Add(new wxStaticText(page, wxID_ANY,
290                                     wxString::Format("%d", display.GetDepth())));
291 
292         sizer->Add(new wxStaticText(page, wxID_ANY, "Scaling: "));
293         sizer->Add(new wxStaticText(page, wxID_ANY,
294                                     wxString::Format("%.2f",
295                                                      display.GetScaleFactor())));
296 
297         sizer->Add(new wxStaticText(page, wxID_ANY, "Name: "));
298         sizer->Add(new wxStaticText(page, wxID_ANY, display.GetName()));
299 
300         sizer->Add(new wxStaticText(page, wxID_ANY, "Primary: "));
301         sizer->Add(new wxStaticText(page, wxID_ANY,
302                                     display.IsPrimary() ? "yes" : "no"));
303 
304         // add it to another sizer to have borders around it and button below
305         wxSizer *sizerTop = new wxBoxSizer(wxVERTICAL);
306         sizerTop->Add(sizer, wxSizerFlags(1).Expand().DoubleBorder());
307 
308 #if wxUSE_DISPLAY
309         wxChoice *choiceModes = new wxChoice(page, Display_ChangeMode);
310         const wxArrayVideoModes modes = display.GetModes();
311         const size_t countModes = modes.GetCount();
312         for ( size_t nMode = 0; nMode < countModes; nMode++ )
313         {
314             const wxVideoMode& mode = modes[nMode];
315 
316             choiceModes->Append(VideoModeToText(mode),
317                                 new MyVideoModeClientData(mode));
318         }
319         const wxString currentMode = VideoModeToText(display.GetCurrentMode());
320         choiceModes->SetStringSelection(currentMode);
321 
322         sizer->Add(new wxStaticText(page, wxID_ANY, "&Modes: "),
323                    wxSizerFlags().CentreVertical());
324         sizer->Add(choiceModes, wxSizerFlags().Expand());
325 
326         sizer->Add(new wxStaticText(page, wxID_ANY, "Current: "));
327         sizer->Add(new wxStaticText(page, Display_CurrentMode, currentMode));
328 
329         sizerTop->Add(new wxButton(page, Display_ResetMode, "&Reset mode"),
330                       wxSizerFlags().Centre().Border());
331 #endif // wxUSE_DISPLAY
332 
333         page->SetSizer(sizerTop);
334         page->Layout();
335 
336         m_book->AddPage(page, wxString::Format("Display %zu", nDpy + 1));
337     }
338 
339     SetClientSize(m_book->GetBestSize());
340     SetMinSize(GetSize());
341 }
342 
343 #if wxUSE_DISPLAY
344 
VideoModeToText(const wxVideoMode & mode)345 wxString MyFrame::VideoModeToText(const wxVideoMode& mode)
346 {
347     wxString s;
348     s.Printf("%dx%d", mode.w, mode.h);
349 
350     if ( mode.bpp )
351     {
352         s += wxString::Format(", %dbpp", mode.bpp);
353     }
354 
355     if ( mode.refresh )
356     {
357         s += wxString::Format(", %dHz", mode.refresh);
358     }
359 
360     return s;
361 }
362 
363 #endif // wxUSE_DISPLAY
364 
365 // event handlers
366 
OnQuit(wxCommandEvent & WXUNUSED (event))367 void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
368 {
369     // true is to force the frame to close
370     Close(true);
371 }
372 
OnAbout(wxCommandEvent & WXUNUSED (event))373 void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
374 {
375     wxMessageBox("Demo program for wxDisplay class.\n\n(c) 2003-2006 Vadim Zeitlin",
376                  "About Display Sample",
377                  wxOK | wxICON_INFORMATION,
378                  this);
379 }
380 
OnFromPoint(wxCommandEvent & WXUNUSED (event))381 void MyFrame::OnFromPoint(wxCommandEvent& WXUNUSED(event))
382 {
383 #if wxUSE_STATUSBAR
384     SetStatusText("Press the mouse anywhere...");
385 #endif // wxUSE_STATUSBAR
386 
387     CaptureMouse();
388 }
389 
OnFullScreen(wxCommandEvent & WXUNUSED (event))390 void MyFrame::OnFullScreen(wxCommandEvent& WXUNUSED(event))
391 {
392     ShowFullScreen(!IsFullScreen());
393 }
394 
395 #if wxUSE_DISPLAY
396 
OnChangeMode(wxCommandEvent & event)397 void MyFrame::OnChangeMode(wxCommandEvent& event)
398 {
399     wxDisplay dpy(m_book->GetSelection());
400 
401     // you wouldn't write this in real code, would you?
402     if ( !dpy.ChangeMode(((MyVideoModeClientData *)
403                 wxDynamicCast(event.GetEventObject(), wxChoice)->
404                     GetClientObject(event.GetInt()))->mode) )
405     {
406         wxLogError("Changing video mode failed!");
407     }
408 }
409 
OnResetMode(wxCommandEvent & WXUNUSED (event))410 void MyFrame::OnResetMode(wxCommandEvent& WXUNUSED(event))
411 {
412     wxDisplay dpy(m_book->GetSelection());
413 
414     dpy.ResetMode();
415 }
416 
417 #endif // wxUSE_DISPLAY
418 
OnLeftClick(wxMouseEvent & event)419 void MyFrame::OnLeftClick(wxMouseEvent& event)
420 {
421     if ( HasCapture() )
422     {
423         // mouse events are in client coords, wxDisplay works in screen ones
424         const wxPoint ptScreen = ClientToScreen(event.GetPosition());
425         int dpy = wxDisplay::GetFromPoint(ptScreen);
426         if ( dpy == wxNOT_FOUND )
427         {
428             wxLogError("Mouse clicked outside of display!?");
429         }
430 
431         wxLogStatus(this, "Mouse clicked in display %d (at (%d, %d))",
432                     dpy, ptScreen.x, ptScreen.y);
433 
434         ReleaseMouse();
435     }
436 }
437 
438 #if wxUSE_DISPLAY
439 
OnDisplayChanged(wxDisplayChangedEvent & event)440 void MyFrame::OnDisplayChanged(wxDisplayChangedEvent& event)
441 {
442     m_book->DeleteAllPages();
443     PopuplateWithDisplayInfo();
444 
445     wxLogStatus(this, "Display resolution was changed.");
446 
447     event.Skip();
448 }
449 
450 #endif // wxUSE_DISPLAY
451