I've been looking around the internet for some solutions however they all convert it from a constant string. Here's a piece of code I took to convert strings to wchar_t without additional libraries. What I'm trying to do is, I want to change the background of my windows computer with my background. Now I can't assume that the folder that I downloaded is in C:\Downloads because some people change their downloads folder or maybe they moved the whole folder to another location. So in the first code, I'm trying to get the path of the .exe file.
string GetExePath() {
char buffer[MAX_PATH];
GetModuleFileNameA(NULL, buffer, MAX_PATH);
string::size_type pos = string(buffer).find_last_of("\\/");
return string(buffer).substr(0, pos + 1);//gets the first character in path up to the final backslash
}
Next I'm going to grab the picture that I want to make as my background in the same folder as the .exe file.
//error on the third parameter
int return_value = SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, L(string)(GetExePath() + "\\picture.png"), SPIF_UPDATEINIFILE);
After a while, I replaced the return type of the function and so it would return wchar_t*.
const wchar_t* GetExePath() {
char buffer[MAX_PATH];
GetModuleFileNameA(NULL, buffer, MAX_PATH);
string::size_type pos = string(buffer).find_last_of("\\/");
string path = string(buffer).substr(0, pos + 1);
path += "\\HandleCamWallpaperwithgradient.png";
cout << path << endl;
wstring wide;
for (int i = 0; i < path.length(); ++i){
wide += wchar_t(path[i]);
}
const wchar_t* result = wide.c_str();
return result;
}
However, the third parameter is showing an error saying
So how can I fix it?
Edit: Someone thought that this was a duplicate and it isn't. How to convert string to wstring in C++ is NOT correlated with this question as the one who is asking on that thread is asking help for special characters.
Call the Unicode version GetModuleFileNameW()
in the first place so you don't have to convert.
Also, never return a pointer to a string that is a local variable of a function (unless it is static)! Otherwise you will be returning a dangling pointer. Instead, return a std::wstring
similar to your first version. You can use std::wstring
directly as the buffer by using the "pointer-to-first-character" trick.
std::wstring GetExePath() {
std::wstring buffer(MAX_PATH, L'\0'); // reserve buffer
int len = GetModuleFileNameW(NULL, &buffer[0], buffer.size() );
buffer.resize(len); // resize to actual length
string::size_type pos = buffer.find_last_of(L"\\/");
return buffer.substr(0, pos + 1);//gets the first character in path up to the final backslash
}
The second error can be fixed like this:
std::wstring path = GetExePath() + L"picture.png";
int return_value = SystemParametersInfoW(SPI_SETDESKWALLPAPER, 0, &path[0], SPIF_UPDATEINIFILE);
The pvParam
parameter of SystemParametersInfoW
is a pointer to non-const data, so we have to use the "pointer-to-first-character" trick here again (to avoid ugly const_cast
).
With C++17, this could be written as a one-liner:
int return_value = SystemParametersInfoW(SPI_SETDESKWALLPAPER, 0, (GetExePath() + L"picture.png").data(), SPIF_UPDATEINIFILE);
Other things to improve, left as an exercise:
ERROR_INSUFFICIENT_BUFFER
as described in the comments of GetModuleFileName()
MSDN reference so you can support pathes longer than MAX_PATH
.