桌面下雪 源代码

桌面下雪 源代码
//DELPHI
 interface

uses
  Windows,Messages,SysUtils,Classes,Graphics;

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

  procedureStartSnow;
  procedureStopSnow;
implementation

type

//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)
{

/*
HDC hScreenDC=0;
int j=0;
hScreenDC=CreateDC(“DISPLAY”,NULL,NULL,NULL);

RECT rect = {300,0,500,100} ;
::FillRect(hScreenDC, &rect, (HBRUSH)::GetStockObject(WHITE_BRUSH)) ;
DeleteDC(hScreenDC) ;
*/

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++;
}

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/37730.html

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注