Handmade Hero»Forums»Game
logan bender
8 posts
Day 005: cannot convert from 'const wchar_t [24]' to 'LPCSTR'

I'm picking backup my HMH project after a year off

Using VS code , it complains:

a value of type "const char *" cannot be assigned to an entity of type "LPCWSTR"

on this line:

WindowClass.lpszClassName = "handmadeHeroWindowClass";

It doesn't prevent compiling.

Why am I being told this const char * value is incorrect, when it clearly compiles?

How do I properly assign a string to WindowClass.lpszClassName so that VS code longer sees it as an error?

Simon Anciaux
1337 posts
Day 005: cannot convert from 'const wchar_t [24]' to 'LPCSTR'
Edited by Simon Anciaux on

LPCWSTR is a pointer to a "wide" character string (the W in the name), which is a 16 bit per character string to encode unicode characters (utf 16 encoding).

Take a look at the remark at the end of this page https://learn.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-wndclassexa.

To make it simple there are "two version" of parts the win32 API, one that uses ANSI (~ASCII) and one that uses UNICODE. Depending on the definition of the UNICODE preprocessor constant, some function and struct will be defined to a version or the other.

For example the WNDCLASSEX struct is a macro that is equivalent to WNDCLASSEXA in ANSI and WNDCLASSEXW in unicode. In a similar way RegisterClassEx can be RegisterClassExA or RegisterClassExW.

Casey will talk about that at some point in the series (near the beginning).

In your case to suppress the warning, you can use

WindowClass.lpszClassName = L"handmadeHeroWindowClass";
// or
WindowClass.lpszClassName = TEXT("handmadeHeroWindowClass");
// Seed https://learn.microsoft.com/en-us/windows/win32/api/winnt/nf-winnt-text

A side note, is that LPCWSTR stands for

  • LP long pointer (not sure about the long part, but it's a pointer);
  • C for constant;
  • W for wide;
  • STR for string.

In full: long pointer to a constant wide string.

Mārtiņš Možeiko
2559 posts / 2 projects
Day 005: cannot convert from 'const wchar_t [24]' to 'LPCSTR'

I would recommend against using TEXT() macro. There is zero reason nowadays to write code for supporting both A and W functions. Simply always use explicitly version you want - witch would be W variant on modern Windows. This means using WNDCLASSEXW explicitly (not WNDCLASSEX) and using functions with W suffix explicitly. And having all string literals with L prefix.

logan bender
8 posts
Day 005: cannot convert from 'const wchar_t [24]' to 'LPCSTR'
Edited by logan bender on
Replying to mrmixer (#27081)

thanks for your advice.

Prefixing with "L" causes a compile error

WindowClass.lpszClassName = L"handmadeHeroWindowClass";

.../win32_handmade.cpp(277): error C2440: '=': cannot convert from 'const wchar_t [24]' to 'LPCSTR' .../win32_handmade.cpp(277): note: Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast

TEXT() seems to silence VS Code's complaint and compiles successfully. Which is odd because VS Code tells me that it expands to the same thing - a "L" prefix. I assume TEXT() is a 'function-style cast'?

image.png

Mārtiņš Možeiko
2559 posts / 2 projects
Day 005: cannot convert from 'const wchar_t [24]' to 'LPCSTR'
Replying to userNameExists (#27083)

All TEXT("foo") does is to expand it to either "foo" or L"foo" depending on whether you have UNICODE macro defined. Same macro affects whether macro like CreateWindowEx will be CreateWindowExA (accepting const char* strings) or CreateWindowExW (accepting const wchar_t* strings). Similar for types WNDCLASSEX is a macro either for WNDCLASSEXA or WNDCLASSEXW in same way.

You should not trust whatever highlighting IDE's show you. Because they often get macros wrong and cannot correctly infer correct C types. Trust & read only actual compiler errors.

Using explicitly correct types & functions with A and W suffix may prevent such IDE errors, but not guaranteed.

logan bender
8 posts
Day 005: cannot convert from 'const wchar_t [24]' to 'LPCSTR'
Edited by logan bender on
Replying to mmozeiko (#27084)

Thanks for your replies, and reminding me that there are both ASCII and UNICODE versions of many of these classes.

Replacing these calls

WNDCLASS WindowClass = {}; if (RegisterClass(&WindowClass)){...} HWND Window = CreateWindow(...)

with the explicitly "wide" versions:

WNDCLASSEXW WindowClass = {}; if (RegisterClassExW(&WindowClass)){...} HWND Window = CreateWindowExW(...)

and using the "long" prefix L"StringVariable" seems remove the VS Code complaints & compiles correctly.

BUT: with those changes, the .exe no longer does anything I can see. CreateWindowExW() no longer returns a result.

Mārtiņš Možeiko
2559 posts / 2 projects
Day 005: cannot convert from 'const wchar_t [24]' to 'LPCSTR'
Edited by Mārtiņš Možeiko on
Replying to userNameExists (#27086)

What does "CreateWindowExW() no longer returns a result" means? This function always returns result. What value exactly it returns?

Or you mean process crashes? In such case probably arguments to this function are wrong.

logan bender
8 posts
Day 005: cannot convert from 'const wchar_t [24]' to 'LPCSTR'
Edited by logan bender on
Replying to mmozeiko (#27087)

the problem, I think, is that one of the 'if' evaluations for RegisterClassExW or CreateWindowExW is false:

	if (RegisterClassExW(&WindowClass)) // this is false...
	{
		HWND Window = CreateWindowExW(
			0,
			WindowClass.lpszClassName,
			L"Handmade Hero",
			WS_OVERLAPPEDWINDOW | WS_VISIBLE,
			CW_USEDEFAULT,
			CW_USEDEFAULT,
			CW_USEDEFAULT,
			CW_USEDEFAULT,
			0,
			0,
			Instance,
			0);
		
		if (Window) // or this is false
		{
			// game loop here
		}

I reverted my cod back to the generic RegisterClass and CreateWindowEx as they are the only ones that compile to a working executable, so I can't go back and step through carefully right now.

Mārtiņš Možeiko
2559 posts / 2 projects
Day 005: cannot convert from 'const wchar_t [24]' to 'LPCSTR'
Replying to userNameExists (#27088)

In such cases you should use debugger. Put breakpoints and step over line by line to see how code executes and what are values of functions.

logan bender
8 posts
Day 005: cannot convert from 'const wchar_t [24]' to 'LPCSTR'
Edited by logan bender on
Replying to mmozeiko (#27089)

I moved on to episode 006 and Casey Addresses this 'W" vs "A" API calls a little

It looks like he is opting to do the "A" style calls for now