0

In code blocks, it works without any errors. But in Visual Studio, it says:

C++ argument of type is incompatible with parameter of type LPCWSTR

This is my code:

#if defined(UNICODE) && !defined(_UNICODE)
    #define _UNICODE
#elif defined(_UNICODE) && !defined(UNICODE)
    #define UNICODE
#endif
#include <windows.h>
    
    
int WINAPI WinMain(HINSTANCE hInst,HINSTANCE hPrev,LPSTR lpCmdLine, int iCmdShow){
    
    int s =  MessageBox(NULL,"Hi This is my First c++ GUI","Win32 API Say:",6);
    if(s == 10){
        MessageBox(NULL,"Hi This is my First c++ GUI","Win32 API Say:",6);
    }else if(s == 11){
        MessageBox(NULL,"Yes GO On","Win32 API Say:",MB_ICONINFORMATION);
    }else{
        MessageBox(NULL,"GoodBey !!","Win32 API Say:",MB_OK);
    }
    return 0;
}
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • *MessageBox**W*** wait *PC**W**STR* strings but you pass *PCSTR* – RbMm Aug 11 '20 at 16:09
  • Change `"Hi This is my First c++ GUI","Win32 API Say:"` to `L"Hi This is my First c++ GUI","Win32 API Say:"` and do similar to the rest. – drescherjm Aug 11 '20 at 16:14
  • ***but in in visual studio it says C++ argument of type is incompatible with parameter of type LPCWSTR*** Visual Studio is correct. You passed a narrow string when it required a wide string. – drescherjm Aug 11 '20 at 16:15
  • Thank you Guys <3 you helped me to understand the issue correctly , i should stop using code blocks due to it's weak compiler – PhotonProgramming Aug 11 '20 at 16:19
  • Related: [https://stackoverflow.com/questions/11287213/what-is-a-wide-character-string-in-c-language](https://stackoverflow.com/questions/11287213/what-is-a-wide-character-string-in-c-language) – drescherjm Aug 11 '20 at 16:20
  • *"i should stop using code blocks due to it's weak compiler"* - The issue wasn't caused by the compiler. It was caused by the default project settings. – IInspectable Aug 11 '20 at 18:25
  • In VS, you can also modify the properties->Advanced->Character Set to change the character set to apply the function you want to match by default (MessageBoxA or MessageBoxW).Because your VS is set to "Use Unicode Character Set" by default, it corresponds to the MessageBoxW function when mapping, and the character set of codeblocks is different, and the MessageBoxA function is mapped, and the parameter types they need are different. – Zeus Aug 12 '20 at 01:48

1 Answers1

2

You are using the TCHAR version of MessageBox(), which is actually a preprocessor macro that maps to either MessageBoxW() or MessageBoxA() depending on whether UNICODE is defined or not, respectively.

In case of CodeBlocks, it works if UNICODE is not defined, so MessageBox() maps to MessageBoxA(), which expects LPCSTR (const char *) strings as input. You are passing in char-based string literals, so all is good.

In case of Visual Studio, is fails if UNICODE is defined, so MessageBox() maps to MessageBoxW(), which expects LPCWSTR (const wchar_t *) strings as input. Since you are passing in char-based string literals, and char* is not implicitly convertible to wchar_t*, hence the error.

If you are going to continue using TCHAR functionality 1, you should wrap your string literals in the TEXT() preprocessor macro to make them use the same character encoding that MessageBox() (or any other TCHAR based API) expects, based on compiler settings.

1: you really should not rely on TCHAR in modern code. It exists only for backwards compatibility with legacy code that predates Microsoft's push to get Win9x/ME apps migrated to Unicode on NT4+/Win2K/XP. TCHAR was invented to help such code migrate from ANSI char strings to Unicode wchar_t strings.

Also, you should not be relying on "magic numbers", either. It makes the code harder to read and understand. Use pre-defined named constants instead. You are already doing that for MB_ICONINFORMATION and MB_OK in your 3rd and 4th calls to MessageBox(), but you are using numeric literals instead for the 1st and 2nd calls to MessageBox().

Try this instead:

#if defined(UNICODE) && !defined(_UNICODE)
    #define _UNICODE
#elif defined(_UNICODE) && !defined(UNICODE)
    #define UNICODE
#endif
#include <windows.h>
    
    
int WINAPI WinMain(HINSTANCE hInst,HINSTANCE hPrev,LPSTR lpCmdLine, int iCmdShow){
    
    int s =  MessageBox(NULL, TEXT("Hi This is my First c++ GUI"), TEXT("Win32 API Say:"), MB_CANCELTRYCONTINUE);
    if(s == IDTRYAGAIN){
        MessageBox(NULL, TEXT("Hi This is my First c++ GUI"), TEXT("Win32 API Say:"), MB_CANCELTRYCONTINUE);
    }else if(s == IDCONTINUE){
        MessageBox(NULL, TEXT("Yes GO On"), TEXT("Win32 API Say:"), MB_ICONINFORMATION);
    }else{
        MessageBox(NULL, TEXT("GoodBey !!"), TEXT("Win32 API Say:"), MB_OK);
    }
    return 0;
}

That said, you should not rely on TCHAR APIs at all, and instead just call MessageBoxA() or MessageBoxW() (or other narrow/wide APIs) directly as needed, eg:

#if defined(UNICODE) && !defined(_UNICODE)
    #define _UNICODE
#elif defined(_UNICODE) && !defined(UNICODE)
    #define UNICODE
#endif
#include <windows.h>
    
    
int WINAPI WinMain(HINSTANCE hInst,HINSTANCE hPrev,LPSTR lpCmdLine, int iCmdShow){
    
    int s =  MessageBoxA(NULL, "Hi This is my First c++ GUI", "Win32 API Say:", MB_CANCELTRYCONTINUE);
    if(s == IDTRYAGAIN){
        MessageBoxA(NULL, "Hi This is my First c++ GUI", "Win32 API Say:", MB_CANCELTRYCONTINUE);
    }else if(s == IDCONTINUE){
        MessageBoxA(NULL, "Yes GO On", "Win32 API Say:", MB_ICONINFORMATION);
    }else{
        MessageBoxA(NULL, "GoodBey !!", "Win32 API Say:", MB_OK);
    }
    return 0;
}
#if defined(UNICODE) && !defined(_UNICODE)
    #define _UNICODE
#elif defined(_UNICODE) && !defined(UNICODE)
    #define UNICODE
#endif
#include <windows.h>
    
    
int WINAPI WinMain(HINSTANCE hInst,HINSTANCE hPrev,LPSTR lpCmdLine, int iCmdShow){
    
    int s =  MessageBoxW(NULL, L"Hi This is my First c++ GUI", L"Win32 API Say:", MB_CANCELTRYCONTINUE);
    if(s == IDTRYAGAIN){
        MessageBoxW(NULL, L"Hi This is my First c++ GUI", L"Win32 API Say:", MB_CANCELTRYCONTINUE);
    }else if(s == IDCONTINUE){
        MessageBoxW(NULL, L"Yes GO On", L"Win32 API Say:", MB_ICONINFORMATION);
    }else{
        MessageBoxW(NULL, L"GoodBey !!", L"Win32 API Say:", MB_OK);
    }
    return 0;
}
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • All versions of Windows NT (3.1 and up) used Unicode. Windows 2000 (NT 5.0) introduced UTF-16 support, not Unicode as a whole, as footnote 1 suggests. – IInspectable Aug 11 '20 at 18:22