preferencesshortcutspage.cpp

来自「管理项目进度工具的原代码」· C++ 代码 · 共 599 行 · 第 1/2 页

CPP
599
字号
// PrefererencesShortcutsPage.cpp : implementation file
//

#include "stdafx.h"
#include "todolist.h"
#include "PreferencesShortcutsPage.h"
#include "todoctrl.h"

#include "..\shared\winclasses.h"
#include "..\shared\wclassdefines.h"
#include "..\shared\enstring.h"
#include "..\shared\holdredraw.h"
#include "..\shared\treectrlhelper.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CPreferencesShortcutsPage property page

CPreferencesShortcutsPage::CPreferencesShortcutsPage(CShortcutManager* pMgr, UINT nMenuID, BOOL bIgnoreGrayedItems) 
	: CPreferencesPageBase(CPreferencesShortcutsPage::IDD), 
	m_nMenuID(nMenuID), m_pShortcutMgr(pMgr), m_bIgnoreGrayedItems(bIgnoreGrayedItems)
{
	//{{AFX_DATA_INIT(CPreferencesShortcutsPage)
	m_sOtherCmdID = _T("");
	//}}AFX_DATA_INIT
}

CPreferencesShortcutsPage::~CPreferencesShortcutsPage()
{
}

void CPreferencesShortcutsPage::DoDataExchange(CDataExchange* pDX)
{
	CPreferencesPageBase::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CPreferencesShortcutsPage)
	DDX_Control(pDX, IDC_CURHOTKEY, m_hkCur);
	DDX_Control(pDX, IDC_COMMANDS, m_tcCommands);
	DDX_Control(pDX, IDC_NEWHOTKEY, m_hkNew);
	DDX_Text(pDX, IDC_INUSE, m_sOtherCmdID);
	//}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CPreferencesShortcutsPage, CPreferencesPageBase)
	//{{AFX_MSG_MAP(CPreferencesShortcutsPage)
	ON_BN_CLICKED(IDC_ASSIGNSHORTCUT, OnAssignshortcut)
	//}}AFX_MSG_MAP
	ON_NOTIFY(TVN_SELCHANGED, IDC_COMMANDS, OnSelchangedShortcuts)
	ON_EN_CHANGE(IDC_NEWHOTKEY, OnChangeShortcut)
	ON_REGISTERED_MESSAGE(WM_NCG_DRAWITEM, OnGutterDrawItem)
	ON_REGISTERED_MESSAGE(WM_NCG_RECALCCOLWIDTH, OnGutterRecalcColWidth)
	ON_NOTIFY(NM_CUSTOMDRAW, IDC_COMMANDS, OnTreeCustomDraw)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CPreferencesShortcutsPage message handlers

BOOL CPreferencesShortcutsPage::OnInitDialog() 
{
	CPreferencesPageBase::OnInitDialog();

	m_tcCommands.AddGutterColumn(PSP_SHORTCUTCOLUMNID, CEnString(IDS_PSP_SHORTCUT));

	m_tcCommands.SetGutterColumnHeaderTitle(NCG_CLIENTCOLUMNID, CEnString(IDS_PSP_MENUITEM));
	m_tcCommands.ShowGutterPosColumn(FALSE);
	m_tcCommands.SetGridlineColor(OTC_GRIDCOLOR);
	m_tcCommands.EnableGutterColumnHeaderClicking(PSP_SHORTCUTCOLUMNID, FALSE);
	m_tcCommands.EnableGutterColumnHeaderClicking(NCG_CLIENTCOLUMNID, FALSE);
	
	if (m_nMenuID && m_pShortcutMgr)
	{
		m_tcCommands.SendMessage(WM_NULL);
		m_tcCommands.SendMessage(WM_SETREDRAW, FALSE);

		CMenu menu;
		HTREEITEM htiFirst = NULL;

		if (menu.LoadMenu(m_nMenuID))
		{
			for (int nPos = 0; nPos < (int)menu.GetMenuItemCount(); nPos++)
			{
				HTREEITEM hti = AddMenuItem(NULL, &menu, nPos);

				if (!htiFirst)
					htiFirst = hti;

				m_tcCommands.Expand(hti, TVE_EXPAND);
			}
		}

		if (htiFirst)
			m_tcCommands.EnsureVisible(htiFirst);

		m_tcCommands.SendMessage(WM_SETREDRAW, TRUE);

		// init hotkey controls
		// note: we no longer pass in m_pShortcutMgr->GetInvalidComb() because
		// the hotkey control does a less than perfect job of respecting these
		m_hkNew.SetRules(0, 0);
	}
	
	return TRUE;  // return TRUE unless you set the focus to a control
	              // EXCEPTION: OCX Property Pages should return FALSE
}

HTREEITEM CPreferencesShortcutsPage::AddMenuItem(HTREEITEM htiParent, const CMenu* pMenu, int nPos)
{
	CString sItem;
	pMenu->GetMenuString(nPos, sItem, MF_BYPOSITION);

	// remove '&'
	sItem.Replace("&&", "~~~");
	sItem.Replace("&", "");
	sItem.Replace("~~~", "&");
	
	// remove everything after '\t'
	int nTab = sItem.Find('\t');
	
	if (nTab >= 0)
		sItem = sItem.Left(nTab);
	
	if (!sItem.IsEmpty())
	{
		// don't add disabled items if req
		if (m_bIgnoreGrayedItems && (pMenu->GetMenuState(nPos, MF_BYPOSITION) & MF_GRAYED))
			return NULL;

		HTREEITEM hti = m_tcCommands.InsertItem(sItem, htiParent ? htiParent : TVI_ROOT);

		if (hti)
		{
			UINT nCmdID = pMenu->GetMenuItemID(nPos);
			
			if (nCmdID == (UINT)-1) // submenu
			{
				// make top level items bold
				if (!htiParent)
					m_tcCommands.SetItemState(hti, TVIS_BOLD, TVIS_BOLD);

				CMenu* pSubMenu = pMenu->GetSubMenu(nPos);

				if (pSubMenu)
				{
					for (int nSubPos = 0; nSubPos < (int)pSubMenu->GetMenuItemCount(); nSubPos++)
						m_tcCommands.Expand(AddMenuItem(hti, pSubMenu, nSubPos), TVE_EXPAND);
				}
			}
			else
			{
				DWORD dwShortcut = m_pShortcutMgr->GetShortcut(nCmdID);

				if (dwShortcut)
				{
					m_mapID2Shortcut[nCmdID] = dwShortcut;
					m_mapShortcut2HTI[dwShortcut] = hti;
				}

				m_tcCommands.SetItemData(hti, nCmdID);
			}

			return hti;
		}
	}

	return NULL;
}

void CPreferencesShortcutsPage::OnSelchangedShortcuts(NMHDR* pNMHDR, LRESULT* pResult) 
{
	NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;

	UINT nCmdID = (UINT)pNMTreeView->itemNew.lParam;
	DWORD dwShortcut = 0;
	
	m_mapID2Shortcut.Lookup(nCmdID, dwShortcut);

	WORD wVKeyCode = LOWORD(dwShortcut);
	WORD wModifiers = HIWORD(dwShortcut);

	m_hkCur.SetHotKey(wVKeyCode, wModifiers);
	m_hkNew.SetHotKey(wVKeyCode, wModifiers);

	BOOL bCanHaveShortcut = !m_tcCommands.ItemHasChildren(pNMTreeView->itemNew.hItem);

	m_hkNew.EnableWindow(bCanHaveShortcut);
	GetDlgItem(IDC_CURLABEL)->EnableWindow(bCanHaveShortcut);
	GetDlgItem(IDC_NEWLABEL)->EnableWindow(bCanHaveShortcut);

	// test for reserved shortcut
	// and disable assign button as feedback
	if (bCanHaveShortcut && CToDoCtrl::IsReservedShortcut(dwShortcut))
	{
		bCanHaveShortcut = FALSE;
		m_sOtherCmdID.LoadString(IDS_PSP_RESERVED);
	}
	else
		m_sOtherCmdID.Empty();

	GetDlgItem(IDC_ASSIGNSHORTCUT)->EnableWindow(bCanHaveShortcut);
	UpdateData(FALSE);
	
	*pResult = 0;
}

void CPreferencesShortcutsPage::OnOK()
{
	// copy all the changes to m_pShortcutMgr
	POSITION pos = m_mapID2Shortcut.GetStartPosition();

	while (pos)
	{
		UINT nCmdID = 0;
		DWORD dwShortcut = 0;

		m_mapID2Shortcut.GetNextAssoc(pos, nCmdID, dwShortcut);
		ASSERT (nCmdID);

		m_pShortcutMgr->SetShortcut(nCmdID, dwShortcut);
	}

	m_pShortcutMgr->SaveSettings();
}


void CPreferencesShortcutsPage::OnAssignshortcut() 
{
	HTREEITEM htiSel = m_tcCommands.GetSelectedItem();

	if (!htiSel)
		return;
	
	UINT nCmdID = m_tcCommands.GetItemData(htiSel);

	if (nCmdID)
	{
		// remove any shortcut currently assigned to nCmdID
		DWORD dwPrevSC = 0;

		if (m_mapID2Shortcut.Lookup(nCmdID, dwPrevSC))
			m_mapShortcut2HTI.RemoveKey(dwPrevSC);

		WORD wVKeyCode = 0, wModifiers = 0;
		m_hkNew.GetHotKey(wVKeyCode, wModifiers);

		DWORD dwShortcut = MAKELONG(wVKeyCode, wModifiers);
		
		// handle special case where user is explicitly deleting a 
		// shortcut
		if (!dwShortcut)
			dwShortcut = NO_SHORTCUT;
		// else if anyone has this shortcut we must remove their mapping first
		else
		{
			HTREEITEM htiOther = NULL;

			if (m_mapShortcut2HTI.Lookup(dwShortcut, htiOther) && htiOther)
			{
				UINT nOtherCmdID = m_tcCommands.GetItemData(htiOther);

				if (nOtherCmdID)
					m_mapID2Shortcut.RemoveKey(nOtherCmdID);
			}
		}

		// update maps
		m_mapID2Shortcut[nCmdID] = dwShortcut;

		if (dwShortcut != NO_SHORTCUT)
		{
			m_mapShortcut2HTI[dwShortcut] = htiSel;
			m_hkCur.SetHotKey(LOWORD(dwShortcut), HIWORD(dwShortcut));
		}

		m_sOtherCmdID.Empty();

		m_tcCommands.RecalcGutter();
		m_tcCommands.RedrawGutter();

		CTreeCtrlHelper(m_tcCommands).InvalidateItem(htiSel);

		UpdateData(FALSE);
	}
}

void CPreferencesShortcutsPage::OnChangeShortcut()
{
	HTREEITEM htiSel = m_tcCommands.GetSelectedItem();

	if (!htiSel)
		return;

	UINT nCmdID = m_tcCommands.GetItemData(htiSel);

	WORD wVKeyCode = 0, wModifiers = 0;
	m_hkNew.GetHotKey(wVKeyCode, wModifiers);

⌨️ 快捷键说明

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