#include <iostream>
#include <windows.h>
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <string>
#define BUFFERSIZE 80 * 25
using namespace std;
/**
* Improved scrolly routine! Uses 80 columns by 25 rows
* in a Windows console, written in Code::Blocks, tested
* on Windows 7 Professional SP1
*
* @Author: Shaun B
* @Version: 1.0.0.2 - 2012-09-05
*
**/
int main();
void ClrScr (short, short, short, short, signed char, char);
void Print (short, short, signed char, char *, ...);
void hideCursor();
void scroll();
void exchangeToDisplay();
static unsigned short counter;
static unsigned short i;
static char Erase[BUFFERSIZE];
// Sets variables for:
// Scrolly message -
static char scrolly [] = "....................This is a scrolly text....................Nah nah nah nah nahhhh....................Like a BAWS....................#\0";
// Display string -
static char display [80];
// Keyboard input -
static char character;
// Running boolean -
static char run = 1;
// Sleep time -
static signed int sleep = 100;
// Char buffer for scroll function -
static char buffer[1];
static HANDLE hStdout, hNewScreenBuffer;
static SMALL_RECT srctReadRect;
static SMALL_RECT srctWriteRect;
static CHAR_INFO chiBuffer[BUFFERSIZE];
static COORD coordBufSize = {0};
static COORD coordBufCoord = {0};
static BOOL fSuccess;
static va_list List;
static unsigned short FormattedStringLength;
int main ()
{
// Sets default console size, colours and title:
system("mode CON: COLS=80 LINES=25");
system("title Scrolly started at %TIME% on %DATE%");
// Switches off blinking cursor:
SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), ENABLE_INSERT_MODE);
hideCursor();
// Clears screen from x, y to x1, y1, setting default colours and sending a space
ClrScr (0, 0, 25, 80, 0x12, 32);
// Sets up display string:
exchangeToDisplay();
// Main loop:
while(run)
{
// Printing the display string at 0, 0 with colours E and 3
Print (0, 0, 0xe3, display);
// Does the same for the bottom row of the console:
Print (24, 0, 0x90, display);
if (_kbhit())
{
character=_getch();
}
// Checks for space...
if(character==32)
{
// If so, stops main loop:
run=0;
}
// Checks for left arrow and arrow down...
if((character==75 || character==80) && sleep<255)
{
// Increases sleep call (higher is slower):
sleep+=10;
}
// Checks for other arrow keys...
if((character==72 || character==77) && sleep>0)
{
// Decreases sleep call:
sleep-=10;
}
// Clears character buffer if set:
if(character)
{
character=0;
}
// Checks if time exceeds longest sleep time:
if(sleep>254)
{
sleep=255;
}
// Checks if time exceeds shortest sleep time:
if(sleep<1)
{
sleep=0;
}
// Calls scroll function:
scroll();
// Calls sleep function:
Sleep(sleep+1);
}
system("cls");
std::cout<<"Goodbye!"<<endl;
// Returns when loop is exited:
return 0;
}
void ClrScr (short x, short y, short NoOfLines, short EraseLength, signed char EraseColor, char ErasePattern)
{
//Erase[BUFFERSIZE] = {0};
counter = NoOfLines * EraseLength;
for (i = 0; i < counter; i++)
{
Erase[i] = ErasePattern;
}
// Adds terminator (just in case)
if(Erase[i]!='\0')
{
Erase[i] = '\0';
}
Print (x, y, EraseColor, Erase);
}
void Print (short x, short y, signed char Color, char *String, ...)
{
FormattedStringLength = 0;
char FormattedString[BUFFERSIZE] = {0};
counter = 0;
unsigned char bottom = 0;
hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
hNewScreenBuffer = CreateConsoleScreenBuffer(
GENERIC_READ | // read/write access
GENERIC_WRITE,
0, // not shared
NULL, // no security attributes
CONSOLE_TEXTMODE_BUFFER, // must be TEXTMODE
NULL); // reserved; must be NULL
va_start (List, String);
vsprintf (FormattedString, String, List);
FormattedStringLength = (unsigned short) strlen (FormattedString);
while(counter<FormattedStringLength)
{
counter++;
if(counter%80==0)
{
bottom++;
}
}
va_end (List);
// Make the new screen buffer the active screen buffer.
// Set the source rectangle.
srctReadRect.Top = x;
srctReadRect.Left = y;
srctReadRect.Bottom = bottom;
srctReadRect.Right = 80;
// The temporary buffer size is 25 rows x 80 columns.
coordBufSize.Y = bottom;
coordBufSize.X = 80;
// The top left destination cell of the temporary buffer is
// row 0, col 0.
coordBufCoord.X = 0;
coordBufCoord.Y = 0;
// Copy the block from the screen buffer to the temp. buffer.
fSuccess = ReadConsoleOutput(
hStdout, // screen buffer to read from
chiBuffer, // buffer to copy into
coordBufSize, // col-row size of chiBuffer
coordBufCoord, // top left dest. cell in chiBuffer
&srctReadRect); // screen buffer source rectangle
// Set the destination rectangle.
srctWriteRect.Top = x;
srctWriteRect.Left = y;
srctWriteRect.Bottom = 25;
srctWriteRect.Right = 80;
// Gets buffer information:
for (i = 0; i < BUFFERSIZE; i++)
{
chiBuffer[i].Attributes = Color;
chiBuffer[i].Char.AsciiChar = FormattedString[i];
}
// Copy from the temporary buffer to the new screen buffer.
WriteConsoleOutput(
hStdout, // screen buffer to write to
chiBuffer, // buffer to copy from
coordBufSize, // col-row size of chiBuffer
coordBufCoord, // top left src cell in chiBuffer
&srctWriteRect); // dest. screen buffer rectangle
}
// Turns off blinking cursor:
void hideCursor()
{
CONSOLE_CURSOR_INFO lpCursor;
lpCursor.bVisible = 0;
lpCursor.dwSize = 20;
SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE),&lpCursor);
}
void scroll()
{
// Sets counter to zero:
counter=0;
// The buffer will preserve the first char otherwise the
// scrolling won't wrap around:
buffer[0]=scrolly[counter];
// Loop will happen whilst the terminator hasn't been reached:
while(scrolly[counter]!='#')
{
// Moves each character one element to the left:
scrolly[counter]=scrolly[counter+1];
// Increase our counter
counter++;
}
// Puts the old first character from the start to the end so
// it wraps around:
scrolly[counter-1]=buffer[0];
// Checks to see if the terminator has been over-written, if not
// then it's restored:
if(scrolly[counter]!='#')
{
scrolly[counter]='#';
}
exchangeToDisplay();
}
void exchangeToDisplay()
{
// Writes the first 80 characters of our [shuffled] scrolly text
// to our display string:
for(counter=0; counter<80;counter++)
{
display[counter] = scrolly[counter];
}
}