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 - ' Writing Events '
( Page 5 of 5 )

Writing Events

Just as you can read data from a console screen buffer, you can write events to the console input buffer. This facility is quite useful if you want to record a user's session and then play it back for debugging, or if you have saved data in "macros" that you want played back.

The ConsoleInputBuffer.WriteEvents method takes an array of EventArgs descendant objects and places them in the input queue. The objects in the array must be recognized event types: ConsoleKeyEventArgs, ConsoleMouseEventArgs, ConsoleWindowBufferSizeEventArgs, ConsoleFocusEventArgs, or ConsoleMenuEventArgs. If you pass any other type, the method throws an exception.

Placing focus events, menu events, and window buffer size events in the queue has no real effect on the program's operation. For example, queuing a window buffer size event will not change the size of the screen buffer, nor will queuing a focus event cause the program to gain or lose focus.

The program shown below in Listing 3 places a window buffer size event and a number of key events (simulating the user typing "Hello" and pressing Enter) into the input event queue. It then processes those events.

Listing 3: Writing to the input event queue

using System;
using System.Collections.Generic;
using System.Text;

using Mischel.ConsoleDotNet;

namespace writeEvents
{
  class writeEvents
  {
    static ConsoleScreenBuffer sb;

    static void Main(string[] args)
    {
      sb = JConsole.GetActiveScreenBuffer();
      try
      {
        sb.WriteLine("Write events...");
        EventArgs[] ea = new EventArgs[13];
        ea[0] = new ConsoleWindowBufferSizeEventArgs(80, 100);
        ea[1] = MakeKeyEvent('H', ConsoleKey.H, 35, true);
        ea[2] = MakeKeyEvent('H', ConsoleKey.H, 35, false);
        ea[3] = MakeKeyEvent('e', ConsoleKey.E, 18, true);
        ea[4] = MakeKeyEvent('e', ConsoleKey.E, 18, false);
        ea[5] = MakeKeyEvent('l', ConsoleKey.L, 38, true);
        ea[6] = MakeKeyEvent('l', ConsoleKey.L, 38, false);
        ea[7] = MakeKeyEvent('l', ConsoleKey.L, 38, true);
        ea[8] = MakeKeyEvent('l', ConsoleKey.L, 38, false);
        ea[9] = MakeKeyEvent('o', ConsoleKey.O, 24, true);
        ea[10] = MakeKeyEvent('o', ConsoleKey.O, 24, false);
        ea[11] = MakeKeyEvent(Convert.ToChar(13), ConsoleKey.Enter, 28, true);
        ea[12] = MakeKeyEvent(Convert.ToChar(13), ConsoleKey.Enter, 28, false);
        using (ConsoleInputBuffer ib = JConsole.GetInputBuffer())
        {
          ib.WindowInput = true;
          ib.BufferSizeChange += new ConsoleBufferSizeEventHandler(ib_BufferSizeChange);
          ib.KeyDown += new ConsoleKeyEventHandler(ib_KeyDown);
          ib.KeyUp += new ConsoleKeyEventHandler(ib_KeyUp);
          ib.WriteEvents(ea);
          ib.ProcessEvents();
//          string s = ib.ReadLine();
//          sb.WriteLine(String.Format("You said '{0}'", s));
          sb.Write("Press any key to exit...");
          ib.ReadKey();
        }
      }
      finally
      {
        sb.Dispose();
      }
    }

    static ConsoleKeyEventArgs MakeKeyEvent(char keyChar, ConsoleKey key,
      int scanCode, bool keyDown)
    {
      ConsoleKeyEventArgs eKey = new ConsoleKeyEventArgs();
      eKey.KeyDown = keyDown;
      eKey.RepeatCount = 1;
      eKey.KeyChar = keyChar;
      eKey.Key = key;
      eKey.VirtualScanCode = scanCode;
      return eKey;
    }

    static void ib_KeyUp(object sender, ConsoleKeyEventArgs e)
    {
      sb.WriteLine(String.Format("KeyUp: {0}, {1}", e.Key, e.VirtualScanCode));
    }

    static void ib_KeyDown(object sender, ConsoleKeyEventArgs e)
    {
      sb.WriteLine(String.Format("KeyDown: '{0}' {1}", e.KeyChar, e.Key));
    }

    static void ib_BufferSizeChange(object sender, ConsoleWindowBufferSizeEventArgs e)
    {
      sb.WriteLine(String.Format("Buffer size change ({0},{1})", e.X, e.Y));
    }
  }
}

As presented here, the program processes the input events by displaying each individual event's detail. If you comment out the call to ProcessEvents, and uncomment the two lines below that read and display a string, you can see that keys you place in the input event queue will be read by the high-level input functions. In fact, you could replace the call to ib.ReadLine with a call to Console.ReadLine, and the program would work exactly the same.

Other Console Functions

There are a number of Console API functions that I did not cover in this series of articles. In particular, I did not discuss code pages at all, which you need to use if you want to create localized applications. In addition, I did not discuss console fonts because, although you can get information about the current console font, you can't change the font. Finally, I did not discuss console selection. You can find information about all of these topics in the Console SDK Reference.

While I was in the process of writing these three articles about the Windows Console API, Microsoft released preliminary documentation about several new console functions that will appear in Windows Vista. Among the more interesting functions are SetCurrentConsoleFontEx, which will allow you to set the console font, functions (SetConsoleHistoryInfo and GetConsoleHistoryInfo) that let you manipulate the history buffer, and some more convenient functions for getting and setting screen buffer information. I haven't tested any of these functions yet, as I've not had a chance to work with Windows Vista. When I do get an opportunity, I will add support for those new features to the ConsoleDotNet classes.

Better .NET Console Applications

I've shown that, although the .NET 2.0 Console class provides much better access to the Windows Console, it exposes only a small fraction of the capabilities available in the Windows Console API. By using the classes provided in the ConsoleDotNet namespace, you can allocate consoles from Windows Forms applications, share consoles among processes, create multiple screen buffers, and exercise very fine control over console input. With these capabilities, you can create character mode applications that are much richer than you can create with the .NET Console class alone.



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