2306 lines
75 KiB
C++
2306 lines
75 KiB
C++
|
|
/******************************************************************
|
|
|
|
$Archive: /MfcExt/Source/CoolControlsManager.cpp $
|
|
$Workfile: CoolControlsManager.cpp $
|
|
$Author: Bogdan Ledwig $
|
|
$Date: 99-04-26 22:12 $
|
|
$Revision: 13 $
|
|
|
|
*******************************************************************/
|
|
|
|
#include "StdAfx.h"
|
|
|
|
#include "CoolControlsManager.h"
|
|
|
|
// If you don't want to see extra TRACE diagnostics,
|
|
// modify the line below to: #define CCM_TRACE
|
|
#define CCM_TRACE TRACE
|
|
|
|
#define CCM_TIMER_VAL 100 // 100 ms timer period seems to be good enough...
|
|
#define MAX_CLASSNAME 64 // Length of buffer for retrieving the class name
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
// CCMControl static members initialization
|
|
|
|
HWND CCoolControlsManager::CCMControl::m_hWndOld = NULL;
|
|
CMapPtrToPtr CCoolControlsManager::m_ctrlMap = 10;
|
|
CMapPtrToPtr CCoolControlsManager::m_dlgMap = 10;
|
|
BOOL CCoolControlsManager::m_bEnabled = TRUE;
|
|
|
|
// Changed 02.03.1999 Mike Walter
|
|
CMapWordToPtr CCoolControlsManager::m_threadMap = 10;
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
// Here is the one and only CCoolControlsManager object
|
|
static CCoolControlsManager g_ctrlManager;
|
|
|
|
CCoolControlsManager& GetCtrlManager()
|
|
{
|
|
return g_ctrlManager;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
// WH_CALLWNDPROC hook procedure
|
|
|
|
LRESULT CALLBACK CCM_CallWndProc( int nCode, WPARAM wParam, LPARAM lParam )
|
|
{
|
|
HOOKPROC hHookProc;
|
|
if ( g_ctrlManager.m_threadMap.Lookup( (WORD)GetCurrentThreadId(), (void*&)hHookProc ) == FALSE )
|
|
{
|
|
// TRACE( "CCoolControlsManager: No hook for this thread installed!\n" );
|
|
return 0;
|
|
}
|
|
|
|
if ( nCode == HC_ACTION )
|
|
{
|
|
CWPSTRUCT* pwp = (CWPSTRUCT*)lParam;
|
|
if ( g_ctrlManager.IsEnabled() )
|
|
{
|
|
if ( g_ctrlManager.m_bDialogOnly == TRUE )
|
|
{
|
|
if ( pwp->message == WM_INITDIALOG )
|
|
g_ctrlManager.Install( pwp->hwnd );
|
|
}
|
|
else if ( pwp->message == WM_CREATE && g_ctrlManager.IsEnabled() )
|
|
{
|
|
TCHAR szBuf[MAX_CLASSNAME];
|
|
if ( GetWindowLong( pwp->hwnd, GWL_STYLE ) & WS_CHILD )
|
|
{
|
|
GetClassName( pwp->hwnd, szBuf, MAX_CLASSNAME );
|
|
if ( lstrcmp( szBuf, _T( "ScrollBar" ) ) ) // Don't add scrollbars
|
|
g_ctrlManager.AddControl( pwp->hwnd );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// Changed 02.03.1999 Mike Walter
|
|
return CallNextHookEx( (HHOOK)hHookProc, nCode, wParam, lParam );
|
|
}
|
|
|
|
// Install a hook for the current thread only
|
|
void CCoolControlsManager::InstallHook( DWORD dwThreadID, BOOL bDialogOnly )
|
|
{
|
|
// ASSERT( m_hkWndProc == NULL );
|
|
|
|
m_bDialogOnly = bDialogOnly;
|
|
|
|
// Changes 02.03.1999 Mike Walter
|
|
HOOKPROC hNewHook;
|
|
|
|
if ( m_threadMap.Lookup( (WORD)( dwThreadID == -1 ? GetCurrentThreadId() : dwThreadID ), (void*&)hNewHook ) == FALSE )
|
|
{
|
|
hNewHook = (HOOKPROC)SetWindowsHookEx( WH_CALLWNDPROC,
|
|
(HOOKPROC)CCM_CallWndProc,
|
|
NULL,
|
|
( dwThreadID == -1 ? GetCurrentThreadId() : dwThreadID ) );
|
|
|
|
m_threadMap.SetAt( (WORD)( dwThreadID == -1 ? GetCurrentThreadId() : dwThreadID ), hNewHook );
|
|
|
|
CCM_TRACE( "CCoolControlsManager: WH_CALLWNDPROC hook installed for thread: %d\n", ( dwThreadID == -1 ? GetCurrentThreadId() : dwThreadID ) );
|
|
}
|
|
else
|
|
CCM_TRACE( "CCoolControlsManager: WH_CALLWNDPROC hook already installed for thread: %d!\n", ( dwThreadID == -1 ? GetCurrentThreadId() : dwThreadID ) );
|
|
}
|
|
|
|
// Install a global hook for all windows in the system.
|
|
// This function may be called only when is put in a DLL.
|
|
void CCoolControlsManager::InstallGlobalHook( HINSTANCE hInstance, BOOL bDialogOnly )
|
|
{
|
|
ASSERT( hInstance ); // hInstance must not be NULL!
|
|
ASSERT( m_hkWndProc == NULL );
|
|
|
|
m_bDialogOnly = bDialogOnly;
|
|
|
|
HOOKPROC hkProc = (HOOKPROC)GetProcAddress( hInstance, "CCM_CallWndProc" );
|
|
|
|
m_hkWndProc = (HOOKPROC)SetWindowsHookEx( WH_CALLWNDPROC,
|
|
(HOOKPROC)hkProc,
|
|
hInstance,
|
|
0 );
|
|
|
|
CCM_TRACE( _T( "CCoolControlsManager: WH_CALLWNDPROC global hook installed\n" ) );
|
|
}
|
|
|
|
void CCoolControlsManager::UninstallHook( DWORD dwThreadID )
|
|
{
|
|
// ASSERT( m_hkWndProc != NULL );
|
|
|
|
// Changes 02.03.1999 Mike Walter
|
|
HOOKPROC hHookProc;
|
|
|
|
if ( dwThreadID == -1 )
|
|
{
|
|
if ( g_ctrlManager.m_threadMap.Lookup( (WORD)GetCurrentThreadId(), (void*&)hHookProc ) == FALSE )
|
|
{
|
|
CCM_TRACE( "CCoolControlsManager: No hook installed for thread: %d!\n", GetCurrentThreadId() );
|
|
return;
|
|
}
|
|
|
|
UnhookWindowsHookEx( (HHOOK)hHookProc );
|
|
m_threadMap.RemoveKey( (WORD)GetCurrentThreadId() );
|
|
|
|
CCM_TRACE( "CCoolControlsManager: Hook uninstalled for thread: %d\n", GetCurrentThreadId() );
|
|
CCM_TRACE( "CCoolControlsManager: Thread map has %d items\n",g_ctrlManager.m_threadMap.GetCount() );
|
|
}
|
|
else
|
|
{
|
|
if ( g_ctrlManager.m_threadMap.Lookup( (WORD)dwThreadID, (void*&)hHookProc) == FALSE )
|
|
{
|
|
CCM_TRACE( "CCoolControlsManager: No hook installed for thread: %d!\n", dwThreadID );
|
|
return;
|
|
}
|
|
|
|
UnhookWindowsHookEx( (HHOOK)hHookProc );
|
|
m_threadMap.RemoveKey( (WORD)dwThreadID );
|
|
|
|
CCM_TRACE( "CCoolControlsManager: Hook uninstalled for thread: %d\n", dwThreadID );
|
|
CCM_TRACE( "CCoolControlsManager: Thread map has %d items\n", g_ctrlManager.m_threadMap.GetCount() );
|
|
}
|
|
|
|
if ( m_uTimerID && g_ctrlManager.m_threadMap.IsEmpty() == TRUE )
|
|
KillTimer( NULL, m_uTimerID );
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// Construction/Destruction
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
CCoolControlsManager::CCoolControlsManager()
|
|
{
|
|
m_hkWndProc = NULL;
|
|
m_uTimerID = 0;
|
|
CCM_TRACE( _T( "CCoolControlsManager::CCoolControlsManager()\n" ) );
|
|
}
|
|
|
|
CCoolControlsManager::~CCoolControlsManager()
|
|
{
|
|
// Changed 02.03.1999 Mike Walter
|
|
POSITION pos = m_threadMap.GetStartPosition();
|
|
|
|
while ( pos )
|
|
{
|
|
HOOKPROC hHook;
|
|
DWORD dwThreadID = 0;
|
|
|
|
m_threadMap.GetNextAssoc( pos, (WORD&)dwThreadID, (void*&)hHook );
|
|
UninstallHook( dwThreadID );
|
|
}
|
|
|
|
// If we have any elements in the map (normally impossible), unsubclass they and remove
|
|
pos = m_ctrlMap.GetStartPosition();
|
|
|
|
while ( pos )
|
|
{
|
|
HWND hWnd;
|
|
|
|
CCMControl* pCtl;
|
|
m_ctrlMap.GetNextAssoc( pos, (void*&)hWnd, (void*&)pCtl );
|
|
pCtl->Unsubclass();
|
|
m_ctrlMap.RemoveKey( hWnd );
|
|
delete pCtl;
|
|
}
|
|
|
|
// Now do the same things for dialog map
|
|
pos = m_dlgMap.GetStartPosition();
|
|
|
|
while ( pos )
|
|
{
|
|
HWND hWnd;
|
|
CCMDialog* pCtl;
|
|
m_dlgMap.GetNextAssoc( pos, (void*&)hWnd, (void*&)pCtl );
|
|
|
|
pCtl->Unsubclass();
|
|
m_dlgMap.RemoveKey( hWnd );
|
|
delete pCtl;
|
|
}
|
|
|
|
CCM_TRACE( "CCoolControlsManager::~CCoolControlsManager()\n" );
|
|
}
|
|
|
|
void CCoolControlsManager::Install( HWND hWnd )
|
|
{
|
|
CCMControl* pCtl;
|
|
if ( m_dlgMap.Lookup( hWnd, (void*&)pCtl ) ) // Already in the dialog map
|
|
return;
|
|
|
|
// Iterate through all child windows
|
|
HWND hCtrl = GetTopWindow( hWnd );
|
|
|
|
while ( hCtrl )
|
|
{
|
|
if ( GetWindowLong( hCtrl, GWL_STYLE ) & WS_CHILD )
|
|
{
|
|
TCHAR szBuf[MAX_CLASSNAME];
|
|
GetClassName( hCtrl, szBuf, MAX_CLASSNAME );
|
|
if ( lstrcmpi( szBuf, _T( "#32770" ) ) ) // Never add child dialogs!
|
|
AddControl( hCtrl );
|
|
}
|
|
hCtrl = GetNextWindow( hCtrl, GW_HWNDNEXT );
|
|
}
|
|
|
|
AddDialog( hWnd ); // Add parent window as well
|
|
|
|
// Now redraw all recently inserted controls
|
|
hCtrl = GetTopWindow( hWnd );
|
|
while ( hCtrl )
|
|
{
|
|
if ( m_ctrlMap.Lookup( hCtrl, (void*&)pCtl ) )
|
|
pCtl->DrawBorder();
|
|
hCtrl = GetNextWindow( hCtrl, GW_HWNDNEXT );
|
|
}
|
|
}
|
|
|
|
void CCoolControlsManager::Uninstall( HWND hWnd )
|
|
{
|
|
// Remove all window controls from the map
|
|
// when the window is about to destroy
|
|
CCM_TRACE( _T( "CCoolControlsManager: Uninstall, handle: %X\n" ), hWnd );
|
|
|
|
HWND hCtrl = GetTopWindow( hWnd );
|
|
while ( hCtrl )
|
|
{
|
|
if ( GetWindowLong( hCtrl, GWL_STYLE ) & WS_CHILD )
|
|
RemoveControl( hCtrl );
|
|
hCtrl = GetNextWindow( hCtrl, GW_HWNDNEXT );
|
|
}
|
|
}
|
|
|
|
// In lpszClass you can specify class name, which will be used
|
|
// instead of true class name (useful for non-standard controls
|
|
// that are similar to the one of those we have supported)
|
|
BOOL CCoolControlsManager::AddControl( HWND hWnd, LPCTSTR lpszClass )
|
|
{
|
|
CCMControl* pCtl = NULL;
|
|
|
|
// Must not be NULL or already in the map
|
|
if ( hWnd == NULL || m_ctrlMap.Lookup( hWnd, (void*&)pCtl ) )
|
|
return FALSE;
|
|
|
|
TCHAR szBuf[MAX_CLASSNAME];
|
|
if ( lpszClass == NULL )
|
|
GetClassName( hWnd, szBuf, MAX_CLASSNAME );
|
|
else
|
|
lstrcpy( szBuf, lpszClass );
|
|
|
|
DWORD dwStyle = GetWindowLong( hWnd, GWL_STYLE );
|
|
DWORD dwExStyle = GetWindowLong( hWnd, GWL_EXSTYLE );
|
|
|
|
if ( !lstrcmpi( szBuf, _T( "Button" ) ) )
|
|
{
|
|
if ( ( dwStyle & BS_OWNERDRAW ) == BS_OWNERDRAW )
|
|
return FALSE; // Do not subclass ownerdraw buttons
|
|
else if ( ( dwStyle & BS_GROUPBOX ) == BS_GROUPBOX ||
|
|
( dwStyle & BS_FLAT ) == BS_FLAT )
|
|
return FALSE; // Skip all group boxes and flat buttons
|
|
else if ( ( dwStyle & BS_AUTOCHECKBOX ) == BS_AUTOCHECKBOX ||
|
|
( dwStyle & BS_CHECKBOX ) == BS_CHECKBOX ||
|
|
( dwStyle & BS_3STATE ) == BS_3STATE )
|
|
pCtl = new CCMCheckBox;
|
|
else if ( ( dwStyle & BS_AUTORADIOBUTTON ) == BS_AUTORADIOBUTTON ||
|
|
( dwStyle & BS_RADIOBUTTON ) == BS_RADIOBUTTON )
|
|
pCtl = new CCMRadioButton;
|
|
else
|
|
pCtl = new CCMPushButton; // If none of the above then it must be a pushbutton!
|
|
}
|
|
else if ( !lstrcmpi( szBuf, _T( "ComboBox" ) ) )
|
|
{
|
|
// Special case for simple comboboxes
|
|
if ( ( dwStyle & 0x03 ) == CBS_SIMPLE )
|
|
{
|
|
hWnd = GetTopWindow( hWnd );
|
|
while ( hWnd )
|
|
{
|
|
AddControl( hWnd );
|
|
hWnd = GetNextWindow( hWnd, GW_HWNDNEXT );
|
|
}
|
|
return FALSE;
|
|
}
|
|
else
|
|
pCtl = new CCMComboBox;
|
|
}
|
|
else if ( !lstrcmpi( szBuf, _T( "Edit" ) ) )
|
|
{
|
|
// Edit window in a simple combobox
|
|
GetClassName( GetParent( hWnd ), szBuf, MAX_CLASSNAME );
|
|
if ( !lstrcmpi( szBuf, _T( "ComboBox" ) ) &&
|
|
( GetWindowLong( GetParent( hWnd ), GWL_STYLE ) & 0x03 ) == CBS_SIMPLE )
|
|
pCtl = new CCMEditCombo;
|
|
else
|
|
{
|
|
if ( dwExStyle & WS_EX_CLIENTEDGE )
|
|
pCtl = new CCMEdit;
|
|
}
|
|
#if defined _DEBUG
|
|
lstrcpy( szBuf, _T( "Edit" ) );
|
|
#endif
|
|
}
|
|
else if ( !lstrcmpi( szBuf, _T( "ListBox" ) ) )
|
|
{
|
|
if ( dwExStyle & WS_EX_CLIENTEDGE )
|
|
pCtl = new CCMControl;
|
|
}
|
|
else if ( !lstrcmpi( szBuf, _T( "SysListView32" ) ) )
|
|
{
|
|
if ( dwExStyle & WS_EX_CLIENTEDGE )
|
|
{
|
|
pCtl = new CCMControl;
|
|
AddControl( GetTopWindow( hWnd ) ); // Don't forget to add the header control
|
|
}
|
|
}
|
|
else if ( !lstrcmpi( szBuf, _T( "SHELLDLL_DefView" ) ) ) // In open/save common dialogs
|
|
{
|
|
AddControl( GetTopWindow( hWnd ) ); // Add child ListView control
|
|
return FALSE;
|
|
}
|
|
else if ( !lstrcmpi( szBuf, _T( "SysTreeView32" ) ) )
|
|
{
|
|
if ( dwExStyle & WS_EX_CLIENTEDGE )
|
|
pCtl = new CCMControl;
|
|
}
|
|
else if ( !lstrcmpi( szBuf, _T( "SysDateTimePick32" ) ) )
|
|
{
|
|
if ( dwExStyle & WS_EX_CLIENTEDGE )
|
|
{
|
|
pCtl = new CCMDateTime;
|
|
if ( dwStyle & DTS_UPDOWN )
|
|
AddControl( GetTopWindow( hWnd ) ); // Add up-down control as well
|
|
}
|
|
}
|
|
else if ( !lstrcmpi( szBuf, _T( "SysMonthCal32" ) ) )
|
|
pCtl = new CCMControl;
|
|
else if ( !lstrcmpi( szBuf, _T( "msctls_updown32" ) ) )
|
|
pCtl = new CCMUpDown;
|
|
else if ( !lstrcmpi( szBuf, _T( "ComboLBox" ) ) )
|
|
{
|
|
if ( dwExStyle & WS_EX_CLIENTEDGE )
|
|
pCtl = new CCMControl;
|
|
}
|
|
else if ( !lstrcmpi( szBuf, _T( "ScrollBar" ) ) )
|
|
{
|
|
if ( !( dwStyle & SBS_SIZEBOX ) && !( dwStyle & SBS_SIZEGRIP ) )
|
|
pCtl = new CCMScrollBar;
|
|
}
|
|
else if ( !lstrcmpi( szBuf, _T( "ComboBoxEx32" ) ) )
|
|
{
|
|
AddControl( GetTopWindow( hWnd ) );
|
|
return FALSE;
|
|
}
|
|
else if ( !lstrcmpi( szBuf, _T( "msctls_hotkey32" ) ) )
|
|
{
|
|
if ( dwExStyle & WS_EX_CLIENTEDGE )
|
|
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 );
|
|
|
|
// 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 )
|
|
{
|
|
rc1.top += nScrollSize + nThumbPos;
|
|
rc1.bottom = rc1.top + nThumbSize;
|
|
}
|
|
else // SB_HORZ
|
|
{
|
|
rc1.left += nScrollSize + nThumbPos;
|
|
rc1.right = rc1.left + nThumbSize;
|
|
}
|
|
|
|
if ( nThumbSize <= nScrollArea ) // Don't draw the thumb when it's larger than the scroll area
|
|
DrawScrollbarThumb( hDC, rc1 );
|
|
}
|
|
}
|
|
|
|
BOOL CCoolControlsManager::CCMControl::IsFocused()
|
|
{
|
|
return m_hWnd == GetFocus() ? TRUE : FALSE;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// CCMEdit class
|
|
|
|
void CCoolControlsManager::CCMEdit::DrawControl( HDC hDC, const RECT& rc )
|
|
{
|
|
RECT rect = rc;
|
|
|
|
// Check if edit window has an associated up-down control.
|
|
// If so draw a border around both controls
|
|
HWND hWnd = GetNextWindow( m_hWnd, GW_HWNDNEXT );
|
|
|
|
if ( hWnd )
|
|
{
|
|
TCHAR szBuf[MAX_CLASSNAME];
|
|
// Retrieve window class name
|
|
GetClassName( hWnd, szBuf, MAX_CLASSNAME );
|
|
if ( lstrcmpi( szBuf, _T( "msctls_updown32" ) ) == 0 ) // Up-down is found
|
|
{
|
|
DWORD dwStyle = GetWindowLong( hWnd, GWL_STYLE );
|
|
if ( ( dwStyle & UDS_ALIGNRIGHT || dwStyle & UDS_ALIGNLEFT ) &&
|
|
SendMessage( hWnd, UDM_GETBUDDY, 0, 0L ) == (LONG)m_hWnd )
|
|
{
|
|
RECT rc;
|
|
GetWindowRect( hWnd, &rc );
|
|
const int nEdge = GetSystemMetrics( SM_CXEDGE );
|
|
if ( dwStyle & UDS_ALIGNRIGHT )
|
|
rect.right += ( rc.right - rc.left ) - nEdge;
|
|
else // UDS_ALIGNLEFT
|
|
rect.left -= ( rc.right - rc.left ) - nEdge;
|
|
|
|
HDC hDC = GetDC( hWnd ); // We must draw the lines onto spin control DC
|
|
|
|
COLORREF clr = GetSysColor( m_nState & dsHoverMask ? COLOR_3DDKSHADOW : COLOR_3DHIGHLIGHT );
|
|
if ( !IsWindowEnabled( m_hWnd ) )
|
|
clr = GetSysColor( COLOR_3DFACE );
|
|
FillSolidRect( hDC, 1, 1, rc.right - rc.left - nEdge - 1, 1, clr );
|
|
if ( dwStyle & UDS_ALIGNLEFT )
|
|
FillSolidRect( hDC, 1, 1, 1, rc.bottom - rc.top - nEdge - 1, clr );
|
|
|
|
ReleaseDC( hWnd, hDC );
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( GetWindowLong( m_hWnd, GWL_STYLE ) & ES_READONLY )
|
|
m_nState |= dsDisabled;
|
|
else
|
|
m_nState &= ~dsDisabled;
|
|
CCMControl::DrawControl( hDC, rect );
|
|
}
|
|
|
|
LRESULT CCoolControlsManager::CCMEdit::WindowProc( UINT uMsg, WPARAM wParam, LPARAM lParam )
|
|
{
|
|
switch ( uMsg )
|
|
{
|
|
case WM_ENABLE:
|
|
{
|
|
CallWindowProc( m_oldWndProc, m_hWnd, uMsg, wParam, lParam );
|
|
DrawBorder();
|
|
HWND hWnd = GetNextWindow( m_hWnd, GW_HWNDNEXT );
|
|
if ( hWnd )
|
|
{
|
|
TCHAR szBuf[MAX_CLASSNAME];
|
|
// Retrieve window class name
|
|
GetClassName( hWnd, szBuf, MAX_CLASSNAME );
|
|
if ( lstrcmpi( szBuf, _T( "msctls_updown32" ) ) == 0 && // Up-down is found
|
|
SendMessage( hWnd, UDM_GETBUDDY, 0, 0L ) == (LONG)m_hWnd )
|
|
SendMessage( hWnd, WM_PAINT, 0, 0L ); // Repaint up-down too
|
|
}
|
|
}
|
|
return 0;
|
|
|
|
default:
|
|
return CCMControl::WindowProc( uMsg, wParam, lParam );
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// CCMComboBox class
|
|
|
|
void CCoolControlsManager::CCMComboBox::DrawControl( HDC hDC, const RECT& rect )
|
|
{
|
|
// First, draw borders around the control
|
|
CCMControl::DrawControl( hDC, rect );
|
|
|
|
// Now, we have to draw borders around the drop-down arrow
|
|
RECT rc = rect;
|
|
InflateRect( &rc, -2, -2 );
|
|
rc.left = rc.right - GetSystemMetrics( SM_CXHSCROLL );
|
|
|
|
if ( IsWindowEnabled( m_hWnd ) == TRUE )
|
|
{
|
|
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 );
|
|
}
|
|
else
|
|
Draw3dBorder( hDC, rc, COLOR_3DFACE, COLOR_3DFACE,
|
|
COLOR_3DFACE, COLOR_3DFACE );
|
|
}
|
|
|
|
BOOL CCoolControlsManager::CCMComboBox::IsFocused()
|
|
{
|
|
// Special case for drop-down and simple ComboBoxes
|
|
// which contain child edit control and focus always
|
|
// goes to that edit window
|
|
if ( ( GetWindowLong( m_hWnd, GWL_STYLE ) & 0x03 ) == CBS_DROPDOWN )
|
|
{
|
|
HWND hWnd = GetTopWindow( m_hWnd );
|
|
if ( hWnd && hWnd == GetFocus() )
|
|
return TRUE;
|
|
}
|
|
|
|
return CCMControl::IsFocused();
|
|
}
|
|
|
|
LRESULT CCoolControlsManager::CCMComboBox::WindowProc( UINT uMsg, WPARAM wParam, LPARAM lParam )
|
|
{
|
|
switch ( uMsg )
|
|
{
|
|
// Drop-down ComboBox receives neither WM_SETFOCUS nor WM_KILLFOCUS
|
|
// Instead, it receives these next two messages
|
|
case WM_LBUTTONUP: // For kill focus
|
|
if ( lParam == -1 )
|
|
DrawBorder();
|
|
break;
|
|
|
|
case WM_COMMAND:
|
|
if ( HIWORD( wParam ) == EN_SETFOCUS )
|
|
DrawBorder();
|
|
break;
|
|
|
|
default:
|
|
return CCMControl::WindowProc( uMsg, wParam, lParam );
|
|
}
|
|
|
|
return CallWindowProc( m_oldWndProc, m_hWnd, uMsg, wParam, lParam );
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// CCMDateTime class
|
|
|
|
void CCoolControlsManager::CCMDateTime::DrawControl( HDC hDC, const RECT& rc )
|
|
{
|
|
if ( GetWindowLong( m_hWnd, GWL_STYLE ) & DTS_UPDOWN )
|
|
CCMControl::DrawControl( hDC, rc );
|
|
else
|
|
CCMComboBox::DrawControl( hDC, rc );
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// CCMPushButton class
|
|
|
|
void CCoolControlsManager::CCMPushButton::DrawControl( HDC hDC, const RECT& rc )
|
|
{
|
|
BOOL bDefault = FALSE;
|
|
// Unfortunately BS_DEFPUSHBUTTON is defined as 0x00000001L,
|
|
// and BS_OWNERDRAW as 0x0000000BL (see winuser.h) so we cannot
|
|
// determine the default button for owner-draw controls
|
|
DWORD dwStyle = GetWindowLong( m_hWnd, GWL_STYLE ) & BS_OWNERDRAW;
|
|
|
|
if ( dwStyle != BS_OWNERDRAW )
|
|
{
|
|
if ( dwStyle == BS_DEFPUSHBUTTON && IsWindowEnabled( m_hWnd ) )
|
|
bDefault = TRUE;
|
|
}
|
|
|
|
int nCheck = SendMessage( m_hWnd, BM_GETCHECK, 0, 0 );
|
|
if ( m_nState & dsHoverMask )
|
|
{
|
|
if ( bDefault == TRUE )
|
|
{
|
|
Draw3dBorder( hDC, rc, COLOR_3DDKSHADOW, COLOR_3DDKSHADOW,
|
|
COLOR_3DHIGHLIGHT, COLOR_3DDKSHADOW,
|
|
COLOR_3DLIGHT, COLOR_3DSHADOW );
|
|
}
|
|
else
|
|
{
|
|
if ( nCheck )
|
|
Draw3dBorder( hDC, rc, COLOR_3DDKSHADOW, COLOR_3DHIGHLIGHT,
|
|
COLOR_3DSHADOW, COLOR_3DLIGHT );
|
|
else
|
|
Draw3dBorder( hDC, rc, COLOR_3DHIGHLIGHT, COLOR_3DDKSHADOW,
|
|
COLOR_3DLIGHT, COLOR_3DSHADOW,
|
|
COLOR_3DFACE, COLOR_3DFACE );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( bDefault == TRUE )
|
|
{
|
|
Draw3dBorder( hDC, rc, COLOR_3DDKSHADOW, COLOR_3DDKSHADOW,
|
|
COLOR_3DHIGHLIGHT, COLOR_3DSHADOW,
|
|
COLOR_3DFACE, COLOR_3DFACE );
|
|
}
|
|
else
|
|
{
|
|
if ( nCheck )
|
|
Draw3dBorder( hDC, rc, COLOR_3DSHADOW, COLOR_3DHIGHLIGHT,
|
|
COLOR_3DFACE, COLOR_3DFACE );
|
|
else
|
|
Draw3dBorder( hDC, rc, COLOR_3DHIGHLIGHT, COLOR_3DSHADOW,
|
|
COLOR_3DFACE, COLOR_3DFACE,
|
|
COLOR_3DFACE, COLOR_3DFACE );
|
|
}
|
|
}
|
|
}
|
|
|
|
LRESULT CCoolControlsManager::CCMPushButton::WindowProc( UINT uMsg, WPARAM wParam, LPARAM lParam )
|
|
{
|
|
switch ( uMsg )
|
|
{
|
|
// Button messages
|
|
case BM_SETCHECK:
|
|
case WM_SETTEXT:
|
|
CallWindowProc( m_oldWndProc, m_hWnd, uMsg, wParam, lParam );
|
|
DrawBorder();
|
|
return 0;
|
|
|
|
default:
|
|
return CCMControl::WindowProc( uMsg, wParam, lParam );
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// CCMCheckBox class
|
|
|
|
void CCoolControlsManager::CCMCheckBox::DrawControl( HDC hDC, const RECT& rect )
|
|
{
|
|
DWORD dwStyle = GetWindowLong( m_hWnd, GWL_STYLE );
|
|
|
|
if ( dwStyle & BS_PUSHLIKE )
|
|
{
|
|
CCMPushButton::DrawControl( hDC, rect );
|
|
return;
|
|
}
|
|
|
|
RECT rc;
|
|
|
|
// Checkmark square size, hard coded here because I couldn't find any
|
|
// method to obtain this value from the system.
|
|
// Maybe someone else knows how to do it? If so, please let me know!
|
|
const int nCheckSize = 13;
|
|
|
|
if ( ( dwStyle & BS_VCENTER ) == BS_VCENTER )
|
|
rc.top = rect.top + ( ( rect.bottom - rect.top ) - nCheckSize ) / 2;
|
|
else if ( dwStyle & BS_TOP )
|
|
rc.top = rect.top + 1;
|
|
else if ( dwStyle & BS_BOTTOM )
|
|
rc.top = rect.bottom - nCheckSize - 2;
|
|
else // Default
|
|
rc.top = rect.top + ( ( rect.bottom - rect.top ) - nCheckSize ) / 2;
|
|
|
|
if ( dwStyle & BS_LEFTTEXT )
|
|
rc.left = rect.right - nCheckSize;
|
|
else
|
|
rc.left = rect.left;
|
|
|
|
rc.right = rc.left + nCheckSize;
|
|
rc.bottom = rc.top + nCheckSize;
|
|
|
|
if ( m_nState & dsHoverMask )
|
|
{
|
|
Draw3dBorder( hDC, rc, COLOR_3DDKSHADOW, COLOR_3DHIGHLIGHT,
|
|
COLOR_3DSHADOW, COLOR_3DFACE );
|
|
}
|
|
else
|
|
{
|
|
if ( IsWindowEnabled( m_hWnd ) == TRUE )
|
|
{
|
|
int nState = SendMessage( m_hWnd, BM_GETCHECK, 0, 0L );
|
|
Draw3dBorder( hDC, rc, COLOR_3DSHADOW, COLOR_3DHIGHLIGHT,
|
|
nState == 2 ? COLOR_3DHIGHLIGHT : COLOR_WINDOW,
|
|
nState == 2 ? COLOR_3DHIGHLIGHT : COLOR_WINDOW );
|
|
}
|
|
else
|
|
Draw3dBorder( hDC, rc, COLOR_3DSHADOW, COLOR_3DHIGHLIGHT,
|
|
COLOR_3DFACE, COLOR_3DFACE );
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// CCMRadioButton class
|
|
|
|
void CCoolControlsManager::CCMRadioButton::DrawFrame( POINT* ptArr, int nColor,
|
|
HDC hDC, int xOff, int yOff )
|
|
{
|
|
for ( int i = 0; ; i++ )
|
|
{
|
|
if ( !ptArr[i].x && !ptArr[i].y )
|
|
return;
|
|
|
|
SetPixel( hDC, ptArr[i].x + xOff, ptArr[i].y + yOff, GetSysColor( nColor ) );
|
|
}
|
|
}
|
|
|
|
void CCoolControlsManager::CCMRadioButton::DrawControl( HDC hDC, const RECT& rect )
|
|
{
|
|
DWORD dwStyle = GetWindowLong( m_hWnd, GWL_STYLE );
|
|
|
|
if ( dwStyle & BS_PUSHLIKE )
|
|
{
|
|
CCMPushButton::DrawControl( hDC, rect );
|
|
return;
|
|
}
|
|
|
|
const int nRadioSize = 12;
|
|
RECT rc;
|
|
|
|
if ( ( dwStyle & BS_VCENTER ) == BS_VCENTER )
|
|
rc.top = rect.top + ( ( rect.bottom - rect.top ) - nRadioSize - 1 ) / 2;
|
|
else if ( dwStyle & BS_TOP )
|
|
rc.top = rect.top + 1;
|
|
else if ( dwStyle & BS_BOTTOM )
|
|
rc.top = rect.bottom - nRadioSize - 3;
|
|
else // Default
|
|
rc.top = rect.top + ( ( rect.bottom - rect.top ) - nRadioSize - 1 ) / 2;
|
|
|
|
if ( dwStyle & BS_LEFTTEXT )
|
|
rc.left = rect.right - nRadioSize;
|
|
else
|
|
rc.left = rect.left + 1;
|
|
|
|
rc.right = rc.left + nRadioSize;
|
|
rc.bottom = rc.top + nRadioSize;
|
|
|
|
POINT pt1[] = {
|
|
{ 1,9 },{ 1,8 },
|
|
{ 0,7 },{ 0,6 },{ 0,5 },{ 0,4 },
|
|
{ 1,3 },{ 1,2 },
|
|
{ 2,1 },{ 3,1 },
|
|
{ 4,0 },{ 5,0 },{ 6,0 },{ 7,0 },
|
|
{ 8,1 },{ 9,1 },
|
|
{ 0,0 }
|
|
};
|
|
|
|
POINT pt2[] = {
|
|
{ 2,8 },
|
|
{ 1,7 },{ 1,6 },{ 1,5 },{ 1,4 },
|
|
{ 2,3 },{ 2,2 },
|
|
{ 3,2 },
|
|
{ 4,1 },{ 5,1 },{ 6,1 },{ 7,1 },
|
|
{ 8,2 },{ 9,2 },
|
|
{ 0,0 }
|
|
};
|
|
|
|
|
|
POINT pt3[] = {
|
|
{ 2,9 },{ 3,9 },
|
|
{ 4,10 },{ 5,10 },{ 6,10 },{ 7,10 },
|
|
{ 8,9 },{ 9,9 },
|
|
{ 9,8 },
|
|
{ 10,7 },{ 10,6 },{ 10,5 },{ 10,4 },
|
|
{ 9,3 },
|
|
{ 0,0 }
|
|
};
|
|
|
|
POINT pt4[] = {
|
|
{ 2,10 },{ 3,10 },
|
|
{ 4,11 },{ 5,11 },{ 6,11 },{ 7,11 },
|
|
{ 8,10 },{ 9,10 },
|
|
{ 10,9 },{ 10,8 },
|
|
{ 11,7 },{ 11,6 },{ 11,5 },{ 11,4 },
|
|
{ 10,3 },{ 10,2 },
|
|
{ 0,0 }
|
|
};
|
|
|
|
if ( m_nState & dsHoverMask )
|
|
{
|
|
DrawFrame( pt1, COLOR_3DSHADOW,
|
|
hDC, rc.left, rc.top );
|
|
DrawFrame( pt2, COLOR_3DDKSHADOW,
|
|
hDC, rc.left, rc.top );
|
|
DrawFrame( pt3, COLOR_3DFACE,
|
|
hDC, rc.left, rc.top );
|
|
DrawFrame( pt4, COLOR_WINDOW,
|
|
hDC, rc.left, rc.top );
|
|
}
|
|
else
|
|
{
|
|
if ( IsWindowEnabled( m_hWnd ) == TRUE )
|
|
{
|
|
DrawFrame( pt1, COLOR_3DSHADOW,
|
|
hDC, rc.left, rc.top );
|
|
DrawFrame( pt2, COLOR_WINDOW,
|
|
hDC, rc.left, rc.top );
|
|
DrawFrame( pt3, COLOR_3DFACE,
|
|
hDC, rc.left, rc.top );
|
|
DrawFrame( pt4, COLOR_WINDOW,
|
|
hDC, rc.left, rc.top );
|
|
}
|
|
else
|
|
{
|
|
DrawFrame( pt1, COLOR_3DSHADOW,
|
|
hDC, rc.left, rc.top );
|
|
DrawFrame( pt2, COLOR_3DFACE,
|
|
hDC, rc.left, rc.top );
|
|
DrawFrame( pt3, COLOR_3DFACE,
|
|
hDC, rc.left, rc.top );
|
|
DrawFrame( pt4, COLOR_3DHIGHLIGHT,
|
|
hDC, rc.left, rc.top );
|
|
}
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// CCMUpDown class
|
|
|
|
void CCoolControlsManager::CCMUpDown::DrawButton( HDC hDC, const RECT& rc )
|
|
{
|
|
// If associated edit control is disabled
|
|
// draw the up-down as disabled too
|
|
BOOL bEnabled = IsWindowEnabled( m_hWnd );
|
|
HWND hWnd = (HWND)SendMessage( m_hWnd, UDM_GETBUDDY, 0, 0L );
|
|
if ( hWnd )
|
|
bEnabled = IsWindowEnabled( hWnd );
|
|
|
|
if ( bEnabled && 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::CCMUpDown::DrawControl( HDC hDC, const RECT& rect )
|
|
{
|
|
RECT rc = rect;
|
|
CCMControl* pCtl = NULL;
|
|
DWORD dwStyle = GetWindowLong( m_hWnd, GWL_STYLE );
|
|
HWND hWnd = (HWND)SendMessage( m_hWnd, UDM_GETBUDDY, 0, 0L );
|
|
if ( hWnd && ( dwStyle & UDS_ALIGNRIGHT || dwStyle & UDS_ALIGNLEFT ) )
|
|
{
|
|
if ( dwStyle & UDS_ALIGNLEFT )
|
|
rc.left += 2;
|
|
else // UDS_ALIGNRIGHT
|
|
rc.right -= 2;
|
|
rc.top += 2;
|
|
rc.bottom -= 2;
|
|
|
|
if ( g_ctrlManager.m_ctrlMap.Lookup( hWnd, (void*&)pCtl ) &&
|
|
!( pCtl->GetState() & dsHoverMask ) )
|
|
{
|
|
COLORREF clr1 = GetSysColor( IsWindowEnabled( hWnd ) ? COLOR_3DHIGHLIGHT : COLOR_3DFACE );
|
|
COLORREF clr2 = GetSysColor( IsWindowEnabled( hWnd ) ? COLOR_3DLIGHT : COLOR_3DFACE );
|
|
|
|
FillSolidRect( hDC, rc.left, rc.top - 1,
|
|
rc.right, 1,
|
|
clr1 );
|
|
FillSolidRect( hDC, rc.left, rc.bottom,
|
|
rc.right, 1,
|
|
clr2 );
|
|
|
|
if ( dwStyle & UDS_ALIGNLEFT )
|
|
FillSolidRect( hDC, rc.left - 1, rc.top - 1,
|
|
1, rc.bottom,
|
|
clr1 );
|
|
else
|
|
FillSolidRect( hDC, rc.right, rc.top - 1,
|
|
1, rc.bottom,
|
|
clr2 );
|
|
}
|
|
}
|
|
|
|
RECT r = rc;
|
|
if ( dwStyle & UDS_HORZ )
|
|
{
|
|
r.right = r.left + ( rc.right - rc.left ) / 2;
|
|
DrawButton( hDC, r );
|
|
|
|
r.left = r.right + ( rc.right - rc.left ) % 2;
|
|
r.right = rc.right;
|
|
DrawButton( hDC, r );
|
|
}
|
|
else
|
|
{
|
|
r.bottom = r.top + ( rc.bottom - rc.top ) / 2;
|
|
DrawButton( hDC, r );
|
|
|
|
r.top = r.bottom + ( rc.bottom - rc.top ) % 2;
|
|
r.bottom = rc.bottom;
|
|
DrawButton( hDC, r );
|
|
}
|
|
|
|
if ( pCtl == NULL ) // Get parent (e.g. for datetime with up-down controls)
|
|
{
|
|
hWnd = GetParent( m_hWnd );
|
|
g_ctrlManager.m_ctrlMap.Lookup( hWnd, (void*&)pCtl );
|
|
}
|
|
|
|
if ( pCtl && IsWindowEnabled( hWnd ) ) // Redraw parent or buddy if neccesary
|
|
{
|
|
if ( m_nState & dsHoverMask )
|
|
pCtl->SetState( 0, dsHover );
|
|
else
|
|
pCtl->SetState( dsHover, 0 );
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// CCMEditCombo class
|
|
|
|
void CCoolControlsManager::CCMEditCombo::PrepareDraw( HDC& hDC, RECT& rect )
|
|
{
|
|
GetWindowRect( m_hWnd, &rect );
|
|
InflateRect( &rect, 3, 3 );
|
|
OffsetRect( &rect, -rect.left, -rect.top );
|
|
// Draw onto that DC that is most suitable for given class
|
|
hDC = GetWindowDC( GetParent( m_hWnd ) );
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// CCMScrollBar class
|
|
|
|
void CCoolControlsManager::CCMScrollBar::DrawControl( HDC hDC, const RECT& rc )
|
|
{
|
|
DrawScrollBar( hDC, rc,
|
|
( GetWindowLong( m_hWnd, GWL_STYLE ) & SBS_VERT ) ? SB_VERT : SB_HORZ,
|
|
TRUE );
|
|
}
|
|
|
|
LRESULT CCoolControlsManager::CCMScrollBar::WindowProc( UINT uMsg, WPARAM wParam, LPARAM lParam )
|
|
{
|
|
switch ( uMsg )
|
|
{
|
|
// Scrollbar messages
|
|
case SBM_SETPOS:
|
|
if ( !lParam ) // redraw flag
|
|
break;
|
|
|
|
case SBM_SETSCROLLINFO:
|
|
if ( !wParam ) // redraw flag
|
|
break;
|
|
|
|
case SBM_SETRANGEREDRAW:
|
|
CallWindowProc( m_oldWndProc, m_hWnd, uMsg, wParam, lParam );
|
|
DrawBorder();
|
|
return 0;
|
|
|
|
default:
|
|
return CCMControl::WindowProc( uMsg, wParam, lParam );
|
|
}
|
|
|
|
return CallWindowProc( m_oldWndProc, m_hWnd, uMsg, wParam, lParam );
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// CCMHeaderCtrl class
|
|
|
|
void CCoolControlsManager::CCMHeaderCtrl::DrawButton( HDC hDC, const RECT& rc, int nState )
|
|
{
|
|
if ( nState & dsHoverMask )
|
|
Draw3dBorder( hDC, rc, COLOR_3DHIGHLIGHT, COLOR_3DDKSHADOW,
|
|
COLOR_3DLIGHT, COLOR_3DSHADOW );
|
|
else
|
|
Draw3dBorder( hDC, rc, COLOR_3DHIGHLIGHT, COLOR_3DSHADOW,
|
|
COLOR_3DFACE, COLOR_3DFACE );
|
|
}
|
|
|
|
void CCoolControlsManager::CCMHeaderCtrl::DrawControl( HDC hDC, const RECT& /*rc*/ )
|
|
{
|
|
int nOldItem = m_nOldItem;
|
|
m_nOldItem = -1;
|
|
|
|
RECT rc;
|
|
POINT point;
|
|
GetCursorPos( &point );
|
|
|
|
// This code fails if we will have standalone header control but such cases are rare...
|
|
HWND hWnd = GetParent( m_hWnd );
|
|
GetClientRect( GetParent( m_hWnd ), &rc );
|
|
ScreenToClient( GetParent( m_hWnd ), &point );
|
|
// Test if mouse pointer is within the client area of the list control
|
|
BOOL bInView = PtInRect( &rc, point );
|
|
|
|
GetClientRect( m_hWnd, &rc );
|
|
rc.right = 0;
|
|
GetCursorPos( &point );
|
|
ScreenToClient( m_hWnd, &point );
|
|
hDC = GetDC( m_hWnd );
|
|
|
|
int nState;
|
|
int nCount = SendMessage( m_hWnd, HDM_GETITEMCOUNT, 0, 0L );
|
|
|
|
for ( int i = 0; i < nCount; i++ )
|
|
{
|
|
#if (_WIN32_IE >= 0x0300)
|
|
HDITEM hi;
|
|
hi.mask = HDI_ORDER;
|
|
SendMessage( m_hWnd, HDM_GETITEM, i, (LPARAM)&hi );
|
|
SendMessage( m_hWnd, HDM_GETITEMRECT, hi.iOrder, (LPARAM)&rc );
|
|
#else
|
|
SendMessage( m_hWnd, HDM_GETITEMRECT, i, (LPARAM)&rc );
|
|
#endif
|
|
nState = 0;
|
|
if ( bInView & PtInRect( &rc, point ) )
|
|
{
|
|
nState = dsHover;
|
|
#if (_WIN32_IE >= 0x0300)
|
|
m_nOldItem = hi.iOrder;
|
|
#else
|
|
m_nOldItem = i;
|
|
#endif
|
|
}
|
|
DrawButton( hDC, rc, nState );
|
|
}
|
|
|
|
int l = rc.right;
|
|
GetClientRect( m_hWnd, &rc );
|
|
rc.left = l;
|
|
DrawButton( hDC, rc, 0 );
|
|
|
|
// If header is a child of ListView, redraw the list so
|
|
// it will indicate proper state
|
|
CCMControl* pCtl;
|
|
if ( g_ctrlManager.m_ctrlMap.Lookup( hWnd, (void*&)pCtl ) )
|
|
{
|
|
if ( m_nOldItem >= 0 )
|
|
pCtl->SetState( 0, dsHover );
|
|
else if ( nOldItem >= 0 )
|
|
pCtl->SetState( dsHover, 0 );
|
|
}
|
|
|
|
ReleaseDC( m_hWnd, hDC );
|
|
}
|
|
|
|
BOOL CCoolControlsManager::CCMHeaderCtrl::NeedRedraw( const POINT& point )
|
|
{
|
|
RECT rc;
|
|
GetClientRect( m_hWnd, &rc );
|
|
rc.right = 0;
|
|
|
|
POINT pt = point;
|
|
ScreenToClient( m_hWnd, &pt );
|
|
|
|
int nItem = -1;
|
|
int nCount = SendMessage( m_hWnd, HDM_GETITEMCOUNT, 0, 0L );
|
|
|
|
for ( int i = 0; i < nCount; i++ )
|
|
{
|
|
HDITEM hi;
|
|
hi.mask = HDI_WIDTH;
|
|
SendMessage( m_hWnd, HDM_GETITEM, i, (LPARAM)&hi );
|
|
rc.left = rc.right;
|
|
rc.right = rc.left + hi.cxy;
|
|
if ( PtInRect( &rc, pt ) )
|
|
{
|
|
nItem = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ( m_hWnd != m_hWndOld || ( m_hWnd == m_hWndOld && m_nOldItem != nItem ) )
|
|
return TRUE;
|
|
return FALSE;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// CCMTrackbar class
|
|
|
|
void CCoolControlsManager::CCMTrackbar::DrawThumb( HDC hDC, const RECT& rc )
|
|
{
|
|
DWORD dwStyle = GetWindowLong( m_hWnd, GWL_STYLE );
|
|
|
|
if ( dwStyle & TBS_BOTH )
|
|
{
|
|
FillSolidRect( hDC, rc, GetSysColor( COLOR_3DFACE ) );
|
|
if ( m_nState & dsHoverMask )
|
|
Draw3dBorder( hDC, rc, COLOR_3DHIGHLIGHT, COLOR_3DDKSHADOW,
|
|
COLOR_3DLIGHT, COLOR_3DSHADOW );
|
|
else
|
|
Draw3dBorder( hDC, rc, COLOR_3DHIGHLIGHT, COLOR_3DSHADOW,
|
|
COLOR_3DFACE, COLOR_3DFACE );
|
|
return;
|
|
}
|
|
|
|
HPEN penHighlight = CreatePen( PS_SOLID, 1, GetSysColor( COLOR_3DHIGHLIGHT ) );
|
|
HPEN penLight = CreatePen( PS_SOLID, 1, GetSysColor( m_nState & dsHoverMask ? COLOR_3DLIGHT : COLOR_3DFACE ) );
|
|
HPEN penDkShadow = CreatePen( PS_SOLID, 1, GetSysColor( m_nState & dsHoverMask ? COLOR_3DDKSHADOW : COLOR_3DSHADOW ) );
|
|
HPEN penShadow = CreatePen( PS_SOLID, 1, GetSysColor( m_nState & dsHoverMask ? COLOR_3DSHADOW : COLOR_3DFACE ) );
|
|
|
|
int n;
|
|
if ( dwStyle & TBS_VERT )
|
|
{
|
|
if ( dwStyle & TBS_LEFT )
|
|
{
|
|
n = ( rc.bottom - rc.top ) / 2 + 1;
|
|
|
|
FillSolidRect( hDC, rc, GetSysColor( COLOR_3DFACE ) );
|
|
|
|
HPEN hOldPen = (HPEN)SelectObject( hDC, penHighlight );
|
|
MoveToEx( hDC, rc.right - 2, rc.top, NULL );
|
|
LineTo( hDC, rc.left + n - 1, rc.top );
|
|
LineTo( hDC, rc.left, rc.top + n - 1 );
|
|
|
|
SelectObject( hDC, penDkShadow );
|
|
LineTo( hDC, rc.left + n - 1, rc.bottom - 1 );
|
|
LineTo( hDC, rc.right - 1, rc.bottom - 1 );
|
|
LineTo( hDC, rc.right - 1, rc.top - 1 );
|
|
|
|
SelectObject( hDC, penLight );
|
|
MoveToEx( hDC, rc.right - 3, rc.top + 1, NULL );
|
|
LineTo( hDC, rc.left + n - 1, rc.top + 1 );
|
|
LineTo( hDC, rc.left + 1, rc.top + n - 1 );
|
|
|
|
SelectObject( hDC, penShadow );
|
|
LineTo( hDC, rc.left + n - 1, rc.bottom - 2 );
|
|
LineTo( hDC, rc.right - 2, rc.bottom - 2 );
|
|
LineTo( hDC, rc.right - 2, rc.top );
|
|
|
|
SelectObject( hDC, hOldPen );
|
|
}
|
|
else // TBS_RIGHT
|
|
{
|
|
n = ( rc.bottom - rc.top ) / 2 + 1;
|
|
|
|
FillSolidRect( hDC, rc, GetSysColor( COLOR_3DFACE ) );
|
|
|
|
HPEN hOldPen = (HPEN)SelectObject( hDC, penHighlight );
|
|
MoveToEx( hDC, rc.left, rc.bottom - 2, NULL );
|
|
LineTo( hDC, rc.left, rc.top );
|
|
LineTo( hDC, rc.right - n, rc.top );
|
|
LineTo( hDC, rc.right - 1, rc.top + n - 1 );
|
|
|
|
SelectObject( hDC, penDkShadow );
|
|
MoveToEx( hDC, rc.left, rc.bottom - 1, NULL );
|
|
LineTo( hDC, rc.right - n, rc.bottom - 1 );
|
|
LineTo( hDC, rc.right, rc.top + n - 2 );
|
|
|
|
SelectObject( hDC, penLight );
|
|
MoveToEx( hDC, rc.left + 1, rc.bottom - 3, NULL );
|
|
LineTo( hDC, rc.left + 1, rc.top + 1 );
|
|
LineTo( hDC, rc.right - n, rc.top + 1 );
|
|
LineTo( hDC, rc.right - 2, rc.top + n - 1 );
|
|
|
|
SelectObject( hDC, penShadow );
|
|
MoveToEx( hDC, rc.left + 1, rc.bottom - 2, NULL );
|
|
LineTo( hDC, rc.right - n, rc.bottom - 2 );
|
|
LineTo( hDC, rc.right - 1, rc.top + n - 2 );
|
|
|
|
SelectObject( hDC, hOldPen );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( dwStyle & TBS_TOP )
|
|
{
|
|
n = ( rc.right - rc.left ) / 2 + 1;
|
|
|
|
FillSolidRect( hDC, rc, GetSysColor( COLOR_3DFACE ) );
|
|
|
|
HPEN hOldPen = (HPEN)SelectObject( hDC, penHighlight );
|
|
MoveToEx( hDC, rc.left + n - 2, rc.top + 1, NULL );
|
|
LineTo( hDC, rc.left, rc.top + n - 1 );
|
|
LineTo( hDC, rc.left, rc.bottom - 1 );
|
|
|
|
SelectObject( hDC, penDkShadow );
|
|
LineTo( hDC, rc.right - 1, rc.bottom - 1 );
|
|
LineTo( hDC, rc.right - 1, rc.top + n - 1 );
|
|
LineTo( hDC, rc.left + n - 2, rc.top - 1 );
|
|
|
|
SelectObject( hDC, penLight );
|
|
MoveToEx( hDC, rc.left + n - 2, rc.top + 2, NULL );
|
|
LineTo( hDC, rc.left + 1, rc.top + n - 1 );
|
|
LineTo( hDC, rc.left + 1, rc.bottom - 2 );
|
|
|
|
SelectObject( hDC, penShadow );
|
|
LineTo( hDC, rc.right - 2, rc.bottom - 2 );
|
|
LineTo( hDC, rc.right - 2, rc.top + n - 1 );
|
|
LineTo( hDC, rc.left + n - 2, rc.top );
|
|
|
|
SelectObject( hDC, hOldPen );
|
|
}
|
|
else // TBS_BOTTOM
|
|
{
|
|
n = ( rc.right - rc.left ) / 2 + 1;
|
|
|
|
FillSolidRect( hDC, rc, GetSysColor( COLOR_3DFACE ) );
|
|
|
|
HPEN hOldPen = (HPEN)SelectObject( hDC, penHighlight );
|
|
MoveToEx( hDC, rc.left + n - 2, rc.bottom - 2, NULL );
|
|
LineTo( hDC, rc.left, rc.bottom - n );
|
|
LineTo( hDC, rc.left, rc.top );
|
|
LineTo( hDC, rc.right - 1, rc.top );
|
|
|
|
SelectObject( hDC, penDkShadow );
|
|
LineTo( hDC, rc.right - 1, rc.bottom - n );
|
|
LineTo( hDC, rc.left + n - 2, rc.bottom );
|
|
|
|
SelectObject( hDC, penLight );
|
|
MoveToEx( hDC, rc.left + n - 2, rc.bottom - 3, NULL );
|
|
LineTo( hDC, rc.left + 1, rc.bottom - n );
|
|
LineTo( hDC, rc.left + 1, rc.top + 1 );
|
|
LineTo( hDC, rc.right - 2, rc.top + 1 );
|
|
|
|
SelectObject( hDC, penShadow );
|
|
LineTo( hDC, rc.right - 2, rc.bottom - n );
|
|
LineTo( hDC, rc.left + n - 2, rc.bottom - 1 );
|
|
|
|
SelectObject( hDC, hOldPen );
|
|
}
|
|
}
|
|
|
|
DeleteObject( penHighlight );
|
|
DeleteObject( penLight );
|
|
DeleteObject( penDkShadow );
|
|
DeleteObject( penShadow );
|
|
}
|
|
|
|
void CCoolControlsManager::CCMTrackbar::DrawControl( HDC hDC, const RECT& /*rect*/ )
|
|
{
|
|
hDC = GetDC( m_hWnd );
|
|
DWORD dwStyle = GetWindowLong( m_hWnd, GWL_STYLE );
|
|
|
|
RECT rc;
|
|
SendMessage( m_hWnd, TBM_GETCHANNELRECT, 0, (LPARAM)&rc );
|
|
|
|
// BUG!: Windows incorrectly calculates the channel rectangle for
|
|
// sliders with TBS_VERT style, so we have to calculate the rectangle
|
|
// in different manner. This bug appears on all Windows platforms!
|
|
if ( dwStyle & TBS_VERT )
|
|
{
|
|
int w = ( rc.right - rc.left );
|
|
int h = ( rc.bottom - rc.top );
|
|
rc.top = rc.left;
|
|
rc.bottom = rc.left + w;
|
|
|
|
RECT r;
|
|
SendMessage( m_hWnd, TBM_GETTHUMBRECT, 0, (LPARAM)&r );
|
|
|
|
rc.left = r.left + ( ( r.right - r.left ) / 2 + 1 ) - h / 2;
|
|
if ( dwStyle & TBS_LEFT )
|
|
;
|
|
else if ( dwStyle & TBS_BOTH )
|
|
rc.left -= 1;
|
|
else
|
|
rc.left -= 2;
|
|
|
|
rc.right = rc.left + h;
|
|
}
|
|
|
|
// Draw the channel rect
|
|
if ( m_nState & dsHoverMask )
|
|
Draw3dBorder( hDC, rc, COLOR_3DSHADOW, COLOR_3DHIGHLIGHT,
|
|
COLOR_3DDKSHADOW, COLOR_3DLIGHT );
|
|
else
|
|
Draw3dBorder( hDC, rc, COLOR_3DSHADOW, COLOR_3DHIGHLIGHT,
|
|
COLOR_3DFACE, COLOR_3DFACE );
|
|
|
|
// Draw the slider thumb
|
|
if ( !( dwStyle & TBS_NOTHUMB ) )
|
|
{
|
|
SetRectEmpty( &rc );
|
|
SendMessage( m_hWnd, TBM_GETTHUMBRECT, 0, (LPARAM)&rc );
|
|
DrawThumb( hDC, rc );
|
|
}
|
|
|
|
ReleaseDC( m_hWnd, hDC );
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// CCMToolbar class
|
|
|
|
void CCoolControlsManager::CCMToolbar::DrawButton( HDC hDC, const RECT& rc, int nState )
|
|
{
|
|
if ( nState & bsChecked )
|
|
{
|
|
if ( nState & bsHover )
|
|
Draw3dBorder( hDC, rc,
|
|
COLOR_3DDKSHADOW, COLOR_3DHIGHLIGHT,
|
|
COLOR_3DSHADOW, COLOR_3DSHADOW );
|
|
else
|
|
Draw3dBorder( hDC, rc,
|
|
COLOR_3DSHADOW, COLOR_3DHIGHLIGHT,
|
|
COLOR_3DFACE, COLOR_3DFACE );
|
|
}
|
|
else
|
|
{
|
|
if ( nState & bsHover )
|
|
Draw3dBorder( hDC, rc,
|
|
COLOR_3DHIGHLIGHT, COLOR_3DDKSHADOW,
|
|
COLOR_3DLIGHT, COLOR_3DSHADOW );
|
|
else
|
|
Draw3dBorder( hDC, rc,
|
|
COLOR_3DHIGHLIGHT, COLOR_3DSHADOW,
|
|
COLOR_3DFACE, COLOR_3DFACE );
|
|
}
|
|
}
|
|
|
|
void CCoolControlsManager::CCMToolbar::DrawControl( HDC hDC, const RECT& /*rc*/ )
|
|
{
|
|
if ( GetWindowLong( m_hWnd, GWL_STYLE ) & TBSTYLE_FLAT ) // Skip flat toolbars
|
|
return;
|
|
|
|
int nCount = SendMessage( m_hWnd, TB_BUTTONCOUNT, 0, 0L );
|
|
|
|
hDC = GetDC( m_hWnd ); // We will draw toolbar buttons on the client DC
|
|
|
|
POINT point;
|
|
GetCursorPos( &point );
|
|
ScreenToClient( m_hWnd, &point );
|
|
|
|
m_nOldItem = -1;
|
|
int nState = 0;
|
|
|
|
for ( int i = 0; i < nCount; i++ )
|
|
{
|
|
RECT rc;
|
|
TBBUTTON ti;
|
|
SendMessage( m_hWnd, TB_GETBUTTON, i, (LPARAM)&ti );
|
|
SendMessage( m_hWnd, TB_GETITEMRECT, i, (LPARAM)&rc );
|
|
|
|
if ( !( ti.fsStyle & TBSTYLE_SEP ) )
|
|
{
|
|
nState = ( ti.fsState & TBSTATE_CHECKED ) ? bsChecked : bsNormal;
|
|
if ( PtInRect( &rc, point ) == TRUE )
|
|
{
|
|
if ( ti.fsState & TBSTATE_ENABLED )
|
|
nState |= bsHover;
|
|
m_nOldItem = i;
|
|
}
|
|
DrawButton( hDC, rc, nState );
|
|
}
|
|
}
|
|
|
|
ReleaseDC( m_hWnd, hDC );
|
|
}
|
|
|
|
BOOL CCoolControlsManager::CCMToolbar::NeedRedraw( const POINT& point )
|
|
{
|
|
int nCount = SendMessage( m_hWnd, TB_BUTTONCOUNT, 0, 0L );
|
|
|
|
POINT pt = point;
|
|
ScreenToClient( m_hWnd, &pt );
|
|
int nItem = -1;
|
|
for ( int i = 0; i < nCount; i++ )
|
|
{
|
|
TBBUTTON ti;
|
|
SendMessage( m_hWnd, TB_GETBUTTON, i, (LPARAM)&ti );
|
|
|
|
if ( !( ti.fsStyle & TBSTYLE_SEP ) )
|
|
{
|
|
RECT rc;
|
|
SendMessage( m_hWnd, TB_GETITEMRECT, i, (LPARAM)&rc );
|
|
if ( PtInRect( &rc, pt ) )
|
|
{
|
|
nItem = i;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( m_hWnd != m_hWndOld || ( m_hWnd == m_hWndOld && m_nOldItem != nItem ) )
|
|
return TRUE;
|
|
return FALSE;
|
|
}
|
|
|
|
LRESULT CCoolControlsManager::CCMToolbar::WindowProc( UINT uMsg, WPARAM wParam, LPARAM lParam )
|
|
{
|
|
switch ( uMsg )
|
|
{
|
|
case WM_PAINT:
|
|
case WM_NCPAINT:
|
|
m_nOldItem = -1; // Redraw the whole toolbar unconditionally
|
|
|
|
default:
|
|
return CCMControl::WindowProc( uMsg, wParam, lParam );
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// CCMTabControl class
|
|
|
|
void CCoolControlsManager::CCMTabControl::DrawTab( HDC hDC, const RECT& rect,
|
|
int nItem, int nState )
|
|
{
|
|
RECT rc = rect;
|
|
int nCurSel = SendMessage( m_hWnd, TCM_GETCURSEL, 0, 0L );
|
|
if ( nCurSel == -1 )
|
|
nCurSel = -2;
|
|
|
|
switch ( GetOrientation() )
|
|
{
|
|
case tabLeft:
|
|
if ( nState & bsChecked )
|
|
{
|
|
rc.top -= 2;
|
|
rc.bottom += 2;
|
|
rc.left -= 2;
|
|
rc.right += 1;
|
|
}
|
|
|
|
if ( nState & bsHover )
|
|
{
|
|
if ( nCurSel != nItem - 1 )
|
|
{
|
|
FillSolidRect( hDC, rc.left+2, rc.top, rc.right-rc.left-2, 1, GetSysColor( COLOR_3DHIGHLIGHT ) );
|
|
FillSolidRect( hDC, rc.left+2, rc.top+1, rc.right-rc.left-2, 1, GetSysColor( COLOR_3DLIGHT ) );
|
|
SetPixel( hDC, rc.left+1, rc.top+1, GetSysColor( COLOR_3DHIGHLIGHT ) );
|
|
}
|
|
|
|
FillSolidRect( hDC, rc.left, rc.top+2, 1, rc.bottom-rc.top-4, GetSysColor( COLOR_3DHIGHLIGHT ) );
|
|
FillSolidRect( hDC, rc.left+1, rc.top+2, 1, rc.bottom-rc.top-4, GetSysColor( COLOR_3DLIGHT ) );
|
|
|
|
if ( nCurSel != nItem + 1 )
|
|
{
|
|
FillSolidRect( hDC, rc.left+2, rc.bottom-1, rc.right-rc.left-2, 1, GetSysColor( COLOR_3DDKSHADOW ) );
|
|
FillSolidRect( hDC, rc.left+2, rc.bottom-2, rc.right-rc.left-2, 1, GetSysColor( COLOR_3DSHADOW ) );
|
|
SetPixel( hDC, rc.left+1, rc.bottom-2, GetSysColor( COLOR_3DDKSHADOW ) );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( nCurSel != nItem - 1 )
|
|
{
|
|
FillSolidRect( hDC, rc.left+2, rc.top, rc.right-rc.left-2, 1, GetSysColor( COLOR_3DHIGHLIGHT ) );
|
|
FillSolidRect( hDC, rc.left+2, rc.top+1, rc.right-rc.left-2, 1, GetSysColor( COLOR_3DFACE ) );
|
|
SetPixel( hDC, rc.left+1, rc.top+1, GetSysColor( COLOR_3DHIGHLIGHT ) );
|
|
}
|
|
|
|
FillSolidRect( hDC, rc.left, rc.top+2, 1, rc.bottom-rc.top-4, GetSysColor( COLOR_3DHIGHLIGHT ) );
|
|
FillSolidRect( hDC, rc.left+1, rc.top+2, 1, rc.bottom-rc.top-4, GetSysColor( COLOR_3DFACE ) );
|
|
|
|
if ( nCurSel != nItem + 1 )
|
|
{
|
|
FillSolidRect( hDC, rc.left+2, rc.bottom-1, rc.right-rc.left-2, 1, GetSysColor( COLOR_3DSHADOW ) );
|
|
FillSolidRect( hDC, rc.left+2, rc.bottom-2, rc.right-rc.left-2, 1, GetSysColor( COLOR_3DFACE ) );
|
|
SetPixel( hDC, rc.left+1, rc.bottom-2, GetSysColor( COLOR_3DSHADOW ) );
|
|
}
|
|
}
|
|
break;
|
|
|
|
case tabTop:
|
|
if ( nState & bsChecked )
|
|
{
|
|
rc.top -= 2;
|
|
rc.bottom += 1;
|
|
rc.left -= 2;
|
|
rc.right += 2;
|
|
}
|
|
|
|
if ( nState & bsHover )
|
|
{
|
|
if ( nCurSel != nItem - 1 )
|
|
{
|
|
FillSolidRect( hDC, rc.left, rc.top+2, 1, rc.bottom-rc.top-2, GetSysColor( COLOR_3DHIGHLIGHT ) );
|
|
FillSolidRect( hDC, rc.left+1, rc.top+2, 1, rc.bottom-rc.top-2, GetSysColor( COLOR_3DLIGHT ) );
|
|
SetPixel( hDC, rc.left+1, rc.top+1, GetSysColor( COLOR_3DHIGHLIGHT ) );
|
|
}
|
|
|
|
FillSolidRect( hDC, rc.left+2, rc.top, rc.right-rc.left-4, 1, GetSysColor( COLOR_3DHIGHLIGHT ) );
|
|
FillSolidRect( hDC, rc.left+2, rc.top+1, rc.right-rc.left-4, 1, GetSysColor( COLOR_3DLIGHT ) );
|
|
|
|
if ( nCurSel != nItem + 1 )
|
|
{
|
|
FillSolidRect( hDC, rc.right-1, rc.top+2, 1, rc.bottom-rc.top-2, GetSysColor( COLOR_3DDKSHADOW ) );
|
|
FillSolidRect( hDC, rc.right-2, rc.top+2, 1, rc.bottom-rc.top-2, GetSysColor( COLOR_3DSHADOW ) );
|
|
SetPixel( hDC, rc.right-2, rc.top+1, GetSysColor( COLOR_3DDKSHADOW ) );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( nCurSel != nItem - 1 )
|
|
{
|
|
FillSolidRect( hDC, rc.left, rc.top+2, 1, rc.bottom-rc.top-2, GetSysColor( COLOR_3DHIGHLIGHT ) );
|
|
FillSolidRect( hDC, rc.left+1, rc.top+2, 1, rc.bottom-rc.top-2, GetSysColor( COLOR_3DFACE ) );
|
|
SetPixel( hDC, rc.left+1, rc.top+1, GetSysColor( COLOR_3DHIGHLIGHT ) );
|
|
}
|
|
|
|
FillSolidRect( hDC, rc.left+2, rc.top, rc.right-rc.left-4, 1, GetSysColor( COLOR_3DHIGHLIGHT ) );
|
|
FillSolidRect( hDC, rc.left+2, rc.top+1, rc.right-rc.left-4, 1, GetSysColor( COLOR_3DFACE ) );
|
|
|
|
if ( nCurSel != nItem + 1 )
|
|
{
|
|
FillSolidRect( hDC, rc.right-1, rc.top+2, 1, rc.bottom-rc.top-2, GetSysColor( COLOR_3DSHADOW ) );
|
|
FillSolidRect( hDC, rc.right-2, rc.top+2, 1, rc.bottom-rc.top-2, GetSysColor( COLOR_3DFACE ) );
|
|
SetPixel( hDC, rc.right-2, rc.top+1, GetSysColor( COLOR_3DSHADOW ) );
|
|
}
|
|
}
|
|
break;
|
|
|
|
case tabRight:
|
|
if ( nState & bsChecked )
|
|
{
|
|
rc.top -= 2;
|
|
rc.bottom += 2;
|
|
rc.right += 2;
|
|
rc.left -= 1;
|
|
}
|
|
|
|
if ( nState & bsHover )
|
|
{
|
|
if ( nCurSel != nItem - 1 )
|
|
{
|
|
FillSolidRect( hDC, rc.left, rc.top, rc.right-rc.left-2, 1, GetSysColor( COLOR_3DHIGHLIGHT ) );
|
|
FillSolidRect( hDC, rc.left, rc.top+1, rc.right-rc.left-2, 1, GetSysColor( COLOR_3DLIGHT ) );
|
|
SetPixel( hDC, rc.right-2, rc.top+1, GetSysColor( COLOR_3DHIGHLIGHT ) );
|
|
}
|
|
|
|
FillSolidRect( hDC, rc.right-1, rc.top+2, 1, rc.bottom-rc.top-4, GetSysColor( COLOR_3DDKSHADOW ) );
|
|
FillSolidRect( hDC, rc.right-2, rc.top+2, 1, rc.bottom-rc.top-4, GetSysColor( COLOR_3DSHADOW ) );
|
|
|
|
if ( nCurSel != nItem + 1 )
|
|
{
|
|
FillSolidRect( hDC, rc.left, rc.bottom-2, rc.right-rc.left-2, 1, GetSysColor( COLOR_3DSHADOW ) );
|
|
FillSolidRect( hDC, rc.left, rc.bottom-1, rc.right-rc.left-2, 1, GetSysColor( COLOR_3DDKSHADOW ) );
|
|
SetPixel( hDC, rc.right-2, rc.bottom-2, GetSysColor( COLOR_3DDKSHADOW ) );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( nCurSel != nItem - 1 )
|
|
{
|
|
FillSolidRect( hDC, rc.left, rc.top, rc.right-rc.left-2, 1, GetSysColor( COLOR_3DHIGHLIGHT ) );
|
|
FillSolidRect( hDC, rc.left, rc.top+1, rc.right-rc.left-2, 1, GetSysColor( COLOR_3DFACE ) );
|
|
SetPixel( hDC, rc.right-2, rc.top+1, GetSysColor( COLOR_3DHIGHLIGHT ) );
|
|
}
|
|
|
|
FillSolidRect( hDC, rc.right-1, rc.top+2, 1, rc.bottom-rc.top-4, GetSysColor( COLOR_3DSHADOW ) );
|
|
FillSolidRect( hDC, rc.right-2, rc.top+2, 1, rc.bottom-rc.top-4, GetSysColor( COLOR_3DFACE ) );
|
|
|
|
if ( nCurSel != nItem + 1 )
|
|
{
|
|
FillSolidRect( hDC, rc.left, rc.bottom-1, rc.right-rc.left-2, 1, GetSysColor( COLOR_3DSHADOW ) );
|
|
FillSolidRect( hDC, rc.left, rc.bottom-2, rc.right-rc.left-2, 1, GetSysColor( COLOR_3DFACE ) );
|
|
SetPixel( hDC, rc.right-2, rc.bottom-2, GetSysColor( COLOR_3DSHADOW ) );
|
|
}
|
|
}
|
|
break;
|
|
|
|
case tabBottom:
|
|
if ( nState & bsChecked )
|
|
{
|
|
rc.bottom += 2;
|
|
rc.left -= 2;
|
|
rc.right += 2;
|
|
rc.top -=1;
|
|
}
|
|
|
|
if ( nState & bsHover )
|
|
{
|
|
if ( nCurSel != nItem - 1 )
|
|
{
|
|
FillSolidRect( hDC, rc.left, rc.top, 1, rc.bottom-rc.top-2, GetSysColor( COLOR_3DHIGHLIGHT ) );
|
|
FillSolidRect( hDC, rc.left+1, rc.top, 1, rc.bottom-rc.top-2, GetSysColor( COLOR_3DLIGHT ) );
|
|
SetPixel( hDC, rc.left+1, rc.bottom-2, GetSysColor( COLOR_3DHIGHLIGHT ) );
|
|
}
|
|
|
|
FillSolidRect( hDC, rc.left+2, rc.bottom-1, rc.right-rc.left-4, 1, GetSysColor( COLOR_3DDKSHADOW ) );
|
|
FillSolidRect( hDC, rc.left+2, rc.bottom-2, rc.right-rc.left-4, 1, GetSysColor( COLOR_3DSHADOW ) );
|
|
|
|
if ( nCurSel != nItem + 1 )
|
|
{
|
|
FillSolidRect( hDC, rc.right-1, rc.top, 1, rc.bottom-rc.top-2, GetSysColor( COLOR_3DDKSHADOW ) );
|
|
FillSolidRect( hDC, rc.right-2, rc.top, 1, rc.bottom-rc.top-2, GetSysColor( COLOR_3DSHADOW ) );
|
|
SetPixel( hDC, rc.right-2, rc.bottom-2, GetSysColor( COLOR_3DDKSHADOW ) );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ( nCurSel != nItem - 1 )
|
|
{
|
|
FillSolidRect( hDC, rc.left, rc.top, 1, rc.bottom-rc.top-2, GetSysColor( COLOR_3DHIGHLIGHT ) );
|
|
FillSolidRect( hDC, rc.left+1, rc.top, 1, rc.bottom-rc.top-2, GetSysColor( COLOR_3DFACE ) );
|
|
SetPixel( hDC, rc.left+1, rc.bottom-2, GetSysColor( COLOR_3DHIGHLIGHT ) );
|
|
}
|
|
|
|
FillSolidRect( hDC, rc.left+2, rc.bottom-1, rc.right-rc.left-4, 1, GetSysColor( COLOR_3DSHADOW ) );
|
|
FillSolidRect( hDC, rc.left+2, rc.bottom-2, rc.right-rc.left-4, 1, GetSysColor( COLOR_3DFACE ) );
|
|
|
|
if ( nCurSel != nItem + 1 )
|
|
{
|
|
FillSolidRect( hDC, rc.right-1, rc.top, 1, rc.bottom-rc.top-2, GetSysColor( COLOR_3DSHADOW ) );
|
|
FillSolidRect( hDC, rc.right-2, rc.top, 1, rc.bottom-rc.top-2, GetSysColor( COLOR_3DFACE ) );
|
|
SetPixel( hDC, rc.right-2, rc.bottom-2, GetSysColor( COLOR_3DSHADOW ) );
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
CCoolControlsManager::CCMTabControl::OrientationsEnum CCoolControlsManager::CCMTabControl::GetOrientation() const
|
|
{
|
|
DWORD dwStyle = GetWindowLong( m_hWnd, GWL_STYLE );
|
|
if ( dwStyle & TCS_BOTTOM )
|
|
{
|
|
if ( dwStyle & TCS_VERTICAL )
|
|
return tabRight;
|
|
else
|
|
return tabBottom;
|
|
}
|
|
else
|
|
{
|
|
if ( dwStyle & TCS_VERTICAL )
|
|
return tabLeft;
|
|
else
|
|
return tabTop;
|
|
}
|
|
}
|
|
|
|
void CCoolControlsManager::CCMTabControl::DrawControl( HDC hDC, const RECT& rect )
|
|
{
|
|
DWORD dwStyle = GetWindowLong( m_hWnd, GWL_STYLE );
|
|
if ( dwStyle & TCS_BUTTONS ) // Skip button-like tab controls
|
|
return;
|
|
|
|
hDC = GetDC( m_hWnd ); // We will draw on the client DC
|
|
|
|
RECT rc = rect;
|
|
SendMessage( m_hWnd, TCM_ADJUSTRECT, FALSE, (LPARAM)&rc );
|
|
InflateRect( &rc, 4, 4 );
|
|
|
|
RECT rcSel;
|
|
int nCurSel = SendMessage( m_hWnd, TCM_GETCURSEL, 0, 0L );
|
|
SendMessage( m_hWnd, TCM_GETITEMRECT, nCurSel, (LPARAM)&rcSel );
|
|
|
|
switch ( GetOrientation() )
|
|
{
|
|
case tabLeft:
|
|
rc.left += 2;
|
|
FillSolidRect( hDC, rc.left, rc.bottom, rc.right-rc.left, -1, GetSysColor( COLOR_3DSHADOW ) );
|
|
FillSolidRect( hDC, rc.right, rc.top, -1, rc.bottom-rc.top, GetSysColor( COLOR_3DSHADOW ) );
|
|
break;
|
|
|
|
case tabTop:
|
|
rc.top += 2;
|
|
FillSolidRect( hDC, rc.left, rc.bottom, rc.right-rc.left, -1, GetSysColor( COLOR_3DSHADOW ) );
|
|
FillSolidRect( hDC, rc.right, rc.top, -1, rc.bottom-rc.top, GetSysColor( COLOR_3DSHADOW ) );
|
|
break;
|
|
|
|
case tabRight:
|
|
rc.right -= 2;
|
|
FillSolidRect( hDC, rc.left, rc.bottom, rc.right-rc.left, -1, GetSysColor( COLOR_3DSHADOW ) );
|
|
FillSolidRect( hDC, rc.right, rc.top, -1, rcSel.top-rc.top, GetSysColor( COLOR_3DSHADOW ) );
|
|
FillSolidRect( hDC, rc.right, rcSel.bottom, -1, rc.bottom-rcSel.bottom, GetSysColor( COLOR_3DSHADOW ) );
|
|
break;
|
|
|
|
case tabBottom:
|
|
rc.bottom -= 2;
|
|
FillSolidRect( hDC, rc.left, rc.bottom, rcSel.left-rc.left, -1, GetSysColor( COLOR_3DSHADOW ) );
|
|
FillSolidRect( hDC, rcSel.right, rc.bottom, rc.right-rcSel.right, -1, GetSysColor( COLOR_3DSHADOW ) );
|
|
FillSolidRect( hDC, rc.right, rc.top, -1, rc.bottom-rc.top, GetSysColor( COLOR_3DSHADOW ) );
|
|
break;
|
|
}
|
|
|
|
Draw3dRect( hDC, rc.left+1, rc.top+1, rc.right-rc.left-2, rc.bottom-rc.top-2,
|
|
GetSysColor( COLOR_3DFACE ), GetSysColor( COLOR_3DFACE ) );
|
|
|
|
m_nOldItem = -1;
|
|
int nState = 0;
|
|
POINT point;
|
|
GetCursorPos( &point );
|
|
ScreenToClient( m_hWnd, &point );
|
|
int nCount = SendMessage( m_hWnd, TCM_GETITEMCOUNT, 0, 0L );
|
|
|
|
for ( int i = 0; i < nCount; i++ )
|
|
{
|
|
SendMessage( m_hWnd, TCM_GETITEMRECT, i, (LPARAM)&rc );
|
|
|
|
nState = bsNormal;
|
|
if ( nCurSel != i )
|
|
{
|
|
if ( PtInRect( &rc, point ) == TRUE )
|
|
{
|
|
nState |= bsHover;
|
|
m_nOldItem = i;
|
|
}
|
|
DrawTab( hDC, rc, i, nState );
|
|
}
|
|
}
|
|
|
|
nState = bsChecked;
|
|
if ( PtInRect( &rcSel, point ) == TRUE )
|
|
{
|
|
nState |= bsHover;
|
|
m_nOldItem = nCurSel;
|
|
}
|
|
DrawTab( hDC, rcSel, nCurSel, nState );
|
|
|
|
if ( nCurSel != 0 )
|
|
switch ( GetOrientation() )
|
|
{
|
|
case tabTop:
|
|
FillSolidRect( hDC, rect.left, rect.top, 2, rcSel.bottom-rcSel.top+2, GetSysColor( COLOR_3DFACE ) );
|
|
break;
|
|
case tabBottom:
|
|
FillSolidRect( hDC, rect.left, rect.bottom, 2, -rcSel.bottom+rcSel.top-2, GetSysColor( COLOR_3DFACE ) );
|
|
break;
|
|
}
|
|
|
|
ReleaseDC( m_hWnd, hDC );
|
|
}
|
|
|
|
BOOL CCoolControlsManager::CCMTabControl::NeedRedraw( const POINT& point )
|
|
{
|
|
int nCount = SendMessage( m_hWnd, TCM_GETITEMCOUNT, 0, 0L );
|
|
|
|
TCHITTESTINFO thti;
|
|
thti.pt = point;
|
|
ScreenToClient( m_hWnd, &thti.pt );
|
|
int nItem = SendMessage( m_hWnd, TCM_HITTEST, 0, (LPARAM)&thti );
|
|
|
|
if ( m_hWnd != m_hWndOld || ( m_hWnd == m_hWndOld && m_nOldItem != nItem ) )
|
|
return TRUE;
|
|
return FALSE;
|
|
}
|
|
|
|
LRESULT CCoolControlsManager::CCMTabControl::WindowProc( UINT uMsg, WPARAM wParam, LPARAM lParam )
|
|
{
|
|
switch ( uMsg )
|
|
{
|
|
case WM_PAINT:
|
|
case WM_NCPAINT:
|
|
m_nOldItem = -1; // Redraw the whole control unconditionally
|
|
break;
|
|
}
|
|
return CCMControl::WindowProc( uMsg, wParam, lParam );
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// CCMIPAddress class
|
|
|
|
BOOL CCoolControlsManager::CCMIPAddress::IsFocused()
|
|
{
|
|
HWND hWnd = GetTopWindow( m_hWnd );
|
|
while ( hWnd )
|
|
{
|
|
if ( hWnd == GetFocus() )
|
|
return TRUE;
|
|
hWnd = GetNextWindow( hWnd, GW_HWNDNEXT );
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
LRESULT CCoolControlsManager::CCMIPAddress::WindowProc( UINT uMsg, WPARAM wParam, LPARAM lParam )
|
|
{
|
|
switch ( uMsg )
|
|
{
|
|
case WM_COMMAND:
|
|
if ( HIWORD( wParam ) == EN_SETFOCUS || HIWORD( wParam ) == EN_KILLFOCUS )
|
|
DrawBorder();
|
|
break;
|
|
|
|
default:
|
|
return CCMControl::WindowProc( uMsg, wParam, lParam );
|
|
}
|
|
|
|
return CallWindowProc( m_oldWndProc, m_hWnd, uMsg, wParam, lParam );
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
// CCMDialog class
|
|
|
|
LRESULT CCoolControlsManager::CCMDialog::WindowProc( UINT uMsg, WPARAM wParam, LPARAM lParam )
|
|
{
|
|
switch ( uMsg )
|
|
{
|
|
case WM_PARENTNOTIFY:
|
|
if ( LOWORD( wParam ) == WM_CREATE ) // Add dynamically created controls to the map
|
|
g_ctrlManager.AddControl( (HWND)lParam );
|
|
break;
|
|
|
|
case WM_NCDESTROY:
|
|
// Unsubclass window and remove it from the map
|
|
CallWindowProc( m_oldWndProc, m_hWnd, uMsg, wParam, lParam );
|
|
g_ctrlManager.RemoveDialog( m_hWnd );
|
|
return 0;
|
|
}
|
|
|
|
return CallWindowProc( m_oldWndProc, m_hWnd, uMsg, wParam, lParam );
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////
|
|
// Helper functions for drawing 3D frames (borrowed from CDC class)
|
|
|
|
void CCoolControlsManager::CCMControl::FillSolidRect( HDC hDC, int x, int y, int cx, int cy, COLORREF clr )
|
|
{
|
|
SetBkColor( hDC, clr );
|
|
RECT rect;
|
|
SetRect( &rect, x, y, x + cx, y + cy );
|
|
ExtTextOut( hDC, 0, 0, ETO_OPAQUE, &rect, NULL, 0, NULL );
|
|
}
|
|
|
|
void CCoolControlsManager::CCMControl::FillSolidRect( HDC hDC, const RECT& rect, COLORREF clr )
|
|
{
|
|
SetBkColor( hDC, clr );
|
|
ExtTextOut( hDC, 0, 0, ETO_OPAQUE, &rect, NULL, 0, NULL );
|
|
}
|
|
|
|
void CCoolControlsManager::CCMControl::Draw3dRect( HDC hDC, int x, int y, int cx, int cy,
|
|
COLORREF clrTopLeft, COLORREF clrBottomRight )
|
|
{
|
|
FillSolidRect( hDC, x, y, cx - 1, 1, clrTopLeft );
|
|
FillSolidRect( hDC, x, y, 1, cy - 1, clrTopLeft );
|
|
FillSolidRect( hDC, x + cx, y, -1, cy, clrBottomRight );
|
|
FillSolidRect( hDC, x, y + cy, cx, -1, clrBottomRight );
|
|
}
|
|
|
|
void CCoolControlsManager::CCMControl::Draw3dRect( HDC hDC, const RECT& rect,
|
|
COLORREF clrTopLeft, COLORREF clrBottomRight )
|
|
{
|
|
Draw3dRect( hDC, rect.left, rect.top, rect.right - rect.left,
|
|
rect.bottom - rect.top, clrTopLeft, clrBottomRight );
|
|
}
|
|
|
|
void CCoolControlsManager::CCMControl::Draw3dBorder( HDC hDC, const RECT& rc,
|
|
int nColor1, int nColor2,
|
|
int nColor3, int nColor4 )
|
|
{
|
|
Draw3dRect( hDC, rc, GetSysColor( nColor1 ), GetSysColor( nColor2 ) );
|
|
|
|
Draw3dRect( hDC, rc.left + 1, rc.top + 1, rc.right - rc.left - 2, rc.bottom - rc.top - 2,
|
|
GetSysColor( nColor3 ), GetSysColor( nColor4 ) );
|
|
}
|
|
|
|
void CCoolControlsManager::CCMControl::Draw3dBorder( HDC hDC, const RECT& rc,
|
|
int nColor1, int nColor2,
|
|
int nColor3, int nColor4,
|
|
int nColor5, int nColor6 )
|
|
{
|
|
Draw3dRect( hDC, rc, GetSysColor( nColor1 ), GetSysColor( nColor2 ) );
|
|
|
|
Draw3dRect( hDC, rc.left + 1, rc.top + 1, rc.right - rc.left - 2, rc.bottom - rc.top - 2,
|
|
GetSysColor( nColor3 ), GetSysColor( nColor4 ) );
|
|
Draw3dRect( hDC, rc.left + 2, rc.top + 2, rc.right - rc.left - 4, rc.bottom - rc.top - 4,
|
|
GetSysColor( nColor5 ), GetSysColor( nColor6 ) );
|
|
}
|