首 页 网络编程
网页制作 图形图象 操作系统 冲浪宝典
软件教学 认证考试

网络安全 网络办公 行业资讯 评测对比
您当前位置:站长天空 -> 网络编程-> Visual Basic教程
浅析桌面精灵的实现_delphi教程
作者:网友供稿 点击:0
推荐
西部数码-全国虚拟主机10强!20余项虚拟主机管理功能,全国领先!第6代双线路虚拟主机,南北访问畅通无阻!可在线rar解压,自动数据恢复设置虚拟目录等.免费赠送访问统计,企业邮局.Cn域名注册10元/年,自助建站480元起,免费试用7天,满意再付款!P4主机租用799元/月.月付免压金
站内搜索
文章页数:[1] 

1    软件的开发目的


想必大家对桌面精灵很熟悉吧,想不想自己编一个?笔者非常想编一个,其目的居然是为了取得美眉的喜欢,由此引出了我开发本软件的目的。如果读者有我同样的需求,那么请继续看下去,我将和你共同探讨这个问题。注意以下示例代码均用DELPHI描述。

2    实现原理


其实桌面精灵的原理很简单,主要分以下几步:

1.获取桌面窗口的HDC。

    API 定义如下:

    GetDC函数用于获取指定窗口的图形设备描述表

    HDC GetDC(

    HWND hWnd   // 窗口句柄

    );

    例如:

    DeskTopDC:HDC;//定义桌面窗口的图形设备描述表句柄

    DeskTopDC:=GetDC(0);

    或者DeskTopDC:=GetDC(GetDesktopWindow());

2.创建一个内存位图,把桌面中将要绘图的区域,保存到内存位图中去,以便绘图完成时恢复桌面。为此我定义了一个函数:

    procedure savebackground(BKCanvas :TCanvas;//内存位图的画布对象

                        sp_w:integer;//要保存区域的宽度

                        sp_h :integer ;//要保存区域的高度

                        nx:integer;//要保存区域的X坐标

                        ny:integer);//要保存区域的Y坐标

3.将动画对象透明地拷贝到桌面的绘图区域,笔者用了一个GDIAPI函数方便地实现了此功能。

    定义如下:

    BOOL TransparentBlt(HDC hdcDest,//目标图形设备描述表句柄

                        int nXOriginDest,//绘图矩形的X坐标

                        int nYOriginDest,//绘图矩形的Y坐标

                        int nWidthDest,//绘图矩形的宽度

                        int hHeightDest,//绘图矩形的高度

                        HDC hdcSrc,//源图形设备描述表句柄

                        int nXOriginSrc,//源绘图矩形的X坐标

                        int nYOriginSrc,//源绘图矩形的Y坐标

                        int nWidthSrc,//源绘图矩形的宽度

                        int nHeightSrc,//源绘图矩形的高度

                        UINT crTransparent//设置透明色RGB(r,g,b)

                        );

    注意:

    Windows NT: 需要5.0或以上版本

    Windows: 需要 Windows 98 或 以上版本

    其它低版本不支持。

    此函数包含在msimg32.dll.

    笔者定义了一个tranbit函数来动态调用TransparentBlt函数,具体定义见第三节。

4.将第二步生成的内存位图拷贝到桌面。这样一帧动画就显示完成。不断循环1-4步,你就能看到连续的动画场景了。

3.具体代码


以下是一个演示程序,在DELPHI5.0+WINDOWS2000P中调试通过。创建一个窗体Form1,放上两个Image控件,命名为Image1,Image2,再放上一个Timer控件,命名为Timer1。准备两张位图,一张放入Image1,另一张放入Image2。笔者用了如下样式的位图(截取了一部分),你可以自己画动画对象,也可以借用别人的,笔者就是用微软画的图片。


从图片你可以看出,图片中包括了许多连续的动画帧,一张图片完成一个动作,如旋转一周等,每帧动画大小完全一样,除了动画对象其它像素用一种透明色填充。好了你可以看具体的代码了。

 

unit Unitmain;

interface

uses

  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,

  ExtCtrls, StdCtrls,mmsystem;

 

type

  TForm1 = class(TForm)

    Timer1: TTimer;//爆炸定时器

    Image1: TImage;//储存爆炸的图片

    Image2: TImage;//储存飞行器的图片

    procedure Timer1Timer(Sender: TObject);

    procedure FormCreate(Sender: TObject);

    procedure FormClose(Sender: TObject; var Action: TCloseAction);

  private

    { Private declarations }

    DeskTopDC:HDC;//桌面窗口的图形设备描述表句柄

    stop:boolean;//控制循环的变量

    expnum:integer;//爆炸的当前次数

    procedure Explode(X:integer;Y:integer);//爆炸函数

    procedure shipmove(X:integer;Y:integer);//飞行器函数

  public

    { Public declarations }

  end;

 

var

  Form1: TForm1;

 

implementation

 

{$R *.DFM}

 

//保存桌面背景

procedure savebackground(BKCanvas :TCanvas;

                        sp_w:integer;

                        sp_h :integer ;

                        nx:integer;

                        ny:integer);

var sc:TCanvas;

begin

  sc:=TCanvas.Create;

  try

    sc.Handle:=GetDC(0);

    bkcanvas.CopyRect( rect(0,0,sp_w, sp_h), sc,rect(nx, ny, nx+sp_w, ny+sp_h));

    ReleaseDC(0, sc.handle);

  finally

    sc.free;

  end;

end;

 

//透明拷贝图像函数

//静态调用API函数TransparentBlt

procedure tranbit(hdcDest:HDC;

                    nXOriginDest:integer;

                    nYOriginDest:integer;

                    nWidthDest:integer;

                    hHeightDest:integer;

                    hdcSrc:HDC;

                    nXOriginSrc:integer;

                    nYOriginSrc:integer;

                    nWidthSrc:integer;

                    nHeightSrc:integer;

                    crTransparent:UINT) ;

Var

    LibHandle:HWND;//动态连接库句柄

    //函数原型定义

    DllName:Procedure(hdcDest:HDC;

                    nXOriginDest:integer;

                    nYOriginDest:integer;

                    nWidthDest:integer;

                    hHeightDest:integer;

                    hdcSrc:HDC;

                    nXOriginSrc:integer;

                    nYOriginSrc:integer;

                    nWidthSrc:integer;

                    nHeightSrc:integer;

                    crTransparent:UINT);Stdcall;

begin

    //以下是静态调用dll中函数的例行公事

    LibHandle:=LoadLibrary(msimg32.dll);

    if LibHandle<32 then

    begin

        MessageBox(Form1.Handle,Not Found msimg32.dll,Error,0);

        Exit;

    end;

    @DllName:=GetProcAddress(LibHandle,TransparentBlt);

    if @DllName=nil then

    begin

        MessageBox(Form1.Handle,Not Found TransparentBlt in msimg32.dll,Error,0);

        FreeLibrary(LibHandle);

        Exit;

    end;

    try

        TransparentBlt(hdcDest,

                    nXOriginDest,

                    nYOriginDest,

                    nWidthDest,

                    hHeightDest,

                    hdcSrc,

                    nXOriginSrc,

                    nYOriginSrc,

                    nWidthSrc,

                    nHeightSrc,

                    crTransparent);

    finally

        FreeLibrary(LibHandle);

    end;

end;

 

//爆炸函数

//在桌面的X,Y坐标处发生爆炸

procedure TForm1.Explode(X:integer;Y:integer);

var

    BitMapB : TBitMap;//保存桌面指定区域的内存位图

    w:integer;//一帧动画的宽度

    h:integer;//一帧动画的高度

    i:integer;

    j:integer;

begin

    BitMapB:=TBitMap.Create;

    try

        //动画位图为4*5=20帧

        w:=Image1.Width div 4;//计算每帧的宽度

        h:=image1.Height div 5;//计算每帧的高度

        //初始化内存为图的大小

        BitMapB.Height :=h;

        BitMapB.Width :=w;

        //保存桌面上指定区域的位图

        //注意,由于爆炸是在同一位置完成的,所以只要保存爆炸区域一次就行了。

        savebackground(BitMapB.canvas,w,h,X,Y);

        for i:=0 to 4 do

        begin

            for j:=0 to 3 do

            begin

                //把相应帧画到桌面上

                tranbit(DeskTopDC ,x,y,w,h,

                        image1.Canvas.Handle,j*w,i*h,w,h,RGB(208,2,178));

                Sleep(20);//显示速度太快,停顿20毫秒

                //恢复桌面

                bitblt(DeskTopDC,X,Y,w,h,BitMapB.Canvas.handle,0,0,srccopy);

            end;

        end;

    finally

        BitMapB.Free;

    end;

end;

 

//飞行器的飞行函数

//参数x,y指定飞行器飞行的目的地

procedure TForm1.shipmove(X:integer;Y:integer);

var

    w:integer;

    h:integer;

    i:integer;

    j:integer;

    k:integer;

    l:integer;

    BitMapB : TBitMap;

begin

    Randomize();

    BitMapB:=TBitMap.Create;

    try

        //动画位图为4*16-3帧空帧=61帧

        w:=Image2.Width div 4;

        h:=image2.Height div 16;

        BitMapB.Height :=h;

        BitMapB.Width :=w;

        k:=0;

        l:=0;

        while not stop do

            for i:=0 to 15 do

                for j:=0 to 3 do

                begin

                    if (i=15) and (i>0) then break;//如果是空帧就不画了

                //保存桌面上指定区域的位图

            //注意,由于飞行是在不同位置完成的,所以要保存即将被绘图的桌面区域

                    savebackground(BitMapB.canvas,w,h,k,l);

    tranbit(DeskTopDC ,k,l,w,h,image2.Canvas.Handle,j*w,i*h,w,h,RGB(208,2,178));

 

                    sleep(10);

                    bitblt(DeskTopDC,k,l,w,h,BitMapB.Canvas.handle,0,0,srccopy);

                    if(k<x)then k:=k+1;

                    if(l<y)then l:=l+1;

                    if timer1.Enabled =false then

                    if(k>x-10)then//到达目的地就停止飞行,并引爆炸弹

                    begin

                        stop:=true;

                        timer1.Enabled :=true;//炸弹引爆器

                    end;

            end;

    finally

        BitMapB.Free;

    end;

end;

 

procedure TForm1.Timer1Timer(Sender: TObject);

var

    x,y:integer;

begin

   

    if(expnum = 0) then

    begin

        Explode(screen.width div 2-20,screen.Height div 2-20);

        sndPlaySound(explosion.wav,SND_NOSTOP);

        expnum:=expnum+1;

    end

    else if expnum<10 then//爆炸最多10次

    begin

        //产生随机位置

        x:=Random(screen.Width-100);

        y:=Random(Screen.Height-100);

        Explode(x,y);//爆炸

        sndPlaySound(explosion.wav,SND_NOSTOP);//播放爆炸声音

        expnum:=expnum+1;

    end

    else

    begin

        stop:=true;

        timer1.Enabled :=false;

        close();

    end;

end;

 

procedure TForm1.FormCreate(Sender: TObject);

begin

    DeskTopDC:=GetDC(0);

    chdir(ExtractFilePath(application.ExeName));

    stop:=false;

    expnum:=0;

    //飞行器开始飞行,目的地为屏幕中央

    self.shipmove(screen.width div 2,screen.Height div 2);

end;

 

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);

begin

    stop:=true;

    Timer1.Enabled :=false;

    ReleaseDC(0, DeskTopDC);

end;

 

end.

4.结束语


正如我们所希望的那样:一个飞行器飞入桌面,慢慢向屏幕中央靠近,当它到达目的地时就爆炸了,并引出一连串的爆炸。程序顺利地完成了我们的希望,但是程序还有许多不足,最好用directx来完成动画,这样效果可能会更好。如谁对其感兴趣的话,发E_MAIL给我,我们一起探讨。(E_MAIL:CODEHUNTER@SOHU.COM)

文章整理:站长天空 网址:http://www.z6688.com/
以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢!

文章页数:[1] 


放大字体显示 缩小字体显示 打印文章 推荐给朋友
热门文章
·ASP.net中动态加载控件时一些问题的总结-ASP教程,ASP应用
·C#读写注册表-.NET教程,C#语言
·Visual Basic .NET中的异常处理简介(下)-.NET教程,VB.Net语言
·C#:文件的按行读/写及文件目录对话框的使用-.NET教程,C#语言
·ADO.Net:使用DataReader向数据库中插入数据-ASP教程,数据库相关
·列一张网恋赔偿清单(爆笑)
·如何用Photoshop画服装款式图-网页设计,Photoshop
·.NET下使用DataAdapter保存数据时,如何生成command语句及使用事务-.NET教程,数据库应用
·新型dc/dc电源控制芯片dpa426的应用
·ASP.NET 2.0 - Enter Key - Default Submit Button-.NET教程,Asp.Net开发
最新文章
·个人站长的网络赚钱两条新出路_网赚技巧
·adsense帐户最佳化纵深谈-adsense资深专员_网赚技巧
·google adsense容易被k的可能性列表_网赚技巧
·如何让程序被站长接受和产生利润_站长访谈
·马云,即成的中国互联网第4代霸主_站长访谈
·google关键词广告创建的十二招_google推广
·如何使google更快速收录你的新站_google推广
·几个颇有创意的网站推广方法_站长心得
·网络编辑:标题,如何让网民一见钟情(2)_网络编辑
·网站建设基础seo搜索引擎优化_seo网站优化
相关主题
西部数码虚拟主机

友情链接
CNNIC 西部数码
万网 自助建站
虚拟主机 asp空间
域名注册 域名
域名申请 主页空间
论坛空间 网站空间
国际域名 虚拟空间
空间租用 DDOS防火墙
成都主机托管 四川主机托管
主机租用 服务器租用
网站目录 自助建站
虚拟主机 网址大全
软件下载
自助链接
虚拟主机资讯 特价虚拟主机
版权申明:本站文章均来自网络,如有侵权,请联系我们,我们收到后立即删除,谢谢!
关于我们:站长天空:专业提供最新的站长资讯、在线教程、虚拟主机权威评测、虚拟主机性能对比、网站制作教程,开发教程,站长工具。包括网页制作教程、冲浪宝典、编程参考、操作系统、软件教学、行业动态等。
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有。
发表评论 打印  刷新     关闭