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