检测是否在 C# 中按下了任何键(不是 A、B,而是任何)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1752494/
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
Detect if any key is pressed in C# (not A, B, but any)
提问by Christian Ruppert
[EDIT 3] I kind of "solved it" by at using the "strange" version. At least for the most important keys. It is suffient for my case, where I want to check that ALT and ALT+A are not the same (thereby making sure A is not pressed). Not perfect, but already to much time for such a tiny problem. Thanks for all the answers anyway... [EDIT 3]
[编辑 3] 我通过使用“奇怪”版本来“解决它”。至少对于最重要的键。这对于我的情况就足够了,我想检查 ALT 和 ALT+A 是否不同(从而确保 A 没有被按下)。不完美,但对于这么小的问题已经有太多时间了。无论如何,感谢所有的答案...... [编辑 3]
[EDIT 4] Solved it much cleaner thanks to 280Z28 [/EDIT 4]
[编辑 4] 由于 280Z28 [/编辑 4]
I know how to check for modifier keys and how to test for a single key. The problem is, I want to check if any key is pressed. The following approach seems "strange" :-)
我知道如何检查修饰键以及如何测试单个键。问题是,我想检查是否按下了任何键。以下方法似乎“奇怪”:-)
WPF Application written in C#
用 C# 编写的 WPF 应用程序
if (Keyboard.IsKeyDown(Key.A)) return true;
if (Keyboard.IsKeyDown(Key.B)) return true;
if (Keyboard.IsKeyDown(Key.C)) return true;
I know it is an enum, so I thought about a loop, but what is the "biggest number" to use. And is this possible? btw, its a very special case, normally I would use an event, but in this case I have to do it this way. Unfortunatily, the there is no "list" Keyboard.CurrentlyDownKeys. At least I didnt see it.
我知道它是一个枚举,所以我想到了一个循环,但要使用的“最大数字”是多少。这可能吗?顺便说一句,这是一个非常特殊的情况,通常我会使用一个事件,但在这种情况下我必须这样做。不幸的是,没有“列表”Keyboard.CurrentlyDownKeys。至少我没看到。
Thanks, Chris
谢谢,克里斯
EDIT:Ok, because it seems to be a bigger deal, here the reason for this: I have defined a "KeySet" which serves as DictionaryKey for custom functions. If anybody clicks on an element, the wrapper iterates through the dictionary and checks if any of the predefined "Keysets" is active.
编辑:好的,因为这似乎是一个更大的交易,原因如下:我定义了一个“KeySet”,作为自定义函数的 DictionaryKey。如果有人点击某个元素,包装器将遍历字典并检查是否有任何预定义的“键集”处于活动状态。
This allows me to define simple triggers, like e.g. Run this function if ALT+A+B is pressed. Another option is e.g. Run this function if ALT+STRG+A is pressed (during a mouse click on a WPF element).
这允许我定义简单的触发器,例如,如果按下 ALT+A+B,则运行此函数。另一个选项是,例如,如果按下 ALT+STRG+A(在 WPF 元素上单击鼠标期间),则运行此函数。
The only "problem" with the current implementation, if I define a Keyset which does NOT contain any REAL keys, like run if ALT is pressed, it is also triggered if ALT+A is pressed. Oh, while writing this, I realize that there is another problem. ALT+A+B would currently also trigger if ALT+A+B+C is pressed.
当前实现的唯一“问题”是,如果我定义了一个不包含任何 REAL 键的 Keyset,例如按下 ALT 则运行,如果按下 ALT+A,它也会被触发。哦,在写这个的时候,我意识到还有一个问题。如果按下 ALT+A+B+C,ALT+A+B 当前也会触发。
Perhaps my approach is wrong, and I should create a "static key tracker" and compare the keyset to its values (aquired via events).. I will give this a try.
也许我的方法是错误的,我应该创建一个“静态键跟踪器”并将键集与其值(通过事件获得)进行比较。我会尝试一下。
EDIT 2This is not working, at least not in a simple way. I need an FrameworkElement to attach to KeyDown, but I do not have it in a static constructor. And I am not interested in KeyDownEvents of a certain element, but "globally"...I think I juts postpone this problem, its not that important. Still, if anybody knows a better of different approach...
编辑 2这不起作用,至少不是以简单的方式。我需要一个 FrameworkElement 来附加到 KeyDown,但我在静态构造函数中没有它。而且我对某个元素的 KeyDownEvents 不感兴趣,但是“全局”......我想我只是推迟这个问题,它并不那么重要。不过,如果有人知道更好的不同方法......
So long, for anyone who cares, here some code:
这么久,对于任何关心的人,这里有一些代码:
public class KeyModifierSet
{
internal readonly HashSet<Key> Keys = new HashSet<Key>();
internal readonly HashSet<ModifierKeys> MKeys = new HashSet<ModifierKeys>();
public override int GetHashCode()
{
int hash = Keys.Count + MKeys.Count;
foreach (var t in Keys)
{
hash *= 17;
hash = hash + t.GetHashCode();
}
foreach (var t in MKeys)
{
hash *= 19;
hash = hash + t.GetHashCode();
}
return hash;
}
public override bool Equals(object obj)
{
return Equals(obj as KeyModifierSet);
}
public bool Equals(KeyModifierSet other)
{
// Check for null
if (ReferenceEquals(other, null))
return false;
// Check for same reference
if (ReferenceEquals(this, other))
return true;
// Check for same Id and same Values
return Keys.SetEquals(other.Keys) && MKeys.SetEquals(other.MKeys);
}
public bool IsActive()
{
foreach (var k in Keys)
if (Keyboard.IsKeyUp(k)) return false;
if ((Keys.Count == 0) && !Keyboard.IsKeyDown(Key.None)) return false;
foreach (var k in MKeys)
if ((Keyboard.Modifiers & k) == 0) return false;
if ((MKeys.Count == 0) && Keyboard.Modifiers > 0) return false;
return true;
}
public KeyModifierSet(ModifierKeys mKey)
{
MKeys.Add(mKey);
}
public KeyModifierSet()
{
}
public KeyModifierSet(Key key)
{
Keys.Add(key);
}
public KeyModifierSet(Key key, ModifierKeys mKey)
{
Keys.Add(key);
MKeys.Add(mKey);
}
public KeyModifierSet Add(Key key)
{
Keys.Add(key);
return this;
}
public KeyModifierSet Add(ModifierKeys key)
{
MKeys.Add(key);
return this;
}
}
采纳答案by Sam Harwell
[DllImport("user32.dll", EntryPoint = "GetKeyboardState", SetLastError = true)]
private static extern bool NativeGetKeyboardState([Out] byte[] keyStates);
private static bool GetKeyboardState(byte[] keyStates)
{
if (keyStates == null)
throw new ArgumentNullException("keyState");
if (keyStates.Length != 256)
throw new ArgumentException("The buffer must be 256 bytes long.", "keyState");
return NativeGetKeyboardState(keyStates);
}
private static byte[] GetKeyboardState()
{
byte[] keyStates = new byte[256];
if (!GetKeyboardState(keyStates))
throw new Win32Exception(Marshal.GetLastWin32Error());
return keyStates;
}
private static bool AnyKeyPressed()
{
byte[] keyState = GetKeyboardState();
// skip the mouse buttons
return keyState.Skip(8).Any(state => (state & 0x80) != 0);
}
回答by FrustratedWithFormsDesigner
Where is this code running from? Is it in an event handler? Many forms and controls will fire a KeyPress event as well as a KeyDown event. You may want to look into those events and set your flag to true when one of them occurs. You'd also have to listen for the corresponding event that tells you when the key is released (KeyUp, also, I think).
这段代码从哪里运行?它在事件处理程序中吗?许多窗体和控件将触发 KeyPress 事件以及 KeyDown 事件。您可能需要查看这些事件,并在其中一个事件发生时将标志设置为 true。您还必须监听相应的事件,该事件告诉您何时释放键(KeyUp,我认为也是如此)。
回答by Wim Hollebrandse
If you're using Windows.Forms
, use the KeyDown
event and read out the specific key using the appropriate KeyEventArgs
. You can access the KeyCode
property on the KeyEventArgs
variable.
如果您正在使用Windows.Forms
,请使用该KeyDown
事件并使用适当的KeyEventArgs
. 您可以访问变量KeyCode
上的属性KeyEventArgs
。
To check for ranges, say between A and Z:
要检查范围,请说在 A 和 Z 之间:
if (e.KeyCode>=Keys.A && e.KeyCode<=Keys.Z)
{
// do stuff...or not
}
回答by eKek0
normally I would use an event
You should still be using an event, preferably KeyDown since you don't mind what key is pressed, if you are programming on windows. If not, you could use something like Console.ReadLine();.
如果您在 Windows 上编程,您仍然应该使用一个事件,最好是 KeyDown,因为您不介意按下什么键。如果没有,你可以使用像Console.ReadLine();这样的东西。.
edit:If you are looking for something like
编辑:如果您正在寻找类似的东西
if (Keyboard.IsKeyDown(Key.AnyKey)) return true;
then you must be joking...
那你一定是在开玩笑……
edit 2:Well, the approach of your logger is interesting, but I think that you are reinventing the wheel. All programming languages provides some way to handle wich key was pressed, when this can be known. In C# for Windows, this is done using events. Besides, I think you won't be able to handle this kind of things by yourself in .NET, since you need to access some system functions from the Win32 API, and AFAIK you aren't allowed to do this (at least easily...) in managed code. Some solution would be to create a HOOK and send messages from there to your application, but I don't know how to do this in C#. This was the way in Delphi, where I have more experience.
编辑 2:嗯,您的记录器的方法很有趣,但我认为您正在重新发明轮子。所有的编程语言都提供了一些方法来处理按下的键,当这可以知道时。在 C# for Windows 中,这是使用事件完成的。此外,我认为您将无法在 .NET 中自己处理此类事情,因为您需要从 Win32 API 访问某些系统功能,而 AFAIK 不允许您这样做(至少很容易。 ..) 在托管代码中。一些解决方案是创建一个 HOOK 并将消息从那里发送到您的应用程序,但我不知道如何在 C# 中执行此操作。这是在德尔福的方式,在那里我有更多的经验。
回答by No Refunds No Returns
http://sourceforge.net/projects/keystate/shows "special" keys. Otherwise I think you're just going to have to monitor them. SOunds like you want to do this systemwide? What are you trying to accomplish?
http://sourceforge.net/projects/keystate/显示“特殊”键。否则我认为你只需要监视它们。听起来您想在系统范围内执行此操作?你想达到什么目的?
回答by xpda
You can increment a counter for each keydown event, and decrement it for each keyup event. When the counter is zero, no keys are down.
您可以为每个 keydown 事件增加一个计数器,并为每个 keyup 事件减少它。当计数器为零时,没有键被关闭。
回答by Carlc75
Using the XNA framework you can use thw follow for checking if any key has been pressed.
使用 XNA 框架,您可以使用 thw follow 来检查是否按下了任何键。
Keyboard.GetState().GetPressedKeys().Length > 0
回答by Andy
Quite an old question but in case anyone comes across this and doesn't want to use external dll's, you could just enumerate the possible keys and loop over them.
一个很老的问题,但如果有人遇到这个问题并且不想使用外部 dll,你可以枚举可能的键并循环它们。
bool IsAnyKeyPressed()
{
var allPossibleKeys = Enum.GetValues(typeof(Key));
bool results = false;
foreach (var currentKey in allPossibleKeys)
{
Key key = (Key)currentKey;
if (key != Key.None)
if (Keyboard.IsKeyDown((Key)currentKey)) { results = true; break; }
}
return results;
}
You could optimize this a bit by doing the enum outside of the function and retaining the list for later.
您可以通过在函数外部进行枚举并保留列表以供稍后使用来优化此功能。
回答by ILIAS BURKETT
In the Key Enumeration there is an Enumeration value of Zero(0), which basically tests "No Key Pressed", which is opposite of "Any key pressed". So, something like this might work;
在 Key Enumeration 中有一个 Enumeration 值 Zero(0),它基本上测试“No Key Pressed”,这与“Any key press”相反。所以,这样的事情可能会奏效;
If !GetKeyState(0)==True then
Do Something
End If
Or
或者
If GetKeyState(0)==False then
Do Something
End If