1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/msw/display.cpp
3 // Purpose: MSW Implementation of wxDisplay class
4 // Author: Royce Mitchell III, Vadim Zeitlin
5 // Modified by: Ryan Norton (IsPrimary override)
8 // Copyright: (c) wxWidgets team
9 // Copyright: (c) 2002-2006 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"
31 #include "wx/msw/missing.h"
32 #include "wx/dynarray.h"
37 #include "wx/dynload.h"
38 #include "wx/sysopt.h"
40 #include "wx/display.h"
41 #include "wx/display_impl.h"
43 // define this to use DirectDraw for display mode switching: this is disabled
44 // by default because ddraw.h is now always available and also it's not really
45 // clear what are the benefits of using DirectDraw compared to the standard API
47 #if !defined(wxUSE_DIRECTDRAW)
48 #define wxUSE_DIRECTDRAW 0
52 // Older versions of windef.h don't define HMONITOR. Unfortunately, we
53 // can't directly test whether HMONITOR is defined or not in windef.h as
54 // it's not a macro but a typedef, so we test for an unrelated symbol which
55 // is only defined in winuser.h if WINVER >= 0x0500
56 #if !defined(HMONITOR_DECLARED) && !defined(MNS_NOCHECK)
57 DECLARE_HANDLE(HMONITOR
);
58 typedef BOOL(CALLBACK
* MONITORENUMPROC
)(HMONITOR
, HDC
, LPRECT
, LPARAM
);
59 typedef struct tagMONITORINFO
65 } MONITORINFO
, *LPMONITORINFO
;
66 typedef struct tagMONITORINFOEX
: public tagMONITORINFO
68 TCHAR szDevice
[CCHDEVICENAME
];
69 } MONITORINFOEX
, *LPMONITORINFOEX
;
70 #define MONITOR_DEFAULTTONULL 0x00000000
71 #define MONITOR_DEFAULTTOPRIMARY 0x00000001
72 #define MONITOR_DEFAULTTONEAREST 0x00000002
73 #define MONITORINFOF_PRIMARY 0x00000001
74 #define HMONITOR_DECLARED
76 #endif // !__WXWINCE__
81 // we don't want to link with ddraw.lib which contains the real
82 // IID_IDirectDraw2 definition
83 const GUID wxIID_IDirectDraw2
=
84 { 0xB3A6F3E0, 0x2B43, 0x11CF, { 0xA2,0xDE,0x00,0xAA,0x00,0xB9,0x33,0x56 } };
85 #endif // wxUSE_DIRECTDRAW
87 // ----------------------------------------------------------------------------
88 // typedefs for dynamically loaded Windows functions
89 // ----------------------------------------------------------------------------
91 typedef LONG (WINAPI
*ChangeDisplaySettingsEx_t
)(LPCTSTR lpszDeviceName
,
98 typedef BOOL (PASCAL
*DDEnumExCallback_t
)(GUID
*pGuid
,
99 LPTSTR driverDescription
,
104 typedef HRESULT (WINAPI
*DirectDrawEnumerateEx_t
)(DDEnumExCallback_t lpCallback
,
108 typedef HRESULT (WINAPI
*DirectDrawCreate_t
)(GUID
*lpGUID
,
109 LPDIRECTDRAW
*lplpDD
,
110 IUnknown
*pUnkOuter
);
111 #endif // wxUSE_DIRECTDRAW
113 typedef BOOL (WINAPI
*EnumDisplayMonitors_t
)(HDC
,LPCRECT
,MONITORENUMPROC
,LPARAM
);
114 typedef HMONITOR (WINAPI
*MonitorFromPoint_t
)(POINT
,DWORD
);
115 typedef HMONITOR (WINAPI
*MonitorFromWindow_t
)(HWND
,DWORD
);
116 typedef BOOL (WINAPI
*GetMonitorInfo_t
)(HMONITOR
,LPMONITORINFO
);
119 // emulation of ChangeDisplaySettingsEx() for Win95
120 LONG WINAPI
ChangeDisplaySettingsExForWin95(LPCTSTR
WXUNUSED(lpszDeviceName
),
124 LPVOID
WXUNUSED(lParam
))
126 return ::ChangeDisplaySettings(lpDevMode
, dwFlags
);
128 #endif // !__WXWINCE__
130 // ----------------------------------------------------------------------------
131 // display information classes
132 // ----------------------------------------------------------------------------
136 wxDisplayInfo(HMONITOR hmon
= NULL
)
142 virtual ~wxDisplayInfo() { }
145 // use GetMonitorInfo() to fill in all of our fields if needed (i.e. if it
146 // hadn't been done before)
150 // handle of this monitor used by MonitorXXX() functions, never NULL
153 // the entire area of this monitor in virtual screen coordinates
156 // the work or client area, i.e. the area available for the normal windows
159 // the display device name for this monitor, empty initially and retrieved
160 // on demand by DoGetName()
163 // the flags of this monitor, also used as initialization marker: if this
164 // is -1, GetMonitorInfo() hadn't been called yet
168 WX_DEFINE_ARRAY_PTR(wxDisplayInfo
*, wxDisplayInfoArray
);
170 // ----------------------------------------------------------------------------
171 // common base class for all Win32 wxDisplayImpl versions
172 // ----------------------------------------------------------------------------
174 class wxDisplayImplWin32Base
: public wxDisplayImpl
177 wxDisplayImplWin32Base(size_t n
, wxDisplayInfo
& info
)
183 virtual wxRect
GetGeometry() const;
184 virtual wxRect
GetClientArea() const;
185 virtual wxString
GetName() const;
186 virtual bool IsPrimary() const;
188 virtual wxVideoMode
GetCurrentMode() const;
191 // convert a DEVMODE to our wxVideoMode
192 static wxVideoMode
ConvertToVideoMode(const DEVMODE
& dm
)
194 // note that dmDisplayFrequency may be 0 or 1 meaning "standard one"
195 // and although 0 is ok for us we don't want to return modes with 1hz
197 return wxVideoMode(dm
.dmPelsWidth
,
200 dm
.dmDisplayFrequency
> 1 ? dm
.dmDisplayFrequency
: 0);
203 wxDisplayInfo
& m_info
;
206 // ----------------------------------------------------------------------------
207 // common base class for all Win32 wxDisplayFactory versions
208 // ----------------------------------------------------------------------------
210 // functions dynamically bound by wxDisplayFactoryWin32Base::Initialize()
211 static MonitorFromPoint_t gs_MonitorFromPoint
= NULL
;
212 static MonitorFromWindow_t gs_MonitorFromWindow
= NULL
;
213 static GetMonitorInfo_t gs_GetMonitorInfo
= NULL
;
215 class wxDisplayFactoryWin32Base
: public wxDisplayFactory
218 virtual ~wxDisplayFactoryWin32Base();
220 bool IsOk() const { return !m_displays
.empty(); }
222 virtual size_t GetCount() { return m_displays
.size(); }
223 virtual int GetFromPoint(const wxPoint
& pt
);
224 virtual int GetFromWindow(wxWindow
*window
);
227 // ctor checks if the current system supports multimon API and dynamically
228 // bind the functions we need if this is the case and sets
229 // ms_supportsMultimon if they're available
230 wxDisplayFactoryWin32Base();
232 // delete all m_displays elements: can be called from the derived class
233 // dtor if it is important to do this before destroying it (as in
234 // wxDisplayFactoryDirectDraw case), otherwise will be done by our dtor
237 // find the monitor corresponding to the given handle, return wxNOT_FOUND
239 int FindDisplayFromHMONITOR(HMONITOR hmon
) const;
242 // flag indicating whether gs_MonitorXXX functions are available
243 static int ms_supportsMultimon
;
245 // the array containing information about all available displays, should be
246 // filled by the derived class ctors
247 wxDisplayInfoArray m_displays
;
250 DECLARE_NO_COPY_CLASS(wxDisplayFactoryWin32Base
)
253 // ----------------------------------------------------------------------------
254 // wxDisplay implementation using Windows multi-monitor support functions
255 // ----------------------------------------------------------------------------
257 class wxDisplayImplMultimon
: public wxDisplayImplWin32Base
260 wxDisplayImplMultimon(size_t n
, wxDisplayInfo
& info
)
261 : wxDisplayImplWin32Base(n
, info
)
265 virtual wxArrayVideoModes
GetModes(const wxVideoMode
& mode
) const;
266 virtual bool ChangeMode(const wxVideoMode
& mode
);
269 DECLARE_NO_COPY_CLASS(wxDisplayImplMultimon
)
272 class wxDisplayFactoryMultimon
: public wxDisplayFactoryWin32Base
275 wxDisplayFactoryMultimon();
277 virtual wxDisplayImpl
*CreateDisplay(size_t n
);
280 // EnumDisplayMonitors() callback
281 static BOOL CALLBACK
MultimonEnumProc(HMONITOR hMonitor
,
287 // add a monitor description to m_displays array
288 void AddDisplay(HMONITOR hMonitor
, LPRECT lprcMonitor
);
291 // ----------------------------------------------------------------------------
292 // wxDisplay implementation using DirectDraw
293 // ----------------------------------------------------------------------------
297 struct wxDisplayInfoDirectDraw
: wxDisplayInfo
299 wxDisplayInfoDirectDraw(const GUID
& guid
, HMONITOR hmon
, LPTSTR name
)
300 : wxDisplayInfo(hmon
),
307 virtual ~wxDisplayInfoDirectDraw()
314 // IDirectDraw object used to control this display, may be NULL
315 IDirectDraw2
*m_pDD2
;
317 // DirectDraw GUID for this display, only valid when using DirectDraw
321 DECLARE_NO_COPY_CLASS(wxDisplayInfoDirectDraw
)
324 class wxDisplayImplDirectDraw
: public wxDisplayImplWin32Base
327 wxDisplayImplDirectDraw(size_t n
, wxDisplayInfo
& info
, IDirectDraw2
*pDD2
)
328 : wxDisplayImplWin32Base(n
, info
),
334 virtual ~wxDisplayImplDirectDraw()
339 virtual wxArrayVideoModes
GetModes(const wxVideoMode
& mode
) const;
340 virtual bool ChangeMode(const wxVideoMode
& mode
);
343 IDirectDraw2
*m_pDD2
;
345 DECLARE_NO_COPY_CLASS(wxDisplayImplDirectDraw
)
348 class wxDisplayFactoryDirectDraw
: public wxDisplayFactoryWin32Base
351 wxDisplayFactoryDirectDraw();
352 virtual ~wxDisplayFactoryDirectDraw();
354 virtual wxDisplayImpl
*CreateDisplay(size_t n
);
357 // callback used with DirectDrawEnumerateEx()
358 static BOOL WINAPI
DDEnumExCallback(GUID
*pGuid
,
359 LPTSTR driverDescription
,
364 // add a monitor description to m_displays array
365 void AddDisplay(const GUID
& guid
, HMONITOR hmon
, LPTSTR name
);
369 wxDynamicLibrary m_dllDDraw
;
371 // dynamically resolved DirectDrawCreate()
372 DirectDrawCreate_t m_pfnDirectDrawCreate
;
374 DECLARE_NO_COPY_CLASS(wxDisplayFactoryDirectDraw
)
377 #endif // wxUSE_DIRECTDRAW
380 // ============================================================================
381 // common classes implementation
382 // ============================================================================
384 // ----------------------------------------------------------------------------
386 // ----------------------------------------------------------------------------
388 /* static */ wxDisplayFactory
*wxDisplay::CreateFactory()
390 // we have 2 implementations for modern Windows: one using standard Win32
391 // and another using DirectDraw, the choice between them is done using a
395 if ( wxSystemOptions::GetOptionInt(_T("msw.display.directdraw")) )
397 wxDisplayFactoryDirectDraw
*factoryDD
= new wxDisplayFactoryDirectDraw
;
398 if ( factoryDD
->IsOk() )
403 #endif // wxUSE_DIRECTDRAW
405 wxDisplayFactoryMultimon
*factoryMM
= new wxDisplayFactoryMultimon
;
406 if ( factoryMM
->IsOk() )
412 // finally fall back to a stub implementation if all else failed (Win95?)
413 return new wxDisplayFactorySingle
;
416 // ----------------------------------------------------------------------------
418 // ----------------------------------------------------------------------------
420 void wxDisplayInfo::Initialize()
422 if ( m_flags
== (DWORD
)-1 )
424 WinStruct
<MONITORINFOEX
> monInfo
;
425 if ( !gs_GetMonitorInfo(m_hmon
, (LPMONITORINFO
)&monInfo
) )
427 wxLogLastError(_T("GetMonitorInfo"));
432 wxCopyRECTToRect(monInfo
.rcMonitor
, m_rect
);
433 wxCopyRECTToRect(monInfo
.rcWork
, m_rectClient
);
434 m_devName
= monInfo
.szDevice
;
435 m_flags
= monInfo
.dwFlags
;
439 // ----------------------------------------------------------------------------
440 // wxDisplayImplWin32Base
441 // ----------------------------------------------------------------------------
443 wxRect
wxDisplayImplWin32Base::GetGeometry() const
445 if ( m_info
.m_rect
.IsEmpty() )
448 return m_info
.m_rect
;
451 wxRect
wxDisplayImplWin32Base::GetClientArea() const
453 if ( m_info
.m_rectClient
.IsEmpty() )
456 return m_info
.m_rectClient
;
459 wxString
wxDisplayImplWin32Base::GetName() const
461 if ( m_info
.m_devName
.empty() )
464 return m_info
.m_devName
;
467 bool wxDisplayImplWin32Base::IsPrimary() const
469 if ( m_info
.m_flags
== (DWORD
)-1 )
472 return (m_info
.m_flags
& MONITORINFOF_PRIMARY
) != 0;
475 wxVideoMode
wxDisplayImplWin32Base::GetCurrentMode() const
479 // The first parameter of EnumDisplaySettings() must be NULL under Win95
480 // according to MSDN. The version of GetName() we implement for Win95
481 // returns an empty string.
482 const wxString name
= GetName();
483 const wxChar
* const deviceName
= name
.empty() ? NULL
: name
.c_str();
486 dm
.dmSize
= sizeof(dm
);
487 dm
.dmDriverExtra
= 0;
488 if ( !::EnumDisplaySettings(deviceName
, ENUM_CURRENT_SETTINGS
, &dm
) )
490 wxLogLastError(_T("EnumDisplaySettings(ENUM_CURRENT_SETTINGS)"));
494 mode
= ConvertToVideoMode(dm
);
500 // ----------------------------------------------------------------------------
501 // wxDisplayFactoryWin32Base
502 // ----------------------------------------------------------------------------
504 int wxDisplayFactoryWin32Base::ms_supportsMultimon
= -1;
506 wxDisplayFactoryWin32Base::wxDisplayFactoryWin32Base()
508 if ( ms_supportsMultimon
== -1 )
510 ms_supportsMultimon
= 0;
512 wxDynamicLibrary
dllUser32(_T("user32.dll"));
516 gs_MonitorFromPoint
= (MonitorFromPoint_t
)
517 dllUser32
.GetSymbol(wxT("MonitorFromPoint"));
518 if ( !gs_MonitorFromPoint
)
521 gs_MonitorFromWindow
= (MonitorFromWindow_t
)
522 dllUser32
.GetSymbol(wxT("MonitorFromWindow"));
523 if ( !gs_MonitorFromWindow
)
526 gs_GetMonitorInfo
= (GetMonitorInfo_t
)
527 dllUser32
.GetSymbolAorW(wxT("GetMonitorInfo"));
528 if ( !gs_GetMonitorInfo
)
531 ms_supportsMultimon
= 1;
533 // we can safely let dllUser32 go out of scope, the DLL itself will
534 // still remain loaded as all Win32 programs use it
538 void wxDisplayFactoryWin32Base::Clear()
540 WX_CLEAR_ARRAY(m_displays
);
543 wxDisplayFactoryWin32Base::~wxDisplayFactoryWin32Base()
548 // helper for GetFromPoint() and GetFromWindow()
549 int wxDisplayFactoryWin32Base::FindDisplayFromHMONITOR(HMONITOR hmon
) const
553 const size_t count
= m_displays
.size();
554 for ( size_t n
= 0; n
< count
; n
++ )
556 if ( hmon
== m_displays
[n
]->m_hmon
)
564 int wxDisplayFactoryWin32Base::GetFromPoint(const wxPoint
& pt
)
570 return FindDisplayFromHMONITOR(gs_MonitorFromPoint(pt2
,
571 MONITOR_DEFAULTTONULL
));
574 int wxDisplayFactoryWin32Base::GetFromWindow(wxWindow
*window
)
576 return FindDisplayFromHMONITOR(gs_MonitorFromWindow(GetHwndOf(window
),
577 MONITOR_DEFAULTTONULL
));
580 // ============================================================================
581 // wxDisplay implementation using Win32 multimon API
582 // ============================================================================
584 // ----------------------------------------------------------------------------
585 // wxDisplayFactoryMultimon initialization
586 // ----------------------------------------------------------------------------
588 wxDisplayFactoryMultimon::wxDisplayFactoryMultimon()
590 if ( !ms_supportsMultimon
)
593 // look up EnumDisplayMonitors() which we don't need with DirectDraw
595 EnumDisplayMonitors_t pfnEnumDisplayMonitors
;
599 wxDynamicLibrary
dllUser32(_T("user32.dll"));
600 pfnEnumDisplayMonitors
= (EnumDisplayMonitors_t
)
601 dllUser32
.GetSymbol(wxT("EnumDisplayMonitors"));
602 if ( !pfnEnumDisplayMonitors
)
606 // enumerate all displays
607 if ( !pfnEnumDisplayMonitors(NULL
, NULL
, MultimonEnumProc
, (LPARAM
)this) )
609 wxLogLastError(wxT("EnumDisplayMonitors"));
615 wxDisplayFactoryMultimon::MultimonEnumProc(
616 HMONITOR hMonitor
, // handle to display monitor
617 HDC
WXUNUSED(hdcMonitor
), // handle to monitor-appropriate device context
618 LPRECT lprcMonitor
, // pointer to monitor intersection rectangle
619 LPARAM dwData
// data passed from EnumDisplayMonitors (this)
622 wxDisplayFactoryMultimon
*const self
= (wxDisplayFactoryMultimon
*)dwData
;
623 self
->AddDisplay(hMonitor
, lprcMonitor
);
625 // continue the enumeration
629 // ----------------------------------------------------------------------------
630 // wxDisplayFactoryMultimon helper functions
631 // ----------------------------------------------------------------------------
633 void wxDisplayFactoryMultimon::AddDisplay(HMONITOR hMonitor
, LPRECT lprcMonitor
)
635 wxDisplayInfo
*info
= new wxDisplayInfo(hMonitor
);
637 // we also store the display geometry
638 info
->m_rect
= wxRect(lprcMonitor
->left
, lprcMonitor
->top
,
639 lprcMonitor
->right
- lprcMonitor
->left
,
640 lprcMonitor
->bottom
- lprcMonitor
->top
);
642 // now add this monitor to the array
643 m_displays
.Add(info
);
646 // ----------------------------------------------------------------------------
647 // wxDisplayFactoryMultimon inherited pure virtuals implementation
648 // ----------------------------------------------------------------------------
650 wxDisplayImpl
*wxDisplayFactoryMultimon::CreateDisplay(size_t n
)
652 wxCHECK_MSG( n
< m_displays
.size(), NULL
, _T("invalid display index") );
654 return new wxDisplayImplMultimon(n
, *(m_displays
[n
]));
657 // ----------------------------------------------------------------------------
658 // wxDisplayImplMultimon implementation
659 // ----------------------------------------------------------------------------
662 wxDisplayImplMultimon::GetModes(const wxVideoMode
& modeMatch
) const
664 wxArrayVideoModes modes
;
666 // The first parameter of EnumDisplaySettings() must be NULL under Win95
667 // according to MSDN. The version of GetName() we implement for Win95
668 // returns an empty string.
669 const wxString name
= GetName();
670 const wxChar
* const deviceName
= name
.empty() ? NULL
: name
.c_str();
673 dm
.dmSize
= sizeof(dm
);
674 dm
.dmDriverExtra
= 0;
675 for ( int iModeNum
= 0;
676 ::EnumDisplaySettings(deviceName
, iModeNum
, &dm
);
679 const wxVideoMode mode
= ConvertToVideoMode(dm
);
680 if ( mode
.Matches(modeMatch
) )
689 bool wxDisplayImplMultimon::ChangeMode(const wxVideoMode
& mode
)
691 // prepare ChangeDisplaySettingsEx() parameters
697 if ( mode
== wxDefaultVideoMode
)
699 // reset the video mode to default
703 else // change to the given mode
705 wxCHECK_MSG( mode
.w
&& mode
.h
, false,
706 _T("at least the width and height must be specified") );
709 dm
.dmSize
= sizeof(dm
);
710 dm
.dmDriverExtra
= 0;
711 dm
.dmFields
= DM_PELSWIDTH
| DM_PELSHEIGHT
;
712 dm
.dmPelsWidth
= mode
.w
;
713 dm
.dmPelsHeight
= mode
.h
;
717 dm
.dmFields
|= DM_BITSPERPEL
;
718 dm
.dmBitsPerPel
= mode
.bpp
;
723 dm
.dmFields
|= DM_DISPLAYFREQUENCY
;
724 dm
.dmDisplayFrequency
= mode
.refresh
;
731 #else // !__WXWINCE__
732 flags
= CDS_FULLSCREEN
;
733 #endif // __WXWINCE__/!__WXWINCE__
737 // get pointer to the function dynamically
739 // we're only called from the main thread, so it's ok to use static
741 static ChangeDisplaySettingsEx_t pfnChangeDisplaySettingsEx
= NULL
;
742 if ( !pfnChangeDisplaySettingsEx
)
744 wxDynamicLibrary
dllUser32(_T("user32.dll"));
745 if ( dllUser32
.IsLoaded() )
747 pfnChangeDisplaySettingsEx
= (ChangeDisplaySettingsEx_t
)
748 dllUser32
.GetSymbolAorW(_T("ChangeDisplaySettingsEx"));
750 //else: huh, no user32.dll??
753 if ( !pfnChangeDisplaySettingsEx
)
755 // we must be under Win95 and so there is no multiple monitors
757 pfnChangeDisplaySettingsEx
= ChangeDisplaySettingsExForWin95
;
759 #endif // !__WXWINCE__
762 // do change the mode
763 switch ( pfnChangeDisplaySettingsEx
765 GetName(), // display name
766 pDevMode
, // dev mode or NULL to reset
769 NULL
// pointer to video parameters (not used)
772 case DISP_CHANGE_SUCCESSFUL
:
775 // If we have a top-level, full-screen frame, emulate
776 // the DirectX behavior and resize it. This makes this
777 // API quite a bit easier to use.
778 wxWindow
*winTop
= wxTheApp
->GetTopWindow();
779 wxFrame
*frameTop
= wxDynamicCast(winTop
, wxFrame
);
780 if (frameTop
&& frameTop
->IsFullScreen())
782 wxVideoMode current
= GetCurrentMode();
783 frameTop
->SetClientSize(current
.w
, current
.h
);
788 case DISP_CHANGE_BADMODE
:
789 // don't complain about this, this is the only "expected" error
793 wxFAIL_MSG( _T("unexpected ChangeDisplaySettingsEx() return value") );
800 // ============================================================================
801 // DirectDraw-based wxDisplay implementation
802 // ============================================================================
806 // ----------------------------------------------------------------------------
807 // wxDisplayFactoryDirectDraw initialization
808 // ----------------------------------------------------------------------------
810 wxDisplayFactoryDirectDraw::wxDisplayFactoryDirectDraw()
812 if ( !ms_supportsMultimon
)
816 // suppress the errors if ddraw.dll is not found, we're prepared to handle
821 m_dllDDraw
.Load(_T("ddraw.dll"));
823 if ( !m_dllDDraw
.IsLoaded() )
826 DirectDrawEnumerateEx_t pDDEnumEx
= (DirectDrawEnumerateEx_t
)
827 m_dllDDraw
.GetSymbolAorW(_T("DirectDrawEnumerateEx"));
831 // we can't continue without DirectDrawCreate() later, so resolve it right
832 // now and fail the initialization if it's not available
833 m_pfnDirectDrawCreate
= (DirectDrawCreate_t
)
834 m_dllDDraw
.GetSymbol(_T("DirectDrawCreate"));
835 if ( !m_pfnDirectDrawCreate
)
838 if ( (*pDDEnumEx
)(DDEnumExCallback
,
840 DDENUM_ATTACHEDSECONDARYDEVICES
) != DD_OK
)
842 wxLogLastError(_T("DirectDrawEnumerateEx"));
846 wxDisplayFactoryDirectDraw::~wxDisplayFactoryDirectDraw()
848 // we must clear m_displays now, before m_dllDDraw is unloaded as otherwise
849 // calling m_pDD2->Release() later would crash
853 // ----------------------------------------------------------------------------
854 // callbacks for monitor/modes enumeration stuff
855 // ----------------------------------------------------------------------------
858 wxDisplayFactoryDirectDraw::DDEnumExCallback(GUID
*pGuid
,
859 LPTSTR
WXUNUSED(driverDescription
),
866 wxDisplayFactoryDirectDraw
* self
=
867 wx_static_cast(wxDisplayFactoryDirectDraw
*, lpContext
);
868 self
->AddDisplay(*pGuid
, hmon
, driverName
);
870 //else: we're called for the primary monitor, skip it
872 // continue the enumeration
876 // ----------------------------------------------------------------------------
877 // wxDisplayFactoryDirectDraw helpers
878 // ----------------------------------------------------------------------------
880 void wxDisplayFactoryDirectDraw::AddDisplay(const GUID
& guid
,
884 m_displays
.Add(new wxDisplayInfoDirectDraw(guid
, hmon
, name
));
887 // ----------------------------------------------------------------------------
888 // wxDisplayFactoryDirectDraw inherited pure virtuals implementation
889 // ----------------------------------------------------------------------------
891 wxDisplayImpl
*wxDisplayFactoryDirectDraw::CreateDisplay(size_t n
)
893 wxCHECK_MSG( n
< m_displays
.size(), NULL
, _T("invalid display index") );
895 wxDisplayInfoDirectDraw
*
896 info
= wx_static_cast(wxDisplayInfoDirectDraw
*, m_displays
[n
]);
901 GUID
guid(info
->m_guid
);
902 HRESULT hr
= (*m_pfnDirectDrawCreate
)(&guid
, &pDD
, NULL
);
904 if ( FAILED(hr
) || !pDD
)
907 wxLogApiError(_T("DirectDrawCreate"), hr
);
911 // we got IDirectDraw, but we need IDirectDraw2
912 hr
= pDD
->QueryInterface(wxIID_IDirectDraw2
, (void **)&info
->m_pDD2
);
915 if ( FAILED(hr
) || !info
->m_pDD2
)
917 wxLogApiError(_T("IDirectDraw::QueryInterface(IDD2)"), hr
);
921 // NB: m_pDD2 will now be only destroyed when m_displays is destroyed
922 // which is ok as we don't want to recreate DD objects all the time
924 //else: DirectDraw object corresponding to our display already exists
926 return new wxDisplayImplDirectDraw(n
, *info
, info
->m_pDD2
);
929 // ============================================================================
930 // wxDisplayImplDirectDraw
931 // ============================================================================
933 // ----------------------------------------------------------------------------
934 // video modes enumeration
935 // ----------------------------------------------------------------------------
937 // tiny helper class used to pass information from GetModes() to
938 // wxDDEnumModesCallback
939 class wxDDVideoModesAdder
942 // our Add() method will add modes matching modeMatch to modes array
943 wxDDVideoModesAdder(wxArrayVideoModes
& modes
, const wxVideoMode
& modeMatch
)
945 m_modeMatch(modeMatch
)
949 void Add(const wxVideoMode
& mode
)
951 if ( mode
.Matches(m_modeMatch
) )
956 wxArrayVideoModes
& m_modes
;
957 const wxVideoMode
& m_modeMatch
;
959 DECLARE_NO_COPY_CLASS(wxDDVideoModesAdder
)
962 HRESULT WINAPI
wxDDEnumModesCallback(LPDDSURFACEDESC lpDDSurfaceDesc
,
965 // we need at least the mode size
966 static const DWORD FLAGS_REQUIRED
= DDSD_HEIGHT
| DDSD_WIDTH
;
967 if ( (lpDDSurfaceDesc
->dwFlags
& FLAGS_REQUIRED
) == FLAGS_REQUIRED
)
969 wxDDVideoModesAdder
* const vmodes
=
970 wx_static_cast(wxDDVideoModesAdder
*, lpContext
);
972 vmodes
->Add(wxVideoMode(lpDDSurfaceDesc
->dwWidth
,
973 lpDDSurfaceDesc
->dwHeight
,
974 lpDDSurfaceDesc
->ddpfPixelFormat
.dwRGBBitCount
,
975 lpDDSurfaceDesc
->dwRefreshRate
));
978 // continue the enumeration
983 wxDisplayImplDirectDraw::GetModes(const wxVideoMode
& modeMatch
) const
985 wxArrayVideoModes modes
;
986 wxDDVideoModesAdder
modesAdder(modes
, modeMatch
);
988 HRESULT hr
= m_pDD2
->EnumDisplayModes
992 &modesAdder
, // callback parameter
993 wxDDEnumModesCallback
998 wxLogApiError(_T("IDirectDraw::EnumDisplayModes"), hr
);
1004 // ----------------------------------------------------------------------------
1005 // video mode switching
1006 // ----------------------------------------------------------------------------
1008 bool wxDisplayImplDirectDraw::ChangeMode(const wxVideoMode
& mode
)
1010 wxWindow
*winTop
= wxTheApp
->GetTopWindow();
1011 wxCHECK_MSG( winTop
, false, _T("top level window required for DirectX") );
1013 HRESULT hr
= m_pDD2
->SetCooperativeLevel
1016 DDSCL_EXCLUSIVE
| DDSCL_FULLSCREEN
1020 wxLogApiError(_T("IDirectDraw2::SetCooperativeLevel"), hr
);
1025 hr
= m_pDD2
->SetDisplayMode(mode
.w
, mode
.h
, mode
.bpp
, mode
.refresh
, 0);
1028 wxLogApiError(_T("IDirectDraw2::SetDisplayMode"), hr
);
1036 #endif // wxUSE_DIRECTDRAW
1038 #endif // wxUSE_DISPLAY