如何将动态字符串转换为 wchar_t 以更改背景

How to convert a dynamic string to wchar_t to change background

我一直在网上寻找一些解决方案,但它们都是从常量字符串转换而来的。 Here's 我使用的一段代码,无需额外的库即可将字符串转换为 wchar_t。我想做的是,我想用我的背景更改 windows 计算机的背景。现在我不能假设我下载的文件夹在 C:\Downloads 中,因为有些人更改了他们的下载文件夹,或者他们可能将整个文件夹移动到另一个位置。所以在第一个代码中,我试图获取 .exe 文件的路径。

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
}

接下来我要将我要制作的图片作为我的背景,放在与 .exe 文件相同的文件夹中。

//error on the third parameter
int return_value = SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, L(string)(GetExePath() + "\picture.png"), SPIF_UPDATEINIFILE);
  1. 错误(活动)E0040 需要一个标识符
  2. 错误(活动)E0020 标识符 "L" 未定义
  3. Error (active) E0254 type name is not allowed
  4. 错误(活动)E0018 需要 ')'

过了一会儿,我替换了函数的 return 类型,所以它会 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;
}

但是,第三个参数显示错误

  1. 错误 E0167 "const wchar_t *" 类型的参数与 "PVOID"
  2. 类型的参数不兼容

那我该如何解决呢?


编辑:有人认为这是重复的,但事实并非如此。 How to convert string to wstring in C++ 与此问题无关,因为在该线程上提问的人正在寻求特殊字符的帮助。

首先调用 Unicode 版本 GetModuleFileNameW(),因此您无需转换。

此外,永远不要 return 指向作为函数局部变量的字符串的指针(除非它是静态的)!否则,您将成为 return 悬空指针。相反,return std::wstring 类似于您的第一个版本。您可以使用 "pointer-to-first-character" 技巧将 std::wstring 直接用作缓冲区。

std::wstring GetExePath() {
    std::wstring buffer(MAX_PATH, L'[=10=]');  // 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
}

第二个错误可以这样修正:

std::wstring path = GetExePath() + L"picture.png";
int return_value = SystemParametersInfoW(SPI_SETDESKWALLPAPER, 0, &path[0], SPIF_UPDATEINIFILE); 

SystemParametersInfoWpvParam参数是指向非常量数据的指针,所以我们又要在这里使用"pointer-to-first-character"的技巧(避免难看的const_cast ).

对于 C++17,这可以写成一行代码:

int return_value = SystemParametersInfoW(SPI_SETDESKWALLPAPER, 0, (GetExePath() + L"picture.png").data(), SPIF_UPDATEINIFILE); 

其他需要改进的地方,留作练习:

  • GetModuleFileName() MSDN reference 的注释中所述检查错误条件 ERROR_INSUFFICIENT_BUFFER 以便您可以支持长于 MAX_PATH.
  • 的路径