2010-12-04 17 views
8

मेरे पास सी # में लिखा गया एक सरल कंसोल ऐप है। मैं तीर कुंजी प्रेस का पता लगाने में सक्षम होना चाहता हूं, इसलिए मैं उपयोगकर्ता को स्टीयर करने की अनुमति दे सकता हूं। मैं कंसोल ऐप के साथ कीडाउन/कीप घटनाओं का पता कैसे लगा सकता हूं?सी # कंसोल ऐप के लिए तीर कुंजी इनपुट

मेरे सभी googling विंडोज़ फॉर्म के बारे में जानकारी के लिए नेतृत्व किया है। मेरे पास एक जीयूआई नहीं है। यह एक कंसोल ऐप है (एक सीरियल पोर्ट पर रोबोट को नियंत्रित करने के लिए)।

मैं इन घटनाओं को संभालने के लिए लिखा काम करता है है, लेकिन मैं कैसे वास्तव में घटनाओं प्राप्त करने के लिए रजिस्टर करने के लिए पता नहीं है:

private void myKeyDown(object sender, KeyEventArgs e) 
    { 
     switch (e.KeyCode) 
     { 
      case Keys.Left: 
       ... 
      case Keys.Right: 
       ... 
      case Keys.Up: 
       ... 
     } 
    } 

    private void myKeyUp(object sender, KeyEventArgs e) 
    { 
     ... pretty much the same as myKeyDown 
    } 

यह शायद एक बहुत बुनियादी सवाल है, लेकिन मैं काफी सी # करने के लिए नया हूँ , और मुझे पहले इस तरह के इनपुट प्राप्त करने की आवश्यकता नहीं है।

अद्यतन: कई सुझाव दे रहे हैं कि मैं System.Console.ReadKey(true).Key का उपयोग करता हूं। यह मदद नहीं करेगा। मुझे एक कुंजी को दबाए जाने के पल को जानने की जरूरत है, जब इसे रिलीज़ किया जाता है, तो कई चाबियों को एक साथ दबाया जा सकता है। इसके अलावा, रीडकी एक अवरुद्ध कॉल है - जिसका अर्थ है कि प्रोग्राम रुक जाएगा और दबाए जाने की कुंजी की प्रतीक्षा करेगा।

अद्यतन: ऐसा लगता है कि ऐसा करने का एकमात्र व्यवहार्य तरीका विंडोज फॉर्म का उपयोग करना है। यह कष्टप्रद है, क्योंकि मैं इसे एक हेडलेस सिस्टम पर उपयोग नहीं कर सकता। कुंजीपटल इनपुट प्राप्त करने के लिए एक फॉर्म जीयूआई की आवश्यकता है ... बेवकूफ।

लेकिन वैसे भी, वंशावली के लिए, मेरा समाधान यहां है। मैं अपने .sln में एक नया प्रपत्र प्रोजेक्ट बनाया:

private void Form1_Load(object sender, EventArgs e) 
    { 
     try 
     { 
      this.KeyDown += new KeyEventHandler(Form1_KeyDown); 
      this.KeyUp += new KeyEventHandler(Form1_KeyUp); 
     } 
     catch (Exception exc) 
     { 
      ... 
     } 
    } 

    void Form1_KeyDown(object sender, KeyEventArgs e) 
    { 
     switch (e.KeyCode) 
     { 
      // handle up/down/left/right 
      case Keys.Up: 
      case Keys.Left: 
      case Keys.Right: 
      case Keys.Down: 
      default: return; // ignore other keys 
     } 
    } 

    private void Form1_KeyUp(object sender, KeyEventArgs e) 
    { 
     // undo what was done by KeyDown 
    } 

ध्यान दें कि यदि आप एक कुंजी को दबाए रखें, KeyDown कई बार बुलाया जाएगा, और KeyUp केवल एक बार कहा जाएगा (जब आप इसे जारी)। तो आपको बार-बार कुंजीडाउन कॉल को गहन तरीके से संभालने की आवश्यकता है।

+0

आप रीडकी को एक अलग थ्रेड में कॉल कर सकते हैं, मेरे कताई थ्रेड सुझाव देखें। हालांकि वह कीप/कीडाउन सामग्री को संबोधित नहीं करता है। – Rushyo

उत्तर

14

थोड़ा देर हो चुकी है, लेकिन कंसोल एप्लिकेशन में कीबोर्ड स्थिति तक पहुंचने का तरीका यहां दिया गया है।

ध्यान दें कि यह सभी प्रबंधित कोड नहीं है क्योंकि इसे User32.dll से आयात करने के लिए GetKeyState की आवश्यकता है।

/// <summary> 
/// Codes representing keyboard keys. 
/// </summary> 
/// <remarks> 
/// Key code documentation: 
/// http://msdn.microsoft.com/en-us/library/dd375731%28v=VS.85%29.aspx 
/// </remarks> 
internal enum KeyCode : int 
{ 
    /// <summary> 
    /// The left arrow key. 
    /// </summary> 
    Left = 0x25, 

    /// <summary> 
    /// The up arrow key. 
    /// </summary> 
    Up, 

    /// <summary> 
    /// The right arrow key. 
    /// </summary> 
    Right, 

    /// <summary> 
    /// The down arrow key. 
    /// </summary> 
    Down 
} 

/// <summary> 
/// Provides keyboard access. 
/// </summary> 
internal static class NativeKeyboard 
{ 
    /// <summary> 
    /// A positional bit flag indicating the part of a key state denoting 
    /// key pressed. 
    /// </summary> 
    private const int KeyPressed = 0x8000; 

    /// <summary> 
    /// Returns a value indicating if a given key is pressed. 
    /// </summary> 
    /// <param name="key">The key to check.</param> 
    /// <returns> 
    /// <c>true</c> if the key is pressed, otherwise <c>false</c>. 
    /// </returns> 
    public static bool IsKeyDown(KeyCode key) 
    { 
     return (GetKeyState((int)key) & KeyPressed) != 0; 
    } 

    /// <summary> 
    /// Gets the key state of a key. 
    /// </summary> 
    /// <param name="key">Virtuak-key code for key.</param> 
    /// <returns>The state of the key.</returns> 
    [System.Runtime.InteropServices.DllImport("user32.dll")] 
    private static extern short GetKeyState(int key); 
} 
+0

दिलचस्प। इसके लिए कुंजीपटल को अपने आप पर मतदान करने की आवश्यकता होगी, जिसका अर्थ है कि मेरे पास सिर्फ ईवेंट-आधारित ऐप नहीं हो सकता है। लेकिन यह करने के लिए काफी आसान है। – Tim

+2

हां, कंसोल अनुप्रयोगों में आम तौर पर एक संदेश लूप नहीं होता है, लेकिन आपके खुद को रोल करने से रोकने के लिए कुछ भी नहीं है, और फिर आपका शेष एप्लिकेशन ईवेंट संचालित हो जाता है। – Ergwun

+0

बहुत उपयोगी, इसके लिए +1! – teodron

4
var isUp = Console.ReadKey().Key == ConsoleKey.UpArrow; 

या एक और उदाहरण है, बस अपने मामले के लिए:

while (true) 
{ 
    var ch = Console.ReadKey(false).Key; 
    switch(ch) 
    { 
     case ConsoleKey.Escape: 
      ShutdownRobot(); 
      return; 
     case ConsoleKey.UpArrow: 
      MoveRobotUp(); 
      break; 
     case ConsoleKey.DownArrow: 
      MoveRobotDown(); 
      break; 
    } 
} 
0

उदाहरण कोड:

 ConsoleKeyInfo kb = Console.ReadKey(); 
     if (kb.Key == ConsoleKey.LeftArrow) 
       Console.WriteLine("Left Arrow pressed"); 
2
System.Console.ReadKey(true).Key == ConsoleKey.UpArrow 

आप एक स्पिन में है कि डाल सकता है, कुछ की तरह:

while(Running) 
{ 
    DoStuff(); 
    System.Console.ReadKey(true).Key == ConsoleKey.UpArrow 
    Thread.Sleep(1) 
} 
+0

एक कुंजी दबाए रखने, या एकाधिक कुंजी पकड़ने के बारे में क्या? मैं सिर्फ नवीनतम कुंजी दबा नहीं चाहता हूं - मैं कई कुंजी दबाए रखना चाहता हूं (या बिल्कुल कोई भी कुंजी दबाया नहीं जाता है)। – Tim

+0

फिर आपको सीधे कीबोर्ड संदेशों को संभालने की आवश्यकता है। ऐसा करने का सबसे आसान तरीका विंडोज पर डायरेक्ट इनपुट का उपयोग कर रहा है। – Rushyo

+0

यदि आपको इसे मैन्युअल रूप से करना होगा, तो प्रासंगिक Win32 फ़ंक्शन GetConsoleWindow और SetWindowsHookEx हैं। कच्चे विंडोज संदेशों को फंसाने के लिए कंसोल की 'WH_CALLWNDPROC' ईवेंट को हुक करें। एक कंसोल को बहुत अधिक अमूर्तता नहीं मिलती है जो एक विंडोज़ फॉर्म करता है, हालांकि इसमें कार्यक्षमता हो सकती है जो आप इस तथ्य की तलाश में कर रहे हैं, किसी ने सुझाव नहीं दिया है कि यह मेरा तात्पर्य है कि यह आपका अगला तार्किक कदम है। – Rushyo

0

आप इस

bool keyWasPressed = false; 
if (consolekey.avalable) 
{ 
keyvar = console.readkey(true); 
keyWasPressed = true; 
} 
if(keyWasPressed) 
{ 
//enter you code here using keyvar 
} 
else 
{ 
//the commands that happen if you don't press anything 
} 
0

मैं एक ही मुद्दा है कि आप और मैंने पाया है, यहाँ, कोई रोचक पोस्ट कार्यों का उपयोग कर ऐसा कर सकते हैं। मूल पोस्ट यहां पाया जा सकता: C# Console Application - How do I always read input from the console?

मैं एक रास्पबेरी GPIO के माध्यम से एक PWM उत्पादन का अनुकरण करने के (का उपयोग कर मोनो सी #) एक एलसीडी बैकलाइट का परीक्षण करने के लिए है। दो सरल कुंजी के साथ मैं कर्तव्य चक्र (ऊपर/नीचे) और कार्यक्रम को रोकने के लिए एक अतिरिक्त कुंजी को बदलना चाहता था।

मैंने कोशिश की इस (चर):

static ConsoleKeyInfo key = new ConsoleKeyInfo(); 
static int counter = 0; 
static int duty = 5; // Starts in 50% 

मुख्य कार्यक्रम:

static void Main(string[] args) 
{ 
// cancellation by keyboard string 
    CancellationTokenSource cts = new CancellationTokenSource(); 
    // thread that listens for keyboard input 
    var kbTask = Task.Run(() => 
    { 
     while (true) 
     { 
      key = Console.ReadKey(true); 
      if (key.KeyChar == 'x' || key.KeyChar == 'X') 
      { 
       cts.Cancel(); 
       break; 
      } 
      else if (key.KeyChar == 'W' || key.KeyChar == 'w') 
      { 
       if (duty < 10) 
        duty++; 
       //Console.WriteLine("\tIncrementa Ciclo"); 
       //mainAppState = StateMachineMainApp.State.TIMER; 
       //break; 
      } 
      else if (key.KeyChar == 'S' || key.KeyChar == 's') 
      { 
       if (duty > 0) 
        duty--; 
       //Console.WriteLine("\tDecrementa Ciclo"); 
       //mainAppState = StateMachineMainApp.State.TIMER; 
       // break; 
      } 
     } 
    }); 

    // thread that performs main work 
    Task.Run(() => DoWork(), cts.Token); 

    string OsVersion = Environment.OSVersion.ToString(); 
    Console.WriteLine("Sistema operativo: {0}", OsVersion); 
    Console.WriteLine("Menú de Progama:"); 
    Console.WriteLine(" W. Aumentar ciclo útil"); 
    Console.WriteLine(" S. Disminuir ciclo útil"); 
    Console.WriteLine(" X. Salir del programa"); 

    Console.WriteLine(); 
    // keep Console running until cancellation token is invoked 
    kbTask.Wait(); 
} 

static void DoWork() 
{ 
    while (true) 
    { 
     Thread.Sleep(50); 
     if (counter < 10) 
     { 
      if (counter < duty) 
       Console.Write("─"); 
       //Console.WriteLine(counter + " - ON"); 
      else 
       Console.Write("_"); 
       //Console.WriteLine(counter + " - OFF"); 
      counter++; 
     } 
     else 
     { 
      counter = 0; 
     } 
    } 
} 

जब यह कर्तव्य चक्र को बढ़ाने के लिए आवश्यक है, दबाने 'डब्ल्यू' कुंजी मुख्य कार्य कर्तव्य बदलता है कि बनाता है चक्र चर (कर्तव्य); कमी के लिए 'एस' कुंजी के साथ एक ही बात। कार्यक्रम 'एक्स' कुंजी दबाए जाने पर समाप्त होता है।

संबंधित मुद्दे