#include <afxtempl.h>
class CWndHotKeyManage
{
protected:
typedef struct _tagWKItem_t
{
HWND hWnd; // window to receive hot-key notification
int id; // identifier of hot key
UINT fsModifiers; // key-modifier flags
UINT vk; // virtual-key code
BOOL bFocusActive; //
_tagWKItem_t()
{
memset(this, 0, sizeof(*this));
}
}WKITEM, *LPWKITEM;
CArray <WKITEM, const WKITEM &> m_WKList;
CRITICAL_SECTION m_Lock;
protected:
void Lock()
{
EnterCriticalSection(&m_Lock);
}
void Unlock()
{
LeaveCriticalSection(&m_Lock);
}
INT_PTR FindItem(HWND hWnd, int id)
{
INT_PTR iFound=-1;
for(INT_PTR i=0; i<m_WKList.GetSize(); i++)
{
WKITEM *p = &m_WKList[i];
if(hWnd == p->hWnd && id == p->id)
{
iFound = i;
break;
}
}
return iFound;
}
public:
CWndHotKeyManage()
{
InitializeCriticalSection(&m_Lock);
}
virtual ~CWndHotKeyManage()
{
Lock();
m_WKList.RemoveAll();
Unlock();
DeleteCriticalSection(&m_Lock);
}
public:
BOOL RegisterHotKey(HWND hWnd, int id, UINT fsModifiers, UINT vk, BOOL bActive=FALSE)
{
BOOL bRet = FALSE;
WKITEM NewItem;
NewItem.hWnd = hWnd;
NewItem.id = id;
NewItem.fsModifiers = fsModifiers;
NewItem.vk = vk;
NewItem.bFocusActive = bActive;
Lock();
int iPos = FindItem(hWnd, id);
if(iPos >= 0)
{
m_WKList.SetAt(iPos, NewItem);
bRet = TRUE;
}
else
{
m_WKList.Add(NewItem);
bRet = TRUE;
}
Unlock();
return bRet;
}
BOOL UnregisterHotKey(HWND hWnd, int id)
{
Lock();
int iPos = FindItem(hWnd, id);
if(iPos >= 0)
{
m_WKList.RemoveAt(iPos);
}
Unlock();
return TRUE;
}
public:
BOOL TranslateMessage(LPMSG lpMsg)
{
BOOL bRet = 0;
do
{
if(!(lpMsg->message == WM_KEYDOWN
|| lpMsg->message == WM_SYSKEYDOWN))
break;
UINT vKeyKey = lpMsg->wParam;
BOOL bCtlKey = GetKeyState(VK_CONTROL);
BOOL bSftKey = GetKeyState(VK_SHIFT);
BOOL bAltKey = GetKeyState(VK_MENU);
BOOL bWinKey = GetKeyState(VK_LWIN) || GetKeyState(VK_RWIN);
Lock();
for(INT_PTR i=0; i<m_WKList.GetSize(); i++)
{
WKITEM *p = &m_WKList[i];
//匹配窗口
if(!(p->hWnd == NULL || lpMsg->hwnd == p->hWnd))
{
TRACE(_T("wnd:%p %p\n"), p->hWnd, lpMsg->hwnd);
continue;
}
//要求激活?
if(p->bFocusActive
&& GetFocus() != lpMsg->hwnd)
{
TRACE(_T("FocusWnd %p %p\n"), GetFocus(), lpMsg->hwnd);
continue;
}
//匹配主键
if(p->vk != vKeyKey)
{
TRACE(_T("MainKey %u %u\n"), p->vk, vKeyKey);
continue;
}
//Control
BOOL bCtrlMf = (p->fsModifiers & MOD_CONTROL)?TRUE:FALSE;
if(bCtrlMf != bCtlKey)
{
TRACE(_T("Contrl %d %d\n"), bCtrlMf, bCtlKey);
continue;
}
//Shift
BOOL bShiftMf = (p->fsModifiers & MOD_SHIFT)?TRUE:FALSE;
if(bShiftMf != bSftKey)
{
TRACE(_T("Shift %d %d\n"), bShiftMf, bSftKey);
continue;
}
//Alt
BOOL bAltMf = (p->fsModifiers & MOD_ALT)?TRUE:FALSE;
if(bAltMf != bAltKey)
{
TRACE(_T("Alt %d %d\n"), bAltMf, bAltKey);
continue;
}
//Win
BOOL bWinMf = (p->fsModifiers & MOD_WIN)?TRUE:FALSE;
if(bWinMf != bWinKey)
{
TRACE(_T("Win %d %d\n"), bWinMf, bWinKey);
continue;
}
//完全匹配
LPARAM lParam = MAKELPARAM(p->fsModifiers, p->vk);
PostMessage(lpMsg->hwnd, WM_HOTKEY, p->id, lParam);
bRet = TRUE;
break;
}
Unlock();
}while(0);
return bRet;
}
}; |