📄 d3dsaver.cpp
字号:
//-----------------------------------------------------------------------------
// File: D3DSaver.cpp
//
// Desc: Framework for screensavers that use Direct3D.
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//-----------------------------------------------------------------------------
#include <Windows.h>
#include <windowsx.h>
#include <commctrl.h>
#include <stdio.h>
#include <tchar.h>
#include <regstr.h>
#define COMPILE_MULTIMON_STUBS
#include <multimon.h>
#include <mmsystem.h>
#include <D3DX9.h>
#include "D3DSaver.h"
#include "dxutil.h"
// Resource IDs. D3DSaver assumes that you will create resources with
// these IDs that it can use. The easiest way to do this is to copy
// the resources from the rc file of an existing D3DSaver-based program.
#define IDI_MAIN_ICON 101
#define IDD_SINGLEMONITORSETTINGS 200
#define IDD_MULTIMONITORSETTINGS 201
#define IDC_MONITORSTAB 2000
#define IDC_TABNAMEFMT 2001
#define IDC_ADAPTERNAME 2002
#define IDC_RENDERING 2003
#define IDC_MOREINFO 2004
#define IDC_DISABLEHW 2005
#define IDC_SCREENUSAGEBOX 2006
#define IDC_RENDER 2007
#define IDC_LEAVEBLACK 2008
#define IDC_DISPLAYMODEBOX 2009
#define IDC_MODESSTATIC 2010
#define IDC_MODESCOMBO 2011
#define IDC_AUTOMATIC 2012
#define IDC_DISPLAYMODENOTE 2013
#define IDC_GENERALBOX 2014
#define IDC_SAME 2015
#define IDC_MODEFMT 2016
#define IDS_ERR_GENERIC 2100
#define IDS_ERR_NODIRECT3D 2101
#define IDS_ERR_NOWINDOWEDHAL 2102
#define IDS_ERR_CREATEDEVICEFAILED 2103
#define IDS_ERR_NOCOMPATIBLEDEVICES 2104
#define IDS_ERR_NOHARDWAREDEVICE 2105
#define IDS_ERR_HALNOTCOMPATIBLE 2106
#define IDS_ERR_NOHALTHISMODE 2107
#define IDS_ERR_MEDIANOTFOUND 2108
#define IDS_ERR_RESIZEFAILED 2109
#define IDS_ERR_OUTOFMEMORY 2110
#define IDS_ERR_OUTOFVIDEOMEMORY 2111
#define IDS_ERR_NOPREVIEW 2112
#define IDS_INFO_GOODHAL 2200
#define IDS_INFO_BADHAL_GOODSW 2201
#define IDS_INFO_BADHAL_BADSW 2202
#define IDS_INFO_BADHAL_NOSW 2203
#define IDS_INFO_NOHAL_GOODSW 2204
#define IDS_INFO_NOHAL_BADSW 2205
#define IDS_INFO_NOHAL_NOSW 2206
#define IDS_INFO_DISABLEDHAL_GOODSW 2207
#define IDS_INFO_DISABLEDHAL_BADSW 2208
#define IDS_INFO_DISABLEDHAL_NOSW 2209
#define IDS_RENDERING_HAL 2210
#define IDS_RENDERING_SW 2211
#define IDS_RENDERING_NONE 2212
// Use the following structure rather than DISPLAY_DEVICE, since some old
// versions of DISPLAY_DEVICE are missing the last two fields and this can
// cause problems with EnumDisplayDevices on Windows 2000.
struct DISPLAY_DEVICE_FULL
{
DWORD cb;
TCHAR DeviceName[32];
TCHAR DeviceString[128];
DWORD StateFlags;
TCHAR DeviceID[128];
TCHAR DeviceKey[128];
};
static CD3DScreensaver* s_pD3DScreensaver = NULL;
//-----------------------------------------------------------------------------
// Name: CD3DScreensaver()
// Desc: Constructor
//-----------------------------------------------------------------------------
CD3DScreensaver::CD3DScreensaver()
{
s_pD3DScreensaver = this;
m_bCheckingSaverPassword = FALSE;
m_bIs9x = FALSE;
m_dwSaverMouseMoveCount = 0;
m_hWndParent = NULL;
m_hPasswordDLL = NULL;
m_hWnd = NULL;
m_VerifySaverPassword = NULL;
m_bAllScreensSame = FALSE;
m_pD3D = NULL;
m_pd3dDevice = NULL;
m_bWindowed = FALSE;
m_bWaitForInputIdle = FALSE;
m_bErrorMode = FALSE;
m_hrError = S_OK;
m_szError[0] = TEXT('\0');
m_fFPS = 0.0f;
m_strDeviceStats[0] = TEXT('\0');
m_strFrameStats[0] = TEXT('\0');
// Note: clients should load a resource into m_strWindowTitle to localize this string
lstrcpy( m_strWindowTitle, TEXT("Screen Saver") );
m_bAllowRef = FALSE;
m_bUseDepthBuffer = FALSE;
m_bMultithreaded = FALSE;
m_bOneScreenOnly = FALSE;
m_strRegPath[0] = TEXT('\0');
m_dwMinDepthBits = 16;
m_dwMinStencilBits = 0;
m_SwapEffectFullscreen = D3DSWAPEFFECT_DISCARD;
m_SwapEffectWindowed = D3DSWAPEFFECT_COPY;
SetRectEmpty( &m_rcRenderTotal );
SetRectEmpty( &m_rcRenderCurDevice );
ZeroMemory( m_Monitors, sizeof(m_Monitors) );
m_dwNumMonitors = 0;
ZeroMemory( m_Adapters, sizeof(m_Adapters) );
m_dwNumAdapters = 0;
ZeroMemory( m_RenderUnits, sizeof(m_RenderUnits) );
m_dwNumRenderUnits = 0;
m_fTime = 0.0f;
}
//-----------------------------------------------------------------------------
// Name: Create()
// Desc: Have the client program call this function before calling Run().
//-----------------------------------------------------------------------------
HRESULT CD3DScreensaver::Create( HINSTANCE hInstance )
{
HRESULT hr;
SetThreadPriority( GetCurrentThread(), THREAD_PRIORITY_IDLE );
m_hInstance = hInstance;
// Parse the command line and do the appropriate thing
TCHAR* pstrCmdLine = GetCommandLine();
m_SaverMode = ParseCommandLine( pstrCmdLine );
EnumMonitors();
// Create the screen saver window(s)
if( m_SaverMode == sm_preview ||
m_SaverMode == sm_test ||
m_SaverMode == sm_full )
{
if( FAILED( hr = CreateSaverWindow() ) )
{
m_bErrorMode = TRUE;
m_hrError = hr;
}
}
if( m_SaverMode == sm_preview )
{
// In preview mode, "pause" (enter a limited message loop) briefly
// before proceeding, so the display control panel knows to update itself.
m_bWaitForInputIdle = TRUE;
// Post a message to mark the end of the initial group of window messages
PostMessage( m_hWnd, WM_USER, 0, 0 );
MSG msg;
while( m_bWaitForInputIdle )
{
// If GetMessage returns FALSE, it's quitting time.
if( !GetMessage( &msg, m_hWnd, 0, 0 ) )
{
// Post the quit message to handle it later
PostQuitMessage(0);
break;
}
TranslateMessage( &msg );
DispatchMessage( &msg );
}
}
// Create Direct3D object
if( (m_pD3D = Direct3DCreate9( D3D_SDK_VERSION ) ) == NULL )
{
m_bErrorMode = TRUE;
m_hrError = D3DAPPERR_NODIRECT3D;
return S_OK;
}
// Give the app the opportunity to register a pluggable SW D3D Device.
if( FAILED( hr = RegisterSoftwareDevice() ) )
{
m_bErrorMode = TRUE;
m_hrError = hr;
return S_OK;
}
// 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.
if( FAILED( hr = BuildDeviceList() ) )
{
m_bErrorMode = TRUE;
m_hrError = hr;
return S_OK;
}
// Make sure that at least one valid usable D3D device was found
BOOL bCompatibleDeviceFound = FALSE;
for( DWORD iAdapter = 0; iAdapter < m_dwNumAdapters; iAdapter++ )
{
if( m_Adapters[iAdapter]->bHasAppCompatHAL ||
m_Adapters[iAdapter]->bHasAppCompatSW )
{
bCompatibleDeviceFound = TRUE;
break;
}
}
if( !bCompatibleDeviceFound )
{
m_bErrorMode = TRUE;
m_hrError = D3DAPPERR_NOCOMPATIBLEDEVICES;
return S_OK;
}
// Read any settings we need
ReadSettings();
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: EnumMonitors()
// Desc: Determine HMONITOR, desktop rect, and other info for each monitor.
// Note that EnumDisplayDevices enumerates monitors in the order
// indicated on the Settings page of the Display control panel, which
// is the order we want to list monitors in, as opposed to the order
// used by D3D's GetAdapterInfo.
//-----------------------------------------------------------------------------
VOID CD3DScreensaver::EnumMonitors( VOID )
{
DWORD iDevice = 0;
DISPLAY_DEVICE_FULL dispdev;
DISPLAY_DEVICE_FULL dispdev2;
DEVMODE devmode;
dispdev.cb = sizeof(dispdev);
dispdev2.cb = sizeof(dispdev2);
devmode.dmSize = sizeof(devmode);
devmode.dmDriverExtra = 0;
MonitorInfo* pMonitorInfoNew;
while( EnumDisplayDevices(NULL, iDevice, (DISPLAY_DEVICE*)&dispdev, 0) )
{
// Ignore NetMeeting's mirrored displays
if( (dispdev.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER) == 0 )
{
// To get monitor info for a display device, call EnumDisplayDevices
// a second time, passing dispdev.DeviceName (from the first call) as
// the first parameter.
EnumDisplayDevices(dispdev.DeviceName, 0, (DISPLAY_DEVICE*)&dispdev2, 0);
pMonitorInfoNew = &m_Monitors[m_dwNumMonitors];
ZeroMemory( pMonitorInfoNew, sizeof(MonitorInfo) );
lstrcpy( pMonitorInfoNew->strDeviceName, dispdev.DeviceString );
lstrcpy( pMonitorInfoNew->strMonitorName, dispdev2.DeviceString );
pMonitorInfoNew->iAdapter = NO_ADAPTER;
if( dispdev.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP )
{
EnumDisplaySettings( dispdev.DeviceName, ENUM_CURRENT_SETTINGS, &devmode );
if( dispdev.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE )
{
// For some reason devmode.dmPosition is not always (0, 0)
// for the primary display, so force it.
pMonitorInfoNew->rcScreen.left = 0;
pMonitorInfoNew->rcScreen.top = 0;
}
else
{
pMonitorInfoNew->rcScreen.left = devmode.dmPosition.x;
pMonitorInfoNew->rcScreen.top = devmode.dmPosition.y;
}
pMonitorInfoNew->rcScreen.right = pMonitorInfoNew->rcScreen.left + devmode.dmPelsWidth;
pMonitorInfoNew->rcScreen.bottom = pMonitorInfoNew->rcScreen.top + devmode.dmPelsHeight;
pMonitorInfoNew->hMonitor = MonitorFromRect( &pMonitorInfoNew->rcScreen, MONITOR_DEFAULTTONULL );
}
m_dwNumMonitors++;
if( m_dwNumMonitors == MAX_DISPLAYS )
break;
}
iDevice++;
}
}
//-----------------------------------------------------------------------------
// Name: Run()
// Desc: Starts main execution of the screen saver.
//-----------------------------------------------------------------------------
INT CD3DScreensaver::Run()
{
HRESULT hr;
// Parse the command line and do the appropriate thing
switch ( m_SaverMode )
{
case sm_config:
{
if( m_bErrorMode )
{
DisplayErrorMsg( m_hrError, 0 );
}
else
{
DoConfig();
}
break;
}
case sm_preview:
case sm_test:
case sm_full:
{
if( FAILED( hr = DoSaver() ) )
DisplayErrorMsg( hr, 0 );
break;
}
case sm_passwordchange:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -