#include <windows.h> /* for HANDLE type, and console functions */
#include <stdio.h> /* standard input/output */
#include <stdlib.h> /* included for rand */
#include <time.h> /* For randomization seed */
#include "redRectangle.h" /* our image file */
#define WIDTH 70
#define HEIGHT 35
#define YES 1
#define NO 0
#define VK_C 0x43 /* virtual key C definition */
HANDLE wHnd; /* write (output) handle */
HANDLE rHnd; /* read (input handle */
/* Ensure that you do not index outside of the console sceen buffer! */
boundCheck(int *x, int *y)
{
if (*x < 0)
{
*x = 0;
}
if (*x > WIDTH - 3)
{
*x = WIDTH - 3;
}
if (*y < 0)
{
*y = 0;
}
if (*y > HEIGHT - 3)
{
*y = HEIGHT - 3;
}
}
/* Writes an image to the buffer */
void writeImageToBuffer(CHAR_INFO buffer[], int chars[], int colors[], int imageWidth, int imageHeight, int xoffset, int yoffset)
{
int x, y;
/* Keep xoffset and yoffset within the screen's boundaries */
boundCheck(&xoffset, &yoffset);
for (y = 0; y < imageHeight; ++y)
{
for (x = 0; x < imageWidth; ++x)
{
buffer[(x + xoffset) + WIDTH * (y + yoffset)].Char.AsciiChar = chars[x + imageWidth * y];
buffer[(x + xoffset) + WIDTH * (y + yoffset)].Attributes = colors[x + imageWidth * y];
}
}
return;
}
writeCircleToBuffer(CHAR_INFO buf[], int xoffset, int yoffset)
{
/* Keep xoffset and yoffset within the screen's boundaries */
boundCheck(&xoffset, &yoffset);
buf[xoffset + (WIDTH * yoffset)].Char.AsciiChar = (unsigned char)7;
buf[xoffset + (WIDTH * yoffset)].Attributes = BACKGROUND_BLUE |
BACKGROUND_RED |
BACKGROUND_GREEN |
BACKGROUND_INTENSITY |
FOREGROUND_RED;
}
/* Read console input buffer and return malloc'd INPUT_RECORD array */
DWORD getInput(INPUT_RECORD **eventBuffer)
{
/* Variable for holding the number of current events, and a point to it */
DWORD numEvents = 0;
/* Variable for holding how many events were read */
DWORD numEventsRead = 0;
/* Put the number of console input events into numEvents */
GetNumberOfConsoleInputEvents(rHnd, &numEvents);
if (numEvents) /* if there's an event */
{
/* Allocate the correct amount of memory to store the events */
*eventBuffer = malloc(sizeof(INPUT_RECORD) * numEvents);
/* Place the stored events into the eventBuffer pointer */
ReadConsoleInput(rHnd, *eventBuffer, numEvents, &numEventsRead);
}
/* Return the amount of events successfully read */
return numEventsRead;
}
int main(void)
{
int j, offsetx, offsety;
int write = NO;
/* Used for indexing the eventBuffer */
DWORD i;
srand(time(0));
/* Window size coordinates, be sure to start index at zero! */
SMALL_RECT windowSize = {0, 0, WIDTH - 1, HEIGHT - 1};
/* A COORD struct for specificying the console's screen buffer dimensions */
COORD bufferSize = {WIDTH, HEIGHT};
/* Setting up different variables for passing to WriteConsoleOutput */
COORD characterBufferSize = {WIDTH, HEIGHT};
COORD characterPosition = {0, 0};
SMALL_RECT consoleWriteArea = {0, 0, WIDTH - 1, HEIGHT - 1};
/* A CHAR_INFO structure containing data about an array of characters + colors */
CHAR_INFO consoleBuffer[WIDTH * HEIGHT];
/* A pointer to type INPUT_RECORD, used to point to a buffer of INPUT_RECORD structs */
INPUT_RECORD *eventBuffer;
/* Variable for holding how many events were read */
DWORD numEventsRead = 0;
/* initialize handles */
wHnd = GetStdHandle(STD_OUTPUT_HANDLE);
rHnd = GetStdHandle(STD_INPUT_HANDLE);
/* Set the console's title */
SetConsoleTitle("Our shiny new title!");
/* Set the window size */
SetConsoleWindowInfo(wHnd, TRUE, &windowSize);
/* Set the screen's buffer size */
SetConsoleScreenBufferSize(wHnd, bufferSize);
for (j = 0; j < (WIDTH * HEIGHT); j++)
{
consoleBuffer[j].Char.AsciiChar = ' ';
consoleBuffer[j].Attributes =
BACKGROUND_BLUE |
BACKGROUND_GREEN |
BACKGROUND_RED |
BACKGROUND_INTENSITY;
}
write = YES;
while(1)
{
/* Get the input and number of events successfully obtained */
numEventsRead = getInput(&eventBuffer);
/* if more than 0 are read */
if (numEventsRead)
{
/* loop through the amount of records */
for (i = 0; i < numEventsRead; i++)
{
/* check each event */
switch (eventBuffer[i].EventType)
{
/* if type of event is a KEY_EVENT */
case KEY_EVENT:
switch (eventBuffer[i].Event.KeyEvent.wVirtualKeyCode)
{
/* if escape key is pressed*/
case VK_ESCAPE:
return 0;
/* If C key is pressed, define at top of file */
case VK_C:
/* If keypress was a keydown event, not keyup */
if (eventBuffer[i].Event.KeyEvent.bKeyDown == 0)
{
for (j = 0; j < WIDTH * HEIGHT; j++)
{
consoleBuffer[j].Char.AsciiChar = ' ';
consoleBuffer[j].Attributes =
BACKGROUND_BLUE |
BACKGROUND_GREEN |
BACKGROUND_RED |
BACKGROUND_INTENSITY;
}
/* Update screen this loop pass */
write = YES;
}
break;
}
break;
case MOUSE_EVENT:
offsetx = eventBuffer[i].Event.MouseEvent.dwMousePosition.X;
offsety = eventBuffer[i].Event.MouseEvent.dwMousePosition.Y;
if (eventBuffer[i].Event.MouseEvent.dwButtonState == FROM_LEFT_1ST_BUTTON_PRESSED)
{
writeImageToBuffer(consoleBuffer, REDRECTANGLE.chars, REDRECTANGLE.colors, REDRECTANGLE.width, REDRECTANGLE.height, offsetx - 1, offsety - 1);
/* Update screen this loop pass */
write = YES;
}
else if (eventBuffer[i].Event.MouseEvent.dwButtonState == RIGHTMOST_BUTTON_PRESSED)
{
writeCircleToBuffer(consoleBuffer, offsetx, offsety);
/* Update screen this loop pass */
write = YES;
}
break;
}
}
/* Delete your used INPUT_RECORD array */
free(eventBuffer);
}
/* If write is 1, meaning the screen needs to be updated */
if (write)
{
/* Write our character buffer (a single dimensional array) to the console buffer */
WriteConsoleOutputA(wHnd, consoleBuffer, characterBufferSize, characterPosition, &consoleWriteArea);
write = NO;
}
}
}