为了表示我的歉意(特发此贴(对新手很好哦,高手不要帕我哦,易碎啊))
这是c贴吧高手写的,开始没有注释。不然很难看懂。发现没有注释别人要看懂你的想法还是很难了哦。我以后要学会呀。。。我是从他VB注释改过来的哦。好多人想要注释,都要自己找,这下你们就方便了啊。。
程序代码://基本原理是:先随机取的一个屏幕的坐标值(放在pData[i]),再取得屏幕上对应点的原来的颜色值存储在pcolor[i]
//中然后将其设置成雪花的颜色值&HFEFFFE(就是画出雪花),
//到下一个Timerde事件时先根据原来存储的pDate[i],恢复原来点的颜色,再随机取新的坐标值,重复····从而形成雪花飘动的效果
//在此基础上加上判断图像边缘(用自定义的对比度函数GetContrast,它返回与点pDate[i]下面相邻的点的颜色值各RGB分量之差的和
//当这个差大于某一个值,比喻程序用50是认为此处达到边缘)随机,风向等。
//雪花颜色值是snowcol=&HFEFFFE,之所以取这一个值是因为开始时发现有时候会出现2个雪花重叠从而造成混乱
//(也即上下2个雪花相邻,这样下一个雪花会干扰上一个雪花取得屏幕原来的颜色),
//所以将雪花设置成这种接近白色当不如白色FFFFFF常见颜色,
//当遇到取得的屏幕原始值是SnowCol就认为出现重叠,就跳过这一个Timer事件不进行屏幕操作。
#include <windows.h>
#include <time.h>
const int ScrnWidth=1024;
const int ScrnHight=800;
const long SnowCol =0xFEFFFE; //雪花颜色
const long SnowColDown =0xFFFFFF; //积雪雪花颜色
const long SnowColDuck =0xFFDDDD; //深色积雪颜色
const int SnowNum = 500; //雪花数量为500
const int ID_TIMER = 1; //定时器标识符
const char g_szClassName[] = "myWindowClass";
typedef struct POINTAPI
{
long x;
long y;
}a; //存取雪花的结构信息.
static HDC hDC1;
static struct POINTAPI pData[500];
static long pColor[500]; //存取原来坐标的颜色值
static int Vx,Vy,PVx,PVy,timecont; //vx 雪花整体水平漂移速度
//vy雪花总体垂直下落速度
//pvx单个雪花实际水平速度
//pvy单个雪花实际垂直速度
long Abs(long num)
{
if(num>=0)return(num);
else return(-num);
}
int Random(int max)
{
return(rand()%max);
}
int InitP(int i)
{
pData[i].x=Random(ScrnWidth);
pData[i].y = Random(5);
pColor[i] = GetPixel(hDC1, pData[i].x, pData[i].y); //检索指定位置的点的像素的RGB颜色值(返回值)
//取得屏幕原来的颜色值
return 1;
}
//取得一点与周围点的对比度,确定是不是在这一点堆积雪花
long GetContrast(int i)
{
long ColorCmp; //存取作对比点的颜色值
long tempR; //存取ColorCmp的红色值
long tempG; //同理
long tempB; //同理
int Slope; //存取雪花飘落的方向
if(PVy!=0) Slope = PVx / PVy; //若pvx/pvy在-1和1之间则slope=0;就取正下方的的像素点。
//若pvx/pvy>1,取右下方的点,pvx/pvy<-1则取左下方
else Slope = 2; //根据雪花飘落方向决定取哪一点做对比点
if(Slope==0) ColorCmp = GetPixel(hDC1, pData[i].x, pData[i].y + 1);
else if(Slope > 1) ColorCmp = GetPixel(hDC1, pData[i].x + 1, pData[i].y + 1);
else ColorCmp = GetPixel(hDC1, pData[i].x - 1, pData[i].y + 1);
//确定当前位置没有与另一个雪花重叠,重叠就返回0;用于防止由于不同雪花重叠造成雪花乱堆。
if(ColorCmp==SnowCol)return 0;
//分别获取ColorCmp与对比点的蓝,绿,红的差值。
tempB = Abs((ColorCmp>>16)&0xff - (pColor[i]>>16)&0xff);
tempG = Abs((ColorCmp>>8)&0xff - (pColor[i]>>8)&0xff);
tempR = Abs((ColorCmp)&0xff - (pColor[i])&0xff);
//return(tempR * 0.114 + tempG * 0.587 + tempB * 0.299);
return((tempR + tempG + tempB) / 3); //返回对比度
}
//画出一帧,即重画所有雪花位置一次。
void DrawP(void)
{
int i;
// srand(time(0));
for(i=0;i<SnowNum;i++) //防止雪花重叠造成干扰
{
if(pColor[i]!=SnowCol&&pColor[i]!=-1)
SetPixel(hDC1, pData[i].x, pData[i].y, pColor[i]); //还原上一个位置的颜色
//设置新的位置,i%3用于将雪花分为3类采用不同的速度,以便形成参次感。
PVx = Random(2) - 1 + Vx * (i % 3);
PVy = Vy * (i % 3 + 1);
pData[i].x = pData[i].x + PVx; //+pvx与前一点形成的距离差,形成速度的差别
pData[i].y = pData[i].y + PVy; //同理
//取的新位置的原始点的颜色值,用于下一步雪花飘过时恢复此处的颜色
pColor[i] = GetPixel(hDC1, pData[i].x, pData[i].y);
//如果获取颜色值失败,表明雪花已经飘出屏幕,重新初始化,GetPixel如果获取失败就返回-1.
if(pColor[i] ==-1)
InitP(i);
else
//如果雪花没有重叠,若对比度较小(即不能堆积)就画出雪花
//Random(16)>5用于防止某些连续而明显的边界截获所有的雪花
if(pColor[i]!=SnowCol)
if (Random(16) > 5 || GetContrast(i) < 50)//GetContrast(i)<50判断是否超出对比度50这个值就认为是边缘就会堆积雪花
SetPixel(hDC1, pData[i].x, pData[i].y, SnowCol);
//否者表明找到明显的边界,画出堆积的学,并初始化以便画新的的雪花
else
{
SetPixel(hDC1, pData[i].x, pData[i].y - 1, SnowColDuck);
SetPixel(hDC1, pData[i].x - 1, pData[i].y, SnowColDuck);
SetPixel(hDC1, pData[i].x + 1, pData[i].y, SnowColDown);
InitP(i);
}
}
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_TIMER: //时钟
{
if(timecont>200)
{
timecont=0;
Vx = Random(4) - 2;
Vy = Random(2) + 2;
}
else timecont+=1;
DrawP();
}
break;
case WM_CREATE:
{
int j;
srand(time(0));
Vx = Random(4) - 2;
Vy = Random(2) + 2;
for(j = 0;j<SnowNum;j++)
{
pData[j].x = Random(ScrnWidth);
pData[j].y = Random(ScrnHight);
pColor[j] = GetPixel(hDC1, pData[j].x, pData[j].y);
}
SetTimer(hwnd, ID_TIMER, 10, NULL);
hDC1 = GetDC(0);
timecont=0;
}
break;
case WM_CLOSE:
ReleaseDC(0, hDC1);
DestroyWindow(hwnd);
break;
case WM_DESTROY:
KillTimer(hwnd, ID_TIMER);
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, msg, wParam, lParam);
}
return 0;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
WNDCLASSEX wc;
HWND hwnd;
MSG Msg;
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = 0;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wc.lpszMenuName = NULL;
wc.lpszClassName = g_szClassName;
wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
if(!RegisterClassEx(&wc))
{
MessageBox(NULL, "窗体注册失败!", "错误!",
MB_ICONEXCLAMATION | MB_OK);
return 0;
}
hwnd = CreateWindowEx(
WS_EX_CLIENTEDGE,
g_szClassName,
"屏幕飘雪",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, 240, 120,
NULL, NULL, hInstance, NULL);
if(hwnd == NULL)
{
MessageBox(NULL, "窗体创建失败!", "错误!",
MB_ICONEXCLAMATION | MB_OK);
return 0;
}
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
while(GetMessage(&Msg, NULL, 0, 0) > 0)
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
return Msg.wParam;
} 我的小雪花,呵呵,这个是我写的,写的超简单哦!但也有到图标留雪功能。呵呵,因为哪里是白色的啊!!!!我的没有层次感,没有写代码。这个给新手学西更容易一点,代码简单。。。嘻嘻。写的不好,不要拍我
程序代码:#include <windows.h>
#include <time.h>
#include <stdio.h>
int win32_init(HINSTANCE hinst);
HWND win32_create(HINSTANCE hinst);
void win32_show(HWND hwnd);
void win32_run();
void draw_snow();
void init();
HWND hwnd;
int scrwidth=1280;
int scrheight=800;
int n;
char str[20];
HDC hdc;
typedef struct _Snow
{int x;
int y;
}Snow;
Snow snow[500];
long int color[500];
LRESULT CALLBACK WinProc(HWND hwnd,UINT msg,WPARAM wparam ,LPARAM lparam);
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd )
{
if(win32_init(hInstance))
{if(hwnd=win32_create(hInstance))
{
win32_show(hwnd);
win32_run();
}
else return false;
}
else
{
MessageBox(0,"注册窗口失败",0,0);
return false;
}
return true;
}
int win32_init(HINSTANCE hinst)
{
WNDCLASS wc;
memset(&wc,0,sizeof(wc));
wc.hInstance=hinst;
wc.lpszClassName="snow";
wc.hbrBackground=(HBRUSH) 1;
wc.lpfnWndProc=WinProc;
return RegisterClass(&wc);
}
HWND win32_create(HINSTANCE hinst)
{
return CreateWindow("snow",
"snow",
WS_OVERLAPPEDWINDOW,
200,
200,
200,
150,
0,
0,
hinst,
0);
}
void win32_show(HWND hwnd)
{
ShowWindow(hwnd,SW_SHOW);
UpdateWindow(hwnd);
}
void win32_run()
{MSG msg;
while(GetMessage(&msg,0,0,0)>0)
{
DispatchMessage(&msg);
}
}
void init(int n)
{snow[n].x=rand()%scrwidth;
snow[n].y=rand()%300;
color[n]=GetPixel(hdc,snow[n].x,snow[n].y);
}
LRESULT CALLBACK WinProc(HWND hwnd,UINT msg,WPARAM wparam ,LPARAM lparam)
{
switch(msg)
{case WM_CREATE:
srand(time(0));
for(n=0;n<500;n++)
{
snow[n].x=rand()%scrwidth;
snow[n].y=rand()%scrheight;
color[n]=GetPixel(hdc,snow[n].x,snow[n].y);
}
hdc=GetDC(0);//这里,我开始觉的不写一样的,我hwnd为0以为可以,结果什么都没有.我想这里的0难道是expoloere.exe的句柄吗!!!
SetTimer(hwnd,1,50,0);
break;
case WM_TIMER:
for(n=0;n<500;n++)
{
SetPixel(hdc,snow[n].x,snow[n].y,color[n]);
}
for(n=0;n<500;n++)
{if((snow[n].y=snow[n].y+5)<=800&&(color[n]=GetPixel(hdc,snow[n].x,snow[n].y))!=RGB(255,255,255))
{
SetPixel(hdc,snow[n].x,snow[n].y,RGB(255,255,255));
}
else
{SetPixel(hdc,snow[n].x,snow[n].y-1,RGB(255,255,255));
SetPixel(hdc,snow[n].x,snow[n].y-2,RGB(255,255,255));
SetPixel(hdc,snow[n].x,snow[n].y-3,RGB(255,255,255));
SetPixel(hdc,snow[n].x,snow[n].y-4,RGB(255,255,255));
SetPixel(hdc,snow[n].x-1,snow[n].y-1,RGB(255,255,255));
SetPixel(hdc,snow[n].x+1,snow[n].y-1,RGB(255,255,255));
init(n);
}
}
break;
case WM_CLOSE:PostQuitMessage(0);
exit(0);
break;
default:
return DefWindowProc(hwnd,msg,wparam,lparam);
}
return false;
}。









