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;
}

このコードは単に背景の壁紙を変更するためのものですが、「ファイルが見つかりません」という意味の Error: 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 (とにかく文字列を受け取るすべて) には 2 つのバージョンがあります。1 つは ANSI (8 ビット文字) 用の ...A で終わるバージョンで、もう 1 つはワイド文字 (別名) 用の ...W で終わるバージョンです。 UNICODE (技術的には「本物の」Unicode ではありませんが、この返信で受け取る価値がある以上のものです)。

コンパイル時にUNICODE#defineが指定されている場合、プレーンな飾りのないバージョンが ...W バージョンとして #defined になります。それ以外の場合は、...A バージョンとして #define されます。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 には2 つのSystemParametersInfo 関数があることに注意してください。W はワイド LPWSTR を期待し、A はプレーン LPSTR を期待します。また、UNICODE が定義されているかどうかによって、「デフォルト」のものを選択します。(いつでも手動で A または W を追加して、明示的に呼び出すことができます。)

元のコードで発生する可能性が高いのは、UNICODE が定義されていないため、ANSI 文字列を期待する ...A バージョンを使用することになりますが、UNICODE 文字列を渡しているため、機能しません。 .

動作させるために行った「少しの変更」は、ほんの少しではありません。ANSI 文字列を API の ...A バージョンに渡しているため、正常に動作します。

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 は通常、コードで明示的に定義されるのではなく、メイクファイルまたはコンパイラ設定オプションで定義されるため、Win32 プログラミングに慣れていない場合は、驚くべき機能のようなものになる可能性があります。)

LPWSTR は推奨されていないことに注意してください。どちらかといえば、それは反対です。XP など以降の典型的な Win32 の慣行は、W フレーバーの文字列を全面的に使用することでした。そのため、Win32 で「非推奨」と見なされるのは、実質的にプレーンな「...」文字列です。(たとえば、多くの COM API はワイド文字列のみを使用します。)

他のほとんどの関数には、これに対する保護があります。誤って ANSI 文字列を渡して SetWindowTextW を指定しようとすると、コンパイル時にエラーが発生します。これは、渡した LPSTR が、関数が期待する LPWSTR 型と一致しないためです。しかし、SystemParamtersInfo は注意が必要です。data パラメーターに void* を使用するため、コンパイル時に [ほとんど] すべてを受け入れます。エラーが発生するのは、実行時に関数を呼び出したときだけです

--

ところで、これは、あなたが最初に投稿したときの質問への回答で David Herfernan が指摘したことです-

いくつかの考えられる原因が思い浮かびます:
...
  • 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 に答える