【问题标题】:Wait for user KeyPress WinForms等待用户 KeyPress WinForms
【发布时间】:2018-07-15 01:14:27
【问题描述】:

您好,我的问题似乎很简单,但我无法单独解决。

我有一个 WinForms 应用程序,它有一个按钮。当我按下它时,一些代码会运行,我希望在其中有一个循环,只要按下任何键就会中断。

我当然不能使用 Console.ReadKey(),因为它是一个 winforms,我不想用鼠标点击按钮,也不想使用另一个 EventArg。

有没有什么方法可以通过循环检测 winforms 应用程序中的击键。

这就是想法:

private void btn_Click(object sender, EventArgs e)
    {
        // Do stuff
        while (Key is not pressed)
            { 
                try to detect key pressing
            }
        // Other stuff
    }

提前致谢。

【问题讨论】:

  • 答案将取决于“一些代码运行”的情况。表单是否仍在接收更新且代码异步运行?
  • 最好有单独的按钮和键盘处理程序并引入一个标志
  • 你等不及了,这会让 UI 挂起。只需在 Click 事件处理程序中将 bool 变量设置为 true。然后在 KeyPress 事件处理程序中,您可以检查变量并执行 //otherstuff。请考虑一下如何将其重置为 false

标签: c# winforms


【解决方案1】:

如果您想在表单处于焦点时检测按键按下,您可以使用此问题的答案https://stackoverflow.com/a/18291854/10015658

所以你的代码会这样:

创建新类“KeyHandler”

public class KeyHandler
{
    [DllImport("user32.dll")]
    private static extern bool RegisterHotKey(IntPtr hWnd, int id, int fsModifiers, int vk);

    [DllImport("user32.dll")]
    private static extern bool UnregisterHotKey(IntPtr hWnd, int id);

    private int key;
    private IntPtr hWnd;
    private int id;

    public KeyHandler(Keys key, Form form)
    {
        this.key = (int)key;
        this.hWnd = form.Handle;
        id = this.GetHashCode();
    }

    public override int GetHashCode()
    {
        return key ^ hWnd.ToInt32();
    }

    public bool Register()
    {
        return RegisterHotKey(hWnd, id, 0, key);
    }

    public bool Unregiser()
    {
        return UnregisterHotKey(hWnd, id);
    }
}

你的主From类:(假设你的表单类名是Form1)

private KeyHandler ghk;
bool isButtonClicked = false;

public Form1()
{
    InitializeComponent();

    // Keys.A is the key you want to subscribe
    ghk = new KeyHandler(Keys.A, this);
    ghk.Register();
}

private void HandleHotkey()
{
     // Key 'A' pressed

     if(isButtonClicked)
     {
         // Put the boolean to false to avoid spamming the function with multiple press
         isButtonClicked = false;

         // Other Stuff
     }
}

private void btn_Click(object sender, EventArgs e)
{
    // Do stuff

    isButtonClicked = true;
}

protected override void WndProc(ref Message m)
{
    //0x0312 is the windows message id for hotkey
    if (m.Msg == 0x0312)
        HandleHotkey();
    base.WndProc(ref m);
}

不要忘记使用

using System.Windows.Forms;
using System.Runtime.InteropServices;

【讨论】:

    【解决方案2】:

    有很多方法可以实现你想要的。

    一个简单的方法是设置 Form 的 KeyPreview 为 true 并在表单级别处理 keypress 事件。请注意,您需要允许循环中断(Thread.Sleep() 或 Task.Delay())。

    有关高级连接到 Windows 消息,请查看此question

    【讨论】:

      【解决方案3】:

      解决此问题的一种方法是在单击按钮后为KeyDown 添加事件处理程序,让它等待键输入,然后触发第二个操作并删除事件处理程序。

      看起来像这样:

      private void btn_Click(object sender, EventArgs e)
      {
          // Do stuff
          KeyEventHandler handler = null;
          handler = delegate (object s, KeyEventArgs ev)
          {
              if (ev.KeyCode == Keys.A)
              {
                  btn.KeyDown -= handler;
                  // Do other stuff
              }
          };
          btn.KeyDown += handler;
      }
      

      当然,您需要将 Keys.A 替换为您想要“监听”的实际密钥。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-04-13
        • 2015-05-13
        • 2013-08-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-08-26
        相关资源
        最近更新 更多