在Windows窗体应用程序中实现键盘快捷方式的最佳方法?

时间:2020-12-23 05:55:50

I'm looking for a best way to implement common Windows keyboard shortcuts (for example Ctrl+F, Ctrl+N) in my Windows Forms application in C#.

我正在寻找一种在C#中的Windows窗体应用程序中实现常用Windows键盘快捷键(例如Ctrl + F,Ctrl + N)的最佳方法。

The application has a main form which hosts many child forms (one at a time). When a user hits Ctrl+F, I'd like to show a custom search form. The search form would depend on the current open child form in the application.

该应用程序有一个主窗体,可以容纳许多子窗体(一次一个)。当用户按Ctrl + F时,我想显示自定义搜索表单。搜索表单取决于应用程序中当前打开的子表单。

I was thinking of using something like this in the ChildForm_KeyDown event:

我想在ChildForm_KeyDown事件中使用这样的东西:

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

But this doesn't work. The event doesn't even fire when you press a key. What is the solution?

但这不起作用。按键时,事件甚至不会触发。解决办法是什么?

11 个解决方案

#1


You probably forgot to set the form's KeyPreview property to True. Overriding the ProcessCmdKey() method is the generic solution:

您可能忘记将表单的KeyPreview属性设置为True。覆盖ProcessCmdKey()方法是通用解决方案:

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);
}

#2


On your Main form

在您的主表单上

  1. Set KeyPreview to True
  2. 将KeyPreview设置为True

  3. Add KeyDown event handler with the following code

    使用以下代码添加KeyDown事件处理程序

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

#3


The best way is to use menu mnemonics, i.e. to have menu entries in your main form that get assigned the keyboard shortcut you want. Then everything else is handled internally and all you have to do is to implement the appropriate action that gets executed in the Click event handler of that menu entry.

最好的方法是使用菜单助记符,即在主窗体中为菜单条目分配所需的键盘快捷键。然后其他所有内容都在内部处理,您所要做的就是实现在该菜单项的Click事件处理程序中执行的相应操作。

#4


You can even try this example:

你甚至可以尝试这个例子:

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...
}

#5


If you have a menu then changing ShortcutKeys property of the ToolStripMenuItem should do the trick.

如果您有一个菜单,那么更改ToolStripMenuItem的ShortcutKeys属性应该可以解决问题。

If not, you could create one and set its visible property to false.

如果没有,您可以创建一个并将其visible属性设置为false。

#6


Hans's answer could be made a little easier for someone new to this, so here is my version.

汉斯的答案对于刚接触这个的人来说可以更容易一些,所以这是我的版本。

You do not need to fool with KeyPreview, leave it set to false. To use the code below, just paste it below your form1_load and run with F5 to see it work:

你不需要愚弄KeyPreview,把它设置为false。要使用下面的代码,只需将其粘贴到form1_load下面并使用F5运行即可使用:

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


From the main Form, you have to:

从主表单中,您必须:

  • Be sure you set KeyPreview to true( TRUE by default)
  • 确保将KeyPreview设置为true(默认为TRUE)

  • Add MainForm_KeyDown(..) - by which you can set here any shortcuts you want.
  • 添加MainForm_KeyDown(..) - 您可以在此处设置所需的任何快捷方式。

Additionally,I have found this on google and I wanted to share this to those who are still searching for answers. (for global)

此外,我在谷歌上发现了这一点,我想与那些仍在寻找答案的人分享。 (适用于全球)

I think you have to be using user32.dll

我想你必须使用user32.dll

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
    }
}

Further read this http://www.fluxbytes.com/csharp/how-to-register-a-global-hotkey-for-your-application-in-c/

进一步阅读http://www.fluxbytes.com/csharp/how-to-register-a-global-hotkey-for-your-application-in-c/

#8


In WinForm, we can always get the Control Key status by:

在WinForm中,我们始终可以通过以下方式获取Control Key状态:

bool IsCtrlPressed = (Control.ModifierKeys & Keys.Control) != 0;

#9


private void buttonCheck_Click_1(object sender, EventArgs e)
{
    bool jeElement = false;

    for (int i = 0; i < listBox1.Items.Count; i++)
    {
        if (textBox1.Text == listBox1.Items[i].ToString())
        {
            jeElement = true;
            break;
        }
    }

    if (jeElement)
    {
        label1.Text = "je element";
    }
    else
    {
        label1.Text = "ni element";
    }
    textBox1.ResetText();
    textBox1.Focus();
}

private void Form1_KeyDown(object sender, KeyEventArgs e)
{
    if (e.Alt == true && e.KeyCode == Keys.A)
    {
        buttonCheck.PerformClick();
    }
}

private void timer1_Tick(object sender, EventArgs e)
{
    if (radioButtonF.Checked)
    {
        progressBar1.Value++;
    }
    else
    {
        progressBar1.Value--;
    }

    if (progressBar1.Value == progressBar1.Maximum)
    {
        timer1.Stop();
        label1.Text = "End";
    }

    if (progressBar1.Value == progressBar1.Minimum)
    {
        timer1.Stop();
        label1.Text = "Begining";
    }
}

private void radioButtonF_CheckedChanged(object sender, EventArgs e)
{
    timer1.Start();
    progressBar1.Value = 0;
    progressBar1.Maximum = 100;
}

private void radioButtonB_CheckedChanged(object sender, EventArgs e)
{
    timer1.Start();
    progressBar1.Value = 100;
    progressBar1.Minimum = 0;
}

please don't delete this comment

请不要删除此评论

#10


private void Form1_KeyDown(object sender, KeyEventArgs e)
{
    if(e.Alt == true && e.KeyCode == Keys.A)
    {
        button1ADD.PerformClick();
    }

    if(e.Alt == true && e.KeyCode == Keys.D)
    {
        button2DeleteaaLL.PerformClick();
    }

    if(e.Alt == true && e.KeyCode == Keys.S)
    {
        Deleteselectedbtn.PerformClick();
    }

    if(e.Alt == true && e.KeyCode == Keys.C)
    {
        button4Close.PerformClick();
    }
}

private void Form1_Shown(object sender, EventArgs e)
{
    txtInput.Focus();
}

private void button1ADD_Click(object sender, EventArgs e)
{
    if(!string.IsNullOrEmpty(txtInput.Text))
    {
        Listmylist.Items.Add(txtInput.Text);
        txtInput.Clear();
        txtInput.Focus();
    }
}

private void button2DeleteaaLL_Click(object sender, EventArgs e)
{
    Listmylist.Items.Clear();
    txtInput.Focus();
}

private void Deleteselectedbtn_Click(object sender, EventArgs e)
{
    Listmylist.Items.RemoveAt(Listmylist.SelectedIndex);
    txtInput.Focus();
}

private void button4Close_Click(object sender, EventArgs e)
{
    Application.Exit();
}

private void txtInput_TextChanged(object sender, EventArgs e)
{
    button1ADD.Enabled = true;
}

#11


private void button1_Click(object sender, EventArgs e)
{
    if (button2.Enabled == false)
    {
        timer1.Stop();
        button2.Enabled = true;
        label1.Text = "Preteklo je " + progressBar1.Value + " desetink";

    }
    else
    {
        timer1.Start();
        button1.Enabled = false;
        progressBar1.Value = 0;
        label1.Text = "";
    }
}

private void button2_Click(object sender, EventArgs e)
{
    if (button1.Enabled == false)
    {
        timer1.Stop();
        button1.Enabled = true;
        label1.Text = "Preteklo je " + progressBar1.Value + " desetink";
    }
    else
    {
        timer1.Start();
        button2.Enabled = false;
        progressBar1.Value = 0;
        label1.Text = "";
    }
}

private void timer1_Tick(object sender, EventArgs e)
{
    if (progressBar1.Value < progressBar1.Maximum)
    {
        progressBar1.Value++;
        if (progressBar1.Value == progressBar1.Maximum)
        {
            timer1.Stop();
            button2.Enabled = true;
            button1.Enabled = true;
        }
    }
}

#1


You probably forgot to set the form's KeyPreview property to True. Overriding the ProcessCmdKey() method is the generic solution:

您可能忘记将表单的KeyPreview属性设置为True。覆盖ProcessCmdKey()方法是通用解决方案:

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);
}

#2


On your Main form

在您的主表单上

  1. Set KeyPreview to True
  2. 将KeyPreview设置为True

  3. Add KeyDown event handler with the following code

    使用以下代码添加KeyDown事件处理程序

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

#3


The best way is to use menu mnemonics, i.e. to have menu entries in your main form that get assigned the keyboard shortcut you want. Then everything else is handled internally and all you have to do is to implement the appropriate action that gets executed in the Click event handler of that menu entry.

最好的方法是使用菜单助记符,即在主窗体中为菜单条目分配所需的键盘快捷键。然后其他所有内容都在内部处理,您所要做的就是实现在该菜单项的Click事件处理程序中执行的相应操作。

#4


You can even try this example:

你甚至可以尝试这个例子:

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...
}

#5


If you have a menu then changing ShortcutKeys property of the ToolStripMenuItem should do the trick.

如果您有一个菜单,那么更改ToolStripMenuItem的ShortcutKeys属性应该可以解决问题。

If not, you could create one and set its visible property to false.

如果没有,您可以创建一个并将其visible属性设置为false。

#6


Hans's answer could be made a little easier for someone new to this, so here is my version.

汉斯的答案对于刚接触这个的人来说可以更容易一些,所以这是我的版本。

You do not need to fool with KeyPreview, leave it set to false. To use the code below, just paste it below your form1_load and run with F5 to see it work:

你不需要愚弄KeyPreview,把它设置为false。要使用下面的代码,只需将其粘贴到form1_load下面并使用F5运行即可使用:

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


From the main Form, you have to:

从主表单中,您必须:

  • Be sure you set KeyPreview to true( TRUE by default)
  • 确保将KeyPreview设置为true(默认为TRUE)

  • Add MainForm_KeyDown(..) - by which you can set here any shortcuts you want.
  • 添加MainForm_KeyDown(..) - 您可以在此处设置所需的任何快捷方式。

Additionally,I have found this on google and I wanted to share this to those who are still searching for answers. (for global)

此外,我在谷歌上发现了这一点,我想与那些仍在寻找答案的人分享。 (适用于全球)

I think you have to be using user32.dll

我想你必须使用user32.dll

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
    }
}

Further read this http://www.fluxbytes.com/csharp/how-to-register-a-global-hotkey-for-your-application-in-c/

进一步阅读http://www.fluxbytes.com/csharp/how-to-register-a-global-hotkey-for-your-application-in-c/

#8


In WinForm, we can always get the Control Key status by:

在WinForm中,我们始终可以通过以下方式获取Control Key状态:

bool IsCtrlPressed = (Control.ModifierKeys & Keys.Control) != 0;

#9


private void buttonCheck_Click_1(object sender, EventArgs e)
{
    bool jeElement = false;

    for (int i = 0; i < listBox1.Items.Count; i++)
    {
        if (textBox1.Text == listBox1.Items[i].ToString())
        {
            jeElement = true;
            break;
        }
    }

    if (jeElement)
    {
        label1.Text = "je element";
    }
    else
    {
        label1.Text = "ni element";
    }
    textBox1.ResetText();
    textBox1.Focus();
}

private void Form1_KeyDown(object sender, KeyEventArgs e)
{
    if (e.Alt == true && e.KeyCode == Keys.A)
    {
        buttonCheck.PerformClick();
    }
}

private void timer1_Tick(object sender, EventArgs e)
{
    if (radioButtonF.Checked)
    {
        progressBar1.Value++;
    }
    else
    {
        progressBar1.Value--;
    }

    if (progressBar1.Value == progressBar1.Maximum)
    {
        timer1.Stop();
        label1.Text = "End";
    }

    if (progressBar1.Value == progressBar1.Minimum)
    {
        timer1.Stop();
        label1.Text = "Begining";
    }
}

private void radioButtonF_CheckedChanged(object sender, EventArgs e)
{
    timer1.Start();
    progressBar1.Value = 0;
    progressBar1.Maximum = 100;
}

private void radioButtonB_CheckedChanged(object sender, EventArgs e)
{
    timer1.Start();
    progressBar1.Value = 100;
    progressBar1.Minimum = 0;
}

please don't delete this comment

请不要删除此评论

#10


private void Form1_KeyDown(object sender, KeyEventArgs e)
{
    if(e.Alt == true && e.KeyCode == Keys.A)
    {
        button1ADD.PerformClick();
    }

    if(e.Alt == true && e.KeyCode == Keys.D)
    {
        button2DeleteaaLL.PerformClick();
    }

    if(e.Alt == true && e.KeyCode == Keys.S)
    {
        Deleteselectedbtn.PerformClick();
    }

    if(e.Alt == true && e.KeyCode == Keys.C)
    {
        button4Close.PerformClick();
    }
}

private void Form1_Shown(object sender, EventArgs e)
{
    txtInput.Focus();
}

private void button1ADD_Click(object sender, EventArgs e)
{
    if(!string.IsNullOrEmpty(txtInput.Text))
    {
        Listmylist.Items.Add(txtInput.Text);
        txtInput.Clear();
        txtInput.Focus();
    }
}

private void button2DeleteaaLL_Click(object sender, EventArgs e)
{
    Listmylist.Items.Clear();
    txtInput.Focus();
}

private void Deleteselectedbtn_Click(object sender, EventArgs e)
{
    Listmylist.Items.RemoveAt(Listmylist.SelectedIndex);
    txtInput.Focus();
}

private void button4Close_Click(object sender, EventArgs e)
{
    Application.Exit();
}

private void txtInput_TextChanged(object sender, EventArgs e)
{
    button1ADD.Enabled = true;
}

#11


private void button1_Click(object sender, EventArgs e)
{
    if (button2.Enabled == false)
    {
        timer1.Stop();
        button2.Enabled = true;
        label1.Text = "Preteklo je " + progressBar1.Value + " desetink";

    }
    else
    {
        timer1.Start();
        button1.Enabled = false;
        progressBar1.Value = 0;
        label1.Text = "";
    }
}

private void button2_Click(object sender, EventArgs e)
{
    if (button1.Enabled == false)
    {
        timer1.Stop();
        button1.Enabled = true;
        label1.Text = "Preteklo je " + progressBar1.Value + " desetink";
    }
    else
    {
        timer1.Start();
        button2.Enabled = false;
        progressBar1.Value = 0;
        label1.Text = "";
    }
}

private void timer1_Tick(object sender, EventArgs e)
{
    if (progressBar1.Value < progressBar1.Maximum)
    {
        progressBar1.Value++;
        if (progressBar1.Value == progressBar1.Maximum)
        {
            timer1.Stop();
            button2.Enabled = true;
            button1.Enabled = true;
        }
    }
}