Sign in to follow this  

a text based window

This topic is 4746 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I'm trying to make a text based window like this in the dos console with C++ :
* * * Titel * * * 
*               *
*               *
* * * * * * * * *

but for the moment all I can come up with is
* * * * * * * * * 
*               *
*               *
* * * * * * * * *

I can't seem to find a good algoritme to create that first line with a text centered in it. The main problem for now is that I create the width with "* ". Does any1 have any tips, or maybe links? thanx in advance...

Share this post


Link to post
Share on other sites
I dont know how you are doing your drawing, but Consider what you know.
-The width of the window
-The number of characters in the title, strlen()

The distance between the title and the edge is:
((float)width-strlen("title"))/2
Since your corners are always '*', subtract one:
(((float)width-strlen("title"))/2f)-1
This is the length between the corner and the title, exclusive.
Divide by two again to see how many "* " pairs you need on each side of your title:
((((float)width-strlen("title"))/2f)-1)/2
(Should be right, but I didnt have a chance to test it)
I'm sure you'll have to play around with it, but it should get you off on the right start.

It really depends on how you draw your windows. Are all the windows drawn seperately or do you just store the whole screen in an array?

I think the best way for you do it is to write a line drawing algorithm.
Something like drawline(int x1, int y1, int x2, int z2, char* pattern)
Ex: drawline(30, 20, 40, 50, "* ")

This way you can draw anyline you wish with any pattern you wish.
Look into line drawing algorithms, Bresenham seems to be a popular one. You could easily adapt it to display any pattern you'ld like.

Have fun and good luck.

Share this post


Link to post
Share on other sites
This should do what you want:


#include <iostream>
#include <string>

const int width = 40;
const char chars[2] = {'*', ' '};

void DrawTopLine(const std::string& txt)
{
int txtleft = width/2 - txt.length()/2;
int txtright = width/2 + txt.length()/2;
for (int current=0; current<width; current++)
{
if (current<txtleft || current>txtright) std::cout << chars[current&1];
else std::cout << txt.substr(current-txtleft, 1);
}
}

int main()
{
DrawTopLine("Hello, world!");
return 0;
}


Share this post


Link to post
Share on other sites
[EDIT] I swear no one had posted when i began typing this! [embarrass][/EDIT]

Let's say you have 1 space after each *, as you said

On the first line you will have text that is supposed to be -cenetered-, but you need to figure out how many *'s you wanted on each side.

Lets say you wanted only 3 per side, as the example has it

Now for any text, lets say we had "Gamedev.net".

If you were to make a string such that:
"* * * GameDev.net * * *" was stored,
"* * * " + "GameDev.net" + "* * * ", you could the copy the string and write a for loop, so it would replace all even based indexes (since it starts at 0) with an *, so you would be left with:
"* * * *a*e*e*.*e* * * *"

Now you need to loop through each odd based index and make it a " ", so you would be left with:
"* * * * * * * * * * * *"

Now that you had the top and bottom, you would just need to draw in the sides (before the bottom tohugh), which you just use 0 and the sizeof the string: "* * * * * * * * * * * *"

After everything, you would have:

* * * GameDev.net * * *
* *
* *
* *
* * * * * * * * * * * *

Here there code of my concepts:

// However many you want
char ends[] = "* * * * *";
// Text you want to display
char text[] = "A B C D E F G H I J K L M N O P Q R S T";
// Rows you want
int rowcount = 5;
// Variables we will use
char TitleRow[256];
char RegRow[256];
char FinalRow[256];

// clear out the string
memset(TitleRow,' ',256);
// Format the string
sprintf(TitleRow,"%s %s %s",ends,text,ends);

// clear out the string
memset(RegRow,' ',256);
// set start row *
RegRow[0] = '*';
// set end row *
RegRow[ strlen(TitleRow) - 1 ] = '*';
// cut off the string
RegRow[ strlen(TitleRow) ] = 0;

// clear out the string
memset(FinalRow,' ',256);
for(int x=0;x< strlen(TitleRow) ;x++)
{
if(x==0 || x%2 == 0) // even
FinalRow[x] = '*';
else
FinalRow[x] = ' ';
}
// cut off the string
FinalRow[x] = 0;

// Print the title row
cout << TitleRow << endl;
for(x=0;x<rowcount;x++)
{
// Print the rows
cout << RegRow << endl;
}
// Print the last row
cout << FinalRow << endl;




Tell me how it works for you, I designed it in my head and gave it a quick test, and it worked fine. It is very inefficient and bad use of C++ standards, I mixed C/C++ together like crazy [lol], but since you are just making a dos console program, it sohuld be ok. Good luck!

Share this post


Link to post
Share on other sites
thx for the help guys, I think I will use prototype's solution (just changing it a bit)
But there is 1 line that I don't completely understand in prototype's solution :

std::cout << chars[current&1];

why is "&1" in there?

Share this post


Link to post
Share on other sites
The '&1' is a simple trick to make a toggling value out of a counter.
So the value of 'current' is ANDed with 1, which results in either 0 or 1. This is used as an index in chars[] to get the next character to draw.
Hope you get it, I'm not very good at explaining. :)


const char chars[2] = {'*', ' '};
std::cout << chars[current&1]; // result in either '*' or ' '


Share this post


Link to post
Share on other sites
I'm using visual c++ at home and your code gives me alot of errors, where at work I use dev cpp and there it compiles right, what is wrong?

error C2143: syntax error : missing ',' before '&'
error C2059: syntax error : '&'
error C2065: 'width' : undeclared identifier
error C2065: 'txt' : undeclared identifier
error C2228: left of '.length' must have class/struct/union type
error C2228: left of '.length' must have class/struct/union type
error C2228: left of '.substr' must have class/struct/union type
error C2660: 'DrawTopLine' : function does not take 2 parameters
Error executing cl.exe.

titel.exe - 8 error(s), 0 warning(s)

Share this post


Link to post
Share on other sites
thats a fast answer :D

yes I copied it exactly
I don't understand it either
it's like he doesn't understand the c++ version of the string library

edit : I changed my code so now it works, but I don't use the "* " anymore, just 1 "*"

and to find the length of my string I use strlen().
but there is still a bug in there :(

when I get my string I use

cin >> string ;

but it seems that cin doesn't accept spaces?!?




[Edited by - da_cobra on December 15, 2004 1:18:06 PM]

Share this post


Link to post
Share on other sites

This topic is 4746 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this