I'm trying to compile some code, but I'm getting an error:
Error invalid conversion from DWORD to const char *
Here's the code I'm trying to compile:
hWindow = FindWindow(NULL, "Window");
if (hWindow){
GetWindowThreadProcessId(hWindow, &pid);
}
hProcess = OpenProcess(PROCESS_ALL_ACCESS, 0, pid);
if(hProcess != NULL) {
SetWindowText(GetDlgItem(MyWindow, MyStatic), pid);
}
How do I convert a DWORD to a const char *?
SetWindowText expects a const char * (i.e. a C-string) and you are passing it a number (pid), it's obvious that you get an error.
The standard C++ way to perform the conversion is to use a string stream (from header <sstream>:
std::ostringstream os;
os<<pid;
SetDlgItemText(MyWindow, MyStatic, os.str().c_str());
(here I used SetDlgItemText instead of GetDlgItem+SetWindowText to save typing, but it's the same thing)
Alternatively, you can use snprintf.
char buffer[40];
snprintf(buffer, sizeof(buffer), "%u", pid);
SetDlgItemText(MyWindow, MyStatic, buffer);
In this line
SetWindowText(GetDlgItem(MyWindow, MyStatic), pid);
pid is a DWORD (as you used it in GetWindowThreadProcessId(hWindow, &pid) which takes a LPDWORD as the second argument). However, SetWindowText expects a C-string as it's second argument, so instead of pid, you must pass a value of type char * or char [].
To display the value of pid, you can make use of sprintf:
char * str = new char[10];
sprintf(str,"%d",pid);
You may have to modify the size of str a little (10 might be too small, or bigger than necessary - that's up to you and your situation).
Related
After getting a struct from C# to C++ using C++/CLI:
public value struct SampleObject
{
LPWSTR a;
};
I want to print its instance:
printf(sampleObject->a);
but I got this error:
Error 1 error C2664: 'printf' : cannot convert parameter 1 from
'LPWSTR' to 'const char *'
How can I convert from LPWSTR to char*?
Thanks in advance.
Use the wcstombs() function, which is located in <stdlib.h>. Here's how to use it:
LPWSTR wideStr = L"Some message";
char buffer[500];
// First arg is the pointer to destination char, second arg is
// the pointer to source wchar_t, last arg is the size of char buffer
wcstombs(buffer, wideStr, 500);
printf("%s", buffer);
Hope this helped someone! This function saved me from a lot of frustration.
Just use printf("%ls", sampleObject->a). The use of l in %ls means that you can pass a wchar_t[] such as L"Wide String".
(No, I don't know why the L and w prefixes are mixed all the time)
int length = WideCharToMultiByte(cp, 0, sampleObject->a, -1, 0, 0, NULL, NULL);
char* output = new char[length];
WideCharToMultiByte(cp, 0, sampleObject->a, -1, output , length, NULL, NULL);
printf(output);
delete[] output;
use WideCharToMultiByte() method to convert multi-byte character.
Here is example of converting from LPWSTR to char*
or wide character to character.
/*LPWSTR to char* example.c */
#include <stdio.h>
#include <windows.h>
void LPWSTR_2_CHAR(LPWSTR,LPSTR,size_t);
int main(void)
{
wchar_t w_char_str[] = {L"This is wide character string test!"};
size_t w_len = wcslen(w_char_str);
char char_str[w_len + 1];
memset(char_str,'\0',w_len * sizeof(char));
LPWSTR_2_CHAR(w_char_str,char_str,w_len);
puts(char_str);
return 0;
}
void LPWSTR_2_CHAR(LPWSTR in_char,LPSTR out_char,size_t str_len)
{
WideCharToMultiByte(CP_ACP,WC_COMPOSITECHECK,in_char,-1,out_char,str_len,NULL,NULL);
}
Here is a Simple Solution. Check wsprintf
LPWSTR wideStr = "some text";
char* resultStr = new char [wcslen(wideStr) + 1];
wsprintfA ( resultStr, "%S", wideStr);
The "%S" will implicitly convert UNICODE to ANSI.
Don't convert.
Use wprintf instead of printf:
wprintf
See the examples which explains how to use it.
Alternatively, you can use std::wcout as:
wchar_t *wstr1= L"string";
LPWSTR wstr2= L"string"; //same as above
std::wcout << wstr1 << L", " << wstr2;
Similarly, use functions which are designed for wide-char, and forget the idea of converting wchar_t to char, as it may loss data.
Have a look at the functions which deal with wide-char here:
Unicode in Visual C++
What I'm trying to achieve is getting my program executed on Windows startup using the Registry. When I try to put the file location, the compiler complains it cannot convert from filesystem::path to const BYTE*. I have no idea how to fix this, since I'm a beginner when it comes to C++. I have provided the code below:
HKEY newValue;
RegOpenKey(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Run", &newValue);
RegSetValueEx(newValue, "myprogram", 0, REG_SZ, fs::temp_directory_path().append(filename), sizeof("tes3t")); // This line is the issue. fs::temp_directory_path().append(filename)
RegCloseKey(newValue);
return 0;
EXCEPTION: No suitable conversion function from "std:filesystem::path" to "const BYTE *" exists
Per the RegSetValueExA() documentation, the function does not accept a std::filesystem::path object. That is what the error message is complaining about.
LSTATUS RegSetValueExA(
HKEY hKey,
LPCSTR lpValueName,
DWORD Reserved,
DWORD dwType,
const BYTE *lpData, // <-- here
DWORD cbData
);
The 5th parameter takes a const BYTE* pointer to a null-terminated C-style string. The 6th parameter takes the number of characters in the string, including the null terminator:
lpData
The data to be stored.
For string-based types, such as REG_SZ, the string must be null-terminated. With the REG_MULTI_SZ data type, the string must be terminated with two null characters.
Note lpData indicating a null value is valid, however, if this is the case, cbData must be set to '0'.
cbData
The size of the information pointed to by the lpData parameter, in bytes. If the data is of type REG_SZ, REG_EXPAND_SZ, or REG_MULTI_SZ, cbData must include the size of the terminating null character or characters.
std::filesystem::path does not have an implicit conversion to const BYTE*, hence the compiler error. You need to explicitly convert the path to a std::string or std::wstring first (prefer the latter, since the Registry stores strings as Unicode internally), before you can then save that string value to the Registry, eg:
// using std::string...
HKEY newValue;
// don't use RegOpenKey()! It is provided only for backwards compatibility with 16bit apps...
if (RegOpenKeyExA(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Run", 0, KEY_SET_VALUE, &newValue) == 0)
{
// this may lose data for non-ASCII characters!
std::string s = fs::temp_directory_path().append(filename).string();
// this will convert the ANSI string to Unicode for you...
RegSetValueExA(newValue, "myprogram", 0, REG_SZ, reinterpret_cast<LPCBYTE>(s.c_str()), s.size()+1);
RegCloseKey(newValue);
}
return 0;
// using std::wstring...
HKEY newValue;
// don't use RegOpenKey()! It is provided only for backwards compatibility with 16bit apps...
if (RegOpenKeyExW(HKEY_CURRENT_USER, L"Software\\Microsoft\\Windows\\CurrentVersion\\Run", 0, KEY_SET_VALUE, &newValue) == 0)
{
// no data loss here!
std::wstring s = fs::temp_directory_path().append(filename).wstring();
// no ANSI->Unicode conversion is performed here...
RegSetValueExW(newValue, L"myprogram", 0, REG_SZ, reinterpret_cast<LPCBYTE>(s.c_str()), (s.size()+1) * sizeof(WCHAR));
RegCloseKey(newValue);
}
return 0;
The WinAPI functions do not take arguments of std::filesystem::path type so you need to convert it to a const BYTE* somehow.
This is one example:
std::string fullpath = (fs::temp_directory_path() / filename).string();
RegSetValueEx(
newValue,
"myprogram",
0,
REG_SZ,
reinterpret_cast<LPCBYTE>(fullpath.c_str()), // returns a "const char*" then cast
fullpath.size() + 1 // + 1 for null terminator
);
This is my very first native extension between AIR and C++, and in C++ programming as well, so I am not sure where to look for help with type conversions.
From AIR side I receive a string in uint8_t (FRE... function call). I need to use this string for writing to registry, where wchar_t is expected.
I am not sure if I can simply make a type casting, or make new wchar[] array of the same size and copy characters or do I need to use someting like MultiByteToWideChar() to convert UTF-8 characters to wchar_t. Im not sure about the correct size of output array in this case.
...
FREObject retObj = NULL;
uint32_t strLength = 0;
const uint8_t *path8 = NULL;
// this is what I get from actionscript call
FREResult status = FREGetObjectAsUTF8(argv[ARG_PATH], &strLength, &path8);
if ((status != FRE_OK) || (strLength <= 0) || (path8 == NULL)) return retObj;
LONG hStatus;
HKEY hKey;
wchar_t *path;
// ??? how to copy uint_t into wchar_t
hStatus = RegOpenKeyEx(HKEY_CURRENT_USER, path, 0, KEY_ALL_ACCESS, &hKey);
...
std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t> cv;
std::wstring dst = cv.from_bytes(src);
I'm having a bit of trouble with handling unicode conversions.
The following code outputs this into my text file.
HELLO??O
std::string test = "HELLO";
std::string output;
int len = WideCharToMultiByte(CP_OEMCP, 0, (LPCWSTR)test.c_str(), -1, NULL, 0, NULL, NULL);
char *buf = new char[len];
int len2 = WideCharToMultiByte(CP_OEMCP, 0, (LPCWSTR)test.c_str(), -1, buf, len, NULL, NULL);
output = buf;
std::wofstream outfile5("C:\\temp\\log11.txt");
outfile5 << test.c_str();
outfile5 << output.c_str();
outfile5.close();
But as you can see, output is just a unicode conversion from the test variable. How is this possible?
Check if the LEN is correct after first measuring call. In general, you should not cast test.c_str() to LPCWSTR. The 'test' as is 'char'-string not 'wchar_t'-wstring. You may cast it to LPCSTR - note the 'W' missing. The WinAPI has distinction between that. You really should be using wstring if you want to keep widechars in it.. Yeah, after re-reading your code, the test should be a wstring, then you can cast it to LPCWSTR safely.
after reading this
Microsoft wstring reference
I changed
std::string test = "HELLO";
to
std::wstring test = L"HELLO";
And the string was outputted correctly and I got
HELLOHELLO
I have a function that gets a std::string. That function calls
RegSetValueEx
the 5th parameter is the value of the registry value and expects a variable of type const BYTE*.
So I have to convert the std::string to const BYTE* and also give the length of the resulting array as the 6th parameter.
I have found a way to do it, but it feels ugly and I don't really understand what is going on. Here is a slimmed down version of that function:
void function(const std::string& newValue)
{
HKEY keyHandle;
if(RegOpenKeyEx(HKEY_CLASSES_ROOT, TEXT("some key"),0,KEY_ALL_ACCESS,&keyHandle) == ERROR_SUCCESS)
{
std::wstring wNewValue;
wNewValue.assign(newValue.begin(),newValue.end());
if (RegSetValueEx(keyHandle, TEXT("some value"), NULL, REG_SZ, (const BYTE*)(LPCTSTR)(wNewValue.c_str()), wNewValue.size()*2)==ERROR_SUCCESS)
{
//do something
}
RegCloseKey(keyHandle);
}
}
As you can see, i first make a wide string (UNICODE is defined), then use a double cast, and for the length i have to do *2, else it will only set half of the input string.
Is this form of cast the normal/best way to do it?
Why the * 2, what would be a better way?
void function(const std::string& newValue)
{
HKEY keyHandle;
if(RegOpenKeyEx(HKEY_CLASSES_ROOT, TEXT("some key"),0,KEY_ALL_ACCESS,&keyHandle) == ERROR_SUCCESS)
{
if (RegSetValueExA(keyHandle, "some value", NULL, REG_SZ, (const BYTE*)newValue.c_str(), newValue.size() + 1)==ERROR_SUCCESS)
{
//do something
}
RegCloseKey(keyHandle);
}
}
I removed the part where you convert your string to a wstring, instead you'll be using the ANSI version of RegSetValueEx explicitly.
quote from RegSetValueEx remarks in MSDN:
If dwType is the REG_SZ, REG_MULTI_SZ,
or REG_EXPAND_SZ type and the ANSI
version of this function is used
(either by explicitly calling
RegSetValueExA or by not defining
UNICODE before including the Windows.h
file), the data pointed to by the
lpData parameter must be an ANSI
character string. The string is
converted to Unicode before it is
stored in the registry.
Also note that the cbData parameter should include the size of the null termination aswell.
The * 2 is because RegSetValueEx wants to know the number of bytes to write und each char (wchar_t) in a wstring is two bytes wide. So the resulting byte-array has twice the size!
Shouldn't it be wNewValue.size()*2+2 ? The +2 for the null character?
MSDN says: The size of the information pointed to by the lpData parameter, in bytes. If the data is of type REG_SZ, REG_EXPAND_SZ, or REG_MULTI_SZ, cbData must include the size of the terminating null character or characters.
You could also copy the unicode string into a byte array:
LPWSTR pData = L"SampleGrabber";
int dwSize = wcslen(pData)*sizeof(TCHAR);
BYTE slump[256];
memset((void*) slump, 0, 256*sizeof(BYTE));
memcpy((void*) slump, (const void *) pData, dwSize*sizeof(BYTE));
globit = RegSetValueEx(hKey, NULL, 0, REG_SZ, (const BYTE*) slump, dwSize);
If you had the misfortune to be writing code for a WINCE 5.0 device and it lacked part of the regedit API.