| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204 | #include "./menushortcuts.h"#include <strsafe.h>// change key string to capitalised only so it's more UI consistant (otherwise messes up the localisation look)wchar_t* CapitaliseKeyName(wchar_t* szAccelName){	if(szAccelName) {		wchar_t *p = &szAccelName[1];		int space = 0;		while(p && *p){			if(*p == L' ') space = 1;			else {				if(!space) {					*p = tolower(*p);				}				else {					space = 0;				}			}			p = CharNextW(p);		}	}	return szAccelName;}BOOL AppendShortcutTextEx(LPWSTR pszItemText, INT cchTextMax, WORD wID, ACCEL *pszAccel, INT cchAccel, UINT uMode) {	BOOL bDirty = FALSE;	if (!pszItemText) return FALSE;	UINT cchLen = lstrlenW(pszItemText);	if (MSF_REPLACE == (0x0F & uMode))	{		UINT len;		for (len = 0; len < cchLen && L'\t' != pszItemText[len]; len++);		if (cchLen != len)		{			cchLen = len;			pszItemText[len] = L'\0';			bDirty = TRUE;		}	}	if (wID > 0)	{		wchar_t szAccelName[64] = {0};		BOOL bFirst = TRUE;		pszItemText += cchLen;		size_t cchText = cchTextMax - cchLen;		for(int k = 0; k < cchAccel; k++)		{			if (wID == pszAccel[k].cmd)			{				HRESULT hr = StringCchCopyExW(pszItemText, cchText, ((bFirst) ? L"\t" : L", "),  &pszItemText, &cchText, STRSAFE_IGNORE_NULLS);				if (S_OK == hr && (FCONTROL & pszAccel[k].fVirt)) {					GetKeyNameTextW(MapVirtualKey(VK_CONTROL, 0)<<16, szAccelName, sizeof(szAccelName)/sizeof(szAccelName[0]));					hr = StringCchCopyExW(pszItemText, cchText, CapitaliseKeyName(szAccelName), &pszItemText, &cchText, STRSAFE_IGNORE_NULLS);					if(S_OK == hr) StringCchCatExW(pszItemText, cchText, L"+", &pszItemText, &cchText, STRSAFE_IGNORE_NULLS);				}				if (S_OK == hr && (FALT & pszAccel[k].fVirt)) {					GetKeyNameTextW(MapVirtualKey(VK_MENU, 0)<<16, szAccelName, sizeof(szAccelName)/sizeof(szAccelName[0]));					hr = StringCchCopyExW(pszItemText, cchText, CapitaliseKeyName(szAccelName), &pszItemText, &cchText, STRSAFE_IGNORE_NULLS);					if(S_OK == hr) hr = StringCchCatExW(pszItemText, cchText, L"+", &pszItemText, &cchText, STRSAFE_IGNORE_NULLS);				}				if (S_OK == hr && (FSHIFT & pszAccel[k].fVirt)) {					GetKeyNameTextW(MapVirtualKey(VK_SHIFT, 0)<<16, szAccelName, sizeof(szAccelName)/sizeof(szAccelName[0]));					hr = StringCchCopyExW(pszItemText, cchText, CapitaliseKeyName(szAccelName), &pszItemText, &cchText, STRSAFE_IGNORE_NULLS);					if(S_OK == hr) hr = StringCchCatExW(pszItemText, cchText, L"+", &pszItemText, &cchText, STRSAFE_IGNORE_NULLS);				}				if (S_OK == hr)				{					if (FVIRTKEY & pszAccel[k].fVirt)					{						szAccelName[0] = L'\0';						UINT vkey = MapVirtualKey(pszAccel[k].key, 0);						/* benski> this removes "NUM" from the descriptions of certain characters */						switch(pszAccel[k].key)						{						case VK_INSERT:						case VK_DELETE:						case VK_HOME:						case VK_END:						case VK_NEXT:  // Page down						case VK_PRIOR: // Page up						case VK_LEFT:						case VK_RIGHT:						case VK_UP:						case VK_DOWN:							vkey |= 0x100; // Add extended bit						}						vkey<<=16;						if (GetKeyNameTextW(vkey, szAccelName, sizeof(szAccelName)/sizeof(szAccelName[0]))) {							hr = StringCchCopyExW(pszItemText, cchText, CapitaliseKeyName(szAccelName), &pszItemText, &cchText, STRSAFE_IGNORE_NULLS);						}					}					else if (cchText > 1) 					{						pszItemText[0] = (wchar_t)pszAccel[k].key;						pszItemText[1] = L'\0';						pszItemText += 2;						cchText -= 2;					}				}				bFirst = FALSE;				bDirty = (S_OK == hr);			}		}	}	return bDirty;}BOOL AppendMenuShortcutsEx(HMENU hMenu, ACCEL *pszAccel, INT cchAccel, UINT uMode){	wchar_t szText[4096] = {0};	if (!hMenu) return FALSE;	MENUITEMINFOW mii = { sizeof(MENUITEMINFOW), };	INT c = GetMenuItemCount(hMenu);	if (0 == c || -1 == c) return TRUE;	for (int i = 0; i < c; i++)	{		mii.fMask = MIIM_ID | MIIM_STRING | MIIM_FTYPE | MIIM_SUBMENU;		mii.cch = sizeof(szText)/sizeof(szText[0]);		mii.dwTypeData = szText;				if (GetMenuItemInfoW(hMenu, i, TRUE, &mii) && 			0 == ((MFT_SEPARATOR | MFT_MENUBREAK |MFT_MENUBARBREAK) & mii.fType))		{			if (AppendShortcutTextEx(mii.dwTypeData, sizeof(szText)/sizeof(szText[0]), (WORD)mii.wID, pszAccel, cchAccel, uMode))			{				mii.fMask = MIIM_STRING;				SetMenuItemInfoW(hMenu, i, TRUE, &mii);			}			if (NULL != mii.hSubMenu && (MSF_WALKSUBMENU & uMode))			{				AppendMenuShortcutsEx(mii.hSubMenu, pszAccel, cchAccel, uMode);				}		}	}	return TRUE;}BOOL AppendMenuShortcuts(HMENU hMenu, HACCEL *phAccel, INT count, UINT uMode){	ACCEL *pszAccel = NULL;	INT c = 0;	if (!hMenu) return FALSE;	if (phAccel)	{		for (int i = 0; i < count; i++)		{			c += CopyAcceleratorTable(phAccel[i], NULL, 0);		}		if (c)		{			pszAccel = (ACCEL*)calloc(c, sizeof(ACCEL));			if (!pszAccel) return FALSE;		}		int k = 0;		for (int i = 0; i < count; i++)		{			k += CopyAcceleratorTable(phAccel[i], &pszAccel[k], c - k);		}	}	BOOL r = AppendMenuShortcutsEx(hMenu, pszAccel, c, uMode);	if (pszAccel) free(pszAccel);	return r;}BOOL AppendShortcutText(LPWSTR pszItemText, INT cchTextMax, WORD wID, HACCEL *phAccel, INT count, UINT uMode){	ACCEL *pszAccel = NULL;	INT c = 0;	if (!pszItemText) return FALSE;	if (phAccel)	{		for (int i = 0; i < count; i++)		{			c += CopyAcceleratorTable(phAccel[i], NULL, 0);		}		if (c)		{			pszAccel = (ACCEL*)calloc(c, sizeof(ACCEL));			if (!pszAccel) return FALSE;		}		int k = 0;		for (int i = 0; i < count; i++)		{			k += CopyAcceleratorTable(phAccel[i], &pszAccel[k], c - k);		}	}	BOOL r = AppendShortcutTextEx(pszItemText, cchTextMax, wID, pszAccel, c, uMode);	if (pszAccel) free(pszAccel);	return r;}
 |