You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1543 lines
34 KiB
C++
1543 lines
34 KiB
C++
// XTPShortcutManager.cpp : implementation of the CXTPShortcutManager class.
|
|
//
|
|
// This file is a part of the XTREME COMMANDBARS MFC class library.
|
|
// (c)1998-2012 Codejock Software, All Rights Reserved.
|
|
//
|
|
// THIS SOURCE FILE IS THE PROPERTY OF CODEJOCK SOFTWARE AND IS NOT TO BE
|
|
// RE-DISTRIBUTED BY ANY MEANS WHATSOEVER WITHOUT THE EXPRESSED WRITTEN
|
|
// CONSENT OF CODEJOCK SOFTWARE.
|
|
//
|
|
// THIS SOURCE CODE CAN ONLY BE USED UNDER THE TERMS AND CONDITIONS OUTLINED
|
|
// IN THE XTREME TOOLKIT PRO LICENSE AGREEMENT. CODEJOCK SOFTWARE GRANTS TO
|
|
// YOU (ONE SOFTWARE DEVELOPER) THE LIMITED RIGHT TO USE THIS SOFTWARE ON A
|
|
// SINGLE COMPUTER.
|
|
//
|
|
// CONTACT INFORMATION:
|
|
// support@codejock.com
|
|
// http://www.codejock.com
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
#include "stdafx.h"
|
|
#include "Resource.h"
|
|
|
|
#include "Common/XTPPropExchange.h"
|
|
#include "Common/XTPVC80Helpers.h"
|
|
#include "Common/XTPResourceManager.h"
|
|
|
|
#include "XTPCommandBarsDefines.h"
|
|
#include "XTPShortcutManager.h"
|
|
#include "XTPCommandBars.h"
|
|
|
|
#ifdef _DEBUG
|
|
#define new DEBUG_NEW
|
|
#undef THIS_FILE
|
|
static char THIS_FILE[] = __FILE__;
|
|
#endif
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// CXTPShortcutManagerAccel
|
|
|
|
CXTPShortcutManagerAccel::CXTPShortcutManagerAccel()
|
|
{
|
|
cmd = 0;
|
|
key[0].fVirt = 0;
|
|
key[0].key = 0;
|
|
key[1].fVirt = 0;
|
|
key[1].key = 0;
|
|
|
|
m_pManager = 0;
|
|
|
|
}
|
|
|
|
CXTPShortcutManagerAccel::CXTPShortcutManagerAccel(ACCEL* pAccel)
|
|
{
|
|
cmd = pAccel->cmd;
|
|
|
|
key[0].fVirt = pAccel->fVirt;
|
|
key[0].key = pAccel->key;
|
|
|
|
key[1].fVirt = 0;
|
|
key[1].key = 0;
|
|
|
|
m_pManager = 0;
|
|
|
|
}
|
|
|
|
CXTPShortcutManagerAccel::CXTPShortcutManagerAccel(const XTP_SHORTCUTMANAGER_ACCEL& accel)
|
|
{
|
|
cmd = accel.cmd;
|
|
|
|
key[0] = accel.key[0];
|
|
key[1] = accel.key[1];
|
|
|
|
m_pManager = NULL;
|
|
|
|
}
|
|
|
|
CXTPShortcutManagerAccel::CXTPShortcutManagerAccel(const CXTPShortcutManagerAccel& accel)
|
|
{
|
|
cmd = accel.cmd;
|
|
|
|
key[0] = accel.key[0];
|
|
key[1] = accel.key[1];
|
|
|
|
m_pManager = NULL;
|
|
|
|
}
|
|
|
|
|
|
const CXTPShortcutManagerAccel& CXTPShortcutManagerAccel::operator=(const CXTPShortcutManagerAccel& accel)
|
|
{
|
|
cmd = accel.cmd;
|
|
|
|
key[0] = accel.key[0];
|
|
key[1] = accel.key[1];
|
|
|
|
m_pManager = accel.m_pManager;
|
|
|
|
return *this;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// CXTPShortcutManagerAccelTable
|
|
CXTPShortcutManagerAccelTable::CXTPShortcutManagerAccelTable(CXTPShortcutManager* pManager)
|
|
{
|
|
m_pManager = pManager;
|
|
|
|
}
|
|
|
|
CXTPShortcutManagerAccelTable::~CXTPShortcutManagerAccelTable()
|
|
{
|
|
RemoveAll();
|
|
}
|
|
|
|
void CXTPShortcutManagerAccelTable::RemoveAll()
|
|
{
|
|
for (int i = 0; i < GetCount(); i++)
|
|
{
|
|
m_arrAccels[i]->InternalRelease();
|
|
}
|
|
m_arrAccels.RemoveAll();
|
|
}
|
|
|
|
void CXTPShortcutManagerAccelTable::RemoveAt(int nIndex)
|
|
{
|
|
if (nIndex >= 0 && nIndex < m_arrAccels.GetSize())
|
|
{
|
|
m_arrAccels[nIndex]->InternalRelease();
|
|
m_arrAccels.RemoveAt(nIndex);
|
|
}
|
|
}
|
|
|
|
void CXTPShortcutManagerAccelTable::Add(const XTP_SHORTCUTMANAGER_ACCEL& accel)
|
|
{
|
|
CXTPShortcutManagerAccel* pAccel = new CXTPShortcutManagerAccel(accel);
|
|
pAccel->m_pManager = m_pManager;
|
|
|
|
m_arrAccels.Add(pAccel);
|
|
}
|
|
|
|
void CXTPShortcutManagerAccelTable::CopyAccelTable(LPACCEL lpAccel, int nSize)
|
|
{
|
|
RemoveAll();
|
|
|
|
for (int i = 0; i < nSize; i++)
|
|
{
|
|
Add(CXTPShortcutManagerAccel(&lpAccel[i]));
|
|
}
|
|
}
|
|
|
|
XTP_SHORTCUTMANAGER_ACCEL* CXTPShortcutManagerAccelTable::CopyAccels() const
|
|
{
|
|
XTP_SHORTCUTMANAGER_ACCEL* pAccels = new XTP_SHORTCUTMANAGER_ACCEL[GetCount()];
|
|
|
|
for (int i = 0; i < GetCount(); i++)
|
|
{
|
|
pAccels[i] = *m_arrAccels[i];
|
|
}
|
|
|
|
return pAccels;
|
|
}
|
|
|
|
void CXTPShortcutManagerAccelTable::CopyAccelTable(HACCEL hAccelTable)
|
|
{
|
|
RemoveAll();
|
|
|
|
if (hAccelTable == NULL)
|
|
return;
|
|
|
|
int nAccelSize = ::CopyAcceleratorTable (hAccelTable, NULL, 0);
|
|
if (nAccelSize == 0)
|
|
return;
|
|
|
|
LPACCEL lpAccel = new ACCEL[nAccelSize];
|
|
::CopyAcceleratorTable (hAccelTable, lpAccel, nAccelSize);
|
|
|
|
CopyAccelTable(lpAccel, nAccelSize);
|
|
|
|
delete[] lpAccel;
|
|
}
|
|
|
|
int CXTPShortcutManagerAccelTable::GetCount() const
|
|
{
|
|
return (int)m_arrAccels.GetSize();
|
|
}
|
|
|
|
CXTPShortcutManagerAccel* CXTPShortcutManagerAccelTable::GetAt(int nIndex) const
|
|
{
|
|
return nIndex >= 0 && nIndex < m_arrAccels.GetSize() ? m_arrAccels.GetAt(nIndex) : NULL;
|
|
}
|
|
|
|
void CXTPShortcutManagerAccelTable::CopyAccelTable(CXTPShortcutManagerAccelTable* pAccelTable)
|
|
{
|
|
RemoveAll();
|
|
|
|
int nAccelSize = pAccelTable->GetCount();
|
|
|
|
for (int i = 0; i < nAccelSize; i++)
|
|
{
|
|
Add(*pAccelTable->GetAt(i));
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// CXTPShortcutManagerKeyNameText::CXTPShortcutManagerKeyNameText
|
|
|
|
CXTPShortcutManager::CKeyNameText::CKeyNameText()
|
|
{
|
|
static const struct
|
|
{
|
|
WORD wKey; // Virtual Key Code.
|
|
LPCTSTR szKeyName; // Display Name (i.e "CTRL").
|
|
}
|
|
virtKeys[] =
|
|
{
|
|
{ _T('0'), _T("0") },
|
|
{ _T('1'), _T("1") },
|
|
{ _T('2'), _T("2") },
|
|
{ _T('3'), _T("3") },
|
|
{ _T('4'), _T("4") },
|
|
{ _T('5'), _T("5") },
|
|
{ _T('6'), _T("6") },
|
|
{ _T('7'), _T("7") },
|
|
{ _T('8'), _T("8") },
|
|
{ _T('9'), _T("9") },
|
|
{ _T('A'), _T("A") },
|
|
{ _T('B'), _T("B") },
|
|
{ _T('C'), _T("C") },
|
|
{ _T('D'), _T("D") },
|
|
{ _T('E'), _T("E") },
|
|
{ _T('F'), _T("F") },
|
|
{ _T('G'), _T("G") },
|
|
{ _T('H'), _T("H") },
|
|
{ _T('I'), _T("I") },
|
|
{ _T('J'), _T("J") },
|
|
{ _T('K'), _T("K") },
|
|
{ _T('L'), _T("L") },
|
|
{ _T('M'), _T("M") },
|
|
{ _T('N'), _T("N") },
|
|
{ _T('O'), _T("O") },
|
|
{ _T('P'), _T("P") },
|
|
{ _T('Q'), _T("Q") },
|
|
{ _T('R'), _T("R") },
|
|
{ _T('S'), _T("S") },
|
|
{ _T('T'), _T("T") },
|
|
{ _T('U'), _T("U") },
|
|
{ _T('V'), _T("V") },
|
|
{ _T('W'), _T("W") },
|
|
{ _T('X'), _T("X") },
|
|
{ _T('Y'), _T("Y") },
|
|
{ _T('Z'), _T("Z") },
|
|
{ VK_LBUTTON, _T("Left Button") },
|
|
{ VK_RBUTTON, _T("Right Button") },
|
|
{ VK_CANCEL, _T("Ctrl+Break") },
|
|
{ VK_MBUTTON, _T("Middle Button") },
|
|
{ VK_BACK, _T("Backspace") },
|
|
{ VK_TAB, _T("Tab") },
|
|
{ VK_CLEAR, _T("Clear") },
|
|
{ VK_RETURN, _T("Enter") },
|
|
{ VK_SHIFT, _T("Shift") },
|
|
{ VK_CONTROL, _T("Ctrl") },
|
|
{ VK_MENU, _T("Alt") },
|
|
{ VK_PAUSE, _T("Pause") },
|
|
{ VK_CAPITAL, _T("Caps Lock") },
|
|
{ VK_ESCAPE, _T("Esc") },
|
|
{ VK_SPACE, _T("Space") },
|
|
{ VK_PRIOR, _T("Page Up") },
|
|
{ VK_NEXT, _T("Page Down") },
|
|
{ VK_END, _T("End") },
|
|
{ VK_HOME, _T("Home") },
|
|
{ VK_LEFT, _T("Left Arrow") },
|
|
{ VK_UP, _T("Up Arrow") },
|
|
{ VK_RIGHT, _T("Right Arrow") },
|
|
{ VK_DOWN, _T("Down Arrow") },
|
|
{ VK_SELECT, _T("Select") },
|
|
{ VK_PRINT, _T("Print") },
|
|
{ VK_EXECUTE, _T("Execute") },
|
|
{ VK_SNAPSHOT, _T("Snapshot") },
|
|
{ VK_INSERT, _T("Ins") },
|
|
{ VK_DELETE, _T("Del") },
|
|
{ VK_HELP, _T("Help") },
|
|
{ VK_LWIN , _T("Win") },
|
|
{ VK_RWIN, _T("Win") },
|
|
{ VK_APPS, _T("Application") },
|
|
{ VK_MULTIPLY, _T("Num *") },
|
|
{ VK_ADD, _T("Num +") },
|
|
{ VK_SEPARATOR, _T("Separator") },
|
|
{ VK_SUBTRACT, _T("Num -") },
|
|
{ VK_DECIMAL, _T("Num .") },
|
|
{ VK_DIVIDE, _T("Num /") },
|
|
{ VK_F1, _T("F1") },
|
|
{ VK_F2, _T("F2") },
|
|
{ VK_F3, _T("F3") },
|
|
{ VK_F4, _T("F4") },
|
|
{ VK_F5, _T("F5") },
|
|
{ VK_F6, _T("F6") },
|
|
{ VK_F7, _T("F7") },
|
|
{ VK_F8, _T("F8") },
|
|
{ VK_F9, _T("F9") },
|
|
{ VK_F10, _T("F10") },
|
|
{ VK_F11, _T("F11") },
|
|
{ VK_F12, _T("F12") },
|
|
{ VK_NUMPAD0, _T("Num 0") },
|
|
{ VK_NUMPAD1, _T("Num 1") },
|
|
{ VK_NUMPAD2, _T("Num 2") },
|
|
{ VK_NUMPAD3, _T("Num 3") },
|
|
{ VK_NUMPAD4, _T("Num 4") },
|
|
{ VK_NUMPAD5, _T("Num 5") },
|
|
{ VK_NUMPAD6, _T("Num 6") },
|
|
{ VK_NUMPAD7, _T("Num 7") },
|
|
{ VK_NUMPAD8, _T("Num 8") },
|
|
{ VK_NUMPAD9, _T("Num 9") },
|
|
{ VK_NUMLOCK, _T("Num Lock") },
|
|
{ VK_SCROLL, _T("Scrl Lock") },
|
|
{ VK_ATTN, _T("Attn") },
|
|
{ VK_CRSEL, _T("Crsel") },
|
|
{ VK_EXSEL, _T("Exsel") },
|
|
{ VK_EREOF, _T("Ereof") },
|
|
{ VK_PLAY, _T("Play") },
|
|
{ VK_ZOOM, _T("Zoom") },
|
|
{ VK_NONAME, _T("No Name") },
|
|
{ VK_PA1, _T("Pa1") },
|
|
{ VK_OEM_CLEAR, _T("Oem Clear") },
|
|
};
|
|
|
|
for (int i = 0; i < _countof(virtKeys); i++)
|
|
{
|
|
SetAt(virtKeys[i].wKey, virtKeys[i].szKeyName);
|
|
}
|
|
}
|
|
|
|
WORD CXTPShortcutManager::CKeyNameText::Parse(LPCTSTR lpszKey)
|
|
{
|
|
POSITION pos = m_mapVirtualKeys.GetStartPosition();
|
|
while (pos)
|
|
{
|
|
WORD rKey;
|
|
CString strKey;
|
|
|
|
m_mapVirtualKeys.GetNextAssoc(pos, rKey, strKey);
|
|
|
|
if (strKey.CompareNoCase(lpszKey) == 0)
|
|
return rKey;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
CString CXTPShortcutManager::CKeyNameText::Translate(UINT nKey)
|
|
{
|
|
CString strKeyNameText;
|
|
|
|
if (m_mapVirtualKeys.Lookup((WORD)nKey, strKeyNameText))
|
|
{
|
|
return strKeyNameText;
|
|
}
|
|
|
|
return _T("");
|
|
}
|
|
|
|
void CXTPShortcutManager::CKeyNameText::SetAt(UINT uiVirtKey, LPCTSTR strKeyNameText)
|
|
{
|
|
m_mapVirtualKeys.SetAt((WORD)uiVirtKey, strKeyNameText);
|
|
}
|
|
|
|
|
|
#define SAFE_DESTROY_ACCELTABLE(hAccelTable) if (hAccelTable) {::DestroyAcceleratorTable (hAccelTable); hAccelTable = NULL;}
|
|
|
|
CXTPShortcutManager::CXTPShortcutManager(CXTPCommandBars* pCommandBars)
|
|
{
|
|
m_pCommandBars = pCommandBars;
|
|
|
|
m_pAccelTable = new CXTPShortcutManagerAccelTable(this);
|
|
m_pOriginalAccelTable = NULL;
|
|
|
|
m_bAllowEscapeShortcut = FALSE;
|
|
m_bUseSystemKeyNameText = FALSE;
|
|
m_bAllowDoubleKeyShortcuts = TRUE;
|
|
|
|
m_pKeyNameText = new CKeyNameText();
|
|
|
|
m_nDisableShortcuts = 0;
|
|
m_bDisableOnCapture = TRUE;
|
|
|
|
}
|
|
|
|
CXTPShortcutManager::~CXTPShortcutManager()
|
|
{
|
|
SAFE_DELETE(m_pAccelTable);
|
|
SAFE_DELETE(m_pOriginalAccelTable);
|
|
|
|
SAFE_DELETE(m_pKeyNameText);
|
|
|
|
}
|
|
|
|
void CXTPShortcutManager::SetAccelerators(UINT nIDResource)
|
|
{
|
|
m_pAccelTable->RemoveAll();
|
|
|
|
LPCTSTR lpszResourceName = MAKEINTRESOURCE(nIDResource);
|
|
HINSTANCE hInst = AfxFindResourceHandle(lpszResourceName, RT_ACCELERATOR);
|
|
|
|
if (hInst)
|
|
{
|
|
HACCEL hAccel = ::LoadAccelerators(hInst, lpszResourceName);
|
|
|
|
m_pAccelTable->CopyAccelTable(hAccel);
|
|
CreateOriginalAccelTable();
|
|
}
|
|
}
|
|
|
|
void CXTPShortcutManager::SetDefaultAccelerator(HACCEL hAccelTable)
|
|
{
|
|
m_pAccelTable->CopyAccelTable(hAccelTable);
|
|
CreateOriginalAccelTable();
|
|
}
|
|
|
|
void CXTPShortcutManager::CreateOriginalAccelTable()
|
|
{
|
|
if (m_pOriginalAccelTable == NULL)
|
|
m_pOriginalAccelTable = new CXTPShortcutManagerAccelTable(this);
|
|
|
|
m_pOriginalAccelTable->CopyAccelTable(m_pAccelTable);
|
|
}
|
|
|
|
void CXTPShortcutManager::Reset()
|
|
{
|
|
ASSERT(m_pOriginalAccelTable);
|
|
|
|
if (m_pOriginalAccelTable)
|
|
{
|
|
m_pAccelTable->CopyAccelTable(m_pOriginalAccelTable);
|
|
}
|
|
}
|
|
|
|
CString CXTPShortcutManager::Format(CXTPShortcutManagerAccel* lpAccel, int* pPriority)
|
|
{
|
|
CString str;
|
|
CKeyHelper helper (lpAccel, this);
|
|
helper.Format (str);
|
|
|
|
if (pPriority)
|
|
{
|
|
*pPriority = helper.Priority();
|
|
}
|
|
|
|
return str;
|
|
}
|
|
|
|
BOOL CXTPShortcutManager::OnPreviewEditKey(CXTPShortcutManagerAccel* pAccel)
|
|
{
|
|
if ((pAccel->key[0].fVirt & FCONTROL) == 0
|
|
&& (pAccel->key[0].fVirt & FSHIFT) == 0
|
|
&& (pAccel->key[0].fVirt & FALT) == 0
|
|
&& (pAccel->key[0].fVirt & FVIRTKEY)
|
|
&& (pAccel->key[0].key == VK_ESCAPE) && !m_bAllowEscapeShortcut)
|
|
return FALSE;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void CXTPShortcutManager::DisableShortcuts(BOOL bDisable)
|
|
{
|
|
m_nDisableShortcuts += bDisable ? +1 : -1;
|
|
}
|
|
|
|
BOOL CXTPShortcutManager::IsAccelMessage(CXTPShortcutManagerAccel::SHORTCUTACCEL& accel, int nKeyState, LPMSG lpMsg) const
|
|
{
|
|
BOOL fVirt = lpMsg->message == WM_KEYDOWN || lpMsg->message == WM_SYSKEYDOWN;
|
|
WORD flags = accel.fVirt;
|
|
|
|
if ( (DWORD)accel.key != lpMsg->wParam ||
|
|
((fVirt != 0) != ((flags & FVIRTKEY) != 0)))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
if (fVirt && ((nKeyState & (FSHIFT | FCONTROL)) != (flags & (FSHIFT | FCONTROL))))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
if ((nKeyState & FALT) != (flags & FALT))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
int CXTPShortcutManager::GetAccelKeyState() const
|
|
{
|
|
int vkCtrl = VK_CONTROL;
|
|
int vkAlt = VK_MENU;
|
|
|
|
if ((GetKeyState(VK_RMENU) & 0x8000) && (GetKeyState(VK_LCONTROL) & 0x8000))
|
|
{
|
|
vkCtrl = VK_RCONTROL;
|
|
vkAlt = VK_LMENU;
|
|
}
|
|
|
|
int nKeyState = 0;
|
|
if (GetKeyState(vkCtrl) & 0x8000) nKeyState |= FCONTROL;
|
|
if (GetKeyState(vkAlt) & 0x8000) nKeyState |= FALT;
|
|
if (GetKeyState(VK_SHIFT) & 0x8000) nKeyState |= FSHIFT;
|
|
|
|
return nKeyState;
|
|
}
|
|
|
|
BOOL CXTPShortcutManager::TranslateAccelerator(LPMSG lpMsg)
|
|
{
|
|
if (!m_pCommandBars || m_pCommandBars->IsCustomizeMode())
|
|
return FALSE;
|
|
|
|
HWND hWnd = m_pCommandBars->GetSite()->GetSafeHwnd();
|
|
|
|
if (m_nDisableShortcuts > 0)
|
|
return FALSE;
|
|
|
|
CXTPShortcutManagerAccelTable* pAccelTable = GetDefaultAccelerator();
|
|
|
|
if (pAccelTable == NULL || pAccelTable->GetCount() == 0)
|
|
return FALSE;
|
|
|
|
if (lpMsg->message != WM_KEYDOWN && lpMsg->message != WM_SYSKEYDOWN && lpMsg->message != WM_CHAR && lpMsg->message != WM_SYSCHAR)
|
|
return FALSE;
|
|
|
|
int nKeyState = GetAccelKeyState();
|
|
|
|
BOOL bFound = FALSE;
|
|
|
|
int nAccelSize = pAccelTable->GetCount();
|
|
|
|
for (int i = 0; i < nAccelSize; i++)
|
|
{
|
|
CXTPShortcutManagerAccel* accel = pAccelTable->GetAt(i);
|
|
|
|
if (!IsAccelMessage(accel->key[0], nKeyState, lpMsg))
|
|
continue;
|
|
|
|
bFound = TRUE;
|
|
|
|
if (IsWindowEnabled(hWnd) && (!m_bDisableOnCapture || ::GetCapture() == NULL) && !IsIconic(hWnd) && accel->cmd != 0)
|
|
{
|
|
if (accel->key[1].key != 0)
|
|
{
|
|
if (m_pCommandBars->GetSite()->IsFrameWnd())
|
|
{
|
|
CKeyHelper key(accel, this);
|
|
CString strMessage, strFormat;
|
|
|
|
CXTPResourceManager::AssertValid(XTPResourceManager()->LoadString(&strFormat, XTP_IDS_SHORTCUT_SECONDKEY));
|
|
strMessage.Format(strFormat, (LPCTSTR)key.Format(&accel->key[0]));
|
|
|
|
((CFrameWnd*)m_pCommandBars->GetSite())->SetMessageText(strMessage);
|
|
}
|
|
|
|
BOOL bAccept = FALSE;
|
|
|
|
m_nDisableShortcuts++;
|
|
|
|
::SetCapture(hWnd);
|
|
while (::GetCapture() == hWnd)
|
|
{
|
|
MSG msg;
|
|
VERIFY(::GetMessage(&msg, NULL, 0, 0));
|
|
|
|
if (msg.message == WM_KEYDOWN || msg.message == WM_SYSKEYDOWN)
|
|
{
|
|
if (msg.wParam == VK_SHIFT || msg.wParam == VK_CONTROL || msg.wParam == VK_MENU)
|
|
continue;
|
|
|
|
nKeyState = GetAccelKeyState();
|
|
|
|
for (int j = 0; j < nAccelSize; j++)
|
|
{
|
|
CXTPShortcutManagerAccel* secondAccel = pAccelTable->GetAt(j);
|
|
|
|
if (secondAccel->key[0].fVirt == accel->key[0].fVirt && secondAccel->key[0].key == accel->key[0].key)
|
|
{
|
|
if (!IsAccelMessage(secondAccel->key[1], nKeyState, &msg))
|
|
continue;
|
|
|
|
bAccept = TRUE;
|
|
accel = secondAccel;
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
if (!bAccept)
|
|
{
|
|
MessageBeep(MB_ICONEXCLAMATION);
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
DispatchMessage (&msg);
|
|
|
|
if (msg.message == WM_COMMAND || msg.message == WM_ACTIVATE || msg.message == WM_LBUTTONDOWN ||
|
|
msg.message == WM_NCACTIVATE || msg.message == WM_CLOSE || msg.message == WM_SYSCOMMAND)
|
|
break;
|
|
}
|
|
::ReleaseCapture();
|
|
|
|
m_nDisableShortcuts--;
|
|
|
|
if (IsWindow(hWnd) && m_pCommandBars->GetSite()->IsFrameWnd())
|
|
{
|
|
((CFrameWnd*)m_pCommandBars->GetSite())->SetMessageText((UINT)0);
|
|
}
|
|
|
|
if (!bAccept)
|
|
return TRUE;
|
|
}
|
|
|
|
SendMessage(hWnd, WM_COMMAND, accel->cmd, 0);
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return bFound;
|
|
}
|
|
|
|
BOOL CXTPShortcutManager::FindDefaultFrameAccelerator(int nCmd, CString& strShortcut)
|
|
{
|
|
CFrameWnd* pFrame = DYNAMIC_DOWNCAST(CFrameWnd, m_pCommandBars->GetSite());
|
|
HACCEL hAccelTable = pFrame ? pFrame->m_hAccelTable : NULL;
|
|
|
|
if (!hAccelTable)
|
|
return FALSE;
|
|
|
|
ASSERT(hAccelTable);
|
|
|
|
int nAccelSize = ::CopyAcceleratorTable (hAccelTable, NULL, 0);
|
|
|
|
LPACCEL lpAccel = new ACCEL[nAccelSize];
|
|
::CopyAcceleratorTable (hAccelTable, lpAccel, nAccelSize);
|
|
|
|
BOOL bFound = FALSE;
|
|
BOOL bEqual = FALSE;
|
|
CString strFirst = _T("");
|
|
int nFirstPriorety = 0;
|
|
|
|
|
|
for (int i = 0; i < nAccelSize; i++)
|
|
{
|
|
if (lpAccel[i].cmd == nCmd)
|
|
{
|
|
int nPriority = 0;
|
|
CXTPShortcutManagerAccel accel(&lpAccel[i]);
|
|
CString str = Format(&accel, &nPriority);
|
|
|
|
if (str == strShortcut)
|
|
bEqual = TRUE;
|
|
|
|
if (strFirst.IsEmpty() || (nFirstPriorety < nPriority))
|
|
{
|
|
strFirst = str;
|
|
nFirstPriorety = nPriority;
|
|
}
|
|
|
|
bFound = TRUE;
|
|
}
|
|
}
|
|
delete[] lpAccel;
|
|
|
|
if (!bFound)
|
|
strShortcut = "";
|
|
else if (!bEqual)
|
|
strShortcut = strFirst;
|
|
|
|
return bFound;
|
|
}
|
|
|
|
BOOL CXTPShortcutManager::FindDefaultAccelerator(int nCmd, CString& strShortcut)
|
|
{
|
|
CXTPShortcutManagerAccelTable* pAccelTable = GetDefaultAccelerator();
|
|
|
|
int nAccelSize = pAccelTable ? pAccelTable->GetCount() : 0;
|
|
|
|
if (m_pOriginalAccelTable == NULL && nAccelSize == 0)
|
|
return FindDefaultFrameAccelerator(nCmd, strShortcut);
|
|
|
|
if (nAccelSize == 0)
|
|
return FALSE;
|
|
|
|
BOOL bFound = FALSE;
|
|
BOOL bEqual = FALSE;
|
|
CString strFirst = _T("");
|
|
int nFirstPriorety = 0;
|
|
|
|
for (int i = 0; i < nAccelSize; i++)
|
|
{
|
|
CXTPShortcutManagerAccel* accel = pAccelTable->GetAt(i);
|
|
if (accel->cmd == (int)nCmd)
|
|
{
|
|
int nPriority = 0;
|
|
CString str = Format(accel, &nPriority);
|
|
|
|
if (str == strShortcut)
|
|
bEqual = TRUE;
|
|
|
|
if (strFirst.IsEmpty() || (nFirstPriorety < nPriority))
|
|
{
|
|
strFirst = str;
|
|
nFirstPriorety = nPriority;
|
|
}
|
|
|
|
bFound = TRUE;
|
|
}
|
|
}
|
|
|
|
if (!bFound)
|
|
strShortcut = "";
|
|
else if (!bEqual)
|
|
strShortcut = strFirst;
|
|
|
|
return bFound;
|
|
}
|
|
|
|
CXTPShortcutManager::CKeyHelper::CKeyHelper(const CXTPShortcutManagerAccel* lpAccel, CXTPShortcutManager* pManager/*= NULL*/) :
|
|
m_pManager(pManager), m_lpAccel (lpAccel)
|
|
{
|
|
m_bAllowLocaleKey = TRUE;
|
|
}
|
|
|
|
CXTPShortcutManager::CKeyHelper::~CKeyHelper()
|
|
{
|
|
}
|
|
|
|
int CXTPShortcutManager::CKeyHelper::Priority()
|
|
{
|
|
if (m_lpAccel == NULL)
|
|
return 0;
|
|
if (m_lpAccel->key[0].fVirt & FCONTROL)
|
|
return 3;
|
|
if (m_lpAccel->key[0].fVirt & FALT)
|
|
return 2;
|
|
if (m_lpAccel->key[0].fVirt & FSHIFT)
|
|
return 1;
|
|
return 4;
|
|
}
|
|
|
|
void CXTPShortcutManager::CKeyHelper::Format(CString& str) const
|
|
{
|
|
str.Empty ();
|
|
|
|
if (m_lpAccel == NULL)
|
|
{
|
|
ASSERT (FALSE);
|
|
return;
|
|
}
|
|
|
|
str = Format(&m_lpAccel->key[0]);
|
|
|
|
if (m_lpAccel->key[1].key != 0)
|
|
{
|
|
CString str2 = Format(&m_lpAccel->key[1]);
|
|
|
|
if (!str2.IsEmpty())
|
|
{
|
|
str += _T(", ") + str2;
|
|
}
|
|
}
|
|
}
|
|
|
|
CString CXTPShortcutManager::CKeyHelper::Format(const CXTPShortcutManagerAccel::SHORTCUTACCEL* pAccel) const
|
|
{
|
|
CString str;
|
|
|
|
if (pAccel->key != VK_CANCEL)
|
|
{
|
|
if (pAccel->fVirt & FCONTROL)
|
|
{
|
|
AddVirtKeyStr(str, VK_CONTROL);
|
|
}
|
|
|
|
if (pAccel->fVirt & FSHIFT)
|
|
{
|
|
AddVirtKeyStr(str, VK_SHIFT);
|
|
}
|
|
|
|
if (pAccel->fVirt & FALT)
|
|
{
|
|
AddVirtKeyStr(str, VK_MENU);
|
|
}
|
|
|
|
if (pAccel->fVirt & 0x20)
|
|
{
|
|
AddVirtKeyStr (str, VK_LWIN);
|
|
}
|
|
}
|
|
|
|
if (pAccel->key)
|
|
{
|
|
if (pAccel->fVirt & FVIRTKEY)
|
|
{
|
|
AddVirtKeyStr(str, pAccel->key, TRUE);
|
|
}
|
|
else if ((pAccel->key >= 1 && pAccel->key <= 26) && (pAccel->fVirt == FNOINVERT))
|
|
{
|
|
AddVirtKeyStr(str, VK_CONTROL);
|
|
str += (char) ('A' + pAccel->key - 1);
|
|
}
|
|
else if (pAccel->key != VK_ESCAPE && pAccel->key != VK_TAB)
|
|
{
|
|
str += (char) pAccel->key;
|
|
}
|
|
}
|
|
else if (str.GetLength() > 0)
|
|
{
|
|
str = str.Left(str.GetLength() - 1);
|
|
}
|
|
return str;
|
|
}
|
|
|
|
|
|
void CXTPShortcutManager::CKeyHelper::AddVirtKeyStr(CString& str, UINT uiVirtKey, BOOL bLast) const
|
|
{
|
|
ASSERT(m_pManager);
|
|
if (!m_pManager)
|
|
return;
|
|
|
|
CString strKey;
|
|
|
|
if (m_bAllowLocaleKey)
|
|
{
|
|
strKey = m_pManager->GetKeyNameText(uiVirtKey);
|
|
}
|
|
else
|
|
{
|
|
strKey = m_pManager->m_pKeyNameText->Translate(uiVirtKey);
|
|
|
|
if (strKey.IsEmpty())
|
|
{
|
|
strKey.Format(_T("0x%x"), uiVirtKey);
|
|
}
|
|
|
|
}
|
|
|
|
if (!strKey.IsEmpty())
|
|
{
|
|
str += strKey;
|
|
|
|
if (!bLast)
|
|
{
|
|
str += '+';
|
|
}
|
|
}
|
|
}
|
|
|
|
CString CXTPShortcutManager::CKeyHelper::GetLocalKeyNameText(UINT uiVirtKey)
|
|
{
|
|
#define BUFFER_LEN 50
|
|
TCHAR szBuffer[BUFFER_LEN + 1];
|
|
ZeroMemory(szBuffer, BUFFER_LEN);
|
|
|
|
if (uiVirtKey == VK_CANCEL)
|
|
return _T("");
|
|
|
|
UINT nScanCode = ::MapVirtualKeyEx (uiVirtKey, 0,
|
|
::GetKeyboardLayout (0)) << 16 | 0x1;
|
|
|
|
if (uiVirtKey >= VK_PRIOR && uiVirtKey <= VK_HELP)
|
|
{
|
|
nScanCode |= 0x01000000;
|
|
}
|
|
|
|
::GetKeyNameText(nScanCode, szBuffer, BUFFER_LEN);
|
|
|
|
CString strKey = szBuffer;
|
|
|
|
if (!strKey.IsEmpty())
|
|
{
|
|
strKey.MakeLower();
|
|
|
|
for (int i = 0; i < strKey.GetLength(); i++)
|
|
{
|
|
TCHAR c = strKey[i];
|
|
if (IsCharLower(c))
|
|
{
|
|
strKey.SetAt (i, CXTPShortcutManager::ToUpper(c));
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return strKey;
|
|
}
|
|
|
|
int CXTPShortcutManager::FindAccelPos(LPCTSTR lpszAccel)
|
|
{
|
|
LPCTSTR lpsz = _tcschr(lpszAccel, _T('&'));
|
|
|
|
while (lpsz && *(lpsz + 1) == _T('&'))
|
|
{
|
|
lpsz = _tcschr(lpsz + 2, _T('&'));
|
|
}
|
|
|
|
return (lpsz == NULL) ? -1 : (int)(lpsz - lpszAccel);
|
|
}
|
|
|
|
BOOL CXTPShortcutManager::CompareAccelKey(TCHAR chAccel, UINT wParam)
|
|
{
|
|
if (wParam >= VK_NUMPAD0 && wParam <= VK_NUMPAD9)
|
|
return (UINT)chAccel == (wParam + '0' - VK_NUMPAD0);
|
|
|
|
TCHAR tchVirtualKey = (TCHAR)MapVirtualKey(wParam, 2);
|
|
if (tchVirtualKey == NULL)
|
|
return FALSE;
|
|
|
|
TCHAR chAccelUpper = ToUpper(chAccel);
|
|
|
|
if ((chAccel == (TCHAR)wParam) || (chAccelUpper == (TCHAR)wParam))
|
|
return TRUE;
|
|
|
|
int nLayoutCount = GetKeyboardLayoutList(0, 0);
|
|
if (nLayoutCount >= 1)
|
|
{
|
|
CArray<HKL, HKL&> arrLayoutList;
|
|
arrLayoutList.SetSize(nLayoutCount);
|
|
|
|
GetKeyboardLayoutList(nLayoutCount, arrLayoutList.GetData());
|
|
|
|
BYTE keyState[256];
|
|
if (!GetKeyboardState (keyState))
|
|
return FALSE;
|
|
|
|
for (int i = 0; i < nLayoutCount; i++)
|
|
{
|
|
WORD chKey = 0;
|
|
|
|
#ifdef _UNICODE
|
|
if (ToUnicodeEx((UINT)wParam, 0, keyState, (LPWSTR)&chKey, 1, 0, arrLayoutList[i]) == 1)
|
|
#else
|
|
if (ToAsciiEx((UINT)wParam, 0, keyState, &chKey, 0, arrLayoutList[i]) == 1)
|
|
#endif
|
|
{
|
|
if ((chAccel == (TCHAR)chKey) || (chAccelUpper == ToUpper((TCHAR)chKey)))
|
|
return TRUE;
|
|
}
|
|
|
|
BYTE ksShift = keyState[VK_SHIFT];
|
|
keyState[VK_SHIFT]= 0x81;
|
|
|
|
#ifdef _UNICODE
|
|
if (ToUnicodeEx((UINT)wParam, 0, keyState, (LPWSTR)&chKey, 1, 0, arrLayoutList[i]) == 1)
|
|
#else
|
|
if (ToAsciiEx((UINT)wParam, 0, keyState, &chKey, 0, arrLayoutList[i]) == 1)
|
|
#endif
|
|
{
|
|
if ((chAccel == (TCHAR)chKey) || (chAccelUpper == ToUpper((TCHAR)chKey)))
|
|
return TRUE;
|
|
}
|
|
|
|
keyState[VK_SHIFT] = ksShift;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
void CXTPShortcutManager::SetKeyNameText(UINT uiVirtKey, LPCTSTR strKeyNameText)
|
|
{
|
|
m_pKeyNameText->SetAt(uiVirtKey, strKeyNameText);
|
|
}
|
|
|
|
CString CXTPShortcutManager::GetKeyNameText(UINT uiVirtKey)
|
|
{
|
|
CString strKey;
|
|
|
|
if (m_bUseSystemKeyNameText)
|
|
{
|
|
strKey = CKeyHelper::GetLocalKeyNameText(uiVirtKey);
|
|
}
|
|
|
|
if (strKey.IsEmpty())
|
|
{
|
|
strKey = m_pKeyNameText->Translate(uiVirtKey);
|
|
}
|
|
|
|
if (strKey.IsEmpty() && !m_bUseSystemKeyNameText)
|
|
{
|
|
strKey = CKeyHelper::GetLocalKeyNameText(uiVirtKey);
|
|
}
|
|
|
|
return strKey;
|
|
}
|
|
|
|
TCHAR CXTPShortcutManager::ToUpper(TCHAR vkTCHAR)
|
|
{
|
|
TCHAR szChar[2] = {vkTCHAR, _T('\0') };
|
|
|
|
CharUpper(szChar);
|
|
return szChar[0];
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CKeyAssign
|
|
|
|
CXTPShortcutManager::CKeyAssign::CKeyAssign(CXTPShortcutManager* pManager/*= NULL*/)
|
|
: m_keyHelper(&m_accel, pManager)
|
|
{
|
|
m_nKeyDefined = 0;
|
|
m_bExtendedOnly = FALSE;
|
|
|
|
m_bAllowDoubleKeyShortcuts = pManager ? pManager->m_bAllowDoubleKeyShortcuts : FALSE;
|
|
|
|
ResetKey();
|
|
}
|
|
|
|
CXTPShortcutManager::CKeyAssign::~CKeyAssign()
|
|
{
|
|
}
|
|
|
|
BOOL CXTPShortcutManager::CKeyAssign::PreTranslateMessage(MSG* pMsg)
|
|
{
|
|
if (pMsg->message == WM_LBUTTONDOWN || pMsg->message == WM_MBUTTONDOWN || pMsg->message == WM_RBUTTONDOWN)
|
|
{
|
|
SetFocus ();
|
|
return TRUE;
|
|
}
|
|
|
|
if (pMsg->message != WM_KEYDOWN && pMsg->message != WM_SYSKEYDOWN && pMsg->message != WM_KEYUP && pMsg->message != WM_SYSKEYUP)
|
|
return CEdit::PreTranslateMessage(pMsg);
|
|
|
|
if (m_bAllowDoubleKeyShortcuts)
|
|
return TranslateDoubleKeyShortcutsMessage(pMsg);
|
|
|
|
return TranslateSingleKeyShortcutsMessage(pMsg);
|
|
}
|
|
|
|
BOOL CXTPShortcutManager::CKeyAssign::TranslateDoubleKeyShortcutsMessage(MSG* pMsg)
|
|
{
|
|
BOOL bPressed = pMsg->message == WM_KEYDOWN || pMsg->message == WM_SYSKEYDOWN;
|
|
if (!bPressed)
|
|
return FALSE;
|
|
|
|
BOOL bControlPressed = ::GetKeyState(VK_CONTROL) & 0x8000;
|
|
BOOL bAltPressed = ::GetKeyState(VK_MENU) & 0x8000;
|
|
|
|
if (!bControlPressed && !bAltPressed && (pMsg->wParam == VK_TAB))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
if (pMsg->wParam == VK_SHIFT || pMsg->wParam == VK_CONTROL || pMsg->wParam == VK_MENU)
|
|
return FALSE;
|
|
|
|
if (pMsg->wParam == VK_BACK)
|
|
{
|
|
if (m_nKeyDefined == 2)
|
|
{
|
|
m_accel.key[1].fVirt = 0;
|
|
m_accel.key[1].key = 0;
|
|
m_nKeyDefined = 1;
|
|
}
|
|
else
|
|
{
|
|
ResetKey();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (m_nKeyDefined > 1)
|
|
ResetKey();
|
|
|
|
if (m_nKeyDefined > 1)
|
|
{
|
|
ASSERT(FALSE);
|
|
return FALSE;
|
|
}
|
|
|
|
// read in the actual state because we were not tracking releases if there was a
|
|
// definition
|
|
SetAccelFlag(m_nKeyDefined, FSHIFT, ::GetKeyState(VK_SHIFT) & 0x8000);
|
|
SetAccelFlag(m_nKeyDefined, FCONTROL, bControlPressed);
|
|
SetAccelFlag(m_nKeyDefined, FALT, bAltPressed);
|
|
|
|
m_accel.key[m_nKeyDefined].key = (WORD)pMsg->wParam;
|
|
SetAccelFlag(m_nKeyDefined, FVIRTKEY, TRUE);
|
|
|
|
m_nKeyDefined++;
|
|
}
|
|
|
|
if (m_keyHelper.GetShortcutManager() && !m_keyHelper.GetShortcutManager()->OnPreviewEditKey(&m_accel))
|
|
{
|
|
ResetKey();
|
|
return TRUE;
|
|
}
|
|
|
|
CString str;
|
|
m_keyHelper.Format(str);
|
|
|
|
SetWindowText(str);
|
|
|
|
SetSel(str.GetLength(), str.GetLength());
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL CXTPShortcutManager::CKeyAssign::TranslateSingleKeyShortcutsMessage(MSG* pMsg)
|
|
{
|
|
BOOL bPressed = pMsg->message == WM_KEYDOWN || pMsg->message == WM_SYSKEYDOWN;
|
|
|
|
BOOL bControlPressed = ::GetKeyState(VK_CONTROL) & 0x8000;
|
|
BOOL bAltPressed = ::GetKeyState(VK_MENU) & 0x8000;
|
|
BOOL bWinPressed = (::GetKeyState(VK_LWIN) & 0x8000) || (::GetKeyState(VK_RWIN) & 0x8000);
|
|
|
|
if (!bControlPressed && !bAltPressed && (pMsg->wParam == VK_TAB))
|
|
{
|
|
if (m_nKeyDefined == 0)
|
|
ResetKey();
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
if (bPressed && !((1 << 30) & pMsg->lParam))
|
|
{
|
|
ResetKey();
|
|
}
|
|
|
|
if (m_bExtendedOnly)
|
|
{
|
|
if (bPressed)
|
|
{
|
|
SetAccelFlag(0, FSHIFT, GetKeyState(VK_SHIFT) < 0);
|
|
SetAccelFlag(0, FCONTROL, GetKeyState(VK_CONTROL) < 0);
|
|
SetAccelFlag(0, FALT, GetKeyState(VK_MENU) < 0);
|
|
SetAccelFlag(0, 0x20, bWinPressed);
|
|
}
|
|
}
|
|
else if (m_nKeyDefined == 0)
|
|
{
|
|
// read in the actual state because we were not tracking releases if there was a
|
|
// definition
|
|
SetAccelFlag(0, FSHIFT, ::GetKeyState(VK_SHIFT) & 0x8000);
|
|
SetAccelFlag(0, FCONTROL, bControlPressed);
|
|
SetAccelFlag(0, FALT, bAltPressed);
|
|
SetAccelFlag(0, 0x20, bWinPressed);
|
|
|
|
if (pMsg->wParam == VK_SHIFT
|
|
|| pMsg->wParam == VK_CONTROL
|
|
|| pMsg->wParam == VK_MENU
|
|
|| pMsg->wParam == VK_LWIN
|
|
|| pMsg->wParam == VK_RWIN
|
|
)
|
|
{
|
|
// all work is already done
|
|
}
|
|
else if (bPressed)
|
|
{
|
|
m_accel.key[0].key = (WORD)pMsg->wParam;
|
|
SetAccelFlag(0, FVIRTKEY, TRUE);
|
|
m_nKeyDefined = 1;
|
|
}
|
|
}
|
|
|
|
if (m_keyHelper.GetShortcutManager() && !m_keyHelper.GetShortcutManager()->OnPreviewEditKey(&m_accel))
|
|
{
|
|
ResetKey();
|
|
return TRUE;
|
|
}
|
|
|
|
CString str;
|
|
m_keyHelper.Format (str);
|
|
|
|
SetWindowText(str);
|
|
return TRUE;
|
|
}
|
|
|
|
void CXTPShortcutManager::CKeyAssign::ResetKey()
|
|
{
|
|
m_accel.cmd = 0;
|
|
m_accel.key[0].fVirt = m_accel.key[1].fVirt = 0;
|
|
m_accel.key[0].key = m_accel.key[1].key = 0;
|
|
|
|
|
|
m_nKeyDefined = 0;
|
|
|
|
if (m_hWnd != NULL)
|
|
{
|
|
SetWindowText (_T(""));
|
|
}
|
|
}
|
|
|
|
void CXTPShortcutManager::CKeyAssign::SetAccelFlag(int nKey, BYTE bFlag, BOOL bSet)
|
|
{
|
|
ASSERT(nKey == 0 || nKey == 1);
|
|
if (nKey > 1)
|
|
return;
|
|
|
|
if (bSet) m_accel.key[nKey].fVirt |= bFlag;
|
|
else m_accel.key[nKey].fVirt &= ~bFlag;
|
|
}
|
|
|
|
BOOL CXTPShortcutManager::CKeyAssign::IsKeyDefined () const
|
|
{
|
|
return m_nKeyDefined != 0;
|
|
}
|
|
|
|
CXTPShortcutManagerAccel* CXTPShortcutManager::CKeyAssign::GetAccel()
|
|
{
|
|
return &m_accel;
|
|
}
|
|
|
|
void CXTPShortcutManager::CKeyAssign::SetAccel(CXTPShortcutManagerAccel* pAccel)
|
|
{
|
|
m_accel = *pAccel;
|
|
|
|
m_nKeyDefined = (m_accel.key[0].key != 0 ? 1 : 0) + (m_accel.key[1].key != 0 ? 1 : 0);
|
|
|
|
if (m_hWnd != NULL)
|
|
{
|
|
CString str;
|
|
m_keyHelper.Format (str);
|
|
|
|
SetWindowText (str);
|
|
}
|
|
}
|
|
|
|
void CXTPShortcutManager::UpdateAcellTable(LPACCEL lpAccel, int nSize)
|
|
{
|
|
m_pAccelTable->CopyAccelTable(lpAccel, nSize);
|
|
}
|
|
|
|
void CXTPShortcutManager::UpdateAcellTable(XTP_SHORTCUTMANAGER_ACCEL* lpAccel, int nSize)
|
|
{
|
|
m_pAccelTable->RemoveAll();
|
|
|
|
for (int i = 0; i < nSize; i++)
|
|
{
|
|
m_pAccelTable->Add(lpAccel[i]);
|
|
}
|
|
}
|
|
|
|
BOOL CXTPShortcutManager::GetShortcut(int ID, CXTPShortcutManagerAccel* pAccel)
|
|
{
|
|
CXTPShortcutManagerAccelTable* pAccelTable = GetDefaultAccelerator();
|
|
|
|
if (!pAccelTable)
|
|
return FALSE;
|
|
|
|
for (int i = 0; i < pAccelTable->GetCount(); i++)
|
|
{
|
|
CXTPShortcutManagerAccel* accel = pAccelTable->GetAt(i);
|
|
if (accel->cmd == ID)
|
|
{
|
|
*pAccel = *accel;
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
void CXTPShortcutManager::AddShortcut(long cmd, LPCTSTR strKey)
|
|
{
|
|
CXTPShortcutManagerAccel accel;
|
|
if (!ParseShortcut(strKey, &accel))
|
|
return;
|
|
|
|
accel.cmd = cmd;
|
|
|
|
m_pAccelTable->Add(accel);
|
|
}
|
|
|
|
void CXTPShortcutManager::AddShortcut(long fVirt, long key, long cmd)
|
|
{
|
|
CXTPShortcutManagerAccel accel;
|
|
accel.key[0].fVirt = (BYTE)(fVirt | FVIRTKEY);
|
|
accel.key[0].key = (WORD)key;
|
|
accel.cmd = cmd;
|
|
|
|
int nAccelSize = m_pAccelTable->GetCount();
|
|
|
|
for (int i = 0; i < nAccelSize; i++)
|
|
{
|
|
CXTPShortcutManagerAccel* accelOld = m_pAccelTable->GetAt(i);
|
|
if (CKeyHelper::EqualAccels(&accel, accelOld))
|
|
{
|
|
accelOld->cmd = cmd;
|
|
return;
|
|
}
|
|
}
|
|
|
|
m_pAccelTable->Add(accel);
|
|
}
|
|
|
|
void CXTPShortcutManager::SerializeShortcuts(CArchive& ar)
|
|
{
|
|
CXTPPropExchangeArchive px(ar);
|
|
DoPropExchange(&px);
|
|
}
|
|
|
|
void CXTPShortcutManager::SaveShortcuts(LPCTSTR lpszProfileName)
|
|
{
|
|
if (m_pOriginalAccelTable == NULL)
|
|
return;
|
|
|
|
XTP_SHORTCUTMANAGER_ACCEL* lpAccel = m_pAccelTable->CopyAccels();
|
|
|
|
AfxGetApp()->WriteProfileBinary(lpszProfileName, _T("Accelerators"), (LPBYTE)lpAccel, m_pAccelTable->GetCount() * sizeof(XTP_SHORTCUTMANAGER_ACCEL));
|
|
AfxGetApp()->WriteProfileInt(lpszProfileName, _T("AcceleratorsVersion"), 1);
|
|
|
|
delete[] lpAccel;
|
|
}
|
|
|
|
void CXTPShortcutManager::LoadShortcuts(LPCTSTR lpszProfileName)
|
|
{
|
|
if (m_pOriginalAccelTable == NULL)
|
|
return;
|
|
|
|
int nVersion = AfxGetApp()->GetProfileInt(lpszProfileName, _T("AcceleratorsVersion"), 0);
|
|
|
|
if (nVersion == 0)
|
|
{
|
|
UINT uiSize;
|
|
LPACCEL lpAccel = 0;
|
|
if (AfxGetApp()->GetProfileBinary(lpszProfileName, _T("Accelerators"), (LPBYTE*) &lpAccel, &uiSize))
|
|
{
|
|
int nAccelSize = uiSize / sizeof(ACCEL);
|
|
ASSERT (lpAccel != NULL);
|
|
|
|
UpdateAcellTable(lpAccel, nAccelSize);
|
|
|
|
delete[] lpAccel;
|
|
}
|
|
}
|
|
else if (nVersion == 1)
|
|
{
|
|
UINT uiSize;
|
|
XTP_SHORTCUTMANAGER_ACCEL* lpAccel = 0;
|
|
|
|
if (AfxGetApp()->GetProfileBinary(lpszProfileName, _T("Accelerators"), (LPBYTE*) &lpAccel, &uiSize))
|
|
{
|
|
int nAccelSize = uiSize / sizeof(XTP_SHORTCUTMANAGER_ACCEL);
|
|
ASSERT (lpAccel != NULL);
|
|
|
|
UpdateAcellTable(lpAccel, nAccelSize);
|
|
|
|
delete[] lpAccel;
|
|
}
|
|
}
|
|
}
|
|
|
|
BOOL CXTPShortcutManager::ParseShortcutVirtKey(CString& strShortcutKey, int nAccel) const
|
|
{
|
|
CString str = m_pKeyNameText->Translate(nAccel) + _T('+');
|
|
|
|
int nIndex = strShortcutKey.Find(str);
|
|
if (nIndex != -1)
|
|
{
|
|
strShortcutKey = strShortcutKey.Left(nIndex) + strShortcutKey.Mid(nIndex + str.GetLength());
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL CXTPShortcutManager::ParseShortcut(CString strShortcutKey, BYTE& fVirt, WORD& key) const
|
|
{
|
|
fVirt = FVIRTKEY;
|
|
key = 0;
|
|
|
|
if (ParseShortcutVirtKey(strShortcutKey, VK_CONTROL))
|
|
{
|
|
fVirt |= FCONTROL;
|
|
}
|
|
|
|
if (ParseShortcutVirtKey(strShortcutKey, VK_MENU))
|
|
{
|
|
fVirt |= FALT;
|
|
}
|
|
|
|
if (ParseShortcutVirtKey(strShortcutKey, VK_SHIFT))
|
|
{
|
|
fVirt |= FSHIFT;
|
|
}
|
|
|
|
key = m_pKeyNameText->Parse(strShortcutKey);
|
|
if (key != 0)
|
|
return TRUE;
|
|
|
|
if (strShortcutKey.GetLength() > 3 && strShortcutKey[0] == _T('0') && strShortcutKey[1] == _T('x'))
|
|
{
|
|
SCANF_S(strShortcutKey, _T("0x%hx"), &key);
|
|
}
|
|
|
|
return key != 0;
|
|
}
|
|
|
|
BOOL CXTPShortcutManager::ParseShortcut(CString strShortcut, CXTPShortcutManagerAccel* accel)
|
|
{
|
|
int nIndex = strShortcut.Find(_T(", "));
|
|
if (nIndex == -1)
|
|
{
|
|
if (!ParseShortcut(strShortcut, accel->key[0].fVirt, accel->key[0].key))
|
|
return FALSE;
|
|
|
|
accel->key[1].fVirt = 0;
|
|
accel->key[1].key = 0;
|
|
}
|
|
else
|
|
{
|
|
if (!ParseShortcut(strShortcut.Left(nIndex), accel->key[0].fVirt, accel->key[0].key))
|
|
return FALSE;
|
|
|
|
if (!ParseShortcut(strShortcut.Mid(nIndex + 2), accel->key[1].fVirt, accel->key[1].key))
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void CXTPShortcutManager::DoPropExchange(CXTPPropExchange* pPX)
|
|
{
|
|
pPX->ExchangeSchemaSafe();
|
|
|
|
if (pPX->IsStoring())
|
|
{
|
|
int nAccelSize = m_pAccelTable->GetCount();
|
|
|
|
if (pPX->IsAllowBlobValues())
|
|
{
|
|
XTP_SHORTCUTMANAGER_ACCEL* lpAccel = m_pAccelTable->CopyAccels();
|
|
|
|
pPX->WriteCount(nAccelSize);
|
|
pPX->Write(_T("Data"), lpAccel, nAccelSize * sizeof(XTP_SHORTCUTMANAGER_ACCEL));
|
|
|
|
delete[] lpAccel;
|
|
}
|
|
else
|
|
{
|
|
CXTPPropExchangeEnumeratorPtr pEnumerator(pPX->GetEnumerator(_T("Shortcut")));
|
|
POSITION posEnum = pEnumerator->GetPosition(nAccelSize);
|
|
|
|
for (int i = 0; i < nAccelSize; i++)
|
|
{
|
|
CXTPPropExchangeSection secItem(pEnumerator->GetNext(posEnum));
|
|
|
|
CXTPShortcutManagerAccel* pAccel = m_pAccelTable->GetAt(i);
|
|
|
|
CString strShortcut;
|
|
|
|
CKeyHelper keyHelper(pAccel, this);
|
|
keyHelper.m_bAllowLocaleKey = FALSE;
|
|
|
|
keyHelper.Format(strShortcut);
|
|
|
|
PX_Int(&secItem, _T("Id"), pAccel->cmd, 0);
|
|
PX_String(&secItem, _T("Key"), strShortcut);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m_pAccelTable->RemoveAll();
|
|
|
|
if (pPX->GetSchema() < _XTP_SCHEMA_1200)
|
|
{
|
|
if (pPX->IsAllowBlobValues())
|
|
{
|
|
int nAccelSize = (int)pPX->ReadCount();
|
|
LPACCEL lpAccel = new ACCEL[nAccelSize];
|
|
pPX->Read(_T("Data"), lpAccel, nAccelSize* sizeof(ACCEL));
|
|
|
|
UpdateAcellTable(lpAccel, nAccelSize);
|
|
delete[] lpAccel;
|
|
}
|
|
else
|
|
{
|
|
CArray<ACCEL, ACCEL&> accels;
|
|
CXTPPropExchangeEnumeratorPtr pEnumerator(pPX->GetEnumerator(_T("Accel")));
|
|
POSITION posEnum = pEnumerator->GetPosition(0);
|
|
while (posEnum)
|
|
{
|
|
ACCEL accel;
|
|
CXTPPropExchangeSection secItem(pEnumerator->GetNext(posEnum));
|
|
PX_UShort(&secItem, _T("Id"), (USHORT&)(accel.cmd), 0);
|
|
PX_Byte(&secItem, _T("virt"), (accel.fVirt), 0);
|
|
PX_UShort(&secItem, _T("key"), (USHORT&)(accel.key), 0);
|
|
accels.Add(accel);
|
|
}
|
|
UpdateAcellTable(accels.GetData(), (int)accels.GetSize());
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
if (pPX->IsAllowBlobValues())
|
|
{
|
|
int nAccelSize = (int)pPX->ReadCount();
|
|
|
|
XTP_SHORTCUTMANAGER_ACCEL* lpAccel = new XTP_SHORTCUTMANAGER_ACCEL[nAccelSize];
|
|
pPX->Read(_T("Data"), lpAccel, nAccelSize * sizeof(XTP_SHORTCUTMANAGER_ACCEL));
|
|
|
|
UpdateAcellTable(lpAccel, nAccelSize);
|
|
delete[] lpAccel;
|
|
}
|
|
else
|
|
{
|
|
CXTPPropExchangeEnumeratorPtr pEnumerator(pPX->GetEnumerator(_T("Shortcut")));
|
|
POSITION posEnum = pEnumerator->GetPosition(0);
|
|
while (posEnum)
|
|
{
|
|
CXTPShortcutManagerAccel accel;
|
|
CXTPPropExchangeSection secItem(pEnumerator->GetNext(posEnum));
|
|
PX_Int(&secItem, _T("Id"), accel.cmd, 0);
|
|
|
|
CString strShortcut;
|
|
// TODO: Add Parse Here
|
|
PX_String(&secItem, _T("Key"), strShortcut, _T(""));
|
|
if (ParseShortcut(strShortcut, &accel))
|
|
{
|
|
m_pAccelTable->Add(accel);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
BOOL CXTPShortcutManager::OnBeforeAdd(CXTPShortcutManagerAccel* accel)
|
|
{
|
|
|
|
UNREFERENCED_PARAMETER(accel);
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL CXTPShortcutManager::OnBeforeRemove(CXTPShortcutManagerAccel* accel)
|
|
{
|
|
|
|
UNREFERENCED_PARAMETER(accel);
|
|
return FALSE;
|
|
}
|
|
|