问题是您将 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 参数,因此在编译时将接受 [几乎]任何东西,并且只有在运行时调用该函数时才会遇到错误。
--
顺便说一句,这是大卫赫弗南在您第一次发布问题时在回答您的问题时指出的-
一些可能的原因浮现在脑海中:
...