Why am I getting conflicting error messages relating to my strings?

19 hours ago 3
ARTICLE AD BOX

The only way that this code:

wc.lpszClassName = g_szClassName;

Can produce different errors is if you are compiling it in different contexts with different compiler configurations.

Most Win32 API structs and functions that deal with strings are declared to use TCHAR strings, which map to either wchar_t or char, and their symbol names have W or A appended to their names, depending on whether or not UNICODE is defined during the precompile stage.

This is explained in more detail on MSDN:

Get Started with Win32 and C++ > Working with Strings

As such...

When the variable is a char variable, it gives the following error:

a value of type "const char *" cannot be assigned to an entity of type "LPCWSTR" (aka "const WCHAR *")

This happens only when you compile the translation unit (.cpp file) with UNICODE defined, where WNDCLASSEX will map to WNDCLASSEXW, which uses wchar_t strings.

When the variable is a wchar_t, I get the following error instead:

'=': cannot convert from 'const wchar_t [14]' to 'LPCSTR'

This happens only when you compile the translation unit without UNICODE defined, so WNDCLASSEX will map to WNDCLASSEXA, which uses char strings.

The same issue applies to other APIs used in your code, including DefWindowProc, RegisterClassEx, CreateWindowEx, GetMessage, MessageBox, etc.

Don't mix your precompiler configurations across translation units. Pick one and stick with it consistently.

When using strings with TCHAR-based APIs, use the TCHAR type and the TEXT() macro for literals, eg:

const TCHAR g_szClassName[] = TEXT("myWindowClass"); // Step 4: the Window Procedure LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch(msg) { case WM_CLOSE: DestroyWindow(hwnd); break; case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hwnd, msg, wParam, lParam); } return 0; } int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { WNDCLASSEX wc; HWND hwnd; MSG Msg; //Step 1: Registering the Window Class wc.cbSize = sizeof(WNDCLASSEX); wc.style = 0; wc.lpfnWndProc = WndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInstance; wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); wc.lpszMenuName = NULL; wc.lpszClassName = g_szClassName; //this one wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION); if(!RegisterClassEx(&wc)) { MessageBox(NULL, TEXT("Window Registration Failed!"), TEXT("Error!"), MB_ICONEXCLAMATION | MB_OK); return 0; } // Step 2: Creating the Window hwnd = CreateWindowEx( WS_EX_CLIENTEDGE, g_szClassName, TEXT("The title of my window"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 240, 120, NULL, NULL, hInstance, NULL); if(hwnd == NULL) { MessageBox(NULL, TEXT("Window Creation Failed!"), TEXT("Error!"), MB_ICONEXCLAMATION | MB_OK); return 0; } ShowWindow(hwnd, nCmdShow); UpdateWindow(hwnd); // Step 3: The Message Loop while(GetMessage(&Msg, NULL, 0, 0) > 0) { TranslateMessage(&Msg); DispatchMessage(&Msg); } return Msg.wParam; }

Otherwise, simply don't rely on TCHAR-based APIs at all, use A and W APIs explicitly as needed, eg:

const wchar_t g_szClassName[] = L"myWindowClass"; // Step 4: the Window Procedure LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch(msg) { case WM_CLOSE: DestroyWindow(hwnd); break; case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProcW(hwnd, msg, wParam, lParam); } return 0; } int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { WNDCLASSEXW wc; HWND hwnd; MSG Msg; //Step 1: Registering the Window Class wc.cbSize = sizeof(WNDCLASSEXW); wc.style = 0; wc.lpfnWndProc = WndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInstance; wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); wc.lpszMenuName = NULL; wc.lpszClassName = g_szClassName; //this one wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION); if(!RegisterClassExW(&wc)) { MessageBoxW(NULL, L"Window Registration Failed!", L"Error!", MB_ICONEXCLAMATION | MB_OK); return 0; } // Step 2: Creating the Window hwnd = CreateWindowExW( WS_EX_CLIENTEDGE, g_szClassName, L"The title of my window", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 240, 120, NULL, NULL, hInstance, NULL); if(hwnd == NULL) { MessageBoxW(NULL, L"Window Creation Failed!", L"Error!", MB_ICONEXCLAMATION | MB_OK); return 0; } ShowWindow(hwnd, nCmdShow); UpdateWindow(hwnd); // Step 3: The Message Loop while(GetMessageW(&Msg, NULL, 0, 0) > 0) { TranslateMessage(&Msg); DispatchMessageW(&Msg); } return Msg.wParam; }
Read Entire Article