Visual Studio 2010!

Read now >

View Now
DevSource RSS FEEDS
XML Want an easy way to keep up with breaking tech news? And the Get DevSource headlines delivered to your desktop with RSS.
ADVERTISEMENT
ADVERTISEMENT

 

DevSource.com: Your Source for Visual Studio on Facebook
ADVERTISEMENT
Console Input in .NET
By Jim Mischel

Rate This Article: Add This Article To:

Console Input in .NET - ' Low'
( Page 3 of 5 )

-Level Input">

Low-Level Input

Low-level input gives your application direct access to the input event stream. The GetNumberOfConsoleInputEvents function returns the total number of events available in the input queue. ReadConsoleInput removes one or more events from the input queue and places them in an array. PeekConsoleInput reads input records but does not remove them from the queue.

FlushConsoleInputBuffer empties the input queue, discarding all input event records.

The WriteConsoleInput API function allows you to place events into the input queue. This function makes it possible to script a console session by reading pre-recorded (or created) input event records from a file and then playing them back as the program runs. You could also use this function to have one application control another that is attached to the same console window.

The advantage of using low-level input is that you have full access to all of the input events. You get key down and key up events for all of the keys on the keyboard, including normal character keys, function keys, Alt-key combinations, and even shift, control, Alt, and caps lock keys. You also can obtain mouse events and window resizing events if you enable those modes. Mouse events are enabled by default.

The disadvantage of using low-level input is that you have to do your own line editing if you want the user to enter lines of text. This can be a very difficult problem. Fortunately, the two modes can work together. That is, your program can use the low-level routines for mouse input and single-character command sequences, and then use the high-level functions if you need traditional line-oriented input. The only drawback, of course, is that mouse events are discarded when the program is using the high-level ReadConsole function.

System.Console implements two low-level input functions: KeyAvailable and ReadKey. KeyAvailable returns True if there is a key down event record available in the input queue. ReadKey reads the next key down event and returns a ConsoleKeyInfo structure that describes the key that was pressed. ReadKey returns information about almost all key presses. It does not include shift, Alt, control, or caps lock key events. That is, ReadKey lets you know if the user pressed Alt+S, but it won't return an Alt key press by itself. The ConsoleInputBuffer class duplicates the functionality of KeyAvailable and ReadKey so that applications can access the input buffer when the standard input handle has been redirected.

The System.Console class does not provide direct access to the console input buffer. With the standard .NET console interface, there is no way to peek into the event queue, flush the queue, or process key up and mouse events. In a sense, the low-level input routines supported by System.Console are more like medium-level. ConsoleInputBuffer does allow direct input buffer access. The NumInputEvents property returns the number of events currently waiting in the queue. ReadEvents removes raw input events from the queue and returns them in an array of ConsoleInputEventInfo structures. PeekEvents returns an array of input events without removing them from the queue, and Flush empties the queue, discarding all events.

The ConsoleInputBuffer.WriteEvents method allows applications to write events to the input queue.

The program in Listing 1 illustrates using the low-level input methods to get raw input event information.

Listing 1: Processing raw input events

static void Main(string[] args)
{
  using (ConsoleInputBuffer ib = JConsole.GetInputBuffer())
  {
    while (true)
    {
      ConsoleInputEventInfo[] events = ib.ReadEvents(10);
      Console.WriteLine("{0} events", events.Length);
      foreach (ConsoleInputEventInfo ev in events)
      {
        Console.WriteLine("Event type = {0}", ev.EventType);
        switch (ev.EventType)
        {
          case ConsoleInputEventType.KeyEvent:
            Console.WriteLine("Key {0}", ev.KeyEvent.KeyDown ? "down" : "up");
            Console.WriteLine("Scan code = {0}", ev.KeyEvent.VirtualScanCode);
            Console.WriteLine("Virtual key code = {0}", ev.KeyEvent.VirtualKeyCode);
            break;
          case ConsoleInputEventType.MouseEvent:
            if ((ev.MouseEvent.EventFlags & (ConsoleMouseEventType)0xfffff) == 0)
              Console.Write("Mouse button,");
            if ((ev.MouseEvent.EventFlags & ConsoleMouseEventType.DoubleClick) != 0)
              Console.Write("Double click,");
            if ((ev.MouseEvent.EventFlags & ConsoleMouseEventType.MouseWheeled) != 0)
              Console.Write("Mouse wheeled,");
            if ((ev.MouseEvent.EventFlags & ConsoleMouseEventType.MouseMoved) != 0)
              Console.Write("Mouse moved,");
            if ((ev.MouseEvent.EventFlags & ConsoleMouseEventType.MouseHWheeled) != 0)
              Console.Write ("Mouse hWheeled,");
            Console.WriteLine("Button state = {0}", ev.MouseEvent.ButtonState);
            break;
        }
      }
    }
  }
}

Although you could modify that code and fit it into your .NET console application, it's kind of messy and very fragile. There's a lot going on in some of the events — especially the mouse events. The whole interface is just begging to be wrapped up into a pretty .NET interface that raises events in the same way that keyboard and mouse actions raise events in GUI applications.



 
 
>>> More Using Microsoft Visual Studio Articles          >>> More By Jim Mischel