Display Variable in Win32 MessageBox

I was wondering how I could go about printing the contents of a variable in a message box's body:

I currently have a function that fetches the MAC address of an adapter
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
/*============================================================
	static void MACAdr::GetMACaddress(void)
	------------
	Get the MAC address of given devices.
============================================================*/
void MACAdr::GetMACaddress()
{
	IP_ADAPTER_INFO AdapterInfo[16];//Allocate Information.
	DWORD dwBufLen = sizeof(AdapterInfo); //Save size of buffer.
	DWORD dwStatus = GetAdaptersInfo(AdapterInfo, &dwBufLen);

	//Verify that the buffer return value is valid,
	//failure to do so could result in a buffer overflow.
	//@TODO: We need to find a new way to check if value is valid.
	//		 doing it this way causes an infinte loop.
	if(dwStatus == ERROR_SUCCESS)
	{
		PIP_ADAPTER_INFO pAdapterInfo = AdapterInfo; //Pointer to current adapter.

		do
		{
			//Print and indexing code goes here.
			PrintMACaddress(pAdapterInfo->Address);
		}while(pAdapterInfo);

	}//End if
}

and I have a template that will print out the the address:
1
2
3
4
5
template <class s32Data>
s32Data PrintMACaddress(s32Data address)
{
	return MessageBox(/*HWND*/NULL, address, "MACAddress" /*LPSTR*/, MB_OK);
}


error C2664: 'MessageBoxA' : cannot convert parameter 2 from 'unsigned char *' to 'LPCSTR'
1>          Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast


Does anyone know how I can output my MACAddress: pAdapterInfo->Address

In to a message box?


Thanks.


EDIT: I just realized that my print template is wrong....
The return type of PrintMACaddress() is not correct. It needs to match the return type of the MessageBox() function.

A message box can only display strings. You need to convert the address to a string. You can do this using a stringstream or wstringstream (if you are using Unicode, and you should be!!!). Google this if you don't know how. It has been answered multiple times here and in other forums.
The return type of PrintMACaddress() is not correct. It needs to match the return type of the MessageBox() function.
This is probably a stupid question, but what do you mean when you say it has to match the return type of MessageBox? I didn't know Messagebox had a return type.

EDIT: I took a look on the forums and Google, and I found a few ways, but I'm still not 100% on how to convert to a string. When ever I try a wstringstream, it says that it can't convert it to type LPSTR. You wouldn't happen to have a article laying around on this topic, would you?
Last edited on
I don't. If the compiler cannot convert to LPSTR, then it means you are compiling an ANSI build, not a UNICODE build, in which case you need to A. configure the project as a UNICODE build, or B. use stringstream instead of wstringstream.

Note that in order to extract the string contained in the stringstream (or wstringstream) object, you call for its str() method. Check the documentation in this site (left menu) and read about the string streams and its methods.

MessageBox() has a return type, yes. In my SDK, I see it returns an int, and the returned value represents the button that was pressed by the user.

Now, picking up the UNICODE topic: Functions that don't end in "A" or "W" are usually macro names (like MessageBox) that point to the real function name. Example: MessageBox is a macro that expands to MessageBoxA if UNICODE is not #defined. If UNICODE is #defined, then MessageBox expands to MessageBoxW. The ones that end in A take char's and related data types like LPSTR; the ones ending in W take wchar_t's and related data types like LPWSTR. Finally, the macro name actually takes TCHAR's and related data types like LPTSTR. The actual definition of a TCHAR is dependent on whether UNICODE has been #defined, just like the function macro names.

So, knowing the above, you must always follow these rules:

-If you call a function that ends in A, use the char data type and related types like LPSTR, LPCSTR and even the STL classes std::string and std::stringstream.
-If you call a function that ends in W, use the wchar_t data type and related types like LPWSTR, LPCWSTR and even the STL classes std::wstring and std::wstringstream.
-If you call a function that doesn't end in either, use the TCHAR data type and related types like LPTSTR, LPCTSTR and even the STL classes .... whooops!! No data type defined in the STL for this case, but you can define your own tstring and tstringstream data types like this:

1
2
typedef std::basic_string<TCHAR> tstring;
typedef std::basic_stringstream<TCHAR, char_traits<TCHAR>, allocator<TCHAR>> tstringstream;


If yoiu ALWAYS follow the rules above, you'll have no problem compiling either Unicode or ANSI builds of your software, regardless of how many code you see out there that doesn't follow these rules, including samples from the very Microsoft.
Last edited on
Wow that is a mouthful! Thank you as that just answered 120% my problems. I do have one more quick question though, as this is turning into one of those "Nightmares". As I said above I've looked around and tried a few different ways of doing this:
1
2
std::string MyString =(LPWSTR)pAdapterInfo->Address;
	std::wstringstream MyString();


I have the project set to UNICODE and yet everything I try still throws the same error. Cannot convert. Am I doing something wrong here? (I mean I know I am, nothing is working :D).

BTW, Thanks for the help Web; I appreciate it!
Last edited on
Yes, you are doing something wrong: If you have set your project to create a Unicode build, then you must stop using the ANSI string std::string and use the Unicode string std::wstring.

Trust me, it is best if you just do the typedef things I showed you and always use tstring and tstringstream. Throw those typedef's into the precompiled header (if you use Visual Studio) and be done with it; otherwise throw them into a header you always add everywhere, like some Globals.h, or maybe a utility header you might have for your own use.

Now back to the problem: IP_ADAPTER_INFO::Address is a byte array; the MAC address. You want to show the MAC address as a string. Typically, a MAC is shown in the form XX:XX:XX:XX:XX:XX, where each X is a hexadecimal digit. The easiest is therefore using a stringstream to change each byte to a hex representation and add colons in between until you are done. Once you are done, you just print out the result. To convert a single digit to a hex, you could do:

1
2
3
4
5
6
7
tstring ByteToHex(BYTE val)
{
    tstringstream ss;
    //Exercise:  Make sure the resulting string is always 2 digits in width.
    ss << std::hex << val;
    return ss.str();
}


Now it is up to you to modify the above to accept the byte array and its length (provided by IP_ADAPTER_INFO::AddressLength) and output the entire MAC, not just a single byte.
Woot, after a little pen and paper testing I was finally able to get it working. I was just over thinking things. Thank you Web.
Topic archived. No new replies allowed.