    <rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:admin="http://webns.net/mvcb/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:content="http://purl.org/rss/1.0/modules/content/">
     <channel>
        <title>ACCU  :: Handling the Windows Console</title>
        <link>https://members.accu.org/index.php/articles/889</link>
        <description>Professionalism in Programming</description>
        <dc:language>en-us</dc:language> 
        <dc:creator>Administrator</dc:creator> 
        <admin:generatorAgent rdf:resource="http://www.xaraya.org" /> 
        <admin:errorReportsTo rdf:resource="mailto:webeditor@accu.org" />
       <sy:updatePeriod>hourly</sy:updatePeriod>
       <sy:updateFrequency>1</sy:updateFrequency>
       <docs>http://backend.userland.com/rss</docs>




<div class="xar-mod-head"><span class="xar-mod-title">CVu Journal Vol 11, #4 - Jun 1999</span></div>

<table border="0" cellpadding="1" cellspacing="0">
    <tbody>
    <tr>
        <td valign="top">
            Browse in :
       </td>
       <td valign="top">

                                            <a href="https://members.accu.org/index.php/articles/">All</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c76/">Journals</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c77/">CVu</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c131/">114</a>
<br />
</td>
   </tr>
   </tbody>
</table>




<div class="xar-error">
   <p>
 <strong>Note:</strong> when you create a new publication type,
the articles module will automatically use the templates
<em>user-display-[publicationtype].xt</em>
and <em>user-summary-[publicationtype].xt</em>.
If those templates do not exist when you try to preview or display a new article,
you'll get this warning :-)  Please place your own templates in themes/<em>yourtheme</em>/modules/articles . The templates will get the extension .xt there. </p>
</div>
<div class="xar-norm xar-standard-box-padding">
   <h1><strong>Title:</strong>&nbsp;Handling the Windows Console</h1>
<p><strong>Author:</strong>&nbsp;</p>
<p>
<strong>Date:</strong> 03 June 1999 13:15:31 +01:00 or Thu, 03 June 1999 13:15:31 +01:00</p>
<p><strong>Summary:</strong>&nbsp;</p>
<p><strong>Body:</strong>&nbsp;<div class="article" lang="en">
<div class="titlepage">
<div>
<div>
<h2><a name="d0e1" id="d0e1"></a>Handling the Windows
Console</h2>
</div>
<div class="author">
<h3><span class="firstname">Nigel</span>
<span class="surname">Thornton-Clark</span></h3>
<tt class="email">&lt;<a href=
"mailto:nigeltc@inchbrook.demon.co.uk">nigeltc@inchbrook.demon.co.uk</a>&gt;</tt></div>
</div>
<hr></div>
<div class="section" lang="en">
<div class="titlepage">
<h2><a name="d0e20" id="d0e20"></a></h2>
</div>
<p>When I first loaded Microsoft Visual C++ 5.0 onto my PC, I was
rather shocked to discover that none of my old text mode programs
would compile. The reason being that the <tt class=
"function">int86()</tt> library call had disappeared completely and
none of the simple screen handling these programs had inherited
from their DOS roots would work. After several days of muttering
under my breath about backward compatibility, I dug through the
sample code and the header files and discovered that there is still
a way to manipulate the DOS box, or console as we are encouraged to
call it these days. The API is neither well-documented nor easy to
use but at least it works.</p>
<p>The key to the console API is the header file <tt class=
"filename">wincon.h</tt> which contains the usual structure
definitions and prototypes. Before you can do anything, you need to
get handles for the console using <tt class=
"function">GetStdHandle()</tt>:</p>
<pre class="programlisting">
  conOut = GetStdHandle(STD_OUTPUT_HANDLE);
  conIn = GetStdHandle(STD_INPUT_HANDLE);
</pre>
<p>Once you have the handles, it is a good idea to turn off various
input options to prevent the console from echoing characters or
waiting until the user hits the Enter key:</p>
<pre class="programlisting">
  DWORD modeIn;
  GetConsoleMode( conIn, &amp;modeIn );
  modeIn = modeIn &amp; ~(ENABLE_LINE_INPUT|ENABLE_ECHO_INPUT);
  SetConsoleMode( conIn, modeIn );
</pre>
<p>After the console has been configured, you can write characters
and attributes to the console using the functions <tt class=
"function">WriteConsoleOutputCharacter()</tt> and <tt class=
"function">WriteConsoleOutputAttribute()</tt> as the following code
illustrates:</p>
<pre class="programlisting">
  void ScrWriteString( int row, int col, char* text, WORD attr )  {
  COORD pos;
  pos.X = (SHORT)col;
  pos.Y = (SHORT)row;

  DWORD nChars;
  WriteConsoleOutputCharacter( conOut, text, strlen(text), pos, &amp;nChars );

  WORD* attrs = (WORD*)malloc( sizeof(WORD) * strlen(text) );
  if ( attrs ) {
    for( size_t i=0; i&lt;strlen(text); i++ )  attrs[i] = attr;
    WriteConsoleOutputAttribute( conOut, attrs, strlen(text), pos, &amp;nChars );
    free( attrs );
    }

  return;
  }
</pre>
<p>As you can see, both functions take a start position encoded as
a <span class="structname">COORD</span> structure and a length
parameter to indicate how many characters or attributes to write.
They also return the number of characters or attributes actually
written. The most counterintuitive part of the process is that
characters and attributes are treated separately which seems very
strange to someone who is used to packing a character and an
attribute into a 16-bit word. The attributes themselves consist of
foreground and background colours ORed together so, for instance,
<tt class="constant">FOREGROUND_RED</tt>|<tt class=
"constant">BACKGROUND_BLUE</tt> specifies red text on a blue
background.</p>
<p>If you are used to programming in an event driven environment,
console programming will feel strange because there is no message
queue. You have to go and grab the events you want. The code to
read keystrokes from the console looks something like this:</p>
<pre class="programlisting">
  WORD ScrGetKey( WORD&amp; key )   {
  INPUT_RECORD inputBuffer;
  DWORD nEvents;

  // Wait for the key to be released 
  do   {
    // Read input events until we get a key
    ReadConsoleInput( conIn, &amp;inputBuffer, 1, &amp;nEvents );
    if ( inputBuffer.EventType == KEY_EVENT ) key = inputBuffer.Event.KeyEvent.wVirtualKeyCode;
  } while( !((inputBuffer.EventType == KEY_EVENT ) &amp;&amp; 
                                          (inputBuffer.Event.KeyEvent.bKeyDown == FALSE)) );

  return( key );
  }
</pre>
<p>The <span class="structname">KeyEvent</span> structure also
returns information about the actual character read but this
handled differently in Windows 95, which returns an 8-bit ASCII
character, and Windows NT, which returns a Unicode character.</p>
<p>Because <tt class="function">ReadConsoleInput()</tt> returns raw
keyboard events, I find it best to catch keystrokes when the key is
released <tt class="literal">(bKeyDown == FALSE)</tt> otherwise you
can get a lot of spurious keystrokes if the user holds down a key.
The keystrokes returned are the standard, Windows virtual key codes
such as <tt class="constant">VK_ESCAPE</tt> and <tt class=
"constant">VK_LEFT</tt>.</p>
<p><tt class="function">ReadConsoleInput()</tt> can also be used to
read mouse events and a number of window-related events but, if you
need to use these, you would probably end up having to hand-code a
complete message queue. At this point, you'd be better off writing
a full-blown Windows application.</p>
<p>The cursor size and visibility can be set using a <span class=
"structname">CONSOLE_CURSOR_INFO</span> structure and the
<tt class="function">SetConsoleCursorInfo()</tt> function. The
cursor position can be set using <tt class=
"function">SetConsoleCursorPosition()</tt>:</p>
<pre class="programlisting">
  void ScrMove( int row, int col )  {
  COORD position;

  position.X = (SHORT)col;
  position.Y = (SHORT)row;
  SetConsoleCursorPosition( conOut, position );

  return;
  }
</pre>
<p>There are also functions to set the console's title, to set a
control-C handler, and even to set a code-page for the console.</p>
<p>As you can see, it is possible to manipulate the Windows console
in much the same way as the old DOS screen; it's just that the
interface has changed rather radically. At first this annoyed me
but then I realised that it was probably a result of insulating the
programmer from the hardware interrupts which is a sensible
precaution given the complexity of the Windows environment.</p>
</div>
</p>
<p><strong>Notes:</strong>&nbsp;</p>
<p><em>More fields may be available via dynamicdata ..</em></p>
</div>
</channel>
</rss>
