An MSDN OnLine WinNT / WinXP Console converted to D example:
/+****************************************************************
* Program : winconsole.exe (a Windows' console get text example)
* Source : winconsole.d
* Author : David L. 'SpottedTiger' Davis
* Created Date : 29.Jul.04 Converted, Compiled and Tested with dmd v0.97
* Modified Date : 31.Jul.04 Minor changes.
* : 18.Jun.05 Compiled and Tested with dmd v0.127
* : 04.Jun.06 Compiled and Tested with dmd v0.160
* : 21.Jan.07 Compiled and Tested with dmd v1.0
* Requirements : std.c.windows.windows and std.c.windows.wincon
* License : Public Domain
* :
* Source From : MSDN OnLine Example: "Using the High-Level Input and Output Functions"
* : http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc
* : /base/using_the_high_level_input_and_output_functions.asp
*****************************************************************
*
* Note: wincon.d needs to be copied into C:\dmd\src\phobos\std\c\windows
*
* To Compiled: C:\dmd\MKOD_ex>dmd winconsole.d ..\src\phobos\std\c\windows\wincon.d
+/
private import std.c.windows.windows;
// Must copy from the site and place into the
// "C:\dmd\src\phobos\std\c\windows directory."
private import std.c.windows.wincon;
extern( Windows )
{
// -- WinBase.h --
enum : uint
{
STD_INPUT_HANDLE = -10,
STD_OUTPUT_HANDLE = -11,
STD_ERROR_HANDLE = -12
}
struct OVERLAPPED
{
DWORD Internal;
DWORD InternalHigh;
DWORD Offset;
DWORD OffsetHigh;
HANDLE hEvent;
};
alias OVERLAPPED *LPOVERLAPPED;
struct SECURITY_ATTRIBUTES
{
DWORD nLength;
LPVOID lpSecurityDescriptor;
BOOL bInheritHandle;
};
alias SECURITY_ATTRIBUTES *PSECURITY_ATTRIBUTES;
alias SECURITY_ATTRIBUTES *LPSECURITY_ATTRIBUTES;
HANDLE GetStdHandle
(
DWORD nStdHandle
);
BOOL SetStdHandle
(
DWORD nStdHandle,
HANDLE hHandle
);
BOOL WriteFile
(
HANDLE hFile,
LPCVOID lpBuffer,
DWORD nNumberOfBytesToWrite,
LPDWORD lpNumberOfBytesWritten,
LPOVERLAPPED lpOverlapped
);
BOOL ReadFile
(
HANDLE hFile,
LPVOID lpBuffer,
DWORD nNumberOfBytesToRead,
LPDWORD lpNumberOfBytesRead,
LPOVERLAPPED lpOverlapped
);
} // end extern( Windows )
HANDLE hStdout;
HANDLE hStdin;
CONSOLE_SCREEN_BUFFER_INFO csbiInfo;
int main()
{
char[] lpszPrompt1 = "Type a line and press Enter, or q to quit: ";
char[] lpszPrompt2 = "Type any key, or q to quit: ";
CHAR chBuffer[ 256 ];
DWORD cRead;
DWORD cWritten;
DWORD fdwMode;
DWORD fdwOldMode;
WORD wOldColorAttrs;
// Get handles to STDIN and STDOUT.
hStdin = GetStdHandle( STD_INPUT_HANDLE );
hStdout = GetStdHandle( STD_OUTPUT_HANDLE );
if ( hStdin == INVALID_HANDLE_VALUE || hStdout == INVALID_HANDLE_VALUE )
{
MessageBoxA( null, "GetStdHandle", "Console Error", MB_OK );
return 0;
}
// Save the current text colors.
if ( !GetConsoleScreenBufferInfo( hStdout, cast(PCONSOLE_SCREEN_BUFFER_INFO)&csbiInfo ) )
{
MessageBoxA( null, "GetConsoleScreenBufferInfo", "Console Error", MB_OK );
return 0;
}
wOldColorAttrs = csbiInfo.wAttributes;
// Set the text attributes to draw red text on black background.
if ( !SetConsoleTextAttribute( hStdout, FOREGROUND_RED | FOREGROUND_INTENSITY ) )
{
MessageBoxA( null, "SetConsoleTextAttribute", "Console Error", MB_OK );
return 0;
}
// Write to STDOUT and read from STDIN by using the default
// modes. Input is echoed automatically, and ReadFile
// does not return until a carriage return is typed.
//
// The default input modes are line, processed, and echo.
// The default output modes are processed and wrap at EOL.
while ( 1 )
{
if ( !WriteFile(
hStdout, // output handle
cast(LPCSTR)lpszPrompt1, // prompt string
cast(DWORD)lpszPrompt1.length, // string length
&cWritten, // bytes written
null ) ) // not overlapped
{
MessageBoxA( null, "WriteFile", "Console Error", MB_OK );
return 0;
}
if ( !ReadFile(
hStdin, // input handle
cast(void *)chBuffer, // buffer to read into
255, // size of buffer
&cRead, // actual bytes read
null ) ) // not overlapped
break;
if ( chBuffer[ 0 ] == 'q' ) break;
}
// Turn off the line input mode, and echo the input mode.
if ( !GetConsoleMode( hStdin, &fdwOldMode ) )
{
MessageBoxA( null, "GetConsoleMode", "Console Error", MB_OK );
return 0;
}
fdwMode = fdwOldMode &
~( ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT );
if ( !SetConsoleMode( hStdin, fdwMode ) )
{
MessageBoxA( null, "SetConsoleMode", "Console Error", MB_OK );
return 0;
}
// Without line and echo input modes, ReadFile returns
// when any input is available. Carriage returns must
// be handled, and WriteFile is used to echo input.
NewLine();
while ( 1 )
{
if ( !WriteFile(
hStdout, // output handle
cast(LPCSTR)lpszPrompt2, // prompt string
cast(DWORD)lpszPrompt2.length, // string length
&cWritten, // bytes written
null ) ) // not overlapped
{
MessageBoxA( null, "WriteFile", "Console Error", MB_OK );
return 0;
}
if ( !ReadFile( hStdin, cast(void *)chBuffer, 1, &cRead, null ) ) break;
if ( chBuffer[ 0 ] == '\r' )
NewLine();
else if ( !WriteFile( hStdout, cast(void *)chBuffer, cRead, &cWritten, null ) )
break;
else
NewLine();
if (chBuffer[ 0 ] == 'q' ) break;
}
// Restore the original console mode.
SetConsoleMode( hStdin, fdwOldMode );
// Restore the original text colors.
SetConsoleTextAttribute( hStdout, wOldColorAttrs );
return 0;
} // end int main()
// The NewLine function handles carriage returns when the processed
// input mode is disabled. It gets the current cursor position
// and resets it to the first cell of the next row.
void NewLine()
{
if ( !GetConsoleScreenBufferInfo( hStdout, cast(PCONSOLE_SCREEN_BUFFER_INFO)&csbiInfo ) )
{
MessageBoxA( null, "GetConsoleScreenBufferInfo", "Console Error", MB_OK );
return;
}
csbiInfo.dwCursorPosition.X = 0;
// If it is the last line in the screen buffer, scroll
// the buffer up.
if ( ( csbiInfo.dwSize.Y - 1 ) == csbiInfo.dwCursorPosition.Y )
{
ScrollScreenBuffer( hStdout, 1 );
}
// Otherwise, advance the cursor to the next line.
else csbiInfo.dwCursorPosition.Y += 1;
if ( !SetConsoleCursorPosition( hStdout, csbiInfo.dwCursorPosition ) )
{
MessageBoxA( null, "SetConsoleCursorPosition", "Console Error", MB_OK );
return;
}
} // end void NewLine()
void ScrollScreenBuffer
(
in HANDLE h,
in INT x
)
{
SMALL_RECT srctScrollRect;
SMALL_RECT srctClipRect;
CHAR_INFO chiFill;
COORD coordDest;
srctScrollRect.Left = 0;
srctScrollRect.Top = 1;
srctScrollRect.Right = csbiInfo.dwSize.X - x;
srctScrollRect.Bottom = csbiInfo.dwSize.Y - x;
// The destination for the scroll rectangle is one row up.
coordDest.X = 0;
coordDest.Y = 0;
// The clipping rectangle is the same as the scrolling rectangle.
// The destination row is left unchanged.
srctClipRect = srctScrollRect;
// Set the fill character and attributes.
chiFill.Attributes = FOREGROUND_RED | FOREGROUND_INTENSITY;
chiFill.Char.AsciiChar = cast(char)' ';
// Scroll up one line.
ScrollConsoleScreenBufferA(
h, // screen buffer handle
&srctScrollRect, // scrolling rectangle
&srctClipRect, // clipping rectangle
coordDest, // top left destination cell
&chiFill ); // fill character and color
} // end void ScrollScreenBuffer( in HANDLE, in INT )
Example output:
C:\dmd\MKoD_ex>bin\dmd winconsole.d
C:\dmd\bin\..\..\dm\bin\link.exe winconsole,,,user32+kernel32/noi;
C:\dmd\MKoD_ex>winconsole
Type a line and press Enter, or q to quit: Prompt is now waiting for my input.
Type a line and press Enter, or q to quit: Every character is typing in as RED. :)
Type a line and press Enter, or q to quit: q = Quit
Type any key, or q to quit: q
C:\dmd\MKoD_ex>