Sign in to follow this  
Googol PL3X

Passing Char arrays to MessageBox()

Recommended Posts

Googol PL3X    100
I want to pass an array of chars (C style string) to the second parameter of a MessageBox like this char words[255]; sprintf_s(words, "Letters : %f", g_iLetters); MessageBox(g_hWnd, words, L"Words", MB_OK); I've seen people passing char arrays to this function before (succesfuly) but I can't seem to figure it out, any help would be appreciated.

Share this post


Link to post
Share on other sites
Evil Steve    2017
Quote:
Original post by Googol PL3X
Nope, same error of converting parameter 2 from a char* to LPCWSTR
You're compiling in unicode, but passing a non-unicode string. You'll need to use a wide-character version of sprintf (See the Documentation for swprintf_s), use MultiByteToWideChar to convert from non-unicode to unicode, or call the multi-byte version of MessageBox, and change the 3rd parameter to non-unicode too.

Share this post


Link to post
Share on other sites
Googol PL3X    100
Hey, thanks everyone. Although I'm having some trouble filling the parameters for the MultiByteToWideChar function. This is what I have so far:

MultiByteToWideChar(CP_ACP, 0, &words, sizeof(words), buffer, 100);

Is this right? Also, I'm not sure what buffer should be, because it's supposed to hold the output? Should it be wide char or just char?
thanks

EDIT: never mind, got it!

Share this post


Link to post
Share on other sites
Erik Rufelt    5901
It should be something like:

WCHAR buffer[100];

MultiByteToWideChar(
CP_UTF8,
0,
words,
strlen(words),
buffer,
100
);


Though it would probably be easier to just make words WCHAR and use wsprintf, or call MessageBoxA(g_hWnd, words, "Words", MB_OK);

Share this post


Link to post
Share on other sites
Googol PL3X    100
Neither of those methods appear to compile. I've changed this to calculate FPS, so now it looks like this:

float fFPS = (float)g_dwFrames / ( g_fEndTime - g_fStartTime );
char strFPS[255];
sprintf_s( strFPS, "FPS : %f", fFPS );
MessageBox( g_hWnd, strFPS, "FPS Count", MB_OK );

But this isn't working, can someone help?

Share this post


Link to post
Share on other sites
Zao    970
The proper way to call MultiByteToWideChar and its mirror WideCharToMultiByte is to call it twice. The first time you pass in no buffer and get the size needed as the return value. You then allocate a buffer in some way and call it again.


{
char const * src = "omgwtf";
int cch = MultiByteToWideChar(CP_UTF8, 0, src, -1, 0, 0);
std::vector<wchar_t> buf(cch);
MultiByteToWideChar(CP_UTF8, 0, src, -1, &buf[0], cch);
MessageBox(0, &buf[0], L"Yay", MB_OK);
}



As for your confusion about string types, there are two kinds of character types and string literals in C++.
The first is the regular char, which represents possibly multi-byte text in the execution charset. Those can be initialized by string literals like "omgwtf".
Then there are wchar_t, which is a wide character whose width is determined by the platform you're on. On Linux and some other posixy platforms it's 32 bits unsigned and usually contains UTF-32. On Windows it's 16 bits unsigned and contains UTF-16. You initialize one of those with a wide string literal like L"omgwtfbbq".

Most Windows API functions come in two variants, an A and a W variant. MessageBox is actually a macro that resolves to either MessageBoxA or MessageBoxW, depending on if UNICODE is defined or not.

The A functions take multibyte character strings in the current codepage and the W functions take wide strings in UTF-16.

MultiByteToWideChar does exactly what the name says, it converts from one of the narrow codepages to a wide string. As the source may be in a multi-byte encoding, you may need more than one source char to get a wchar_t. Thus, you need to call it two times, the first time to determine the proper length.

Share this post


Link to post
Share on other sites
Googol PL3X    100
I understand that, but I've seen programms with exactly the same libs, includes and stuff in C++ DirectX9 that can call with out having to put L before literal strings or convert stuff for the windows message boxes!! Why is this, it's very frustrating!

Share this post


Link to post
Share on other sites
Evil Steve    2017
Quote:
Original post by Googol PL3X
I understand that, but I've seen programms with exactly the same libs, includes and stuff in C++ DirectX9 that can call with out having to put L before literal strings or convert stuff for the windows message boxes!! Why is this, it's very frustrating!
Because they're using the multi-byte character set, not Unicode

Share this post


Link to post
Share on other sites
The easiest way, I'd imagine, is to either switch to using wchar_t and swprintf_s or just use MessageBoxA if you don't care about Unicode.

So, changing your original example to either of these should work.

Unicode:

wchar_t words[255];
swprintf_s(words, L"Letters : %f", g_iLetters);
MessageBox(g_hWnd, words, L"Words", MB_OK);


ASCII:

char words[255];
sprintf_s(words, "Letters : %f", g_iLetters);
MessageBoxA(g_hWnd, words, "Words", MB_OK);


Or, alternatively (assuming you're using VC), go into the General page of the project settings and set the character set to "Not Set" instead of Unicode and you can just use char and MessageBox. As long as you're really sure you don't need Unicode support in your app.

Share this post


Link to post
Share on other sites
Googol PL3X    100
Evil Steve, I understand that, but the code is exactly the same, and it still produces different results, and James, unfourtunately neither compiled.

EDIT: fixed, works now, thanks for your help everyone.

Share this post


Link to post
Share on other sites
Evil Steve    2017
Quote:
Original post by Googol PL3X
Evil Steve, I understand that, but the code is exactly the same, and it still produces different results, and James, unfourtunately neither compiled.

EDIT: fixed, works now, thanks for your help everyone.
Yes, but the character sets are a project setting, not something you change in code. Take a look over the link and you'll see.

Share this post


Link to post
Share on other sites
Googol PL3X    100
Quote:
Original post by Evil Steve
Quote:
Original post by Googol PL3X
Evil Steve, I understand that, but the code is exactly the same, and it still produces different results, and James, unfourtunately neither compiled.

EDIT: fixed, works now, thanks for your help everyone.
Yes, but the character sets are a project setting, not something you change in code. Take a look over the link and you'll see.


Oh! I never realised that, is one preferable over the other?

Share this post


Link to post
Share on other sites
Twisol    468
Generally you only need Unicode if you plan on using characters from other character sets, like Japanese characters. With all of my projects - which are all console-based anyways - I just set it to use MultiByte in the project settings, and go about my business.

Share this post


Link to post
Share on other sites
Spoonbender    1258
Quote:
Original post by Twisol
Generally you only need Unicode if you plan on using characters from other character sets, like Japanese characters. With all of my projects - which are all console-based anyways - I just set it to use MultiByte in the project settings, and go about my business.


Yeah, or german characters, or scandinavian ones, or spanish ones, or .....

Honestly, make unicode the default. Please. It's not that difficult.
(On the contrary, it saves you from having to deal with ancient cruft like codepages and such when displaying non-English characters. It just works)

Share this post


Link to post
Share on other sites
Twisol    468
Unicode, in my opinion, is slightly more difficult to deal with at first. Unicode -is- the default, which is why the original poster's problem showed up at all. If he/she wants to deal with vanilla multi-byte - that is, without codepages or anything, just plain default ASCII - so be it!

Share this post


Link to post
Share on other sites
Spoonbender    1258
Quote:
Original post by Twisol
Unicode, in my opinion, is slightly more difficult to deal with at first. Unicode -is- the default, which is why the original poster's problem showed up at all. If he/she wants to deal with vanilla multi-byte - that is, without codepages or anything, just plain default ASCII - so be it!


There's nothing difficult about it. You basically just have to do the following:
Wrap string literals in the TEXT() macro, and enable Unicode in your IDE. That's it. You now have an application which works against Microsoft's Unicode API.
The only "difficult" part is in knowing that this is what you need to do.

Anyway, he asked if one was preferable above the other and the answer is yes, Unicode is definitely preferable. That is why Microsoft set it as default. That is why Windows uses it internally (If you use multibyte instead, it has to convert all the strings you pass it internally)

As for whether or not you "need" anything beyond plain ASCII characters, how do you know? What if the user types in his name, and it happens to contain, say, an ø? What if the user specifies a path containing a non-ASCII character?

Of course, if you really don't care how amateurish your application will look the first time a non-American runs it, that's your choice. But then I have to wonder why you bothered to ask which setting was preferable, when you've already made up your mind, and don't care about the actual answer.

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