]> git.saurik.com Git - wxWidgets.git/blob - src/msw/display.cpp
Inital fill in background, removed tabs, -1->wxID_ANY, TRUE->true, FALSE->false
[wxWidgets.git] / src / msw / display.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: display.cpp
3 // Purpose: MSW Implementation of wxDisplay class
4 // Author: Royce Mitchell III
5 // Modified by: VZ (resolutions enumeration/change support, DirectDraw, ...)
6 // Created: 06/21/02
7 // RCS-ID: $Id$
8 // Copyright: (c) wxWidgets team
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 // ===========================================================================
13 // declarations
14 // ===========================================================================
15
16 // ---------------------------------------------------------------------------
17 // headers
18 // ---------------------------------------------------------------------------
19
20 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
21 #pragma implementation "display.h"
22 #endif
23
24 // For compilers that support precompilation, includes "wx.h".
25 #include "wx/wxprec.h"
26
27 #ifdef __BORLANDC__
28 #pragma hdrstop
29 #endif
30
31 #if wxUSE_DISPLAY
32
33 #ifndef WX_PRECOMP
34 #include "wx/app.h"
35 #include "wx/dynarray.h"
36 #include "wx/frame.h"
37 #endif
38
39 #include "wx/dynload.h"
40
41 #include "wx/display.h"
42
43 // the following define is necessary to access the multi-monitor function
44 // declarations in a manner safe to use w/ Windows 95
45 #define COMPILE_MULTIMON_STUBS
46
47 // if you don't have multimon.h you can download the file from:
48 //
49 // http://www.microsoft.com/msj/0697/monitor/monitortextfigs.htm#fig4
50 //
51
52 #ifdef _MSC_VER
53 // as (m)any standard header(s), this one doesn't compile without warnings
54 // with VC++ 6 <sigh>
55 #pragma warning(disable:4706)
56 #endif
57
58 #include <multimon.h>
59
60 #ifdef _MSC_VER
61 #pragma warning(default:4706)
62 #endif
63
64 #include <ddraw.h>
65
66 // we don't want to link with ddraw.lib which contains the real
67 // IID_IDirectDraw2 definition
68 const GUID wxIID_IDirectDraw2 =
69 { 0xB3A6F3E0, 0x2B43, 0x11CF, { 0xA2,0xDE,0x00,0xAA,0x00,0xB9,0x33,0x56 } };
70
71 // ----------------------------------------------------------------------------
72 // macros
73 // ----------------------------------------------------------------------------
74
75 #ifdef _UNICODE
76 #define WINFUNC(x) _T(#x) L"W"
77 #else
78 #define WINFUNC(x) #x "A"
79 #endif
80
81 // ----------------------------------------------------------------------------
82 // typedefs for dynamically loaded Windows functions
83 // ----------------------------------------------------------------------------
84
85 typedef LONG (WINAPI *ChangeDisplaySettingsEx_t)(LPCTSTR lpszDeviceName,
86 LPDEVMODE lpDevMode,
87 HWND hwnd,
88 DWORD dwFlags,
89 LPVOID lParam);
90
91 typedef BOOL (PASCAL *DDEnumExCallback_t)(GUID *pGuid,
92 LPTSTR driverDescription,
93 LPTSTR driverName,
94 LPVOID lpContext,
95 HMONITOR hmon);
96
97 typedef HRESULT (WINAPI *DirectDrawEnumerateEx_t)(DDEnumExCallback_t lpCallback,
98 LPVOID lpContext,
99 DWORD dwFlags);
100
101 typedef HRESULT (WINAPI *DirectDrawCreate_t)(GUID *lpGUID,
102 LPDIRECTDRAW *lplpDD,
103 IUnknown *pUnkOuter);
104
105 // ----------------------------------------------------------------------------
106 // private classes
107 // ----------------------------------------------------------------------------
108
109 class wxDisplayInfo
110 {
111 public:
112 // handle of this monitor used by MonitorXXX() functions, never NULL
113 HMONITOR m_hmon;
114
115 // IDirectDraw object used to control this display, may be NULL
116 IDirectDraw2 *m_pDD2;
117
118 // DirectDraw GUID for this display, only valid when using DirectDraw
119 GUID m_guid;
120
121 // the entire area of this monitor in virtual screen coordinates
122 wxRect m_rect;
123
124 // the display device name for this monitor, empty initially and retrieved
125 // on demand by DoGetName()
126 wxString m_devName;
127
128 wxDisplayInfo() { m_hmon = NULL; m_pDD2 = NULL; }
129 ~wxDisplayInfo() { if ( m_pDD2 ) m_pDD2->Release(); }
130 };
131
132 WX_DECLARE_OBJARRAY(wxDisplayInfo, wxDisplayInfoArray);
133 #include "wx/arrimpl.cpp"
134 WX_DEFINE_OBJARRAY(wxDisplayInfoArray);
135
136 // this module is used to cleanup gs_displays array
137 class wxDisplayModule : public wxModule
138 {
139 public:
140 virtual bool OnInit() { return true; }
141 virtual void OnExit();
142
143 DECLARE_DYNAMIC_CLASS(wxDisplayModule)
144 };
145
146 IMPLEMENT_DYNAMIC_CLASS(wxDisplayModule, wxModule)
147
148 // ----------------------------------------------------------------------------
149 // globals
150 // ----------------------------------------------------------------------------
151
152 // do we use DirectX?
153 static bool gs_useDirectX = false;
154
155 // dynamically resolved DirectDrawCreate()
156 static DirectDrawCreate_t gs_DirectDrawCreate = NULL;
157
158 // this is not really MT-unsafe as wxDisplay is only going to be used from the
159 // main thread, i.e. we consider that it's a GUI class and so don't protect it
160 static wxDisplayInfoArray *gs_displays = NULL;
161
162 // ===========================================================================
163 // implementation
164 // ===========================================================================
165
166 // ----------------------------------------------------------------------------
167 // callbacks for monitor/modes enumeration stuff
168 // ----------------------------------------------------------------------------
169
170 static BOOL CALLBACK wxmswMonitorEnumProc (
171 HMONITOR hMonitor, // handle to display monitor
172 HDC WXUNUSED(hdcMonitor), // handle to monitor-appropriate device context
173 LPRECT lprcMonitor, // pointer to monitor intersection rectangle
174 LPARAM WXUNUSED(dwData) // data passed from EnumDisplayMonitors (unused)
175 )
176 {
177 wxDisplayInfo *info = new wxDisplayInfo();
178
179 // we need hMonitor to be able to map display id to it which is needed for
180 // MonitorXXX() functions, in particular MonitorFromPoint()
181 info->m_hmon = hMonitor;
182
183 // we also store the display geometry
184 info->m_rect.SetX ( lprcMonitor->left );
185 info->m_rect.SetY ( lprcMonitor->top );
186 info->m_rect.SetWidth ( lprcMonitor->right - lprcMonitor->left );
187 info->m_rect.SetHeight ( lprcMonitor->bottom - lprcMonitor->top );
188
189 // now add this monitor to the array
190 gs_displays->Add(info);
191
192 // continue the enumeration
193 return true;
194 }
195
196 BOOL PASCAL
197 wxDDEnumExCallback(GUID *pGuid,
198 LPTSTR WXUNUSED(driverDescription),
199 LPTSTR driverName,
200 LPVOID WXUNUSED(lpContext),
201 HMONITOR hmon)
202 {
203 if ( pGuid )
204 {
205 wxDisplayInfo *info = new wxDisplayInfo();
206
207 info->m_hmon = hmon;
208 info->m_guid = *pGuid;
209 info->m_devName = driverName;
210
211 gs_displays->Add(info);
212 }
213 //else: we're called for the primary monitor, skip it
214
215 // continue the enumeration
216 return true;
217 }
218
219 HRESULT WINAPI wxDDEnumModesCallback(LPDDSURFACEDESC lpDDSurfaceDesc,
220 LPVOID lpContext)
221 {
222 // we need at least the mode size
223 static const DWORD FLAGS_REQUIRED = DDSD_HEIGHT | DDSD_WIDTH;
224 if ( (lpDDSurfaceDesc->dwFlags & FLAGS_REQUIRED) == FLAGS_REQUIRED )
225 {
226 wxArrayVideoModes * const modes = (wxArrayVideoModes *)lpContext;
227
228 modes->Add(wxVideoMode(lpDDSurfaceDesc->dwWidth,
229 lpDDSurfaceDesc->dwHeight,
230 lpDDSurfaceDesc->ddpfPixelFormat.dwRGBBitCount,
231 lpDDSurfaceDesc->dwRefreshRate));
232 }
233
234 // continue the enumeration
235 return DDENUMRET_OK;
236 }
237
238 // ----------------------------------------------------------------------------
239 // local functions
240 // ----------------------------------------------------------------------------
241
242 // initialize gs_displays using DirectX functions
243 static bool DoInitDirectX()
244 {
245 // suppress the errors if ddraw.dll is not found
246 wxLog::EnableLogging(false);
247
248 wxDynamicLibrary dllDX(_T("ddraw.dll"));
249
250 wxLog::EnableLogging(true);
251
252 if ( !dllDX.IsLoaded() )
253 return false;
254
255 DirectDrawEnumerateEx_t pDDEnumEx = (DirectDrawEnumerateEx_t)
256 dllDX.GetSymbol(WINFUNC(DirectDrawEnumerateEx));
257 if ( !pDDEnumEx )
258 return false;
259
260 // we'll also need DirectDrawCreate() later, resolve it right now
261 gs_DirectDrawCreate = (DirectDrawCreate_t)
262 dllDX.GetSymbol(_T("DirectDrawCreate"));
263 if ( !gs_DirectDrawCreate )
264 return false;
265
266 if ( (*pDDEnumEx)(wxDDEnumExCallback,
267 NULL,
268 DDENUM_ATTACHEDSECONDARYDEVICES) != DD_OK )
269 {
270 return false;
271 }
272
273 // ok, it seems like we're going to use DirectDraw and so we're going to
274 // need ddraw.dll all the time, don't unload it
275 dllDX.Detach();
276
277 return true;
278 }
279
280 // initialize gs_displays using the standard Windows functions
281 static void DoInitStdWindows()
282 {
283 // enumerate all displays
284 if ( !::EnumDisplayMonitors(NULL, NULL, wxmswMonitorEnumProc, 0) )
285 {
286 wxLogLastError(wxT("EnumDisplayMonitors"));
287
288 // TODO: still create at least one (valid) entry in gs_displays for the
289 // primary display!
290 }
291 }
292
293 // this function must be called before accessing gs_displays array as it
294 // creates and initializes it
295 static void InitDisplays()
296 {
297 if ( gs_displays )
298 return;
299
300 gs_displays = new wxDisplayInfoArray();
301
302 if ( !gs_useDirectX || !DoInitDirectX() )
303 {
304 // either we were told not to try to use DirectX or fall back to std
305 // functions if DirectX method failed
306 gs_useDirectX = false;
307
308 DoInitStdWindows();
309 }
310 }
311
312 // convert a DEVMODE to our wxVideoMode
313 wxVideoMode ConvertToVideoMode(const DEVMODE& dm)
314 {
315 // note that dmDisplayFrequency may be 0 or 1 meaning "standard one" and
316 // although 0 is ok for us we don't want to return modes with 1hz refresh
317 return wxVideoMode(dm.dmPelsWidth,
318 dm.dmPelsHeight,
319 dm.dmBitsPerPel,
320 dm.dmDisplayFrequency > 1 ? dm.dmDisplayFrequency : 0);
321 }
322
323 // emulation of ChangeDisplaySettingsEx() for Win95
324 LONG WINAPI ChangeDisplaySettingsExForWin95(LPCTSTR WXUNUSED(lpszDeviceName),
325 LPDEVMODE lpDevMode,
326 HWND WXUNUSED(hwnd),
327 DWORD dwFlags,
328 LPVOID WXUNUSED(lParam))
329 {
330 return ::ChangeDisplaySettings(lpDevMode, dwFlags);
331 }
332
333 // ----------------------------------------------------------------------------
334 // wxDisplayModule
335 // ----------------------------------------------------------------------------
336
337 void wxDisplayModule::OnExit()
338 {
339 delete gs_displays;
340 }
341
342 // ---------------------------------------------------------------------------
343 // wxDisplay
344 // ---------------------------------------------------------------------------
345
346 /* static */
347 void wxDisplay::UseDirectX(bool useDX)
348 {
349 wxCHECK_RET( !gs_displays, _T("it is too late to call UseDirectX") );
350
351 gs_useDirectX = useDX;
352 }
353
354 // helper of GetFromPoint() and GetFromWindow()
355 static int DisplayFromHMONITOR(HMONITOR hmon)
356 {
357 if ( hmon )
358 {
359 const size_t count = wxDisplay::GetCount();
360
361 for ( size_t n = 0; n < count; n++ )
362 {
363 if ( hmon == (*gs_displays)[n].m_hmon )
364 return n;
365 }
366 }
367
368 return wxNOT_FOUND;
369 }
370
371 /* static */
372 size_t wxDisplayBase::GetCount()
373 {
374 InitDisplays();
375
376 // I'm not sure if they really always return the same thing and if this is
377 // not true I'd like to know in which situation does it happen
378 wxASSERT_MSG( gs_displays->GetCount() == (size_t)::GetSystemMetrics(SM_CMONITORS),
379 _T("So how many displays does this system have?") );
380
381 return gs_displays->GetCount();
382 }
383
384 /* static */
385 int wxDisplayBase::GetFromPoint ( const wxPoint& pt )
386 {
387 POINT pt2;
388 pt2.x = pt.x;
389 pt2.y = pt.y;
390
391 return DisplayFromHMONITOR(::MonitorFromPoint(pt2, MONITOR_DEFAULTTONULL));
392 }
393
394 /* static */
395 int wxDisplayBase::GetFromWindow(wxWindow *window)
396 {
397 return DisplayFromHMONITOR
398 (
399 ::MonitorFromWindow(GetHwndOf(window), MONITOR_DEFAULTTONULL)
400 );
401 }
402
403 // ----------------------------------------------------------------------------
404 // wxDisplay ctor/dtor
405 // ----------------------------------------------------------------------------
406
407 wxDisplay::wxDisplay ( size_t n )
408 : wxDisplayBase ( n )
409 {
410 // if we do this in ctor we won't have to call it from all the member
411 // functions
412 InitDisplays();
413
414 if ( gs_useDirectX )
415 {
416 wxDisplayInfo& dpyInfo = (*gs_displays)[n];
417
418 LPDIRECTDRAW2& pDD2 = dpyInfo.m_pDD2;
419 if ( !pDD2 )
420 {
421 if ( !gs_DirectDrawCreate )
422 {
423 // what to do??
424 return;
425 }
426
427 IDirectDraw *pDD;
428 HRESULT hr = (*gs_DirectDrawCreate)(&dpyInfo.m_guid, &pDD, NULL);
429
430 if ( FAILED(hr) || !pDD )
431 {
432 // what to do??
433 wxLogApiError(_T("DirectDrawCreate"), hr);
434 }
435 else // got IDirectDraw, we want IDirectDraw2
436 {
437 hr = pDD->QueryInterface(wxIID_IDirectDraw2, (void **)&pDD2);
438 if ( FAILED(hr) || !pDD2 )
439 {
440 wxLogApiError(_T("IDirectDraw::QueryInterface(IDD2)"), hr);
441 }
442
443 pDD->Release();
444 }
445 }
446 //else: DirectDraw object corresponding to our display already exists
447
448 // increment its ref count to account for Release() in dtor
449 //
450 // NB: pDD2 will be only really Release()d when gs_displays is
451 // destroyed which is ok as we don't want to recreate DD objects
452 // all the time
453 pDD2->AddRef();
454 }
455 }
456
457 wxDisplay::~wxDisplay()
458 {
459 wxDisplayInfo& dpyInfo = (*gs_displays)[m_index];
460
461 LPDIRECTDRAW2& pDD2 = dpyInfo.m_pDD2;
462 if ( pDD2 )
463 {
464 pDD2->Release();
465 }
466 }
467
468 // ----------------------------------------------------------------------------
469 // wxDisplay simple accessors
470 // ----------------------------------------------------------------------------
471
472 bool wxDisplay::IsOk() const
473 {
474 return m_index < GetCount() &&
475 (!gs_useDirectX || (*gs_displays)[m_index].m_pDD2);
476 }
477
478 wxRect wxDisplay::GetGeometry() const
479 {
480 wxDisplayInfo& dpyInfo = (*gs_displays)[m_index];
481 wxRect& rect = dpyInfo.m_rect;
482 if ( !rect.width )
483 {
484 MONITORINFO monInfo;
485 wxZeroMemory(monInfo);
486 monInfo.cbSize = sizeof(monInfo);
487
488 if ( !::GetMonitorInfo(dpyInfo.m_hmon, &monInfo) )
489 {
490 wxLogLastError(_T("GetMonitorInfo"));
491 }
492 else
493 {
494 wxCopyRECTToRect(monInfo.rcMonitor, rect);
495 }
496 }
497
498 return rect;
499 }
500
501 wxString wxDisplay::GetName() const
502 {
503 wxDisplayInfo& dpyInfo = (*gs_displays)[m_index];
504 if ( dpyInfo.m_devName.empty() )
505 {
506 MONITORINFOEX monInfo;
507 wxZeroMemory(monInfo);
508 monInfo.cbSize = sizeof(monInfo);
509
510 // NB: Cast from MONITORINFOEX* to MONITORINFO* is done because
511 // Mingw headers - unlike the ones from Microsoft's Platform SDK -
512 // don't derive the former from the latter in C++ mode and so
513 // the pointer's type is not converted implicitly.
514 if ( !::GetMonitorInfo(dpyInfo.m_hmon, (LPMONITORINFO)&monInfo) )
515 {
516 wxLogLastError(_T("GetMonitorInfo"));
517 }
518 else
519 {
520 dpyInfo.m_devName = monInfo.szDevice;
521 }
522 }
523
524 return dpyInfo.m_devName;
525 }
526
527 wxString wxDisplay::GetNameForEnumSettings() const
528 {
529 int major, minor;
530 const bool isWin95 = wxGetOsVersion(&major, &minor) == wxWIN95 &&
531 major == 4 && minor == 0;
532
533 // the first parameter of EnumDisplaySettings() must be NULL under Win95
534 // according to MSDN but GetMonitorInfo() stub in multimon.h still returns
535 // something even in this case, so we have to correct this manually
536 wxString name;
537 if ( !isWin95 )
538 name = GetName();
539
540 return name;
541 }
542
543 // ----------------------------------------------------------------------------
544 // video modes enumeration
545 // ----------------------------------------------------------------------------
546
547 wxArrayVideoModes
548 wxDisplay::DoGetModesDirectX(const wxVideoMode& WXUNUSED(modeMatch)) const
549 {
550 wxArrayVideoModes modes;
551
552 IDirectDraw2 *pDD = (*gs_displays)[m_index].m_pDD2;
553
554 if ( pDD )
555 {
556 HRESULT hr = pDD->EnumDisplayModes
557 (
558 DDEDM_REFRESHRATES,
559 NULL, // all modes (TODO: use modeMatch!)
560 &modes, // callback parameter
561 wxDDEnumModesCallback
562 );
563
564 if ( FAILED(hr) )
565 {
566 wxLogApiError(_T("IDirectDraw::EnumDisplayModes"), hr);
567 }
568 }
569
570 return modes;
571 }
572
573 wxArrayVideoModes
574 wxDisplay::DoGetModesWindows(const wxVideoMode& modeMatch) const
575 {
576 wxArrayVideoModes modes;
577
578 const wxString name = GetNameForEnumSettings();
579
580 const wxChar * const deviceName = name.empty() ? NULL : name.c_str();
581
582 DEVMODE dm;
583 for ( int iModeNum = 0;
584 ::EnumDisplaySettings(deviceName, iModeNum, &dm);
585 iModeNum++ )
586 {
587 const wxVideoMode mode = ConvertToVideoMode(dm);
588 if ( mode.Matches(modeMatch) )
589 {
590 modes.Add(mode);
591 }
592 }
593
594 return modes;
595 }
596
597 wxArrayVideoModes wxDisplay::GetModes(const wxVideoMode& modeMatch) const
598 {
599 return gs_useDirectX ? DoGetModesDirectX(modeMatch)
600 : DoGetModesWindows(modeMatch);
601 }
602
603 wxVideoMode wxDisplay::GetCurrentMode() const
604 {
605 wxVideoMode mode;
606
607 const wxString name = GetNameForEnumSettings();
608
609 DEVMODE dm;
610 if ( !::EnumDisplaySettings(name.empty() ? NULL : name.c_str(),
611 ENUM_CURRENT_SETTINGS,
612 &dm) )
613 {
614 wxLogLastError(_T("EnumDisplaySettings(ENUM_CURRENT_SETTINGS)"));
615 }
616 else
617 {
618 mode = ConvertToVideoMode(dm);
619 }
620
621 return mode;
622 }
623
624 // ----------------------------------------------------------------------------
625 // video mode switching
626 // ----------------------------------------------------------------------------
627
628 bool wxDisplay::DoChangeModeDirectX(const wxVideoMode& mode)
629 {
630 IDirectDraw2 *pDD = (*gs_displays)[m_index].m_pDD2;
631 if ( !pDD )
632 return false;
633
634 wxWindow *winTop = wxTheApp->GetTopWindow();
635 wxCHECK_MSG( winTop, false, _T("top level window required for DirectX") );
636
637 HRESULT hr = pDD->SetCooperativeLevel
638 (
639 GetHwndOf(winTop),
640 DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN
641 );
642 if ( FAILED(hr) )
643 {
644 wxLogApiError(_T("IDirectDraw::SetCooperativeLevel"), hr);
645
646 return false;
647 }
648
649 hr = pDD->SetDisplayMode(mode.w, mode.h, mode.bpp, mode.refresh, 0);
650 if ( FAILED(hr) )
651 {
652 wxLogApiError(_T("IDirectDraw::SetDisplayMode"), hr);
653
654 return false;
655 }
656
657
658 return true;
659 }
660
661 bool wxDisplay::DoChangeModeWindows(const wxVideoMode& mode)
662 {
663 // prepare ChangeDisplaySettingsEx() parameters
664 DEVMODE dm,
665 *pDevMode;
666 int flags;
667
668 if ( mode == wxDefaultVideoMode )
669 {
670 // reset the video mode to default
671 pDevMode = NULL;
672 flags = 0;
673 }
674 else // change to the given mode
675 {
676 wxCHECK_MSG( mode.w && mode.h, false,
677 _T("at least the width and height must be specified") );
678
679 wxZeroMemory(dm);
680 dm.dmSize = sizeof(dm);
681 dm.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
682 dm.dmPelsWidth = mode.w;
683 dm.dmPelsHeight = mode.h;
684
685 if ( mode.bpp )
686 {
687 dm.dmFields |= DM_BITSPERPEL;
688 dm.dmBitsPerPel = mode.bpp;
689 }
690
691 if ( mode.refresh )
692 {
693 dm.dmFields |= DM_DISPLAYFREQUENCY;
694 dm.dmDisplayFrequency = mode.refresh;
695 }
696
697 pDevMode = &dm;
698
699 flags = CDS_FULLSCREEN;
700 }
701
702
703 // get pointer to the function dynamically
704 //
705 // we're only called from the main thread, so it's ok to use static
706 // variable
707 static ChangeDisplaySettingsEx_t pfnChangeDisplaySettingsEx = NULL;
708 if ( !pfnChangeDisplaySettingsEx )
709 {
710 wxDynamicLibrary dllUser32(_T("user32.dll"));
711 if ( dllUser32.IsLoaded() )
712 {
713 pfnChangeDisplaySettingsEx = (ChangeDisplaySettingsEx_t)
714 dllUser32.GetSymbol(WINFUNC(ChangeDisplaySettingsEx));
715 }
716 //else: huh, no user32.dll??
717
718 if ( !pfnChangeDisplaySettingsEx )
719 {
720 // we must be under Win95 and so there is no multiple monitors
721 // support anyhow
722 pfnChangeDisplaySettingsEx = ChangeDisplaySettingsExForWin95;
723 }
724 }
725
726 // do change the mode
727 switch ( pfnChangeDisplaySettingsEx
728 (
729 GetName(), // display name
730 pDevMode, // dev mode or NULL to reset
731 NULL, // reserved
732 flags,
733 NULL // pointer to video parameters (not used)
734 ) )
735 {
736 case DISP_CHANGE_SUCCESSFUL:
737 // ok
738 {
739 // If we have a top-level, full-screen frame, emulate
740 // the DirectX behavior and resize it. This makes this
741 // API quite a bit easier to use.
742 wxWindow *winTop = wxTheApp->GetTopWindow();
743 wxFrame *frameTop = wxDynamicCast(winTop, wxFrame);
744 if (frameTop && frameTop->IsFullScreen())
745 {
746 wxVideoMode current = GetCurrentMode();
747 frameTop->SetClientSize(current.w, current.h);
748 }
749 }
750 return true;
751
752 case DISP_CHANGE_BADMODE:
753 // don't complain about this, this is the only "expected" error
754 break;
755
756 default:
757 wxFAIL_MSG( _T("unexpected ChangeDisplaySettingsEx() return value") );
758 }
759
760 return false;
761 }
762
763 bool wxDisplay::ChangeMode(const wxVideoMode& mode)
764 {
765 return gs_useDirectX ? DoChangeModeDirectX(mode)
766 : DoChangeModeWindows(mode);
767 }
768
769 #endif // wxUSE_DISPLAY
770