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