1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/msw/display.cpp
3 // Purpose: MSW Implementation of wxDisplay class
4 // Author: Royce Mitchell III
5 // Modified by: VZ (resolutions enumeration/change support, DirectDraw, ...)
6 // Ryan Norton (IsPrimary override)
9 // Copyright: (c) wxWidgets team
10 // Licence: wxWindows licence
11 /////////////////////////////////////////////////////////////////////////////
13 // ===========================================================================
15 // ===========================================================================
17 // ---------------------------------------------------------------------------
19 // ---------------------------------------------------------------------------
21 // For compilers that support precompilation, includes "wx.h".
22 #include "wx/wxprec.h"
32 #include "wx/dynarray.h"
36 #include "wx/dynload.h"
38 #include "wx/display.h"
40 // Mingw's w32api headers don't include ddraw.h, though the user may have
41 // installed it. If using configure, we actually probe for ddraw.h there
42 // and set HAVE_DDRAW_H. Otherwise, assume we don't have it if using
43 // the w32api headers, and that we do otherwise.
44 #if !defined HAVE_W32API_H && !defined HAVE_DDRAW_H
45 #define HAVE_DDRAW_H 1
49 // Older versions of windef.h don't define HMONITOR. Unfortunately, we
50 // can't directly test whether HMONITOR is defined or not in windef.h as
51 // it's not a macro but a typedef, so we test for an unrelated symbol which
52 // is only defined in winuser.h if WINVER >= 0x0500
53 #if !defined(HMONITOR_DECLARED) && !defined(MNS_NOCHECK)
54 DECLARE_HANDLE(HMONITOR
);
55 #define HMONITOR_DECLARED
57 #endif // !__WXWINCE__
62 // we don't want to link with ddraw.lib which contains the real
63 // IID_IDirectDraw2 definition
64 const GUID wxIID_IDirectDraw2
=
65 { 0xB3A6F3E0, 0x2B43, 0x11CF, { 0xA2,0xDE,0x00,0xAA,0x00,0xB9,0x33,0x56 } };
68 // ----------------------------------------------------------------------------
70 // ----------------------------------------------------------------------------
73 #define WINFUNC(x) _T(#x) L"W"
75 #define WINFUNC(x) #x "A"
78 // ----------------------------------------------------------------------------
79 // typedefs for dynamically loaded Windows functions
80 // ----------------------------------------------------------------------------
82 typedef LONG (WINAPI
*ChangeDisplaySettingsEx_t
)(LPCTSTR lpszDeviceName
,
89 typedef BOOL (PASCAL
*DDEnumExCallback_t
)(GUID
*pGuid
,
90 LPTSTR driverDescription
,
95 typedef HRESULT (WINAPI
*DirectDrawEnumerateEx_t
)(DDEnumExCallback_t lpCallback
,
99 typedef HRESULT (WINAPI
*DirectDrawCreate_t
)(GUID
*lpGUID
,
100 LPDIRECTDRAW
*lplpDD
,
101 IUnknown
*pUnkOuter
);
104 typedef BOOL (WINAPI
*EnumDisplayMonitors_t
)(HDC
,LPCRECT
,MONITORENUMPROC
,LPARAM
);
105 typedef HMONITOR (WINAPI
*MonitorFromPoint_t
)(POINT
,DWORD
);
106 typedef HMONITOR (WINAPI
*MonitorFromWindow_t
)(HWND
,DWORD
);
107 typedef BOOL (WINAPI
*GetMonitorInfo_t
)(HMONITOR
,LPMONITORINFO
);
109 static EnumDisplayMonitors_t gs_EnumDisplayMonitors
= NULL
;
110 static MonitorFromPoint_t gs_MonitorFromPoint
= NULL
;
111 static MonitorFromWindow_t gs_MonitorFromWindow
= NULL
;
112 static GetMonitorInfo_t gs_GetMonitorInfo
= NULL
;
114 // ----------------------------------------------------------------------------
116 // ----------------------------------------------------------------------------
121 // handle of this monitor used by MonitorXXX() functions, never NULL
124 // IDirectDraw object used to control this display, may be NULL
126 IDirectDraw2
*m_pDD2
;
131 // DirectDraw GUID for this display, only valid when using DirectDraw
134 // the entire area of this monitor in virtual screen coordinates
137 // the display device name for this monitor, empty initially and retrieved
138 // on demand by DoGetName()
141 wxDisplayInfo() { m_hmon
= NULL
; m_pDD2
= NULL
; }
144 if ( m_pDD2
) m_pDD2
->Release();
149 WX_DECLARE_OBJARRAY(wxDisplayInfo
, wxDisplayInfoArray
);
150 #include "wx/arrimpl.cpp"
151 WX_DEFINE_OBJARRAY(wxDisplayInfoArray
);
153 // this module is used to cleanup gs_displays array
154 class wxDisplayModule
: public wxModule
157 virtual bool OnInit() { return true; }
158 virtual void OnExit();
160 DECLARE_DYNAMIC_CLASS(wxDisplayModule
)
163 IMPLEMENT_DYNAMIC_CLASS(wxDisplayModule
, wxModule
)
165 // ----------------------------------------------------------------------------
167 // ----------------------------------------------------------------------------
170 // do we use DirectX?
171 static bool gs_useDirectX
= false;
174 // Try to look up the functions needed for supporting multiple monitors. If
175 // they aren't available (probably because we're running on Win95 or NT4 which
176 // predate this API), set a flag which makes wxDisplay return results for a
178 static bool OsSupportsMultipleMonitors()
180 static int isNewEnough
= -1;
181 if ( isNewEnough
== -1 )
184 wxDynamicLibrary
dllUser32(_T("user32.dll"));
185 // Check for one of the symbols to avoid logging errors just because
186 // we happen to be running on Win95 or NT4.
187 if ( dllUser32
.IsLoaded() &&
188 dllUser32
.HasSymbol(wxT("EnumDisplayMonitors")) )
190 // GetMonitorInfo has Unicode/ANSI variants, the others don't.
191 gs_EnumDisplayMonitors
= (EnumDisplayMonitors_t
)
192 dllUser32
.GetSymbol(wxT("EnumDisplayMonitors"));
193 gs_MonitorFromPoint
= (MonitorFromPoint_t
)
194 dllUser32
.GetSymbol(wxT("MonitorFromPoint"));
195 gs_MonitorFromWindow
= (MonitorFromWindow_t
)
196 dllUser32
.GetSymbol(wxT("MonitorFromWindow"));
197 gs_GetMonitorInfo
= (GetMonitorInfo_t
)
198 dllUser32
.GetSymbol(WINFUNC(GetMonitorInfo
));
199 if ( gs_EnumDisplayMonitors
!= NULL
&&
200 gs_MonitorFromPoint
!= NULL
&&
201 gs_MonitorFromWindow
!= NULL
&&
202 gs_GetMonitorInfo
!= NULL
)
208 return (isNewEnough
!= 0);
212 // dynamically resolved DirectDrawCreate()
213 static DirectDrawCreate_t gs_DirectDrawCreate
= NULL
;
216 // this is not really MT-unsafe as wxDisplay is only going to be used from the
217 // main thread, i.e. we consider that it's a GUI class and so don't protect it
218 static wxDisplayInfoArray
*gs_displays
= NULL
;
220 // ===========================================================================
222 // ===========================================================================
224 // ----------------------------------------------------------------------------
225 // callbacks for monitor/modes enumeration stuff
226 // ----------------------------------------------------------------------------
228 static BOOL CALLBACK
wxmswMonitorEnumProc (
229 HMONITOR hMonitor
, // handle to display monitor
230 HDC
WXUNUSED(hdcMonitor
), // handle to monitor-appropriate device context
231 LPRECT lprcMonitor
, // pointer to monitor intersection rectangle
232 LPARAM
WXUNUSED(dwData
) // data passed from EnumDisplayMonitors (unused)
235 wxDisplayInfo
*info
= new wxDisplayInfo();
237 // we need hMonitor to be able to map display id to it which is needed for
238 // MonitorXXX() functions, in particular MonitorFromPoint()
239 info
->m_hmon
= hMonitor
;
241 // we also store the display geometry
242 info
->m_rect
.SetX ( lprcMonitor
->left
);
243 info
->m_rect
.SetY ( lprcMonitor
->top
);
244 info
->m_rect
.SetWidth ( lprcMonitor
->right
- lprcMonitor
->left
);
245 info
->m_rect
.SetHeight ( lprcMonitor
->bottom
- lprcMonitor
->top
);
247 // now add this monitor to the array
248 gs_displays
->Add(info
);
250 // continue the enumeration
256 wxDDEnumExCallback(GUID
*pGuid
,
257 LPTSTR
WXUNUSED(driverDescription
),
259 LPVOID
WXUNUSED(lpContext
),
264 wxDisplayInfo
*info
= new wxDisplayInfo();
267 info
->m_guid
= *pGuid
;
268 info
->m_devName
= driverName
;
270 gs_displays
->Add(info
);
272 //else: we're called for the primary monitor, skip it
274 // continue the enumeration
278 HRESULT WINAPI
wxDDEnumModesCallback(LPDDSURFACEDESC lpDDSurfaceDesc
,
281 // we need at least the mode size
282 static const DWORD FLAGS_REQUIRED
= DDSD_HEIGHT
| DDSD_WIDTH
;
283 if ( (lpDDSurfaceDesc
->dwFlags
& FLAGS_REQUIRED
) == FLAGS_REQUIRED
)
285 wxArrayVideoModes
* const modes
= (wxArrayVideoModes
*)lpContext
;
287 modes
->Add(wxVideoMode(lpDDSurfaceDesc
->dwWidth
,
288 lpDDSurfaceDesc
->dwHeight
,
289 lpDDSurfaceDesc
->ddpfPixelFormat
.dwRGBBitCount
,
290 lpDDSurfaceDesc
->dwRefreshRate
));
293 // continue the enumeration
298 // ----------------------------------------------------------------------------
300 // ----------------------------------------------------------------------------
303 // initialize gs_displays using DirectX functions
304 static bool DoInitDirectX()
307 // suppress the errors if ddraw.dll is not found
308 wxLog::EnableLogging(false);
311 wxDynamicLibrary
dllDX(_T("ddraw.dll"));
314 wxLog::EnableLogging();
317 if ( !dllDX
.IsLoaded() )
320 DirectDrawEnumerateEx_t pDDEnumEx
= (DirectDrawEnumerateEx_t
)
321 dllDX
.GetSymbol(WINFUNC(DirectDrawEnumerateEx
));
325 // we'll also need DirectDrawCreate() later, resolve it right now
326 gs_DirectDrawCreate
= (DirectDrawCreate_t
)
327 dllDX
.GetSymbol(_T("DirectDrawCreate"));
328 if ( !gs_DirectDrawCreate
)
331 if ( (*pDDEnumEx
)(wxDDEnumExCallback
,
333 DDENUM_ATTACHEDSECONDARYDEVICES
) != DD_OK
)
338 // ok, it seems like we're going to use DirectDraw and so we're going to
339 // need ddraw.dll all the time, don't unload it
346 // initialize gs_displays using the standard Windows functions
347 static void DoInitStdWindows()
349 // enumerate all displays
350 if ( !gs_EnumDisplayMonitors(NULL
, NULL
, wxmswMonitorEnumProc
, 0) )
352 wxLogLastError(wxT("EnumDisplayMonitors"));
354 // TODO: still create at least one (valid) entry in gs_displays for the
359 // this function must be called before accessing gs_displays array as it
360 // creates and initializes it
361 static void InitDisplays()
366 gs_displays
= new wxDisplayInfoArray();
369 if ( !gs_useDirectX
|| !DoInitDirectX() )
371 // either we were told not to try to use DirectX or fall back to std
372 // functions if DirectX method failed
373 gs_useDirectX
= false;
382 // convert a DEVMODE to our wxVideoMode
383 wxVideoMode
ConvertToVideoMode(const DEVMODE
& dm
)
385 // note that dmDisplayFrequency may be 0 or 1 meaning "standard one" and
386 // although 0 is ok for us we don't want to return modes with 1hz refresh
387 return wxVideoMode(dm
.dmPelsWidth
,
390 dm
.dmDisplayFrequency
> 1 ? dm
.dmDisplayFrequency
: 0);
394 // emulation of ChangeDisplaySettingsEx() for Win95
395 LONG WINAPI
ChangeDisplaySettingsExForWin95(LPCTSTR
WXUNUSED(lpszDeviceName
),
399 LPVOID
WXUNUSED(lParam
))
401 return ::ChangeDisplaySettings(lpDevMode
, dwFlags
);
403 #endif // !__WXWINCE__
405 // ----------------------------------------------------------------------------
407 // ----------------------------------------------------------------------------
409 void wxDisplayModule::OnExit()
414 // ---------------------------------------------------------------------------
416 // ---------------------------------------------------------------------------
419 void wxDisplay::UseDirectX(bool useDX
)
421 wxCHECK_RET( !gs_displays
, _T("it is too late to call UseDirectX") );
424 // DirectDrawEnumerateEx requires Win98 or Win2k anyway.
425 if ( OsSupportsMultipleMonitors() ) gs_useDirectX
= useDX
;
431 // helper for GetFromPoint() and GetFromWindow()
432 static int DisplayFromHMONITOR(HMONITOR hmon
)
436 const size_t count
= wxDisplay::GetCount();
438 for ( size_t n
= 0; n
< count
; n
++ )
440 if ( hmon
== (*gs_displays
)[n
].m_hmon
)
449 size_t wxDisplayBase::GetCount()
451 if ( !OsSupportsMultipleMonitors() ) return 1;
455 //RN: FIXME: This is wrong - the display info array should reload after every call
456 //to GetCount() - otherwise it will not be accurate.
457 //The user can change the number of displays in display properties/settings
458 //after GetCount or similar is called and really mess this up...
459 //wxASSERT_MSG( gs_displays->GetCount() == (size_t)::GetSystemMetrics(SM_CMONITORS),
460 // _T("So how many displays does this system have?") );
462 return gs_displays
->GetCount();
466 int wxDisplayBase::GetFromPoint ( const wxPoint
& pt
)
468 if ( !OsSupportsMultipleMonitors() )
470 const wxSize size
= wxGetDisplaySize();
471 if (pt
.x
>= 0 && pt
.x
< size
.GetWidth() &&
472 pt
.y
>= 0 && pt
.y
< size
.GetHeight())
483 return DisplayFromHMONITOR(gs_MonitorFromPoint(pt2
, MONITOR_DEFAULTTONULL
));
487 int wxDisplayBase::GetFromWindow(wxWindow
*window
)
489 if ( !OsSupportsMultipleMonitors() )
491 const wxRect
r(window
->GetRect());
492 const wxSize size
= wxGetDisplaySize();
493 if (r
.x
< size
.GetWidth() && r
.x
+ r
.width
>= 0 &&
494 r
.y
< size
.GetHeight() && r
.y
+ r
.height
>= 0)
501 return DisplayFromHMONITOR
503 gs_MonitorFromWindow(GetHwndOf(window
), MONITOR_DEFAULTTONULL
)
507 // ----------------------------------------------------------------------------
508 // wxDisplay ctor/dtor
509 // ----------------------------------------------------------------------------
511 wxDisplay::wxDisplay ( size_t n
)
512 : wxDisplayBase ( n
)
514 if ( !OsSupportsMultipleMonitors() ) return;
516 // if we do this in ctor we won't have to call it from all the member
523 wxDisplayInfo
& dpyInfo
= (*gs_displays
)[n
];
525 LPDIRECTDRAW2
& pDD2
= dpyInfo
.m_pDD2
;
528 if ( !gs_DirectDrawCreate
)
535 HRESULT hr
= (*gs_DirectDrawCreate
)(&dpyInfo
.m_guid
, &pDD
, NULL
);
537 if ( FAILED(hr
) || !pDD
)
540 wxLogApiError(_T("DirectDrawCreate"), hr
);
542 else // got IDirectDraw, we want IDirectDraw2
544 hr
= pDD
->QueryInterface(wxIID_IDirectDraw2
, (void **)&pDD2
);
545 if ( FAILED(hr
) || !pDD2
)
547 wxLogApiError(_T("IDirectDraw::QueryInterface(IDD2)"), hr
);
553 //else: DirectDraw object corresponding to our display already exists
555 // increment its ref count to account for Release() in dtor
557 // NB: pDD2 will be only really Release()d when gs_displays is
558 // destroyed which is ok as we don't want to recreate DD objects
565 wxDisplay::~wxDisplay()
568 if ( !OsSupportsMultipleMonitors() ) return;
570 wxDisplayInfo
& dpyInfo
= (*gs_displays
)[m_index
];
572 LPDIRECTDRAW2
& pDD2
= dpyInfo
.m_pDD2
;
580 // ----------------------------------------------------------------------------
581 // wxDisplay simple accessors
582 // ----------------------------------------------------------------------------
584 bool wxDisplay::IsOk() const
587 return m_index
< GetCount() &&
588 (!gs_useDirectX
|| (*gs_displays
)[m_index
].m_pDD2
);
590 return m_index
< GetCount();
594 wxRect
wxDisplay::GetGeometry() const
596 if ( !OsSupportsMultipleMonitors() )
598 wxSize size
= wxGetDisplaySize();
599 return wxRect(0, 0, size
.GetWidth(), size
.GetHeight());
602 wxDisplayInfo
& dpyInfo
= (*gs_displays
)[m_index
];
603 wxRect
& rect
= dpyInfo
.m_rect
;
607 wxZeroMemory(monInfo
);
608 monInfo
.cbSize
= sizeof(monInfo
);
610 if ( !gs_GetMonitorInfo(dpyInfo
.m_hmon
, &monInfo
) )
612 wxLogLastError(_T("GetMonitorInfo"));
616 wxCopyRECTToRect(monInfo
.rcMonitor
, rect
);
623 wxString
wxDisplay::GetName() const
625 if ( !OsSupportsMultipleMonitors() ) return wxT("");
627 wxDisplayInfo
& dpyInfo
= (*gs_displays
)[m_index
];
628 if ( dpyInfo
.m_devName
.empty() )
630 MONITORINFOEX monInfo
;
631 wxZeroMemory(monInfo
);
632 monInfo
.cbSize
= sizeof(monInfo
);
634 // NB: Cast from MONITORINFOEX* to MONITORINFO* is done because
635 // Mingw headers - unlike the ones from Microsoft's Platform SDK -
636 // don't derive the former from the latter in C++ mode and so
637 // the pointer's type is not converted implicitly.
638 if ( !gs_GetMonitorInfo(dpyInfo
.m_hmon
, (LPMONITORINFO
)&monInfo
) )
640 wxLogLastError(_T("GetMonitorInfo"));
644 dpyInfo
.m_devName
= monInfo
.szDevice
;
648 return dpyInfo
.m_devName
;
651 // ----------------------------------------------------------------------------
652 // determine if this is the primary display
653 // ----------------------------------------------------------------------------
655 bool wxDisplay::IsPrimary() const
657 if ( !OsSupportsMultipleMonitors() ) return true;
659 wxDisplayInfo
& dpyInfo
= (*gs_displays
)[m_index
];
661 MONITORINFOEX monInfo
;
662 wxZeroMemory(monInfo
);
663 monInfo
.cbSize
= sizeof(monInfo
);
665 // NB: Cast from MONITORINFOEX* to MONITORINFO* is done because
666 // Mingw headers - unlike the ones from Microsoft's Platform SDK -
667 // don't derive the former from the latter in C++ mode and so
668 // the pointer's type is not converted implicitly.
669 if ( !gs_GetMonitorInfo(dpyInfo
.m_hmon
, (LPMONITORINFO
)&monInfo
) )
671 wxLogLastError(_T("GetMonitorInfo"));
674 return (monInfo
.dwFlags
& MONITORINFOF_PRIMARY
) == MONITORINFOF_PRIMARY
;
677 // ----------------------------------------------------------------------------
678 // video modes enumeration
679 // ----------------------------------------------------------------------------
683 wxDisplay::DoGetModesDirectX(const wxVideoMode
& WXUNUSED(modeMatch
)) const
685 wxArrayVideoModes modes
;
687 IDirectDraw2
*pDD
= (*gs_displays
)[m_index
].m_pDD2
;
691 HRESULT hr
= pDD
->EnumDisplayModes
694 NULL
, // all modes (TODO: use modeMatch!)
695 &modes
, // callback parameter
696 wxDDEnumModesCallback
701 wxLogApiError(_T("IDirectDraw::EnumDisplayModes"), hr
);
710 wxDisplay::DoGetModesWindows(const wxVideoMode
& modeMatch
) const
712 wxArrayVideoModes modes
;
714 // The first parameter of EnumDisplaySettings() must be NULL under Win95
715 // according to MSDN. The version of GetName() we implement for Win95
716 // returns an empty string.
717 const wxString name
= GetName();
718 const wxChar
* const deviceName
= name
.empty() ? NULL
: name
.c_str();
721 dm
.dmSize
= sizeof(dm
);
722 dm
.dmDriverExtra
= 0;
723 for ( int iModeNum
= 0;
724 ::EnumDisplaySettings(deviceName
, iModeNum
, &dm
);
727 const wxVideoMode mode
= ConvertToVideoMode(dm
);
728 if ( mode
.Matches(modeMatch
) )
737 wxArrayVideoModes
wxDisplay::GetModes(const wxVideoMode
& modeMatch
) const
740 return gs_useDirectX
? DoGetModesDirectX(modeMatch
)
741 : DoGetModesWindows(modeMatch
);
743 return DoGetModesWindows(modeMatch
);
747 wxVideoMode
wxDisplay::GetCurrentMode() const
751 // The first parameter of EnumDisplaySettings() must be NULL under Win95
752 // according to MSDN. The version of GetName() we implement for Win95
753 // returns an empty string.
754 const wxString name
= GetName();
755 const wxChar
* const deviceName
= name
.empty() ? NULL
: name
.c_str();
758 dm
.dmSize
= sizeof(dm
);
759 dm
.dmDriverExtra
= 0;
760 if ( !::EnumDisplaySettings(deviceName
, ENUM_CURRENT_SETTINGS
, &dm
) )
762 wxLogLastError(_T("EnumDisplaySettings(ENUM_CURRENT_SETTINGS)"));
766 mode
= ConvertToVideoMode(dm
);
772 // ----------------------------------------------------------------------------
773 // video mode switching
774 // ----------------------------------------------------------------------------
777 bool wxDisplay::DoChangeModeDirectX(const wxVideoMode
& mode
)
779 IDirectDraw2
*pDD
= (*gs_displays
)[m_index
].m_pDD2
;
783 wxWindow
*winTop
= wxTheApp
->GetTopWindow();
784 wxCHECK_MSG( winTop
, false, _T("top level window required for DirectX") );
786 HRESULT hr
= pDD
->SetCooperativeLevel
789 DDSCL_EXCLUSIVE
| DDSCL_FULLSCREEN
793 wxLogApiError(_T("IDirectDraw::SetCooperativeLevel"), hr
);
798 hr
= pDD
->SetDisplayMode(mode
.w
, mode
.h
, mode
.bpp
, mode
.refresh
, 0);
801 wxLogApiError(_T("IDirectDraw::SetDisplayMode"), hr
);
811 bool wxDisplay::DoChangeModeWindows(const wxVideoMode
& mode
)
813 // prepare ChangeDisplaySettingsEx() parameters
819 if ( mode
== wxDefaultVideoMode
)
821 // reset the video mode to default
825 else // change to the given mode
827 wxCHECK_MSG( mode
.w
&& mode
.h
, false,
828 _T("at least the width and height must be specified") );
831 dm
.dmSize
= sizeof(dm
);
832 dm
.dmDriverExtra
= 0;
833 dm
.dmFields
= DM_PELSWIDTH
| DM_PELSHEIGHT
;
834 dm
.dmPelsWidth
= mode
.w
;
835 dm
.dmPelsHeight
= mode
.h
;
839 dm
.dmFields
|= DM_BITSPERPEL
;
840 dm
.dmBitsPerPel
= mode
.bpp
;
845 dm
.dmFields
|= DM_DISPLAYFREQUENCY
;
846 dm
.dmDisplayFrequency
= mode
.refresh
;
853 #else // !__WXWINCE__
854 flags
= CDS_FULLSCREEN
;
855 #endif // __WXWINCE__/!__WXWINCE__
859 // get pointer to the function dynamically
861 // we're only called from the main thread, so it's ok to use static
863 static ChangeDisplaySettingsEx_t pfnChangeDisplaySettingsEx
= NULL
;
864 if ( !pfnChangeDisplaySettingsEx
)
866 wxDynamicLibrary
dllUser32(_T("user32.dll"));
867 if ( dllUser32
.IsLoaded() )
869 pfnChangeDisplaySettingsEx
= (ChangeDisplaySettingsEx_t
)
870 dllUser32
.GetSymbol(WINFUNC(ChangeDisplaySettingsEx
));
872 //else: huh, no user32.dll??
875 if ( !pfnChangeDisplaySettingsEx
)
877 // we must be under Win95 and so there is no multiple monitors
879 pfnChangeDisplaySettingsEx
= ChangeDisplaySettingsExForWin95
;
881 #endif // !__WXWINCE__
884 // do change the mode
885 switch ( pfnChangeDisplaySettingsEx
887 GetName(), // display name
888 pDevMode
, // dev mode or NULL to reset
891 NULL
// pointer to video parameters (not used)
894 case DISP_CHANGE_SUCCESSFUL
:
897 // If we have a top-level, full-screen frame, emulate
898 // the DirectX behavior and resize it. This makes this
899 // API quite a bit easier to use.
900 wxWindow
*winTop
= wxTheApp
->GetTopWindow();
901 wxFrame
*frameTop
= wxDynamicCast(winTop
, wxFrame
);
902 if (frameTop
&& frameTop
->IsFullScreen())
904 wxVideoMode current
= GetCurrentMode();
905 frameTop
->SetClientSize(current
.w
, current
.h
);
910 case DISP_CHANGE_BADMODE
:
911 // don't complain about this, this is the only "expected" error
915 wxFAIL_MSG( _T("unexpected ChangeDisplaySettingsEx() return value") );
921 bool wxDisplay::ChangeMode(const wxVideoMode
& mode
)
924 return gs_useDirectX
? DoChangeModeDirectX(mode
)
925 : DoChangeModeWindows(mode
);
927 return DoChangeModeWindows(mode
);
931 #endif // wxUSE_DISPLAY