Thread: Displaying Variables trough MessageBox

  1. #1
    Registered User
    Join Date
    Oct 2005
    Location
    Brasil
    Posts
    220

    Displaying Variables trough MessageBox

    When i try to display a variable trough message box function, the message box comes up, but there is nothing written in it like it supposed to be. Any error in the code?

    Code:
    TCHAR GetString(UINT ID)
    {
    	TCHAR Buffer;
    	LoadString(GetModuleHandle(NULL), ID, (LPWSTR)Buffer, 60);
    
    	return Buffer;
    }
    
    ...
    
    MessageBox( NULL, (LPCWSTR)GetString(IDS_INVALID_PATH), L"Error", MB_ICONERROR);

  2. #2
    Registered User
    Join Date
    Oct 2005
    Location
    Brasil
    Posts
    220
    This is another problem that i am having:

    Code:
    CHAR FilePath[90];
    *((LPWORD)FilePath) = NumberLetters;
    SendDlgItemMessage(GetDlgItem(hwndDlg, EDIT_BOX), EDIT_BOX, EM_GETLINE, (WPARAM) 0, (LPARAM) FilePath);
    FilePath[NumberLetters] = 0;
    MessageBox( NULL, (LPCWSTR)FilePath, L"Atention", MB_ICONINFORMATION);
    It simply displays some squares where should be the FilePath variable, the "Atention" displays correctly

  3. #3
    Registered User
    Join Date
    May 2003
    Posts
    1,619
    Code:
    	TCHAR Buffer;
    Here you allocate space for a single character.

    Code:
    	LoadString(GetModuleHandle(NULL), ID, (LPWSTR)Buffer, 60);
    Here you cast an integer type into a pointer type -- so the contents of Buffer (the random garbage it contains at the beginning) are used as an address to a 60-character buffer that you never actually created. Right now the API is writing characters to a random memory address; frankly I'm surprised it didn't cause an access violation.

    Code:
    	return Buffer;
    Now you're returning a single character, which (because you never changed it) still contains the garbage it was initialized with.

    You're obviously using C++ as your second example would be generating compiler errors in C. So use a std::wstring or some variant thereof.


    Also, if you're not going to make your program compile correctly in both Unicode and non-Unicode character sets, don't bother with TCHAR -- use WCHAR. The whole point of TCHAR is to enable programs to use strings sometimes as CHAR and sometimes as WCHAR depending on whether _UNICODE is defined.

    Your program won't work at all if you turn off _UNICODE -- you have LPCWSTR casts, you prefix strings with L, neither of which would work if you compiled without _UNICODE -- so just make them WCHAR strings and make it obvious that it was meant to be Unicode only.




    Here's some C++ code that would do what you need:
    Code:
    #include <string>
    
    ...
    
    
    std::basic_string<WCHAR> GetString(UINT ID)
    {
    	WCHAR Buffer[60];
    	LoadString(GetModuleHandle(NULL), ID, Buffer, 60);
    	return std::basic_string<WCHAR>(Buffer);
    }
    
    ...
    
    MessageBox( NULL, GetString(IDS_INVALID_PATH).c_str(), L"Error", MB_ICONERROR);
    Last edited by Cat; 08-26-2006 at 07:32 PM.
    You ever try a pink golf ball, Wally? Why, the wind shear on a pink ball alone can take the head clean off a 90 pound midget at 300 yards.

  4. #4
    Registered User
    Join Date
    May 2003
    Posts
    1,619
    Quote Originally Posted by Scarvenger
    This is another problem that i am having:

    It simply displays some squares where should be the FilePath variable, the "Atention" displays correctly
    As you've typed it, FilePath is an ANSI string. That is, it's a CHAR[] not WCHAR[] or TCHAR[] buffer.

    The very fact you needed to cast it to a LPCWSTR should have told you that you couldn't use it in place of a WCHAR string.
    Last edited by Cat; 08-26-2006 at 07:35 PM.
    You ever try a pink golf ball, Wally? Why, the wind shear on a pink ball alone can take the head clean off a 90 pound midget at 300 yards.

  5. #5
    Registered User
    Join Date
    Oct 2005
    Location
    Brasil
    Posts
    220
    Thank you, my first problem is solved, but this:
    Code:
    NumberLetters = (WORD) SendDlgItemMessage(hwndDlg, 
                                             EDIT_BOX, 
                                             EM_LINELENGTH, 
                                             (WPARAM) 0, 
                                             (LPARAM) 0); 
    
    ...
    
    WCHAR FilePath[90];
    *((LPWORD)FilePath) = NumberLetters;
    SendDlgItemMessage(GetDlgItem(hwndDlg, EDIT_BOX), EDIT_BOX, EM_GETLINE, (WPARAM) 0, (LPARAM) FilePath);
    FilePath[NumberLetters] = 0;
    MessageBox( NULL, FilePath, L"Atention", MB_ICONINFORMATION);
    Player.AddMediaToLibrary( FilePath );
    Is still displaying squares where should be a the FilePath

  6. #6
    Registered User
    Join Date
    May 2003
    Posts
    1,619
    1. You don't need a GetDlgItem() on your second message. You need the hwnd of the dialog, not the hwnd of the control.

    2. You go through all the trouble to get the number of characters, and then you decide not to use it? You allocate a fixed 90 char buffer -- and what's worse, you don't tell the EM_GETLINE message that it is 90 chars, you tell it that it's NumberLetters in length. What happens if NumberLetters is 100? You tell it the buffer is 100 elements long but in reality it's only 90. You've just overwritten 10 bytes of the stack and you probably crashed the program.

    Code:
    // Allocate whichever is greater: NumberLetters or the size we need to store one WORD.
    int allocate = NumberLetters > (sizeof(WORD)/sizeof(WCHAR)) ? NumberLetters : (sizeof(WORD)/sizeof(WCHAR)) ;
    
    WCHAR * buffer = new WCHAR[allocate];
    *((LPWORD)buffer ) = allocate;
    SendDlgItemMessage(hwndDlg, EDIT_BOX, EM_GETLINE, (WPARAM) 0, (LPARAM) buffer );
    std::basic_string<WCHAR> FilePath(buffer,NumberLetters);
    delete[] buffer;
    
    MessageBox( NULL, FilePath.c_str(), L"Atention", MB_ICONINFORMATION);
    Player.AddMediaToLibrary( FilePath.c_str() );
    Last edited by Cat; 08-27-2006 at 01:26 AM.
    You ever try a pink golf ball, Wally? Why, the wind shear on a pink ball alone can take the head clean off a 90 pound midget at 300 yards.

  7. #7
    Registered User
    Join Date
    Oct 2005
    Location
    Brasil
    Posts
    220
    Oh my god thank you!
    My last question:

    Code:
    MessageBox(NULL, FindFileData.cFileName, L"!", MB_ICONINFORMATION);
    mp3fi.Init((const char*)FindFileData.cFileName);
    MessageBox(NULL, mp3fi.szArtist, L"!", MB_ICONINFORMATION);
    Well, mp3fi.szArtist is a char*, any clue on how do i convert it to a LPCWSTR? Or i have to make changes to the whole mp3fi in order to this class use only std::basic_string<WCHAR> type?

  8. #8
    Registered User
    Join Date
    May 2003
    Posts
    1,619
    You can't simply cast between WCHAR and char *. It won't work. Including that you can't cast FindFileData.cFileName; nor can you cast mp3fi.szArtist.

    On the other hand, I do have some functions you could use to accomplish this goal. You should be able to use codepage = CP_ACP (the default system codepage), flags = 0.


    Code:
    std::basic_string<WCHAR> ToWideChar(std::basic_string<CHAR> s, UINT codepage, DWORD flags){
    	// Get the needed size
    	int neededSize = MultiByteToWideChar(
    		codepage,
    		flags,
    		s.c_str(),
    		(int) s.size(),
    		NULL,
    		0);
    
    	if (neededSize == 0) throw std::runtime_error("Unable to determine the size of buffer needed");
    
    	WCHAR * buffer = new WCHAR[neededSize];
    
    	int size = MultiByteToWideChar(
    		codepage,
    		flags,
    		s.c_str(),
    		(int) s.size(),
    		buffer,
    		neededSize);
    
    	std::basic_string<WCHAR> ret(buffer,size);
    
    	delete[] buffer;
    
    	return ret;
    }
    
    std::basic_string<CHAR> ToMultibyte(std::basic_string<WCHAR> s, UINT codepage, DWORD flags){
    
    	// Get the needed size
    	int neededSize = WideCharToMultiByte(
    		codepage,
    		flags,
    		s.c_str(),
    		(int) s.size(),
    		NULL,
    		0,
    		NULL,
    		NULL);
    
    	if (neededSize == 0) throw std::runtime_error("Unable to determine the size of buffer needed");
    
    	CHAR * buffer = new CHAR[neededSize];
    
    	int size = WideCharToMultiByte(
    		codepage,
    		flags,
    		s.c_str(),
    		(int) s.size(),
    		buffer,
    		neededSize,
    		NULL,
    		NULL);
    
    	std::basic_string<CHAR> ret(buffer,size);
    
    	delete[] buffer;
    
    	return ret;
    }

    You'd use them like this:

    Code:
    mp3fi.Init( ToMultibyte(FindFileData.cFileName,CP_ACP,0).c_str() );
    
    std::basic_string<WCHAR> artist = ToWideChar(mp3fi.szArtist, CP_ACP,0);
    MessageBox(NULL, artist.c_str(), L"!", MB_ICONINFORMATION);
    You ever try a pink golf ball, Wally? Why, the wind shear on a pink ball alone can take the head clean off a 90 pound midget at 300 yards.

  9. #9
    Registered User
    Join Date
    Oct 2005
    Location
    Brasil
    Posts
    220
    thank you, it worked!!!!!

  10. #10
    erstwhile
    Join Date
    Jan 2002
    Posts
    2,227
    std::basic_string<WCHAR>
    The stl already provides a typedef alias for this, namely std::wstring.
    CProgramming FAQ
    Caution: this person may be a carrier of the misinformation virus.

  11. #11
    Registered User
    Join Date
    May 2003
    Posts
    1,619
    Quote Originally Posted by Ken Fitlike
    The stl already provides a typedef alias for this, namely std::wstring.

    std::wstring is a typedef for std::basic_string<wchar_t>.

    I am not positive wchar_t and WCHAR are guaranteed to be the same on all implementations. I know on my compiler WCHAR == wchar_t which is (depending on compiler options) sometimes also == unsigned short.

    When I use windows strings I always make my own typedefs for std::basic_string<CHAR> and std::basic_string<WCHAR> just in case for some reason they weren't just #defines for char and wchar_t, respectively.
    Last edited by Cat; 08-28-2006 at 05:21 PM.
    You ever try a pink golf ball, Wally? Why, the wind shear on a pink ball alone can take the head clean off a 90 pound midget at 300 yards.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. esbo's data sharing example
    By esbo in forum C Programming
    Replies: 49
    Last Post: 01-08-2008, 11:07 PM
  2. Creating local variables in a program?
    By fl0at in forum C Programming
    Replies: 5
    Last Post: 01-04-2008, 07:34 PM
  3. Global Variables
    By Taka in forum C Programming
    Replies: 34
    Last Post: 11-02-2007, 03:25 AM
  4. static variables
    By Luigi in forum C++ Programming
    Replies: 4
    Last Post: 04-24-2003, 07:13 PM
  5. EnterCriticalSection and MessageBox
    By novacain in forum Windows Programming
    Replies: 13
    Last Post: 01-30-2003, 08:48 AM