C# 检测按下 Shift 键而不使用 Windows 窗体中的事件?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/570577/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 08:40:27  来源:igfitidea点击:

Detect Shift key is pressed without using events in Windows Forms?

c#

提问by

I need to be able to detect that the shift key is being held, but I don't want to use events or global variables to determine that. Is there an API in C# that lets you ask what keys are currently pressed instead of using the event?

我需要能够检测到正在按住 shift 键,但我不想使用事件或全局变量来确定。C# 中是否有 API 可以让您询问当前按下了哪些键而不是使用事件?

回答by JoshBerke

Not sure if this available in C# but you can call GetAsyncKeyState. This method returns the state of a key at the time the method is called.

不确定这在 C# 中是否可用,但您可以调用GetAsyncKeyState。此方法返回调用该方法时键的状态。

To call it from C# you'll need to use interop like any other Win32 API.

要从 C# 调用它,您需要像任何其他 Win32 API 一样使用互操作。

回答by Dan Bystr?m

Form.ModifierKeys(static property)

Form.ModifierKeys(静态属性)

回答by ConsultUtah

You can install a low-level keyboard hook.

您可以安装一个低级键盘钩子

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

class InterceptKeys
{
    private const int WH_KEYBOARD_LL = 13;
    private const int WM_KEYDOWN = 0x0100;
    private static LowLevelKeyboardProc _proc = HookCallback;
    private static IntPtr _hookID = IntPtr.Zero;

    public static void Main()
    {
        _hookID = SetHook(_proc);
        Application.Run();
        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)
    {
        if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN)
        {
            int vkCode = Marshal.ReadInt32(lParam);
            Console.WriteLine((Keys)vkCode);
        }
        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);
}

回答by SLaks

if ((Control.ModifierKeys & Keys.Shift) != 0) 

This will also be trueif another modifier key is also down (eg, Ctrl+Shift). If you want to check whether Shift alone is pressed without any other modifiers, use

true如果另一个修饰键也按下(例如,Ctrl+Shift),也会出现这种情况。如果要检查是否单独按下 Shift 而没有任何其他修饰符,请使用

if (Control.ModifierKeys == Keys.Shift)

Note that even this will be trueif another non-modifier is down (Eg, Shift+A). If you want to check whether Shift and onlyShift is pressed, you'll have to use an API call.

请注意,true如果另一个非修饰符被关闭(例如,Shift+A),即使这样也会如此。如果要检查是否按下了Shift 并且按下了 Shift,则必须使用 API 调用。



If you're in a class that inherits Control(such as a form), you can remove the Controlqualifier. (staticproperties don't need qualifiers in inherited classes)

如果您在继承的类Control(例如表单)中,则可以删除Control限定符。(static属性在继承的类中不需要限定符)