📄 dxutgui.cpp
字号:
//--------------------------------------------------------------------------------------
void CDXUTDialogResourceManager::EnableKeyboardInputForAllDialogs()
{
// Enable keyboard input for all registered dialogs
for( int i = 0; i < m_Dialogs.GetSize(); ++i )
m_Dialogs[i]->EnableKeyboardInput( true );
}
//--------------------------------------------------------------------------------------
void CDXUTDialog::Refresh()
{
if( s_pControlFocus )
s_pControlFocus->OnFocusOut();
if( m_pControlMouseOver )
m_pControlMouseOver->OnMouseLeave();
s_pControlFocus = NULL;
s_pControlPressed = NULL;
m_pControlMouseOver = NULL;
for( int i=0; i < m_Controls.GetSize(); i++ )
{
CDXUTControl* pControl = m_Controls.GetAt(i);
pControl->Refresh();
}
if( m_bKeyboardInput )
FocusDefaultControl();
}
//--------------------------------------------------------------------------------------
HRESULT CDXUTDialog::OnRender( float fElapsedTime )
{
// If this assert triggers, you need to call CDXUTDialogResourceManager::On*Device() from inside
// the application's device callbacks. See the SDK samples for an example of how to do this.
assert( m_pManager->GetD3DDevice() && m_pManager->m_pStateBlock && L"To fix hook up CDXUTDialogResourceManager to device callbacks. See comments for details" );
// See if the dialog needs to be refreshed
if( m_fTimeLastRefresh < s_fTimeRefresh )
{
m_fTimeLastRefresh = DXUTGetTime();
Refresh();
}
// For invisible dialog, out now.
if( !m_bVisible )
return S_OK;
DXUT_SCREEN_VERTEX vertices[4] =
{
(float)m_x, (float)m_y, 0.5f, 1.0f, m_colorTopLeft, 0.0f, 0.5f,
(float)m_x + m_width, (float)m_y, 0.5f, 1.0f, m_colorTopRight, 1.0f, 0.5f,
(float)m_x + m_width, (float)m_y + m_height, 0.5f, 1.0f, m_colorBottomRight, 1.0f, 1.0f,
(float)m_x, (float)m_y + m_height, 0.5f, 1.0f, m_colorBottomLeft, 0.0f, 1.0f,
};
IDirect3DDevice9* pd3dDevice = m_pManager->GetD3DDevice();
// Set up a state block here and restore it when finished drawing all the controls
m_pManager->m_pStateBlock->Capture();
pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );
pd3dDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA );
pd3dDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );
pd3dDevice->SetRenderState( D3DRS_ALPHATESTENABLE, FALSE );
pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_SELECTARG2 );
pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 );
pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE );
pd3dDevice->SetVertexShader( NULL );
pd3dDevice->SetPixelShader( NULL );
//pd3dDevice->Clear( 0, NULL, D3DCLEAR_ZBUFFER, 0, 1.0f, 0 );
pd3dDevice->SetRenderState( D3DRS_ZENABLE, FALSE );
if( !m_bMinimized )
{
pd3dDevice->SetFVF( DXUT_SCREEN_VERTEX::FVF );
pd3dDevice->DrawPrimitiveUP( D3DPT_TRIANGLEFAN, 2, vertices, sizeof(DXUT_SCREEN_VERTEX) );
}
pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE );
pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_MODULATE );
pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE );
pd3dDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR );
DXUTTextureNode* pTextureNode = GetTexture( 0 );
pd3dDevice->SetTexture( 0, pTextureNode->pTexture );
m_pManager->m_pSprite->Begin( D3DXSPRITE_DONOTSAVESTATE );
// Render the caption if it's enabled.
if( m_bCaption )
{
// DrawSprite will offset the rect down by
// m_nCaptionHeight, so adjust the rect higher
// here to negate the effect.
RECT rc = { 0, -m_nCaptionHeight, m_width, 0 };
DrawSprite( &m_CapElement, &rc );
rc.left += 5; // Make a left margin
WCHAR wszOutput[256];
StringCchCopy( wszOutput, 256, m_wszCaption );
if( m_bMinimized )
StringCchCat( wszOutput, 256, L" (Minimized)" );
DrawText( wszOutput, &m_CapElement, &rc, true );
}
// If the dialog is minimized, skip rendering
// its controls.
if( !m_bMinimized )
{
for( int i=0; i < m_Controls.GetSize(); i++ )
{
CDXUTControl* pControl = m_Controls.GetAt(i);
// Focused control is drawn last
if( pControl == s_pControlFocus )
continue;
pControl->Render( pd3dDevice, fElapsedTime );
}
if( s_pControlFocus != NULL && s_pControlFocus->m_pDialog == this )
s_pControlFocus->Render( pd3dDevice, fElapsedTime );
}
m_pManager->m_pSprite->End();
m_pManager->m_pStateBlock->Apply();
return S_OK;
}
//--------------------------------------------------------------------------------------
VOID CDXUTDialog::SendEvent( UINT nEvent, bool bTriggeredByUser, CDXUTControl* pControl )
{
// If no callback has been registered there's nowhere to send the event to
if( m_pCallbackEvent == NULL )
return;
// Discard events triggered programatically if these types of events haven't been
// enabled
if( !bTriggeredByUser && !m_bNonUserEvents )
return;
m_pCallbackEvent( nEvent, pControl->GetID(), pControl, m_pCallbackEventUserContext );
}
//--------------------------------------------------------------------------------------
int CDXUTDialogResourceManager::AddFont( LPCWSTR strFaceName, LONG height, LONG weight )
{
// See if this font already exists
for( int i=0; i < m_FontCache.GetSize(); i++ )
{
DXUTFontNode* pFontNode = m_FontCache.GetAt(i);
if( 0 == _wcsnicmp( pFontNode->strFace, strFaceName, MAX_PATH-1 ) &&
pFontNode->nHeight == height &&
pFontNode->nWeight == weight )
{
return i;
}
}
// Add a new font and try to create it
DXUTFontNode* pNewFontNode = new DXUTFontNode();
if( pNewFontNode == NULL )
return -1;
ZeroMemory( pNewFontNode, sizeof(DXUTFontNode) );
StringCchCopy( pNewFontNode->strFace, MAX_PATH, strFaceName );
pNewFontNode->nHeight = height;
pNewFontNode->nWeight = weight;
m_FontCache.Add( pNewFontNode );
int iFont = m_FontCache.GetSize()-1;
// If a device is available, try to create immediately
if( m_pd3dDevice )
CreateFont( iFont );
return iFont;
}
//--------------------------------------------------------------------------------------
HRESULT CDXUTDialog::SetFont( UINT index, LPCWSTR strFaceName, LONG height, LONG weight )
{
// If this assert triggers, you need to call CDXUTDialog::Init() first. This change
// was made so that the DXUT's GUI could become seperate and optional from DXUT's core. The
// creation and interfacing with CDXUTDialogResourceManager is now the responsibility
// of the application if it wishes to use DXUT's GUI.
assert( m_pManager != NULL && L"To fix call CDXUTDialog::Init() first. See comments for details." );
// Make sure the list is at least as large as the index being set
UINT i;
for( i=m_Fonts.GetSize(); i <= index; i++ )
{
m_Fonts.Add( -1 );
}
int iFont = m_pManager->AddFont( strFaceName, height, weight );
m_Fonts.SetAt( index, iFont );
return S_OK;
}
//--------------------------------------------------------------------------------------
DXUTFontNode* CDXUTDialog::GetFont( UINT index )
{
if( NULL == m_pManager )
return NULL;
return m_pManager->GetFontNode( m_Fonts.GetAt( index ) );
}
//--------------------------------------------------------------------------------------
int CDXUTDialogResourceManager::AddTexture( LPCWSTR strFilename )
{
// See if this texture already exists
for( int i=0; i < m_TextureCache.GetSize(); i++ )
{
DXUTTextureNode* pTextureNode = m_TextureCache.GetAt(i);
if( 0 == _wcsnicmp( pTextureNode->strFilename, strFilename, MAX_PATH-1 ) )
{
return i;
}
}
// Add a new texture and try to create it
DXUTTextureNode* pNewTextureNode = new DXUTTextureNode();
if( pNewTextureNode == NULL )
return -1;
ZeroMemory( pNewTextureNode, sizeof(DXUTTextureNode) );
StringCchCopy( pNewTextureNode->strFilename, MAX_PATH, strFilename );
m_TextureCache.Add( pNewTextureNode );
int iTexture = m_TextureCache.GetSize()-1;
// If a device is available, try to create immediately
if( m_pd3dDevice )
CreateTexture( iTexture );
return iTexture;
}
//--------------------------------------------------------------------------------------
HRESULT CDXUTDialog::SetTexture( UINT index, LPCWSTR strFilename )
{
// If this assert triggers, you need to call CDXUTDialog::Init() first. This change
// was made so that the DXUT's GUI could become seperate and optional from DXUT's core. The
// creation and interfacing with CDXUTDialogResourceManager is now the responsibility
// of the application if it wishes to use DXUT's GUI.
assert( m_pManager != NULL && L"To fix call CDXUTDialog::Init() first. See comments for details." );
// Make sure the list is at least as large as the index being set
for( UINT i=m_Textures.GetSize(); i <= index; i++ )
{
m_Textures.Add( -1 );
}
int iTexture = m_pManager->AddTexture( strFilename );
m_Textures.SetAt( index, iTexture );
return S_OK;
}
//--------------------------------------------------------------------------------------
DXUTTextureNode* CDXUTDialog::GetTexture( UINT index )
{
if( NULL == m_pManager )
return NULL;
return m_pManager->GetTextureNode( m_Textures.GetAt( index ) );
}
//--------------------------------------------------------------------------------------
bool CDXUTDialog::MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
bool bHandled = false;
// For invisible dialog, do not handle anything.
if( !m_bVisible )
return false;
// If automation command-line switch is on, enable this dialog's keyboard input
// upon any key press or mouse click.
if( DXUTGetAutomation() &&
( WM_LBUTTONDOWN == uMsg || WM_LBUTTONDBLCLK == uMsg || WM_KEYDOWN == uMsg ) )
{
m_pManager->EnableKeyboardInputForAllDialogs();
}
// If caption is enable, check for clicks in the caption area.
if( m_bCaption )
{
static bool bDrag;
if( uMsg == WM_LBUTTONDOWN || uMsg == WM_LBUTTONDBLCLK )
{
POINT mousePoint = { short(LOWORD(lParam)), short(HIWORD(lParam)) };
if( mousePoint.x >= m_x && mousePoint.x < m_x + m_width &&
mousePoint.y >= m_y && mousePoint.y < m_y + m_nCaptionHeight )
{
bDrag = true;
SetCapture( DXUTGetHWND() );
return true;
}
} else
if( uMsg == WM_LBUTTONUP && bDrag )
{
POINT mousePoint = { short(LOWORD(lParam)), short(HIWORD(lParam)) };
if( mousePoint.x >= m_x && mousePoint.x < m_x + m_width &&
mousePoint.y >= m_y && mousePoint.y < m_y + m_nCaptionHeight )
{
ReleaseCapture();
bDrag = false;
m_bMinimized = !m_bMinimized;
return true;
}
}
}
// If the dialog is minimized, don't send any messages to controls.
if( m_bMinimized )
return false;
// If a control is in focus, it belongs to this dialog, and it's enabled, then give
// it the first chance at handling the message.
if( s_pControlFocus &&
s_pControlFocus->m_pDialog == this &&
s_pControlFocus->GetEnabled() )
{
// If the control MsgProc handles it, then we don't.
if( s_pControlFocus->MsgProc( uMsg, wParam, lParam ) )
return true;
}
switch( uMsg )
{
case WM_SIZE:
case WM_MOVE:
{
// Handle sizing and moving messages so that in case the mouse cursor is moved out
// of an UI control because of the window adjustment, we can properly
// unhighlight the highlighted control.
POINT pt = { -1, -1 };
OnMouseMove( pt );
break;
}
case WM_ACTIVATEAPP:
// Call OnFocusIn()/OnFocusOut() of the control that currently has the focus
// as the application is activated/deactivated. This matches the Windows
// behavior.
if( s_pControlFocus &&
s_pControlFocus->m_pDialog == this &&
s_pControlFocus->GetEnabled() )
{
if( wParam )
s_pControlFocus->OnFocusIn();
else
s_pControlFocus->OnFocusOut();
}
break;
// Keyboard messages
case WM_KEYDOWN:
case WM_SYSKEYDOWN:
case WM_KEYUP:
case WM_SYSKEYUP:
{
// If a control is in focus, it belongs to this dialog, and it's enabled, then give
// it the first chance at handling the message.
if( s_pControlFocus &&
s_pControlFocus->m_pDialog == this &&
s_pControlFocus->GetEnabled() )
{
if( s_pControlFocus->HandleKeyboard( uMsg, wParam, lParam ) )
return true;
}
// Not yet handled, see if this matches a control's hotkey
// Activate the hotkey if the focus doesn't belong to an
// edit box.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -