📄 d3dapp.cpp
字号:
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)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) )
return hr;
// 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()
{
// Get access to current adapter, device, and mode
D3DAdapterInfo* pAdapterInfo = &m_Adapters[m_dwAdapter];
D3DDeviceInfo* pDeviceInfo = &pAdapterInfo->devices[pAdapterInfo->dwCurrentDevice];
D3DModeInfo* pModeInfo = &pDeviceInfo->modes[pDeviceInfo->dwCurrentMode];
// Need device change if going windowed and the current device
// can only be fullscreen
if( !m_bWindowed && !pDeviceInfo->bCanDoWindowed )
return ForceWindowed();
m_bReady = FALSE;
// Toggle the windowed state
m_bWindowed = !m_bWindowed;
pDeviceInfo->bWindowed = m_bWindowed;
// Prepare window for windowed/fullscreen change
AdjustWindowForChange();
// Set up the presentation parameters
m_d3dpp.Windowed = pDeviceInfo->bWindowed;
if( m_bWindowed )
m_d3dpp.MultiSampleType = pDeviceInfo->MultiSampleTypeWindowed;
else
m_d3dpp.MultiSampleType = pDeviceInfo->MultiSampleTypeFullscreen;
m_d3dpp.AutoDepthStencilFormat = pModeInfo->DepthStencilFormat;
m_d3dpp.hDeviceWindow = m_hWnd;
if( m_bWindowed )
{
m_d3dpp.BackBufferWidth = m_rcWindowClient.right - m_rcWindowClient.left;
m_d3dpp.BackBufferHeight = m_rcWindowClient.bottom - m_rcWindowClient.top;
m_d3dpp.BackBufferFormat = pAdapterInfo->d3ddmDesktop.Format;
}
else
{
m_d3dpp.BackBufferWidth = pModeInfo->Width;
m_d3dpp.BackBufferHeight = pModeInfo->Height;
m_d3dpp.BackBufferFormat = pModeInfo->Format;
}
// Resize the 3D device
if( FAILED( Resize3DEnvironment() ) )
{
if( m_bWindowed )
return ForceWindowed();
else
return E_FAIL;
}
// 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 );
}
m_bReady = TRUE;
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;
D3DAdapterInfo* pAdapterInfoCur = &m_Adapters[m_dwAdapter];
D3DDeviceInfo* pDeviceInfoCur = &pAdapterInfoCur->devices[pAdapterInfoCur->dwCurrentDevice];
BOOL bFoundDevice = FALSE;
if( pDeviceInfoCur->bCanDoWindowed )
{
bFoundDevice = TRUE;
}
else
{
// Look for a windowable device on any adapter
D3DAdapterInfo* pAdapterInfo;
DWORD dwAdapter;
D3DDeviceInfo* pDeviceInfo;
DWORD dwDevice;
for( dwAdapter = 0; dwAdapter < m_dwNumAdapters; dwAdapter++ )
{
pAdapterInfo = &m_Adapters[dwAdapter];
for( dwDevice = 0; dwDevice < pAdapterInfo->dwNumDevices; dwDevice++ )
{
pDeviceInfo = &pAdapterInfo->devices[dwDevice];
if( pDeviceInfo->bCanDoWindowed )
{
m_dwAdapter = dwAdapter;
pDeviceInfoCur = pDeviceInfo;
pAdapterInfo->dwCurrentDevice = dwDevice;
bFoundDevice = TRUE;
break;
}
}
if( bFoundDevice )
break;
}
}
if( !bFoundDevice )
return E_FAIL;
pDeviceInfoCur->bWindowed = TRUE;
m_bWindowed = TRUE;
// Now destroy the current 3D device objects, then reinitialize
m_bReady = FALSE;
// Release all scene objects that will be re-created for the new device
InvalidateDeviceObjects();
DeleteDeviceObjects();
// Release display objects, so a new device can be created
if( m_pd3dDevice->Release() > 0L )
return DisplayErrorMsg( D3DAPPERR_NONZEROREFCOUNT, MSGERR_APPMUSTEXIT );
// Create the new device
if( FAILED( hr = Initialize3DEnvironment() ) )
return DisplayErrorMsg( hr, MSGERR_APPMUSTEXIT );
m_bReady = TRUE;
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 );
}
else
{
// Set fullscreen-mode style
SetWindowLong( m_hWnd, GWL_STYLE, WS_POPUP|WS_SYSMENU|WS_VISIBLE );
m_hMenu = (HMENU)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_RESIZEFAILED, MSGERR_APPMUSTEXIT );
return E_FAIL;
}
}
// Prompt the user to change the mode
if( IDOK != DialogBoxParam( (HINSTANCE)GetModuleHandle(NULL),
MAKEINTRESOURCE(IDD_SELECTDEVICE), m_hWnd,
SelectDeviceProc, (LPARAM)this ) )
return S_OK;
// Get access to the newly selected adapter, device, and mode
DWORD dwDevice;
dwDevice = m_Adapters[m_dwAdapter].dwCurrentDevice;
m_bWindowed = m_Adapters[m_dwAdapter].devices[dwDevice].bWindowed;
// Release all scene objects that will be re-created for the new device
InvalidateDeviceObjects();
DeleteDeviceObjects();
// Release display objects, so a new device can be created
if( m_pd3dDevice->Release() > 0L )
return DisplayErrorMsg( D3DAPPERR_NONZEROREFCOUNT, MSGERR_APPMUSTEXIT );
// Inform the display class of the change. It will internally
// re-create valid surfaces, a d3ddevice, etc.
if( FAILED( hr = Initialize3DEnvironment() ) )
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: SelectDeviceProc()
// Desc: Windows message handling function for the device select dialog
//-----------------------------------------------------------------------------
INT_PTR CALLBACK CD3DApplication::SelectDeviceProc( HWND hDlg, UINT msg,
WPARAM wParam, LPARAM lParam )
{
// Get access to the UI controls
HWND hwndAdapterList = GetDlgItem( hDlg, IDC_ADAPTER_COMBO );
HWND hwndDeviceList = GetDlgItem( hDlg, IDC_DEVICE_COMBO );
HWND hwndFullscreenModeList = GetDlgItem( hDlg, IDC_FULLSCREENMODES_COMBO );
HWND hwndWindowedRadio = GetDlgItem( hDlg, IDC_WINDOW );
HWND hwndFullscreenRadio = GetDlgItem( hDlg, IDC_FULLSCREEN );
HWND hwndMultiSampleList = GetDlgItem( hDlg, IDC_MULTISAMPLE_COMBO );
BOOL bUpdateDlgControls = FALSE;
// Static state for adapter/device/mode selection
static CD3DApplication* pd3dApp;
static DWORD dwOldAdapter, dwNewAdapter;
static DWORD dwOldDevice, dwNewDevice;
static DWORD dwOldMode, dwNewMode;
static BOOL bOldWindowed, bNewWindowed;
static D3DMULTISAMPLE_TYPE OldMultiSampleTypeWindowed, NewMultiSampleTypeWindowed;
static D3DMULTISAMPLE_TYPE OldMultiSampleTypeFullscreen, NewMultiSampleTypeFullscreen;
// Working variables
D3DAdapterInfo* pAdapter;
D3DDeviceInfo* pDevice;
// Handle the initialization message
if( WM_INITDIALOG == msg )
{
// Old state
pd3dApp = (CD3DApplication*)lParam;
dwOldAdapter = pd3dApp->m_dwAdapter;
pAdapter = &pd3dApp->m_Adapters[dwOldAdapter];
dwOldDevice = pAdapter->dwCurrentDevice;
pDevice = &pAdapter->devices[dwOldDevice];
dwOldMode = pDevice->dwCurrentMode;
bOldWindowed = pDevice->bWindowed;
OldMultiSampleTypeWindowed = pDevice->MultiSampleTypeWindowed;
OldMultiSampleTypeFullscreen = pDevice->MultiSampleTypeFullscreen;
// New state is initially the same as the old state
dwNewAdapter = dwOldAdapter;
dwNewDevice = dwOldDevice;
dwNewMode = dwOldMode;
bNewWindowed = bOldWindowed;
NewMultiSampleTypeWindowed = OldMultiSampleTypeWindowed;
NewMultiSampleTypeFullscreen = OldMultiSampleTypeFullscreen;
// Set flag to update dialog controls below
bUpdateDlgControls = TRUE;
}
if( WM_COMMAND == msg )
{
// Get current UI state
bNewWindowed = Button_GetCheck( hwndWindowedRadio );
if( IDOK == LOWORD(wParam) )
{
// Handle the case when the user hits the OK button. Check if any
// of the options were changed
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -