String issues and MENUITEMINFO

Started by
7 comments, last by Defend 13 years, 7 months ago
VC++2008, Win32, Directx9

I'm trying to build a menu dynamically in run-time, based on available video resolutions.

The MENUITEMINFO struct needs a LPWSTR for its dwTypeData. Not a LPCWSTR, but LPWSTR.

I have a line of strings and ints that I can turn into a wstring without hassle, but from there I'm just not sure.



        cout << i << ":  " << painterBBSizes.cx << "x" << painterBBSizes.cy << endl;        MENUITEMINFO        mitemInfo;        std::wstringstream   labelStream;        std::wstring         label;        labelStream << painterBBSizes.cx << " x " << painterBBSizes.cy;        label = labelStream.str();        LPTSTR dest = CT2W(label.c_str());        ERRORPOP(label.c_str());  // Outputs correctly.        ERRORPOP(dest);  // Outputs gibberish.               mitemInfo.cbSize        = sizeof(MENUITEMINFO);        mitemInfo.fMask         = MIIM_TYPE|MIIM_ID|MIIM_DATA;        mitemInfo.fType         = MFT_STRING;        mitemInfo.fState        = NULL;        mitemInfo.wID           = ID_END_THEGREATESTID + 1 + i;        mitemInfo.hSubMenu      = NULL;        mitemInfo.hbmpChecked   = NULL;        mitemInfo.hbmpUnchecked = NULL;        mitemInfo.dwItemData    = NULL;        mitemInfo.dwTypeData    = dest;      // Outputs the same gibberish.                mitemInfo.cch           = sizeof(dest);                  InsertMenuItem(g_menu, ID_END_THEGREATESTID, false, &mitemInfo);


The result is gibberish.
ERRORPOP() requires a LPCWSTR.



Anyone see the problem? Cheers.
Advertisement
Your use of the CT2W macro is the problem. CT2W converts narrow C strings to wide strings, whereas you're handing it a wide string already (std::wstring).

Wielder of the Sacred Wands
[Work - ArenaNet] [Epoch Language] [Scribblings]

I thought CT2W was effectively the same as CW2W here, which is supposed to convert a wide to a wide, yes, but simply output a non-const LPWSTR. Unless I'm mistaken on the difference between wide and narrow strings.

Anyway, do you have a possible solution you could offer?

Man I hate strings. Ascii strings, char strings, wide strings, tstrings, LPSTR, LPWSTR, LPCWSTR... arrrgh. All this stuff is supposed to make it simpler yet here I am simply trying to make an int appear in text. But no, I have to waste a day dealing with the fact that Microsoft needs a non-const LPWSTR.

Is there not a simple way to take a LPCWSTR string and copy its contents to a new LPWSTR?

Strings. >_<
Just allocate a buffer (using std::vector is probably the simplest way), copy the string bytes into it (not neglecting the terminator bytes), and then pass that buffer instead of your std::wstring.

Wielder of the Sacred Wands
[Work - ArenaNet] [Epoch Language] [Scribblings]

Thanks for that, I'll give it a try once home.

I did find that simply giving the address of myString worked before (I didn't check the output though), but I wasn't comfortable with throwing array addresses around like that. A vector crossed my mind but I wasn't sure of any of this.

It bugs me that in 2010 we're still throwing buffers around to manage strings. -_- I thought we were past all that.
Quote:Original post by Defend
It bugs me that in 2010 we're still throwing buffers around to manage strings. -_- I thought we were past all that.


C++ is past that. A lot of the Win32 API code has been around since Win95 (and some of it before that).

"I can't believe I'm defending logic to a turing machine." - Kent Woolworth [Other Space]

I found too many ways to copy string contents to a vector. This seems the best, so I thought I'd chuck it here and see if anyone wants to confirm or reject that. So does this look like a perfectly good way to turn an int + text into a non-const LPTSTR? Cheers.

        tstringstream       labelStream;        tstring             label;        labelStream     << painterBBSizes.cx << " x etc..";        label           = labelStream.str();            std::vector<TCHAR> dest(label.begin(), label.end());        dest.push_back('\0');                       // Null terminate the string.


And here's the whole for loop I'm using, if anyone wants to glance at it.
[source=c++]    for (UINT i = 0; i < painterBBSizes.size(); i++)     {        MENUITEMINFO        mitemInfo;        tstringstream       labelStream;        tstring             label;        labelStream     << painterBBSizes.cx << " x " << painterBBSizes.cy;        label           = labelStream.str();            std::vector<TCHAR> dest(label.begin(), label.end());        dest.push_back('\0');                       // Null terminate the string.               mitemInfo.cbSize        = sizeof(MENUITEMINFO);        mitemInfo.fMask         = MIIM_TYPE|MIIM_ID|MIIM_DATA;        mitemInfo.fType         = MFT_STRING;        mitemInfo.fState        = NULL;        mitemInfo.wID           = ID_END_THEGREATESTID + 1 + i;        mitemInfo.hSubMenu      = NULL;        mitemInfo.hbmpChecked   = NULL;        mitemInfo.hbmpUnchecked = NULL;        mitemInfo.dwItemData    = NULL;                  mitemInfo.dwTypeData    = &dest[0];         // LPTSTR == TCHAR*. Must be a null terminated,        mitemInfo.cch           = dest.size();      // non-const string. cch size includes the \0.        mitemInfo.hbmpItem      = NULL;            InsertMenuItem(g_menu, ID_END_THEGREATESTID, false, &mitemInfo);    }
Looks fine to me [smile]

Wielder of the Sacred Wands
[Work - ArenaNet] [Epoch Language] [Scribblings]

Cheers for the help too.

I realised I can just use << ends; instead of push_back('\0') for that null termination too.

This topic is closed to new replies.

Advertisement