1

I am a programmer familiar with C# & Java and new to C++. I am trying to create an editor in C# WPF for my C++ OpenGL application and I am following these tutorials: Creating OpenGL Windows in WPF and Walkthrough: Host a Win32 Control in WPF. The latter is from Microsoft.

This line of code Helper::ErrorExit(L"RegisterWindowClass"); gives me this error: Argument of type "const wchar_t*" is incompatible with parameter of type "LPTSTR". It is the L that is triggering this according to Visual Studio and I don't exactly know how to fix it.

public:
        //
        // Taken from MSDN
        //
        static void ErrorExit(LPTSTR lpszFunction)
        {
            // Retrieve the system error message for the last-error code
            LPVOID lpMsgBuf;
            LPVOID lpDisplayBuf;
            DWORD dw = GetLastError();

            FormatMessage(
                FORMAT_MESSAGE_ALLOCATE_BUFFER |
                FORMAT_MESSAGE_FROM_SYSTEM |
                FORMAT_MESSAGE_IGNORE_INSERTS,
                NULL,
                dw,
                MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
                (LPTSTR)&lpMsgBuf,
                0, NULL);

            // Display the error message and exit the process

            lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT,
                (lstrlen((LPCTSTR)lpMsgBuf) + lstrlen((LPCTSTR)lpszFunction) + 40) * sizeof(TCHAR));

            StringCchPrintf((LPTSTR)lpDisplayBuf,
                LocalSize(lpDisplayBuf) / sizeof(TCHAR),
                TEXT("%s failed with error %d: %s"),
                lpszFunction, dw, lpMsgBuf);
            ::MessageBox(NULL, (LPCTSTR)lpDisplayBuf, TEXT("Error"), MB_OK);

            LocalFree(lpMsgBuf);
            LocalFree(lpDisplayBuf);
            ExitProcess(dw);
        }
  • 2
    One is a pointer to non-modifiable stuff (const), the other to modifiable stuff - so, yeah, you can't pass a pointer to const stuff to something expecting a pointer to non-const stuff. – Avi Berger Jun 17 '22 at 02:00
  • Any idea what I should replace it with? I have multiple instances of this. This is sample code I am trying to compile from the internet. – Distinct_Cabinet Jun 17 '22 at 02:02
  • String literals in C++ are non-modifiable (its not the L, its being a string literal that is making it const). However, I'd expect to be able to pass a string literal to something like ErrorExit(). Is this a library/api call? what is its prototype? – Avi Berger Jun 17 '22 at 02:07
  • I am updating the question to include the definition for ErrorExit so hopefully, that helps. Also my understanding is that String literal is just a fancy way of saying a String? – Distinct_Cabinet Jun 17 '22 at 02:09
  • 1
    [1](https://stackoverflow.com/questions/21834833/argument-of-type-const-char-is-incompatible-with-parameter-of-type-lpcwstr) and [2](https://stackoverflow.com/questions/33001284/incompatible-with-parameter-of-type-lpcwstr), but choose the opposite setting value. – 273K Jun 17 '22 at 02:10
  • Also, the T in LPTSTR is a microsoft thing that is compiled as narrow or wide characters at compile time. So what it is depends on compiler settings. – Avi Berger Jun 17 '22 at 02:12
  • 1
    More or less a string literal is a literal string value specified in the code as opposed to a string variable. Sort of like specifying a 5 in the code vs. using an int variable. Its a bit more complicated since C++ doesn't have a fundamental string type, but builds them up from simpler components – Avi Berger Jun 17 '22 at 02:18
  • 1
    Just to break down further, the bits of a string typedef in Windows API go like this: `LP`=long pointer; `C`=const; `W`=WCHAR; `T`=TCHAR; `STR`=string. So `LPSTR`=`char*`; `LPCSTR`=`const char*`; `LPWSTR`=`wchar_t*`; `LPCWSTR`=`const wchar_t*` and then the `T` variants which resolve to either `char` or `wchar_t` depending on the project settings (this is how the T-values work). Some love it, others (including myself) hate it. – paddy Jun 17 '22 at 02:19
  • Are you compiling with unicode character set on? Otherwise T maps to char not wchar_t. Checkout settings under Project Configuration Properties/Character set, set to "Use Unicode Character Set" – AndersK Jun 17 '22 at 02:46

1 Answers1

3

TEXT("RegisterWindowClass") is supposed to be used.

Avoid using L"RegisterWindowClass" or "RegisterWindowClass" with parameters of type LPTSTR.

Also change the parameter type to LPCTSTR in static void ErrorExit(LPCTSTR lpszFunction).

273K
  • 29,503
  • 10
  • 41
  • 64
  • I am trying your solution but I am still getting the same error with `Helper::ErrorExit(TEXT("RegisterWindowClass"));` What specific settings do I need to set if that could be the issue? You mentioned something about an opposite setting value? – Distinct_Cabinet Jun 17 '22 at 02:17
  • `TEXT()` must work unless you use some dirty macros hacks. Look at `ErrorExit` - `TEXT()` is working there. – 273K Jun 17 '22 at 02:20
  • Isn't TEXT just a macro that expands with the L in unicode builds & without in non-unicode builds? I don't think TEXT will make any difference here. – Avi Berger Jun 17 '22 at 02:21
  • That's pretty much what Visual Studio is saying. – Distinct_Cabinet Jun 17 '22 at 02:22
  • Maybe you are missing #include – 273K Jun 17 '22 at 02:23
  • I have that one – Distinct_Cabinet Jun 17 '22 at 02:24
  • @AviBerger Yes, that's all it does. In theory consistent use of the macro should mean that you can arbitrarily have additional types in future (_e.g._ UTF-32) although in practice the `_T` / `TEXT` macros really get in the way for ordinary app development and don't do much to assist "future-proofing" or portability, especially when it comes to practical translation between character encodings which is inevitable. Perhaps they are useful if you're writing a library. Using the macro is nevertheless correct, if a little annoying. I generally don't use it because I exclusively work in Unicode. – paddy Jun 17 '22 at 02:26
  • @273K I took a look at your second comment on this answer and went to the function definition and changed it to: `static void ErrorExit(TEXT("RegisterWindowClass"))` and that fixed the initial error, however, I am getting a new error saying 'Browsing operations around this macro may fail. Consider adding it to a hint file. & expected a type specifier'. – Distinct_Cabinet Jun 17 '22 at 02:30
  • 2
    No, this answer and that solution doesn't really address the underlying problem. The problem is not the macro or lack thereof. The problem is the parameter type of the `ErrorExit` function which takes a non-const string. You are passing it a string literal, which is why you get the error about dropping const-qualifier. The function should take a `LPCTSTR` parameter, not `LPTSTR`. That is the proper fix. – paddy Jun 17 '22 at 02:32
  • 2
    Right, change the declaration to `static void ErrorExit(LPCTSTR lpszFunction)`. The MSDN article might be very old of the time of Visual Studio 95. – 273K Jun 17 '22 at 02:33
  • Visual Studio isn't saying anything against that so I guess that works! Learned a lot from this post! – Distinct_Cabinet Jun 17 '22 at 02:41
  • A better answer would be to avoid [generic-text mappings](https://learn.microsoft.com/en-us/cpp/c-runtime-library/generic-text-mappings) altogether. Just use wide character string literals throughout, explicitly call the Unicode versions of API calls (where they exist), and strictly have your string arguments be of type `wchar_t*`/`std::wstring`/`std::wstring_view`. If nothing else this makes source code self-contained. Unlike, say, `LPCTSTR`, which is one of two things, depending on environment properties external to the code at hand. – IInspectable Jun 18 '22 at 08:48