📄 coolcontrolsmanager.cpp
字号:
/******************************************************************
$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 )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -