menushortcuts.cpp 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. #include "./menushortcuts.h"
  2. #include <strsafe.h>
  3. // change key string to capitalised only so it's more UI consistant (otherwise messes up the localisation look)
  4. wchar_t* CapitaliseKeyName(wchar_t* szAccelName){
  5. if(szAccelName) {
  6. wchar_t *p = &szAccelName[1];
  7. int space = 0;
  8. while(p && *p){
  9. if(*p == L' ') space = 1;
  10. else {
  11. if(!space) {
  12. *p = tolower(*p);
  13. }
  14. else {
  15. space = 0;
  16. }
  17. }
  18. p = CharNextW(p);
  19. }
  20. }
  21. return szAccelName;
  22. }
  23. BOOL AppendShortcutTextEx(LPWSTR pszItemText, INT cchTextMax, WORD wID, ACCEL *pszAccel, INT cchAccel, UINT uMode)
  24. {
  25. BOOL bDirty = FALSE;
  26. if (!pszItemText) return FALSE;
  27. UINT cchLen = lstrlenW(pszItemText);
  28. if (MSF_REPLACE == (0x0F & uMode))
  29. {
  30. UINT len;
  31. for (len = 0; len < cchLen && L'\t' != pszItemText[len]; len++);
  32. if (cchLen != len)
  33. {
  34. cchLen = len;
  35. pszItemText[len] = L'\0';
  36. bDirty = TRUE;
  37. }
  38. }
  39. if (wID > 0)
  40. {
  41. wchar_t szAccelName[64] = {0};
  42. BOOL bFirst = TRUE;
  43. pszItemText += cchLen;
  44. size_t cchText = cchTextMax - cchLen;
  45. for(int k = 0; k < cchAccel; k++)
  46. {
  47. if (wID == pszAccel[k].cmd)
  48. {
  49. HRESULT hr = StringCchCopyExW(pszItemText, cchText, ((bFirst) ? L"\t" : L", "), &pszItemText, &cchText, STRSAFE_IGNORE_NULLS);
  50. if (S_OK == hr && (FCONTROL & pszAccel[k].fVirt)) {
  51. GetKeyNameTextW(MapVirtualKey(VK_CONTROL, 0)<<16, szAccelName, sizeof(szAccelName)/sizeof(szAccelName[0]));
  52. hr = StringCchCopyExW(pszItemText, cchText, CapitaliseKeyName(szAccelName), &pszItemText, &cchText, STRSAFE_IGNORE_NULLS);
  53. if(S_OK == hr) StringCchCatExW(pszItemText, cchText, L"+", &pszItemText, &cchText, STRSAFE_IGNORE_NULLS);
  54. }
  55. if (S_OK == hr && (FALT & pszAccel[k].fVirt)) {
  56. GetKeyNameTextW(MapVirtualKey(VK_MENU, 0)<<16, szAccelName, sizeof(szAccelName)/sizeof(szAccelName[0]));
  57. hr = StringCchCopyExW(pszItemText, cchText, CapitaliseKeyName(szAccelName), &pszItemText, &cchText, STRSAFE_IGNORE_NULLS);
  58. if(S_OK == hr) hr = StringCchCatExW(pszItemText, cchText, L"+", &pszItemText, &cchText, STRSAFE_IGNORE_NULLS);
  59. }
  60. if (S_OK == hr && (FSHIFT & pszAccel[k].fVirt)) {
  61. GetKeyNameTextW(MapVirtualKey(VK_SHIFT, 0)<<16, szAccelName, sizeof(szAccelName)/sizeof(szAccelName[0]));
  62. hr = StringCchCopyExW(pszItemText, cchText, CapitaliseKeyName(szAccelName), &pszItemText, &cchText, STRSAFE_IGNORE_NULLS);
  63. if(S_OK == hr) hr = StringCchCatExW(pszItemText, cchText, L"+", &pszItemText, &cchText, STRSAFE_IGNORE_NULLS);
  64. }
  65. if (S_OK == hr)
  66. {
  67. if (FVIRTKEY & pszAccel[k].fVirt)
  68. {
  69. szAccelName[0] = L'\0';
  70. UINT vkey = MapVirtualKey(pszAccel[k].key, 0);
  71. /* benski> this removes "NUM" from the descriptions of certain characters */
  72. switch(pszAccel[k].key)
  73. {
  74. case VK_INSERT:
  75. case VK_DELETE:
  76. case VK_HOME:
  77. case VK_END:
  78. case VK_NEXT: // Page down
  79. case VK_PRIOR: // Page up
  80. case VK_LEFT:
  81. case VK_RIGHT:
  82. case VK_UP:
  83. case VK_DOWN:
  84. vkey |= 0x100; // Add extended bit
  85. }
  86. vkey<<=16;
  87. if (GetKeyNameTextW(vkey, szAccelName, sizeof(szAccelName)/sizeof(szAccelName[0]))) {
  88. hr = StringCchCopyExW(pszItemText, cchText, CapitaliseKeyName(szAccelName), &pszItemText, &cchText, STRSAFE_IGNORE_NULLS);
  89. }
  90. }
  91. else if (cchText > 1)
  92. {
  93. pszItemText[0] = (wchar_t)pszAccel[k].key;
  94. pszItemText[1] = L'\0';
  95. pszItemText += 2;
  96. cchText -= 2;
  97. }
  98. }
  99. bFirst = FALSE;
  100. bDirty = (S_OK == hr);
  101. }
  102. }
  103. }
  104. return bDirty;
  105. }
  106. BOOL AppendMenuShortcutsEx(HMENU hMenu, ACCEL *pszAccel, INT cchAccel, UINT uMode)
  107. {
  108. wchar_t szText[4096] = {0};
  109. if (!hMenu) return FALSE;
  110. MENUITEMINFOW mii = { sizeof(MENUITEMINFOW), };
  111. INT c = GetMenuItemCount(hMenu);
  112. if (0 == c || -1 == c) return TRUE;
  113. for (int i = 0; i < c; i++)
  114. {
  115. mii.fMask = MIIM_ID | MIIM_STRING | MIIM_FTYPE | MIIM_SUBMENU;
  116. mii.cch = sizeof(szText)/sizeof(szText[0]);
  117. mii.dwTypeData = szText;
  118. if (GetMenuItemInfoW(hMenu, i, TRUE, &mii) &&
  119. 0 == ((MFT_SEPARATOR | MFT_MENUBREAK |MFT_MENUBARBREAK) & mii.fType))
  120. {
  121. if (AppendShortcutTextEx(mii.dwTypeData, sizeof(szText)/sizeof(szText[0]), (WORD)mii.wID, pszAccel, cchAccel, uMode))
  122. {
  123. mii.fMask = MIIM_STRING;
  124. SetMenuItemInfoW(hMenu, i, TRUE, &mii);
  125. }
  126. if (NULL != mii.hSubMenu && (MSF_WALKSUBMENU & uMode))
  127. {
  128. AppendMenuShortcutsEx(mii.hSubMenu, pszAccel, cchAccel, uMode);
  129. }
  130. }
  131. }
  132. return TRUE;
  133. }
  134. BOOL AppendMenuShortcuts(HMENU hMenu, HACCEL *phAccel, INT count, UINT uMode)
  135. {
  136. ACCEL *pszAccel = NULL;
  137. INT c = 0;
  138. if (!hMenu) return FALSE;
  139. if (phAccel)
  140. {
  141. for (int i = 0; i < count; i++)
  142. {
  143. c += CopyAcceleratorTable(phAccel[i], NULL, 0);
  144. }
  145. if (c)
  146. {
  147. pszAccel = (ACCEL*)calloc(c, sizeof(ACCEL));
  148. if (!pszAccel) return FALSE;
  149. }
  150. int k = 0;
  151. for (int i = 0; i < count; i++)
  152. {
  153. k += CopyAcceleratorTable(phAccel[i], &pszAccel[k], c - k);
  154. }
  155. }
  156. BOOL r = AppendMenuShortcutsEx(hMenu, pszAccel, c, uMode);
  157. if (pszAccel) free(pszAccel);
  158. return r;
  159. }
  160. BOOL AppendShortcutText(LPWSTR pszItemText, INT cchTextMax, WORD wID, HACCEL *phAccel, INT count, UINT uMode)
  161. {
  162. ACCEL *pszAccel = NULL;
  163. INT c = 0;
  164. if (!pszItemText) return FALSE;
  165. if (phAccel)
  166. {
  167. for (int i = 0; i < count; i++)
  168. {
  169. c += CopyAcceleratorTable(phAccel[i], NULL, 0);
  170. }
  171. if (c)
  172. {
  173. pszAccel = (ACCEL*)calloc(c, sizeof(ACCEL));
  174. if (!pszAccel) return FALSE;
  175. }
  176. int k = 0;
  177. for (int i = 0; i < count; i++)
  178. {
  179. k += CopyAcceleratorTable(phAccel[i], &pszAccel[k], c - k);
  180. }
  181. }
  182. BOOL r = AppendShortcutTextEx(pszItemText, cchTextMax, wID, pszAccel, c, uMode);
  183. if (pszAccel) free(pszAccel);
  184. return r;
  185. }