流星雨屏幕程序

2023-11-07 17:30
文章标签 程序 屏幕 流星雨

本文主要是介绍流星雨屏幕程序,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

之前看到朋友晒流星雨屏幕图,今天就来实现这个流星雨屏幕程序。

语言:C++,平台:VS,框架:win32。

  首先来看看程序运行的情况。

在这里插入图片描述
  接着来介绍一下程序的主题部分,分为三个部分:窗口的建立数据的存储消息的处理

窗口的建立

  主要功能就是创建一个窗口来承载要显示的东西,否则不可能直接在屏幕上面就操作吧,那你的屏幕上面岂不是会被搞成乱七八糟,还如何使用?

  废话不多说,先创建一个窗口类(WNDCLASS)来定义一下要创建的窗口类型,主要类型就是:窗口风格,窗口的消息处理函数,窗口的图标、光标。背景颜色等等。之后注册该窗口类。

    TCHAR szClassName[] = TEXT("数字雨");    //窗口类名HWND hwnd;MSG msg;          //消息函数WNDCLASS wndclass;wndclass.style = CS_HREDRAW | CS_VREDRAW;       //窗口风格,垂直水平窗口改变就重新绘制wndclass.lpfnWndProc = WndProc;  //消息处理函数wndclass.cbClsExtra = 0;wndclass.cbWndExtra = 0;wndclass.hInstance = hInstance;wndclass.hIcon = LoadIcon(hInstance,  MAKEINTRESOURCE(IDI_ICON1));   //加载一个图标wndclass.hCursor = NULL;wndclass.hbrBackground = (HBRUSH)GetStockObject(GRAY_BRUSH);wndclass.lpszMenuName = NULL;wndclass.lpszClassName = szClassName;      //窗口类名if (!RegisterClass(&wndclass)){MessageBox(NULL, _T("注册窗口失败"), _T("提示"), MB_ICONERROR);return -1;}

  注册成功之后就调用API创建窗口,指定窗口创建的位置大小边框风格菜单等,即完成创建窗口。

  因为是全屏,所以不能带标题栏菜单栏等窗口类型,同时创建的窗口是弹出式窗口

    hwnd = CreateWindow(szClassName, NULL,WS_DLGFRAME | WS_THICKFRAME | WS_POPUP, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN), NULL, NULL, hInstance, NULL);if (!hwnd){MessageBox(NULL, _T("创建窗口失败"), _T("提示"), MB_ICONERROR);return -1;}

  创建完成之后,就显示窗口,因为是全屏显示,所以最大化显示窗口

	ShowWindow(hwnd, SW_SHOWMAXIMIZED);UpdateWindow(hwnd);ShowCursor(FALSE);

  然后开始消息循环机制

	while (GetMessage(&msg, NULL, 0, 0)){TranslateMessage(&msg);DispatchMessage(&msg);}

数据的存储

  由于要显示一些数字,当然也可以是其他汉字或者英文字母,所以这里定义一个队列来存储这些数据。

  创建一个双向链表来存储字符

typedef struct charList
{struct charList * prev;TCHAR ch;    //放字符struct charList * next;
}CharList;

  创建一个循环队列来存放这些字符串以及类型其属性,比如字符数多少,显示的位置等等。

typedef struct tagCharColumn
{struct charList * head, *cur; //头结点和尾结点int x, y, iShownLen, iStrNum; //显示位置,显示字数,字符数
}CharQueue;

  然后开始创建队列,上面定义了7组字符串,为了随机显示,每次创建该队列的时候,就随机选取一组字符串,然后设置显示的位置。

struct showChar
{TCHAR myChar[60];int iNum; //字符个数
}charArr[7] = {{ TEXT("10101010101010101011010"), 23 },{ TEXT("1010110101010101010101"), 21 },{ TEXT("10101111101100100001010100001"), 28 },{ TEXT("10101000101"), 11 },{ TEXT("101010101111011111110010000011110101010"), 40 },{ TEXT("101011101001010101010"), 21 },{ TEXT("101010101010101010101010101111"), 30 }
};

  之后生成各个节点,最后收尾相连,形成循环队列。

void CreateQueue(CharQueue * cc, int cyScreen, int x)
{CharList * front;int NumTemp = rand() % 6;         //七组字符串cc->x = x;cc->y = rand() % 10 ? rand() % cyScreen : 0; //大约9/10的概率从中间开始下落。cc->iShownLen = 1;                           //一开始就显示一个字符,然后慢慢增加,增加到等于歌词字符数时保持不变cc->iStrNum = charArr[NumTemp].iNum;         //歌词字符数cc->head = cc->cur = front = (CharList *)calloc(cc->iStrNum, sizeof(CharList)); //创建显示列//生成每个节点int i;for (i = 0; i<cc->iStrNum - 1; i++){cc->cur->prev = front;cc->cur->ch = charArr[NumTemp].myChar[i];front = cc->cur++;front->next = cc->cur;}//最后一个是标点符号cc->cur->prev = front;cc->cur->ch = charArr[NumTemp].myChar[i];cc->cur->next = cc->head;cc->head->prev = cc->cur;cc->cur = cc->head;             //首尾相连
} 

  注意这里,链表存储一个字符,而队列来存储整个字符串

消息的处理

  在窗口上面显示图案文字,这就涉及到GDI绘图
首先获取窗口大小,也就是屏幕大小,因为是整体显示,接着得到设备上下文(窗口)句柄。

	cxScreen = GetSystemMetrics(SM_CXSCREEN);  //获得屏幕的宽度cyScreen = GetSystemMetrics(SM_CYSCREEN);  //获得屏幕的高度hdc = GetDC(hwnd);   

  接下来就是重点了,不可以直接在窗口上面绘制,而是创建一个和窗口DC一样兼容的内存DC

  然后创建一块画布,只有画布上面才可以绘制图像文字等,再然后创建画笔,把画布和画笔都放入到内存DC中,这样就可以在内存DC上面绘制图像文字了。

	hdcMem = CreateCompatibleDC(hdc);          //创建一个兼容的内存DChBitmap = CreateCompatibleBitmap(hdc, cxScreen, cyScreen);    //创建一块画布SelectObject(hdcMem, hBitmap);             //将画布放到内存DC中hFont = CreateFont(iFontHeight, iFontWidth, 0/*角度设置*/, 0/*角度设置*/, FW_DONTCARE/*黑体*/, 0, 0, 0,/*斜体 下划线 啊、删除线*/DEFAULT_CHARSET/*字符集*/, OUT_DEFAULT_PRECIS/*指定输出精度*/, CLIP_DEFAULT_PRECIS/*指定裁剪精度*/,DRAFT_QUALITY/*指向输出质量*/, FIXED_PITCH | FF_SWISS/*指定字体间距| 字体族*/, TEXT("CloudKaiTiGBK"));SelectObject(hdcMem, hFont);               //将字体放到内存DC中SetBkMode(hdcMem, TRANSPARENT);            //设置窗口背景

  最后创建屏幕显示的队列(通过屏幕的分辨率以及显示文字直接的间隔来计算),播放音乐(音乐的播放需要加上相应的媒体库 #pragma comment(lib, “WINMM.LIB”)),开启定时器(主要功能就是下面文字的显示,控制显示的快慢)

	PlaySound(L"123.wav", NULL, SND_FILENAME | SND_ASYNC | SND_LOOP);//异步循环播放AllChar = (CharQueue *)calloc(NumOfColumn, sizeof(CharQueue));//自动初始化为0for (i = 0; i<NumOfColumn; i++){CreateQueue(AllChar + i, cyScreen, ColSpan * i + 17);}SetTimer(hwnd, 1, 100, NULL);

  定义的数据类型如下:

#define NumOfColumn 25  //显示列的列数
#define ColSpan     64  //列字符串之间的间隔HDC hdc=0;
static HDC hdcMem;
static HBITMAP hBitmap;
PAINTSTRUCT           ps;
static CharQueue * AllChar;
HFONT hFont=0;
static int cxScreen, cyScreen;
static int iFontWidth = 20, iFontHeight = 30;
int i, j, y, greenToblack;
CharQueue * ccElem;
CharList * temp;

  整块的程序如下:

case WM_CREATE:cxScreen = GetSystemMetrics(SM_CXSCREEN);  //获得屏幕的宽度cyScreen = GetSystemMetrics(SM_CYSCREEN);  //获得屏幕的高度hdc = GetDC(hwnd);                         //获得设备上下文环境句柄hdcMem = CreateCompatibleDC(hdc);          //创建一个兼容的内存DChBitmap = CreateCompatibleBitmap(hdc, cxScreen, cyScreen);    //创建一块画布SelectObject(hdcMem, hBitmap);             //将画布放到内存DC中hFont = CreateFont(iFontHeight, iFontWidth, 0/*角度设置*/, 0/*角度设置*/, FW_DONTCARE/*黑体*/, 0, 0, 0,/*斜体 下划线 啊、删除线*/DEFAULT_CHARSET/*字符集*/, OUT_DEFAULT_PRECIS/*指定输出精度*/, CLIP_DEFAULT_PRECIS/*指定裁剪精度*/,DRAFT_QUALITY/*指向输出质量*/, FIXED_PITCH | FF_SWISS/*指定字体间距| 字体族*/, TEXT("CloudKaiTiGBK"));SelectObject(hdcMem, hFont);               //将字体放到内存DC中SetBkMode(hdcMem, TRANSPARENT);            //设置窗口背景PlaySound(L"123.wav", NULL, SND_FILENAME | SND_ASYNC | SND_LOOP);//异步循环播放AllChar = (CharQueue *)calloc(NumOfColumn, sizeof(CharQueue));//自动初始化为0srand(time(0));for (i = 0; i<NumOfColumn; i++){CreateQueue(AllChar + i, cyScreen, ColSpan * i + 17);}SetTimer(hwnd, 1, 100, NULL);return 0;

  做完了这些初始化工作,然后就开始正式的文字显示工作(逻辑处理)。

  主要思路是:队列中的字符由随机的位置从上往下逐个显示,最新的显示为最亮的颜色,显示过的文字逐步变为背景颜色(即逐步消失),然后当文字显示的超过屏幕的宽时,这删除该队列,重新创建一个新的队列,就这样循环显示。

  具体步骤分为以下几步:

  1. 创建一个屏幕显示的队列文字的循环
  2. 拿出队列中的一个字符进行显示,每次显示的文字书增加
  3. 将显示过的文字颜色进行逐步改变成背景颜色,逐步消失
  4. 改变下次显示文字的纵坐标,进行位置的变更
  5. 判断显示的文字是否超出屏幕,如果超出,就删除该队列,创建新的队列显示
  6. GDI绘图,将内存DC绘制的文字图案复制到环境DC(即窗口DC)中,完成显示。
  7. 接着就 一直循环这个过程就完成显示。
case WM_TIMER:PatBlt(hdcMem, 0, 0, cxScreen, cyScreen,BLACKNESS);for (i = 0; i<NumOfColumn; i++){ccElem = AllChar + i;temp = ccElem->head;SetTextColor(hdcMem, RGB(255, 255, 255));TextOut(hdcMem, ccElem->x, ccElem->y, &temp->ch, _tcslen(&(temp->ch)) /*字符个数*/);y = ccElem->y;greenToblack = 0;ccElem->head = ccElem->head->next;temp = temp->prev;for (j = 1; j<ccElem->iShownLen; j++){SetTextColor(hdcMem, RGB(0, 255 - 255 * (greenToblack++) / (ccElem->iStrNum), 0));TextOut(hdcMem, ccElem->x, y -= iFontHeight, &temp->ch, _tcslen(&(temp->ch)));temp = temp->prev;}if (ccElem->iShownLen<ccElem->iStrNum){ccElem->iShownLen++;}ccElem->y += iFontHeight;if (ccElem->y - ccElem->iStrNum*iFontHeight > cyScreen){free(ccElem->cur);CreateQueue(ccElem, cyScreen, ColSpan * i + 17);}}hdc = GetDC(hwnd);BitBlt(hdc, 0, 0, cxScreen, cyScreen, hdcMem, 0, 0, SRCCOPY);ReleaseDC(hwnd, hdc);return 0;

  最后如果要退出程序,可以设置几个按键程序响应函数,退出相应的进程。

  在退出的时候,也有几个注意点,就是首先关闭之后,调用的WM_CLOSE消息,然后再调用WM_DESTROY消息,最后就退出消息循环,程序关闭。

case WM_KEYDOWN:{switch (wParam){case VK_LEFT:{KillTimer(hwnd, 1);for (i = 0; i<NumOfColumn; i++){ccElem = AllChar + i;free(ccElem->cur);}free(AllChar);DeleteObject(hBitmap);DeleteDC(hdcMem);DeleteObject(hFont);ReleaseDC(hwnd, hdc);PostQuitMessage(0);}break;case VK_ESCAPE:{KillTimer(hwnd, 1);for (i = 0; i<NumOfColumn; i++){ccElem = AllChar + i;free(ccElem->cur);}free(AllChar);DeleteObject(hBitmap);DeleteDC(hdcMem);DeleteObject(hFont);ReleaseDC(hwnd, hdc);PostQuitMessage(0);}break;}}break;case WM_CLOSE://确定退出,销毁窗口,抛出一个WM_DESTYRY的消息DestroyWindow(hwnd);break;case WM_DESTROY:PostQuitMessage(0);break;}

  这样就完成整个流星雨屏幕程序的实现。如果需要源代码,可以在CSDN博客上面下载,如果没有积分,也可以私聊邮箱,在个人简介里面。
  网址:https://download.csdn.net/download/qq_34430371/12283490

这篇关于流星雨屏幕程序的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/365183

相关文章

JAVA智听未来一站式有声阅读平台听书系统小程序源码

智听未来,一站式有声阅读平台听书系统 🌟&nbsp;开篇:遇见未来,从“智听”开始 在这个快节奏的时代,你是否渴望在忙碌的间隙,找到一片属于自己的宁静角落?是否梦想着能随时随地,沉浸在知识的海洋,或是故事的奇幻世界里?今天,就让我带你一起探索“智听未来”——这一站式有声阅读平台听书系统,它正悄悄改变着我们的阅读方式,让未来触手可及! 📚&nbsp;第一站:海量资源,应有尽有 走进“智听

EMLOG程序单页友链和标签增加美化

单页友联效果图: 标签页面效果图: 源码介绍 EMLOG单页友情链接和TAG标签,友链单页文件代码main{width: 58%;是设置宽度 自己把设置成与您的网站宽度一样,如果自适应就填写100%,TAG文件不用修改 安装方法:把Links.php和tag.php上传到网站根目录即可,访问 域名/Links.php、域名/tag.php 所有模板适用,代码就不粘贴出来,已经打

跨系统环境下LabVIEW程序稳定运行

在LabVIEW开发中,不同电脑的配置和操作系统(如Win11与Win7)可能对程序的稳定运行产生影响。为了确保程序在不同平台上都能正常且稳定运行,需要从兼容性、驱动、以及性能优化等多个方面入手。本文将详细介绍如何在不同系统环境下,使LabVIEW开发的程序保持稳定运行的有效策略。 LabVIEW版本兼容性 LabVIEW各版本对不同操作系统的支持存在差异。因此,在开发程序时,尽量使用

CSP 2023 提高级第一轮 CSP-S 2023初试题 完善程序第二题解析 未完

一、题目阅读 (最大值之和)给定整数序列 a0,⋯,an−1,求该序列所有非空连续子序列的最大值之和。上述参数满足 1≤n≤105 和 1≤ai≤108。 一个序列的非空连续子序列可以用两个下标 ll 和 rr(其中0≤l≤r<n0≤l≤r<n)表示,对应的序列为 al,al+1,⋯,ar​。两个非空连续子序列不同,当且仅当下标不同。 例如,当原序列为 [1,2,1,2] 时,要计算子序列 [

这些心智程序你安装了吗?

原文题目:《为什么聪明人也会做蠢事(四)》 心智程序 大脑有两个特征导致人类不够理性,一个是处理信息方面的缺陷,一个是心智程序出了问题。前者可以称为“认知吝啬鬼”,前几篇文章已经讨论了。本期主要讲心智程序这个方面。 心智程序这一概念由哈佛大学认知科学家大卫•帕金斯提出,指个体可以从记忆中提取出的规则、知识、程序和策略,以辅助我们决策判断和解决问题。如果把人脑比喻成计算机,那心智程序就是人脑的

uniapp设置微信小程序的交互反馈

链接:uni.showToast(OBJECT) | uni-app官网 (dcloud.net.cn) 设置操作成功的弹窗: title是我们弹窗提示的文字 showToast是我们在加载的时候进入就会弹出的提示。 2.设置失败的提示窗口和标签 icon:'error'是设置我们失败的logo 设置的文字上限是7个文字,如果需要设置的提示文字过长就需要设置icon并给

基于SpringBoot的宠物服务系统+uniapp小程序+LW参考示例

系列文章目录 1.基于SSM的洗衣房管理系统+原生微信小程序+LW参考示例 2.基于SpringBoot的宠物摄影网站管理系统+LW参考示例 3.基于SpringBoot+Vue的企业人事管理系统+LW参考示例 4.基于SSM的高校实验室管理系统+LW参考示例 5.基于SpringBoot的二手数码回收系统+原生微信小程序+LW参考示例 6.基于SSM的民宿预订管理系统+LW参考示例 7.基于

Spring Roo 实站( 一 )部署安装 第一个示例程序

转自:http://blog.csdn.net/jun55xiu/article/details/9380213 一:安装 注:可以参与官网spring-roo: static.springsource.org/spring-roo/reference/html/intro.html#intro-exploring-sampleROO_OPTS http://stati

未来工作趋势:零工小程序在共享经济中的作用

经济在不断发展的同时,科技也在飞速发展。零工经济作为一种新兴的工作模式,正在全球范围内迅速崛起。特别是在中国,随着数字经济的蓬勃发展和共享经济模式的深入推广,零工小程序在促进就业、提升资源利用效率方面显示出了巨大的潜力和价值。 一、零工经济的定义及现状 零工经济是指通过临时性、自由职业或项目制的工作形式,利用互联网平台快速匹配供需双方的新型经济模式。这种模式打破了传统全职工作的界限,为劳动

Java程序到CPU上执行 的步骤

相信很多的小伙伴在最初学习编程的时候会容易产生一个疑惑❓,那就是编写的Java代码究竟是怎么一步一步到CPU上去执行的呢?CPU又是如何执行的呢?今天跟随小编的脚步去化解开这个疑惑❓。 在学习这个过程之前,我们需要先讲解一些与本内容相关的知识点 指令 指令是指导CPU运行的命令,主要由操作码+被操作数组成。 其中操作码用来表示要做什么动作,被操作数是本条指令要操作的数据,可能是内存地址,也