Windows Forms uygulamasında klavye kısayollarını uygulamanın en iyi yolu?


280

C # Windows Forms uygulamamda yaygın Windows klavye kısayollarını (örneğin Ctrl+ F, Ctrl+ N) uygulamak için en iyi yolu arıyorum .

Uygulama, birçok çocuk formuna (birer birer) ev sahipliği yapan bir ana forma sahiptir. Bir kullanıcı Ctrl+ 'ya geldiğinde F, özel bir arama formu göstermek istiyorum. Arama formu, başvurudaki geçerli açık alt forma bağlı olacaktır.

ChildForm_KeyDown olayında böyle bir şey kullanmayı düşünüyordum :

   if (e.KeyCode == Keys.F && Control.ModifierKeys == Keys.Control)
        // Show search form

Ama bu işe yaramıyor. Bir tuşa bastığınızda olay bile başlamaz. Çözüm nedir?


Winforms'un yerel Windows API'sında olduğu gibi bunun için belirli bir işlevselliğe sahip olmadığı gerçekten garip.
Stewart

Yanıtlar:


460

Muhtemelen formun KeyPreview özelliğini True olarak ayarlamayı unuttunuz . ProcessCmdKey () yöntemini geçersiz kılmak genel çözümdür:

protected override bool ProcessCmdKey(ref Message msg, Keys keyData) {
  if (keyData == (Keys.Control | Keys.F)) {
    MessageBox.Show("What the Ctrl+F?");
    return true;
  }
  return base.ProcessCmdKey(ref msg, keyData);
}

Bu iyi çalışıyor, ancak yalnızca form etkin pencere ise benim için algılar. Herkes nasıl bağlamak için herhangi bir pencere görünümünde bilmek mümkün mü?
03:41

Bazı durumlarda KeyPreviewoldukça vazgeçilmezdir. Örneğin, girişi bastırmak için bir kısayola basmak gerekir, ancak yine de ayrı bir MenuStripolayın tetiklenmesine izin vermek için . ProcessCmdKeyyaklaşımı olay ateşleme mantığının kopyalanmasını zorlardı.
Saul

1
Hmm, hayır, Form'un KeyDown olay işleyicisi bir menü öğesinin Click olay işleyicisinden oldukça farklı. Yine de aynı şekilde yapıyorsunuz, doğrudan olay işleyici yöntemini çağırın (yalnızca bir olay tarafından çağrılmasına gerek yoktur) veya ortak mantığı ayrı bir yönteme yeniden aktarabilirsiniz.
Hans Passant

14
"Ctrl + F nedir?" LOL
kchad

73

Ana formunuzda

  1. KeyPreviewDoğru olarak ayarla
  2. Aşağıdaki kodla KeyDown olay işleyicisi ekleyin

    private void MainForm_KeyDown(object sender, KeyEventArgs e)
    {
        if (e.Control && e.KeyCode == Keys.N)
        {
            SearchForm searchForm = new SearchForm();
            searchForm.Show();
        }
    }
    

4
+ için, KeyPreview öğesini True olarak ayarlayın .. eksikti
Usman

20

En iyi yol, menü anımsatıcılarını kullanmaktır, yani ana formunuzda istediğiniz klavye kısayoluna atanan menü girişlerine sahip olmaktır. Sonra diğer her şey dahili olarak ele alınır ve tek yapmanız gereken Clicko menü girişinin olay işleyicisinde yürütülen uygun eylemi uygulamaktır .


1
Sorun, ana formun ortak Windows menüleri kullanmamasıdır. Alt formları göstermek için kullanılan özel gezinme panelini kullanır. Arama formları, alt formdaki ToolStripButton'a tıklanarak çağrılır.
Rockcoder

menu mnemonicsgerçek örnek?
Kiquenet


1
Anımsatıcılar kısayol tuşlarından farklı bir kavramdır ve nasıl çalıştıklarında önemli farklılıklar vardır. Kısacası, anımsatıcılar, klavyeyi kullanarak menülere, menü komutlarına ve iletişim kutusu kontrollerine erişmek için kullanılan altı çizili karakterlerdir. OTOH, kısayol tuşları, menülerden geçmeden komutlara erişmenin bir yoludur ve ayrıca Ctrl + F veya F5 gibi rastgele tuş vuruşları olabilir, karakter tuşlarıyla sınırlı değildir.
Stewart

1
@Stewart Doğru! Cevabım, tüm klavye kısayollarının anımsatıcı olduğunu ima etmeye çalışmıyordu, sadece menü anımsatıcılarının bu işlevselliği almanın en kolay yolu olduğu. Ne yazık ki, Rockcoder'ın açıkladığı gibi, bu çözüm burada uygun görünmüyor. Mümkünse yine de tercih edilen çözüm olarak öneriyorum. Genel bir çözüm için Hans'ın kabul ettiği cevap ileriye giden yoldur.
Konrad Rudolph

11

Bu örneği bile deneyebilirsiniz:

public class MDIParent : System.Windows.Forms.Form
{
    public bool NextTab()
    {
         // some code
    }

    public bool PreviousTab()
    {
         // some code
    }

    protected override bool ProcessCmdKey(ref Message message, Keys keys)
    {
        switch (keys)
        {
            case Keys.Control | Keys.Tab:
              {
                NextTab();
                return true;
              }
            case Keys.Control | Keys.Shift | Keys.Tab:
              {
                PreviousTab();
                return true;
              }
        }
        return base.ProcessCmdKey(ref message, keys);
    }
}

public class mySecondForm : System.Windows.Forms.Form
{
    // some code...
}

8

Sonra değişen bir menü varsa ShortcutKeystesise ToolStripMenuItemhile yapmak gerekir.

Değilse, bir tane oluşturabilir ve visibleözelliğini false olarak ayarlayabilirsiniz .


Hayır menüm yok. Arama için ToolStripButton aslında BindingNavigator denetiminde bulunur, bu nedenle bir menü eklemek muhtemelen bir seçenek değildir.
Rockcoder

6

Ana Formdan şunları yapmanız gerekir:

  • KeyPreview değerini true olarak ayarladığınızdan emin olun (varsayılan olarak TRUE)
  • MainForm_KeyDown (..) ekleyin - burada istediğiniz herhangi bir kısayolu ayarlayabilirsiniz.

Buna ek olarak, bunu Google'da buldum ve bunu hala cevap arayanlarla paylaşmak istedim. (global için)

Bence user32.dll kullanıyor olmalısınız

protected override void WndProc(ref Message m)
{
    base.WndProc(ref m);

    if (m.Msg == 0x0312)
    {
        /* Note that the three lines below are not needed if you only want to register one hotkey.
         * The below lines are useful in case you want to register multiple keys, which you can use a switch with the id as argument, or if you want to know which key/modifier was pressed for some particular reason. */

        Keys key = (Keys)(((int)m.LParam >> 16) & 0xFFFF);                  // The key of the hotkey that was pressed.
        KeyModifier modifier = (KeyModifier)((int)m.LParam & 0xFFFF);       // The modifier of the hotkey that was pressed.
        int id = m.WParam.ToInt32();                                        // The id of the hotkey that was pressed.


        MessageBox.Show("Hotkey has been pressed!");
        // do something
    }
}

Daha fazla bilgiyi http://www.fluxbytes.com/csharp/how-to-register-a-global-hotkey-for-your-application-in-c/


4

Hans'ın cevabı bu konuda yeni biri için biraz daha kolay olabilir, işte benim versiyonum.

Kandırmaya gerek yok KeyPreview, onu açık bırak false. Aşağıdaki kodu kullanmak için kodunuzu altına yapıştırın form1_loadve çalıştığını F5görmek için ile çalıştırın :

protected override void OnKeyPress(KeyPressEventArgs ex)
{
    string xo = ex.KeyChar.ToString();

    if (xo == "q") //You pressed "q" key on the keyboard
    {
        Form2 f2 = new Form2();
        f2.Show();
    }
}

7
İlk olarak, ProcessCmdKey'i geçersiz kılmak, OP'nin sorduğu bazı komut benzeri işlemler yapmak için tasarlanmış bir tuşa basmanın önerilen yoludur. İkincisi, Hans'ın KeyPreview değerini true olarak ayarlama hakkındaki yorumunu yanlış anladınız; OP'ye tekniğinin neden çalışmadığını anlatıyordu. ProcessCmdKey kullanmak için KeyPreview öğesinin true değerine ayarlanması gerekmez.
RenniePet

2

WinForm'da Kontrol Anahtarı durumunu her zaman şu şekilde elde edebiliriz:

bool IsCtrlPressed = (Control.ModifierKeys & Keys.Control) != 0;
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.