Formlar KeyDown olaylarına yanıt vermiyor


82

Bir süredir Windows Forms projem üzerinde çalışıyorum ve klavye kısayollarını denemeye karar verdim. Biraz okuduktan sonra, sadece bir olay işleyicisi yazmam ve onu formun KeyDown olayına bağlamam gerektiğini düşündüm:

private void Form1_KeyDown(object sender, KeyEventArgs e)
{
    if (e.Control && e.Alt && e.KeyCode == Keys.O)
    {
        MessageBox.Show("Ctrl+Alt+O: magic!");
    }
}

Bunu, Visual Studio tasarımcısının Özellikler panelini açmanın ve ardından Form1_KeyDownolay işleyicisini oluşturmak için formumun KeyDown olayını çift tıklatmanın iyi bir yolunu yaptım . Ancak başvurumu test ederken, form Ctrl+ Alt+ Oklavye kısayoluna hiç yanıt vermiyor . Visual Studio tasarımcısı, olay işleyicisini forma bağlamak için kod oluşturdu:

private void InitializeComponent()
{
    // ...

    this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.Form1_KeyDown);

    // ...
}

Bu yüzden Console.WriteLine(), işleyiciye çağrıldığını kontrol etmek için bir çağrı eklemeyi denedim , ama bunda da şans yok.

Ayrıca, olay bağlama çağrısında (hemen yukarıda gösterilen) bir kesme noktası ayarlamaya çalıştım ve programın bu kesme noktasına gayet iyi ulaştığını gördüm. Ancak yöntem tanımının kendisinde belirlediğim herhangi bir kesme noktasına asla ulaşılmaz.

İlk birkaç adımı doğru yaptığımdan emin olmak için bunları şu şekilde tekrarlamayı denedim:

  • Aynı çözümde yeni bir form.
    Aynı sorun: Ctrl+ 'a bastığımda form yanıt vermiyorAlt + Oklavye kısayoluma bastığımda ve hata ayıklayıcı olay işleyicisine bile girmiyor. Bunu tekrar denedim ve işe yarıyor.

  • Yepyeni bir WinForms çözümü.
    Mükemmel çalışıyor: mesaj diyaloğu belirir ( Console.WriteLine()çağrı da çalışır).

Yani burada oldukça kayboldum. Bu tek projedeki tüm formların KeyDown olaylarını almasını engelleyen nedir?

Yanıtlar:


174

Formunuzun KeyPreview özelliği true olarak ayarlanmış mı?

Form.KeyPreview Özellik

Olay odağı olan denetime geçirilmeden önce formun anahtar olayları alıp almayacağını gösteren bir değer alır veya ayarlar.

http://msdn.microsoft.com/en-us/library/system.windows.forms.form.keypreview.aspx


19
Bu, VB6 programcılarını mutlu etmek için kullanıma sunulan bir hack. Yürütme sırası sorunları var, bunun yerine ProcessCmdKey () 'i geçersiz kılın.
Hans Passant

@HansPassant, yürütme sırası sorunlarını açıklayan hiçbir şey bulamıyorum. KeyDown + KeyPreview tüm anahtarları görmez, ki bu yeterli bir sorundur, ancak yürütme sırası sorunları nelerdir?
kdbanman

1
Kısayol tuş vuruşlarını algılamak için birçok geçersiz kılma vardır. Sırayla yürütülen KeyPreview + KeyDown son durumda.
Hans Passant

54

StackOverflow'da ve MSDN 1 , 2'de bu sorun için en yaygın tavsiye parçası ( burada kabul edilen yanıt dahil) hızlı ve kolaydır:

KeyDownolaylar Form, KeyPreviewözelliği ayarlandığı sürece tetiklenirtrue

Çoğu amaç için bu yeterlidir, ancak iki nedenden dolayı risklidir:

  1. KeyDownişleyiciler tüm anahtarları görmez . Özellikle, "gezinme için kullanılan tuş vuruşlarını göremezsiniz. İmleç tuşları ve bir iletişim kutusu için Sekme, Escape ve Enter gibi."

  2. Önemli olayları engellemenin birkaç farklı yolu vardır ve hepsi sırayla gerçekleşir. KeyDownele alındı son . Bu nedenle, KeyPreviewpek bir ön izleme değildir ve olay yolda birkaç durakta susturulabilir.

(Bu puanlar için @HansPassant'a kredi verin.)

Bunun yerine, geçersiz ProcessCmdKeyGözlerinde farklı Form:

protected override bool ProcessCmdKey(ref Message msg, Keys keyData) {
    if (keyData == Keys.Up)
    {
        // Handle key at form level.
        // Do not send event to focused control by returning true.
        return true;
    }
  return base.ProcessCmdKey(ref msg, keyData);
}

Bu şekilde, tüm anahtarlar yöntem tarafından görülebilir ve yöntem, olayı görmek için ilk sırada yer alır.

Odaklanmış kontrollerin KeyDownolayı görüp görmemesi üzerinde hala kontrole sahip olduğunuzu unutmayın . Sadece dönmek truesonraki engellemek için KeyDownoldukça ayarlamak yerine, olayı KeyPressEventArgs.Handlediçin truebir de olduğu gibi KeyDownolay işleyicisi. İşte daha fazla ayrıntı içeren bir makale.


1
Bu doğru yanıttır, özellikle de KeyPreview true olarak ayarlandığında PreviewKeyDown'ın hiç çalışmayacağını görürseniz.
Tim

23

KeyPreviewFormunuzdaki özelliği true olarak ayarlamayı deneyin . Bu, tuşlara basmak için benim için çalıştı.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.