一个下雪的小程序 c++ vc6.0

时间:2022-07-13 17:11:28
一个小的win32程序。使用vc6.0。
  1. #include "stdafx.h"
  2. #include <windows.h> 
  3. #include <math.h> 
  4. #include <stdlib.h>
  5. #define ID_TIMER    1 
  6. #define SNOWNUM      500  // 雪花数量 
  7. #define CONTRAST    50    // 对比度 
  8. #define YSTART      5    // 用于确定雪花初始时的y坐标 
  9. #define SNOWCR      RGB(0xFF, 0xFF, 0xFF) //雪花的颜色—白色 
  10. #define SNOWGATHERCR RGB(0xDB, 0xDB, 0xFF) //堆积雪花的颜色 
  11. typedef struct tagSnow 
  12.   POINT ptSnowsPos[SNOWNUM]; //用于保存各个雪花的坐标 
  13.   COLORREF crOrg[SNOWNUM]; //用于画雪花前屏幕原来的颜色 
  14.   int iVx, iVy, iAllVx, iAllVy; 
  15. }Snow; 
  16. void initSnow(HDC hdc, Snow *sn, int iSnow, int cxScreen); 
  17. int GetContrast(HDC hdc, Snow *sn, int iSnow); 
  18. void drawSnow(HDC hdc, Snow *sn, int cxScreen); 
  19. LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ; 
  20. int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, 
  21.                     PSTR szCmdLine, int iCmdShow) 
  22.         static TCHAR szAppName[] = TEXT ("clsDeskSnow") ; 
  23.         HWND            hwnd ; 
  24.         MSG            msg ; 
  25.         WNDCLASS    wndclass ; 
  26.         wndclass.style        = CS_HREDRAW | CS_VREDRAW ; 
  27.         wndclass.lpfnWndProc  = WndProc ; 
  28.         wndclass.cbClsExtra    = 0 ; 
  29.         wndclass.cbWndExtra    = 0 ; 
  30.         wndclass.hInstance    = hInstance ; 
  31.         wndclass.hIcon        = LoadIcon (NULL, IDI_APPLICATION) ; 
  32.         wndclass.hCursor      = LoadCursor (NULL, IDC_ARROW) ; 
  33.         wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ; 
  34.         wndclass.lpszMenuName  = NULL ; 
  35.         wndclass.lpszClassName = szAppName ; 
  36.         if(!RegisterClass (&wndclass)) 
  37.         { 
  38.             MessageBox (NULL, TEXT ("This program requires Windows NT!"), szAppName, MB_ICONERROR) ; 
  39.             return 0; 
  40.         } 
  41.         hwnd = CreateWindow (szAppName,        TEXT ("桌面下雪"), 
  42.                             WS_MINIMIZEBOX | WS_SYSMENU, 
  43.                             CW_USEDEFAULT, CW_USEDEFAULT, 
  44.                             240, 120, 
  45.                             NULL, NULL, hInstance, NULL) ; 
  46.         ShowWindow (hwnd, iCmdShow) ; 
  47.         UpdateWindow (hwnd) ; 
  48.         while (GetMessage (&msg, NULL, 0, 0)) 
  49.         { 
  50.             TranslateMessage (&msg) ; 
  51.             DispatchMessage (&msg) ; 
  52.         } 
  53.         return msg.wParam ; 
  54. LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 
  55.       HDC          hdc ; 
  56.       PAINTSTRUCT  ps ; 
  57.       RECT        rect ; 
  58.       static int cxScreen, cyScreen; //屏幕宽高度(单位:像素) 
  59.       static int iTimes, iLoopTimes=100; 
  60.       static Snow snowDream; 
  61.       int i; 
  62.       switch (message) 
  63.       { 
  64.         case WM_CREATE: 
  65.             cxScreen = GetSystemMetrics (SM_CXSCREEN) ; 
  66.             cyScreen = GetSystemMetrics (SM_CYSCREEN) ; 
  67.             srand ((int) GetCurrentTime ()) ; //初始化随机数发生器 
  68.             snowDream.iAllVx = (unsigned)rand()%3 - 1; //雪花总体水平飘行速度(-1,0,1) 
  69.             snowDream.iAllVy = (unsigned)rand()%2 + 1; //雪花总体垂直下落速度(1,2) 
  70.             hdc = GetDC(NULL); //检索整个屏幕的设备上下文环境 
  71.             for(i=0; i <SNOWNUM; i++) 
  72.             { 
  73.                 snowDream.ptSnowsPos[i].x = rand() % cxScreen; //一个雪花开始下落的x坐标 
  74.                 snowDream.ptSnowsPos[i].y = rand() % YSTART; //一个雪花开始下落的y坐标 
  75.                 snowDream.crOrg[i] = GetPixel(hdc, snowDream.ptSnowsPos[i].x, 
  76.                           snowDream.ptSnowsPos[i].y); //获取给定点的原来的颜色值 
  77.             } 
  78.             ReleaseDC(NULL, hdc); 
  79.             SetTimer(hwnd, ID_TIMER, 10, NULL); //定时器,10毫秒 
  80.             return 0 ; 
  81.             
  82.         case WM_DISPLAYCHANGE: //当显示分辨率改变的时候 
  83.             cxScreen = GetSystemMetrics (SM_CXSCREEN) ; 
  84.             cyScreen = GetSystemMetrics (SM_CYSCREEN) ; 
  85.             return 0; 
  86.             
  87.         case WM_TIMER: 
  88.             hdc = GetDC(NULL); //检索整个屏幕的设备上下文环境 
  89.             if(iTimes > iLoopTimes) 
  90.             { 
  91.                 iTimes = 0; 
  92.                 iLoopTimes = 50 + (unsigned)rand()%50; 
  93.                 if(snowDream.iAllVx != 0) 
  94.                   snowDream.iAllVx = 0; 
  95.                 else                  
  96.                   snowDream.iAllVx = (unsigned)rand()%3 - 1; //雪花总体水平飘行速度(-1,0,1) 
  97.                 snowDream.iAllVy = (unsigned)rand()%2 + 1; //雪花总体垂直下落速度(1,2) 
  98.             } 
  99.             else 
  100.                 iTimes++; 
  101.             drawSnow(hdc, &snowDream, cxScreen); 
  102.             ReleaseDC(NULL, hdc); 
  103.             return 0; 
  104.         case WM_PAINT: 
  105.             hdc = BeginPaint (hwnd, &ps) ; 
  106.             GetClientRect (hwnd, &rect) ; 
  107.             DrawText (hdc, TEXT ("桌面下雪!"), -1, &rect, 
  108.                       DT_SINGLELINE | DT_CENTER | DT_VCENTER) ; 
  109.             EndPaint (hwnd, &ps) ; 
  110.             return 0 ; 
  111.         case WM_DESTROY: 
  112.             KillTimer(hwnd, ID_TIMER); // 中止定时器 
  113.             InvalidateRect(NULL, NULL, TRUE); // 刷新桌面 
  114.             PostQuitMessage (0) ; 
  115.             return 0 ; 
  116.         } 
  117.         return DefWindowProc (hwnd, message, wParam, lParam) ; 
  118. void initSnow(HDC hdc, Snow *sn, int iSnow, int cxScreen) //初始化第iSnow个雪花 
  119.   sn->ptSnowsPos[iSnow].x = (unsigned)rand() % cxScreen; //x范围整个屏幕宽 
  120.   sn->ptSnowsPos[iSnow].y = (unsigned)rand() % YSTART; //y范围离屏幕顶部YSTART像素点以内 
  121.   sn->crOrg[iSnow] = GetPixel(hdc, sn->ptSnowsPos[iSnow].x, 
  122.             sn->ptSnowsPos[iSnow].y ) ;//获取给定点的原来的颜色值 
  123. int GetContrast(HDC hdc, Snow *sn, int iSnow) 
  124.   int iR, iG, iB; 
  125.   COLORREF crCmp; 
  126.   
  127.   if(0 == sn->iVx) //若水平速度为0,则取比其大一个像素的正下方的点 
  128.     crCmp = GetPixel(hdc, sn->ptSnowsPos[iSnow].x, sn->ptSnowsPos[iSnow].y + 1); 
  129.   else //若水平速度>0,取右下方的点。 <0则取左下方的点 
  130.     crCmp = GetPixel(hdc, sn->ptSnowsPos[iSnow].x + (sn->iVx>0?1:-1), sn->ptSnowsPos[iSnow].y + 1); 
  131.   if(crCmp==SNOWCR) //如果为雪花的颜色 
  132.     return 0; 
  133.   //分别获取crCmp与对比点的蓝、绿、红部分的差值 
  134.   iB = abs((crCmp>>16)&0xFF - (sn->crOrg[iSnow]>>16)&0xFF); 
  135.   iG = abs((crCmp>>8)&0xFF  - (sn->crOrg[iSnow]>>8)&0xFF); 
  136.   iR = abs((crCmp)&0xFF    - (sn->crOrg[iSnow])&0xFF); 
  137.   return (iR+iG+iB)/3; 
  138. void drawSnow(HDC hdc, Snow *sn, int cxScreen) 
  139.   int i; 
  140.   for(i=0; i <SNOWNUM; i++) 
  141.   { 
  142.       //如果保存的原来的颜色不是雪花的颜色 
  143.       if(sn->crOrg[i] != SNOWCR) 
  144.         SetPixel(hdc, sn->ptSnowsPos[i].x, sn->ptSnowsPos[i].y, 
  145.           sn->crOrg[i]); //还原上一个位置的颜色 
  146.       sn->iVx = sn->iAllVx*(i%3+1); //雪花的x飘动速度 
  147.       sn->iVy = sn->iAllVy*(i%3+1); //雪花的y飘动速度 
  148.       //rand()%5-2使雪花下落的时候 有抖动效果 
  149.       sn->ptSnowsPos[i].x += sn->iVx+rand()%5-2; //雪花的下一个x坐标 
  150.       sn->ptSnowsPos[i].y += sn->iVy+1; //雪花的下一个y坐标 
  151.       //获取给定点的原来的颜色值 
  152.       sn->crOrg[i] = GetPixel(hdc, sn->ptSnowsPos[i].x, sn->ptSnowsPos[i].y); 
  153.     
  154.       if(CLR_INVALID == sn->crOrg[i]) //如果获取颜色失败,即雪花飘出了屏幕 
  155.       { 
  156.         initSnow(hdc, sn, i, cxScreen); //重新初始化 雪花 
  157.         continue
  158.       } 
  159.       if(sn->crOrg[i] != SNOWCR) //若当前点的颜色 不等于 雪花的颜色 
  160.       { 
  161.         if(SNOWGATHERCR == sn->crOrg[i]) //当前点的颜色=堆积的雪的颜色 
  162.       {  //设置为雪花的颜色 
  163.           SetPixel(hdc, sn->ptSnowsPos[i].x, sn->ptSnowsPos[i].y, SNOWCR); 
  164.           sn->crOrg[i] = SNOWCR; 
  165.           //initSnow(hdc, sn, i, cxScreen); //重新初始化 雪花 
  166.       } 
  167.       else if(GetContrast(hdc, sn, i) > 50) //若对比度>50 
  168.         {  //堆积雪花 
  169.             SetPixel(hdc, sn->ptSnowsPos[i].x,  sn->ptSnowsPos[i].y,  SNOWGATHERCR); 
  170.             SetPixel(hdc, sn->ptSnowsPos[i].x-1, sn->ptSnowsPos[i].y+1, SNOWGATHERCR); 
  171.             SetPixel(hdc, sn->ptSnowsPos[i].x+1, sn->ptSnowsPos[i].y+1, SNOWGATHERCR); 
  172.             initSnow(hdc, sn, i, cxScreen); //重新初始化 雪花 
  173.         } 
  174.         else //对比度 <50,不堆积,画出这帧雪花.等下次的时候再还原此点原本的颜色.以产生飘动效果 
  175.           SetPixel(hdc, sn->ptSnowsPos[i].x, sn->ptSnowsPos[i].y, SNOWCR); 
  176.       } 
  177.   }