वर्तमान में दबाए गए कुंजी का पता कैसे लगाएं?


123

में Windows Forms , आप पता कर सकते हैं, किसी भी समय, कर्सर की वर्तमान स्थिति के लिए धन्यवाद कर्सर वर्ग।

कीबोर्ड के लिए एक ही चीज़ उपलब्ध नहीं लगती है। क्या यह जानना संभव है कि, उदाहरण के लिए, Shiftकुंजी दबाया गया है?

क्या प्रत्येक कीबोर्ड सूचना (KeyDown और KeyUp ईवेंट) को ट्रैक करना बिल्कुल आवश्यक है?


क्या आप WPF वातावरण में काम कर रहे हैं या कुछ और?
इपोट्टर

70
@epotter: दूसरा शब्द WinForms बताता है।
बजे विल एडिन्स '

जवाबों:


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

यह भी सही होगा अगर Ctrl+ Shiftनीचे है। यदि आप जाँच करना चाहते हैं कि क्या शिफ्ट को अकेले दबाया गया है,

if (Control.ModifierKeys == Keys.Shift)

यदि आप एक ऐसी श्रेणी में हैं, जो विरासत में मिलती है Control(जैसे कि एक रूप), तो आप इसे हटा सकते हैंControl.


8
जब तक मैं कुछ याद कर रहा हूँ, आपने सवाल का ठीक से जवाब नहीं दिया है। ओपी सभी कुंजियों के बारे में पूछ रहा है और केवल एक उदाहरण के रूप में Shift कुंजी का उपयोग किया है। तो आप अन्य कुंजियों जैसे ए से जेड, 0 से 9 आदि का पता कैसे लगाते हैं
ऐश

2
यह देखते हुए कि उन्होंने उत्तर स्वीकार कर लिया है, ऐसा प्रतीत होता है कि उन्हें केवल संशोधक कुंजियों की आवश्यकता थी। यदि आप अन्य कुंजी चाहते हैं, तो आपको GetKeyStateएपीआई फ़ंक्शन को कॉल करना होगा।
SLaks

2
GetKeyState के लिए कोई ज़रूरत नहीं है। आपको बस एक संदेश फ़िल्टर जोड़ना होगा। मेरा जवाब देखिए।
ऐश

2
एक WPF समाधान के लिए आप Keyboard.Modifiers == ModifierKeys.Shift उन लोगों के लिए उपयोग कर सकते हैं (जो खोज पर यहां आए थे)
बिल तारबेल

3
इसके बजाय (Control.ModifierKeys & Keys.Shift) != 0एक का उपयोग कर सकते हैंControl.ModifierKeys.HasFlag(Keys.Shift)
टमक्समोन

55

नीचे दिया गया कोड है कि वर्तमान में दबाए गए लगभग सभी कुंजी का पता लगाना है, न कि केवल Shiftकुंजी।

private KeyMessageFilter m_filter = new KeyMessageFilter();

private void Form1_Load(object sender, EventArgs e)
{
    Application.AddMessageFilter(m_filter);
}


public class KeyMessageFilter : IMessageFilter
{
    private const int WM_KEYDOWN = 0x0100;
    private const int WM_KEYUP = 0x0101;
    private bool m_keyPressed = false;

    private Dictionary<Keys, bool> m_keyTable = new Dictionary<Keys, bool>();

    public Dictionary<Keys, bool> KeyTable
    {
        get { return m_keyTable; }
        private set { m_keyTable = value; }
    }

    public bool IsKeyPressed()
    {
        return m_keyPressed;
    }

    public bool IsKeyPressed(Keys k)
    {
        bool pressed = false;

        if (KeyTable.TryGetValue(k, out pressed))
        {
            return pressed;
        }

        return false;
    }

    public bool PreFilterMessage(ref Message m)
    {
        if (m.Msg == WM_KEYDOWN)
        {
            KeyTable[(Keys)m.WParam] = true;

            m_keyPressed = true;
        }

        if (m.Msg == WM_KEYUP)
        {
            KeyTable[(Keys)m.WParam] = false;

            m_keyPressed = false;
        }

        return false;
    }
}

1
GetKeyStateअधिक कुशल होगा। जब विंडोज आपके लिए पहले से ही ऐसा करता है तो सभी कुंजी को ट्रैक करने का कोई मतलब नहीं है।
SLACs

3
@Slaks, जब तक आपके पास कुछ बेंचमार्क डेटा नहीं है, आप अनुमान लगा रहे हैं। इसके अलावा GetKeyState आपको एक कुंजी की स्थिति बताएगा, अगर आप उस कीबोर्ड ईवेंट को पहले स्थान पर फँसा सकते हैं। प्रश्न का मेरा पढ़ना यह है कि ओपी यह जानना चाहता है कि किसी भी समय एक कुंजी का राज्य कैसे प्राप्त किया जाए । तो GetKeyState अपने आप में बेकार है।
ऐश

3
कुंजी को दबाने के लिए आप इसका उपयोग कैसे करेंगे?
गेब्रियल रयान नह्मियास

गेब्रियल: अपने रूप में एक फ़ील्ड के रूप में KeyMessageFilter का एक उदाहरण बनाएं। Form_Load में Application.AddMessageFilter () में इसे पास करें। फिर इस उदाहरण पर IsKeyPressed () को उस प्रत्येक / किसी भी कुंजी के लिए कॉल करें जिसमें आप रुचि रखते हैं।
Ash

@ आपके जवाब के लिए धन्यवाद - क्या आप SHIFT कुंजी इत्यादि की जाँच के लिए एक कोड उदाहरण कर पाएंगे?
BKSpurgeon

23

यदि आप System.Windows.Input का संदर्भ लेते हैं, तो आप निम्नलिखित को भी देख सकते हैं

if (Keyboard.Modifiers == ModifierKeys.Shift)

कीबोर्ड नामस्थान का उपयोग Keyboard.IsKeyDown (Key) के साथ अन्य कुंजियों के दबाए गए राज्य की जांच करने के लिए भी किया जा सकता है, या यदि आप KeyDownEvent या इसी तरह के किसी कार्यक्रम के लिए सदस्यता ले रहे हैं, तो इवेंट तर्क वर्तमान में की गई कुंजियों की एक सूची ले जाते हैं।


1
वास्तव में Keyboard.Modifiers हमेशा ठीक से काम नहीं करते हैं। : मुश्किल तरीके की तलाश करनी है discoveringdotnet.alexeyev.org/2008/09/...
मैक्सिम Alexeyev

सिवाय इसके कि फॉर्म मॉडिफायर्स का उपयोग नहीं किया जा रहा है, System.Windows.Input modifiers एक अलग नामस्थान है और हर बार हमारे लिए ठीक काम किया है।
जेफ वेन

18

इनमें से अधिकांश उत्तर या तो बहुत जटिल हैं या मेरे लिए काम नहीं करते हैं (उदाहरण के लिए System.Windows.Input मौजूद नहीं है)। फिर मुझे कुछ सैंपल कोड मिले जो ठीक काम करता है: http://www.switchonthecode.com/tutorials/winforms-accessing-mouse-and-keyboard-state

यदि भविष्य में पृष्ठ गायब हो जाता है, तो मैं नीचे प्रासंगिक स्रोत कोड पोस्ट कर रहा हूं:

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

namespace MouseKeyboardStateTest
{
  public abstract class Keyboard
  {
    [Flags]
    private enum KeyStates
    {
      None = 0,
      Down = 1,
      Toggled = 2
    }

    [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
    private static extern short GetKeyState(int keyCode);

    private static KeyStates GetKeyState(Keys key)
    {
      KeyStates state = KeyStates.None;

      short retVal = GetKeyState((int)key);

      //If the high-order bit is 1, the key is down
      //otherwise, it is up.
      if ((retVal & 0x8000) == 0x8000)
        state |= KeyStates.Down;

      //If the low-order bit is 1, the key is toggled.
      if ((retVal & 1) == 1)
        state |= KeyStates.Toggled;

      return state;
    }

    public static bool IsKeyDown(Keys key)
    { 
      return KeyStates.Down == (GetKeyState(key) & KeyStates.Down);
    }

    public static bool IsKeyToggled(Keys key)
    { 
      return KeyStates.Toggled == (GetKeyState(key) & KeyStates.Toggled);
    }
  }
}

3
System.Windows.Inputमौजूद; इससे जूझ रहे अन्य लोगों के लिए आपको एक संदर्भ जोड़ने की जरूरत है PresentationCore, और गणन WindowsBaseतक पहुंचने के लिए एक अतिरिक्त संदर्भ System.Windows.Input.Key। यह जानकारी हमेशा MSDN पर पाई जा सकती है।
अल्फी

1
यह वर्ग माना जाता है static, नहीं abstract
लिटिल एंडियन

1
लिंक टूट गया है (404)।
पीटर मोर्टेंसन

2
"यदि भविष्य में पेज गायब हो जाए तो मैं नीचे प्रासंगिक स्रोत कोड पोस्ट कर रहा हूं"
parsley72

12

.NET फ्रेमवर्क संस्करण 3.0 के बाद Keyboard.IsKeyDownसे, नए System.Windows.Inputनामस्थान से विधि का उपयोग करना संभव है । उदाहरण के लिए:

if (((Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl)) && Keyboard.IsKeyDown(Key.F))
{
    // CTRL + F is currently pressed
}

भले ही यह WPF का हिस्सा है, यह विधि WinForm अनुप्रयोगों के लिए ठीक काम करती है (बशर्ते कि आप PresentationCore.dll और WindowsBase.dll के संदर्भ जोड़ दें )। हालांकि, दुर्भाग्य से, Keyboard.IsKeyDownविधि के 3.0 और 3.5 संस्करणों ने WinForm अनुप्रयोगों के लिए काम नहीं किया। इसलिए, यदि आप इसे WinForm एप्लिकेशन में उपयोग करना चाहते हैं, तो आपको इसे काम करने के लिए .NET फ्रेमवर्क 4.0 या बाद में लक्षित करने की आवश्यकता होगी।


बस एक नोट, यह केवल WPF के लिए है
डिएगो विएरा

2
@DiegoVieira वास्तव में, यह सच नहीं है। कार्यक्षमता को WPF के भाग के रूप में जोड़ा गया था, और इसके लिए आवश्यक है कि उन WPF पुस्तकालयों को संदर्भित किया जाए, लेकिन Keyboard.IsKeyDownविधि एक WinForm परियोजना में भी काम करती है।
स्टीवन डॉगगार्ट

वास्तव में, आपको
Diego Vieira

2
ध्यान दें कि यह Win32KeyboardDevice.GetKeyStatesFromSystem (कुंजी) के कार्यान्वयन में परिवर्तन की वजह से नहीं है काम (WinForms में) यदि लक्षित कर नेट 3.5 या इससे पहले, केवल 4.0+, :(
LMK

@LMK अच्छा कैच। मैंने खुद इसका परीक्षण किया और सत्यापित किया कि आपने क्या कहा। मैंने उस जानकारी को दर्शाने के लिए अपना उत्तर अपडेट किया। धन्यवाद!
स्टीवन डॉगार्ट

8

आप कर सकते हैं पी / आह्वान Win32 के लिए नीचे GetAsyncKeyState कीबोर्ड पर किसी भी कुंजी परीक्षण करने के लिए।

आप इस फ़ंक्शन के कुंजी enum (जैसे Keys.Shift) से मानों में पास कर सकते हैं, इसलिए इसे जोड़ने के लिए केवल कोड की कुछ पंक्तियों की आवश्यकता होती है।


Keyboardसंकलक द्वारा पहचाना नहीं गया था, लेकिन GetAsyncKeystateuser32 में ठीक काम किया। धन्यवाद!
आइंस्टीन एक्स। रहस्य


3

मैंने विंडोज फॉर्म फॉर्म पर कीबोर्ड इनपुट को प्रबंधित करने का सबसे अच्छा तरीका कीस्ट्रोके के बाद और ध्यान केंद्रित करने से पहले घटना को प्राप्त करने से पहले इसे संसाधित करना है। Microsoft इस सटीक चीज़ को सुविधाजनक बनाने के लिए .KeyPreviewForm नामक एक अंतर्निहित इन- प्रॉपर्टी रखता है:

public frmForm()
{
    // ...
    frmForm.KeyPreview = true;
    // ...
}

फिर फॉर्म का _KeyDown, _KeyPress, और / या _KeyUp घटनाओं को इनपुट फॉर्म तक पहुंचने से पहले देखा जा सकता है, जब फ़ोकस फ़ोकस कंट्रोल उन्हें देखता है, और आप हैंडलर लॉजिक को लागू कर सकते हैं ताकि वहां होने वाली ईवेंट को कैप्चर किया जा सके और फ़ोकस किए गए फ़ॉर्म नियंत्रण से इसे पारित किया जा सके। ।

यद्यपि XAML के इवेंट-राउटिंग आर्किटेक्चर के रूप में संरचनात्मक रूप से सुशोभित नहीं है , यह Winforms में फ़ॉर्म-स्तर के कार्यों का प्रबंधन बहुत सरल बनाता है। कैविट्स के लिए KeyPreview पर MSDN नोट देखें ।


2
if (Form.ModifierKeys == Keys.Shift)

एक पाठ बॉक्स के लिए काम करता है अगर उपरोक्त कोड फॉर्म की कीडाउन घटना में है और कोई अन्य नियंत्रण कुंजी डाउन के लिए कीडाउन इवेंट को कैप्चर नहीं करता है।

इसके अलावा कोई भी आगे की प्रक्रिया को रोक सकता है:

e.Handled = true;

2
if (Control.ModifierKeys == Keys.Shift)
    //Shift is pressed

कर्सर x / y स्थिति एक संपत्ति है, और एक कुंजीपट (जैसे माउस क्लिक / मूसमव) एक घटना है। सबसे अच्छा अभ्यास आमतौर पर इंटरफ़ेस को घटना संचालित करने के लिए होता है। केवल उसी समय के बारे में जब आपको ऊपर की आवश्यकता होगी, यदि आप एक शिफ्ट + मूसलीक चीज़ करने की कोशिश कर रहे हैं।


0

WinForms में:

if( Form.ModifierKeys == Keys.Shift )

ऐसा लगता है कि स्टैक ओवरफ्लो प्रश्न के डुप्लिकेट की तरह पता लगाता है कि शिफ्ट कुंजी को विंडोज फॉर्म में घटनाओं का उपयोग किए बिना दबाया जाता है?


वह परवाह नहीं कर सकता है, लेकिन मैं सिर्फ इसे बाहर करना चाहता था: पी
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.