Sign in to follow this  
GosuDrew

Displaying Text Problem

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 this post


Link to post
Share on other sites
Guest Anonymous Poster
Why aren't you using std::string?

Share this post


Link to post
Share on other sites
Quote:
Original post by GosuDrew
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.


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 this post


Link to post
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 this post


Link to post
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 this post


Link to post
Share on other sites
Quote:
Original post by Anon Mike
Quote:
Original post by GosuDrew
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.


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.

Share this post


Link to post
Share on other sites

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