• 13
• 18
• 19
• 27
• 10

# Displaying Text Problem

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

## Recommended Posts

Hi, I'm using windows gdi. At the moment, I'm using an edit control to display text messages between two people. The problem is I want to display a person's name followed by a colon with some color and then display the following text message with another color. But I can not do this with the below code because I set the text of an edit control all at once and I can't find some function just to append text. Aside from creating my own custom edit control, is there an easier way to do this? Thanks.
void PrintMessage(char* msg, char* name)
{
//hold message and name lengths
int msg_len = strlen(msg);
int name_len = strlen(name);

if (msg_len > 0)
{
//get text length of edit control
int edit_len = GetWindowTextLength(hEditChat);

//sum up name, message, and edit control string lengths
int total_len = name_len + edit_len + msg_len;

//allocate enough memory to hold the message plus what is already
//in the edit control
char* buf = new char[total_len + 6];

//check to see if allocation was successful
if (buf == 0) {
MessageBox(hWnd, "new Failed!", "Error", MB_ICONERROR);
return;
}

//initialize the buffer to zeros
ZeroMemory(buf, total_len + 6);

if (edit_len > 0)  //first message?
{
//get the text from edit control
SendMessage(hEditChat, WM_GETTEXT, total_len + 6, (long) buf);

//concatenate a newline, player's name, and the message
strncat(buf, "\r\n", 2);
//SendMessage(hEditChat, WM_SETTEXT, NULL, (long) buf);
strncat(buf, name, name_len);
strncat(buf, ":  ", 3);
strncat(buf, msg, msg_len);
}
else  //not first message
{
//concatenate player's name and the message
strncat(buf, name, name_len);
strncat(buf, ":  ", 3);
strncat(buf, msg, msg_len);
}

//set the new text
SendMessage(hEditChat, WM_SETTEXT, NULL, (long) buf);

//scroll to the bottom of chat edit control
SendMessage (hEditChat, EM_SCROLL, SB_BOTTOM, 0) ;

//free up the buffer
delete [] buf;
}
}


##### Share on other sites
Why aren't you using std::string?

##### Share on other sites
Quote:
 Original post by GosuDrewThe problem is I want to display a person's name followed by a colon with some color and then display the following text message with another color.

You're already out of luck. Edit controls can only display text in one color. For text with multiple colors applied you have to use a richedit control.

Quote:
 But I can not do this with the below code because I set the text of an edit control all at once and I can't find some function just to append text.

It does seem odd that there is no support for append. I've seen two methods to do this. The first is get the current text in the control, do the append in your own code, then replace the text. The second is to use EM_SETSEL to set a degenerate range at the end of the control then use EM_REPLACESEL to replace this range. Either one works. The latter is a bit simpler but looks kind of wierd.

##### Share on other sites
0) You're using 'new' for allocation, which means you're using C++. That means you can use std::string. Use std::string.
1) 'new' does NOT return 0 on a failed allocation. It will throw an exception instead. Most C++ code ignores that possibility anyway, or else catches the exception further up the call stack (possibly way at the top); but you can certainly write code to catch the exception. But don't allocate memory yourself if you don't have to: use std::string.
2) std::strings keep track of their length, so you don't make repeated calls to strlen(). Use them.
3) std::strings provide concatenation as a member function, without requiring you to do any management of the buffer size or length calculation. Use them.
4) Normally you would just "remember" the contents of the control in a std::string variable, modify the variable and put changes back. If this isn't possible for whatever reason, then to make the SendMessage() call work properly, you can read into a temporary buffer. To avoid manual memory management, we'll use a vector of char.
5) Simplify your logic: you always append the name, colon and message, and leave whatever was present in the control; all that changes is whether you need to put a newline after the control (if there was already something there).
6) Early-outs are OK; use "guard clauses" to reduce levels of indentation.
7) In case you missed it the first several times, use std::string.

void PrintMessage(const std::string& msg, const std::string& name) {  if (msg.empty()) { return; } // length is 0  // Get the existing text into a new buffer, then create a string from it.  vector<char> buffer(GetWindowTextLength(hEditChat));  SendMessage(hEditChat, WM_GETTEXT, buffer.size(), &(buffer[0]));  std::string control(buffer.begin(), buffer.end());    // If there is already text in there, append the newline  if (!control.empty()) { control += "\r\n"; }  // Append the other stuff  control += name + ":  " + msg;  // Set up the control as before  SendMessage(hEditChat, WM_SETTEXT, 0, reinterpret_cast<long>(control.c_str()));  SendMessage(hEditChat, EM_SCROLL, SB_BOTTOM, 0) ;}

##### Share on other sites
Please, for the love of all coders, use std::string!

If you're new std::string you want std::string::c_str() to get it into the format that SendMessage() needs.

Edit: Zahlman beat me, nice work btw :)

##### Share on other sites
Quote:
Original post by Anon Mike
Quote:
 Original post by GosuDrewThe problem is I want to display a person's name followed by a colon with some color and then display the following text message with another color.

You're already out of luck. Edit controls can only display text in one color. For text with multiple colors applied you have to use a richedit control.

Thanks, I'll look into this richedit control.