LPCWSTR error; is there a better solution? - c++

I have the following c++ code, and it seems like everywhere I attempt to put a string, I have to convert it in order to avoid a `Cannot conver parameter 2 from 'const char[x] to LPCWSTR. I know I can fix this issue by doing a simple conversion, but is there any way around having to convert practically every string I provide? I am a c# developer learning c++ so I'm guessing I'm missing some fundamental concept of the language, if someone could shed some light on this, I'd be grateful!
#include <Windows.h>
#include <string>
using namespace std;
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
PSTR cmdLine,
int showCmd)
{
MessageBox(0, "First Win32 Program.", "My App", MB_OK);
}
Is there a better solution than just this:
{
MessageBox(0, (LPCWSTR)"First Win32 Program.", (LPCWSTR)"My App", MB_OK);
}
And for some odd reason my application is coming up in Japanese or Chinese. So lost on this one.

Use L"text" to create your strings. This way you're creating a wide string which most-likely are expected from the WinAPI.
#include <Windows.h>
#include <string>
using namespace std;
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
PSTR cmdLine,
int showCmd)
{
MessageBox(0, L"First Win32 Program.", L"My App", MB_OK);
}
The problem is you're injecting a narrow string by using a C-style cast to LPCWSTR. So two of your narrow chars (8 bit each) will end mixed-up in one UNICODE char (16 bit each).

You should use the L prefix with your literals. The WINAPI works mostly with wide strings.
As for why that prefix works, here's the relevant part in the standard (§2.14.5/11):
A string literal that begins with L, such as L"asdf", is a wide string literal. A wide string literal has type
“array of n const wchar_t”, where n is the size of the string as defined below; it has static storage duration
and is initialized with the given characters.
The garbage you get is because you're doing a cast that doesn't mean anything, and end up with garbage data that the library tries to interpret as a wide string.
Indeed, here's what a LPCWSTR:
typedef const wchar_t* LPCWSTR;

Related

Why does LoadLibrary fail whilst LoadLibraryA succeeds in loading a DLL? [duplicate]

This question already has answers here:
Cast to LPCWSTR?
(4 answers)
Closed 3 years ago.
I'm trying to load a DLL into C++ but was getting error code 126, which I think means the DLL couldn't be found. After some poking around I changed LoadLibrary to LoadLibraryA and suddendly it worked. However, I am at a complete loss as to why. I realise that I haven't provided the dll for this code to be runable but would be greatful if somebody could provide an explaination as to why this is happening? And prehaps an example of how to get LoadLibary working.
Broken version
#include <stdio.h>
#include <windows.h>
typedef char* (*gf_getCurrentLibraryVersion) ();
int main() {
gf_getCurrentLibraryVersion getVersion;
HINSTANCE hLib = LoadLibrary((LPCWSTR)"libsbnw.dll");
if (hLib) {
getVersion = (gf_getCurrentLibraryVersion)GetProcAddress(hLib, "gf_getCurrentLibraryVersion");
printf("Version = %s\n", getVersion());
}
else {
printf("Error loading dll: %d/n", GetLastError());
}
printf("Hit any key to continue\n");
getchar();
return 0;
}
Compiles and outputs
Error loading dll: 126/nHit any key to continue
to console
Working version
#include <stdio.h>
#include <windows.h>
typedef char* (*gf_getCurrentLibraryVersion) ();
int main() {
gf_getCurrentLibraryVersion getVersion;
HINSTANCE hLib = LoadLibraryA("libsbnw.dll");
if (hLib) {
getVersion = (gf_getCurrentLibraryVersion)GetProcAddress(hLib, "gf_getCurrentLibraryVersion");
printf("Version = %s\n", getVersion());
}
else {
printf("Error loading dll: %d/n", GetLastError());
}
printf("Hit any key to continue\n");
getchar();
return 0;
}
Compiles and outputs
version is: 1.3.4
The problem with your LoadLibrary((LPCWSTR)"libsbnw.dll") call is that your build environment converts that to a LoadLibraryW call, but the way you are trying to pass a wide-character string is wrong.
As you have it, you are simply casting a const char* pointer to a const wchar_t* pointer, which won't work (for example, it will interpret the initial "li" characters as a single 16-bit character).
What you need to do is specify the string literal as a wide character constant, using the L prefix:
HINSTANCE hLib = LoadLibrary(L"libsbnw.dll");
Or, alternatively, using the TEXT() macro (which will boil down to the same, when using the UNICODE build environment):
HINSTANCE hLib = LoadLibrary(TEXT("libsbnw.dll"));
Feel free to ask for further explanation and/or clarification.
Ordinarily the compiler will try to point out when you're making a mistake. But in this case you've told it not to by adding an explicit cast to the string.
HINSTANCE hLib = LoadLibrary((LPCWSTR)"libsbnw.dll");
//^^^^^^^^^
I'm assuming you've built your app with Unicode enabled, which defines a macro converting LoadLibrary to LoadLibraryW. The parameter must be a wide-character string.
HINSTANCE hLib = LoadLibraryW(L"libsbnw.dll");
There's another macro you can use when you're not sure if the app will be compiled with Unicode or not, TEXT() or the shorter form _T(). Not recommended for modern code since needing to turn Unicode on or off hasn't been a problem in many years, just use Unicode always.
HINSTANCE hLib = LoadLibrary(TEXT("libsbnw.dll"));

WINDOWS api can't resolve external symbol [duplicate]

This question already has answers here:
error: cannot convert 'const wchar_t [13]' to 'LPCSTR {aka const char*}' in assignment
(3 answers)
Closed 6 years ago.
Does anyone have any idea why this is happening?
#define _x64
#include <Windows.h>
#include <iostream>
#include <windef.h>
#include <Winuser.h>
#include <tchar.h>
using namespace std;
int WINAPI MessageBoxW(
_In_opt_ HWND hWnd,
_In_opt_ LPCTSTR lpText,
_In_opt_ LPCTSTR lpCaption,
_In_ UINT uType
);
int main(){
std::cout << MessageBoxW(NULL, L"", L"", 0);
}
I am using compiling with Microsoft (R) Incremental Linker Version 14.00.24215.1 and using the "/EHsc" option at the command line for a command line input of "cl /EHsc winbasicb.cpp". I am not doing anything fancy I feel. Just using the /EHsc option for optimized compilation and linking.
I am getting this error.
/out:winbasicb.exe
winbasicb.obj
winbasicb.obj : error LNK2019: unresolved external symbol __imp_MessageBoxW referenced in function main
winbasicb.exe : fatal error LNK1120: 1 unresolved externals
I have read error: cannot convert 'const wchar_t [13]' to 'LPCSTR {aka const char*}' in assignment, but that was not helpful because they're getting a compiler error but I'm getting a linker error. In that question, the error was due to using MessageBoxW(..., "", "", ...) instead of MessageBoxW(..., L"", L"", ...), but I used L"" as I should but I'm getting a linker error.
In Windows there are two versions of just about all Windows API functions.
If you see the "Requirements" section of this reference page you will see that there is one MessageBoxW and one MessageBoxA function. The symbol MessageBox is a macro defined as one of the actual functions depending on the UNICODE macro.
The MessageBoxW function expects the strings to be wide-character strings, which is what you pass. Unfortunately it seem you don't have the correct Unicode settings, so the ANSI (narrow character, plain char) version MessageBoxA is used instead.
There are two solutions: Either make sure you have the correct Unicode settings. Or by explicitly call MessageBoxW. Or don't use wide-character strings (i.e. drop the L prefix).
You are calling the TCHAR version of MessageBox(). The conversion error message is complaining that you are passing Unicode strings to MessageBoxA(), which expects Ansi strings instead. This means your project is being compiled without UNICODE defined, thus TCHAR maps to char and MessageBox() maps to MessageBoxA(). But the L prefix is used to create Unicode literals, not Ansi literals.
When passing string literals to TCHAR based functions, use the TEXT() macro to ensure proper character encoding:
int msgboxID = MessageBox(
NULL,
TEXT("temp.txt already exists.\nDo you want to replace it?"),
TEXT("Confirm Save As"),
MB_ICONEXCLAMATION | MB_YESNO
);
Otherwise, stay away from the TCHAR functions (TCHAR should only be used when compiling the same codebase for both Win9x/ME and NT4+ Windows families), use the Ansi or Unicode functions directly instead:
int msgboxID = MessageBoxA(
NULL,
"temp.txt already exists.\nDo you want to replace it?",
"Confirm Save As",
MB_ICONEXCLAMATION | MB_YESNO
);
int msgboxID = MessageBoxW(
NULL,
L"temp.txt already exists.\nDo you want to replace it?",
L"Confirm Save As",
MB_ICONEXCLAMATION | MB_YESNO
);

cannot convert const wchar_t to 'const_char' for argument 2 in MessageBOX etc etc

I'm learning DirectX for a project for university, My compiler however shows this error:
"10 C:\Dev-Cpp\projectdirectx\main.cpp cannot convert `const wchar_t*' to `const CHAR*' for argument `2' to `int MessageBoxA(HWND__*, const CHAR*, const CHAR*, UINT)'"
I don't understand this at all, I don't know what I did wrong, What i'm attempting to do is a simple messagebox, Here's the code:
#include <windows.h>
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nShowCmd)
{
MessageBox(NULL, L"testing testing",
L"C++", MB_OK);
return 0;
}
What do I do?
You are building an ANSI build, but using a Unicode literal. Either use regular string literals (drop L prefix in front), or switch to a Unicode build.
Just remove the L prefix from the strings.
The problem is that you are trying to invoke wide character version of MessageBox function, which is not the case in your build environment. Just remove the L macro in the function call and it should work.

How to convert type "int" to type "LPCSTR" in Win32 C++

Hello friends how can I convert type "int" to type "LPCSTR"? I want to give the variable "int cxClient" to the "MessageBox" function's second parameter "LPCSTR lpText". Following is the sample code:
int cxClient;
cxClient = LOWORD (lParam);
MessageBox(hwnd, cxClient, "Testing", MB_OK);
But it does not work. The following function is the method signature of the "MessageBox" function:
MessageBox(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType);
Convert the int to a string by using the right sprintf variant
TCHAR buf[100];
_stprintf(buf, _T("%d"), cxClient);
MessageBox(hwnd, buf, "Testing", MB_OK);
you need <tchar.h>.
I think _stprintf is the quick answer here - but if you want to go pure C++ like David suggests, then
#ifdef _UNICODE
wostringstream oss;
#else
ostringstream oss;
#endif
oss<<cxClient;
MessageBox(0, oss.str().c_str(), "Testing", MB_OK);
You need
#include <sstream>
using namespace std;
using std::to_string
std::string message = std::to_string(cxClient)
http://en.cppreference.com/w/cpp/string/basic_string/to_string

How to #define hard coded strings when L prefix (Visual C++ compiler) is used?

How to #define the path L"C:\Windows\System32\taskmgr.exe" for handling wide char
#define TASK_MGR "C:\\Windows\\System32\\taskmgr.exe"
KillProcess(TASK_MGR); //this works
HINSTANCE resurrect = ShellExecute(NULL, L"open", L"C:\\Windows\\System32\\taskmgr.exe", NULL, NULL, SW_MINIMIZE);
You need to use multiple macros. Fortunately, the Windows headers already define such a macro that widens a string literal when necessary, TEXT(), so there's no good reason to write your own.
The following code works fine:
#define TASK_MGR "C:\\Windows\\System32\\taskmgr.exe"
KillProcess(TASK_MGR); // Not sure what KillProcess is or why it takes a narrow
// string, regardless of whether Unicode is defined...
// The Win32 function is named TerminateProcess.
HINSTANCE resurrect = ShellExecute(NULL, L"open", TEXT(TASK_MGR), NULL, NULL,
SW_MINIMIZE);
...well, except for the fact that you hard-coded a path to Task Manager and it's not going to be found at that location on all machines (like mine, for example). But I trust that this is just for example purposes only and you already know well not to hard-code paths.
Which version of Visual C++ are you using? This works on Visual Studio 2008:
#define PATH L"C:\\Windows\\System32\\taskmgr.exe";
void func()
{
const wchar_t *test = PATH;
}
If, as Xeo commented, you want to widen the char array, use MultiByteToWideChar.
You can use string concatenation:
#define TASK_MGR "C:\\Windows\\System32\\taskmgr.exe"
/* ... */
HINSTANCE resurrect = ShellExecute(NULL, L"open", L"" TASK_MGR, NULL, NULL, SW_MINIMIZE);
Personally, I'd go with
static TCHAR const TASK_MGR[] = _T("C:\\Windows\\System32\\taskmgr.exe");
The usual rant on hard-coded path names also applies.