⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 coolcontrolsmanager.cpp

📁 打印数据生成和模拟
💻 CPP
📖 第 1 页 / 共 5 页
字号:
			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 );
	
	// The minimal thumb size depends on the system version
	// For Windows 98 minimal thumb size is a half of scrollbar size 
	// and for Windows NT is always 8 pixels regardless of system metrics. 
	// I really don't know why.
	int nMinThumbSize;
	if ( GetVersion() & 0x80000000 ) // Windows 98 code
		nMinThumbSize = nScrollSize / 2;
	else                    
		nMinThumbSize = 8;
	
	// Calculate the arrow rectangles
	RECT rc1 = rect, rc2 = rect;   
	if ( nType == SB_HORZ )
	{
		if ( ( rect.right - rect.left ) < 2 * nScrollSize )
			nScrollSize = ( rect.right - rect.left ) / 2;
		
		rc1.right = rect.left + nScrollSize;
		rc2.left = rect.right - nScrollSize;
	}
	else // SB_VERT
	{
		if ( ( rect.bottom - rect.top ) < 2 * nScrollSize )
			nScrollSize = ( rect.bottom - rect.top ) / 2;
		
		rc1.bottom = rect.top + nScrollSize;      
		rc2.top = rect.bottom - nScrollSize;
	}   
	
	// Draw the scrollbar arrows
	DrawScrollbarThumb( hDC, rc1 );
	DrawScrollbarThumb( hDC, rc2 );
	
	// Disabled scrollbar never have a thumb
	if ( bScrollbarCtrl == TRUE && IsWindowEnabled( m_hWnd ) == FALSE )
		return;      
	
	SCROLLINFO si;
	si.cbSize = sizeof( SCROLLINFO );
	si.fMask = SIF_ALL;     
	GetScrollInfo( m_hWnd, bScrollbarCtrl ? SB_CTL : nType, &si );
	
	// Calculate the size and position of the thumb   
	int nRange = si.nMax - si.nMin + 1;      
	if ( nRange )
	{
		int nScrollArea = ( nType == SB_VERT ? ( rect.bottom - rect.top ) : ( rect.right - rect.left ) ) - 2 * nScrollSize;
		
		int nThumbSize; 
		if ( si.nPage == 0 ) // If nPage is not set then thumb has default size
			nThumbSize = GetSystemMetrics( SM_CXHTHUMB );
		else
			nThumbSize = max( MulDiv( si.nPage ,nScrollArea, nRange ), nMinThumbSize );
		
		if ( nThumbSize >= nScrollArea )
		{
			nThumbSize = nScrollArea;
			if ( bScrollbarCtrl == FALSE )
				return;
		}
		
		int nThumbPos;
		if ( UINT( nRange ) == si.nPage )
		{
			nThumbPos = 0;
			nThumbSize--;
		}
		else
			nThumbPos = MulDiv( si.nPos - si.nMin, nScrollArea - nThumbSize, nRange - si.nPage );
		
		if ( nType == SB_VERT )

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -