Annoying Data Types...

Hi, I would like to send a string of text to the SetWindow() function, but the data type required is LPCWSTR ( I know it is a null terminated 16-bit character string for Unicode builds). I do not wish to switch away from Unicode.

I have found this function to convert a string to TCHAR, but when I go to compile it VC++ says mbstowcs() is unsafe.

1
2
3
4
5
6
7
8
9
10
TCHAR* StringToTCHAR(string& s)
{
  tstring tstr;
  const char* all = s.c_str();
  int len = 1 + strlen(all);
  wchar_t* t = new wchar_t[len]; 
  if (NULL == t) throw std::bad_alloc();
  mbstowcs(t, all, len);
  return (TCHAR*)t;
}


Should I use this method on the link below to convert it, using MultibyteToWideChar()?

http://www.codeguru.com/forum/archive/index.php/t-231165.html

Most people just use the _T() macro or prefix it with L, but in my case, I do not know what the string literal would be, so I am lost.

Thank you for any help you can give.
I don't fully understand your question. For one thing, what is the SetWindow() function? Do you mean SetWindowText()? If you do then I think you should be more careful in your postings. I personally find it really aggrevating when I read posts and folks misspell code. I know my spelling is poor in the prose I write, and I've probably made some misspellings here, but I don't misspell code or function names.

I'll try to answer based on the assumption you mean SetWindowText(). Of course I'm wasting my time if that isn't what you meant, proof of my statemebnts above.

If you are doing a UNICODE build you just declare your variables as TCHAR and you can pass them directly to SetWindowText() which is macroed to SetWindowTextW() in the windows header files. It will work. If you have an ansi string you could specifically use SetWindowTextA for it, or, as you stated, use a conversion function to convert it to wide character.

In terms of the warnings you are getting (apparently from Visual Studio???), don't they suggest alternatives? I only use C++ for my eMbedded and Windows CE/Mobile work, so the security issues are a non-issue for me, and I turn them off with defines such as SECURE_NO_WARNINGS or something like that.
For one, TCHAR is not the same as wchar_t. If you want a TCHAR, use a TCHAR, don't use wchar_t.

For two, if you dont' want to use TCHARs (if you just want to give a char string), you can use the ANSI versions of WinAPI calls.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// This is bad because it gives a char string as a TCHAR string
SetWindowText( wnd, "Text" );  // BAD

// This is also bad because it gives a wchar_t string as a TCHAR string
SetWindowText( wnd, L"Text" );  // BAD


//  Note that either of the above might compile in some cases, BUT THEY'RE STILL BAD
//  Below options are good:

// Give a char string as a char string:
SetWindowTextA( wnd, "Text" );  // GOOD

// Give a TCHAR string as a TCHAR string:
SetWindowText( wnd, _T("Text") );  // GOOD

// Give a wchar_t string as a wchar_t string:
SetWindowTextW( wnd, L"Text" );  // GOOD 


If you have a char array that you want to pass to SetWindowText, the solution is NOT to convert it to TCHAR, but simply give it to the ANSI version of the function (SetWindowTextA):

1
2
3
4
char foo[] = "Whatever";

// SetWindowText( wnd, foo );  // BAD
SetWindowTextA( wnd, foo );  // GOOD 


More reading: http://www.cplusplus.com/forum/articles/16820/
Last edited on
Yes I meant SetWindowText() function, I even proof-read the post twice! (Sorry).

The build is required to be Unicode, and the second parameter of the SetWindowText() function is dependent on other parts of the program, so I can't prefix it with L or _T. It is passed as a variable, not as a string literal.

So if I need to pass a string to a LPWSTR, I was thinking I need to convert it to wstring or wchar_t using MultiByteToWideChar()?

Am I better of copying a standard string to a TCHAR?

Please excuse my stupidity, this is just really quite confusing.

Or is there a way to simply prefix a string variable with L?
After reading the posts and the link several times over, I've come up with this method, to pass, for instance, an integer value to the SetWindowText() function.

1
2
3
4
5
6
7
int stuff = 3;
stringstream ss;
ss << stuff;
const char* constCharS = ss.str().c_str();
TCHAR *tStr = {0};
ustrcpy(tStr,constCharS);
SetWindowText(button,tStr);


using the function provided in the above link
1
2
3
4
5
6
7
8
9
10
void ustrcpy(TCHAR* dst, const char* src)
{
  while(*src)
  {
   *dst = *src;
   ++dst;
   ++src;
  }
  *dst = *src;
}
Last edited on
The build is required to be Unicode, and the second parameter of the SetWindowText() function is dependent on other parts of the program, so I can't prefix it with L or _T. It is passed as a variable, not as a string literal.


So use SetWindowTextA as I suggested in my previous post. It lets you pass a char string (not Unicode), but doesn't stop the rest of the program from being bulit as Unicode.

Windows will automatically convert up to Unicode behind the scenes. You don't have to do it manually.

1
2
3
// from your code...
TCHAR *tStr = {0};
ustrcpy(tStr,constCharS);


This will horribly corrupt memory. Don't do it. Pointers are not strings.



Again... you're making this way harder on yourself than it has to be. Just do this:

 
SetWindowTextA(button,ss.str().c_str());
Last edited on
Just the other day I replied to someone who was absolutely determined to prefix variables with an 'L' to somehow turn them into wide character string variables. You really, really have to disabuse yourself of that idea. You only use the 'L' prefix on something like this...

L"Hello, World!"

...if you are wanting to use that literal string in a function requiring a wide character string parameter, or assigning that string to a wide character variable. This prefix is for string literal constants - not variables

I don't use the standard string class (I use my own), but does it not react accordingly to a #define UNICODE? If it does, then the .c_str member should return the address of a wide character string. That you should be able to use directly in SetWindowText()'s 2nd parameter, which, as I stated, will actually be the W version if UNICODE is defined.

If you are not sure what is going on, create yourself a console program with the same build environment as your program and output the sizeof(TCHAR). If its 1 then you aren't working in a wide character string environment. If 2 you are.

You are on the right track though. The Windows Api functions do not deal in any way whatsoever with string classes. The Windows Api does not know what they are. The Windows Api deals exclusively with pointers to character arrays. In a very real sense its not even exactly kosher to talk of 'strings' with the Windows Api. C doesn't have any variable type that is even a 'string'. They are arrays of bytes with a null demarking the end.

Every Api function that takes a string parameter comes in two versions. For example, in your case they would be SetWindowTextA and SetWindowTextW. There really isn't a SetWindowText. The preprocessor converts calls to SetWindowText into calls to the respective A or W version depending on the UNICODE macro.

If you are not sure what you have returned from .c_str, take the address and run through it 1 byte at a time with a for loop and output the chars (define >> char c) and see what you get. If its wide character every other byte will be a zero (for English and most European languages).

Did you read Disch's link? It explains all this well. I just scanned it quick, but intend to read it all tomorrow in detail. Its really quite good.

You are right on the money about one thing though. It is quite annoying. I've been fighting it about ten years now, and here about a year ago I decided to finally give in and just use TCHARs and the tchar.h macros for everything. It won and I lost.
Last edited on
Topic archived. No new replies allowed.