📄 d3dapp.cpp
字号:
hCursor = (HCURSOR)GetClassLongPtr( m_hWnd, GCLP_HCURSOR );
#else
hCursor = (HCURSOR)ULongToHandle( GetClassLong( m_hWnd, GCL_HCURSOR ) );
#endif
D3DUtil_SetDeviceCursor( m_pd3dDevice, hCursor, true );
m_pd3dDevice->ShowCursor( true );
}
// Confine cursor to fullscreen window
if( m_bClipCursorWhenFullscreen )
{
if (!m_bWindowed )
{
RECT rcWindow;
GetWindowRect( m_hWnd, &rcWindow );
ClipCursor( &rcWindow );
}
else
{
ClipCursor( NULL );
}
}
// Initialize the app's device-dependent objects
hr = InitDeviceObjects();
if( FAILED(hr) )
{
DeleteDeviceObjects();
}
else
{
m_bDeviceObjectsInited = true;
hr = RestoreDeviceObjects();
if( FAILED(hr) )
{
InvalidateDeviceObjects();
}
else
{
m_bDeviceObjectsRestored = true;
return S_OK;
}
}
// Cleanup before we try again
Cleanup3DEnvironment();
}
// If that failed, fall back to the reference rasterizer
if( hr != D3DAPPERR_MEDIANOTFOUND &&
hr != HRESULT_FROM_WIN32( ERROR_FILE_NOT_FOUND ) &&
pDeviceInfo->DevType == D3DDEVTYPE_HAL )
{
if (FindBestWindowedMode(false, true))
{
m_bWindowed = true;
AdjustWindowForChange();
// Make sure main window isn't topmost, so error message is visible
SetWindowPos( m_hWnd, HWND_NOTOPMOST,
m_rcWindowBounds.left, m_rcWindowBounds.top,
( m_rcWindowBounds.right - m_rcWindowBounds.left ),
( m_rcWindowBounds.bottom - m_rcWindowBounds.top ),
SWP_SHOWWINDOW );
// Let the user know we are switching from HAL to the reference rasterizer
DisplayErrorMsg( hr, MSGWARN_SWITCHEDTOREF );
hr = Initialize3DEnvironment();
}
}
return hr;
}
//-----------------------------------------------------------------------------
// Name: BuildPresentParamsFromSettings()
// Desc:
//-----------------------------------------------------------------------------
void CD3DApplication::BuildPresentParamsFromSettings()
{
m_d3dpp.Windowed = m_d3dSettings.IsWindowed;
m_d3dpp.BackBufferCount = 1;
m_d3dpp.MultiSampleType = m_d3dSettings.MultisampleType();
m_d3dpp.MultiSampleQuality = m_d3dSettings.MultisampleQuality();
m_d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
m_d3dpp.EnableAutoDepthStencil = m_d3dEnumeration.AppUsesDepthBuffer;
m_d3dpp.hDeviceWindow = m_hWnd;
if( m_d3dEnumeration.AppUsesDepthBuffer )
{
m_d3dpp.Flags = D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL;
m_d3dpp.AutoDepthStencilFormat = m_d3dSettings.DepthStencilBufferFormat();
}
else
{
m_d3dpp.Flags = 0;
}
if( m_bWindowed )
{
m_d3dpp.BackBufferWidth = m_rcWindowClient.right - m_rcWindowClient.left;
m_d3dpp.BackBufferHeight = m_rcWindowClient.bottom - m_rcWindowClient.top;
m_d3dpp.BackBufferFormat = m_d3dSettings.PDeviceCombo()->BackBufferFormat;
m_d3dpp.FullScreen_RefreshRateInHz = 0;
m_d3dpp.PresentationInterval = m_d3dSettings.PresentInterval();
}
else
{
m_d3dpp.BackBufferWidth = m_d3dSettings.DisplayMode().Width;
m_d3dpp.BackBufferHeight = m_d3dSettings.DisplayMode().Height;
m_d3dpp.BackBufferFormat = m_d3dSettings.PDeviceCombo()->BackBufferFormat;
m_d3dpp.FullScreen_RefreshRateInHz = m_d3dSettings.Fullscreen_DisplayMode.RefreshRate;
m_d3dpp.PresentationInterval = m_d3dSettings.PresentInterval();
}
}
//-----------------------------------------------------------------------------
// Name: Reset3DEnvironment()
// Desc:
//-----------------------------------------------------------------------------
HRESULT CD3DApplication::Reset3DEnvironment()
{
HRESULT hr;
// Release all vidmem objects
if( m_bDeviceObjectsRestored )
{
m_bDeviceObjectsRestored = false;
InvalidateDeviceObjects();
}
// Reset the device
if( FAILED( hr = m_pd3dDevice->Reset( &m_d3dpp ) ) )
return hr;
// Store render target surface desc
LPDIRECT3DSURFACE9 pBackBuffer;
m_pd3dDevice->GetBackBuffer( 0, 0, D3DBACKBUFFER_TYPE_MONO, &pBackBuffer );
pBackBuffer->GetDesc( &m_d3dsdBackBuffer );
pBackBuffer->Release();
// Set up the fullscreen cursor
if( m_bShowCursorWhenFullscreen && !m_bWindowed )
{
HCURSOR hCursor;
#ifdef _WIN64
hCursor = (HCURSOR)GetClassLongPtr( m_hWnd, GCLP_HCURSOR );
#else
hCursor = (HCURSOR)ULongToHandle( GetClassLong( m_hWnd, GCL_HCURSOR ) );
#endif
D3DUtil_SetDeviceCursor( m_pd3dDevice, hCursor, true );
m_pd3dDevice->ShowCursor( true );
}
// Confine cursor to fullscreen window
if( m_bClipCursorWhenFullscreen )
{
if (!m_bWindowed )
{
RECT rcWindow;
GetWindowRect( m_hWnd, &rcWindow );
ClipCursor( &rcWindow );
}
else
{
ClipCursor( NULL );
}
}
// Initialize the app's device-dependent objects
hr = RestoreDeviceObjects();
if( FAILED(hr) )
{
InvalidateDeviceObjects();
return hr;
}
m_bDeviceObjectsRestored = true;
// If the app is paused, trigger the rendering of the current frame
if( false == m_bFrameMoving )
{
m_bSingleStep = true;
DXUtil_Timer( TIMER_START );
DXUtil_Timer( TIMER_STOP );
}
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: ToggleFullScreen()
// Desc: Called when user toggles between fullscreen mode and windowed mode
//-----------------------------------------------------------------------------
HRESULT CD3DApplication::ToggleFullscreen()
{
HRESULT hr;
int AdapterOrdinalOld = m_d3dSettings.AdapterOrdinal();
D3DDEVTYPE DevTypeOld = m_d3dSettings.DevType();
Pause( true );
m_bIgnoreSizeChange = true;
// Toggle the windowed state
m_bWindowed = !m_bWindowed;
m_d3dSettings.IsWindowed = m_bWindowed;
// Prepare window for windowed/fullscreen change
AdjustWindowForChange();
// If AdapterOrdinal and DevType are the same, we can just do a Reset().
// If they've changed, we need to do a complete device teardown/rebuild.
if (m_d3dSettings.AdapterOrdinal() == AdapterOrdinalOld &&
m_d3dSettings.DevType() == DevTypeOld)
{
// Reset the 3D device
BuildPresentParamsFromSettings();
hr = Reset3DEnvironment();
}
else
{
Cleanup3DEnvironment();
hr = Initialize3DEnvironment();
}
if( FAILED( hr ) )
{
if( hr != D3DERR_OUTOFVIDEOMEMORY )
hr = D3DAPPERR_RESETFAILED;
m_bIgnoreSizeChange = false;
if( !m_bWindowed )
{
// Restore window type to windowed mode
m_bWindowed = !m_bWindowed;
m_d3dSettings.IsWindowed = m_bWindowed;
AdjustWindowForChange();
SetWindowPos( m_hWnd, HWND_NOTOPMOST,
m_rcWindowBounds.left, m_rcWindowBounds.top,
( m_rcWindowBounds.right - m_rcWindowBounds.left ),
( m_rcWindowBounds.bottom - m_rcWindowBounds.top ),
SWP_SHOWWINDOW );
}
return DisplayErrorMsg( hr, MSGERR_APPMUSTEXIT );
}
m_bIgnoreSizeChange = false;
// When moving from fullscreen to windowed mode, it is important to
// adjust the window size after resetting the device rather than
// beforehand to ensure that you get the window size you want. For
// example, when switching from 640x480 fullscreen to windowed with
// a 1000x600 window on a 1024x768 desktop, it is impossible to set
// the window size to 1000x600 until after the display mode has
// changed to 1024x768, because windows cannot be larger than the
// desktop.
if( m_bWindowed )
{
SetWindowPos( m_hWnd, HWND_NOTOPMOST,
m_rcWindowBounds.left, m_rcWindowBounds.top,
( m_rcWindowBounds.right - m_rcWindowBounds.left ),
( m_rcWindowBounds.bottom - m_rcWindowBounds.top ),
SWP_SHOWWINDOW );
}
Pause( false );
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: ForceWindowed()
// Desc: Switch to a windowed mode, even if that means picking a new device
// and/or adapter
//-----------------------------------------------------------------------------
HRESULT CD3DApplication::ForceWindowed()
{
HRESULT hr;
if( m_bWindowed )
return S_OK;
if( !FindBestWindowedMode(false, false) )
{
return E_FAIL;
}
m_bWindowed = true;
// Now destroy the current 3D device objects, then reinitialize
Pause( true );
// Release all scene objects that will be re-created for the new device
Cleanup3DEnvironment();
// Create the new device
if( FAILED(hr = Initialize3DEnvironment() ) )
return DisplayErrorMsg( hr, MSGERR_APPMUSTEXIT );
Pause( false );
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: AdjustWindowForChange()
// Desc: Prepare the window for a possible change between windowed mode and
// fullscreen mode. This function is virtual and thus can be overridden
// to provide different behavior, such as switching to an entirely
// different window for fullscreen mode (as in the MFC sample apps).
//-----------------------------------------------------------------------------
HRESULT CD3DApplication::AdjustWindowForChange()
{
if( m_bWindowed )
{
// Set windowed-mode style
SetWindowLong( m_hWnd, GWL_STYLE, m_dwWindowStyle );
if( m_hMenu != NULL )
{
SetMenu( m_hWnd, m_hMenu );
m_hMenu = NULL;
}
}
else
{
// Set fullscreen-mode style
SetWindowLong( m_hWnd, GWL_STYLE, WS_POPUP|WS_SYSMENU|WS_VISIBLE );
if( m_hMenu == NULL )
{
m_hMenu = GetMenu( m_hWnd );
SetMenu( m_hWnd, NULL );
}
}
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: UserSelectNewDevice()
// Desc: Displays a dialog so the user can select a new adapter, device, or
// display mode, and then recreates the 3D environment if needed
//-----------------------------------------------------------------------------
HRESULT CD3DApplication::UserSelectNewDevice()
{
HRESULT hr;
// Can't display dialogs in fullscreen mode
if( m_bWindowed == false )
{
if( FAILED( ToggleFullscreen() ) )
{
DisplayErrorMsg( D3DAPPERR_RESETFAILED, MSGERR_APPMUSTEXIT );
return E_FAIL;
}
}
CD3DSettingsDialog settingsDialog( &m_d3dEnumeration, &m_d3dSettings);
if( settingsDialog.ShowDialog( m_hWnd ) != IDOK )
return S_OK;
settingsDialog.GetFinalSettings( &m_d3dSettings );
m_bWindowed = m_d3dSettings.IsWindowed;
// Release all scene objects that will be re-created for the new device
Cleanup3DEnvironment();
// Inform the display class of the change. It will internally
// re-create valid surfaces, a d3ddevice, etc.
if( FAILED( hr = Initialize3DEnvironment() ) )
{
if( hr != D3DERR_OUTOFVIDEOMEMORY )
hr = D3DAPPERR_RESETFAILED;
if( !m_bWindowed )
{
// Restore window type to windowed mode
m_bWindowed = !m_bWindowed;
m_d3dSettings.IsWindowed = m_bWindowed;
AdjustWindowForChange();
SetWindowPos( m_hWnd, HWND_NOTOPMOST,
m_rcWindowBounds.left, m_rcWindowBounds.top,
( m_rcWindowBounds.right - m_rcWindowBounds.left ),
( m_rcWindowBounds.bottom - m_rcWindowBounds.top ),
SWP_SHOWWINDOW );
}
return DisplayErrorMsg( hr, MSGERR_APPMUSTEXIT );
}
// If the app is paused, trigger the rendering of the current frame
if( false == m_bFrameMoving )
{
m_bSingleStep = true;
DXUtil_Timer( TIMER_START );
DXUtil_Timer( TIMER_STOP );
}
return S_OK;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -