0
#include <iostream>
#include <windows.h>
using namespace std;

int main(){
    LPWSTR test = L"c:/aizen.png";
    int result = SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, test, SPIF_UPDATEINIFILE);
    if(result)
        cout << "Wallpaper set!";
    else
        cout << "Error: " << GetLastError();
    cin >> result;
    return 0;
}

该代码只是为了更改背景墙纸,但我不断收到错误:2,这意味着“找不到文件”。但是,文件在那里!我正在使用 microsoft visual studio 2010,我尝试以管理员身份运行、区分大小写、更改斜杠等。我做错了什么?

4

3 回答 3

2

错误 2 是File not found

首先,确保它aizen.png实际上位于驱动器的根文件夹中C:\(在 Vista 及更高版本上不太可能,因为非管理员用户通常没有那里的写入权限)。

如果文件确实存在,则问题很可能是您没有正确转义反斜杠:

LPWSTR test = L"c:\\aizen.png";
于 2013-02-03T07:25:21.913 回答
1

问题是您将 UNICODE 字符串 - LPWSTR- 传递给采用 ANSI 的 API。

几乎所有 Win32 API(无论如何都接受字符串)有两个版本,一个以 ...A 结尾的 ANSI(8 位字符),一个以 ...W 结尾的宽字符,又名UNICODE(技术上不是“真正的”unicode,但这比这个回复更值得)。

如果您#define在编译时有 UNICODE d,那么简单的未修饰版本将 #defined 为 ...W 版本;否则它会被 #defined 定义为 ...A 版本。看看winuer.h,你会看到:

WINUSERAPI
BOOL
WINAPI
SystemParametersInfoA(
    __in UINT uiAction,
    __in UINT uiParam,
    __inout_opt PVOID pvParam,
    __in UINT fWinIni);
WINUSERAPI
BOOL
WINAPI
SystemParametersInfoW(
    __in UINT uiAction,
    __in UINT uiParam,
    __inout_opt PVOID pvParam,
    __in UINT fWinIni);
#ifdef UNICODE
#define SystemParametersInfo  SystemParametersInfoW
#else
#define SystemParametersInfo  SystemParametersInfoA
#endif // !UNICODE

请注意,Windows 有两个SystemParametersInfo 函数;W 期望宽 LPWSTR 而 A 期望普通 LPSTR;以及是否定义了 UNICODE 选择哪个是“默认”。(您始终可以手动添加 A 或 W 以显式调用。)

在您的原始代码中可能发生的情况是,由于您没有定义 UNICODE,您最终会使用 ...A 版本,它需要一个 ANSI 字符串,但您传递的是一个 UNICODE 字符串 - 所以它不起作用.

您为使其正常工作所做的“一点改变”不仅仅是一点点:您现在将一个 ANSI 字符串传递给 ...A 版本的 API,因此它可以正常工作:

int result = SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, (void*)"c:/aizen.jpg", SPIF_UPDATEINIFILE);

或者,您可以使用 LPWSTR 显式调用 W 版本:

int result = SystemParametersInfoW(SPI_SETDESKWALLPAPER, 0, L"c:\\aizen.jpg", SPIF_UPDATEINIFILE);

或者,您可以在应用程序的开头定义 UNICODE,使用 L"..." 字符串和 API 的普通版本 - 只需在 #include 之前在原始应用程序顶部添加 #define UNICODE 。(UNICODE 通常在 makefile 或编译器设置选项中定义,而不是在代码中显式定义,因此,如果您是 Win32 编程的新手,它可能会带来一些惊喜。)

请注意,推荐使用 LPWSTR;如果有的话,情况正好相反;自 XP 左右以来,典型的 Win32 实践一直是全面使用 W 风格的字符串,因此它实际上是在 Win32 上被视为“弃用”的普通“...”字符串。(例如,许多 COM API 只使用宽字符串。)

大多数其他功能对此都有一些保护;如果您不小心尝试传递一个 ANSI 字符串来表示 SetWindowTextW,您将收到编译时错误,因为您传入的 LPSTR 与函数期望的预期 LPWSTR 类型不匹配。但是 SystemParamtersInfo 很棘手;它需要一个 void* 作为 data 参数,因此在编译时将接受 [几乎]任何东西,并且只有在运行时调用该函数时才会遇到错误。

--

顺便说一句,这是大卫赫弗南在您第一次发布问题时在回答您的问题时指出的-

一些可能的原因浮现在脑海中:
...
  • 您的 ANSI/Unicode 编码不匹配。
于 2013-02-04T06:02:12.557 回答
-1

看起来很奇怪,如果您使用 MinGW c++ 编译器进行编译,它实际上会通过一些更改来编译它:

int main(){
        int result = SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, (void*)"c:/aizen.jpg", SPIF_UPDATEINIFILE);

这会起作用,显然 LPWSTR 已被弃用...... Visual Studio 可能存在权限问题。以管理员身份运行,然后重试。

于 2013-02-04T01:51:30.667 回答