c# specific sequence keypress event any where in form 形式

c# specific sequence keypress event any where in form

我是 C# 初学者,想就如何解决以下问题寻求一些建议:

随机按下下面的键“ctrl + v + a”在表单的任意位置[=19]时,我想创建一个事件来启用一些文本框=].

  private void test_KeyDown(object sender, KeyEventArgs e)
    {
        if ((int)e.KeyData == (int)Keys.Control + (int)Keys.V + (int)Keys.A)
        {
            textbox1.Enabled = true;
            textbox2.Enabled = true;

        }
    }

以下代码无效。

您可能会错过“&&” if ((int)e.KeyData == (int)Keys.Control && (int)e.KeyData == (int)Keys.V && (int)e.KeyData == (int)Keys.A))

你可以试试这个Javascript代码也:

document.addEventListener('keydown', logKey);

function logKey(e) {
  log.textContent += ` ${e.code}`;
}

你可以在if条件

中给出e.Control==true && e.KeyCode==Keys.V && e.Keycode==Keys.A

因为 KeyEventArgs e 仅存储一个密钥,我假设您必须存储密钥 V 状态。

private bool _keyVPressed;

private void Form1_KeyDown(object sender, KeyEventArgs e)
{
    _keyVPressed = _keyVPressed || KeyVPressed(e.KeyCode);
    if (e.Control && _keyVPressed && e.KeyCode == Keys.A)
    {
        textBox1.Enabled = true;
    }
}

private void Form1_KeyUp(object sender, KeyEventArgs e) => _keyVPressed = !KeyVPressed(e.KeyCode);

private bool KeyVPressed(Keys k) => k is Keys.V;

要在表单中的任何地方应用此行为,您需要将事件附加到表单中的每个控件

this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.Form1_KeyDown);
this.KeyUp += new System.Windows.Forms.KeyEventHandler(this.Form1_KeyUp);
//...
//some designer code
//...
this.textBox1.KeyDown += new System.Windows.Forms.KeyEventHandler(this.Form1_KeyDown);
this.textBox1.KeyUp += new System.Windows.Forms.KeyEventHandler(this.Form1_KeyUp);

一种方法是处理 KeyDown 事件,如果第一个键,比如 A 按下,而 Ctrl 键,设置一个 boolForm 级别的 true 以指示序列正在开始。下一个 KeyDown 事件应该是序列中的第二个键,比如 VCtrl 键按下(仍然)。如果你一开始设置的bool仍然为真,也就是说Ctrl键还没有松开,那就执行你想做的。使用KeyUp事件检测Ctrl键是否松开,如果松开,将bool值设置为false,因为不按顺序

伪代码如下所示:

  • private bool isSequence;
  • KeyDown 事件处理器
    • if (Ctrl && e.KeyData == Keys.A) { isSequence = true; }
    • if (Ctrl && e.KeyData == Keys.V && isSequence) { DoWhateverThing(); }
  • KeyUp 事件处理器
    • if (e.KeyData == Ctrl) { isSequence = false; }

基本上您想要跟踪 key events 个表单。

首先,你可以inherit你所有来自基本表单的表单(表单的KeyPreview 属性应该是True) , 喜欢;

public class BaseForm : Form
{
    private static List<Keys> keyPress = new List<Keys>(); // to store the key values
    public BaseForm()
    {
        this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.BaseForm_KeyDown); // register event for all forms which inherits from BaseForm
    }

    private void BaseForm_KeyDown(object sender, KeyEventArgs e)
    {
        if (e.KeyCode == Keys.ControlKey || e.KeyCode == Keys.C || e.KeyCode == Keys.V) // right now Control, C, V keys are included
        {

            if (keyPress.Any(x => x == e.KeyCode)) // If keypress list has the current key press so pattern is broken
            {
                keyPress.Clear(); //clear the list user should start again
            }
            else
            {
                keyPress.Add(e.KeyCode);
            }

            if (keyPress.Count > 2) 
            {
                this.Controls["textBox1"].Enabled = true; 
                keyPress.Clear(); // clear the keyPress list
            }
        }
    }
}

因此,通过这样做,您无需为所有表单注册按键事件。

其次,可以使用全局键hook。 (更多信息请点击this)在主线程入口处Low-LevelKeyboardHook会附加到进程中,每个按键事件都会在HookCallback.

处被捕获
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using System.Linq;

namespace KeyHookTryApp
{
   static class Program
   {
       private const int WH_KEYBOARD_LL = 13;
       private const int WM_KEYDOWN = 0x0100;
       private static LowLevelKeyboardProc _proc = HookCallback;
       private static IntPtr _hookID = IntPtr.Zero;
       private static Form1 f;
       private static List<Keys> keyPress = new List<Keys>();
       /// <summary>
       /// The main entry point for the application.
       /// </summary>
       [STAThread]
       static void Main()
       {
           _hookID = SetHook(_proc);
           Application.EnableVisualStyles();
           Application.SetCompatibleTextRenderingDefault(false);
           f = new Form1();
           Application.Run(f);
           UnhookWindowsHookEx(_hookID);
       }
       private static IntPtr SetHook(LowLevelKeyboardProc proc)
       {
           using (Process curProcess = Process.GetCurrentProcess())
           using (ProcessModule curModule = curProcess.MainModule)
           {
               return SetWindowsHookEx(WH_KEYBOARD_LL, proc,
                   GetModuleHandle(curModule.ModuleName), 0);
           }
       }

       private delegate IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam);

       private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
       {
           int vkCode = Marshal.ReadInt32(lParam);
           Keys key = (Keys)vkCode;

           if (nCode >= 0 && ((key == Keys.LControlKey || key == Keys.RControlKey) || key == Keys.C || key == Keys.V))
           {
               if (keyPress.Any(x => x == key))
               {
                   keyPress.Clear();
               }
               else
               {
                   keyPress.Add(key);
               } 

               if (keyPress.Count > 2)
               {
                   f.Controls["textBox1"].Enabled = true;
                   keyPress.Clear();
               }
           }
           else if(keyPress.Count > 0)
           {
               keyPress.Clear();
           }

           return CallNextHookEx(_hookID, nCode, wParam, lParam);
       }

       [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
       private static extern IntPtr SetWindowsHookEx(int idHook,LowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId);

       [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
       [return: MarshalAs(UnmanagedType.Bool)]
       private static extern bool UnhookWindowsHookEx(IntPtr hhk);

       [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
       private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode,IntPtr wParam, IntPtr lParam);

       [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
       private static extern IntPtr GetModuleHandle(string lpModuleName);
   }
}

如果有多个表格。表单控件应该可以从全局访问,或者表单应该有自定义方法,如 EnableTextBoxes().

所以你想这样做形式上的任何地方。
执行此操作的最佳方法是覆盖表单的 ProcessCmdKey 方法。
但它有一些局限性。您只能使用 Control | Alt | Shift 个密钥和一个以上的密钥。

喜欢:
ctrl + V 有效
ctrl + A 有效
ctrl + alt + V 有效
ctrl + alt + shift + V 作品

ctrl + V + A 无效
ctrl + alt + V + A 无效

所以你必须使用另一个键,例如使用 ctrl + shift + V

    protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
    {
        switch (keyData)
        {
            case (Keys.Control | Keys.Shift | Keys.V):
                textbox1.Enabled = true;
                textbox2.Enabled = true;
                return true;

      // more keys if you want

            case (Keys.Control | Keys.H):
                MessageBox.Show("Hello World!");
                return true;
        }

        return base.ProcessCmdKey(ref msg, keyData);
    }