Как да уловя Keys.F1 независимо от фокусираната контрола във формуляр?

Използвах събитие KeyDown и някакъв прост код като if (e.KeyCode == Keys.F1) за улавяне на F1 е натиснат във формуляр, НО ако има някои текстови полета във формуляра или ако има някои електронни таблици с Dock Fill във формуляра, тогава кодът по-горе става безполезен и не прави нищо. Но искам да направя нещо, когато потребителят натисне F1 на този формуляр. така че как да заснемем конкретно събитие на натискане на клавиш като F1 в целия формуляр...и аз не искам да отида до маршрута, който улавя KeyDown на всички други контроли във формуляра и ги предава на формуляра за обработка. има ли някакъв по-чист начин да направите това?


person Bohn    schedule 10.05.2011    source източник


Отговори (4)


Да, наистина има. Правилният начин формулярът да обработва ключови събития, независимо от контролата, която в момента има входен фокус, е да замени ProcessCmdKey метод на вашия клас формуляр:

protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
    if (keyData == Keys.F1)
    {
        MessageBox.Show("You pressed the F1 key");
        return true;    // indicate that you handled this keystroke
    }

    // Call the base class
    return base.ProcessCmdKey(ref msg, keyData);
}

Връщате true, за да посочите, че сте обработили натискането на клавиша и не искате то да бъде предадено на други контроли. Ако наистина искате то да бъде предадено на манипулаторите на събития за други контроли, просто върнете false.

И най-добре е да игнорирате свойството KeyPreview . Това е анахронизъм от 6-те дни на VB и всъщност не е предпочитаният начин да се направи това в света на .NET. Допълнителна информация: Недостатък на настройката на Form.KeyPreview = true?

person Cody Gray    schedule 10.05.2011
comment
Как не е предпочитаният начин? KeyPreview използва ориентираната към събитията архитектура на .NET, докато вие просто отменяте WndProc, предпочитания Win3.1 (да, точно така, технология от 1992 г.) начин за това. - person Blindy; 10.05.2011
comment
@Blindy: Идиоматичният начин за правене на нещата в света на Windows API не се е променил много от първите дни на Windows. И това не е точно същото като замяна на WndProc (въпреки че и това работи). Рамката извиква този метод в подходящия момент специално за обработка на тези събития. Освен това правенето на нещата по този начин ви позволява да решите дали искате събитието да бъде предадено на други контроли или не. - person Cody Gray; 10.05.2011
comment
Всъщност е точно същото като замяна на WndProc, когато uMsg=WM_KEYDOWN. И точно както при проверката на кодовете на виртуалните ключове в API на Win32, вие не знаете дали потребителят е въвел действителния ключ или неговата изместена версия (наред с други неща). Всеки сам, но бих бил по-внимателен кой API наричам по-лош. - person Blindy; 10.05.2011
comment
@Blindy: Функционално? Или идиоматично? Не се карам за функцията - вече казах, че и такава работи. Но категорично не съм съгласен, че KeyPreview е по-добра алтернатива. - person Cody Gray; 10.05.2011

Задайте KeyPreview на формуляра на true. Това ще гарантира, че формулярът първо получава съобщенията за натискане на клавиши и ако се справите с него, можете да зададете e.Handled = true, така че да не се предава надолу към контролите.

person Bala R    schedule 10.05.2011

Включете KeyPreview и всяко натискане на клавиш във формуляра първо ще бъде пренасочено през неговите манипулатори на ключови събития.

person Blindy    schedule 10.05.2011

Друг начин е да замените функцията ProcessCmdKey http://msdn.microsoft.com/en-us/library/system.windows.forms.control.processcmdkey(v=VS.100).aspx

person JTorrecilla    schedule 10.05.2011