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/dynarray.h" 
  36 #include "wx/dynload.h" 
  37 #include "wx/sysopt.h" 
  39 #include "wx/display.h" 
  40 #include "wx/display_impl.h" 
  42 // define this to use DirectDraw for display mode switching: this is disabled 
  43 // by default because ddraw.h is now always available and also it's not really 
  44 // clear what are the benefits of using DirectDraw compared to the standard API 
  46 #if !defined(wxUSE_DIRECTDRAW) 
  47     #define wxUSE_DIRECTDRAW 0 
  51     // Older versions of windef.h don't define HMONITOR.  Unfortunately, we 
  52     // can't directly test whether HMONITOR is defined or not in windef.h as 
  53     // it's not a macro but a typedef, so we test for an unrelated symbol which 
  54     // is only defined in winuser.h if WINVER >= 0x0500 
  55     #if !defined(HMONITOR_DECLARED) && !defined(MNS_NOCHECK) 
  56         DECLARE_HANDLE(HMONITOR
); 
  57         typedef BOOL(CALLBACK 
* MONITORENUMPROC 
)(HMONITOR
, HDC
, LPRECT
, LPARAM
); 
  58         typedef struct tagMONITORINFO
 
  64         } MONITORINFO
, *LPMONITORINFO
; 
  65         typedef struct tagMONITORINFOEX 
: public tagMONITORINFO
 
  67             TCHAR       szDevice
[CCHDEVICENAME
]; 
  68         } MONITORINFOEX
, *LPMONITORINFOEX
; 
  69         #define MONITOR_DEFAULTTONULL       0x00000000 
  70         #define MONITOR_DEFAULTTOPRIMARY    0x00000001 
  71         #define MONITOR_DEFAULTTONEAREST    0x00000002 
  72         #define MONITORINFOF_PRIMARY        0x00000001 
  73         #define HMONITOR_DECLARED 
  75 #endif // !__WXWINCE__ 
  80     // we don't want to link with ddraw.lib which contains the real 
  81     // IID_IDirectDraw2 definition 
  82     const GUID wxIID_IDirectDraw2 
= 
  83      { 0xB3A6F3E0, 0x2B43, 0x11CF, { 0xA2,0xDE,0x00,0xAA,0x00,0xB9,0x33,0x56 } }; 
  84 #endif // wxUSE_DIRECTDRAW 
  86 // ---------------------------------------------------------------------------- 
  87 // typedefs for dynamically loaded Windows functions 
  88 // ---------------------------------------------------------------------------- 
  90 typedef LONG (WINAPI 
*ChangeDisplaySettingsEx_t
)(LPCTSTR lpszDeviceName
, 
  97 typedef BOOL (PASCAL 
*DDEnumExCallback_t
)(GUID 
*pGuid
, 
  98                                           LPTSTR driverDescription
, 
 103 typedef HRESULT (WINAPI 
*DirectDrawEnumerateEx_t
)(DDEnumExCallback_t lpCallback
, 
 107 typedef HRESULT (WINAPI 
*DirectDrawCreate_t
)(GUID 
*lpGUID
, 
 108                                              LPDIRECTDRAW 
*lplpDD
, 
 109                                              IUnknown 
*pUnkOuter
); 
 110 #endif // wxUSE_DIRECTDRAW 
 112 typedef BOOL (WINAPI 
*EnumDisplayMonitors_t
)(HDC
,LPCRECT
,MONITORENUMPROC
,LPARAM
); 
 113 typedef HMONITOR (WINAPI 
*MonitorFromPoint_t
)(POINT
,DWORD
); 
 114 typedef HMONITOR (WINAPI 
*MonitorFromWindow_t
)(HWND
,DWORD
); 
 115 typedef BOOL (WINAPI 
*GetMonitorInfo_t
)(HMONITOR
,LPMONITORINFO
); 
 118 // emulation of ChangeDisplaySettingsEx() for Win95 
 119 LONG WINAPI 
ChangeDisplaySettingsExForWin95(LPCTSTR 
WXUNUSED(lpszDeviceName
), 
 123                                             LPVOID 
WXUNUSED(lParam
)) 
 125     return ::ChangeDisplaySettings(lpDevMode
, dwFlags
); 
 127 #endif // !__WXWINCE__ 
 129 // ---------------------------------------------------------------------------- 
 130 // display information classes 
 131 // ---------------------------------------------------------------------------- 
 135     wxDisplayInfo(HMONITOR hmon 
= NULL
) 
 141     virtual ~wxDisplayInfo() { } 
 144     // use GetMonitorInfo() to fill in all of our fields if needed (i.e. if it 
 145     // hadn't been done before) 
 149     // handle of this monitor used by MonitorXXX() functions, never NULL 
 152     // the entire area of this monitor in virtual screen coordinates 
 155     // the work or client area, i.e. the area available for the normal windows 
 158     // the display device name for this monitor, empty initially and retrieved 
 159     // on demand by DoGetName() 
 162     // the flags of this monitor, also used as initialization marker: if this 
 163     // is -1, GetMonitorInfo() hadn't been called yet 
 167 WX_DEFINE_ARRAY_PTR(wxDisplayInfo 
*, wxDisplayInfoArray
); 
 169 // ---------------------------------------------------------------------------- 
 170 // common base class for all Win32 wxDisplayImpl versions 
 171 // ---------------------------------------------------------------------------- 
 173 class wxDisplayImplWin32Base 
: public wxDisplayImpl
 
 176     wxDisplayImplWin32Base(size_t n
, wxDisplayInfo
& info
) 
 182     virtual wxRect 
GetGeometry() const; 
 183     virtual wxRect 
GetClientArea() const; 
 184     virtual wxString 
GetName() const; 
 185     virtual bool IsPrimary() const; 
 187     virtual wxVideoMode 
GetCurrentMode() const; 
 190     // convert a DEVMODE to our wxVideoMode 
 191     static wxVideoMode 
ConvertToVideoMode(const DEVMODE
& dm
) 
 193         // note that dmDisplayFrequency may be 0 or 1 meaning "standard one" 
 194         // and although 0 is ok for us we don't want to return modes with 1hz 
 196         return wxVideoMode(dm
.dmPelsWidth
, 
 199                            dm
.dmDisplayFrequency 
> 1 ? dm
.dmDisplayFrequency 
: 0); 
 202     wxDisplayInfo
& m_info
; 
 205 // ---------------------------------------------------------------------------- 
 206 // common base class for all Win32 wxDisplayFactory versions 
 207 // ---------------------------------------------------------------------------- 
 209 // functions dynamically bound by wxDisplayFactoryWin32Base::Initialize() 
 210 static MonitorFromPoint_t gs_MonitorFromPoint 
= NULL
; 
 211 static MonitorFromWindow_t gs_MonitorFromWindow 
= NULL
; 
 212 static GetMonitorInfo_t gs_GetMonitorInfo 
= NULL
; 
 214 class wxDisplayFactoryWin32Base 
: public wxDisplayFactory
 
 217     virtual ~wxDisplayFactoryWin32Base(); 
 219     bool IsOk() const { return !m_displays
.empty(); } 
 221     virtual size_t GetCount() { return m_displays
.size(); } 
 222     virtual int GetFromPoint(const wxPoint
& pt
); 
 223     virtual int GetFromWindow(wxWindow 
*window
); 
 226     // ctor checks if the current system supports multimon API and dynamically 
 227     // bind the functions we need if this is the case and sets 
 228     // ms_supportsMultimon if they're available 
 229     wxDisplayFactoryWin32Base(); 
 231     // delete all m_displays elements: can be called from the derived class 
 232     // dtor if it is important to do this before destroying it (as in 
 233     // wxDisplayFactoryDirectDraw case), otherwise will be done by our dtor 
 236     // find the monitor corresponding to the given handle, return wxNOT_FOUND 
 238     int FindDisplayFromHMONITOR(HMONITOR hmon
) const; 
 241     // flag indicating whether gs_MonitorXXX functions are available 
 242     static int ms_supportsMultimon
; 
 244     // the array containing information about all available displays, should be 
 245     // filled by the derived class ctors 
 246     wxDisplayInfoArray m_displays
; 
 249     DECLARE_NO_COPY_CLASS(wxDisplayFactoryWin32Base
) 
 252 // ---------------------------------------------------------------------------- 
 253 // wxDisplay implementation using Windows multi-monitor support functions 
 254 // ---------------------------------------------------------------------------- 
 256 class wxDisplayImplMultimon 
: public wxDisplayImplWin32Base
 
 259     wxDisplayImplMultimon(size_t n
, wxDisplayInfo
& info
) 
 260         : wxDisplayImplWin32Base(n
, info
) 
 264     virtual wxArrayVideoModes 
GetModes(const wxVideoMode
& mode
) const; 
 265     virtual bool ChangeMode(const wxVideoMode
& mode
); 
 268     DECLARE_NO_COPY_CLASS(wxDisplayImplMultimon
) 
 271 class wxDisplayFactoryMultimon 
: public wxDisplayFactoryWin32Base
 
 274     wxDisplayFactoryMultimon(); 
 276     virtual wxDisplayImpl 
*CreateDisplay(size_t n
); 
 279     // EnumDisplayMonitors() callback 
 280     static BOOL CALLBACK 
MultimonEnumProc(HMONITOR hMonitor
, 
 286     // add a monitor description to m_displays array 
 287     void AddDisplay(HMONITOR hMonitor
, LPRECT lprcMonitor
); 
 290 // ---------------------------------------------------------------------------- 
 291 // wxDisplay implementation using DirectDraw 
 292 // ---------------------------------------------------------------------------- 
 296 struct wxDisplayInfoDirectDraw 
: wxDisplayInfo
 
 298     wxDisplayInfoDirectDraw(const GUID
& guid
, HMONITOR hmon
, LPTSTR name
) 
 299         : wxDisplayInfo(hmon
), 
 306     virtual ~wxDisplayInfoDirectDraw() 
 313     // IDirectDraw object used to control this display, may be NULL 
 314     IDirectDraw2 
*m_pDD2
; 
 316     // DirectDraw GUID for this display, only valid when using DirectDraw 
 320     DECLARE_NO_COPY_CLASS(wxDisplayInfoDirectDraw
) 
 323 class wxDisplayImplDirectDraw 
: public wxDisplayImplWin32Base
 
 326     wxDisplayImplDirectDraw(size_t n
, wxDisplayInfo
& info
, IDirectDraw2 
*pDD2
) 
 327         : wxDisplayImplWin32Base(n
, info
), 
 333     virtual ~wxDisplayImplDirectDraw() 
 338     virtual wxArrayVideoModes 
GetModes(const wxVideoMode
& mode
) const; 
 339     virtual bool ChangeMode(const wxVideoMode
& mode
); 
 342     IDirectDraw2 
*m_pDD2
; 
 344     DECLARE_NO_COPY_CLASS(wxDisplayImplDirectDraw
) 
 347 class wxDisplayFactoryDirectDraw 
: public wxDisplayFactoryWin32Base
 
 350     wxDisplayFactoryDirectDraw(); 
 351     virtual ~wxDisplayFactoryDirectDraw(); 
 353     virtual wxDisplayImpl 
*CreateDisplay(size_t n
); 
 356     // callback used with DirectDrawEnumerateEx() 
 357     static BOOL WINAPI 
DDEnumExCallback(GUID 
*pGuid
, 
 358                                         LPTSTR driverDescription
, 
 363     // add a monitor description to m_displays array 
 364     void AddDisplay(const GUID
& guid
, HMONITOR hmon
, LPTSTR name
); 
 368     wxDynamicLibrary m_dllDDraw
; 
 370     // dynamically resolved DirectDrawCreate() 
 371     DirectDrawCreate_t m_pfnDirectDrawCreate
; 
 373     DECLARE_NO_COPY_CLASS(wxDisplayFactoryDirectDraw
) 
 376 #endif // wxUSE_DIRECTDRAW 
 379 // ============================================================================ 
 380 // common classes implementation 
 381 // ============================================================================ 
 383 // ---------------------------------------------------------------------------- 
 385 // ---------------------------------------------------------------------------- 
 387 /* static */ wxDisplayFactory 
*wxDisplay::CreateFactory() 
 389     // we have 2 implementations for modern Windows: one using standard Win32 
 390     // and another using DirectDraw, the choice between them is done using a 
 394     if ( wxSystemOptions::GetOptionInt(_T("msw.display.directdraw")) ) 
 396         wxDisplayFactoryDirectDraw 
*factoryDD 
= new wxDisplayFactoryDirectDraw
; 
 397         if ( factoryDD
->IsOk() ) 
 402 #endif // wxUSE_DIRECTDRAW 
 404     wxDisplayFactoryMultimon 
*factoryMM 
= new wxDisplayFactoryMultimon
; 
 405     if ( factoryMM
->IsOk() ) 
 411     // finally fall back to a stub implementation if all else failed (Win95?) 
 412     return new wxDisplayFactorySingle
; 
 415 // ---------------------------------------------------------------------------- 
 417 // ---------------------------------------------------------------------------- 
 419 void wxDisplayInfo::Initialize() 
 421     if ( m_flags 
== (DWORD
)-1 ) 
 423         WinStruct
<MONITORINFOEX
> monInfo
; 
 424         if ( !gs_GetMonitorInfo(m_hmon
, (LPMONITORINFO
)&monInfo
) ) 
 426             wxLogLastError(_T("GetMonitorInfo")); 
 431         wxCopyRECTToRect(monInfo
.rcMonitor
, m_rect
); 
 432         wxCopyRECTToRect(monInfo
.rcWork
, m_rectClient
); 
 433         m_devName 
= monInfo
.szDevice
; 
 434         m_flags 
= monInfo
.dwFlags
; 
 438 // ---------------------------------------------------------------------------- 
 439 // wxDisplayImplWin32Base 
 440 // ---------------------------------------------------------------------------- 
 442 wxRect 
wxDisplayImplWin32Base::GetGeometry() const 
 444     if ( m_info
.m_rect
.IsEmpty() ) 
 447     return m_info
.m_rect
; 
 450 wxRect 
wxDisplayImplWin32Base::GetClientArea() const 
 452     if ( m_info
.m_rectClient
.IsEmpty() ) 
 455     return m_info
.m_rectClient
; 
 458 wxString 
wxDisplayImplWin32Base::GetName() const 
 460     if ( m_info
.m_devName
.IsEmpty() ) 
 463     return m_info
.m_devName
; 
 466 bool wxDisplayImplWin32Base::IsPrimary() const 
 468     if ( m_info
.m_flags 
== (DWORD
)-1 ) 
 471     return (m_info
.m_flags 
& MONITORINFOF_PRIMARY
) != 0; 
 474 wxVideoMode 
wxDisplayImplWin32Base::GetCurrentMode() const 
 478     // The first parameter of EnumDisplaySettings() must be NULL under Win95 
 479     // according to MSDN.  The version of GetName() we implement for Win95 
 480     // returns an empty string. 
 481     const wxString name 
= GetName(); 
 482     const wxChar 
* const deviceName 
= name
.empty() ? NULL 
: name
.c_str(); 
 485     dm
.dmSize 
= sizeof(dm
); 
 486     dm
.dmDriverExtra 
= 0; 
 487     if ( !::EnumDisplaySettings(deviceName
, ENUM_CURRENT_SETTINGS
, &dm
) ) 
 489         wxLogLastError(_T("EnumDisplaySettings(ENUM_CURRENT_SETTINGS)")); 
 493         mode 
= ConvertToVideoMode(dm
); 
 499 // ---------------------------------------------------------------------------- 
 500 // wxDisplayFactoryWin32Base 
 501 // ---------------------------------------------------------------------------- 
 503 int wxDisplayFactoryWin32Base::ms_supportsMultimon 
= -1; 
 505 wxDisplayFactoryWin32Base::wxDisplayFactoryWin32Base() 
 507     if ( ms_supportsMultimon 
== -1 ) 
 509         ms_supportsMultimon 
= 0; 
 511         wxDynamicLibrary 
dllUser32(_T("user32.dll")); 
 515         gs_MonitorFromPoint 
= (MonitorFromPoint_t
) 
 516             dllUser32
.GetSymbol(wxT("MonitorFromPoint")); 
 517         if ( !gs_MonitorFromPoint 
) 
 520         gs_MonitorFromWindow 
= (MonitorFromWindow_t
) 
 521             dllUser32
.GetSymbol(wxT("MonitorFromWindow")); 
 522         if ( !gs_MonitorFromWindow 
) 
 525         gs_GetMonitorInfo 
= (GetMonitorInfo_t
) 
 526             dllUser32
.GetSymbolAorW(wxT("GetMonitorInfo")); 
 527         if ( !gs_GetMonitorInfo 
) 
 530         ms_supportsMultimon 
= 1; 
 532         // we can safely let dllUser32 go out of scope, the DLL itself will 
 533         // still remain loaded as all Win32 programs use it 
 537 void wxDisplayFactoryWin32Base::Clear() 
 539     WX_CLEAR_ARRAY(m_displays
); 
 542 wxDisplayFactoryWin32Base::~wxDisplayFactoryWin32Base() 
 547 // helper for GetFromPoint() and GetFromWindow() 
 548 int wxDisplayFactoryWin32Base::FindDisplayFromHMONITOR(HMONITOR hmon
) const 
 552         const size_t count 
= m_displays
.size(); 
 553         for ( size_t n 
= 0; n 
< count
; n
++ ) 
 555             if ( hmon 
== m_displays
[n
]->m_hmon 
) 
 563 int wxDisplayFactoryWin32Base::GetFromPoint(const wxPoint
& pt
) 
 569     return FindDisplayFromHMONITOR(gs_MonitorFromPoint(pt2
, 
 570                                                        MONITOR_DEFAULTTONULL
)); 
 573 int wxDisplayFactoryWin32Base::GetFromWindow(wxWindow 
*window
) 
 575     return FindDisplayFromHMONITOR(gs_MonitorFromWindow(GetHwndOf(window
), 
 576                                                         MONITOR_DEFAULTTONULL
)); 
 579 // ============================================================================ 
 580 // wxDisplay implementation using Win32 multimon API 
 581 // ============================================================================ 
 583 // ---------------------------------------------------------------------------- 
 584 // wxDisplayFactoryMultimon initialization 
 585 // ---------------------------------------------------------------------------- 
 587 wxDisplayFactoryMultimon::wxDisplayFactoryMultimon() 
 589     if ( !ms_supportsMultimon 
) 
 592     // look up EnumDisplayMonitors() which we don't need with DirectDraw 
 594     EnumDisplayMonitors_t pfnEnumDisplayMonitors
; 
 598         wxDynamicLibrary 
dllUser32(_T("user32.dll")); 
 599         pfnEnumDisplayMonitors 
= (EnumDisplayMonitors_t
) 
 600             dllUser32
.GetSymbol(wxT("EnumDisplayMonitors")); 
 601         if ( !pfnEnumDisplayMonitors 
) 
 605     // enumerate all displays 
 606     if ( !pfnEnumDisplayMonitors(NULL
, NULL
, MultimonEnumProc
, (LPARAM
)this) ) 
 608         wxLogLastError(wxT("EnumDisplayMonitors")); 
 614 wxDisplayFactoryMultimon::MultimonEnumProc( 
 615   HMONITOR hMonitor
,        // handle to display monitor 
 616   HDC 
WXUNUSED(hdcMonitor
), // handle to monitor-appropriate device context 
 617   LPRECT lprcMonitor
,       // pointer to monitor intersection rectangle 
 618   LPARAM dwData             
// data passed from EnumDisplayMonitors (this) 
 621     wxDisplayFactoryMultimon 
*const self 
= (wxDisplayFactoryMultimon 
*)dwData
; 
 622     self
->AddDisplay(hMonitor
, lprcMonitor
); 
 624     // continue the enumeration 
 628 // ---------------------------------------------------------------------------- 
 629 // wxDisplayFactoryMultimon helper functions 
 630 // ---------------------------------------------------------------------------- 
 632 void wxDisplayFactoryMultimon::AddDisplay(HMONITOR hMonitor
, LPRECT lprcMonitor
) 
 634     wxDisplayInfo 
*info 
= new wxDisplayInfo(hMonitor
); 
 636     // we also store the display geometry 
 637     info
->m_rect 
= wxRect(lprcMonitor
->left
, lprcMonitor
->top
, 
 638                           lprcMonitor
->right 
- lprcMonitor
->left
, 
 639                           lprcMonitor
->bottom 
- lprcMonitor
->top
); 
 641     // now add this monitor to the array 
 642     m_displays
.Add(info
); 
 645 // ---------------------------------------------------------------------------- 
 646 // wxDisplayFactoryMultimon inherited pure virtuals implementation 
 647 // ---------------------------------------------------------------------------- 
 649 wxDisplayImpl 
*wxDisplayFactoryMultimon::CreateDisplay(size_t n
) 
 651     wxCHECK_MSG( n 
< m_displays
.size(), NULL
, _T("invalid display index") ); 
 653     return new wxDisplayImplMultimon(n
, *(m_displays
[n
])); 
 656 // ---------------------------------------------------------------------------- 
 657 // wxDisplayImplMultimon implementation 
 658 // ---------------------------------------------------------------------------- 
 661 wxDisplayImplMultimon::GetModes(const wxVideoMode
& modeMatch
) const 
 663     wxArrayVideoModes modes
; 
 665     // The first parameter of EnumDisplaySettings() must be NULL under Win95 
 666     // according to MSDN.  The version of GetName() we implement for Win95 
 667     // returns an empty string. 
 668     const wxString name 
= GetName(); 
 669     const wxChar 
* const deviceName 
= name
.empty() ? NULL 
: name
.c_str(); 
 672     dm
.dmSize 
= sizeof(dm
); 
 673     dm
.dmDriverExtra 
= 0; 
 674     for ( int iModeNum 
= 0; 
 675           ::EnumDisplaySettings(deviceName
, iModeNum
, &dm
); 
 678         const wxVideoMode mode 
= ConvertToVideoMode(dm
); 
 679         if ( mode
.Matches(modeMatch
) ) 
 688 bool wxDisplayImplMultimon::ChangeMode(const wxVideoMode
& mode
) 
 690     // prepare ChangeDisplaySettingsEx() parameters 
 696     if ( mode 
== wxDefaultVideoMode 
) 
 698         // reset the video mode to default 
 702     else // change to the given mode 
 704         wxCHECK_MSG( mode
.w 
&& mode
.h
, false, 
 705                         _T("at least the width and height must be specified") ); 
 708         dm
.dmSize 
= sizeof(dm
); 
 709         dm
.dmDriverExtra 
= 0; 
 710         dm
.dmFields 
= DM_PELSWIDTH 
| DM_PELSHEIGHT
; 
 711         dm
.dmPelsWidth 
= mode
.w
; 
 712         dm
.dmPelsHeight 
= mode
.h
; 
 716             dm
.dmFields 
|= DM_BITSPERPEL
; 
 717             dm
.dmBitsPerPel 
= mode
.bpp
; 
 722             dm
.dmFields 
|= DM_DISPLAYFREQUENCY
; 
 723             dm
.dmDisplayFrequency 
= mode
.refresh
; 
 730 #else // !__WXWINCE__ 
 731         flags 
= CDS_FULLSCREEN
; 
 732 #endif // __WXWINCE__/!__WXWINCE__ 
 736     // get pointer to the function dynamically 
 738     // we're only called from the main thread, so it's ok to use static 
 740     static ChangeDisplaySettingsEx_t pfnChangeDisplaySettingsEx 
= NULL
; 
 741     if ( !pfnChangeDisplaySettingsEx 
) 
 743         wxDynamicLibrary 
dllUser32(_T("user32.dll")); 
 744         if ( dllUser32
.IsLoaded() ) 
 746             pfnChangeDisplaySettingsEx 
= (ChangeDisplaySettingsEx_t
) 
 747                 dllUser32
.GetSymbolAorW(_T("ChangeDisplaySettingsEx")); 
 749         //else: huh, no user32.dll?? 
 752         if ( !pfnChangeDisplaySettingsEx 
) 
 754             // we must be under Win95 and so there is no multiple monitors 
 756             pfnChangeDisplaySettingsEx 
= ChangeDisplaySettingsExForWin95
; 
 758 #endif // !__WXWINCE__ 
 761     // do change the mode 
 762     switch ( pfnChangeDisplaySettingsEx
 
 764                 GetName(),      // display name 
 765                 pDevMode
,       // dev mode or NULL to reset 
 768                 NULL            
// pointer to video parameters (not used) 
 771         case DISP_CHANGE_SUCCESSFUL
: 
 774                 // If we have a top-level, full-screen frame, emulate 
 775                 // the DirectX behavior and resize it.  This makes this 
 776                 // API quite a bit easier to use. 
 777                 wxWindow 
*winTop 
= wxTheApp
->GetTopWindow(); 
 778                 wxFrame 
*frameTop 
= wxDynamicCast(winTop
, wxFrame
); 
 779                 if (frameTop 
&& frameTop
->IsFullScreen()) 
 781                     wxVideoMode current 
= GetCurrentMode(); 
 782                     frameTop
->SetClientSize(current
.w
, current
.h
); 
 787         case DISP_CHANGE_BADMODE
: 
 788             // don't complain about this, this is the only "expected" error 
 792             wxFAIL_MSG( _T("unexpected ChangeDisplaySettingsEx() return value") ); 
 799 // ============================================================================ 
 800 // DirectDraw-based wxDisplay implementation 
 801 // ============================================================================ 
 805 // ---------------------------------------------------------------------------- 
 806 // wxDisplayFactoryDirectDraw initialization 
 807 // ---------------------------------------------------------------------------- 
 809 wxDisplayFactoryDirectDraw::wxDisplayFactoryDirectDraw() 
 811     if ( !ms_supportsMultimon 
) 
 815     // suppress the errors if ddraw.dll is not found, we're prepared to handle 
 820     m_dllDDraw
.Load(_T("ddraw.dll")); 
 822     if ( !m_dllDDraw
.IsLoaded() ) 
 825     DirectDrawEnumerateEx_t pDDEnumEx 
= (DirectDrawEnumerateEx_t
) 
 826         m_dllDDraw
.GetSymbolAorW(_T("DirectDrawEnumerateEx")); 
 830     // we can't continue without DirectDrawCreate() later, so resolve it right 
 831     // now and fail the initialization if it's not available 
 832     m_pfnDirectDrawCreate 
= (DirectDrawCreate_t
) 
 833         m_dllDDraw
.GetSymbol(_T("DirectDrawCreate")); 
 834     if ( !m_pfnDirectDrawCreate 
) 
 837     if ( (*pDDEnumEx
)(DDEnumExCallback
, 
 839                       DDENUM_ATTACHEDSECONDARYDEVICES
) != DD_OK 
) 
 841         wxLogLastError(_T("DirectDrawEnumerateEx")); 
 845 wxDisplayFactoryDirectDraw::~wxDisplayFactoryDirectDraw() 
 847     // we must clear m_displays now, before m_dllDDraw is unloaded as otherwise 
 848     // calling m_pDD2->Release() later would crash 
 852 // ---------------------------------------------------------------------------- 
 853 // callbacks for monitor/modes enumeration stuff 
 854 // ---------------------------------------------------------------------------- 
 857 wxDisplayFactoryDirectDraw::DDEnumExCallback(GUID 
*pGuid
, 
 858                                              LPTSTR 
WXUNUSED(driverDescription
), 
 865         wxDisplayFactoryDirectDraw 
* self 
= 
 866             wx_static_cast(wxDisplayFactoryDirectDraw 
*, lpContext
); 
 867         self
->AddDisplay(*pGuid
, hmon
, driverName
); 
 869     //else: we're called for the primary monitor, skip it 
 871     // continue the enumeration 
 875 // ---------------------------------------------------------------------------- 
 876 // wxDisplayFactoryDirectDraw helpers 
 877 // ---------------------------------------------------------------------------- 
 879 void wxDisplayFactoryDirectDraw::AddDisplay(const GUID
& guid
, 
 883     m_displays
.Add(new wxDisplayInfoDirectDraw(guid
, hmon
, name
)); 
 886 // ---------------------------------------------------------------------------- 
 887 // wxDisplayFactoryDirectDraw inherited pure virtuals implementation 
 888 // ---------------------------------------------------------------------------- 
 890 wxDisplayImpl 
*wxDisplayFactoryDirectDraw::CreateDisplay(size_t n
) 
 892     wxCHECK_MSG( n 
< m_displays
.size(), NULL
, _T("invalid display index") ); 
 894     wxDisplayInfoDirectDraw 
* 
 895         info 
= wx_static_cast(wxDisplayInfoDirectDraw 
*, m_displays
[n
]); 
 900         GUID 
guid(info
->m_guid
); 
 901         HRESULT hr 
= (*m_pfnDirectDrawCreate
)(&guid
, &pDD
, NULL
); 
 903         if ( FAILED(hr
) || !pDD 
) 
 906             wxLogApiError(_T("DirectDrawCreate"), hr
); 
 910         // we got IDirectDraw, but we need IDirectDraw2 
 911         hr 
= pDD
->QueryInterface(wxIID_IDirectDraw2
, (void **)&info
->m_pDD2
); 
 914         if ( FAILED(hr
) || !info
->m_pDD2 
) 
 916             wxLogApiError(_T("IDirectDraw::QueryInterface(IDD2)"), hr
); 
 920         // NB: m_pDD2 will now be only destroyed when m_displays is destroyed 
 921         //     which is ok as we don't want to recreate DD objects all the time 
 923     //else: DirectDraw object corresponding to our display already exists 
 925     return new wxDisplayImplDirectDraw(n
, *info
, info
->m_pDD2
); 
 928 // ============================================================================ 
 929 // wxDisplayImplDirectDraw 
 930 // ============================================================================ 
 932 // ---------------------------------------------------------------------------- 
 933 // video modes enumeration 
 934 // ---------------------------------------------------------------------------- 
 936 // tiny helper class used to pass information from GetModes() to 
 937 // wxDDEnumModesCallback 
 938 class wxDDVideoModesAdder
 
 941     // our Add() method will add modes matching modeMatch to modes array 
 942     wxDDVideoModesAdder(wxArrayVideoModes
& modes
, const wxVideoMode
& modeMatch
) 
 944           m_modeMatch(modeMatch
) 
 948     void Add(const wxVideoMode
& mode
) 
 950         if ( mode
.Matches(m_modeMatch
) ) 
 955     wxArrayVideoModes
& m_modes
; 
 956     const wxVideoMode
& m_modeMatch
; 
 958     DECLARE_NO_COPY_CLASS(wxDDVideoModesAdder
) 
 961 HRESULT WINAPI 
wxDDEnumModesCallback(LPDDSURFACEDESC lpDDSurfaceDesc
, 
 964     // we need at least the mode size 
 965     static const DWORD FLAGS_REQUIRED 
= DDSD_HEIGHT 
| DDSD_WIDTH
; 
 966     if ( (lpDDSurfaceDesc
->dwFlags 
& FLAGS_REQUIRED
) == FLAGS_REQUIRED 
) 
 968         wxDDVideoModesAdder 
* const vmodes 
= 
 969             wx_static_cast(wxDDVideoModesAdder 
*, lpContext
); 
 971         vmodes
->Add(wxVideoMode(lpDDSurfaceDesc
->dwWidth
, 
 972                                 lpDDSurfaceDesc
->dwHeight
, 
 973                                 lpDDSurfaceDesc
->ddpfPixelFormat
.dwRGBBitCount
, 
 974                                 lpDDSurfaceDesc
->dwRefreshRate
)); 
 977     // continue the enumeration 
 982 wxDisplayImplDirectDraw::GetModes(const wxVideoMode
& modeMatch
) const 
 984     wxArrayVideoModes modes
; 
 985     wxDDVideoModesAdder 
modesAdder(modes
, modeMatch
); 
 987     HRESULT hr 
= m_pDD2
->EnumDisplayModes
 
 991                             &modesAdder
,            // callback parameter 
 992                             wxDDEnumModesCallback
 
 997         wxLogApiError(_T("IDirectDraw::EnumDisplayModes"), hr
); 
1003 // ---------------------------------------------------------------------------- 
1004 // video mode switching 
1005 // ---------------------------------------------------------------------------- 
1007 bool wxDisplayImplDirectDraw::ChangeMode(const wxVideoMode
& mode
) 
1009     wxWindow 
*winTop 
= wxTheApp
->GetTopWindow(); 
1010     wxCHECK_MSG( winTop
, false, _T("top level window required for DirectX") ); 
1012     HRESULT hr 
= m_pDD2
->SetCooperativeLevel
 
1015                             DDSCL_EXCLUSIVE 
| DDSCL_FULLSCREEN
 
1019         wxLogApiError(_T("IDirectDraw2::SetCooperativeLevel"), hr
); 
1024     hr 
= m_pDD2
->SetDisplayMode(mode
.w
, mode
.h
, mode
.bpp
, mode
.refresh
, 0); 
1027         wxLogApiError(_T("IDirectDraw2::SetDisplayMode"), hr
); 
1035 #endif // wxUSE_DIRECTDRAW 
1037 #endif // wxUSE_DISPLAY