📄 d3dapp.cpp
字号:
// - Sets up some cursor stuff
// - Calls InitDeviceObjects()
// - Calls RestoreDeviceObjects()
// - If all goes well, m_bActive is set to TRUE, and the function returns
// - Otherwise, initialization is reattempted using the reference device
//-----------------------------------------------------------------------------
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 );
}
GetClientRect( m_hWnd, &m_rcWindowClient ); // Update our copy
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;
bool bDialogBoxMode = false;
bool bOldWindowed = m_bWindowed; // Preserve original windowed flag
if( m_bWindowed == false )
{
// See if the current settings comply with the rules
// for allowing SetDialogBoxMode().
if( (m_d3dpp.BackBufferFormat == D3DFMT_X1R5G5B5 || m_d3dpp.BackBufferFormat == D3DFMT_R5G6B5 || m_d3dpp.BackBufferFormat == D3DFMT_X8R8G8B8 ) &&
( m_d3dpp.MultiSampleType == D3DMULTISAMPLE_NONE ) &&
( m_d3dpp.SwapEffect == D3DSWAPEFFECT_DISCARD ) &&
( (m_d3dpp.Flags & D3DPRESENTFLAG_LOCKABLE_BACKBUFFER) == D3DPRESENTFLAG_LOCKABLE_BACKBUFFER ) &&
( (m_dwCreateFlags & D3DCREATE_ADAPTERGROUP_DEVICE) != D3DCREATE_ADAPTERGROUP_DEVICE ) )
{
if( SUCCEEDED( m_pd3dDevice->SetDialogBoxMode( true ) ) )
bDialogBoxMode = true;
}
// If SetDialogBoxMode(true) didn't work then we can't display dialogs
// in fullscreen mode so we'll go back to windowed mode
if( FALSE == bDialogBoxMode )
{
if( FAILED( ToggleFullscreen() ) )
{
DisplayErrorMsg( D3DAPPERR_RESETFAILED, MSGERR_APPMUSTEXIT );
return E_FAIL;
}
}
}
// The dialog should use the mode the sample runs in, not
// the mode that the dialog runs in.
CD3DSettings tempSettings = m_d3dSettings;
tempSettings.IsWindowed = bOldWindowed;
CD3DSettingsDialog settingsDialog( &m_d3dEnumeration, &tempSettings);
INT_PTR nResult = settingsDialog.ShowDialog( m_hWnd );
// Before creating the device, switch back to SetDialogBoxMode(false)
// mode to allow the user to pick multisampling or backbuffer formats
// not supported by SetDialogBoxMode(true) but typical apps wouldn't
// need to switch back.
if( bDialogBoxMode )
m_pd3dDevice->SetDialogBoxMode( false );
if( nResult != IDOK )
{
// If we had to switch mode to display the dialog, we
// need to go back to the original mode the sample
// was running in.
if( bOldWindowed != m_bWindowed && FAILED( ToggleFullscreen() ) )
{
DisplayErrorMsg( D3DAPPERR_RESETFAILED, MSGERR_APPMUSTEXIT );
return E_FAIL;
}
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;
}
//-----------------------------------------------------------------------------
// Name: Run()
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -