HotKeys.cpp 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302
  1. #include "stdafx.h"
  2. #include "HotKeys.h"
  3. #include "Options.h"
  4. #include "Misc.h"
  5. CHotKeys g_HotKeys;
  6. CHotKey::CHotKey( CString name, DWORD defKey, bool bUnregOnShowDitto )
  7. : m_Name(name), m_bIsRegistered(false), m_bUnRegisterOnShowDitto(bUnregOnShowDitto)
  8. {
  9. m_Atom = ::GlobalAddAtom( m_Name );
  10. ASSERT( m_Atom );
  11. m_Key = (DWORD) g_Opt.GetProfileLong( m_Name, (long) defKey );
  12. g_HotKeys.Add( this );
  13. }
  14. CHotKey::~CHotKey()
  15. {
  16. Unregister();
  17. }
  18. void CHotKey::SetKey( DWORD key, bool bSave )
  19. {
  20. if(m_Key == key)
  21. {
  22. return;
  23. }
  24. if( m_bIsRegistered )
  25. Unregister();
  26. m_Key = key;
  27. if( bSave )
  28. SaveKey();
  29. }
  30. void CHotKey::LoadKey()
  31. {
  32. SetKey( (DWORD) g_Opt.GetProfileLong( m_Name, 0 ) );
  33. }
  34. bool CHotKey::SaveKey()
  35. {
  36. return g_Opt.SetProfileLong( m_Name, (long) m_Key ) != FALSE;
  37. }
  38. BOOL CHotKey::ValidateHotKey(DWORD dwHotKey)
  39. {
  40. ATOM id = ::GlobalAddAtom(_T("HK_VALIDATE"));
  41. BOOL bResult = ::RegisterHotKey( g_HotKeys.m_hWnd,
  42. id,
  43. GetModifier(dwHotKey),
  44. LOBYTE(dwHotKey) );
  45. if(bResult)
  46. ::UnregisterHotKey(g_HotKeys.m_hWnd, id);
  47. ::GlobalDeleteAtom(id);
  48. return bResult;
  49. }
  50. void CHotKey::CopyFromCtrl(CHotKeyCtrl& ctrl, HWND hParent, int nWindowsCBID)
  51. {
  52. long lHotKey = ctrl.GetHotKey();
  53. short sKeyKode = LOBYTE(lHotKey);
  54. short sModifers = HIBYTE(lHotKey);
  55. if(lHotKey && ::IsDlgButtonChecked(hParent, nWindowsCBID))
  56. {
  57. sModifers |= HOTKEYF_EXT;
  58. }
  59. SetKey(MAKEWORD(sKeyKode, sModifers));
  60. }
  61. void CHotKey::CopyToCtrl(CHotKeyCtrl& ctrl, HWND hParent, int nWindowsCBID)
  62. {
  63. long lModifiers = HIBYTE(m_Key);
  64. ctrl.SetHotKey(LOBYTE(m_Key), (WORD)lModifiers);
  65. if(lModifiers & HOTKEYF_EXT)
  66. {
  67. ::CheckDlgButton(hParent, nWindowsCBID, BST_CHECKED);
  68. }
  69. }
  70. UINT CHotKey::GetModifier(DWORD dwHotKey)
  71. {
  72. UINT uMod = 0;
  73. if( HIBYTE(dwHotKey) & HOTKEYF_SHIFT ) uMod |= MOD_SHIFT;
  74. if( HIBYTE(dwHotKey) & HOTKEYF_CONTROL ) uMod |= MOD_CONTROL;
  75. if( HIBYTE(dwHotKey) & HOTKEYF_ALT ) uMod |= MOD_ALT;
  76. if( HIBYTE(dwHotKey) & HOTKEYF_EXT ) uMod |= MOD_WIN;
  77. return uMod;
  78. }
  79. bool CHotKey::Register()
  80. {
  81. if(m_Key)
  82. {
  83. if(m_bIsRegistered == false)
  84. {
  85. ASSERT(g_HotKeys.m_hWnd);
  86. m_bIsRegistered = ::RegisterHotKey(g_HotKeys.m_hWnd,
  87. m_Atom,
  88. GetModifier(),
  89. LOBYTE(m_Key) ) == TRUE;
  90. }
  91. }
  92. else
  93. m_bIsRegistered = true;
  94. return m_bIsRegistered;
  95. }
  96. bool CHotKey::Unregister(bool bOnShowingDitto)
  97. {
  98. if(!m_bIsRegistered)
  99. return true;
  100. if(bOnShowingDitto)
  101. {
  102. if(m_bUnRegisterOnShowDitto == false)
  103. return true;
  104. }
  105. if(m_Key)
  106. {
  107. ASSERT(g_HotKeys.m_hWnd);
  108. if(::UnregisterHotKey( g_HotKeys.m_hWnd, m_Atom))
  109. {
  110. m_bIsRegistered = false;
  111. return true;
  112. }
  113. else
  114. {
  115. Log(_T("Unregister FAILED!"));
  116. ASSERT(0);
  117. }
  118. }
  119. else
  120. {
  121. m_bIsRegistered = false;
  122. return true;
  123. }
  124. return false;
  125. }
  126. CHotKeys::CHotKeys() : m_hWnd(NULL)
  127. {
  128. }
  129. CHotKeys::~CHotKeys()
  130. {
  131. CHotKey* pHotKey;
  132. int count = GetSize();
  133. for(int i=0; i < count; i++)
  134. {
  135. pHotKey = ElementAt(i);
  136. if(pHotKey)
  137. delete pHotKey;
  138. }
  139. }
  140. int CHotKeys::Find( CHotKey* pHotKey )
  141. {
  142. int count = GetSize();
  143. for(int i=0; i < count; i++)
  144. {
  145. if( pHotKey == ElementAt(i) )
  146. return i;
  147. }
  148. return -1;
  149. }
  150. bool CHotKeys::Remove( CHotKey* pHotKey )
  151. {
  152. int i = Find(pHotKey);
  153. if(i >= 0)
  154. {
  155. RemoveAt(i);
  156. return true;
  157. }
  158. return false;
  159. }
  160. void CHotKeys::LoadAllKeys()
  161. {
  162. int count = GetSize();
  163. for(int i=0; i < count; i++)
  164. ElementAt(i)->LoadKey();
  165. }
  166. void CHotKeys::SaveAllKeys()
  167. {
  168. int count = GetSize();
  169. for(int i=0; i < count; i++)
  170. ElementAt(i)->SaveKey();
  171. }
  172. void CHotKeys::RegisterAll(bool bMsgOnError)
  173. {
  174. CString str;
  175. CHotKey* pHotKey;
  176. int count = GetSize();
  177. for(int i = 0; i < count; i++)
  178. {
  179. pHotKey = ElementAt(i);
  180. if(!pHotKey->Register())
  181. {
  182. str = "Error Registering ";
  183. str += pHotKey->GetName();
  184. Log(str);
  185. if(bMsgOnError)
  186. AfxMessageBox(str);
  187. }
  188. }
  189. }
  190. void CHotKeys::UnregisterAll(bool bMsgOnError, bool bOnShowDitto)
  191. {
  192. CString str;
  193. CHotKey* pHotKey;
  194. int count = GetSize();
  195. for(int i = 0; i < count; i++)
  196. {
  197. pHotKey = ElementAt(i);
  198. if(!pHotKey->Unregister(bOnShowDitto))
  199. {
  200. str = "Error Unregistering ";
  201. str += pHotKey->GetName();
  202. Log(str);
  203. if(bMsgOnError)
  204. AfxMessageBox(str);
  205. }
  206. }
  207. }
  208. void CHotKeys::GetKeys(ARRAY& keys)
  209. {
  210. int count = GetSize();
  211. keys.SetSize(count);
  212. for(int i=0; i < count; i++)
  213. keys[i] = ElementAt(i)->GetKey();
  214. }
  215. // caution! this alters hotkeys based upon corresponding indexes
  216. void CHotKeys::SetKeys(ARRAY& keys, bool bSave)
  217. {
  218. int count = GetSize();
  219. ASSERT(count == keys.GetSize());
  220. for(int i=0; i < count; i++)
  221. ElementAt(i)->SetKey(keys[i], bSave);
  222. }
  223. bool CHotKeys::FindFirstConflict(ARRAY& keys, int* pX, int* pY)
  224. {
  225. bool bConflict = false;
  226. int i, j;
  227. int count = keys.GetSize();
  228. DWORD key;
  229. for(i = 0; i < count && !bConflict; i++)
  230. {
  231. key = keys.ElementAt(i);
  232. // only check valid keys
  233. if(key == 0)
  234. continue;
  235. // scan the array for a duplicate
  236. for(j = i+1; j < count; j++ )
  237. {
  238. if(keys.ElementAt(j) == key)
  239. {
  240. bConflict = true;
  241. break;
  242. }
  243. }
  244. }
  245. if(bConflict)
  246. {
  247. if(pX)
  248. *pX = i-1;
  249. if(pY)
  250. *pY = j;
  251. }
  252. return bConflict;
  253. }
  254. // if true, pX and pY (if valid) are set to the indexes of the conflicting hotkeys.
  255. bool CHotKeys::FindFirstConflict(int* pX, int* pY)
  256. {
  257. ARRAY keys;
  258. GetKeys(keys);
  259. return FindFirstConflict(keys, pX, pY);
  260. }