📄 d3dapp.cpp
字号:
//-----------------------------------------------------------------------------
// File: D3DApp.cpp
//
// Desc: Application class for the Direct3D samples framework library.
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//-----------------------------------------------------------------------------
#include "dxstdafx.h"
//-----------------------------------------------------------------------------
// Global access to the app (needed for the global WndProc())
//-----------------------------------------------------------------------------
static CD3DApplication* g_pD3DApp = NULL;
//-----------------------------------------------------------------------------
// Name: CD3DApplication()
// Desc: Constructor
//-----------------------------------------------------------------------------
CD3DApplication::CD3DApplication()
{
g_pD3DApp = this;
m_pD3D = NULL;
m_pd3dDevice = NULL;
m_hWnd = NULL;
m_hWndFocus = NULL;
m_hMenu = NULL;
m_bWindowed = true;
m_bActive = false;
m_bDeviceLost = false;
m_bMinimized = false;
m_bMaximized = false;
m_bIgnoreSizeChange = false;
m_bDeviceObjectsInited = false;
m_bDeviceObjectsRestored = false;
m_dwCreateFlags = 0;
m_bFrameMoving = true;
m_bSingleStep = false;
m_fTime = 0.0f;
m_fElapsedTime = 0.0f;
m_fFPS = 0.0f;
m_strDeviceStats[0] = _T('\0');
m_strFrameStats[0] = _T('\0');
m_strWindowTitle = _T("D3D9 Application");
m_dwCreationWidth = 400;
m_dwCreationHeight = 300;
m_bShowCursorWhenFullscreen = false;
m_bStartFullscreen = false;
m_bCreateMultithreadDevice = false;
m_bAllowDialogBoxMode = false;
Pause( true ); // Pause until we're ready to render
// When m_bClipCursorWhenFullscreen is true, the cursor is limited to
// the device window when the app goes fullscreen. This prevents users
// from accidentally clicking outside the app window on a multimon system.
// This flag is turned off by default for debug builds, since it makes
// multimon debugging difficult.
#if defined(_DEBUG) || defined(DEBUG)
m_bClipCursorWhenFullscreen = false;
#else
m_bClipCursorWhenFullscreen = true;
#endif
}
//-----------------------------------------------------------------------------
// Name: WndProc()
// Desc: Static msg handler which passes messages to the application class.
//-----------------------------------------------------------------------------
LRESULT CALLBACK WndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
return g_pD3DApp->MsgProc( hWnd, uMsg, wParam, lParam );
}
//-----------------------------------------------------------------------------
// Name: ConfirmDeviceHelper()
// Desc: Static function used by D3DEnumeration
//-----------------------------------------------------------------------------
bool CD3DApplication::ConfirmDeviceHelper( D3DCAPS9* pCaps, VertexProcessingType vertexProcessingType,
D3DFORMAT adapterFormat, D3DFORMAT backBufferFormat )
{
DWORD dwBehavior;
if (vertexProcessingType == SOFTWARE_VP)
dwBehavior = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
else if (vertexProcessingType == MIXED_VP)
dwBehavior = D3DCREATE_MIXED_VERTEXPROCESSING;
else if (vertexProcessingType == HARDWARE_VP)
dwBehavior = D3DCREATE_HARDWARE_VERTEXPROCESSING;
else if (vertexProcessingType == PURE_HARDWARE_VP)
dwBehavior = D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE;
else
dwBehavior = 0; // TODO: throw exception
return SUCCEEDED( g_pD3DApp->ConfirmDevice( pCaps, dwBehavior, adapterFormat, backBufferFormat ) );
}
//-----------------------------------------------------------------------------
// Name: Create()
// Desc: Here's what this function does:
// - Checks to make sure app is still active (if fullscreen, etc)
// - Checks to see if it is time to draw with DXUtil_Timer, if not, it just returns S_OK
// - Calls FrameMove() to recalculate new positions
// - Calls Render() to draw the new frame
// - Updates some frame count statistics
// - Calls m_pd3dDevice->Present() to display the rendered frame.
//-----------------------------------------------------------------------------
HRESULT CD3DApplication::Create( HINSTANCE hInstance )
{
HRESULT hr;
// Create the Direct3D object
m_pD3D = Direct3DCreate9( D3D_SDK_VERSION );
if( m_pD3D == NULL )
return DisplayErrorMsg( D3DAPPERR_NODIRECT3D, MSGERR_APPMUSTEXIT );
// Build a list of Direct3D adapters, modes and devices. The
// ConfirmDevice() callback is used to confirm that only devices that
// meet the app's requirements are considered.
m_d3dEnumeration.SetD3D( m_pD3D );
m_d3dEnumeration.ConfirmDeviceCallback = ConfirmDeviceHelper;
if( FAILED( hr = m_d3dEnumeration.Enumerate() ) )
{
SAFE_RELEASE( m_pD3D );
return DisplayErrorMsg( hr, MSGERR_APPMUSTEXIT );
}
// Unless a substitute hWnd has been specified, create a window to
// render into
if( m_hWnd == NULL)
{
// Register the windows class
WNDCLASS wndClass = { 0, WndProc, 0, 0, hInstance,
LoadIcon( hInstance, MAKEINTRESOURCE(IDI_MAIN_ICON) ),
LoadCursor( NULL, IDC_ARROW ),
(HBRUSH)GetStockObject(WHITE_BRUSH),
NULL, _T("D3D Window") };
RegisterClass( &wndClass );
// Set the window's initial style
m_dwWindowStyle = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME |
WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_VISIBLE;
HMENU hMenu = LoadMenu( hInstance, MAKEINTRESOURCE(IDR_MENU) );
// Set the window's initial width
RECT rc;
SetRect( &rc, 0, 0, m_dwCreationWidth, m_dwCreationHeight );
AdjustWindowRect( &rc, m_dwWindowStyle, ( hMenu != NULL ) ? true : false );
// Create the render window
m_hWnd = CreateWindow( _T("D3D Window"), m_strWindowTitle, m_dwWindowStyle,
CW_USEDEFAULT, CW_USEDEFAULT,
(rc.right-rc.left), (rc.bottom-rc.top), 0,
hMenu, hInstance, 0 );
}
// The focus window can be a specified to be a different window than the
// device window. If not, use the device window as the focus window.
if( m_hWndFocus == NULL )
m_hWndFocus = m_hWnd;
// Save window properties
m_dwWindowStyle = GetWindowLong( m_hWnd, GWL_STYLE );
GetWindowRect( m_hWnd, &m_rcWindowBounds );
GetClientRect( m_hWnd, &m_rcWindowClient );
if( FAILED( hr = ChooseInitialD3DSettings() ) )
{
SAFE_RELEASE( m_pD3D );
return DisplayErrorMsg( hr, MSGERR_APPMUSTEXIT );
}
// Initialize the application timer
DXUtil_Timer( TIMER_START );
// Initialize the app's custom scene stuff
if( FAILED( hr = OneTimeSceneInit() ) )
{
SAFE_RELEASE( m_pD3D );
return DisplayErrorMsg( hr, MSGERR_APPMUSTEXIT );
}
// Initialize the 3D environment for the app
if( FAILED( hr = Initialize3DEnvironment() ) )
{
SAFE_RELEASE( m_pD3D );
return DisplayErrorMsg( hr, MSGERR_APPMUSTEXIT );
}
// The app is ready to go
Pause( false );
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: FindBestWindowedMode()
// Desc: Sets up m_d3dSettings with best available windowed mode, subject to
// the bRequireHAL and bRequireREF constraints. Returns false if no such
// mode can be found.
//-----------------------------------------------------------------------------
bool CD3DApplication::FindBestWindowedMode( bool bRequireHAL, bool bRequireREF )
{
// Get display mode of primary adapter (which is assumed to be where the window
// will appear)
D3DDISPLAYMODE primaryDesktopDisplayMode;
m_pD3D->GetAdapterDisplayMode(0, &primaryDesktopDisplayMode);
D3DAdapterInfo* pBestAdapterInfo = NULL;
D3DDeviceInfo* pBestDeviceInfo = NULL;
D3DDeviceCombo* pBestDeviceCombo = NULL;
for( UINT iai = 0; iai < m_d3dEnumeration.m_pAdapterInfoList->Count(); iai++ )
{
D3DAdapterInfo* pAdapterInfo = (D3DAdapterInfo*)m_d3dEnumeration.m_pAdapterInfoList->GetPtr(iai);
for( UINT idi = 0; idi < pAdapterInfo->pDeviceInfoList->Count(); idi++ )
{
D3DDeviceInfo* pDeviceInfo = (D3DDeviceInfo*)pAdapterInfo->pDeviceInfoList->GetPtr(idi);
if (bRequireHAL && pDeviceInfo->DevType != D3DDEVTYPE_HAL)
continue;
if (bRequireREF && pDeviceInfo->DevType != D3DDEVTYPE_REF)
continue;
for( UINT idc = 0; idc < pDeviceInfo->pDeviceComboList->Count(); idc++ )
{
D3DDeviceCombo* pDeviceCombo = (D3DDeviceCombo*)pDeviceInfo->pDeviceComboList->GetPtr(idc);
bool bAdapterMatchesBB = (pDeviceCombo->BackBufferFormat == pDeviceCombo->AdapterFormat);
if (!pDeviceCombo->IsWindowed)
continue;
if (pDeviceCombo->AdapterFormat != primaryDesktopDisplayMode.Format)
continue;
// If we haven't found a compatible DeviceCombo yet, or if this set
// is better (because it's a HAL, and/or because formats match better),
// save it
if( pBestDeviceCombo == NULL ||
pBestDeviceCombo->DevType != D3DDEVTYPE_HAL && pDeviceCombo->DevType == D3DDEVTYPE_HAL ||
pDeviceCombo->DevType == D3DDEVTYPE_HAL && bAdapterMatchesBB )
{
pBestAdapterInfo = pAdapterInfo;
pBestDeviceInfo = pDeviceInfo;
pBestDeviceCombo = pDeviceCombo;
if( pDeviceCombo->DevType == D3DDEVTYPE_HAL && bAdapterMatchesBB )
{
// This windowed device combo looks great -- take it
goto EndWindowedDeviceComboSearch;
}
// Otherwise keep looking for a better windowed device combo
}
}
}
}
EndWindowedDeviceComboSearch:
if (pBestDeviceCombo == NULL )
return false;
m_d3dSettings.pWindowed_AdapterInfo = pBestAdapterInfo;
m_d3dSettings.pWindowed_DeviceInfo = pBestDeviceInfo;
m_d3dSettings.pWindowed_DeviceCombo = pBestDeviceCombo;
m_d3dSettings.IsWindowed = true;
m_d3dSettings.Windowed_DisplayMode = primaryDesktopDisplayMode;
m_d3dSettings.Windowed_Width = m_rcWindowClient.right - m_rcWindowClient.left;
m_d3dSettings.Windowed_Height = m_rcWindowClient.bottom - m_rcWindowClient.top;
if (m_d3dEnumeration.AppUsesDepthBuffer)
m_d3dSettings.Windowed_DepthStencilBufferFormat = *(D3DFORMAT*)pBestDeviceCombo->pDepthStencilFormatList->GetPtr(0);
m_d3dSettings.Windowed_MultisampleType = *(D3DMULTISAMPLE_TYPE*)pBestDeviceCombo->pMultiSampleTypeList->GetPtr(0);
m_d3dSettings.Windowed_MultisampleQuality = 0;
m_d3dSettings.Windowed_VertexProcessingType = *(VertexProcessingType*)pBestDeviceCombo->pVertexProcessingTypeList->GetPtr(0);
m_d3dSettings.Windowed_PresentInterval = *(UINT*)pBestDeviceCombo->pPresentIntervalList->GetPtr(0);
return true;
}
//-----------------------------------------------------------------------------
// Name: FindBestFullscreenMode()
// Desc: Sets up m_d3dSettings with best available fullscreen mode, subject to
// the bRequireHAL and bRequireREF constraints. Returns false if no such
// mode can be found.
//-----------------------------------------------------------------------------
bool CD3DApplication::FindBestFullscreenMode( bool bRequireHAL, bool bRequireREF )
{
// For fullscreen, default to first HAL DeviceCombo that supports the current desktop
// display mode, or any display mode if HAL is not compatible with the desktop mode, or
// non-HAL if no HAL is available
D3DDISPLAYMODE adapterDesktopDisplayMode;
D3DDISPLAYMODE bestAdapterDesktopDisplayMode;
D3DDISPLAYMODE bestDisplayMode;
bestAdapterDesktopDisplayMode.Width = 0;
bestAdapterDesktopDisplayMode.Height = 0;
bestAdapterDesktopDisplayMode.Format = D3DFMT_UNKNOWN;
bestAdapterDesktopDisplayMode.RefreshRate = 0;
D3DAdapterInfo* pBestAdapterInfo = NULL;
D3DDeviceInfo* pBestDeviceInfo = NULL;
D3DDeviceCombo* pBestDeviceCombo = NULL;
for( UINT iai = 0; iai < m_d3dEnumeration.m_pAdapterInfoList->Count(); iai++ )
{
D3DAdapterInfo* pAdapterInfo = (D3DAdapterInfo*)m_d3dEnumeration.m_pAdapterInfoList->GetPtr(iai);
m_pD3D->GetAdapterDisplayMode( pAdapterInfo->AdapterOrdinal, &adapterDesktopDisplayMode );
for( UINT idi = 0; idi < pAdapterInfo->pDeviceInfoList->Count(); idi++ )
{
D3DDeviceInfo* pDeviceInfo = (D3DDeviceInfo*)pAdapterInfo->pDeviceInfoList->GetPtr(idi);
if (bRequireHAL && pDeviceInfo->DevType != D3DDEVTYPE_HAL)
continue;
if (bRequireREF && pDeviceInfo->DevType != D3DDEVTYPE_REF)
continue;
for( UINT idc = 0; idc < pDeviceInfo->pDeviceComboList->Count(); idc++ )
{
D3DDeviceCombo* pDeviceCombo = (D3DDeviceCombo*)pDeviceInfo->pDeviceComboList->GetPtr(idc);
bool bAdapterMatchesBB = (pDeviceCombo->BackBufferFormat == pDeviceCombo->AdapterFormat);
bool bAdapterMatchesDesktop = (pDeviceCombo->AdapterFormat == adapterDesktopDisplayMode.Format);
if (pDeviceCombo->IsWindowed)
continue;
// If we haven't found a compatible set yet, or if this set
// is better (because it's a HAL, and/or because formats match better),
// save it
if (pBestDeviceCombo == NULL ||
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -