天天看點

如何在程式中動态設定牆紙

标題     如何在程式中動态設定牆紙    zwvista(原作) 

關鍵字     Wallpaper IActiveDesktop

大家都知道設定WINDOWS桌面牆紙的WIN32 API是SystemParametersInfo, 使用SPI_SETDESKWALLPAPER參數便能設定牆紙:

::SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, "C://ABitmap.bmp", SPIF_SENDWININICHANGE | SPIF_UPDATEINIFILE);

但問題并沒有解決,因為這個WIN32 API有很大的局限性

1. 無法把jpeg, gif等其他非位圖格式的圖檔設為牆紙。

2. 無法調整牆紙的式樣,即無法設定牆紙為居中,平鋪或拉伸。(當然我們可以通過程式設計改變系統資料庫HKEY_CURRENT_USER/Control Panel/Desktop的值來做到這一點)

由于在顯示屬性系統對話框内很容易手動設定這些選項,我們有理由相信,Windows Shell API一定提供了相應的比較高層的函數,接口或類來完成牆紙的設定。事實上,Windows Shell API中确實存在完成這個任務的接口:IActiveDesktop。

以下是我所完成的設定牆紙的函數

//strPicFile是圖像檔案名,支援BMP JPEG GIF等格式

//dwStyle是牆紙的樣式

//WPSTYLE_CENTER 居中 0

//WPSTYLE_TILE 平鋪 1

//WPSTYLE_STRETCH 拉伸 2

//WPSTYLE_MAX 3

//傳回值是TRUE時牆紙設定成功,傳回FALSE時失敗

BOOL SetWallpaper(CString &strPicFile, DWORD dwStyle)

{

  HRESULT hr;

  IActiveDesktop* pIAD;

  //建立接口的執行個體

  hr = CoCreateInstance ( CLSID_ActiveDesktop,  NULL, CLSCTX_INPROC_SERVER,      

              IID_IActiveDesktop, (void**) &pIAD );

  if(!SUCCEEDED(hr)) return FALSE;

  //将檔案名改為寬字元串,這是IActiveDesktop::SetWallpaper的要求

  WCHAR   wszWallpaper [MAX_PATH];

  LPTSTR lpStr = strPicFile.GetBuffer(strPicFile.GetLength() );

  MultiByteToWideChar(CP_ACP, 0, lpStr, -1, wszWallpaper, MAX_PATH);

  strPicFile.ReleaseBuffer();

  //設定牆紙

  hr = pIAD->SetWallpaper(wszWallpaper, 0);

  if(!SUCCEEDED(hr)) return FALSE;

  //設定牆紙的樣式

  WALLPAPEROPT wpo;

  wpo.dwSize = sizeof(wpo);

  wpo.dwStyle = dwStyle;

  hr = pIAD->SetWallpaperOptions(&wpo, 0);

  if(!SUCCEEDED(hr)) return FALSE;

  //應用牆紙的設定

  hr = pIAD->ApplyChanges(AD_APPLY_ALL);

  if(!SUCCEEDED(hr)) return FALSE;

  //讀取牆紙的檔案名并列印在debug視窗内

  hr = pIAD->GetWallpaper(wszWallpaper, MAX_PATH, 0);

  CString strFile = wszWallpaper;

  TRACE(strFile); //如果不用位圖的話,這裡有你意想不到的發現

  //釋放接口的執行個體

  pIAD->Release();

  return TRUE;

}

在MFC程式中應用此函數時,須注意以下三點。

1.在函數所在檔案中加上聲明IActiveDesktop的頭檔案

#include<shlobj.h>

2.在StdAfx.h中插入#include <wininet.h>

位置不能搞錯,否則IActiveDesktop将找不到定義

#include <afxwin.h>     // MFC core and standard components

#include <wininet.h> // NOTE: corrects compilation errors w/IActiveDesktop!!

#include <afxext.h>     // MFC extensions

3.由于此函數引用了COM元件,是以必須在C**App::OnInitInstance()中插入以下語句,初始化COM元件。

AfxOleInit();

補充:

隻有在安裝了IE4.0及以上版本時才能應用IActiveDesktop接口,隻有在打開active desktop(活動桌面)的情況下才能應用SetWallpaper函數,下面是啟用或關閉active desktop的函數:

//bEnable是TRUE時啟用active desktop, 是FALSE時關閉

//傳回值是TRUE時啟用或關閉active desktop成功,傳回FALSE時失敗

BOOL EnableActiveDesktop(BOOL bEnable)

{

  HRESULT hr;

  IActiveDesktop* pIAD;

  //建立接口的執行個體

  hr = CoCreateInstance ( CLSID_ActiveDesktop,  NULL, CLSCTX_INPROC_SERVER,      

              IID_IActiveDesktop, (void**) &pIAD );

  if(!SUCCEEDED(hr)) return FALSE;

  COMPONENTSOPT comp;

  comp.dwSize = sizeof(comp);

  comp.fEnableComponents = bEnable;

  //啟用或關閉active desktop

  comp.fActiveDesktop = bEnable;

  hr = pIAD->SetDesktopItemOptions(&comp, 0);

  if(!SUCCEEDED(hr)) return FALSE;

  //釋放接口的執行個體

  pIAD->Release;

  return TRUE;

}

繼續閱讀