天天看点

桌面下雪 源代码

//DELPHI

interface

uses

   Windows, Messages, SysUtils, Classes, Graphics;

const

   SnowNumber = 500; // 雪点数量-1

   procedure StartSnow;

   procedure StopSnow;

implementation

type

   SnowNode = record

     Point: TPoint;   // 雪点位置

     Color: Integer; // 先前颜色

     Speed: Integer; // 下落速率

     nMove: Integer; // 下落距离

     Stick: Integer; // '粘连'度

   end;

   TSnowThread=class(TThread)

   public

     procedure Execute; override;

   end;

var

   SnowNodes: array[0..SnowNumber] of SnowNode; // 雪点数组

   hTimer: Integer; // '随机风向'时钟句柄

   CrWind: Integer; // 当前'风向' ( -1 ~ 1 )

   CrStep: Integer; // 当前循环步数(用于限速)

   ScreenWidth, ScreenHeight: Integer; // 屏幕尺寸

   SnowThread:TSnowThread;

   procedure StartSnow;

   begin

     if SnowThread=nil then

       SnowThread:=TSnowThread.Create(false);

   end;

   procedure StopSnow;

   begin

     if SnowThread<>nil then

     begin

       SnowThread.Terminate;

       SnowThread.WaitFor;

       SnowThread.free;

       SnowThread:=nil;

     end;

   end;

   // 取屏幕尺寸 -> ScreenWidth, ScreenHeight

procedure GetScreenSize;

begin

   ScreenWidth := GetSystemMetrics(SM_CXSCREEN);

   ScreenHeight := GetSystemMetrics(SM_CYSCREEN);

end;

   // '随机风向'时钟

procedure TimerProc(hWnd: HWND; uMsg: UINT; idEvent: UINT; dwTime: DWORD); stdcall;

begin

   SetTimer(0, hTimer, (Random(27)+4) * 500, @TimerProc); // 重设下次风向改变时间

   if (CrWind <> 0) then CrWind := 0 else CrWind := Random(3) - 1; // 修改风向

end;

   // 初始化雪点数组

procedure InitSnowNodes;

var

   hScreenDc, J: Integer;

begin

   hScreenDc := CreateDC('DISPLAY', nil, nil, nil);

   for J := 0 to SnowNumber do

   begin

     SnowNodes[J].Point.X := Random(ScreenWidth);

     SnowNodes[J].Point.Y := Random(ScreenHeight);

     SnowNodes[J].Color := GetPixel(hScreenDc, SnowNodes[J].Point.X, SnowNodes[J].Point.Y);

     SnowNodes[J].Speed := Random(5) + 1; // 几次循环作下落一次 (1~5)

     SnowNodes[J].nMove := Random(SnowNodes[J].Speed)+1; // 每次下落距离(1~5)

     SnowNodes[J].Stick := 30 - Random(SnowNodes[J].Speed); // '粘连'度(几次循环作一次粘连判断)

   end;

   DeleteDC(hScreenDc);

end;

   // 移动雪点 ..

procedure MoveSnowNodes;

var

   hScreenDc, I, X, Y: Integer;

begin

   hScreenDc := CreateDC('DISPLAY', nil, nil, nil);

   for I := 0 to SnowNumber do

   begin

    // 控制雪点下降速率

     if (CrStep mod SnowNodes[I].Speed) <> 0 then Continue;

    // 恢复上次被覆盖点

     if GetPixel(hScreenDc, SnowNodes[I].Point.X, SnowNodes[I].Point.Y) = $FFFFFF then

       SetPixel(hScreenDc, SnowNodes[I].Point.X, SnowNodes[I].Point.Y, SnowNodes[I].Color);

    // 根据风向作随机飘落

     X := SnowNodes[I].Point.X + Random(3) - 1 + CrWind;

     Y := SnowNodes[I].Point.Y + SnowNodes[I].nMove;

    // 积雪(停留)效果处理

     if ( (CrStep mod SnowNodes[I].Stick) = 0 ) // 降低积雪概率 ..

        and ( GetPixel(hScreenDc, X, Y) <> GetPixel(hScreenDc, X, Y+1) ) // '边缘'判断

        and ( GetPixel(hScreenDc, X-1, Y) <> GetPixel(hScreenDc, X-1, Y+1) )

        and ( GetPixel(hScreenDc, X+1, Y) <> GetPixel(hScreenDc, X+1, Y+1) ) then

     begin

      // 稍微调整坐标

       if GetPixel(hScreenDc, X, Y-1) = GetPixel(hScreenDc, X, Y-2) then Dec(Y) // 上边缘

       else if GetPixel(hScreenDc, X, Y+1) = GetPixel(hScreenDc, X, Y+2) then Inc(Y); // 下边缘

       Inc(X, CrWind);

      // 画三个点(雪花)

       SetPixel(hScreenDc, X, Y, $FFFFFF);

       SetPixel(hScreenDc, X+1, Y+1, $FFFFFF);

       SetPixel(hScreenDc, X-1, Y+1, $FFFFFF);

      // 重生雪点

       SnowNodes[I].Point.Y := Random(10);

       SnowNodes[I].Point.X := Random(ScreenWidth);

       SnowNodes[I].Color := GetPixel(hScreenDc, SnowNodes[I].Point.X, SnowNodes[I].Point.Y);

     end else

     begin

       if (X < 0) or (X > ScreenWidth) or (Y > ScreenHeight) then // 超出范围则重生雪点

       begin

         SnowNodes[I].Point.Y := Random(10);

         SnowNodes[I].Point.X := Random(ScreenWidth);

         SnowNodes[I].Color := GetPixel(hScreenDc, SnowNodes[I].Point.X, SnowNodes[I].Point.Y);

       end else

       begin

        // 保存颜色并绘制雪点

         SnowNodes[I].Color := GetPixel(hScreenDc, X, Y);

         SetPixel(hScreenDc, X, Y, $FFFFFF);

        // 此时保存新雪点位置

         SnowNodes[I].Point.X := X;

         SnowNodes[I].Point.Y := Y;

       end;

     end;

   end;

   DeleteDC(hScreenDc);

   Inc(CrStep);

end;  

{ TSnowThread }

procedure TSnowThread.Execute;

var

   ThreadMsg: TMsg;   // 标准消息结构体

   Frequency: Int64; // 高性能定时器频率

   StartCt, EndCt: Int64; // 高性能定时器计数

   ElapsedTime: Extended; // 时间间隔

begin

   Randomize;   GetScreenSize;   InitSnowNodes; // 初始化

   QueryPerformanceFrequency(Frequency); // 高性能定时器频率

   hTimer := SetTimer(0, 0, Random(5)*500, @TimerProc); // 安装随机风向定时器

   repeat // 消息循环

     QueryPerformanceCounter(StartCt); // 执行运算前 计数值

     if PeekMessage(ThreadMsg, 0, 0, 0, PM_REMOVE) then // 取到消息

     begin

       case ThreadMsg.message of

         WM_TIMER:

           TimerProc(0, 0, 0, 0); // 预设风向改变时间已到

         WM_DISPLAYCHANGE:

           begin

           GetScreenSize; // 重新取屏幕尺寸

           InitSnowNodes; // 初始化雪点数组

           end;

       end;

     end;

     MoveSnowNodes; // 移动雪点

     QueryPerformanceCounter(EndCt); // 执行运算后计数值

     ElapsedTime := (EndCt-StartCt)/Frequency;

     if (ElapsedTime < 0.0005) then Sleep(2) // 简单限速

     else if (ElapsedTime < 0.0010) then Sleep(1)

          else if (ElapsedTime < 0.0015) then Sleep(0);

   until Terminated;

   KillTimer(0, hTimer); // 删除随机风向定时器

   InvalidateRect(0, nil, TRUE); // 刷新屏幕

end;

initialization

   StartSnow;

finalization

   StopSnow;

end.

//SDK

//在Vista下,用SetPixel 画不点,只能用FillRect来画点了;暂时没找到为什么

//还有在VISTA下用CreateDC,然后进行画图,绘制速度很慢,只有去掉VISTA的玻璃效果,

//才能正常绘制

#include<windows.h>

#include<time.h>

#include<stdlib.h>

#include<iostream.h>

const int SnowNumber=500;   //Ñ©µãÊýÁ¿

struct SnowNode{

POINT postion;     //Ñ©µãλÖÃ

int iColor;      //ÏÈÇ°µÄÑÕÉ«

int iSpeed;      //ÏÂÂäËÙ¶È

int iMove;      //ÏÂÂä¾àÀë

int iStick;      //Õ³Ìù¶È

};

SnowNode SnowNodes[SnowNumber]; //Ñ©µãÊý×é

int hTimer=0;

int CrWind=0;

int CrStep=0;      //µ±Ç°Ñ­»·²½Êý£¨ÓÃÓÚÏÞËÙ£©

int ScreenWidth=0;     //ÆÁÄ»¿í¶È

int ScreenHeight=0;     //ÆÁÄ»¸ß¶È

//CBrush brush;

void GetScreenSize();

void CALLBACK TimerProc(HANDLE hWnd,UINT uMsg,UINT idEvent,DWORD dwTime);

void InitSnowNodes();

void MoveSnowNodes();

int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)

{

MSG msg;   //±ê×¼WindowsÏûÏ¢

LARGE_INTEGER Frequency; //¸ßÐÔÄܶ¨Ê±Æ÷ƵÂÊ

LARGE_INTEGER StartCt,EndCt;//¸ßÐÔÄܶ¨Ê±Æ÷¼ÆÊý

double ElapsedTime;    //ʱ¼ä¼ä¸ô

srand((unsigned)time(NULL));

GetScreenSize();

InitSnowNodes();

QueryPerformanceFrequency(&Frequency);

hTimer=SetTimer(0,0,rand()%5*500,(TIMERPROC)TimerProc);

if(hTimer==0)

{

   MessageBox(0,TEXT("´´½¨¶¨Ê±Æ÷ʧ°Ü"),TEXT("Ìáʾ"),MB_OK|MB_ICONINFORMATION);

   return -1;

}

RegisterHotKey(0,0,MOD_CONTROL,(int)'L');

while(1)

{

   QueryPerformanceCounter(&StartCt);   //Ö´ÐÐÔËËãÇ°¼ÆÊýÖµ

   if(PeekMessage(&msg,0,0,0,1))

   {

    switch(msg.message)

    {

     case WM_TIMER:   //Ô¤Éè·çÏò¸Ä±äʱ¼äÒѵ½

      TimerProc(0,0,0,0);

      break;

     case WM_HOTKEY:

      KillTimer(0,hTimer); //ɾ³ýËæ»ú·çÏò¶¨Ê±Æ÷

      UnregisterHotKey(0,0); //ɾ³ýÍ˳öÈȼü

      InvalidateRect(0,NULL,true);

      exit(1);

      break;

     case WM_DISPLAYCHANGE:

      GetScreenSize();   //ÖØÐÂÈ¡ÆÁÄ»µÄ³ß´ç

      InitSnowNodes();   //³õʼ»¯Ñ©µãµÄÊý×é

      break;

    }

   }

   MoveSnowNodes();

   QueryPerformanceCounter(&EndCt); //Ö´ÐÐÔËËãºóµÄ¼ÆÊýÖµ

   ElapsedTime=(double)(EndCt.QuadPart-StartCt.QuadPart)/Frequency.QuadPart;

   if(ElapsedTime<0.0005)

   {

    Sleep(2);

   }else if(ElapsedTime<0.0010)

   {

    Sleep(1);

   }else if(ElapsedTime<0.0015)

   {

    Sleep(3);

   }

}

//MessageBox(0,TEXT("ÏûÏ¢"),TEXT("ÏûÏ¢"),MB_OK|MB_ICONINFORMATION);

return 0;

}

void GetScreenSize()

{

ScreenWidth=GetSystemMetrics(SM_CXSCREEN);

ScreenHeight=GetSystemMetrics(SM_CYSCREEN);

return;

}

void CALLBACK TimerProc(HANDLE hWnd,UINT uMsg,UINT idEvent,DWORD dwTime)

{

//MessageBox(0,TEXT("ÏûÏ¢"),TEXT("ÏûÏ¢"),MB_OK|MB_ICONINFORMATION);

srand((unsigned)time(NULL));

if(hTimer==0)

{

   MessageBox(0,TEXT("´´½¨¶¨Ê±Æ÷ʧ°Ü"),TEXT("Ìáʾ"),MB_OK|MB_ICONINFORMATION);

   return;

}

SetTimer(0,hTimer,((rand()%27+4)*500),(TIMERPROC)TimerProc); //ÖØÉèÏ´ηçÏò¸Ä±äʱ¼ä

if(CrWind!=0)

{   //Ð޸ķçÏò

   CrWind=0;

}else

{

   CrWind=rand()%3-1;

}

return;

}

//#include "atlbase.h"

void InitSnowNodes()

{

HDC hScreenDC=0;

int j=0;

hScreenDC=CreateDC("DISPLAY",NULL,NULL,NULL);

// hScreenDC=GetDC(0);

if(hScreenDC==NULL)

{

   MessageBox(0,"»ñÈ¡ÆÁÄ»DCʧ°Ü!","ÐÅÏ¢",MB_OK|MB_ICONERROR);

   return;

}

srand((unsigned)time(NULL));

for(j=0; j<SnowNumber; j++)

{

   SnowNodes[j].postion.x=rand()%ScreenWidth;

   SnowNodes[j].postion.y=rand()%ScreenHeight;

   SnowNodes[j].iColor=GetPixel(hScreenDC,SnowNodes[j].postion.x,SnowNodes[j].postion.y);

   SnowNodes[j].iSpeed=(rand()%5+1);   //ÿ´ÎÏÂÂä¾àÀ루1~5£©

   SnowNodes[j].iStick=(30-rand()%SnowNodes[j].iSpeed); //Õ³Ìù¶È£¨¼¸´ÎÑ­»·×öÒ»´ÎÕ³Ìù¶ÈÅжϣ©

   //cout<<SnowNodes[j].postion.x<<"   Y:"<<SnowNodes[j].postion.y<<endl;

}

DeleteDC(hScreenDC);

}

void MoveSnowNodes()

{

//MessageBox(0,TEXT("ÏûÏ¢"),TEXT("ÏûÏ¢"),MB_OK|MB_ICONINFORMATION);

HDC hScreenDC=0;

srand((unsigned)time(NULL));

int x=0,y=0,i=0;

hScreenDC=CreateDC("DISPLAY",NULL,NULL,NULL);

// hScreenDC=GetDC(0);

if(hScreenDC==NULL)

{

   MessageBox(0,"»ñÈ¡ÆÁÄ»DCʧ°Ü£¡","ÐÅÏ¢",MB_OK|MB_ICONERROR);

   return;

}

// TextOut(hScreenDC,0,0,"ÊäÈëÄúÒªÏÔʾµÄÐÅÏ¢",0);

HBRUSH hbr2 = CreateSolidBrush(RGB(255,255,255));

for(i=0; i<SnowNumber; i++)

{ //¿ØÖÆÑ©µãϽµËÙ¶È

   if((CrStep%SnowNodes[i].iSpeed)!=0)

   {

    continue;

   }

   if((GetPixel(hScreenDC,SnowNodes[i].postion.x,SnowNodes[i].postion.y))==0XFFFFFF)

   {

    //»Ö¸´Éϴα»¸²¸Çµã

   // SetPixel(hScreenDC,SnowNodes[i].postion.x,SnowNodes[i].postion.y,SnowNodes[i].iColor);

    HBRUSH hbr = CreateSolidBrush(SnowNodes[i].iColor);

    RECT rect = {SnowNodes[i].postion.x,SnowNodes[i].postion.y,SnowNodes[i].postion.x+1,SnowNodes[i].postion.y+1} ;

    ::FillRect(hScreenDC, &rect, hbr) ;

    DeleteObject(hbr);

   }

   x=SnowNodes[i].postion.x+rand()%3+CrWind; //¸ù¾Ý·çÏò×÷Ëæ»úÆ®Âä

   y=SnowNodes[i].postion.y+SnowNodes[i].iSpeed;

//   y=SnowNodes[i].postion.y+SnowNodes[i].iMove;

   if(((CrStep%SnowNodes[i].iStick)==0) && (GetPixel(hScreenDC,x,y)!=(GetPixel(hScreenDC,x,y+1))) &&

    (GetPixel(hScreenDC,x-1,y) != GetPixel(hScreenDC,x-1,y+1)) &&

    (GetPixel(hScreenDC,x+1,y) != GetPixel(hScreenDC,x+1,y+1)))

   {

    if(GetPixel(hScreenDC,x,y-1)==GetPixel(hScreenDC,x,y-2))

    { //ÉÔÉÔµ÷Õû×ø±ê

     y--;

    }else

    {

     if(GetPixel(hScreenDC,x,y-1)==GetPixel(hScreenDC,x,y-2))

     {

      y++;

     }

     x+=CrWind;

    }

   // SetPixel(hScreenDC,x,y,0XFFFFFF);

   // SetPixel(hScreenDC,x+1,y+1,0XFFFFFF);

   // SetPixel(hScreenDC,x-1,y+1,0XFFFFFF);

    RECT rect1 = {x,y,x+1,y+1} ;

    ::FillRect(hScreenDC, &rect1, hbr2) ;

    RECT rect2 = {x+1,y+1,x+2,y+2} ;

    ::FillRect(hScreenDC, &rect2, hbr2) ;

    RECT rect3 = {x-1,y+1,x,y+2} ;

    ::FillRect(hScreenDC, &rect3, hbr2) ;

    SnowNodes[i].postion.x=rand()%ScreenWidth; //ÖØÉúÑ©µã

    SnowNodes[i].postion.y=rand()%10;

    SnowNodes[i].iColor=GetPixel(hScreenDC,SnowNodes[i].postion.x,SnowNodes[i].postion.y);

   }else

   {

    if(x<0 || x>ScreenWidth || y>ScreenHeight)

    {

     SnowNodes[i].postion.y=(rand()%10);

     SnowNodes[i].postion.x=(rand()%ScreenWidth);

     SnowNodes[i].iColor=GetPixel(hScreenDC,SnowNodes[i].postion.x,SnowNodes[i].postion.y);

    }else

    {   

     SnowNodes[i].iColor=GetPixel(hScreenDC,x,y);

     //SetPixel(hScreenDC,x,y,RGB(255,255,255));

     RECT rect = {x,y,x+1,y+1} ;

     ::FillRect(hScreenDC, &rect, hbr2) ;

     SnowNodes[i].postion.x=x;

     SnowNodes[i].postion.y=y;

    }

   }

}

DeleteDC(hScreenDC);

DeleteObject(hbr2);

CrStep++;

}

继续阅读