📄 d3dapp.cpp
字号:
if (m_d3dEnumeration.AppUsesDepthBuffer)
m_d3dSettings.Fullscreen_DepthStencilBufferFormat = *(D3DFORMAT*)pBestDeviceCombo->pDepthStencilFormatList->GetPtr(0);
m_d3dSettings.Fullscreen_MultisampleType = *(D3DMULTISAMPLE_TYPE*)pBestDeviceCombo->pMultiSampleTypeList->GetPtr(0);
m_d3dSettings.Fullscreen_MultisampleQuality = 0;
m_d3dSettings.Fullscreen_VertexProcessingType = *(VertexProcessingType*)pBestDeviceCombo->pVertexProcessingTypeList->GetPtr(0);
m_d3dSettings.Fullscreen_PresentInterval = D3DPRESENT_INTERVAL_DEFAULT;
return true;
}
//-----------------------------------------------------------------------------
// Name: ChooseInitialD3DSettings()
// Desc:
//-----------------------------------------------------------------------------
HRESULT CD3DApplication::ChooseInitialD3DSettings()
{
bool bFoundFullscreen = FindBestFullscreenMode( false, false );
bool bFoundWindowed = FindBestWindowedMode( false, false );
if( m_bStartFullscreen && bFoundFullscreen )
m_d3dSettings.IsWindowed = false;
if( !bFoundWindowed && bFoundFullscreen )
m_d3dSettings.IsWindowed = false;
if( !bFoundFullscreen && !bFoundWindowed )
return D3DAPPERR_NOCOMPATIBLEDEVICES;
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: MsgProc()
// Desc: Message handling function.
//-----------------------------------------------------------------------------
LRESULT CD3DApplication::MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam,
LPARAM lParam )
{
switch( uMsg )
{
case WM_PAINT:
// Handle paint messages when the app is paused
if( m_pd3dDevice && !m_bActive && m_bWindowed &&
m_bDeviceObjectsInited && m_bDeviceObjectsRestored )
{
Render();
m_pd3dDevice->Present( NULL, NULL, NULL, NULL );
}
break;
case WM_GETMINMAXINFO:
((MINMAXINFO*)lParam)->ptMinTrackSize.x = 100;
((MINMAXINFO*)lParam)->ptMinTrackSize.y = 100;
break;
case WM_ENTERSIZEMOVE:
// Halt frame movement while the app is sizing or moving
Pause( true );
break;
case WM_SIZE:
// Pick up possible changes to window style due to maximize, etc.
if( m_bWindowed && m_hWnd != NULL )
m_dwWindowStyle = GetWindowLong( m_hWnd, GWL_STYLE );
if( SIZE_MINIMIZED == wParam )
{
if( m_bClipCursorWhenFullscreen && !m_bWindowed )
ClipCursor( NULL );
Pause( true ); // Pause while we're minimized
m_bMinimized = true;
m_bMaximized = false;
}
else if( SIZE_MAXIMIZED == wParam )
{
if( m_bMinimized )
Pause( false ); // Unpause since we're no longer minimized
m_bMinimized = false;
m_bMaximized = true;
HandlePossibleSizeChange();
}
else if( SIZE_RESTORED == wParam )
{
if( m_bMaximized )
{
m_bMaximized = false;
HandlePossibleSizeChange();
}
else if( m_bMinimized)
{
Pause( false ); // Unpause since we're no longer minimized
m_bMinimized = false;
HandlePossibleSizeChange();
}
else
{
// If we're neither maximized nor minimized, the window size
// is changing by the user dragging the window edges. In this
// case, we don't reset the device yet -- we wait until the
// user stops dragging, and a WM_EXITSIZEMOVE message comes.
}
}
break;
case WM_EXITSIZEMOVE:
Pause( false );
HandlePossibleSizeChange();
break;
case WM_SETCURSOR:
// Turn off Windows cursor in fullscreen mode
if( m_bActive && !m_bWindowed )
{
SetCursor( NULL );
if( m_bShowCursorWhenFullscreen )
m_pd3dDevice->ShowCursor( true );
return true; // prevent Windows from setting cursor to window class cursor
}
break;
case WM_MOUSEMOVE:
if( m_bActive && m_pd3dDevice != NULL )
{
POINT ptCursor;
GetCursorPos( &ptCursor );
if( !m_bWindowed )
ScreenToClient( m_hWnd, &ptCursor );
m_pd3dDevice->SetCursorPosition( ptCursor.x, ptCursor.y, 0 );
}
break;
case WM_ENTERMENULOOP:
// Pause the app when menus are displayed
Pause(true);
break;
case WM_EXITMENULOOP:
Pause(false);
break;
case WM_NCHITTEST:
// Prevent the user from selecting the menu in fullscreen mode
if( !m_bWindowed )
return HTCLIENT;
break;
case WM_POWERBROADCAST:
switch( wParam )
{
#ifndef PBT_APMQUERYSUSPEND
#define PBT_APMQUERYSUSPEND 0x0000
#endif
case PBT_APMQUERYSUSPEND:
// At this point, the app should save any data for open
// network connections, files, etc., and prepare to go into
// a suspended mode.
return true;
#ifndef PBT_APMRESUMESUSPEND
#define PBT_APMRESUMESUSPEND 0x0007
#endif
case PBT_APMRESUMESUSPEND:
// At this point, the app should recover any data, network
// connections, files, etc., and resume running from when
// the app was suspended.
return true;
}
break;
case WM_SYSCOMMAND:
// Prevent moving/sizing and power loss in fullscreen mode
switch( wParam )
{
case SC_MOVE:
case SC_SIZE:
case SC_MAXIMIZE:
case SC_KEYMENU:
case SC_MONITORPOWER:
if( false == m_bWindowed )
return 1;
break;
}
break;
case WM_COMMAND:
switch( LOWORD(wParam) )
{
case IDM_CHANGEDEVICE:
// Prompt the user to select a new device or mode
Pause(true);
UserSelectNewDevice();
Pause(false);
return 0;
case IDM_TOGGLEFULLSCREEN:
// Toggle the fullscreen/window mode
Pause( true );
if( FAILED( ToggleFullscreen() ) )
DisplayErrorMsg( D3DAPPERR_RESETFAILED, MSGERR_APPMUSTEXIT );
Pause( false );
return 0;
case IDM_EXIT:
// Recieved key/menu command to exit app
SendMessage( hWnd, WM_CLOSE, 0, 0 );
return 0;
}
break;
case WM_CLOSE:
Cleanup3DEnvironment();
SAFE_RELEASE( m_pD3D );
FinalCleanup();
HMENU hMenu;
hMenu = GetMenu(hWnd);
if( hMenu != NULL )
DestroyMenu( hMenu );
DestroyWindow( hWnd );
PostQuitMessage(0);
m_hWnd = NULL;
return 0;
}
return DefWindowProc( hWnd, uMsg, wParam, lParam );
}
//-----------------------------------------------------------------------------
// Name: HandlePossibleSizeChange()
// Desc: Reset the device if the client area size has changed.
//-----------------------------------------------------------------------------
HRESULT CD3DApplication::HandlePossibleSizeChange()
{
HRESULT hr = S_OK;
RECT rcClientOld;
rcClientOld = m_rcWindowClient;
if( m_bIgnoreSizeChange )
return S_OK;
// Update window properties
GetWindowRect( m_hWnd, &m_rcWindowBounds );
GetClientRect( m_hWnd, &m_rcWindowClient );
if( rcClientOld.right - rcClientOld.left !=
m_rcWindowClient.right - m_rcWindowClient.left ||
rcClientOld.bottom - rcClientOld.top !=
m_rcWindowClient.bottom - m_rcWindowClient.top)
{
// A new window size will require a new backbuffer
// size, so the 3D structures must be changed accordingly.
Pause( true );
m_d3dpp.BackBufferWidth = m_rcWindowClient.right - m_rcWindowClient.left;
m_d3dpp.BackBufferHeight = m_rcWindowClient.bottom - m_rcWindowClient.top;
if( m_pd3dDevice != NULL )
{
// Reset the 3D environment
if( FAILED( hr = Reset3DEnvironment() ) )
{
if( hr != D3DERR_OUTOFVIDEOMEMORY )
hr = D3DAPPERR_RESETFAILED;
DisplayErrorMsg( hr, MSGERR_APPMUSTEXIT );
}
}
Pause( false );
}
return hr;
}
//-----------------------------------------------------------------------------
// Name: Initialize3DEnvironment()
// Desc:
//-----------------------------------------------------------------------------
HRESULT CD3DApplication::Initialize3DEnvironment()
{
HRESULT hr;
D3DAdapterInfo* pAdapterInfo = m_d3dSettings.PAdapterInfo();
D3DDeviceInfo* pDeviceInfo = m_d3dSettings.PDeviceInfo();
m_bWindowed = m_d3dSettings.IsWindowed;
// Prepare window for possible windowed/fullscreen change
AdjustWindowForChange();
// Set up the presentation parameters
BuildPresentParamsFromSettings();
if( pDeviceInfo->Caps.PrimitiveMiscCaps & D3DPMISCCAPS_NULLREFERENCE )
{
// Warn user about null ref device that can't render anything
DisplayErrorMsg( D3DAPPERR_NULLREFDEVICE, 0 );
}
DWORD behaviorFlags;
if (m_d3dSettings.GetVertexProcessingType() == SOFTWARE_VP)
behaviorFlags = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
else if (m_d3dSettings.GetVertexProcessingType() == MIXED_VP)
behaviorFlags = D3DCREATE_MIXED_VERTEXPROCESSING;
else if (m_d3dSettings.GetVertexProcessingType() == HARDWARE_VP)
behaviorFlags = D3DCREATE_HARDWARE_VERTEXPROCESSING;
else if (m_d3dSettings.GetVertexProcessingType() == PURE_HARDWARE_VP)
behaviorFlags = D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE;
else
behaviorFlags = 0; // TODO: throw exception
// Create the device
hr = m_pD3D->CreateDevice( m_d3dSettings.AdapterOrdinal(), pDeviceInfo->DevType,
m_hWndFocus, behaviorFlags, &m_d3dpp,
&m_pd3dDevice );
if( SUCCEEDED(hr) )
{
// When moving from fullscreen to windowed mode, it is important to
// adjust the window size after recreating 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 );
}
// Store device Caps
m_pd3dDevice->GetDeviceCaps( &m_d3dCaps );
m_dwCreateFlags = behaviorFlags;
// Store device description
if( pDeviceInfo->DevType == D3DDEVTYPE_REF )
lstrcpy( m_strDeviceStats, TEXT("REF") );
else if( pDeviceInfo->DevType == D3DDEVTYPE_HAL )
lstrcpy( m_strDeviceStats, TEXT("HAL") );
else if( pDeviceInfo->DevType == D3DDEVTYPE_SW )
lstrcpy( m_strDeviceStats, TEXT("SW") );
if( behaviorFlags & D3DCREATE_HARDWARE_VERTEXPROCESSING &&
behaviorFlags & D3DCREATE_PUREDEVICE )
{
if( pDeviceInfo->DevType == D3DDEVTYPE_HAL )
lstrcat( m_strDeviceStats, TEXT(" (pure hw vp)") );
else
lstrcat( m_strDeviceStats, TEXT(" (simulated pure hw vp)") );
}
else if( behaviorFlags & D3DCREATE_HARDWARE_VERTEXPROCESSING )
{
if( pDeviceInfo->DevType == D3DDEVTYPE_HAL )
lstrcat( m_strDeviceStats, TEXT(" (hw vp)") );
else
lstrcat( m_strDeviceStats, TEXT(" (simulated hw vp)") );
}
else if( behaviorFlags & D3DCREATE_MIXED_VERTEXPROCESSING )
{
if( pDeviceInfo->DevType == D3DDEVTYPE_HAL )
lstrcat( m_strDeviceStats, TEXT(" (mixed vp)") );
else
lstrcat( m_strDeviceStats, TEXT(" (simulated mixed vp)") );
}
else if( behaviorFlags & D3DCREATE_SOFTWARE_VERTEXPROCESSING )
{
lstrcat( m_strDeviceStats, TEXT(" (sw vp)") );
}
if( pDeviceInfo->DevType == D3DDEVTYPE_HAL )
{
// Be sure not to overflow m_strDeviceStats when appending the adapter
// description, since it can be long. Note that the adapter description
// is initially CHAR and must be converted to TCHAR.
lstrcat( m_strDeviceStats, TEXT(": ") );
const int cchDesc = sizeof(pAdapterInfo->AdapterIdentifier.Description);
TCHAR szDescription[cchDesc];
DXUtil_ConvertAnsiStringToGenericCch( szDescription,
pAdapterInfo->AdapterIdentifier.Description, cchDesc );
int maxAppend = sizeof(m_strDeviceStats) / sizeof(TCHAR) -
lstrlen( m_strDeviceStats ) - 1;
_tcsncat( m_strDeviceStats, szDescription, maxAppend );
}
// Store render target surface desc
LPDIRECT3DSURFACE9 pBackBuffer = NULL;
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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -