📄 coolcontrolsmanager.cpp
字号:
pCtl = new CCMControl;
}
else if ( !lstrcmpi( szBuf, _T( "SysIPAddress32" ) ) )
{
if ( dwExStyle & WS_EX_CLIENTEDGE )
pCtl = new CCMIPAddress;
}
else if ( !lstrcmpi( szBuf, _T( "msctls_trackbar32" ) ) )
pCtl = new CCMTrackbar;
else if ( !lstrcmpi( szBuf, _T( "RichEdit" ) ) )
{
if ( dwExStyle & WS_EX_CLIENTEDGE )
pCtl = new CCMControl;
}
else if ( !lstrcmpi( szBuf, _T( "RichEdit20W" ) ) )
{
if ( dwExStyle & WS_EX_CLIENTEDGE )
pCtl = new CCMControl;
}
else if ( !lstrcmpi( szBuf, _T( "SysHeader32" ) ) )
{
if ( dwStyle & HDS_BUTTONS )
pCtl = new CCMHeaderCtrl;
else
return FALSE;
}
else if ( !lstrcmpi( szBuf, _T( "ToolbarWindow32" ) ) )
{
// Skip the flat toolbars
if ( dwStyle & TBSTYLE_FLAT )
return FALSE;
HWND hCtrl = GetTopWindow( hWnd ); // Add additional toolbar controls
while ( hCtrl )
{
AddControl( hCtrl );
hCtrl = GetNextWindow( hCtrl, GW_HWNDNEXT );
}
pCtl = new CCMToolbar;
}
else if ( !lstrcmpi( szBuf, _T( "SysTabControl32" ) ) )
{
pCtl = new CCMTabControl;
HWND hWndTop = GetTopWindow( hWnd );
if ( hWndTop )
AddControl( hWndTop ); // Also add the up-down control (horizontal tabs only)
}
else // Unknown control, do not process
return FALSE;
if ( pCtl )
{
CCM_TRACE( _T( "CCoolControlsManager::AddControl, handle: %X, type: %s\n" ),
hWnd, szBuf );
// Perform window subclassing
pCtl->Subclass( hWnd, CCM_ControlProc );
// Add the control to the map
m_ctrlMap.SetAt( hWnd, pCtl );
if ( m_uTimerID == 0 ) // If timer is not initialized yet
{
m_uTimerID = SetTimer( NULL, 0, CCM_TIMER_VAL, CCM_TimerProc );
CCM_TRACE( _T( "CControlManager: Timer created\n" ) );
ASSERT( m_uTimerID ); // Failed to create the timer
}
return TRUE;
}
return FALSE;
}
BOOL CCoolControlsManager::RemoveControl( HWND hWnd )
{
BOOL bResult = TRUE;
CCMControl* pCtl;
if ( m_ctrlMap.Lookup( hWnd, (void*&)pCtl ) == FALSE )
bResult = FALSE;
#if defined _DEBUG
TCHAR szBuf[MAX_CLASSNAME];
GetClassName( hWnd, szBuf, MAX_CLASSNAME );
CCM_TRACE( _T( "CCoolControlsManager::RemoveControl, handle: %X, class: %s, " ),
hWnd, szBuf );
CCM_TRACE( bResult ? _T( "OK\n" ) : _T( "fail\n" ) );
#endif
if ( bResult == TRUE )
{
// Unsubclass window and next remove it from the map
pCtl->Unsubclass();
m_ctrlMap.RemoveKey( hWnd );
delete pCtl; // Destroy the object
if ( m_ctrlMap.IsEmpty() )
{
KillTimer( NULL, m_uTimerID );
CCM_TRACE( _T( "CCoolControlsManager: Timer killed, map is empty\n" ) );
m_uTimerID = 0;
}
else
CCM_TRACE( _T( "CCoolControlsManager: map has %d items\n" ), m_ctrlMap.GetCount() );
}
return bResult;
}
void CCoolControlsManager::AddDialog( HWND hWnd )
{
if ( hWnd )
{
CCMDialog* pCtl = new CCMDialog;
pCtl->Subclass( hWnd, CCM_DialogProc ); // Perform window subclassing
m_dlgMap.SetAt( hWnd, pCtl ); // Add the dialog to the map
}
}
void CCoolControlsManager::RemoveDialog( HWND hWnd )
{
CCMDialog* pCtl;
if ( m_dlgMap.Lookup( hWnd, (void*&)pCtl ) == TRUE )
{
// Unsubclass window and next remove it from the map
pCtl->Unsubclass();
m_dlgMap.RemoveKey( hWnd );
delete pCtl; // Destroy the object
}
}
static void CALLBACK CCM_TimerProc( HWND /*hwnd*/, UINT /*uMsg*/,
UINT /*idEvent*/, DWORD /*dwTime*/ )
{
g_ctrlManager.TimerProc();
}
void CCoolControlsManager::TimerProc()
{
// Do not process when the map is empty or the capture is set
if ( m_ctrlMap.IsEmpty() || GetCapture() != NULL )
return;
POINT point;
GetCursorPos( &point );
HWND hWnd = WindowFromPoint( point );
CCMControl* pCtl;
// Lookup for a window in the map
if ( m_ctrlMap.Lookup( hWnd, (void*&)pCtl ) == FALSE ) // Not found
{
// If window does not exist in the map, it can be
// a child of the control (e.g. edit control in ComboBox
// or header control in ListView). If so, get the parent window and
// carry on
hWnd = GetParent( hWnd );
// Not our window, so just reset previous control and exit
if ( hWnd == NULL || m_ctrlMap.Lookup( hWnd, (void*&)pCtl ) == FALSE )
{
// Not our window, so just reset previous control and exit
if ( m_ctrlMap.Lookup( CCMControl::m_hWndOld, (void*&)pCtl ) == TRUE )
{
pCtl->SetState( dsHover, 0 );
CCMControl::m_hWndOld = NULL;
}
return;
}
}
if ( pCtl->NeedRedraw( point ) ) // Window has been found and needs to be redrawn!
{
// First, reset old control (if any)
CCMControl* pCtlOld;
if ( m_ctrlMap.Lookup( CCMControl::m_hWndOld, (void*&)pCtlOld ) == TRUE )
{
pCtlOld->SetState( dsHover, 0 );
CCMControl::m_hWndOld = NULL;
}
// Redraw control under the cursor
pCtl->SetState( 0, dsHover );
CCMControl::m_hWndOld = hWnd;
}
}
///////////////////////////////////////////////////////////////////////
// All messages from subclassed dialogs will come here
static LRESULT CALLBACK CCM_DialogProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
// Try to find dialog in the dialog map
CCoolControlsManager::CCMDialog* pCtl;
if ( g_ctrlManager.m_dlgMap.Lookup( hWnd, (void*&)pCtl ) == FALSE )
{
// This is not our dialog, so just apply default processing
return DefWindowProc( hWnd, uMsg, wParam, lParam );
}
// Otherwise, let the dialog to process this message
return pCtl->WindowProc( uMsg, wParam, lParam );
}
///////////////////////////////////////////////////////////////////////
// All messages from subclassed controls will come here
static LRESULT CALLBACK CCM_ControlProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
CCoolControlsManager::CCMControl* pCtl;
// Try to find window in the control map
if ( g_ctrlManager.m_ctrlMap.Lookup( hWnd, (void*&)pCtl ) == FALSE )
{
// This is not our window, so just apply default processing
return DefWindowProc( hWnd, uMsg, wParam, lParam );
}
// Otherwise, let the control to process this message
return pCtl->WindowProc( uMsg, wParam, lParam );
}
//////////////////////////////////////////////////////////////////////////////
// CCMControl and derived classes
CCoolControlsManager::CCMControl::CCMControl()
{
m_hWnd = NULL;
m_oldWndProc = NULL;
m_nState = dsNormal;
m_nOldState = dsNormal;
}
void CCoolControlsManager::CCMControl::PrepareDraw( HDC& hDC, RECT& rect )
{
GetWindowRect( m_hWnd, &rect );
OffsetRect( &rect, -rect.left, -rect.top );
hDC = GetWindowDC( m_hWnd );
}
void CCoolControlsManager::CCMControl::DrawBorder()
{
HDC hDC;
RECT rect;
PrepareDraw( hDC, rect );
if ( GetWindowLong( m_hWnd, GWL_EXSTYLE ) & WS_EX_CLIENTEDGE )
{
RECT rc;
GetWindowRect( m_hWnd, &rc );
POINT point = { 0, 0 };
ClientToScreen( m_hWnd, &point );
if ( point.x == rc.left + 3 )
InflateRect( &rect, -1, -1 );
}
if ( IsFocused() == TRUE )
m_nState |= dsFocus;
else
m_nState &= ~dsFocus;
// Single line control looks better when this style is added
if ( ( rect.bottom - rect.top ) < 30 )
m_nState |= dsAlternate;
else
m_nState &= ~dsAlternate;
if ( ( m_nOldState & dsHover && m_nState & dsHover ) ||
( m_nOldState & dsFocus && m_nState & dsFocus ) )
; // If previous state is the same as current state, do nothing
else
{
// Perform control-specific drawing routines
CCM_TRACE( _T( "CCoolControlsManager::DrawBorder, handle: %X state: %d\n" ), m_hWnd, m_nState );
DrawControl( hDC, rect );
}
// Update old state
m_nOldState = m_nState;
ReleaseDC( WindowFromDC( hDC ), hDC );
}
BOOL CCoolControlsManager::CCMControl::NeedRedraw( const POINT& /*point*/ )
{
return m_hWnd != m_hWndOld ? TRUE : FALSE;
}
void CCoolControlsManager::CCMCore::Subclass( HWND hWnd, WNDPROC wndNewProc )
{
ASSERT( hWnd ); // Do you really want to subclass a window that has a NULL handle?
m_hWnd = hWnd;
// Store address of the original window procedure
m_oldWndProc = (WNDPROC)GetWindowLong( m_hWnd, GWL_WNDPROC );
// And set the new one
SetWindowLong( m_hWnd, GWL_WNDPROC, (LONG)wndNewProc );
}
void CCoolControlsManager::CCMCore::Unsubclass()
{
SetWindowLong( m_hWnd, GWL_WNDPROC, (LONG)m_oldWndProc );
}
LRESULT CCoolControlsManager::CCMControl::WindowProc( UINT uMsg, WPARAM wParam, LPARAM lParam )
{
switch ( uMsg )
{
// Generic messages
case WM_KILLFOCUS:
case WM_SETFOCUS:
DrawBorder();
break;
case WM_PAINT:
case WM_NCPAINT:
case WM_ENABLE:
CallWindowProc( m_oldWndProc, m_hWnd, uMsg, wParam, lParam );
DrawBorder();
return 0;
case WM_NCDESTROY:
// Unsubclass window and remove it from the map
CallWindowProc( m_oldWndProc, m_hWnd, uMsg, wParam, lParam );
g_ctrlManager.RemoveControl( m_hWnd );
return 0;
}
return CallWindowProc( m_oldWndProc, m_hWnd, uMsg, wParam, lParam );
}
void CCoolControlsManager::CCMControl::DrawControl( HDC hDC, const RECT& rc )
{
if ( m_nState & dsHoverMask )
{
Draw3dBorder( hDC, rc, COLOR_3DSHADOW, COLOR_3DHIGHLIGHT,
COLOR_3DDKSHADOW, COLOR_3DLIGHT );
}
else
{
if ( IsWindowEnabled( m_hWnd ) == FALSE || m_nState & dsDisabled )
Draw3dBorder( hDC, rc, COLOR_3DSHADOW, COLOR_3DHIGHLIGHT,
COLOR_3DFACE, COLOR_3DFACE );
else
Draw3dBorder( hDC, rc, COLOR_3DSHADOW, COLOR_3DHIGHLIGHT,
m_nState & dsAlternate ? COLOR_3DHIGHLIGHT : COLOR_3DLIGHT, COLOR_3DLIGHT );
}
DrawScrollBars( hDC, rc );
}
void CCoolControlsManager::CCMControl::DrawScrollbarThumb( HDC hDC, const RECT& rc )
{
if ( m_nState & dsHoverMask )
Draw3dBorder( hDC, rc, COLOR_3DFACE, COLOR_3DDKSHADOW,
COLOR_3DHIGHLIGHT, COLOR_3DSHADOW );
else
Draw3dBorder( hDC, rc, COLOR_3DHIGHLIGHT, COLOR_3DSHADOW,
COLOR_3DFACE, COLOR_3DFACE );
}
void CCoolControlsManager::CCMControl::DrawScrollBars( HDC hDC, const RECT& rect )
{
const int nFrameSize = GetSystemMetrics( SM_CXEDGE );
const int nScrollSize = GetSystemMetrics( SM_CXHSCROLL );
RECT rc;
DWORD dwStyle = GetWindowLong( m_hWnd, GWL_STYLE );
if ( dwStyle & WS_HSCROLL && dwStyle & WS_VSCROLL )
{
rc.left = rect.left + nFrameSize; rc.top = rect.bottom - nFrameSize - nScrollSize;
rc.right = rect.right - nFrameSize - nScrollSize; rc.bottom = rect.bottom - nFrameSize;
DrawScrollBar( hDC, rc, SB_HORZ );
rc.left = rect.right - nFrameSize - nScrollSize; rc.top = rect.top + nFrameSize;
rc.right = rect.right - nFrameSize; rc.bottom = rect.bottom - nFrameSize - nScrollSize;
DrawScrollBar( hDC, rc, SB_VERT );
}
else if ( dwStyle & WS_VSCROLL )
{
rc.left = rect.right - nFrameSize - nScrollSize; rc.top = rect.top + nFrameSize;
rc.right = rect.right - nFrameSize; rc.bottom = rect.bottom - nFrameSize;
DrawScrollBar( hDC, rc, SB_VERT );
}
else if ( dwStyle & WS_HSCROLL )
{
rc.left = rect.left + nFrameSize; rc.top = rect.bottom - nFrameSize - nScrollSize;
rc.right = rect.right - nFrameSize; rc.bottom = rect.bottom - nFrameSize;
DrawScrollBar( hDC, rc, SB_HORZ );
}
}
void CCoolControlsManager::CCMControl::DrawScrollBar( HDC hDC, const RECT& rect,
int nType, BOOL bScrollbarCtrl )
{
int nScrollSize = GetSystemMetrics( SM_CXHSCROLL );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -