8

I'm Going to start a console application. The problem is how to determine that the CTRL key is pressed alone without any other key.

using System;
using System.Text;

public class ConsoleKeyExample
{
   public static void Main()
    {

       ConsoleKeyInfo input;
       do
       {
           input = Console.ReadKey(true);
           StringBuilder output = new StringBuilder(String.Format("You pressed {0}",input.Key.ToString()));

           Console.WriteLine(output.ToString());
           if ((input.Modifiers & ConsoleModifiers.Control) != 0)
           {
               Console.WriteLine("CTRL Pressed");
            }
       } while (input.Key != ConsoleKey.Escape);
   }
  }

I want to monitor the behavior of the CTRL key. After tracing this code, I put a checkpoint on readkey line, but when I press CTRL, nothing happens, but when I press any other key like "K" it starts reading key from the keyboard.

Jim Simson
  • 2,774
  • 3
  • 22
  • 30
Nautilus
  • 81
  • 1
  • 3
  • Console applications rely on an input stream, so unless some actual characters are inserted into the stream you can't detect keypresses. – Asad Saeeduddin Nov 03 '15 at 01:58
  • what must i do , i need to monitor CTRL key behavior in Console application – Nautilus Nov 03 '15 at 02:02
  • Unfortunately I don't think there's a way to do it without having to P/Invoke to Windows API and using that to monitor keypresses. Like I said, a Console application's primary source of input is the input stream, and unless a keypress puts characters into that input stream, I don't know how you would go about detecting it. – Asad Saeeduddin Nov 03 '15 at 02:07
  • and what about low level keyborad hook ? – Nautilus Nov 03 '15 at 02:27

2 Answers2

8

Unless you are using a .Net framework older than version 4.0 I believe using Enum.HasFlag() is more readable than using bit-wise AND.

e.g.

if (cki.Modifiers.HasFlag(ConsoleModifiers.Control))
{
   Console.Write("CTRL ");
}

I'm not sure why the MSDN article isn't updated to use flags because ConsoleModifiers does support Flags attribute.

Below is an updated copy of the same program that works on framework 4.0 and above.

static void Main(string[] args)
{
    ConsoleKeyInfo cki;

    Console.WriteLine("Press Esc to exit the loop");

    do
    {
        cki = Console.ReadKey(true);

        if (cki.Modifiers.HasFlag(ConsoleModifiers.Control))
        {
            Console.Write("CTRL ");
        }

        if (cki.Modifiers.HasFlag(ConsoleModifiers.Alt))
        {
            Console.Write("ALT ");
        }

        if (cki.Modifiers.HasFlag(ConsoleModifiers.Shift))
        {
            Console.Write("SHIFT ");
        }

        Console.WriteLine(cki.Key.ToString());

    } while (cki.Key != ConsoleKey.Escape);


    Console.WriteLine("Press any key to exit");
    Console.ReadKey();
}
Menol
  • 1,230
  • 21
  • 35
  • I could not get this to work in VS2022, using .NET framework 4.8. The Console.ReadKey() method simply does not return anything when the Ctrl key is pressed by itself. Same goes for Alt and Shift keys when pressed by themselves. It would seem ConsoleModifiers can only be read when another key is also depressed at the same time (not including modifier keys). A very similar approach is used on Microsoft Learn, with the same issue. https://learn.microsoft.com/en-us/dotnet/api/system.consolekeyinfo?redirectedfrom=MSDN&view=net-7.0 – Tristan Bailey Feb 02 '23 at 08:31
5

Yes it is possible by using ConsoleKeyInfo. Example:

public static void Main() 
{
  ConsoleKeyInfo cki;
  // Prevent example from ending if CTL+C is pressed.
  Console.TreatControlCAsInput = true;

  Console.WriteLine("Press any combination of CTL, ALT, and SHIFT, and a console key.");
  Console.WriteLine("Press the Escape (Esc) key to quit: \n");
  do 
  {
     cki = Console.ReadKey();
     Console.Write(" --- You pressed ");
     if((cki.Modifiers & ConsoleModifiers.Alt) != 0) Console.Write("ALT+");
     if((cki.Modifiers & ConsoleModifiers.Shift) != 0) Console.Write("SHIFT+");
     if((cki.Modifiers & ConsoleModifiers.Control) != 0) Console.Write("CTL+");
     Console.WriteLine(cki.Key.ToString());
   } while (cki.Key != ConsoleKey.Escape);
}

Although applies only to .NET Framework 4.6 and 4.5

  • 2
    Why not include the link to the MSDN article, which contains more helpful information, https://msdn.microsoft.com/en-us/library/system.consolekeyinfo(v=vs.110).aspx – supermeerkat May 02 '18 at 15:50