桌面下雪 源代码

    技术2025-03-12  44

    //DELPHI

     interfaceuses   Windows, Messages, SysUtils, Classes, Graphics;const   SnowNumber = 500; // 雪点数量-1   procedure StartSnow;   procedure StopSnow;implementationtype   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, ScreenHeightprocedure 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++;}

     

    最新回复(0)