问题是您将 UNICODE 字符串 - LPWSTR - 传递给采用 ANSI 的 API。
几乎所有 Win32 API(无论如何都接受字符串)有两个版本,一个以 ...A 结尾的 ANSI(8 位字符),一个以 ...W 结尾的 Wide- char,又名 UNICODE(从技术上讲,它不是“真正的”unicode,但这比在这个回复中得到的更多)。
如果您在编译时有 UNICODE #defined,那么简单的未修饰版本将 #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 很棘手;它的 data 参数需要一个 void*,因此在编译时将接受 [几乎] anything,并且只有在运行时调用该函数时才会遇到错误。
--
顺便说一句,这就是 David Herfernan 在answer to your question the first time you posted 中指出的 -
一些可能的原因浮现在脑海中:
...