转载自:http://blog.csdn.net/x313695373/article/details/11661043
/******************************
字符雨,说实话,没数字雨好看,改自旓旓发的黑客帝国--数字雨!!
编译方法:cl.exe NumberRain.cpp
******************************/
#define UNICODE
#include <Windows.h>
#include <string>
#include <vector>
#include <algorithm>
#pragma comment(lib, "gdi32.lib")
#pragma comment(lib, "user32.lib")
//以上是为了在控制台下编译不用加额外的参数,否则会链接错误
using namespace std;
#define ID_TIMER 1
#define INTERVAL 13
#define SPEED 17
//要显示的内容加的这里,可以放你媳妇的名字之类的
wchar_t *g_Contents[] = {
L"一辈子的幸福给你", L"生日快乐", L"还是生日快乐", L"祝生日快乐",
L"日月轮转永不断", L"情苦真挚长相伴", L"不论你身在天涯海角", L"我将永远记住这一天",
L"祝生日快乐",
L"我特别珍视其中的一天", L"祝愿你在这天美梦都能实现",
L"因为你一向这样聪明可爱", L"又这样叫人牵肠挂肚", L"所以这份祝福非你莫属",
};
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
typedef struct TagCOLUMN{
wstring Contents;//显示的内容
wstring::iterator EndIt;//刚刚出现时只显示前面几个字符
int x, y;//显示的位置
int StopTimes, MaxStopTimers;//控制下降的速度
}COLUMN;
int WINAPI wWinMain(
__in HINSTANCE hInstance,
__in_opt HINSTANCE hPrevInstance,
__in wchar_t* lpCmdLine,
__in int nShowCmd
)
{
static wchar_t szAppName[] =L"Matrix";
HWND hwnd;
MSG msg;
WNDCLASS wndclass = {0};
wndclass.style = CS_HREDRAW | CS_VREDRAW;
wndclass.lpfnWndProc = WndProc;
wndclass.hInstance = hInstance;
wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndclass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
wndclass.lpszClassName = szAppName;
if(!RegisterClass(&wndclass)){
MessageBox(NULL, L"must run under NT", szAppName, MB_ICONERROR);
return 0;
}
hwnd = CreateWindow(
szAppName, NULL,
WS_DLGFRAME|WS_THICKFRAME|WS_POPUP,
0, 0,
GetSystemMetrics(SM_CXSCREEN),
GetSystemMetrics(SM_CYSCREEN),
NULL, NULL, hInstance, NULL);
ShowWindow(hwnd, SW_SHOWMAXIMIZED);
UpdateWindow(hwnd);
ShowCursor(FALSE);
srand(GetCurrentTime());
while(GetMessage(&msg, NULL, 0, 0)){
TranslateMessage(&msg);
DispatchMessage(&msg);
}
ShowCursor(TRUE);
return msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
HDC hdc;
int i, j, tmp;
static HDC dcMem;
static HFONT hFont;
static HBITMAP hBitmap;
static int cxScreen, cyScreen;
static int FontWidth = 10, FontHeight = 15;
static vector<COLUMN> columns;
switch(message){
case WM_CREATE:
cxScreen = GetSystemMetrics(SM_CXSCREEN);
cyScreen = GetSystemMetrics(SM_CYSCREEN);
hdc = GetDC(hwnd);
dcMem = CreateCompatibleDC(hdc);
hBitmap = CreateCompatibleBitmap(hdc, cxScreen, cyScreen);
SelectObject(dcMem, hBitmap);
ReleaseDC(hwnd, hdc);
hFont = CreateFont(FontHeight, FontWidth, 0, 0, FW_BOLD,
0, 0, 0,
DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS,
DRAFT_QUALITY, FIXED_PITCH|FF_SWISS,
L"Fixedsys");
SelectObject(dcMem, hFont);
SetBkMode(dcMem, TRANSPARENT);
tmp = cxScreen/(FontWidth*1.5);
columns.assign(tmp, COLUMN());
for(i = 0; i < tmp; i++){
columns[i].Contents = g_Contents[rand()%(sizeof(g_Contents)/sizeof(g_Contents[0]))];
columns[i].EndIt = columns[i].Contents.begin()+1;
columns[i].StopTimes = 0;
columns[i].MaxStopTimers = rand()%SPEED + 1;
columns[i].x = i*FontWidth*1.5;
columns[i].y = rand()%(cyScreen/2);
}
SetTimer(hwnd, ID_TIMER, INTERVAL, NULL);
return 0;
case WM_TIMER:
hdc = GetDC(hwnd);
PatBlt(dcMem, 0, 0, cxScreen, cyScreen, BLACKNESS);//draw the background
//依次画每一列
for_each(columns.begin(), columns.end(), [](COLUMN& col){
col.StopTimes++;
SetTextColor(dcMem, RGB(255,255,255));
//画第一个字符
TextOut(dcMem, col.x, col.y, &col.Contents[0], 1);
int len = col.EndIt - col.Contents.begin();
//画其它字符
for(int i = 1; i < len; i++){
SetTextColor(dcMem, RGB(0, 255-i*255/len, 0));
TextOut(dcMem, col.x, col.y - i*(FontHeight + 5), &col.Contents[i], 1);
}
//用于控制速度,达到阈值则下落
if(col.StopTimes >= col.MaxStopTimers){
col.y += FontHeight;
col.StopTimes = 0;
if(col.EndIt != col.Contents.end())
++col.EndIt;
}
//全部离开屏幕后从新生成数据
if(col.y > cyScreen + FontHeight*col.Contents.size()){
col.Contents = g_Contents[rand()%(sizeof(g_Contents)/sizeof(g_Contents[0]))];
col.EndIt = col.Contents.begin()+1;
col.StopTimes = 0;
col.MaxStopTimers = rand()% SPEED + 1;
col.y = rand()%3?0:rand()%(cyScreen/2);
}
});
BitBlt(hdc, 0, 0, cxScreen, cyScreen, dcMem, 0, 0, SRCCOPY);
ReleaseDC(hwnd, hdc);
return 0;
case WM_RBUTTONDOWN:
KillTimer(hwnd, ID_TIMER);
return 0;
case WM_RBUTTONUP:
SetTimer(hwnd, ID_TIMER, INTERVAL, NULL);
return 0;
case WM_KEYDOWN:
case WM_LBUTTONDOWN:
case WM_DESTROY:
KillTimer(hwnd, ID_TIMER);
DeleteObject(dcMem);
DeleteObject(hBitmap);
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, message, wParam, lParam);
}