Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1373 lines
47 KiB

//-----------------------------------------------------------------------------
// File: Text3D.cpp
//
// Desc: Fun screen saver.
//
// Copyright (c) 2000-2001 Microsoft Corporation. All rights reserved.
//-----------------------------------------------------------------------------
#include <Windows.h>
#include <d3d8.h>
#include <d3dx8.h>
#include <d3dsaver.h>
#include <d3d8rgbrast.h>
#include <time.h>
#include <commdlg.h>
#include <commctrl.h>
#include "Text3D.h"
#include "Resource.h"
#include "dxutil.h"
CTextScreensaver* g_pMyTextScreensaver = NULL;
#define BUF_SIZE 255
TCHAR g_szSectName[BUF_SIZE];
TCHAR g_szFname[BUF_SIZE];
//-----------------------------------------------------------------------------
// Name: WinMain()
// Desc: Entry point to the program. Initializes everything, and goes into a
// message-processing loop. Idle time is used to render the scene.
//-----------------------------------------------------------------------------
INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR, INT )
{
HRESULT hr;
CTextScreensaver textSS;
if( FAILED( hr = textSS.Create( hInst ) ) )
{
textSS.DisplayErrorMsg( hr );
return 0;
}
return textSS.Run();
}
//-----------------------------------------------------------------------------
// Name: LoadTextureFromResource()
// Desc:
//-----------------------------------------------------------------------------
HRESULT LoadTextureFromResource( LPDIRECT3DDEVICE8 pd3dDevice,
TCHAR* strRes, TCHAR* strResType, LPDIRECT3DTEXTURE8* ppTex )
{
HRESULT hr;
HMODULE hModule = NULL;
HRSRC rsrc;
HGLOBAL hgData;
LPVOID pvData;
DWORD cbData;
rsrc = FindResource( hModule, strRes, strResType );
if( rsrc != NULL )
{
cbData = SizeofResource( hModule, rsrc );
if( cbData > 0 )
{
hgData = LoadResource( hModule, rsrc );
if( hgData != NULL )
{
pvData = LockResource( hgData );
if( pvData != NULL )
{
if( FAILED( hr = D3DXCreateTextureFromFileInMemory( pd3dDevice,
pvData, cbData, ppTex ) ) )
{
return hr;
}
}
}
}
}
if( *ppTex == NULL)
return E_FAIL;
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: CTextScreensaver()
// Desc: Constructor
//-----------------------------------------------------------------------------
CTextScreensaver::CTextScreensaver()
{
g_pMyTextScreensaver = this;
LoadString( NULL, IDS_DESCRIPTION, m_strWindowTitle, 200 );
InitCommonControls();
ZeroMemory( m_DeviceObjects, sizeof(m_DeviceObjects) );
m_hFont = NULL;
m_bUseDepthBuffer = TRUE;
m_dwMinDepthBits = 16;
m_floatrect.xSize = 0.0f;
lstrcpy( m_strRegPath, TEXT("Software\\Microsoft\\Screensavers\\Text3D") );
m_fAngleX = 0.0f;
m_fAngleY = 0.0f;
m_fAngleZ = 0.0f;
m_dwMeshUpdateCounter = 0;
srand((UINT)time(NULL)); // seed random number generator
}
//-----------------------------------------------------------------------------
// Name: RegisterSoftwareDevice()
// Desc: This can register the D3D8RGBRasterizer or any other
// pluggable software rasterizer.
//-----------------------------------------------------------------------------
HRESULT CTextScreensaver::RegisterSoftwareDevice()
{
m_pD3D->RegisterSoftwareDevice( D3D8RGBRasterizer );
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: FrameMove()
// Desc: Called once per frame, the call is the entry point for animating
// the scene.
//-----------------------------------------------------------------------------
HRESULT CTextScreensaver::FrameMove()
{
DWORD tick = GetTickCount();
DWORD elapsed = tick - m_dwLastTick;
m_dwLastTick = tick;
// update floatrect
RECT rcBounceBounds;
if( m_floatrect.xSize == 0.0f )
{
// Initialize floatrect
RECT rcBounds;
DWORD dwParentWidth;
DWORD dwParentHeight;
rcBounds = m_rcRenderTotal;
dwParentWidth = rcBounds.right - rcBounds.left;
dwParentHeight = rcBounds.bottom - rcBounds.top;
FLOAT sizeFact;
FLOAT sizeScale;
DWORD size;
sizeScale = m_dwSize / 10.0f;
sizeFact = 0.25f + (0.75f * sizeScale); // range 25-100%
size = (DWORD) (sizeFact * ( dwParentWidth > dwParentHeight ? dwParentHeight : dwParentWidth ) );
if( size > dwParentWidth )
size = dwParentWidth;
if( size > dwParentHeight )
size = dwParentHeight;
// Start floatrect centered on first RenderUnit's screen
if( !m_bWindowed )
{
INT iMonitor = m_RenderUnits[0].iMonitor;
rcBounds = m_Monitors[iMonitor].rcScreen;
}
m_floatrect.xMin = rcBounds.left + ((rcBounds.right - rcBounds.left) - size) / 2.0f;
m_floatrect.yMin = rcBounds.top + ((rcBounds.bottom - rcBounds.top) - size) / 2.0f;
m_floatrect.xSize = (FLOAT)size;
m_floatrect.ySize = (FLOAT)size;
m_floatrect.xVel = 0.01f * (FLOAT) size;
if( rand() % 2 == 0 )
m_floatrect.xVel = -m_floatrect.xVel;
m_floatrect.yVel = 0.01f * (FLOAT) size;
if( rand() % 2 == 0 )
m_floatrect.yVel = -m_floatrect.yVel;
}
rcBounceBounds = m_rcRenderTotal;
FLOAT xMinOld = m_floatrect.xMin;
FLOAT yMinOld = m_floatrect.yMin;
m_floatrect.xMin += m_floatrect.xVel * 20.0f * m_fElapsedTime;
m_floatrect.yMin += m_floatrect.yVel * 20.0f * m_fElapsedTime;
if( m_floatrect.xVel < 0 && m_floatrect.xMin < rcBounceBounds.left ||
m_floatrect.xVel > 0 && (m_floatrect.xMin + m_floatrect.xSize) > rcBounceBounds.right )
{
m_floatrect.xMin = xMinOld; // undo last move
m_floatrect.xVel = -m_floatrect.xVel; // change direction
}
if( m_floatrect.yVel < 0 && m_floatrect.yMin < rcBounceBounds.top ||
m_floatrect.yVel > 0 && (m_floatrect.yMin + m_floatrect.ySize) > rcBounceBounds.bottom )
{
m_floatrect.yMin = yMinOld; // undo last move
m_floatrect.yVel = -m_floatrect.yVel; // change direction
}
UpdateAngles( elapsed );
if ( m_bDisplayTime )
{
if ( UpdateTimeString( m_szDisplayString ) )
{
m_dwMeshUpdateCounter++; // provoke a mesh update at render tiem
}
}
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: Render()
// Desc: Called once per frame, the call is the entry point for 3d
// rendering. This function sets up render states, clears the
// viewport, and renders the scene.
//-----------------------------------------------------------------------------
HRESULT CTextScreensaver::Render()
{
D3DVIEWPORT8 vp;
// First, clear the entire back buffer to the background color
vp.X = 0;
vp.Y = 0;
vp.Width = m_rcRenderCurDevice.right - m_rcRenderCurDevice.left;
vp.Height = m_rcRenderCurDevice.bottom - m_rcRenderCurDevice.top;
vp.MinZ = 0.0f;
vp.MaxZ = 1.0f;
m_pd3dDevice->SetViewport( &vp );
m_pd3dDevice->Clear( 0L, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xff000000, 1.0f, 0L );
// Now determine what part of the floatrect, if any, intersects the current screen
RECT rcFloatThisScreen;
RECT rcFloatThisScreenClipped;
rcFloatThisScreen.left = (INT)m_floatrect.xMin;
rcFloatThisScreen.top = (INT)m_floatrect.yMin;
rcFloatThisScreen.right = rcFloatThisScreen.left + (INT)m_floatrect.xSize;
rcFloatThisScreen.bottom = rcFloatThisScreen.top + (INT)m_floatrect.ySize;
if( !IntersectRect(&rcFloatThisScreenClipped, &rcFloatThisScreen, &m_rcRenderCurDevice) )
{
return S_OK; // no intersection, so nothing further to render on this screen
}
// Convert rcFloatThisScreen from screen to window coordinates
OffsetRect(&rcFloatThisScreen, -m_rcRenderCurDevice.left, -m_rcRenderCurDevice.top);
OffsetRect(&rcFloatThisScreenClipped, -m_rcRenderCurDevice.left, -m_rcRenderCurDevice.top);
// Now set up the viewport to render to the clipped rect
vp.X = rcFloatThisScreenClipped.left;
vp.Y = rcFloatThisScreenClipped.top;
vp.Width = rcFloatThisScreenClipped.right - rcFloatThisScreenClipped.left;
vp.Height = rcFloatThisScreenClipped.bottom - rcFloatThisScreenClipped.top;
vp.MinZ = 0.0f;
vp.MaxZ = 1.0f;
m_pd3dDevice->SetViewport( &vp );
// m_pd3dDevice->Clear( 0L, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0xff0000ff, 1.0f, 0L );
// Now set up the projection matrix to only render the onscreen part of the
// rect to the viewport
D3DXMATRIX matProj;
FLOAT l,r,b,t;
l = -0.8f;
r = 0.8f;
b = 0.8f;
t = -0.8f;
FLOAT cxUnclipped = (rcFloatThisScreen.right + rcFloatThisScreen.left) / 2.0f;
FLOAT cyUnclipped = (rcFloatThisScreen.bottom + rcFloatThisScreen.top) / 2.0f;
l *= (rcFloatThisScreenClipped.left - cxUnclipped) / (rcFloatThisScreen.left - cxUnclipped);
r *= (rcFloatThisScreenClipped.right - cxUnclipped) / (rcFloatThisScreen.right - cxUnclipped);
t *= (rcFloatThisScreenClipped.top - cyUnclipped) / (rcFloatThisScreen.top - cyUnclipped);
b *= (rcFloatThisScreenClipped.bottom - cyUnclipped) / (rcFloatThisScreen.bottom - cyUnclipped);
D3DXMatrixPerspectiveOffCenterLH( &matProj, l, r, t, b, 1.0f, 50.0f );
m_pd3dDevice->SetTransform( D3DTS_PROJECTION , &matProj );
// Mesh updates happen in Render() instead of FrameMove() since they
// are per-device
if( m_pDeviceObjects->m_dwMeshUpdateCounter != m_dwMeshUpdateCounter )
{
BuildTextMesh( m_szDisplayString );
m_pDeviceObjects->m_dwMeshUpdateCounter = m_dwMeshUpdateCounter;
}
m_pd3dDevice->BeginScene();
// Set world matrix
D3DXMATRIX rotx,roty,rotz,trans,trans2;
D3DXMatrixTranslation( &trans , m_fTextOffsetX , m_fTextOffsetY , 0.25f );
D3DXMatrixRotationX( &rotx , m_fAngleX );
D3DXMatrixRotationY( &roty , m_fAngleY );
D3DXMatrixRotationZ( &rotz , m_fAngleZ );
D3DXMatrixTranslation( &trans2, 0, 0, 1.5f + (m_fTextMaxX - m_fTextMinX) );
m_matWorld = trans * rotx * roty * rotz * trans2;
m_pd3dDevice->SetTransform( D3DTS_WORLDMATRIX(0) , &m_matWorld );
// Set other per-frame states
SetPerFrameStates();
// Draw mesh
m_pDeviceObjects->m_pObject->DrawSubset( 0 );
m_pd3dDevice->EndScene();
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: RestoreDeviceObjects()
// Desc:
//-----------------------------------------------------------------------------
HRESULT CTextScreensaver::RestoreDeviceObjects()
{
HRESULT rc;
// Set up sensible view matrix
D3DXMatrixLookAtLH( &m_matView , &D3DXVECTOR3(0,0,0) , &D3DXVECTOR3(0,0,1) , &D3DXVECTOR3(0,1,0) );
m_pd3dDevice->SetTransform( D3DTS_VIEW , &m_matView );
// Set some basic renderstates
m_pd3dDevice->SetRenderState( D3DRS_ZENABLE , TRUE );
m_pd3dDevice->SetRenderState( D3DRS_ZWRITEENABLE , D3DZB_TRUE );
m_pd3dDevice->SetRenderState( D3DRS_ZFUNC , D3DCMP_LESSEQUAL );
m_pd3dDevice->SetRenderState( D3DRS_DITHERENABLE , TRUE );
m_pd3dDevice->SetRenderState( D3DRS_SPECULARENABLE , m_bSpecular );
// Create the GDI font object
LONG h = m_Font.lfHeight;
m_Font.lfHeight = 100;
m_hFont = CreateFontIndirect( &m_Font );
m_Font.lfHeight = h;
if ( m_hFont == NULL )
return E_FAIL;
// Initialise time string
if ( m_bDisplayTime )
UpdateTimeString( m_szDisplayString );
// Make mesh for text string
if ( FAILED(rc = BuildTextMesh( m_szDisplayString )) )
return rc;
// Update offsets for mesh
m_fTextOffsetX = (m_fTextMinX + m_fTextMaxX) * -0.5f;
m_fTextOffsetY = (m_fTextMinY + m_fTextMaxY) * -0.5f;
// Load appropriate texture (if any)
switch ( m_SurfType )
{
case color:
m_pDeviceObjects->m_pTexture = NULL;
break;
case environment:
if ( m_bUseCustomEnvironment )
{
m_pDeviceObjects->m_pTexture = CreateTextureFromFile( m_szCustomEnvironment );
}
if ( m_pDeviceObjects->m_pTexture == NULL )
{
LoadTextureFromResource( m_pd3dDevice, MAKEINTRESOURCE(IDB_SPHEREMAP),
TEXT("JPG"), &m_pDeviceObjects->m_pTexture );
}
break;
case texture:
if ( m_bUseCustomTexture )
{
m_pDeviceObjects->m_pTexture = CreateTextureFromFile( m_szCustomTexture );
}
if ( m_pDeviceObjects->m_pTexture == NULL )
{
LoadTextureFromResource( m_pd3dDevice, MAKEINTRESOURCE(IDB_TEXTURE),
TEXT("JPG"), &m_pDeviceObjects->m_pTexture );
}
break;
default:
return E_FAIL;
}
// Set per-frame states
SetPerFrameStates();
m_dwLastTick = GetTickCount();
return S_OK;
}
//**********************************************************************************
VOID CTextScreensaver::SetPerFrameStates()
{
m_pd3dDevice->SetTexture( 0 , m_pDeviceObjects->m_pTexture );
// Set up texture pipeline
if ( m_SurfType == color )
{
m_pd3dDevice->SetTextureStageState( 0 , D3DTSS_COLOROP , D3DTOP_SELECTARG1 );
m_pd3dDevice->SetTextureStageState( 0 , D3DTSS_COLORARG1 , D3DTA_DIFFUSE );
m_pd3dDevice->SetTextureStageState( 0 , D3DTSS_COLORARG2 , D3DTA_DIFFUSE );
}
else
{
m_pd3dDevice->SetTextureStageState( 0 , D3DTSS_COLOROP , D3DTOP_MODULATE );
m_pd3dDevice->SetTextureStageState( 0 , D3DTSS_COLORARG1 , D3DTA_TEXTURE );
m_pd3dDevice->SetTextureStageState( 0 , D3DTSS_COLORARG2 , D3DTA_DIFFUSE );
}
m_pd3dDevice->SetTextureStageState( 0 , D3DTSS_ALPHAOP , D3DTOP_DISABLE );
m_pd3dDevice->SetTextureStageState( 0 , D3DTSS_MAGFILTER , D3DTEXF_LINEAR );
m_pd3dDevice->SetTextureStageState( 0 , D3DTSS_MINFILTER , D3DTEXF_LINEAR );
m_pd3dDevice->SetTextureStageState( 0 , D3DTSS_MIPFILTER , D3DTEXF_LINEAR );
m_pd3dDevice->SetTextureStageState( 0 , D3DTSS_ADDRESSU , D3DTADDRESS_WRAP );
m_pd3dDevice->SetTextureStageState( 0 , D3DTSS_ADDRESSV , D3DTADDRESS_WRAP );
m_pd3dDevice->SetTextureStageState( 1 , D3DTSS_COLOROP , D3DTOP_DISABLE );
m_pd3dDevice->SetTextureStageState( 1 , D3DTSS_ALPHAOP , D3DTOP_DISABLE );
// Set up lighting
m_pd3dDevice->SetRenderState( D3DRS_LIGHTING , TRUE );
if ( !m_bSpecular )
m_pd3dDevice->SetRenderState( D3DRS_AMBIENT , 0x646464 );
else
m_pd3dDevice->SetRenderState( D3DRS_AMBIENT , 0x464646 );
D3DLIGHT8 light;
light.Type = D3DLIGHT_DIRECTIONAL;
light.Diffuse = D3DXCOLOR(1,1,1,0);
light.Specular = D3DXCOLOR(1.0f, 1.0f, 1.0f, 1.0f);
light.Ambient = D3DXCOLOR(0,0,0,0);
light.Direction = D3DXVECTOR3(0.5,-0.5,1);
light.Position = D3DXVECTOR3(0,0,0);
light.Range = 10000;
light.Falloff = light.Attenuation0 = light.Attenuation1 = light.Attenuation2 = 0;
light.Phi = light.Theta = 0;
m_pd3dDevice->SetLight( 0 , &light );
m_pd3dDevice->LightEnable( 0 , TRUE );
// Set up material
D3DMATERIAL8 mat;
if ( m_SurfType == color )
{
DWORD dwColor;
if( m_bUseCustomColor )
dwColor = m_SurfaceColor;
else
dwColor = 0x00777777;
mat.Diffuse.r = FLOAT(dwColor&0xff)/255.0f;
mat.Diffuse.g = FLOAT((dwColor>>8)&0xff)/255.0f;
mat.Diffuse.b = FLOAT((dwColor>>16)&0xff)/255.0f;
}
else
{
mat.Diffuse = D3DXCOLOR(1,1,1,0);
}
mat.Ambient = mat.Diffuse;
mat.Specular = D3DXCOLOR(1.0f,1.0f,1.0f,0);
mat.Emissive = D3DXCOLOR(0,0,0,0);
mat.Power = 5;
m_pd3dDevice->SetMaterial( &mat );
// Set up texture coordinate generation if we're environment mapping or just force to passthrough
if ( m_SurfType == environment )
{
m_pd3dDevice->SetTextureStageState( 0 , D3DTSS_TEXCOORDINDEX , D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR );
m_pd3dDevice->SetTextureStageState( 0 , D3DTSS_TEXTURETRANSFORMFLAGS , D3DTTFF_COUNT2 );
D3DXMATRIX envmat;
D3DXMatrixIdentity( &envmat );
envmat._11 = envmat._22 = 0.5f;
envmat._31 = envmat._32 = 0.5f;
m_pd3dDevice->SetTransform( D3DTS_TEXTURE0 , &envmat );
}
else
{
D3DXMATRIX matWorldView;
D3DXMATRIX matWorldViewInv;
matWorldView = m_matWorld * m_matView;
D3DXMatrixInverse( &matWorldViewInv, NULL, &matWorldView );
m_pd3dDevice->SetTransform( D3DTS_TEXTURE0, &matWorldViewInv );
m_pd3dDevice->SetTextureStageState( 0 , D3DTSS_TEXCOORDINDEX , D3DTSS_TCI_CAMERASPACEPOSITION );
m_pd3dDevice->SetTextureStageState( 0 , D3DTSS_TEXTURETRANSFORMFLAGS , D3DTTFF_COUNT2 );
}
m_pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE , FALSE );
m_pd3dDevice->SetRenderState( D3DRS_ALPHATESTENABLE , FALSE );
m_pd3dDevice->SetRenderState( D3DRS_SPECULARENABLE , m_bSpecular );
m_pd3dDevice->SetRenderState( D3DRS_WRAP0 , D3DWRAP_U|D3DWRAP_V );
m_pd3dDevice->SetRenderState( D3DRS_POINTSPRITEENABLE , FALSE );
m_pd3dDevice->SetTexture( 0, m_pDeviceObjects->m_pTexture );
}
//-----------------------------------------------------------------------------
// Name: InvalidateDeviceObjects()
// Desc:
//-----------------------------------------------------------------------------
HRESULT CTextScreensaver::InvalidateDeviceObjects()
{
SAFE_RELEASE(m_pDeviceObjects->m_pTexture);
SAFE_RELEASE(m_pDeviceObjects->m_pObject);
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: ConfirmDevice()
// Desc:
//-----------------------------------------------------------------------------
HRESULT CTextScreensaver::ConfirmDevice(D3DCAPS8* pCaps, DWORD dwBehavior,
D3DFORMAT fmtBackBuffer)
{
// Need D3DVTXPCAPS_TEXGEN for D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR
if( ( ( dwBehavior & D3DCREATE_HARDWARE_VERTEXPROCESSING ) ||
( dwBehavior & D3DCREATE_MIXED_VERTEXPROCESSING ) ) &&
( pCaps->VertexProcessingCaps & D3DVTXPCAPS_TEXGEN ) == 0 )
{
return E_FAIL;
}
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: SetDevice()
// Desc:
//-----------------------------------------------------------------------------
VOID CTextScreensaver::SetDevice( UINT iDevice )
{
m_pDeviceObjects = &m_DeviceObjects[iDevice];
}
//***************************************************************************************
IDirect3DTexture8* CTextScreensaver::CreateTextureFromFile( const TCHAR* filename )
{
IDirect3DTexture8* texture;
if ( FAILED(D3DXCreateTextureFromFile( m_pd3dDevice , filename , &texture )) )
return NULL;
else
return texture;
}
//***************************************************************************************
HRESULT CTextScreensaver::BuildTextMesh( const TCHAR* text )
{
// Release any old text mesh we built
SAFE_RELEASE(m_pDeviceObjects->m_pObject);
// Create temporary DC and select the correct font into it
HDC hdc = CreateDC( TEXT("DISPLAY") , NULL , NULL , NULL );
SelectObject( hdc , m_hFont );
TCHAR szText[MAX_DISPLAY_STRING+1];
lstrcpy( szText, text );
// Build new mesh
FLOAT max_deviation = 5.0f / FLOAT(m_dwMeshQuality+10);
GLYPHMETRICSFLOAT metrics[MAX_DISPLAY_STRING+1];
HRESULT rc;
rc = D3DXCreateText( m_pd3dDevice , hdc , szText , max_deviation, 0.5f , &m_pDeviceObjects->m_pObject , NULL, metrics );
if( FAILED( rc ) )
{
// We might have failed because the string had no glyphs, so try
// the default text instead
LoadString( NULL, IDS_DEFAULTTEXT, szText, MAX_DISPLAY_STRING );
rc = D3DXCreateText( m_pd3dDevice , hdc , szText , max_deviation, 0.5f , &m_pDeviceObjects->m_pObject , NULL, metrics );
}
// Delete temporary DC
DeleteDC( hdc );
if ( FAILED(rc) )
return rc;
// Compute the bounding box for the mesh by stepping through the glyph metrics structures
int len = lstrlen( szText );
m_fTextMinX = 1000000;
m_fTextMaxX = -1000000;
m_fTextMinY = 1000000;
m_fTextMaxY = -1000000;
FLOAT originx = 0;
FLOAT originy = 0;
GLYPHMETRICSFLOAT* pglyph = metrics;
for ( int i = 0 ; i < len ; i++ , pglyph++ )
{
if ( (pglyph->gmfptGlyphOrigin.x + originx) < m_fTextMinX )
m_fTextMinX = (pglyph->gmfptGlyphOrigin.x + originx);
if ( (pglyph->gmfptGlyphOrigin.x + originx + pglyph->gmfBlackBoxX) > m_fTextMaxX )
m_fTextMaxX = (pglyph->gmfptGlyphOrigin.x + originx + pglyph->gmfBlackBoxX);
if ( (pglyph->gmfptGlyphOrigin.y + originy) > m_fTextMaxY )
m_fTextMaxY = (pglyph->gmfptGlyphOrigin.y + originy);
if ( (pglyph->gmfptGlyphOrigin.y + originy - pglyph->gmfBlackBoxY) < m_fTextMinY )
m_fTextMinY = (pglyph->gmfptGlyphOrigin.y + originy - pglyph->gmfBlackBoxY);
originx += pglyph->gmfCellIncX;
originy += pglyph->gmfCellIncY;
}
return S_OK;
}
//*********************************************************************************
VOID CTextScreensaver::UpdateAngles( DWORD elapsed )
{
static FLOAT x,y,z,t;
const FLOAT pi2 = 3.1415926536f * 2.0f;
FLOAT inc = FLOAT(elapsed * m_dwRotationSpeed);
switch ( m_RotType )
{
case spin:
y += inc * 0.00002f;
break;
case seesaw:
t += inc * 0.000025f;
y = (FLOAT(sin((t * pi2))) * 0.17f) + 1.0f;
break;
case wobble:
t += inc * 0.000025f;
y = (FLOAT(sin((t * pi2))) * 0.17f) + 1.0f;
z = (FLOAT(cos((t * pi2))) * 0.09f) + 1.0f;
break;
case tumble:
x += inc * 0.000004f;
y += inc * 0.000018f;
z += inc * 0.000007f;
break;
}
x = x - int(x);
y = y - int(y);
z = z - int(z);
m_fAngleX = x * pi2;
m_fAngleY = y * pi2;
m_fAngleZ = z * pi2;
}
//***************************************************************************************
BOOL CTextScreensaver::UpdateTimeString( TCHAR* string )
{
TCHAR str[30];
GetTimeFormat( LOCALE_USER_DEFAULT, 0, NULL, NULL, str, 30 );
if ( lstrcmp( string , str ) )
{
lstrcpy( string , str );
return TRUE;
}
return FALSE;
}
//-----------------------------------------------------------------------------
// Name: ReadSettings()
// Desc:
//-----------------------------------------------------------------------------
VOID CTextScreensaver::ReadSettings()
{
HKEY hkey;
DWORD dwType = REG_DWORD;
DWORD dwLength = sizeof(DWORD);
// Defaults
LoadString( NULL, IDS_DEFAULTTEXT, m_szDisplayString, MAX_DISPLAY_STRING );
m_Font.lfHeight = 96;
m_Font.lfWidth = 0;
m_Font.lfEscapement = 0;
m_Font.lfOrientation = 0;
m_Font.lfWeight = 0;
m_Font.lfItalic = 0;
m_Font.lfUnderline = 0;
m_Font.lfStrikeOut = 0;
m_Font.lfCharSet = DEFAULT_CHARSET;
m_Font.lfOutPrecision = OUT_DEFAULT_PRECIS;
m_Font.lfClipPrecision = OUT_DEFAULT_PRECIS;
m_Font.lfQuality = DEFAULT_QUALITY;
m_Font.lfPitchAndFamily = DEFAULT_PITCH|FF_DONTCARE;
LoadString( NULL, IDS_FONT, m_Font.lfFaceName, LF_FACESIZE );
m_bDisplayTime = FALSE;
m_dwMeshQuality = 500;
m_SurfType = SurfType(environment);
m_bSpecular = TRUE;
m_dwRotationSpeed = 10;
m_dwSize = 10;
m_RotType = RotType(spin);
m_SurfaceColor = 0x00777777;
m_bUseCustomColor = FALSE;
m_bUseCustomTexture = FALSE;
m_bUseCustomEnvironment = FALSE;
lstrcpy( m_szCustomTexture, TEXT("") );
lstrcpy( m_szCustomEnvironment, TEXT("") );
// Read OpenGL settings first, so OS upgrade cases work
ss_ReadSettings();
if( ERROR_SUCCESS == RegCreateKeyEx( HKEY_CURRENT_USER, m_strRegPath,
0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkey, NULL ) )
{
dwLength = (MAX_DISPLAY_STRING + 1) * sizeof(TCHAR);
RegQueryValueEx( hkey, TEXT("DisplayString"), NULL, &dwType, (BYTE*)m_szDisplayString, &dwLength );
dwLength = sizeof(DWORD);
RegQueryValueEx( hkey, TEXT("FontHeight"), NULL, &dwType, (BYTE*)&m_Font.lfHeight, &dwLength );
RegQueryValueEx( hkey, TEXT("FontWeight"), NULL, &dwType, (BYTE*)&m_Font.lfWeight, &dwLength );
RegQueryValueEx( hkey, TEXT("FontItalic"), NULL, &dwType, (BYTE*)&m_Font.lfItalic, &dwLength );
RegQueryValueEx( hkey, TEXT("FontCharSet"), NULL, &dwType, (BYTE*)&m_Font.lfCharSet, &dwLength );
RegQueryValueEx( hkey, TEXT("FontPitchFamily"), NULL, &dwType, (BYTE*)&m_Font.lfPitchAndFamily, &dwLength );
dwLength = sizeof(m_Font.lfFaceName);
RegQueryValueEx( hkey, TEXT("FontFace"), NULL, &dwType, (BYTE*)m_Font.lfFaceName, &dwLength );
dwLength = sizeof(DWORD);
RegQueryValueEx( hkey, TEXT("DisplayTime"), NULL, &dwType, (BYTE*)&m_bDisplayTime, &dwLength );
RegQueryValueEx( hkey, TEXT("MeshQuality"), NULL, &dwType, (BYTE*)&m_dwMeshQuality, &dwLength );
if ( m_dwMeshQuality > 1000 )
m_dwMeshQuality = 1000;
RegQueryValueEx( hkey, TEXT("SurfaceType"), NULL, &dwType, (BYTE*)&m_SurfType, &dwLength );
RegQueryValueEx( hkey, TEXT("Specular"), NULL, &dwType, (BYTE*)&m_bSpecular, &dwLength );
RegQueryValueEx( hkey, TEXT("RotationSpeed"), NULL, &dwType, (BYTE*)&m_dwRotationSpeed, &dwLength );
RegQueryValueEx( hkey, TEXT("Size"), NULL, &dwType, (BYTE*)&m_dwSize, &dwLength );
if( m_dwSize < 1 )
m_dwSize = 1;
if( m_dwSize > 10 )
m_dwSize = 10;
RegQueryValueEx( hkey, TEXT("RotationStyle"), NULL, &dwType, (BYTE*)&m_RotType, &dwLength );
RegQueryValueEx( hkey, TEXT("SurfaceColor"), NULL, &dwType, (BYTE*)&m_SurfaceColor, &dwLength );
RegQueryValueEx( hkey, TEXT("UseCustomColor"), NULL, &dwType, (BYTE*)&m_bUseCustomColor, &dwLength );
RegQueryValueEx( hkey, TEXT("UseCustomTexture"), NULL, &dwType, (BYTE*)&m_bUseCustomTexture, &dwLength );
RegQueryValueEx( hkey, TEXT("UseCustomEnvironment"), NULL, &dwType, (BYTE*)&m_bUseCustomEnvironment, &dwLength );
dwLength = sizeof(m_szCustomTexture);
RegQueryValueEx( hkey, TEXT("CustomTexture"), NULL, &dwType, (BYTE*)m_szCustomTexture, &dwLength );
dwLength = sizeof(m_szCustomEnvironment);
RegQueryValueEx( hkey, TEXT("CustomEnvironment"), NULL, &dwType, (BYTE*)m_szCustomEnvironment, &dwLength );
ReadScreenSettings( hkey );
RegCloseKey( hkey );
}
}
//-----------------------------------------------------------------------------
// Name: ss_ReadSettings()
// Desc:
//-----------------------------------------------------------------------------
VOID CTextScreensaver::ss_ReadSettings()
{
int options;
int optMask = 1;
// Get registry settings
if( ss_RegistrySetup( IDS_SAVERNAME, IDS_INIFILE ) )
{
// get demo type
int demoType = ss_GetRegistryInt( IDS_DEMOTYPE, 0 );
if( demoType == 1 )
{
m_bDisplayTime = TRUE;
}
// get rotation style
m_RotType = (RotType) (ss_GetRegistryInt( IDS_ROTSTYLE, 0 ) + 1); // add 1
if( m_RotType == 1 ) // 1==none,2=right,3=right,4=random->spin
m_RotType = none;
if( m_RotType > 3 )
m_RotType = spin;
// get tesselation
m_dwMeshQuality = ss_GetRegistryInt( IDS_TESSELATION, 0 ); // 0-100
m_dwMeshQuality = m_dwMeshQuality*10 + 1; // 1-1000
if ( m_dwMeshQuality > 1000 )
m_dwMeshQuality = 1000;
// get size
m_dwSize = ss_GetRegistryInt( IDS_SIZE, 0 ); // 0-100
m_dwSize = (unsigned) ( ((m_dwSize / 100.0f) * 90.0f + 10.0f) / 10.0f ); // 1-10
// get speed
m_dwRotationSpeed = ss_GetRegistryInt( IDS_SPEED, 0 ); // 0-100
m_dwRotationSpeed = (unsigned) ( ((m_dwRotationSpeed / 100.0f) * 190.0f + 10.0f) / 10.0f ); // 1-20
// get font, attributes, and charset
ss_GetRegistryString( IDS_FONT_REG, TEXT(""),
m_Font.lfFaceName, LF_FACESIZE );
options = ss_GetRegistryInt( IDS_FONT_ATTRIBUTES, 0 );
if( options >= 0 )
{
optMask = 1;
m_Font.lfWeight = ((options & optMask) != 0) ? FW_BOLD : FW_NORMAL;
optMask <<=1;
m_Font.lfItalic = ((options & optMask) != 0) ? (BYTE) 1 : 0;
}
m_Font.lfCharSet = (BYTE)ss_GetRegistryInt( IDS_CHARSET, 0 );
// get display string
ss_GetRegistryString( IDS_TEXT, TEXT(""), m_szDisplayString, MAX_DISPLAY_STRING );
m_SurfType = (SurfType) ss_GetRegistryInt( IDS_SURFSTYLE, color );
if( m_SurfType >= 1 )
m_SurfType = texture;
// Is there a texture specified in the registry that overrides the default?
ss_GetRegistryString( IDS_TEXTURE, NULL, m_szCustomTexture, MAX_PATH );
if( lstrlen( m_szCustomTexture ) > 0 )
{
m_bUseCustomTexture = TRUE;
}
}
}
//-----------------------------------------------------------------------------
// Name: ss_GetRegistryString()
// Desc:
//-----------------------------------------------------------------------------
BOOL CTextScreensaver::ss_RegistrySetup( int section, int file )
{
if( LoadString(m_hInstance, section, g_szSectName, BUF_SIZE) &&
LoadString(m_hInstance, file, g_szFname, BUF_SIZE) )
{
TCHAR pBuffer[100];
DWORD dwRealSize = GetPrivateProfileSection( g_szSectName, pBuffer, 100, g_szFname );
if( dwRealSize > 0 )
return TRUE;
}
return FALSE;
}
//-----------------------------------------------------------------------------
// Name: ss_GetRegistryInt()
// Desc:
//-----------------------------------------------------------------------------
int CTextScreensaver::ss_GetRegistryInt( int name, int iDefault )
{
TCHAR szItemName[BUF_SIZE];
if( LoadString( m_hInstance, name, szItemName, BUF_SIZE ) )
return GetPrivateProfileInt(g_szSectName, szItemName, iDefault, g_szFname);
return 0;
}
//-----------------------------------------------------------------------------
// Name: ss_GetRegistryString()
// Desc:
//-----------------------------------------------------------------------------
VOID CTextScreensaver::ss_GetRegistryString( int name, LPTSTR lpDefault,
LPTSTR lpDest, int bufSize )
{
TCHAR szItemName[BUF_SIZE];
if( LoadString( m_hInstance, name, szItemName, BUF_SIZE ) )
GetPrivateProfileString(g_szSectName, szItemName, lpDefault, lpDest,
bufSize, g_szFname);
return;
}
//-----------------------------------------------------------------------------
// Name: DoConfig()
// Desc:
//-----------------------------------------------------------------------------
VOID CTextScreensaver::DoConfig()
{
ReadSettings();
DialogBox( NULL, MAKEINTRESOURCE( IDD_SETTINGS ),
m_hWndParent, (DLGPROC)SettingsDialogProcStub );
}
BOOL WINAPI CTextScreensaver::SettingsDialogProcStub( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam )
{
return g_pMyTextScreensaver->SettingsDialogProc( hDlg, message, wParam, lParam );
};
BOOL CTextScreensaver::SettingsDialogProc( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam )
{
switch ( message )
{
case WM_INITDIALOG:
InitItems( hDlg );
return FALSE;
case WM_COMMAND:
switch ( HIWORD(wParam) )
{
case BN_CLICKED:
{
switch( LOWORD(wParam) )
{
case IDOK:
ExtractAndWriteSettings( hDlg );
EndDialog( hDlg, TRUE );
break;
case IDCANCEL:
ReadSettings();
EndDialog( hDlg, FALSE );
break;
case IDC_SELECT_FONT:
SelectFont( hDlg );
break;
case IDC_RADIO_TIME:
EnableWindow( GetDlgItem( hDlg , IDC_DISPLAY_STRING ) , FALSE );
break;
case IDC_RADIO_TEXT:
EnableWindow( GetDlgItem( hDlg , IDC_DISPLAY_STRING ) , TRUE );
break;
case IDC_RADIO_COLOR:
case IDC_RADIO_TEXTURE:
case IDC_RADIO_REFLECTION:
case IDC_USE_CUSTOM_COLOR:
case IDC_USE_CUSTOM_TEXTURE:
case IDC_USE_CUSTOM_ENVIRONMENT:
{
if( IsDlgButtonChecked( hDlg, IDC_RADIO_COLOR ) )
m_SurfType = color;
else if( IsDlgButtonChecked( hDlg, IDC_RADIO_TEXTURE ) )
m_SurfType = texture;
else if( IsDlgButtonChecked( hDlg, IDC_RADIO_REFLECTION ) )
m_SurfType = environment;
EnableTextureWindows( hDlg , SurfType(m_SurfType) );
}
break;
case IDC_SURFACE_COLOR:
SelectSurfaceColor( hDlg );
break;
case IDC_BROWSE_TEXTURE:
SelectCustomTexture( hDlg );
break;
case IDC_BROWSE_ENVIRONMENT:
SelectCustomEnvironment( hDlg );
break;
case IDC_SCREENSETTINGS:
DoScreenSettingsDialog( hDlg );
break;
}
}
break;
case EN_CHANGE:
if ( LOWORD(wParam) == IDC_DISPLAY_STRING )
{
GetDlgItemText( hDlg , IDC_DISPLAY_STRING , m_szDisplayString , MAX_DISPLAY_STRING );
}
break;
}
return FALSE;
}
return FALSE;
}
VOID CTextScreensaver::InitItems( HWND hDlg )
{
TCHAR sz[100];
// Set the limit of the text box
SendDlgItemMessage( hDlg, IDC_DISPLAY_STRING, EM_SETLIMITTEXT, MAX_DISPLAY_STRING, 0 );
// Set the text string
SetDlgItemText( hDlg, IDC_DISPLAY_STRING, m_szDisplayString );
// Set the radio button for time/text display
if ( m_bDisplayTime )
{
EnableWindow( GetDlgItem( hDlg, IDC_DISPLAY_STRING ), FALSE );
CheckRadioButton( hDlg, IDC_RADIO_TIME, IDC_RADIO_TEXT, IDC_RADIO_TIME );
}
else
{
EnableWindow( GetDlgItem( hDlg, IDC_DISPLAY_STRING ), TRUE );
CheckRadioButton( hDlg, IDC_RADIO_TIME, IDC_RADIO_TEXT, IDC_RADIO_TEXT );
}
switch( m_SurfType )
{
case color:
CheckRadioButton( hDlg, IDC_RADIO_COLOR, IDC_RADIO_REFLECTION, IDC_RADIO_COLOR );
break;
case texture:
CheckRadioButton( hDlg, IDC_RADIO_COLOR, IDC_RADIO_REFLECTION, IDC_RADIO_TEXTURE );
break;
case environment:
CheckRadioButton( hDlg, IDC_RADIO_COLOR, IDC_RADIO_REFLECTION, IDC_RADIO_REFLECTION );
break;
}
// Check/uncheck the specular box
SendDlgItemMessage( hDlg, IDC_SPECULAR, BM_SETCHECK,
m_bSpecular ? BST_CHECKED : BST_UNCHECKED, 0 );
// Enable/disable surface color button
EnableWindow( GetDlgItem( hDlg, IDC_SURFACE_COLOR ), m_SurfType == color );
// Check/uncheck the custom texture boxes
SendDlgItemMessage( hDlg, IDC_USE_CUSTOM_COLOR, BM_SETCHECK,
m_bUseCustomColor ? BST_CHECKED : BST_UNCHECKED, 0 );
SendDlgItemMessage( hDlg, IDC_USE_CUSTOM_TEXTURE, BM_SETCHECK,
m_bUseCustomTexture ? BST_CHECKED : BST_UNCHECKED, 0 );
SendDlgItemMessage( hDlg, IDC_USE_CUSTOM_ENVIRONMENT, BM_SETCHECK,
m_bUseCustomEnvironment ? BST_CHECKED : BST_UNCHECKED, 0 );
// Enable all the texture windows as appropriate
EnableTextureWindows( hDlg, m_SurfType );
// Fill the rotation style combo box
LoadString( NULL, IDS_NONE, sz, 100 );
SendDlgItemMessage( hDlg, IDC_ROTATION_STYLE, CB_ADDSTRING, 0, (LPARAM) sz );
LoadString( NULL, IDS_SPIN, sz, 100 );
SendDlgItemMessage( hDlg, IDC_ROTATION_STYLE, CB_ADDSTRING, 0, (LPARAM) sz );
LoadString( NULL, IDS_SEESAW, sz, 100 );
SendDlgItemMessage( hDlg, IDC_ROTATION_STYLE, CB_ADDSTRING, 0, (LPARAM) sz );
LoadString( NULL, IDS_WOBBLE, sz, 100 );
SendDlgItemMessage( hDlg, IDC_ROTATION_STYLE, CB_ADDSTRING, 0, (LPARAM) sz );
LoadString( NULL, IDS_TUMBLE, sz, 100 );
SendDlgItemMessage( hDlg, IDC_ROTATION_STYLE, CB_ADDSTRING, 0, (LPARAM) sz );
// Set the current rotation style selection
SendDlgItemMessage( hDlg, IDC_ROTATION_STYLE, CB_SETCURSEL, m_RotType, 0 );
// Set up the rotation speed slider
SendDlgItemMessage( hDlg, IDC_ROTATION_SPEED, TBM_SETRANGE, TRUE, MAKELONG(1,20) );
SendDlgItemMessage( hDlg, IDC_ROTATION_SPEED, TBM_SETPOS, TRUE, m_dwRotationSpeed );
// Set up the resolution slider
SendDlgItemMessage( hDlg, IDC_RESOLUTION, TBM_SETRANGE, TRUE, MAKELONG(1,10) );
SendDlgItemMessage( hDlg, IDC_RESOLUTION, TBM_SETPOS, TRUE, m_dwMeshQuality / 100 );
// Set up the size slider
SendDlgItemMessage( hDlg, IDC_VIEWPORTSIZE, TBM_SETRANGE, TRUE, MAKELONG(1,10) );
SendDlgItemMessage( hDlg, IDC_VIEWPORTSIZE, TBM_SETPOS, TRUE, m_dwSize );
}
VOID CTextScreensaver::ExtractAndWriteSettings( HWND hDlg )
{
LRESULT ret;
HKEY hkey = NULL;
m_bSpecular = IsDlgButtonChecked( hDlg, IDC_SPECULAR );
m_bUseCustomColor = IsDlgButtonChecked( hDlg, IDC_USE_CUSTOM_COLOR );
m_bUseCustomTexture = IsDlgButtonChecked( hDlg, IDC_USE_CUSTOM_TEXTURE );
m_bUseCustomEnvironment = IsDlgButtonChecked( hDlg, IDC_USE_CUSTOM_ENVIRONMENT );
if ( (ret = SendDlgItemMessage( hDlg, IDC_ROTATION_STYLE, CB_GETCURSEL, 0, 0 )) != CB_ERR )
m_RotType = RotType(ret);
m_dwSize = (DWORD)SendDlgItemMessage( hDlg, IDC_VIEWPORTSIZE, TBM_GETPOS, 0, 0 );
m_dwRotationSpeed = (DWORD)SendDlgItemMessage( hDlg, IDC_ROTATION_SPEED, TBM_GETPOS, 0, 0 );
m_dwMeshQuality = 100 * (DWORD)SendDlgItemMessage( hDlg, IDC_RESOLUTION, TBM_GETPOS, 0, 0 );
GetDlgItemText( hDlg, IDC_DISPLAY_STRING, m_szDisplayString, MAX_DISPLAY_STRING + 1 );
if ( IsDlgButtonChecked( hDlg, IDC_RADIO_TIME ) )
m_bDisplayTime = TRUE;
else
m_bDisplayTime = FALSE;
if( ERROR_SUCCESS == RegCreateKeyEx( HKEY_CURRENT_USER, m_strRegPath,
0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkey, NULL ) )
{
WriteScreenSettings( hkey );
RegSetValueEx( hkey, TEXT("SurfaceType"), NULL, REG_DWORD, (BYTE*)&m_SurfType, sizeof(DWORD) );
RegSetValueEx( hkey, TEXT("Specular"), NULL, REG_DWORD, (BYTE*)&m_bSpecular, sizeof(DWORD) );
RegSetValueEx( hkey, TEXT("SurfaceColor"), NULL, REG_DWORD, (BYTE*)&m_SurfaceColor, sizeof(DWORD) );
RegSetValueEx( hkey, TEXT("CustomTexture"), NULL, REG_SZ, (BYTE*)&m_szCustomTexture, (lstrlen(m_szCustomTexture) + 1) * sizeof(TCHAR) );
RegSetValueEx( hkey, TEXT("CustomEnvironment"), NULL, REG_SZ, (BYTE*)&m_szCustomEnvironment, (lstrlen(m_szCustomEnvironment) + 1) * sizeof(TCHAR) );
RegSetValueEx( hkey, TEXT("UseCustomColor"), NULL, REG_DWORD, (BYTE*)&m_bUseCustomColor, sizeof(DWORD) );
RegSetValueEx( hkey, TEXT("UseCustomTexture"), NULL, REG_DWORD, (BYTE*)&m_bUseCustomTexture, sizeof(DWORD) );
RegSetValueEx( hkey, TEXT("UseCustomEnvironment"), NULL, REG_DWORD, (BYTE*)&m_bUseCustomEnvironment, sizeof(DWORD) );
RegSetValueEx( hkey, TEXT("MeshQuality"), NULL, REG_DWORD, (BYTE*)&m_dwMeshQuality, sizeof(DWORD) );
RegSetValueEx( hkey, TEXT("Size"), NULL, REG_DWORD, (BYTE*)&m_dwSize, sizeof(DWORD) );
RegSetValueEx( hkey, TEXT("RotationSpeed"), NULL, REG_DWORD, (BYTE*)&m_dwRotationSpeed, sizeof(DWORD) );
RegSetValueEx( hkey, TEXT("RotationStyle"), NULL, REG_DWORD, (BYTE*)&m_RotType, sizeof(DWORD) );
RegSetValueEx( hkey, TEXT("DisplayString"), NULL, REG_SZ, (BYTE*)&m_szDisplayString, (lstrlen(m_szDisplayString) + 1) * sizeof(TCHAR) );
RegSetValueEx( hkey, TEXT("DisplayTime"), NULL, REG_DWORD, (BYTE*)&m_bDisplayTime, sizeof(DWORD) );
RegSetValueEx( hkey, TEXT("FontWeight"), NULL, REG_DWORD, (BYTE*)&m_Font.lfWeight, sizeof(DWORD) );
RegSetValueEx( hkey, TEXT("FontHeight"), NULL, REG_DWORD, (BYTE*)&m_Font.lfHeight, sizeof(DWORD) );
RegSetValueEx( hkey, TEXT("FontItalic"), NULL, REG_DWORD, (BYTE*)&m_Font.lfItalic, sizeof(DWORD) );
RegSetValueEx( hkey, TEXT("FontCharSet"), NULL, REG_DWORD, (BYTE*)&m_Font.lfCharSet, sizeof(DWORD) );
RegSetValueEx( hkey, TEXT("FontPitchFamily"), NULL, REG_DWORD, (BYTE*)&m_Font.lfPitchAndFamily, sizeof(DWORD) );
RegSetValueEx( hkey, TEXT("FontFace"), NULL, REG_SZ, (BYTE*)&m_Font.lfFaceName, (lstrlen(m_Font.lfFaceName) + 1) * sizeof(TCHAR) );
RegCloseKey( hkey );
}
}
//***************************************************************************************
VOID CTextScreensaver::SelectSurfaceColor( HWND hDlg )
{
static COLORREF cust_colors[16];
CHOOSECOLOR choose;
choose.lStructSize = sizeof(choose);
choose.hwndOwner = hDlg;
choose.hInstance = HWND(m_hInstance);
choose.rgbResult = m_SurfaceColor;
choose.lpCustColors = cust_colors;
choose.Flags = CC_ANYCOLOR|CC_FULLOPEN|CC_RGBINIT;
choose.lCustData = 0;
choose.lpfnHook = NULL;
choose.lpTemplateName = NULL;
if ( ChooseColor( &choose ) )
m_SurfaceColor = choose.rgbResult;
}
//***************************************************************************************
VOID CTextScreensaver::SelectFont( HWND hDlg )
{
CHOOSEFONT choose;
choose.lStructSize = sizeof(choose);
choose.hwndOwner = hDlg;
choose.hDC;
choose.iPointSize = 720;
choose.lpLogFont = &m_Font;
choose.Flags = CF_TTONLY|CF_FORCEFONTEXIST|CF_NOVERTFONTS|CF_SCREENFONTS|CF_INITTOLOGFONTSTRUCT|CF_ENABLETEMPLATE;
choose.lpTemplateName = MAKEINTRESOURCE(DLG_SELECT_FONT);
choose.hInstance = m_hInstance;
if ( ChooseFont( &choose ) )
m_Font = *choose.lpLogFont;
}
//***************************************************************************************
VOID CTextScreensaver::SelectCustomTexture( HWND hDlg )
{
TCHAR fn[MAX_PATH] = TEXT("\0");
TCHAR strTitle[100];
LoadString( NULL, IDS_OPENTEXTURETITLE, strTitle, 100 );
lstrcpy( fn, m_szCustomTexture );
TCHAR filter[200];
LoadString( NULL, IDS_FILEFILTER, filter, 200);
for( TCHAR* pch = filter; *pch != TEXT('\0'); pch++ )
{
if( *pch == TEXT('#') )
*pch = TEXT('\0');
}
TCHAR szWindowsDir[MAX_PATH];
szWindowsDir[0] = TEXT('\0');
GetWindowsDirectory( szWindowsDir, MAX_PATH );
OPENFILENAME ofn;
memset( &ofn , 0 , sizeof(ofn) );
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = hDlg;
ofn.hInstance = m_hInstance;
ofn.lpstrFilter = filter;
ofn.nFilterIndex = 1;
ofn.lpstrFile = fn;
ofn.nMaxFile = sizeof(fn);
ofn.lpstrTitle = strTitle;
ofn.Flags = OFN_ENABLESIZING|OFN_FILEMUSTEXIST;
ofn.lpstrDefExt = TEXT("mid");
if( lstrlen( fn ) == 0 )
ofn.lpstrInitialDir = szWindowsDir;
if ( GetOpenFileName( &ofn ) )
lstrcpy( m_szCustomTexture , ofn.lpstrFile );
}
//***************************************************************************************
VOID CTextScreensaver::SelectCustomEnvironment( HWND hDlg )
{
TCHAR fn[MAX_PATH] = TEXT("\0");
TCHAR strTitle[100];
LoadString( NULL, IDS_OPENENVIRONMENTMAPTITLE, strTitle, 100 );
TCHAR filter[200];
LoadString( NULL, IDS_FILEFILTER, filter, 200);
for( TCHAR* pch = filter; *pch != TEXT('\0'); pch++ )
{
if( *pch == TEXT('#') )
*pch = TEXT('\0');
}
TCHAR szWindowsDir[MAX_PATH];
szWindowsDir[0] = TEXT('\0');
GetWindowsDirectory( szWindowsDir, MAX_PATH );
OPENFILENAME ofn;
memset( &ofn , 0 , sizeof(ofn) );
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = hDlg;
ofn.hInstance = m_hInstance;
ofn.lpstrFilter = filter;
ofn.nFilterIndex = 1;
ofn.lpstrFile = fn;
ofn.nMaxFile = sizeof(fn);
ofn.lpstrTitle = strTitle;
ofn.Flags = OFN_ENABLESIZING|OFN_FILEMUSTEXIST;
ofn.lpstrDefExt = TEXT("mid");
if( lstrlen( fn ) == 0 )
ofn.lpstrInitialDir = szWindowsDir;
if ( GetOpenFileName( &ofn ) )
lstrcpy( m_szCustomEnvironment , ofn.lpstrFile );
}
//***************************************************************************************
VOID CTextScreensaver::EnableTextureWindows( HWND hDlg , SurfType sel )
{
HWND use_color = GetDlgItem( hDlg , IDC_USE_CUSTOM_COLOR );
HWND use_texture = GetDlgItem( hDlg , IDC_USE_CUSTOM_TEXTURE );
HWND use_environ = GetDlgItem( hDlg , IDC_USE_CUSTOM_ENVIRONMENT );
HWND browse_color = GetDlgItem( hDlg , IDC_SURFACE_COLOR );
HWND browse_texture = GetDlgItem( hDlg , IDC_BROWSE_TEXTURE );
HWND browse_environ = GetDlgItem( hDlg , IDC_BROWSE_ENVIRONMENT );
BOOL color_checked = IsDlgButtonChecked( hDlg , IDC_USE_CUSTOM_COLOR );
BOOL texture_checked = IsDlgButtonChecked( hDlg , IDC_USE_CUSTOM_TEXTURE );
BOOL environment_checked = IsDlgButtonChecked( hDlg , IDC_USE_CUSTOM_ENVIRONMENT );
switch ( sel )
{
case environment:
EnableWindow( use_color , FALSE );
EnableWindow( use_texture , FALSE );
EnableWindow( use_environ , TRUE );
EnableWindow( browse_color , FALSE );
EnableWindow( browse_texture , FALSE );
EnableWindow( browse_environ , environment_checked );
break;
case texture:
EnableWindow( use_color , FALSE );
EnableWindow( use_texture , TRUE );
EnableWindow( use_environ , FALSE );
EnableWindow( browse_color , FALSE );
EnableWindow( browse_texture , texture_checked );
EnableWindow( browse_environ , FALSE );
break;
case color:
default:
EnableWindow( use_color , TRUE );
EnableWindow( use_texture , FALSE );
EnableWindow( use_environ , FALSE );
EnableWindow( browse_color , color_checked );
EnableWindow( browse_texture , FALSE );
EnableWindow( browse_environ , FALSE );
break;
}
}