C++------流星雨

用C++实现模拟数字、字母流星雨,其主要用到链表、win32编程基础。

demo实例:

  1 // DataRainDemo.cpp : 定义应用程序的入口点。
  2 //
  3 
  4 #include "stdafx.h"
  5 #include "DataRainDemo.h"
  6 #include<time.h>
  7 #include<stdlib.h>
  8 #include<windows.h>
  9 #define STRMINLEN   8
 10 #define STRMAXLEN    25
 11 
 12 
 13 
 14 //双向链表的每一个节点
 15 typedef struct MyList
 16 {
 17     struct MyList *prev;                //前一节点
 18     struct MyList *pNext;                //下一节点
 19     char ch;                                    //数据保存
 20 } MyList,*pMyList;
 21 //处理数据
 22 typedef struct MyListColum
 23 {
 24     MyList *phead;                        //整个链表的头
 25     MyList *pCurent;                        //链表所在当前的位置
 26     MyList *pTemp;                        //临时变量
 27     int listStrLen;                            //整个链表的长度    
 28     int x, y;                                    //链表的位置
 29     int iStopTimes;
 30     int iMusStopTimes;
 31 }StrColum,*pStrColum;
 32 
 33 
 34 #define MAX_LOADSTRING 100
 35 
 36 // 全局变量: 
 37 HINSTANCE hInst;                                // 当前实例
 38 WCHAR szTitle[MAX_LOADSTRING];                  // 标题栏文本
 39 WCHAR szWindowClass[MAX_LOADSTRING];            // 主窗口类名
 40 
 41 // 此代码模块中包含的函数的前向声明: 
 42 ATOM                MyRegisterClass(HINSTANCE hInstance);
 43 BOOL                InitInstance(HINSTANCE, int);
 44 LRESULT CALLBACK    WndProc(HWND, UINT, WPARAM, LPARAM);
 45 INT_PTR CALLBACK    About(HWND, UINT, WPARAM, LPARAM);
 46 
 47 int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
 48                      _In_opt_ HINSTANCE hPrevInstance,
 49                      _In_ LPWSTR    lpCmdLine,
 50                      _In_ int       nCmdShow)
 51 {
 52     UNREFERENCED_PARAMETER(hPrevInstance);
 53     UNREFERENCED_PARAMETER(lpCmdLine);
 54 
 55     // TODO: 在此放置代码。
 56 
 57     // 初始化全局字符串
 58     LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
 59     LoadStringW(hInstance, IDC_DATARAINDEMO, szWindowClass, MAX_LOADSTRING);
 60     MyRegisterClass(hInstance);
 61 
 62     // 执行应用程序初始化: 
 63     if (!InitInstance (hInstance, nCmdShow))
 64     {
 65         return FALSE;
 66     }
 67     srand(time(NULL));//以时间为种子
 68     HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_DATARAINDEMO));
 69 
 70     MSG msg;
 71 
 72     // 主消息循环: 
 73     while (GetMessage(&msg, nullptr, 0, 0))
 74     {
 75         if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
 76         {
 77             TranslateMessage(&msg);
 78             DispatchMessage(&msg);
 79         }
 80     }
 81 
 82     return (int) msg.wParam;
 83 }
 84 //宽字节 两个字节代表一个字符
 85 TCHAR randomChar()
 86 {
 87     return (rand() % 10 + 98);//0-9的ASCII
 88 }
 89 
 90 //
 91 //  函数: MyRegisterClass()
 92 //
 93 //  目的: 注册窗口类。
 94 //
 95 ATOM MyRegisterClass(HINSTANCE hInstance)
 96 {
 97     WNDCLASSEXW wcex;
 98 
 99     wcex.cbSize = sizeof(WNDCLASSEX);
100 
101     wcex.style          = CS_HREDRAW | CS_VREDRAW;
102     wcex.lpfnWndProc    = WndProc;
103     wcex.cbClsExtra     = 0;
104     wcex.cbWndExtra     = 0;
105     wcex.hInstance      = hInstance;
106     wcex.hIcon          = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_DATARAINDEMO));
107     wcex.hCursor        = LoadCursor(nullptr, IDC_ARROW);
108     wcex.hbrBackground  = (HBRUSH)(COLOR_WINDOW+1);
109     wcex.lpszMenuName = NULL;//MAKEINTRESOURCEW(IDC_DATARAINDEMO);
110     wcex.lpszClassName  = szWindowClass;
111     wcex.hIconSm        = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
112 
113     return RegisterClassExW(&wcex);
114 }
115 
116 //
117 //   函数: InitInstance(HINSTANCE, int)
118 //
119 //   目的: 保存实例句柄并创建主窗口
120 //
121 //   注释: 
122 //
123 //        在此函数中,我们在全局变量中保存实例句柄并
124 //        创建和显示主程序窗口。
125 //
126 BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
127 {
128    hInst = hInstance; // 将实例句柄存储在全局变量中
129 
130    /*HWND hWnd = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
131       CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, hInstance, nullptr);*/
132    /*
133        API 函数原型:
134     HWND WINAPI CreateWindow(
135       _In_opt_  LPCTSTR lpClassName,      // 窗口类名称
136       _In_opt_  LPCTSTR lpWindowName,  // 窗口标题
137       _In_      DWORD dwStyle,                     // 窗口风格,或称窗口格式
138       _In_      int x,                                         // 初始 x 坐标
139       _In_      int y,                                         // 初始 y 坐标
140       _In_      int nWidth,                                 // 初始 x 方向尺寸
141       _In_      int nHeight,                             // 初始 y 方向尺寸
142       _In_opt_  HWND hWndParent,             // 父窗口句柄
143       _In_opt_  HMENU hMenu,                     // 窗口菜单句柄
144       _In_opt_  HINSTANCE hInstance,          // 程序实例句柄
145       _In_opt_  LPVOID lpParam                      // 创建参数
146     );
147 
148     注:_In_ 说明该参数是输入的,_opt_ 说明该参数是可选参数(不是说没有参数,而是可以利用宏搭配参数)。
149    */
150    HWND hWnd = CreateWindowW(szWindowClass, NULL, WS_DLGFRAME|WS_THICKFRAME|WS_POPUP,
151        0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN), nullptr, nullptr, hInstance, nullptr);
152 
153    if (!hWnd)
154    {
155       return FALSE;
156    }
157 
158    ShowWindow(hWnd, nCmdShow);
159    UpdateWindow(hWnd);
160 
161    return TRUE;
162 }
163 
164 //
165 //  函数: WndProc(HWND, UINT, WPARAM, LPARAM)
166 //
167 //  目的:    处理主窗口的消息。
168 //
169 //  WM_COMMAND  - 处理应用程序菜单
170 //  WM_PAINT    - 绘制主窗口
171 //  WM_DESTROY  - 发送退出消息并返回
172 //
173 //
174 //初始化每个链表
175 void init(StrColum *cc, int cyScreen, int x)
176 {
177     int j;
178     cc->listStrLen = rand() % (STRMAXLEN - STRMINLEN) + STRMINLEN;
179     cc->x = x+3;
180     cc->y = rand() % 3 ? rand() % cyScreen : 0;
181     cc->iMusStopTimes = rand() % 6;
182     cc->iStopTimes = 0;
183     cc->phead = cc->pCurent = (pMyList)calloc(cc->listStrLen,sizeof(MyList));
184     for ( j = 0; j < cc->listStrLen-1; j++)
185     {
186         cc->pCurent->prev = cc->pTemp;
187         cc->pCurent->ch = '\0';
188         cc->pCurent->pNext = cc->pCurent + 1;
189         cc->pTemp = cc->pCurent++;
190     }
191     cc->pCurent->prev = cc->pTemp;
192     cc->pCurent->ch = '\0';
193     cc->pCurent->pNext = cc->phead;
194     cc->phead->prev = cc->pCurent;
195     cc->pCurent = cc->pTemp = cc->phead;
196     cc->phead->ch = randomChar();
197 }
198 LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
199 {
200     HDC hdc;
201     int i, j, temp, ctn;
202     static HDC hdcMem;
203     HFONT hFont;
204     static HBITMAP hBimtmap;
205     static int cxScreen, cyScreen;
206     static int iFontWidth = 10, iFontHeight = 15, iColumCount;
207     static StrColum *ccChain;
208     switch (message)
209     {
210         case WM_CREATE:
211         {
212             cxScreen = GetSystemMetrics(SM_CXSCREEN);
213             cyScreen = GetSystemMetrics(SM_CYSCREEN);
214             SetTimer(hWnd, 1, 10, NULL);
215             hdc = GetDC(hWnd);
216             hdcMem = CreateCompatibleDC(hdc);
217             hBimtmap = CreateCompatibleBitmap(hdc, cxScreen, cyScreen);
218             SelectObject(hdcMem, hBimtmap);
219             ReleaseDC(hWnd, hdc); 
220 
221             hFont = CreateFont(iFontHeight, iFontWidth - 5, 0, 0, 
222                 FW_BOLD, 0, 0, 0, DEFAULT_CHARSET, 
223                 OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
224                 DRAFT_QUALITY, FIXED_PITCH | FF_SWISS, 
225                 TEXT("Fixedsys"));
226             SelectObject(hdcMem,hFont);
227             DeleteObject(hFont);
228             SetBkMode(hdcMem,TRANSPARENT);
229             //设置显示的列数
230             iColumCount = cxScreen / (iFontWidth * 3 / 2);
231             ccChain = (pStrColum)calloc(iColumCount,sizeof(StrColum));
232             for (int i = 0; i < iColumCount; i++)
233             {
234                 init(ccChain + i,cyScreen,(iFontWidth*3/2)*i);
235             }
236             return 0;
237         }
238         break;
239     case WM_COMMAND:
240         {
241             int wmId = LOWORD(wParam);
242             // 分析菜单选择: 
243             switch (wmId)
244             {
245             case IDM_ABOUT:
246                 DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
247                 break;
248             case IDM_EXIT:
249                 DestroyWindow(hWnd);
250                 break;
251             default:
252                 return DefWindowProc(hWnd, message, wParam, lParam);
253             }
254         }
255         break;
256     case WM_PAINT:
257         {
258             PAINTSTRUCT ps;
259             HDC hdc = BeginPaint(hWnd, &ps);
260             // TODO: 在此处添加使用 hdc 的任何绘图代码...
261             EndPaint(hWnd, &ps);
262         }
263         break;
264     
265     case WM_DESTROY:
266         KillTimer(hWnd,1);
267         DeleteObject(hBimtmap);
268         DeleteDC(hdcMem);
269         for ( i = 0; i < iColumCount; i++)
270         {
271             free((ccChain+i)->pCurent);
272         }
273         free(ccChain);
274         PostQuitMessage(0);
275         break;
276     default:
277         return DefWindowProc(hWnd, message, wParam, lParam);
278     case WM_TIMER:
279     {
280         hdc = GetDC(hWnd);
281         PatBlt(hdcMem, 0, 0, cxScreen, cyScreen, BLACKNESS);
282         for (int i = 0; i < iColumCount; i++)
283         {
284             ctn = (ccChain + i)->iStopTimes++ >(ccChain + i)->iMusStopTimes;
285             (ccChain + i)->pTemp = (ccChain + i)->phead;
286             SetTextColor(hdcMem,RGB(255,255,255));
287             TextOut(hdcMem,(ccChain+i)->x,(ccChain+i)->y,&((ccChain+i)->pTemp->ch),1);
288             j = (ccChain + i)->y;
289             (ccChain + i)->pTemp = (ccChain + i)->pTemp->pNext;
290             temp = 0;
291             //temp 绿色过度到黑色
292             while ((ccChain+i)->pTemp!=(ccChain+i)->phead
293                 &&(ccChain+i)->pTemp->ch)
294             {
295                 SetTextColor(hdcMem,RGB(0,255-(255*(temp++)
296                     /(ccChain+i)->listStrLen),0));
297                 TextOut(hdcMem,(ccChain+i)->x,j-=iFontHeight,
298                     &((ccChain+i)->pTemp->ch),1);
299                 (ccChain + i)->pTemp = (ccChain + i)->pTemp->pNext;
300             }
301             if (ctn)
302                 (ccChain + i)->iStopTimes = 0;
303             else
304                 continue;
305             (ccChain + i)->y += iFontHeight;//下次开始显示的地方
306             if ((ccChain+i)->y-(ccChain+i)->listStrLen*iFontHeight>cyScreen)
307             {
308                 free((ccChain+i)->pCurent);
309                 init(ccChain+i,cyScreen,(iFontWidth*3/2)*i);
310             }
311             (ccChain + i)->phead = (ccChain + i)->phead->prev;
312             (ccChain + i)->phead->ch = randomChar();
313         }
314 
315         BitBlt(hdc,0,0,cxScreen,cyScreen,hdcMem,0,0,SRCCOPY);
316         ReleaseDC(hWnd,hdc);
317     }
318     //case WM_RBUTTONDOWN:
319     //    KillTimer(hWnd,1);
320     //    return 0;
321     //case WM_RBUTTONUP:
322     //    SetTimer(hWnd,1,10,NULL);
323     //    return 0;
324         
325     }
326     return 0;
327 }
328 
329 
330 
331 
332 
333 
334 // “关于”框的消息处理程序。
335 INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
336 {
337     UNREFERENCED_PARAMETER(lParam);
338     switch (message)
339     {
340     case WM_INITDIALOG:
341         return (INT_PTR)TRUE;
342 
343     case WM_COMMAND:
344         if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
345         {
346             EndDialog(hDlg, LOWORD(wParam));
347             return (INT_PTR)TRUE;
348         }
349         break;
350     }
351     return (INT_PTR)FALSE;
352 }

 

实现效果展示

posted on 2019-08-31 15:47  lfylcj  阅读(3097)  评论(1编辑  收藏  举报

导航