📄 didevimg.cpp
字号:
// Fill the data from the ImageHeader
pInfo = dihImageHeader.lprgImageInfoArray;
dwBufferCount = dihImageHeader.dwBufferUsed;
while( dwBufferCount > 0)
{
if( pInfo->dwViewID > m_dwNumViews )
{
// Error in the input format, this is out of bounds for our array
hr = E_FAIL;
goto LCleanReturn;
}
if( pInfo->dwFlags & DIDIFT_CONFIGURATION )
{
lstrcpy( m_atszImagePath[pInfo->dwViewID], pInfo->tszImagePath );
}
else if( pInfo->dwFlags & DIDIFT_OVERLAY )
{
hr = AddObject( pInfo->dwObjID );
if( FAILED(hr) )
goto LCleanReturn;
CDIDIObject *pDIObj = GetObject( pInfo->dwObjID );
if( NULL == pDIObj )
{
hr = DIERR_OUTOFMEMORY;
goto LCleanReturn;
}
// Overlay
if( pInfo->tszImagePath[0] )
pDIObj->SetOverlay( pInfo->dwViewID, pInfo->tszImagePath, pInfo->rcOverlay );
// Callout
pDIObj->SetCallout( pInfo->dwViewID, pInfo->dwcValidPts, pInfo->rgptCalloutLine, pInfo->rcCalloutRect, pInfo->dwTextAlign );
}
pInfo++;
dwBufferCount -= dihImageHeader.dwSizeImageInfo;
}
// We made it this far, set the return value as success.
hr = DI_OK;
LCleanReturn:
// Release the resources used for the image info structure
delete [] dihImageHeader.lprgImageInfoArray;
return hr;
}
//-----------------------------------------------------------------------------
// Name: CreateCustomImageInfo
// Desc: Create a default UI for the given device, and fill in all neccesary
// structures to support rendering
//-----------------------------------------------------------------------------
HRESULT CDIDevImage::CreateCustomImageInfo( LPDIRECTINPUTDEVICE8 pDIDevice )
{
HRESULT hr;
DIDEVCAPS didc;
// Allocate space for all the device's objects (axes, buttons, POVS)
ZeroMemory( &didc, sizeof(DIDEVCAPS) );
didc.dwSize = sizeof(DIDEVCAPS);
hr = pDIDevice->GetCapabilities( &didc );
if( FAILED(hr) )
return hr;
m_apObject = new CDIDIObject* [didc.dwAxes + didc.dwButtons + didc.dwPOVs];
if( NULL == m_apObject )
return DIERR_OUTOFMEMORY;
hr = pDIDevice->EnumObjects( EnumDeviceObjectsCB, this, DIDFT_AXIS );
if( FAILED(hr) )
return hr;
hr = pDIDevice->EnumObjects( EnumDeviceObjectsCB, this, DIDFT_BUTTON );
if( FAILED(hr))
return hr;
hr = pDIDevice->EnumObjects( EnumDeviceObjectsCB, this, DIDFT_POV );
if( FAILED(hr))
return hr;
return DI_OK;
}
//-----------------------------------------------------------------------------
// Name: LoadImages
// Desc: Load all images associated with the active view
//-----------------------------------------------------------------------------
HRESULT CDIDevImage::LoadImages()
{
UINT i;
HRESULT hr;
SIZE sizeInit = {0};
SIZE sizeScaled = {0};
FLOAT fxScale, fyScale;
D3DXIMAGE_INFO d3dxImageInfo;
LPDIRECT3DSURFACE9 pLoadSurface = NULL;
LPDIRECT3DSURFACE9 pScaleSurface = NULL;
// Create a temporary surface
pLoadSurface = GetCloneSurface( DIDICONST_MAX_IMAGE_WIDTH, DIDICONST_MAX_IMAGE_HEIGHT );
// Load the background image onto the temporary loading surface
hr = D3DXLoadSurfaceFromFile( pLoadSurface, NULL, NULL,
m_atszImagePath[m_dwActiveView],
NULL, D3DX_FILTER_NONE,
NULL, &d3dxImageInfo );
if( FAILED(hr) )
goto LCleanReturn;
// The actual dimensions of the render surface are determined
// by the background image, the overlay images, and the
// callout rects.
sizeInit.cx = d3dxImageInfo.Width;
sizeInit.cy = d3dxImageInfo.Height;
for( i=0; i < m_dwNumObjects; i++ )
{
DIDICallout* pCallout = m_apObject[i]->GetCallout( m_dwActiveView );
sizeInit.cx = max( sizeInit.cx, pCallout->rcInit.right );
sizeInit.cy = max( sizeInit.cy, pCallout->rcInit.bottom );
}
// Determine the scaling parameters
switch( m_dwScaleMethod )
{
case( DIDISOIS_RESIZE ) :
sizeScaled.cx = m_dwWidthPref;
sizeScaled.cy = m_dwHeightPref;
break;
case( DIDISOIS_MAINTAINASPECTUSINGWIDTH ) :
sizeScaled.cx = m_dwWidthPref;
sizeScaled.cy = (LONG) ( 0.5 + sizeInit.cy * ( (FLOAT)m_dwWidthPref / sizeInit.cx ) );
break;
case( DIDISOIS_MAINTAINASPECTUSINGHEIGHT ) :
sizeScaled.cx = (LONG) ( 0.5 + sizeInit.cx * ( (FLOAT)m_dwHeightPref / sizeInit.cy ) );
sizeScaled.cy = m_dwHeightPref;
break;
case( DIDISOIS_DEFAULT ) :
default :
sizeScaled.cx = sizeInit.cx;
sizeScaled.cy = sizeInit.cy;
break;
}
// Calculate scaling multipliers
fxScale = (FLOAT)sizeScaled.cx / sizeInit.cx;
fyScale = (FLOAT)sizeScaled.cy / sizeInit.cy;
// Scale all object display parameters
for( i=0; i < m_dwNumObjects; i++ )
{
m_apObject[i]->ScaleView( m_dwActiveView, fxScale, fyScale );
}
// Load the background image
hr = CreateScaledSurfaceCopy( pLoadSurface, d3dxImageInfo.Width, d3dxImageInfo.Height,
fxScale, fyScale, &pScaleSurface );
if( FAILED(hr) )
goto LCleanReturn;
// Create a DIB section for the loaded image
hr = CreateDIBSectionFromSurface( pScaleSurface, &(m_ahImages[ m_dwActiveView ]), &sizeScaled );
if( FAILED(hr) )
goto LCleanReturn;
SAFE_RELEASE( pScaleSurface );
// Apply the background color
FillBackground( m_ahImages[ m_dwActiveView ], m_BkColor );
// Load all object images
for( i=0; i < m_dwNumObjects; i++ )
{
DIDIOverlay *pOverlay = m_apObject[i]->GetOverlay( m_dwActiveView );
// Load the file onto the temporary surface
if( !pOverlay->strImagePath[0] )
continue;
hr = D3DXLoadSurfaceFromFile( pLoadSurface,
NULL, NULL,
pOverlay->strImagePath,
NULL, D3DX_FILTER_NONE,
NULL, &d3dxImageInfo );
if( FAILED(hr) )
continue;
// Since overlay rectanges are actually defined by the image size, some
// of the image info files simply define the top-left coordinate of the
// rectangle. We may want good data for the overlay rectangle, so set
// the rect based on image size
pOverlay->rcInit.bottom = pOverlay->rcInit.top + d3dxImageInfo.Height;
pOverlay->rcInit.right = pOverlay->rcInit.left + d3dxImageInfo.Width;
ScaleRect( &( pOverlay->rcInit), &( pOverlay->rcScaled ), fxScale, fyScale );
// Scale the overlay
hr = CreateScaledSurfaceCopy( pLoadSurface, d3dxImageInfo.Width, d3dxImageInfo.Height,
fxScale, fyScale, &pScaleSurface );
if( FAILED(hr) )
goto LCleanReturn;
// Load the stored bitmap from the scaled D3D surface
hr = CreateDIBSectionFromSurface( pScaleSurface, &(pOverlay->hImage) );
if( FAILED(hr) )
goto LCleanReturn;
SAFE_RELEASE( pScaleSurface );
}
hr = DI_OK;
LCleanReturn:
SAFE_RELEASE( pLoadSurface );
SAFE_RELEASE( pScaleSurface );
return hr;
}
//-----------------------------------------------------------------------------
// Name: GetCustomUISize
// Desc: Determine the dimensions of the custom UI based on default values and
// user-supplied sizing information.
//-----------------------------------------------------------------------------
HRESULT CDIDevImage::GetCustomUISize( SIZE* pSize )
{
if( pSize == NULL )
return DIERR_INVALIDPARAM;
// Calculate view dimensions based on values set during a call to
// SetOutputImageSize(), or the default values defined in the header
switch( m_dwScaleMethod )
{
case DIDISOIS_RESIZE :
pSize->cx = m_dwWidthPref;
pSize->cy = m_dwHeightPref;
break;
case DIDISOIS_MAINTAINASPECTUSINGWIDTH :
pSize->cx = m_dwWidthPref;
pSize->cy = (LONG) ( 0.5 + DIDICONST_CUSTOM_VIEW_HEIGHT *
( (FLOAT)m_dwWidthPref / DIDICONST_CUSTOM_VIEW_WIDTH ) );
break;
case DIDISOIS_MAINTAINASPECTUSINGHEIGHT :
pSize->cy = m_dwHeightPref;
pSize->cx = (LONG) ( 0.5 + DIDICONST_CUSTOM_VIEW_WIDTH *
( (FLOAT)m_dwHeightPref / DIDICONST_CUSTOM_VIEW_HEIGHT ) );
break;
default:
pSize->cx = DIDICONST_CUSTOM_VIEW_WIDTH;
pSize->cy = DIDICONST_CUSTOM_VIEW_HEIGHT;
};
return DI_OK;
}
//-----------------------------------------------------------------------------
// Name: BuildCustomUI
// Desc: Creates the callout rects for each view based on stored sizing
// information and callout strings.
//-----------------------------------------------------------------------------
HRESULT CDIDevImage::BuildCustomUI()
{
HDC hdc = NULL;
SIZE size = {0};
UINT i = 0;
int nMaxNameWidth = 0;
int nMaxNameHeight = 0;
int nMaxCalloutWidth = 0;
int nMaxCalloutHeight = 0;
int nRowsPerView = 0;
int nColsPerView = 0;
int nNumVisObjects = 0;
const int GUTTER_SIZE = 20;
const int PADDING_SIZE = 20;
const int SPACING_WIDTH = 10;
const int SPACING_HEIGHT = 10;
const int MAX_CHARS_OBJECT = 20;
const int MAX_CHARS_ACTION = 20;
// we need a device context in order to evaluate the text metrics
hdc = CreateDC( TEXT("DISPLAY"), NULL, NULL, NULL );
if( NULL == hdc )
return E_FAIL;
// select the font into the dc
SelectObject( hdc, m_hFont );
// determine the largest device name
for( i=0; i < m_dwNumObjects; i++ )
{
if( DIDICOS_INVISIBLE & m_apObject[i]->GetCalloutState() )
continue;
nNumVisObjects++;
TCHAR str[ MAX_PATH ] = {0};
m_apObject[i]->GetName( str, MAX_PATH );
if( lstrlen(str) > 15 )
lstrcpy( &str[15], TEXT("...") );
if( str && GetTextExtentPoint32( hdc, str, lstrlen( str ), &size ) )
{
nMaxNameWidth = max( nMaxNameWidth, size.cx );
nMaxNameHeight = max( nMaxNameHeight, size.cy );
}
m_apObject[i]->GetCalloutText( str, MAX_PATH );
if( lstrlen(str) > 15 )
lstrcpy( &str[15], TEXT("...") );
if( str && GetTextExtentPoint32( hdc, str, lstrlen( str ), &size ) )
{
nMaxCalloutWidth = max( nMaxCalloutWidth, size.cx );
nMaxCalloutHeight = max( nMaxCalloutHeight, size.cy );
}
}
// Optionally, you can help constrain the callout sizes by restricting the
// string lengths.
TEXTMETRIC tm = {0};
if( GetTextMetrics( hdc, &tm ) )
{
nMaxCalloutWidth = min( nMaxCalloutWidth, MAX_CHARS_ACTION * tm.tmAveCharWidth );
nMaxNameWidth = min( nMaxNameWidth, MAX_CHARS_OBJECT * tm.tmAveCharWidth );
}
// Release resources
DeleteDC( hdc );
// Calculate view dimensions
GetCustomUISize( &size );
// determine how many callouts we can fit on a single view
nColsPerView = ( size.cx - (2 * PADDING_SIZE) + GUTTER_SIZE ) /
( nMaxNameWidth + nMaxCalloutWidth + SPACING_WIDTH + GUTTER_SIZE );
nColsPerView = max( nColsPerView, 1 );
nRowsPerView = ( size.cy - (2 * PADDING_SIZE) ) /
( nMaxNameHeight + SPACING_HEIGHT );
nRowsPer
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -