用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 }
实现效果展示