在C++ Builder中实现桌布自动更新

原创 2004年05月13日 12:32:00

 

C++ Builder中要实现桌布的自动更换功能,我认为主要两个关键点,其一既然要“自动”那就免不了要用到定时器,我们可以用Timer这个组件来完成,这个还好解决,第二个问题可能比较麻烦了,我们如何来设置桌布,好像BCB中并没有提供什么组件,那我们也就只好自力更生了,虽说本人只是一只菜鸟,但这个问题还是难不了我,它主要是用到了SystemParametersInfo 这个Windows API函数,它的声明如下:

BOOL SystemParametersInfo(<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

  UINT uiAction, // system parameter to query or set

它是一个非常重量级的函数,主要用来设置或获得系统范围上的相关参数(如:我
正在介绍的“如何设置桌布”,还有如:系统字体,屏幕分辨率等),其实光从字
面上也能大概知道它的作用。如果只是简单的调用SystemParametersInfo函数的话,
问题就变得简单多了,但你要总不能只使用默认的桌布样式,所以在设置桌布之
前还应先设置好桌布的样式,比如:桌布的显示位置,是否填满桌面等,然后在
调用SystemParametersInfo函数,这个函数会根据注册表里的桌布样式设置情况来
设置实际的桌布样式。

与桌布样式有关的注册表设定:(位于HKEY_CURRENT_USER/Control Panel/Desktop键)

键名

含义

WallPaper

桌布的文件名,但只限于BMP格式的位图

WallPaperStyle

设置桌布样式

若为0,桌布将以原始尺寸显示在桌面中央

若为1,桌布将填满桌面

若为2,将桌布放大的画面大小,图像有可能失真

WallPaperOriginX

如果WallPaperStyle0,则这表示图像左上角X轴坐标

WallPaperOriginY

如果WallPaperStyle0,则这表示图像左上角Y轴坐标

 

注意:

其实,上表还漏了TileWallpaper键,这个设定值的优先级最高,即当TileWallpaper这个值为1时,不管其它参数为何值,都会将桌布填满桌面,为了简化程序,一般将其设置为0,然后在根据WallPaperStyle来设置桌布样式,这是比较明智的做法。

 

在了解了与桌布相关的注册表的设置情况后,那我们就进入具体的桌布设置吧!

 

#include

       //先在注册表里添好桌布样式,在设置桌布

  TRegistry *Registry = new TRegistry;

  try

  {

    Registry->OpenKey(“//Control Panel//Desktop”,false);

          Registry->WriteString("TileWallpaper","0");

              //设置桌布样式

Registry->WriteString("WallpaperStyle",wallStyle);

  }

  __finally

  {

    delete Registry;

  }

}

       //设置桌布

SystemParametersInfo(SPI_SETDESKWALLPAPER, 0,FileName.c_str(),SPIF_UPDATEINIFILE | SPIF_SENDWININICHANGE);

 

在此,我们已经解决了最为关键的问题,剩下的关于设置定时器那就简单了,只需用一个定时器组件即可完成.

代码如下:

 

void __fastcall TForm1::Timer1Timer(TObject *Sender)

{

    if (ListBox1->Items->Count<=0)

    {

        return ;

    }

 

    if (index>=ListBox1->Items->Count)

    {

        index=0;

    }

        //如果是JPG格式就将其转换为BMP格式,将其存到临时文件夹中

  if(UpperCase(ListBox1->Items->Strings[index]).Pos(".JPG")||UpperCase(ListBox1->Items->Strings[index]).Pos(".JPEG"))

    {

        AnsiString fileName=ExtractFileName(ListBox1->Items->Strings[index]);

        int len=fileName.LastDelimiter(".");

        fileName=fileName.SubString(0,len-1)+".bmp";

        unsigned int *size=new unsigned int(256);

        char * buffer=new char[256];

        GetTempPath(*size,buffer);

        fileName=AnsiString(buffer)+fileName;

        JPEGToBMP(ListBox1->Items->Strings[index],fileName);

            //设置桌布

      SystemParametersInfo(SPI_SETDESKWALLPAPER,0,ListBox1->Items->Strings[index].c_str(),SPIF_UPDATEINIFILE | SPIF_SENDWININICHANGE);

    }

    else

    {

            //设置桌布

        SystemParametersInfo(SPI_SETDESKWALLPAPER,0,ListBox1->Items->Strings[index].c_str(),SPIF_UPDATEINIFILE | SPIF_SENDWININICHANGE);

    }

        //重建系统缓存

    RebuildIconCache();

    index++;

}

就这样,我们就完成了桌布自动更换的功能,是不是很简单,不过由于它受限于BMP位图格式,这一点总是使得桌布的爱好者十分苦恼.我们能不能让它支持其它格式的图形文件呢?当然可以,原理是这样的,在设置桌布之前,现将其它格式的文件转换为位图,在用SystemParametersInfo函数设置桌布即可搞定.

 

JPEG格式转换为位图:

#include

bool __fastcall TForm1::JPEGToBMP(AnsiString jpegFile,AnsiString bmpFile)

{

    //TODO: Add your source code here

    TJPEGImage *jpeg = new TJPEGImage();

    jpeg->LoadFromFile(jpegFile);

    Graphics::TBitmap *bitmap = new Graphics::TBitmap();

    try {

        bitmap->Assign(jpeg);

        bitmap->SaveToFile(bmpFile);

    }

    __finally {

        delete jpeg;

        delete bitmap;

    }

    return true;

}

遗憾的是BCB不直接支持如PNG,GIF等格式与位图的转换,希望在BCB6.0以后的版本中会得到支持.如果要进行PNG,GIF格式的转换,我们可以去寻求控件,这是最简单的办法,还有一种就是自己编写图形格式转换的程序,这个比较困难.首先要知道各种图形格式的标准,然后编写格式转换的算法,这是最重要的,最后进行编码.还有一点我也想说一下,如果你足够细心的话,可能已经发现了我在实现Timer1Timer(TObject *Sender)这个函数的时候用到了一个RebuildIconCache()函数,注释说是重建系统缓存,其实是这样的当你改变了桌布的时候,可能系统来不及重新绘制桌布,这时你需要手动地按下F5来进行刷新,但我们的程序总不能去叫用户刷新吧,所以我增加了一个RebuildIconCache()函数来完成此功能,它是这样实现的。

void __fastcall TForm1::RebuildIconCache()

{

    //TODO: Add your source code here

    int IconW;

    IconW= GetSystemMetrics(SM_CXICON);

    TRegIniFile *Reg = new TRegIniFile("Control Panel//Desktop");

    try

    {

        Reg->WriteString("WindowMetrics", "Shell Icon Size", IntToStr(IconW));

        SendMessage(HWND_BROADCAST, WM_SETTINGCHANGE, 0, 0);

    }

    __finally

    {

        delete Reg;

    }

}

这样只要你改变了桌布设置,再广播WM_SETTINGCHANGE窗口消息,系统就会进行桌布的重新绘制。

 

提示:如果你想自己体会一下这个程序的功能,你不必通过键盘的输入来达到目的,http://www.zccfamily.com/zqget/ 提供了这个程序的所有源代码,你可以去下载来看一下实际的效果。

 

在阅读本文的过程中,无论是心存感激(我帮你解决了问题)还是心有疑惑(这是不是你的原创,还是在其它地方去抄的),或者对本文有什么评价的话,我的联系方式:

 

mailto:zqget@msn.com

设计模式之Builder模式 (C++实现)

刚开始我一直感觉建造者模式不太好懂,也许是我笨了点缘故,勤能补拙嘛,所以只能多看多想了 大话设计模式里面那个对于建造者模式我讲解,个人感觉不太好理解,我是看了很多遍也没体会到那样设计的精髓,后来在另...
  • i_like_cpp
  • i_like_cpp
  • 2013年05月30日 10:26
  • 2836

自动升级系统的设计与实现(源码)

对于PC桌面应用程序而言,自动升级功能往往是必不可少的。而自动升级可以作为一个独立的C/S系统来开发,这样,就可以在不同的桌面应用中进行复用。基于ESFramework的文件传送功能,我实现了一个可直...
  • zhuweisky
  • zhuweisky
  • 2014年08月22日 14:35
  • 4572

基于visual c++之windows核心编程代码分析(8)自动下载更新程序

我们编写Windows程序,经常需要自动更新,该功能如何实现呢,我们来看代码实现与注释讲解     [cpp] view plain copy ...
  • flyingleo1981
  • flyingleo1981
  • 2016年12月08日 21:50
  • 859

c++builder使用Windows系统提供的IP控件

本文是ccrun(老妖)根据偶然间看到的一篇文章略作修改而成。参考资料: 标题:在Delphi中使用IP控件 作者:西安交通大学9649# 刘明华 在些对原作者的无私奉献表示感谢!如欲转载请保留...
  • lz465350
  • lz465350
  • 2014年11月12日 10:45
  • 626

C++ Builder VCL库函数简介

一.BORLAND C++ BUILDER VCL的内存管理函数   1. AllocMem   在队中分配指定字节的内存块,并将分配的每一个字节初始化为 0.函数原型如下:   void ...
  • lixingshi
  • lixingshi
  • 2014年11月18日 10:12
  • 894

使用 C++ Builder 创建应用程序

3.1 创建应用程序 C++Builder的主要用途于设计创建Windows应用程序。有三种基本的Windows应用程序: · WindowsGUI应用程序。 · 控制面板应用程序。 · 服务应用程序...
  • u010984552
  • u010984552
  • 2016年08月19日 20:18
  • 2047

C++builder(Xe5)下加载VC动态库的两种方法

这里分为两种方式:动态加载的
  • JohnnyHu90
  • JohnnyHu90
  • 2014年10月17日 13:08
  • 3581

C++实现软件自动更新功能

软件时常需要更新,如果通过在线通知用户肯定会更方便,实现原理也很简单,通过获取服务器文件中版本号与软件自身版本号对比,给出提示。下面把实现的代码(C++)贴出来,供大家参考。 0.用到的头文件 ...
  • lmhuanying1012
  • lmhuanying1012
  • 2018年01月10日 08:25
  • 48

C++ Builder初学问与答

一直以来都想写一点为BCB初学者快速入门的东西,前不久写了几篇《闲谈BCB》想把自己学习BCB中如何来解决难点的方法说给大家,没想到被骂得不成样子。本想不写了,但觉得这些东西留下来能做什么呢?还是用另...
  • wozengcong
  • wozengcong
  • 2014年01月04日 16:44
  • 1494

在C++ Builder中用socket api来写网络通讯程序(同时支持TCP和UDP协议)

在7月4日看完sockcomp.pas后,我决定用socket api来写一个客户端和服务器并且同时支持TCP,UDP协议,于是我就去做,现将代码贴出来(已调试通过) Socket api Clie...
  • enjoy0104
  • enjoy0104
  • 2015年04月21日 01:05
  • 1081
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:在C++ Builder中实现桌布自动更新
举报原因:
原因补充:

(最多只允许输入30个字)