首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> VC >> VC 教學

VC++ 設定桌面牆紙完全指南:從 BMP 到 JPG/PNG 的跨格式方案

     編輯:VC 教學

前言

「如何用 VC++ 設定桌面牆紙?」是論壇高頻提問。舊 API SystemParametersInfo 僅支援 BMP;若要支援 JPG/PNG 等現代格式,必須啟用 **Active Desktop** 介面 IActiveDesktop。本文雙軌並行,給出最完整落地代碼。

方案一:SystemParametersInfo (僅 BMP、極簡單)


BOOL SetWallpaperBMP(LPCTSTR pszBmpPath) {
    return SystemParametersInfo(
        SPI_SETDESKWALLPAPER, 0,
        (PVOID)pszBmpPath,
        SPIF_SENDWININICHANGE | SPIF_UPDATEINIFILE
    );
}
// 缺點:不支援 JPG/PNG、無法設定填充/拉伸/置中樣式 (需改註冊表並重啟 explorer)

方案二:IActiveDesktop (支援所有格式、完整樣式控制)

環境準備

  • 標頭:#include <shlobj.h>、#include <wininet.h> (順序敏感,置於 afxext.h 之後)
  • 庫:#pragma comment(lib, "wininet.lib")
  • COM 初始化:`AfxOleInit()` 或 `CoInitialize(NULL)` 在 `CWinApp::InitInstance` 中
  • 最低系統:Win2000 / IE4.0+ (現代 Windows 皆內建)

完整實作代碼


BOOL SetWallpaperEx(LPCTSTR pszImagePath, DWORD dwStyle = WPSTYLE_CENTER)
{
    // 1. 建立 IActiveDesktop 介面
    IActiveDesktop* pAD = NULL;
    HRESULT hr = CoCreateInstance(CLSID_ActiveDesktop, NULL, CLSCTX_INPROC_SERVER,
                                  IID_IActiveDesktop, (void**)&pAD);
    if (FAILED(hr)) return FALSE;

    // 2. 啟用 Active Desktop (必要步驟,否則 SetWallpaper 失效)
    COMPONENTSOPT co = { sizeof(COMPONENTSOPT) };
    co.fEnableComponents = TRUE;
    co.fActiveDesktop = TRUE;
    hr = pAD->SetDesktopItemOptions(&co, 0);
    if (FAILED(hr)) { pAD->Release(); return FALSE; }

    // 3. 字串轉寬字元 (SetWallpaper 參數為 LPCWSTR)
    WCHAR wszPath[MAX_PATH];
    MultiByteToWideChar(CP_ACP, 0, pszImagePath, -1, wszPath, MAX_PATH);

    // 4. 設定牆紙路徑
    hr = pAD->SetWallpaper(wszPath, 0);
    if (FAILED(hr)) { pAD->Release(); return FALSE; }

    // 5. 設定顯示樣式
    WALLPAPEROPT wo = { sizeof(WALLPAPEROPT) };
    wo.dwStyle = dwStyle; // WPSTYLE_CENTER | WPSTYLE_TILE | WPSTYLE_STRETCH | WPSTYLE_MAX (Win7+)
    hr = pAD->SetWallpaperOptions(&wo, 0);
    if (FAILED(hr)) { pAD->Release(); return FALSE; }

    // 6. 套用變更
    hr = pAD->ApplyChanges(AD_APPLY_ALL);
    pAD->Release();
    return SUCCEEDED(hr);
}

// 使用範例
SetWallpaperEx(_T("C:\\Pictures\\photo.jpg"), WPSTYLE_STRETCH); // 拉伸填滿
SetWallpaperEx(_T("C:\\Pictures\\logo.png"), WPSTYLE_CENTER);   // 置中

樣式旗標對照表

旗標效果備註
WPSTYLE_CENTER置中,不縮放預設
WPSTYLE_TILE平鋪重複
WPSTYLE_STRETCH拉伸填滿 (可能變形)
WPSTYLE_MAX縮放填滿保持比例 (Win7+)「填滿」模式
WPSTYLE_MIN縮放適應保持比例 (Win7+)「適應」模式

進階:動態切換牆紙 (定時器/隨機/網路下載)


void CRotateWallpaperDlg::OnTimer(UINT_PTR nIDEvent) {
    static int idx = 0;
    CStringArray paths;
    paths.Add(_T("C:\\Wallpaper\\1.jpg"));
    paths.Add(_T("C:\\Wallpaper\\2.png"));
    paths.Add(_T("C:\\Wallpaper\\3.bmp"));

    SetWallpaperEx(paths[idx % paths.GetCount()], WPSTYLE_STRETCH);
    idx++;
    CDialog::OnTimer(nIDEvent);
}

常見坑與對策

現象原因對策
SetWallpaper 返回 0x80004005 (E_FAIL)Active Desktop 未啟用務必先呼叫 SetDesktopItemOptions 設 fActiveDesktop=TRUE
JPG/PNG 顯示為黑色/空白路徑編碼錯誤 (ANSI/Unicode 不匹配)統一用 MultiByteToWideChar 或專案設定 Unicode 字元集
套用後桌面圖示閃爍/重排ApplyChanges 觸發 explorer 重繪正常現象;若頻繁切換可考慮直接操作註冊表 Wallpaper 值 + SPIF_SENDWININICHANGE
多顯示器不同牆紙IActiveDesktop 僅支援單一牆紙Win10+ 需用 IDesktopWallpaper (VirtualDesktop API)

現代替代:IDesktopWallpaper (Win8+、多顯示器、更簡潔)


#include 
#pragma comment(lib, "shell32.lib")

void SetWallpaperModern(LPCWSTR pszPath, DESKTOP_WALLPAPER_POSITION pos = DWPOS_CENTER) {
    IDesktopWallpaper* pDW = NULL;
    CoCreateInstance(CLSID_DesktopWallpaper, NULL, CLSCTX_INPROC_SERVER,
                     IID_IDesktopWallpaper, (void**)&pDW);
    if (pDW) {
        pDW->SetWallpaper(NULL, pszPath);      // NULL = 所有顯示器
        pDW->SetPosition(pos);
        pDW->Release();
    }
}

結語

從 SystemParametersInfo 的 BMP 時代,到 IActiveDesktop 的全格式支援,再到 IDesktopWallpaper 的多螢幕原生體驗,Windows 牆紙 API 見證了桌面演進。**核心心法**:(1) 先啟用 Active Desktop;(2) 路徑務必轉寬字元;(3) 別忘了 ApplyChanges。下次需求來時,直接複製 SetWallpaperEx,三分鐘交付,剩下時間喝咖啡。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved