如何在程序中动态设置墙纸

大家都知道设置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;
}

前言:

  论坛上经常有网友发贴问怎么实现设置桌面墙纸,并且使用的是jpg文件。虽然在下知道可以用API函数SystemParametersInfo可以设置bmp文件为墙纸,也知道可以用IActiveDesktop来设置其他格式的图片文件作为墙纸,但是工作中一直没有使用到该功能,所以也就一直没实现。

  1.用SystemParametersInfo设置墙纸

  很简单,一句话搞定:

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

  but, 这玩意儿只能用bmp文件,不能用其他文件,MS也不把函数功能扩展一下,BS一下MS。

  再but,这玩意儿也不能设置墙纸的样式,比如平铺,拉伸什么的,虽然可通过修改 注册表修改,但是据那位网友说,需要重启才能生效什么的,我没有试,因为这篇文章的主要目的是讨论用IActiveDesktop设置墙纸。

   2.用IActiveDesktop设置墙纸

  习惯上用任何不太熟悉的函数或接口前,查msdn。

  通过msdn,了解到:

  IActiveDesktop是个windows shell interface
  Header shlobj.h
  Minimum operating systems Windows 2000, Windows NT 4.0 with Internet Explorer 4.0, Windows 98, Windows 95 with Internet Explorer 4.0

  同时,在msdn还有一篇文章

  Using the Active Desktop Object

  其实,看了这篇文章你就应该学会如何使用Active Desktop Object了。

  (1)使用IActiveDesktop需要包含的一些头文件,以及进行初始化

  在stdafx.h中

#include <afxwin.h>
#include <wininet.h> //添加这个。注意顺序,顺序乱了也编译不过
#include <afxext.h>
...

  用了com的东西,要进行初始化,不用说了吧。

  在CXXXApp::Initinstance中添加AfxOleInit();

  使用IActiveDesktop的cpp中

#include <shlobj.h>

  (2) 现在开始写实现函数了

  还是我的老的测试工程CTest6Dlg..呵呵

BOOL CTest6Dlg::SetWallPaper(CString strPath)
{
 HRESULT hr;
 IActiveDesktop* pIAD;

 hr = CoCreateInstance( CLSID_ActiveDesktop, NULL, CLSCTX_INPROC_SERVER,IID_IActiveDesktop, (void**)&pIAD);
 if ( !SUCCEEDED(hr) )
  return FALSE;

 // 设置墙纸前先打开活动桌面开关
 COMPONENTSOPT co = {0};
 co.dwSize = sizeof(COMPONENTSOPT);
 co.fEnableComponents = TRUE;
 co.fActiveDesktop = TRUE;
 hr = pIAD->SetDesktopItemOptions(&co, 0);
 if ( !SUCCEEDED(hr) )
  return FALSE;

 //做以下宽字符的转换是因为SetWallpaper的参数是用的LPCWSTR
 WCHAR wszPath[MAX_PATH];
 LPTSTR lpStr = strPath.GetBuffer(strPath.GetLength());
 MultiByteToWideChar(CP_ACP, 0, lpStr, -1, wszPath, MAX_PATH);
 strPath.ReleaseBuffer();

 // 设置墙纸
 hr = pIAD->SetWallpaper(wszPath, 0);
 if ( !SUCCEEDED(hr) )
  return FALSE;

 // 设置墙纸风格
 WALLPAPEROPT wp = {0};
 wp.dwSize = sizeof(WALLPAPEROPT);
 wp.dwStyle |= WPSTYLE_CENTER;
 hr = pIAD->SetWallpaperOptions(&wp, 0);
 if ( !SUCCEEDED(hr) )
  return FALSE;

 // 应用改变
 hr = pIAD->ApplyChanges(AD_APPLY_ALL);
 if ( !SUCCEEDED(hr) )
  return FALSE;

 // 最后释放接口,不要忘了
 pIAD->Release();
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值