0

I am experimenting with C++Builder 12, trying to port some old code from C++Builder 2009.

In that old code, all character strings are defined, for example, like this:

char testString[256]="This is a test";

If I try to use this string in MessageBox(), for example, I get an error:

no matching function for call to MessageBoxW

I can get it to work like this:

MessageBox(NULL, L"This is a test", L"Test", 0);

I'm pretty sure I can get my old code compiled by using some compiler option, but I can't figure it out. In Visual C++, I would fix this by setting the "Character Set" option to "Not Set" instead of "Use Unicode".

Can someone help me out with this?

2
  • 2
    Many Windows API functions that take string pointers also have A and W versions. You just need to call the correct one that matches your character type. Commented Aug 13 at 21:08
  • "all character strings are defined, ... like this:" - Are these strings changed at runtime? If not, you could use auto& testString = "This is a test"; which both makes it immutable and preserves its size (so its string length becomes known at compile time: sizeof testString - 1). Commented Aug 13 at 21:13

1 Answer 1

6

C++Builder's compilers have a _TCHAR maps to option which controls the behavior you are seeing. See _TCHAR Mapping in C++Builder's documentation.

  • When the mapping is set to char, the UNICODE conditional is not defined, causing TCHAR-based APIs to map to their ANSI versions.

  • When the mapping is set to wchar_t, the UNICODE conditional is defined, causing TCHAR-based APIs to map to their Unicode versions.

In this situation, the Win32 MessageBox() is a TCHAR-based API. It maps to either MessageBoxA or MessageBoxW, respectively. You can see this in winuser.h:

WINUSERAPI
int
WINAPI
MessageBoxA(
    _In_opt_ HWND hWnd,
    _In_opt_ LPCSTR lpText,
    _In_opt_ LPCSTR lpCaption,
    _In_ UINT uType);
WINUSERAPI
int
WINAPI
MessageBoxW(
    _In_opt_ HWND hWnd,
    _In_opt_ LPCWSTR lpText,
    _In_opt_ LPCWSTR lpCaption,
    _In_ UINT uType);
#ifdef UNICODE
#define MessageBox  MessageBoxW
#else
#define MessageBox  MessageBoxA
#endif // !UNICODE

Your C++Builder 2009 project is set to map TCHAR to char, but your C++Builder 12 project is set to map TCHR to wchar_t. That is why you are getting a mismatch.

When using strings with TCHAR-based APIs, you should be using the TCHAR type for string variables, and the TEXT() macro for string literals, eg:

TCHAR testString[256] = TEXT("This is a test");
MessageBox(NULL, testString, TEXT("Test"), 0);

MessageBox(NULL, TEXT("This is a test"), TEXT("Test"), 0);

Otherwise, call the ANSI/Unicode APIs directly based on the types of strings you are using, eg:

char testStringA[256] = "This is a test";
MessageBoxA(NULL, testStringA, "Test", 0);

wchar_t testStringW[256] = L"This is a test";
MessageBoxW(NULL, testStringW, L"Test", 0);

MessageBoxA(NULL, "This is a test", "Test", 0);
MessageBoxW(NULL, L"This is a test", L"Test", 0);
Sign up to request clarification or add additional context in comments.

2 Comments

Or the shorter macro _T: _T("my string")
@i486 the _T() macro (and the corresponding _TCHAR type) is for the C runtime library. The TEXT() macro (and corresponding TCHAR type) is for the Win32 API. They are technically separate APIs, but are functionally interchangable in practice, but I don't like mixing APIs like that. You should use the appropriate items for the API being used to avoid any surprises.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.