标題 如何在程式中動态設定牆紙 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;
}