I haven't been programming in c++ very long, but need to make an Win32 application for my school. The teacher helped me a lot with information but after a few days of trying I am still stuck.
Errors:
error C2440: '=' : cannot convert from 'const char [11]' to 'LPCWSTR'
error C2664: 'CreateWindowExW' : cannot convert parameter 2 from 'const char [11]' to 'LPCWSTR'
error C2664: 'TextOutW' : cannot convert parameter 4 from 'char *' to 'LPCWSTR'
IntelliSense: argument of type "char *" is incompatible with parameter of type "LPCWSTR"
Don't know if all the other suff is right, but i only get those 4 error now
cpp file:
/* Hoofdstuk 10, User Interface */
#include "Callback_NYCM.h"
// UI
int WINAPI WinMain(HINSTANCE thisInstance,HINSTANCE prevInstance,LPSTR lpCmdLine,int nShowCmd)
{
PAINTSTRUCT ps;
HDC hdc;
MSG msg;
HWND hwnd;
WNDCLASSEX wndclassex; //struct_WNDCLASSEX via windows.h
// toekenning
wndclassex.cbSize = sizeof(WNDCLASSEX);
wndclassex.style = CS_HREDRAW | CS_VREDRAW;
wndclassex.lpfnWndProc = WndProc;
wndclassex.cbClsExtra = 0;
wndclassex.cbWndExtra = 0;
wndclassex.hInstance = thisInstance;
wndclassex.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wndclassex.hCursor = LoadCursor(thisInstance,IDC_ARROW);
wndclassex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wndclassex.lpszMenuName = NULL;
wndclassex.lpszClassName = "WNDCLASSEX";
wndclassex.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
// functie aanroep
RegisterClassEx(&wndclassex);
// IfThen -> CreateWindows
if(!(hwnd = CreateWindowEx(NULL,"WNDCLASSEX","Hoofdstuk 10",WS_OVERLAPPEDWINDOW
| WS_VISIBLE,50,50,650,300,NULL,NULL,thisInstance,NULL)))
{
return 0;
}
// logische structuur
while(GetMessage(&msg, NULL, 0, 0))
{
if(msg.message == WM_QUIT)
break;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int) msg.wParam;
};
header file:
/*Hoofdstuk 10, Deelnemer.h*/
//Declaratie
class Deelnemer
{
private:
char* nm;
public:
//Constructor
Deelnemer(){
}
//Methoden = prototype
void Deelnemer::Invoeren();
char* Deelnemer::WeergevenNaam();
};
//Implemenmtatie.Invoeren
void Deelnemer::Invoeren()
{
nm = "Roy";
}
//.Weergeven
char* Deelnemer::WeergevenNaam()
{
return nm;
}
callback_NYCM.h:
/*Hoofdstuk 10, Callback_NYCM*/
#include "Windows.h"
#include "Deelnemer.h"
// prototype
LRESULT CALLBACK WndProc(HWND hwnd,UINT message,WPARAM wparam,LPARAM lparam);
//Implementatie
LRESULT CALLBACK WndProc(HWND hwnd,UINT message,WPARAM wparam,LPARAM lparam)
{
//Constructie
PAINTSTRUCT ps;
HDC hdc;
MSG msg;
WNDCLASSEX wndclassex;
// HWND hwnd;
Deelnemer deelnemer1;
//UI
switch(message)
{
case WM_PAINT:
{
//Functieaanroep.Initialisatie
deelnemer1.Invoeren();
//.TextOut
TextOut(hdc,50,50,deelnemer1.WeergevenNaam(),
strlen(deelnemer1.WeergevenNaam()));
EndPaint(hwnd,&ps);
return 0;
}
break;
case WM_DESTROY:
{
PostQuitMessage(0);
return 0;
}
break;
default:
{
return DefWindowProc(hwnd,message,wparam,lparam);
}
break;
}
return 0;
}
I think my constructor or something like that is wrong and my return value for char* Deelnemer::WeergevenNaam()
Could somebody explain me what is wrong in my code so I know how to get it working?
UPDATE:
Updating your application requires to use UNICODE string literals
throughout, i.e. L"MyString" instead of "MyString". You also need to
use WCHAR/wchar_t in place of char
But how do i do this with my code, could somebody help?
UPDATE 2:
That solved al lot of errors!
But i have some more errors left in this part
Deelnemer deelnemer1;
switch(message)
{
case WM_PAINT:
{
//Functieaanroep.Initialisatie
deelnemer1.Invoeren();
//.TextOut
TextOut(hdc,50,50,deelnemer1.WeergevenNaam(),
strlen(deelnemer1.WeergevenNaam()));
EndPaint(hwnd,&ps);
return 0;
}
so the errors are on line: deelnemer1.WeergevenNaam()
-TextOutW' : cannot convert parameter 4 from 'char *' to 'LPCWSTR'
-IntelliSense: argument of type "char *" is incompatible with parameter of type "LPCWSTR"
UPDATE 3:
After some testing i found a solution (like you guys said below) But now i only got this one left:
TextOut (hdc,50,50,deelnemer1.WeergevenNaam(), // on the deelnemer1.weergevenNaam()
with error C2664: 'TextOutW' : cannot convert parameter 4 from 'const char *' to 'LPCWSTR'
Your code is written to compile as ANSI but your solution settings include _UNICODE/UNICODE. You can either set your solution to use ANSI encoding by changing Character Set (on the General node of the Configuration Properties) from Use Unicode Character Set to Use Multi-Byte Character Set or update your application code (the latter is recommended).
Updating your application requires to use UNICODE string literals throughout, i.e. L"MyString" instead of "MyString". You also need to use WCHAR/wchar_t in place of char (where applicable) and call the wide versions of the Windows API. For many API calls there exists a wide version that has a W at the end, e.g. CreateWindowExW. If you are using the Standard C++ Library you will also want to make sure to use the UNICODE variants where character encoding is necessary (e.g. std::wstring instead of std::string). Additional information can be found at Text and Strings in Visual C++.
A bit more background about what is going on here: The Windows API and Microsoft's CRT implementation can be used to compile code using ANSI/Multi-Byte character set or UNICODE character set. To support both character encodings the C/C++ preprocessor replaces the respective character types and API calls with the specific implementations depending on whether or not the _UNICODE and UNICODE preprocessor symbol is defined.
For example, the call CreateWindowEx is expanded to either CreateWindowExA or CreateWindowExW. Both implementations have different parameter types for string arguments (char* and wchar_t* respectively). To use ANSI/Multi-Byte encoding the call would be CreateWindowExA(NULL,"WNDCLASSEX",...). For UNICODE it would look like CreateWindowExW(NULL,L"WNDCLASSEX",...).
To see what the code looks like after the preprocessor is through you can use the /P or /E compiler switches (assuming you're using the Microsoft Compiler).
Note: Don't forget to read The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!).
simple answer - with no explanation of why
change quoted strings to L"foo"
change char to wchar_t
LPCWSTR -> Long Pointer to Constant Wide Character String.
All of your error messages reduce to some form of char[XX] is not the same type as wchar_t[XX].
Microsoft's Win32 API's are designed to compile either with ANSI strings, char, or wide character strings, wchar_t. This is why many Win32 function have two signatures, one ending in A, the other in W.
Example:
CreateWindowExW
CreateWindowExA
CreateWindowEx - A macro that expands to one of the above signatures depending on your build configuration. If you define UNICODE or _UNICODE it will expand to the W version.
Typically you use the macros when you are programming in Win32, and wrap all of your string literals with the _T macro. When defining character arrays that are strings, you'll want to use LPCTSTR and LPTSTR. These are also macros which will expand to either char * or wchar_t * depending on your build settings.
I have it working. The use wchar_t * and L"string". The problem with my code was more the structure because copy/pasting to a new project solved my errors. Thanks guys!
By choosing "not set" on Character Set in Project > Property > Configuration Properties > General, I was able to remove errors C2440 and C2264.
Related
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"));
I am trying to get properties from an HWND. I'm used information from Using Window Properties, but the example below is not working for me. I'm getting an error while compiling my code.
argument of type "BOOL (__stdcall *)(HWND hwndSubclass, LPCSTR lpszString, HANDLE hData)" is incompatible with parameter of type "PROPENUMPROCEXW"
Here is my callback function
BOOL CALLBACK PropEnumProcEx(HWND hwndSubclass, LPCSTR lpszString, HANDLE hData) {
return TRUE;
}
and this how I'm using it
EnumPropsEx(hwnd, PropEnumProcEx, NULL);
Does someone have any suggestions of how this can be fixed?
LPCSTR lpszString should be LPTSTR lpszString. This argument should accept a pointer to either ANSI or Unicode null-terminated string. PROPENUMPROCEXW indicates that you are building Unicode application so EnumPropsEx macro expands to EnumPropsExW call so you need to provide callback accepting wide string as an argument. Typically you should always explicitly call Unicode variants of API functions.
Also you are missing last argument ULONG_PTR dwData.
So your callback should look like:
BOOL CALLBACK
PropEnumProcEx(HWND hwndSubclass, LPTSTR lpszString, HANDLE hData, ULONG_PTR dwData)
{
return TRUE;
}
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
);
I am trying to hook StartDocW to intercept printing via mhook. I use AppInit_DLLs to load my library.
DLL code is simple:
#include <windows.h>
#include "mhook/mhook-lib/mhook.h"
using StartDocPtr = int(*)(HDC, const DOCINFO*);
StartDocPtr orig;
int HookedStartDocW(HDC hdc, const DOCINFO* lpdi) {
return orig(hdc, lpdi);
}
BOOL WINAPI DllMain(__in HINSTANCE, __in DWORD Reason, __in LPVOID) {
orig = (StartDocPtr)GetProcAddress(GetModuleHandle("gdi32"), "StartDocW");
switch (Reason)
{
case DLL_PROCESS_ATTACH:
Mhook_SetHook((PVOID*)&orig, &HookedStartDocW);
break;
case DLL_PROCESS_DETACH:
Mhook_Unhook((PVOID*)&orig);
break;
}
}
Hook is working and printing is done OK. But If I change HookStartDocW to following:
int HookedStartDocW(HDC hdc, const DOCINFO* lpdi) {
char buf[40];
GetModuleFileName(NULL, buf, 40);
return orig(hdc, lpdi);
}
Programs on printing will crash immediately. Even if I just leave char buf[40] and comment GetModuleHandle - program will hang. Why is this happening?
Moreover, if program crashes\hangs on printing (if I add anything besides return orig(hdc, lpdi)) - PC starts to behave very weirdly, refusing to run programs, etc. If I reboot it - Windows just endlessly spins on boot screen, the only way to bring it back to live - is to boot via liveCD and rename\delete my hook DLL.
Printing programs: Excel 2016, notepad.
Compiler - MSVC 2015, x64 release DLL compilation, using MBCS instead of unicode.
Your hook is declared wrong.
Look at the actual declaration of StartDocW() in Wingdi.h:
__gdi_entry WINGDIAPI int WINAPI StartDocW(__in HDC hdc, __in CONST DOCINFOW *lpdi);
You can ignore __gdi_entry. WINGDIAPI simply resolves to __declspec(dllimport). What is important in this declaration is the WINAPI.
Like almost all Win32 API functions, StartDocW() uses the __stdcall calling convention. The WINAPI macro resolves to __stdcall.
Your code does not specify any calling convention at all, so it uses your compiler's default, which is usually __cdecl instead. So you are mismanaging the call stack. That is why your code crashes.
You are also using DOCINFO when you should be using DOCINFOW instead. It is clear in your code that you are compiling for MBCS and not for UNICODE, so DOCINFO maps to DOCINFOA. You can't pass a DOCINFOA to StartDocW(), it expects a DOCINFOW instead.
You need to fix your declarations, eg:
#include <windows.h>
#include "mhook/mhook-lib/mhook.h"
using StartDocPtr = int (WINAPI *)(HDC, const DOCINFOW*);
StartDocPtr orig = nullptr;
int WINAPI HookedStartDocW(HDC hdc, const DOCINFOW* lpdi) {
//...
return orig(hdc, lpdi);
}
BOOL WINAPI DllMain(__in HINSTANCE, __in DWORD Reason, __in LPVOID) {
orig = (StartDocPtr) GetProcAddress(GetModuleHandle(TEXT("gdi32")), "StartDocW");
switch (Reason)
{
case DLL_PROCESS_ATTACH:
Mhook_SetHook((PVOID*)&orig, &HookedStartDocW);
break;
case DLL_PROCESS_DETACH:
Mhook_Unhook((PVOID*)&orig);
break;
}
}
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.