I am designing a user interface for another program I am writing. This interface displays blanks on the screen for name, address ect... and lets the user tab through the blanks and enter information (well, right now you just hit enter to tab through). If the user hits 'F8' then whatever was typed in is saved to a vector, and if the user hits 'F3' then the program displays the contents of the vector and exits. While the user is typing in information, if the cursor reaches the end of the field (20 spaces long on each one) then the cursor moves down to the next field. Along the same concept, if the user backspaces, characters will be erased until the begining of the field is reached and will go no further. I use another vector to hold the start and end coordinates for each field and as the user enters each character the current cursor position is checked against what is in the vector to determine what to do. What I have works well but I was wondering if there was a better way to do it.
Code:
#include <iostream>
#include <windows.h>
#include <vector>
#include <conio.h>
using namespace std;
struct Screen_Locations {
int position, X1, X2, Y;
};
struct Names {
string name, address, city, state;
};
void save(Names& names);
string Read_Cursor(int x, int y, int z);
static int get_code() {
int ch = getch();
if (ch == 0 || ch == 224)
ch = 256 + getch();
return ch;
}
enum { // system dependent key codes
ENTER = 13,
BACKSPACE = 8,
F_3 = 317,
F_8 = 322
};
int main() {
Screen_Locations locations;
vector<Screen_Locations> location_list;
// Load location_vector with screen coordinates for the fields
for (int x = 0; x <= 3; x++) {
locations.position = x;
locations.X1 = 12; // start position of x coor
locations.X2 = 32; // end position of x coor
locations.Y = (x + x); // start position of y coor
location_list.push_back(locations);
}
vector<Screen_Locations>::const_iterator pos_iter;
Names names;
vector<Names> name_list; // all names are saved in this vector
COORD Position;
DWORD NumRead;
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
bool loop = true; // control for the do..while loop
int pos; // variable to keep track of which field the cursor is on
char ch;
wchar_t wch;
do {
system("cls");
cout<<"Name : [ ]\n\n"
<<"Address : [ ]\n\n"
<<"City : [ ]\n\n"
<<"State : [ ]\n\n"
<<"<F8> to save, <F3> to exit" <<endl;
// set cursor to first character of the first field
pos_iter = location_list.begin();
Position.X = pos_iter->X1; Position.Y = pos_iter->Y;
SetConsoleCursorPosition(hOut, Position);
while (wch = get_code() ) {
if (wch == F_3) { // exit the loop and display the names vector
loop = false;
break;
}
else if (wch == F_8) { // save fields to the names vector
save(names);
name_list.push_back(names);
break;
}
// if user hits the backspace key, go back one character unless
// the cursor is allready at the first character
else if (wch == BACKSPACE) {
if (Position.X != pos_iter->X1) {
Position.X--;
cout<<"\b \b";
}
}
// if user hits the enter key, move to the next field or back
// to the first field if the cursor is in the last field allready
else if (wch == ENTER) {
if (pos == 3)
pos = 0;
else
pos++;
pos_iter = location_list.begin() + pos;
Position.X = pos_iter->X1;
Position.Y = pos_iter->Y;
SetConsoleCursorPosition(hOut, Position);
}
// if the user enters a character, display that character
// if the cursor is on the last character of the field then
// move to the first character of the next field
if (wch >= 32 && wch <= 126) {
ch = wch;
cout<<ch;
Position.X++;
if (Position.X == pos_iter->X2) {
pos_iter++;
if (pos_iter == location_list.end() )
pos_iter = location_list.begin();
Position.X = pos_iter->X1; Position.Y = pos_iter->Y;
SetConsoleCursorPosition(hOut, Position);
}
}
}
}
while (loop);
// clear the screen and display the contents of the names vector
system("cls");
vector<Names>::iterator iter;
for (iter = name_list.begin(); iter != name_list.end(); ++iter)
cout<<iter->name <<iter->address <<iter->city <<iter->state <<endl;
cin.get();
return 0;
}
// read the contents of a field and return a string
string Read_Cursor(int x, int y, int z) {
COORD Position;
DWORD NumRead;
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
Position.X = x;
Position.Y = y;
char tempchar[z+1];
ReadConsoleOutputCharacter(hOut, tempchar, z, Position, &NumRead);
string tempstring = tempchar;
return tempstring.assign(tempstring, 0, z);
}
// save the fields to the names vector
void save(Names& names) {
names.name = Read_Cursor(12, 0, 20);
names.address = Read_Cursor(12, 2, 20);
names.city = Read_Cursor(12, 4, 20);
names.state = Read_Cursor(12, 6, 20);
return;
}
BTW, I know that using system commands is not exactly portable, but I am just getting the design aspect right now. I'll go back after and and figure something else out for that.
Thanx!