display.cpp
来自「A*算法 A*算法 A*算法 A*算法A*算法A*算法」· C++ 代码 · 共 806 行 · 第 1/2 页
CPP
806 行
/* static */
int wxDisplayBase::GetFromWindow(wxWindow *window)
{
return DisplayFromHMONITOR
(
::MonitorFromWindow(GetHwndOf(window), MONITOR_DEFAULTTONULL)
);
}
// ----------------------------------------------------------------------------
// wxDisplay ctor/dtor
// ----------------------------------------------------------------------------
wxDisplay::wxDisplay ( size_t n )
: wxDisplayBase ( n )
{
// if we do this in ctor we won't have to call it from all the member
// functions
InitDisplays();
if ( gs_useDirectX )
{
wxDisplayInfo& dpyInfo = (*gs_displays)[n];
LPDIRECTDRAW2& pDD2 = dpyInfo.m_pDD2;
if ( !pDD2 )
{
if ( !gs_DirectDrawCreate )
{
// what to do??
return;
}
IDirectDraw *pDD;
HRESULT hr = (*gs_DirectDrawCreate)(&dpyInfo.m_guid, &pDD, NULL);
if ( FAILED(hr) || !pDD )
{
// what to do??
wxLogApiError(_T("DirectDrawCreate"), hr);
}
else // got IDirectDraw, we want IDirectDraw2
{
hr = pDD->QueryInterface(wxIID_IDirectDraw2, (void **)&pDD2);
if ( FAILED(hr) || !pDD2 )
{
wxLogApiError(_T("IDirectDraw::QueryInterface(IDD2)"), hr);
}
pDD->Release();
}
}
//else: DirectDraw object corresponding to our display already exists
// increment its ref count to account for Release() in dtor
//
// NB: pDD2 will be only really Release()d when gs_displays is
// destroyed which is ok as we don't want to recreate DD objects
// all the time
pDD2->AddRef();
}
}
wxDisplay::~wxDisplay()
{
wxDisplayInfo& dpyInfo = (*gs_displays)[m_index];
LPDIRECTDRAW2& pDD2 = dpyInfo.m_pDD2;
if ( pDD2 )
{
pDD2->Release();
}
}
// ----------------------------------------------------------------------------
// wxDisplay simple accessors
// ----------------------------------------------------------------------------
bool wxDisplay::IsOk() const
{
return m_index < GetCount() &&
(!gs_useDirectX || (*gs_displays)[m_index].m_pDD2);
}
wxRect wxDisplay::GetGeometry() const
{
wxDisplayInfo& dpyInfo = (*gs_displays)[m_index];
wxRect& rect = dpyInfo.m_rect;
if ( !rect.width )
{
MONITORINFO monInfo;
wxZeroMemory(monInfo);
monInfo.cbSize = sizeof(monInfo);
if ( !::GetMonitorInfo(dpyInfo.m_hmon, &monInfo) )
{
wxLogLastError(_T("GetMonitorInfo"));
}
else
{
wxCopyRECTToRect(monInfo.rcMonitor, rect);
}
}
return rect;
}
wxString wxDisplay::GetName() const
{
wxDisplayInfo& dpyInfo = (*gs_displays)[m_index];
if ( dpyInfo.m_devName.empty() )
{
MONITORINFOEX monInfo;
wxZeroMemory(monInfo);
monInfo.cbSize = sizeof(monInfo);
// NB: Cast from MONITORINFOEX* to MONITORINFO* is done because
// Mingw headers - unlike the ones from Microsoft's Platform SDK -
// don't derive the former from the latter in C++ mode and so
// the pointer's type is not converted implicitly.
if ( !::GetMonitorInfo(dpyInfo.m_hmon, (LPMONITORINFO)&monInfo) )
{
wxLogLastError(_T("GetMonitorInfo"));
}
else
{
dpyInfo.m_devName = monInfo.szDevice;
}
}
return dpyInfo.m_devName;
}
wxString wxDisplay::GetNameForEnumSettings() const
{
int major, minor;
const bool isWin95 = wxGetOsVersion(&major, &minor) == wxWIN95 &&
major == 4 && minor == 0;
// the first parameter of EnumDisplaySettings() must be NULL under Win95
// according to MSDN but GetMonitorInfo() stub in multimon.h still returns
// something even in this case, so we have to correct this manually
wxString name;
if ( !isWin95 )
name = GetName();
return name;
}
// ----------------------------------------------------------------------------
// determine if this is the primary display
// ----------------------------------------------------------------------------
bool wxDisplay::IsPrimary() const
{
wxDisplayInfo& dpyInfo = (*gs_displays)[m_index];
MONITORINFOEX monInfo;
wxZeroMemory(monInfo);
monInfo.cbSize = sizeof(monInfo);
// NB: Cast from MONITORINFOEX* to MONITORINFO* is done because
// Mingw headers - unlike the ones from Microsoft's Platform SDK -
// don't derive the former from the latter in C++ mode and so
// the pointer's type is not converted implicitly.
if ( !::GetMonitorInfo(dpyInfo.m_hmon, (LPMONITORINFO)&monInfo) )
{
wxLogLastError(_T("GetMonitorInfo"));
}
return (monInfo.dwFlags & MONITORINFOF_PRIMARY) == MONITORINFOF_PRIMARY;
}
// ----------------------------------------------------------------------------
// video modes enumeration
// ----------------------------------------------------------------------------
wxArrayVideoModes
wxDisplay::DoGetModesDirectX(const wxVideoMode& WXUNUSED(modeMatch)) const
{
wxArrayVideoModes modes;
IDirectDraw2 *pDD = (*gs_displays)[m_index].m_pDD2;
if ( pDD )
{
HRESULT hr = pDD->EnumDisplayModes
(
DDEDM_REFRESHRATES,
NULL, // all modes (TODO: use modeMatch!)
&modes, // callback parameter
wxDDEnumModesCallback
);
if ( FAILED(hr) )
{
wxLogApiError(_T("IDirectDraw::EnumDisplayModes"), hr);
}
}
return modes;
}
wxArrayVideoModes
wxDisplay::DoGetModesWindows(const wxVideoMode& modeMatch) const
{
wxArrayVideoModes modes;
const wxString name = GetNameForEnumSettings();
const wxChar * const deviceName = name.empty() ? NULL : name.c_str();
DEVMODE dm;
for ( int iModeNum = 0;
::EnumDisplaySettings(deviceName, iModeNum, &dm);
iModeNum++ )
{
const wxVideoMode mode = ConvertToVideoMode(dm);
if ( mode.Matches(modeMatch) )
{
modes.Add(mode);
}
}
return modes;
}
wxArrayVideoModes wxDisplay::GetModes(const wxVideoMode& modeMatch) const
{
return gs_useDirectX ? DoGetModesDirectX(modeMatch)
: DoGetModesWindows(modeMatch);
}
wxVideoMode wxDisplay::GetCurrentMode() const
{
wxVideoMode mode;
const wxString name = GetNameForEnumSettings();
DEVMODE dm;
if ( !::EnumDisplaySettings(name.empty() ? NULL : name.c_str(),
ENUM_CURRENT_SETTINGS,
&dm) )
{
wxLogLastError(_T("EnumDisplaySettings(ENUM_CURRENT_SETTINGS)"));
}
else
{
mode = ConvertToVideoMode(dm);
}
return mode;
}
// ----------------------------------------------------------------------------
// video mode switching
// ----------------------------------------------------------------------------
bool wxDisplay::DoChangeModeDirectX(const wxVideoMode& mode)
{
IDirectDraw2 *pDD = (*gs_displays)[m_index].m_pDD2;
if ( !pDD )
return false;
wxWindow *winTop = wxTheApp->GetTopWindow();
wxCHECK_MSG( winTop, false, _T("top level window required for DirectX") );
HRESULT hr = pDD->SetCooperativeLevel
(
GetHwndOf(winTop),
DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN
);
if ( FAILED(hr) )
{
wxLogApiError(_T("IDirectDraw::SetCooperativeLevel"), hr);
return false;
}
hr = pDD->SetDisplayMode(mode.w, mode.h, mode.bpp, mode.refresh, 0);
if ( FAILED(hr) )
{
wxLogApiError(_T("IDirectDraw::SetDisplayMode"), hr);
return false;
}
return true;
}
bool wxDisplay::DoChangeModeWindows(const wxVideoMode& mode)
{
// prepare ChangeDisplaySettingsEx() parameters
DEVMODE dm,
*pDevMode;
int flags;
if ( mode == wxDefaultVideoMode )
{
// reset the video mode to default
pDevMode = NULL;
flags = 0;
}
else // change to the given mode
{
wxCHECK_MSG( mode.w && mode.h, false,
_T("at least the width and height must be specified") );
wxZeroMemory(dm);
dm.dmSize = sizeof(dm);
dm.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
dm.dmPelsWidth = mode.w;
dm.dmPelsHeight = mode.h;
if ( mode.bpp )
{
dm.dmFields |= DM_BITSPERPEL;
dm.dmBitsPerPel = mode.bpp;
}
if ( mode.refresh )
{
dm.dmFields |= DM_DISPLAYFREQUENCY;
dm.dmDisplayFrequency = mode.refresh;
}
pDevMode = &dm;
flags = CDS_FULLSCREEN;
}
// get pointer to the function dynamically
//
// we're only called from the main thread, so it's ok to use static
// variable
static ChangeDisplaySettingsEx_t pfnChangeDisplaySettingsEx = NULL;
if ( !pfnChangeDisplaySettingsEx )
{
wxDynamicLibrary dllUser32(_T("user32.dll"));
if ( dllUser32.IsLoaded() )
{
pfnChangeDisplaySettingsEx = (ChangeDisplaySettingsEx_t)
dllUser32.GetSymbol(WINFUNC(ChangeDisplaySettingsEx));
}
//else: huh, no user32.dll??
if ( !pfnChangeDisplaySettingsEx )
{
// we must be under Win95 and so there is no multiple monitors
// support anyhow
pfnChangeDisplaySettingsEx = ChangeDisplaySettingsExForWin95;
}
}
// do change the mode
switch ( pfnChangeDisplaySettingsEx
(
GetName(), // display name
pDevMode, // dev mode or NULL to reset
NULL, // reserved
flags,
NULL // pointer to video parameters (not used)
) )
{
case DISP_CHANGE_SUCCESSFUL:
// ok
{
// If we have a top-level, full-screen frame, emulate
// the DirectX behavior and resize it. This makes this
// API quite a bit easier to use.
wxWindow *winTop = wxTheApp->GetTopWindow();
wxFrame *frameTop = wxDynamicCast(winTop, wxFrame);
if (frameTop && frameTop->IsFullScreen())
{
wxVideoMode current = GetCurrentMode();
frameTop->SetClientSize(current.w, current.h);
}
}
return true;
case DISP_CHANGE_BADMODE:
// don't complain about this, this is the only "expected" error
break;
default:
wxFAIL_MSG( _T("unexpected ChangeDisplaySettingsEx() return value") );
}
return false;
}
bool wxDisplay::ChangeMode(const wxVideoMode& mode)
{
return gs_useDirectX ? DoChangeModeDirectX(mode)
: DoChangeModeWindows(mode);
}
#endif // wxUSE_DISPLAY
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?