Я делаю программу, чтобы иметь настраиваемые пользователем горячие клавиши, и у меня почти все работает, за исключением 1 заминки, преобразующей ключи-модификаторы в int32 с помощью gethashcode()
private void hotBox1_KeyDown(object sender, KeyEventArgs e)
{
string _senderName = ((TextBox)sender).Name;
int _sender_id = Convert.ToInt32(_senderName.Split(new[] { "hotBox" },
StringSplitOptions.None)[1]) - 1;
Keys modifierKeys = e.Modifiers;
Keys pressedKey = e.KeyData ^ modifierKeys;
/*
* have to convert e.modifiers to 1/2/4/etc it's throwing errors when
* trying to register a new hotkey because it doesn't know what 131072 is
*/
/*
* OKAY so I rigged a bunch of stuff here I don't know why GetHashCode returns
* 131072 (20000 hex) for shift instead of 0x2 (2 dec) which is the hex code for
* shift modifier ???
* Anyway I'm using the fixed values for detecting if shift/ctrl/alt or any
* combination is pressed to not block hotkey from blacklist with use of modifier
* I'm not very knowledgeable with that sort of stuff so feel free to edit to
* make more efficient
*/
Int32[] Modifiers = { 131072, 65536, 262144 }; //Control, Alt, Shift
/*
* BLACKLIST: ctrl+pgdn, ctrl+pgup, caps lock, tab, shift+all numpad (and all
* combinations of shift+{X}+num pad), F12, ctrl+shift{e,r,a,j}
* Q W E R T X D Z A ENT O C S L I H Y K N B U P G M space F8 F1 F 1 2 3 4 5
*/
Keys[] Blacklist = { Keys.Capital, Keys.CapsLock, Keys.F12, Keys.Tab, Keys.Q,
Keys.W, Keys.E, Keys.R, Keys.T, Keys.X, Keys.D, Keys.Z,
Keys.A, Keys.Enter, Keys.O, Keys.C, Keys.S, Keys.L, Keys.I,
Keys.H, Keys.Y, Keys.K, Keys.N, Keys.B, Keys.U, Keys.P,
Keys.G, Keys.M, Keys.Space, Keys.F8, Keys.F1, Keys.F,
Keys.D1, Keys.D2, Keys.D3, Keys.D4, Keys.D5 };
foreach (Keys k in Blacklist)
if (k == pressedKey)
if (modifierKeys.GetHashCode() == Modifiers[0] ||
modifierKeys.GetHashCode() == Modifiers[1] ||
modifierKeys.GetHashCode() == Modifiers[2] ||
modifierKeys.GetHashCode() == Modifiers[0] + Modifiers[1] ||
modifierKeys.GetHashCode() == Modifiers[0] + Modifiers[2] ||
modifierKeys.GetHashCode() == Modifiers[2] + Modifiers[1])
{
//Console.WriteLine("No block"); //yes it finally works!
}
else
{
e.Handled = true;
e.SuppressKeyPress = true;
return;
}
if (e.KeyCode == Keys.Escape)
((TextBox)sender).Parent.Focus();
else if (pressedKey != Keys.ShiftKey &&
pressedKey != Keys.Menu &&
pressedKey != Keys.ControlKey &&
pressedKey != Keys.None)
//pressedKey != Keys.None modifierKeys != Keys.None
{
Set_Hotkey(_sender_id, e.Modifiers.GetHashCode(), e.KeyCode.GetHashCode());
((TextBox)sender).Parent.Focus();
}
else
((TextBox)sender).Text = new KeysConverter().ConvertToString(e.Modifiers);
e.Handled = true;
e.SuppressKeyPress = true;
}
У меня проблема в том, что e.Modifiers.GetHashCode() возвращает 131072 (ctrl), 65536 (alt), 262144 (shift) или любую сумму этих комбинаций для мультимодификаторов. Любой другой ключ, для которого я использую GetHashCode() (кроме модификаторов), возвращает правильные значения, и проблем не возникает.
Когда код доберется до
private static extern bool RegisterHotKey(IntPtr hWnd, int id, int fsModifiers, int vk);
он всегда не сможет зарегистрировать горячую клавишу с модификатором, потому что он не знает, что такое 131072, он ожидает 2, вся остальная логика в коде верна и будет работать правильно, если я попытаюсь зарегистрировать, например, только (клавишу J)
Я не понимаю, почему это происходит, есть ли способ исправить это просто? например, получение 1,2,4,5,6,7 (правильные модификаторы, которые ожидает RegisterHotKey). Я имею в виду что-то немного уродливое/громоздкое, как
int32 _mod;
if (e.modifier.gethashcode() == 131072)
_mod = 2;
и т.д. и т.п. со всеми суммами комбинаций, что аналогично тому, что я делал для проверки черного списка с модификаторами
Кроме того, я прошу прощения за действительно странные комментарии. Я обычно не комментирую код, но я отправляю всю эту программу на github, поэтому я пытаюсь больше комментировать то, что я делаю, и это мой наименее комментируемый пустота, потому что я продолжаю пересматривать это так много пытается исправить это.
foreach
,if
иelse
является плохой практикой и может затруднить чтение и отладку кода. 2) Почему вы используетеGetHashCode()
на предметах для определения модификаторов? СвойствоModifiers
также возвращает перечислениеKeys
. - person krillgar   schedule 07.10.2017GetHashCode()
, где больше комбинаций для хеш-кода, чем возможностей для хэшей. Например, можно предположить, что каждое целое число имеет собственный хеш-код. Что тогда это означает, если вы получаете хеш-код дляDateTime
илиstring
? У вас будет некоторое совпадение. Когда вы пытаетесь выяснить, что это за ключ, идите по тому ключу, который вам сказали. - person krillgar   schedule 08.10.2017