Day11 制作窗口

文章目录

      • 1. 显示窗口(harib08d)
      • 2. 消除闪烁1(harib08g)
      • 3. 消除闪烁2(harib08h)

本章的前三节做了如下修改:

  1. 解决了鼠标无法隐藏在屏幕右侧和下侧的问题。
  2. 当鼠标隐藏在右侧时会在屏幕最左侧产生阴影的问题。
  3. 在struct SHEET结构体中添加struct SHTCTL类型指针,以减少接口中参数列表的个数。

1. 显示窗口(harib08d)

类似制作背景和鼠标,需要先准备一个图层,然后在图层buffer中描绘一个类似窗口的图。make_window8函数类似graphic.c中的init_screen8函数,其中“x”按钮使用类似init_mouse_cursor8的方法。

void make_window8(unsigned char *buf, int xsize, int ysize, char *title)
{static char closebtn[14][16] = {"OOOOOOOOOOOOOOO@","OQQQQQQQQQQQQQ$@","OQQQQQQQQQQQQQ$@","OQQQ@@QQQQ@@QQ$@","OQQQQ@@QQ@@QQQ$@","OQQQQQ@@@@QQQQ$@","OQQQQQQ@@QQQQQ$@","OQQQQQ@@@@QQQQ$@","OQQQQ@@QQ@@QQQ$@","OQQQ@@QQQQ@@QQ$@","OQQQQQQQQQQQQQ$@","OQQQQQQQQQQQQQ$@","O$$$$$$$$$$$$$$@","@@@@@@@@@@@@@@@@"};int x, y;char c;boxfill8(buf, xsize, COL8_C6C6C6, 0,         0,         xsize - 1, 0        );boxfill8(buf, xsize, COL8_FFFFFF, 1,         1,         xsize - 2, 1        );boxfill8(buf, xsize, COL8_C6C6C6, 0,         0,         0,         ysize - 1);boxfill8(buf, xsize, COL8_FFFFFF, 1,         1,         1,         ysize - 2);boxfill8(buf, xsize, COL8_848484, xsize - 2, 1,         xsize - 2, ysize - 2);boxfill8(buf, xsize, COL8_000000, xsize - 1, 0,         xsize - 1, ysize - 1);boxfill8(buf, xsize, COL8_C6C6C6, 2,         2,         xsize - 3, ysize - 3);boxfill8(buf, xsize, COL8_000084, 3,         3,         xsize - 4, 20       );boxfill8(buf, xsize, COL8_848484, 1,         ysize - 2, xsize - 2, ysize - 2);boxfill8(buf, xsize, COL8_000000, 0,         ysize - 1, xsize - 1, ysize - 1);putfonts8_asc(buf, xsize, 24, 4, COL8_FFFFFF, title);for (y = 0; y < 14; y++) {for (x = 0; x < 16; x++) {c = closebtn[y][x];if (c == '@') {c = COL8_000000;} else if (c == '$') {c = COL8_848484;} else if (c == 'Q') {c = COL8_C6C6C6;} else {c = COL8_FFFFFF;}buf[(5 + y) * xsize + (xsize - 21 + x)] = c;}}return;
}

在HariMain函数中相应的调用窗口函数和图层处理函数,显示效果:
在这里插入图片描述

2. 消除闪烁1(harib08g)

图层刷新的规则:

  1. 如果窗口图层变化,无鼠标图层,则刷新窗口图层,不需要刷新背景图层。
  2. 如果窗口图层变化,鼠标在其上,则刷新窗口图层的同时刷新鼠标图层(因为窗口的刷新会覆盖鼠标的一部分显示区域),同样不需要刷新背景图层。

首先修改sheet_refreshsub函数,在参数列表中追加h0入参,表示只刷新在此h0图层及以上的图层。对应的sheet处理函数有对sheet_refreshsub的调用都需要修改。

void sheet_refreshsub(struct SHTCTL *ctl, int vx0, int vy0, int vx1, int vy1, int h0)
{// 略for (h = h0; h <= ctl->top; h++) {// 略}return;
}

其中,在sheet_slide函数中,图层移动时会导致下面的图层露出,因此需要从下面的图层开始刷新。在图层所移动到的目标位置处,比新移来的图层低的图层没有什么变化,只是需要隐藏一部分,所以只需要刷新移动图层和它上面的图层。
sheet_updown函数中,同样的思路,针对个别不需要自下而上全部刷新的图层,仅刷新其局部。
查看效果,窗口图层已经不再闪烁了,只是如果鼠标放置在上面,还是会产生闪烁。
在这里插入图片描述

3. 消除闪烁2(harib08h)

鼠标的闪烁显现是由于一会描绘一会消除产生的。如果期望消除闪烁,就需要在刷新窗口时,避开鼠标覆盖的区域对VRAM的写入处理。
开辟一块内存,大小与VRAM相同,称其为map。这块内存用来表示画面上的点是哪个图层的像素,因此可以理解为图层的地图。
如图,期望刷新图层1的时候,参照map的内容刷新,就不必担心图层1和图层2的重叠部分了。
在这里插入图片描述

struct SHTCTL {unsigned char *vram, *map;int xsize, ysize, top;struct SHEET *sheets[MAX_SHEETS];struct SHEET sheets0[MAX_SHEETS];
};/* 向图层中写入号码 */
void sheet_refreshmap(struct SHTCTL *ctl, int vx0, int vy0, int vx1, int vy1, int h0)
{int h, bx, by, vx, vy, bx0, by0, bx1, by1;unsigned char *buf, sid, *map = ctl->map;struct SHEET *sht;if (vx0 < 0) { vx0 = 0; }if (vy0 < 0) { vy0 = 0; }if (vx1 > ctl->xsize) { vx1 = ctl->xsize; }if (vy1 > ctl->ysize) { vy1 = ctl->ysize; }for (h = h0; h <= ctl->top; h++) {sht = ctl->sheets[h];sid = sht - ctl->sheets0; /* 将进行了减法运算的地址作为图层的号码 */buf = sht->buf;bx0 = vx0 - sht->vx0;by0 = vy0 - sht->vy0;bx1 = vx1 - sht->vx0;by1 = vy1 - sht->vy0;if (bx0 < 0) { bx0 = 0; }if (by0 < 0) { by0 = 0; }if (bx1 > sht->bxsize) { bx1 = sht->bxsize; }if (by1 > sht->bysize) { by1 = sht->bysize; }for (by = by0; by < by1; by++) {vy = sht->vy0 + by;for (bx = bx0; bx < bx1; bx++) {vx = sht->vx0 + bx;if (buf[by * sht->bxsize + bx] != sht->col_inv) {map[vy * ctl->xsize + vx] = sid;}}}}return;
}void sheet_refreshsub(struct SHTCTL *ctl, int vx0, int vy0, int vx1, int vy1, int h0, int h1)
{int h, bx, by, vx, vy, bx0, by0, bx1, by1;unsigned char *buf, *vram = ctl->vram, *map = ctl->map, sid;struct SHEET *sht;/* 如果refresh的范围超出了画面则修正 */if (vx0 < 0) { vx0 = 0; }if (vy0 < 0) { vy0 = 0; }if (vx1 > ctl->xsize) { vx1 = ctl->xsize; }if (vy1 > ctl->ysize) { vy1 = ctl->ysize; }for (h = h0; h <= h1; h++) {sht = ctl->sheets[h];buf = sht->buf;sid = sht - ctl->sheets0;/* 利用vx0 ~ vy1,对bx0 ~ by1倒推 */bx0 = vx0 - sht->vx0;by0 = vy0 - sht->vy0;bx1 = vx1 - sht->vx0;by1 = vy1 - sht->vy0;if (bx0 < 0) { bx0 = 0; }if (by0 < 0) { by0 = 0; }if (bx1 > sht->bxsize) { bx1 = sht->bxsize; }if (by1 > sht->bysize) { by1 = sht->bysize; }for (by = by0; by < by1; by++) {vy = sht->vy0 + by;for (bx = bx0; bx < bx1; bx++) {vx = sht->vx0 + bx;if (map[vy * ctl->xsize + vx] == sid) {		// 修改点vram[vy * ctl->xsize + vx] = buf[by * sht->bxsize + bx];}}}}return;
}void sheet_refresh(struct SHEET *sht, int bx0, int by0, int bx1, int by1)
{if (sht->height >= 0) { /* 如果正在显示,则按照新图层的信息进行刷新 */sheet_refreshsub(sht->ctl, sht->vx0 + bx0, sht->vy0 + by0, sht->vx0 + bx1, sht->vy0 + by1, sht->height, sht->height);}return;
}void sheet_slide(struct SHEET *sht, int vx0, int vy0)
{struct SHTCTL *ctl = sht->ctl;int old_vx0 = sht->vx0, old_vy0 = sht->vy0;sht->vx0 = vx0;sht->vy0 = vy0;if (sht->height >= 0) { /* 如果正在显示,则按照新图层的信息进行刷新 */sheet_refreshmap(ctl, old_vx0, old_vy0, old_vx0 + sht->bxsize, old_vy0 + sht->bysize, 0);sheet_refreshmap(ctl, vx0, vy0, vx0 + sht->bxsize, vy0 + sht->bysize, sht->height);sheet_refreshsub(ctl, old_vx0, old_vy0, old_vx0 + sht->bxsize, old_vy0 + sht->bysize, 0, sht->height - 1);sheet_refreshsub(ctl, vx0, vy0, vx0 + sht->bxsize, vy0 + sht->bysize, sht->height, sht->height);}return;
}

sheet_refresh函数里,由于图层的上下关系没有变,所以不需要重新进行refreshmap的处理。
sheet_slide函数里,需要先重写map,分别对应移动前后的图层,然后调用sheet_refreshsub函数。在移动前的地方,只针对上层图层移走后而露出的下层图层进行重绘就行了,在移动目的地处仅重绘了一张移动过去的图层。
sheet_updown函数,同样在调用sheet_refreshsub之前,需要先执行sheet_refreshmap重新绘制map。
此时的屏幕将不再闪烁,看起来像是一个比较现代化的电脑了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/pingmian/86871.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/86871.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python+uniapp基于微信小程序蜀味道江湖餐饮管理系统nodejs+java

文章目录 具体实现截图本项目支持的技术路线源码获取详细视频演示&#xff1a;文章底部获取博主联系方式&#xff01;&#xff01;&#xff01;&#xff01;本系统开发思路进度安排及各阶段主要任务java类核心代码部分展示主要参考文献&#xff1a;源码获取/详细视频演示 ##项目…

postgresql增量备份系列二 pg_probackup

已经很久没有发文章了,主要是最近工作上的内容都不适合发文章公开。可能往后文章发表也不这么频繁了,不过大家有问题我们可以交流。之前有写过PG增量备份的其他工具使用方法,pg_probackup也是应用比较多的PG备份工具。 一. pg_probackup pg_probackup 是一个用于管理 Postg…

云手机主要是指什么?

云手机是指一种可以运行在云服务器中的手机&#xff0c;主要是将云计算技术运用于网络终端服务&#xff0c;通过云服务器来实现云服务的手机&#xff0c;也是一款深度结合了网络服务的手机&#xff0c;通过自带的系统和网络终端可以通过网络实现众多功能。 那么&#xff0c;下面…

CAU数据挖掘 支持向量机

SVM大致思想 线性分类问题 在一群点中用线性函数分类&#xff1a; 但也有线性不可分问题&#xff1a; 线性不可分问题&#xff1a; 最大间隔法 两个平行超平面间隔距离最大 软间隔 部分难以区分的点忽略 升维 通过升维将非线性变为线性 计算统计理论基础 学习过…

探索理解 Spring AI Advisors:构建可扩展的 AI 应用

Spring AI Advisors API 提供了一种灵活且强大的方式来拦截、修改和增强 Spring 应用程序中的 AI 驱动交互。其核心思想类似于 Spring AOP&#xff08;面向切面编程&#xff09;中的“通知”&#xff08;Advice&#xff09;&#xff0c;允许开发者在不修改核心业务逻辑的情况下…

Linux SSH服务全面配置指南:从基础到安全加固

Linux SSH服务全面配置指南&#xff1a;从基础到安全加固 概述 作为网络安全工程师&#xff0c;SSH&#xff08;Secure Shell&#xff09;服务的安全配置是我们日常工作中不可忽视的重要环节。本文将从基础配置到高级安全加固&#xff0c;全面解析SSH服务的各项参数&#xff…

.NET测试工具Parasoft dotTEST内置安全标准,编码合规更高效

在追求开发速度的时代&#xff0c;确保代码安全并满足严苛的行业合规标准如OWASP、CWE、PCI DSS、ISO 26262等已成为开发者的核心挑战&#xff0c;但开发人员常因复杂的编码标准和漏洞排查而效率低下。.NET测试工具Parasoft dotTEST内置安全标准&#xff0c;实现即插即用&#…

对象的finalization机制Test

Java语言提供了对象终止(finalization)机制来允许开发人员自定义对象被销毁之前的处理逻辑。当垃圾回收器发现没有引用指向一个对象时&#xff0c;通常接下来要做的就是垃圾回收&#xff0c;即清除该对象&#xff0c;而finalization机制使得在清除此对象之前&#xff0c;总会先…

AI初学者如何对大模型进行微调?——零基础保姆级实战指南

仅需8GB显存&#xff0c;三步完成个人专属大模型训练 四步实战&#xff1a;从环境配置到模型发布 步骤1&#xff1a;云端环境搭建&#xff08;10分钟&#xff09; 推荐使用阿里魔塔ModelScope免费GPU资源&#xff1a; # 注册后执行环境初始化 pip3 install --upgrade pip pi…

“单一职责”模式之装饰器模式

目录 “单一职责”模式装饰器模式 Decorator引例动机 Motivation模式定义结构 Structure要点总结 “单一职责”模式 在软件组件的设计中&#xff0c;如果责任划分的不清晰&#xff0c;使用继承得到的结果往往是随着需求的变化&#xff0c;子类急剧膨胀&#xff0c;同时充斥着重…

idea, CreateProcess error=206, 文件名或扩展名太长

idea, CreateProcess error206, 文件名或扩展名太长 解决 “CreateProcess error206, 文件名或扩展名太长” 错误 CreateProcess error206 是 Windows 系统特有的错误&#xff0c;表示命令行参数超出了 Windows 的 32767 字符限制。这个问题在 Java 开发中尤其常见&#xff0c…

一键高效率图片MD5修改工具PHP版

文章目录 图片MD5修改工具项目简介功能特点技术原理系统需求安装方法使用方法Web界面模式命令行模式文件结构常见问题注意事项开发者信息效果演示更多干货🎁1.如果我的博客对你有帮助、如果你喜欢我的博客内容,请 “👍点赞” “✍️评论” “💙收藏” 一键三连哦!2.❤️…

跨主机用 Docker Compose 部署 PostgreSQL + PostGIS 主从

q下面是跨主机用 Docker Compose 部署 PostgreSQL PostGIS 主从复制的完整详细步骤&#xff08;主库 从库&#xff09;&#xff0c;主从都用官方 PostGIS 镜像 postgis/postgis:15-3.3&#xff0c;并注意网络与持久化。复制即可。 &#x1f6a9; 跨主机 PostgreSQL PostGIS …

会议动态|千眼狼高速摄像机、DIC测量系统等科学仪器亮相第十五届全国爆炸力学学术会议

第十五届全国爆炸力学学术会议于6月28日在绍兴盛大召开&#xff0c;会议汇聚来自全国爆炸力学与冲击领域专家学者2000余人&#xff0c;聚焦“爆炸与冲击动力学工程应用”、“材料动态力学行为与损伤断裂“、“工程爆破与毁伤评估”、“含能材料与水中爆炸”、“结构动态响应与安…

vscode一个文件夹有残余的git仓库文件,已经失效了,怎样进行清空仓库残余文件并重新初始化git--ubuntu

vscode一个文件夹有残余的git仓库文件&#xff0c;已经失效了&#xff0c;怎样进行清空仓库残余文件并重新初始化git–ubuntu 首先要把工作区里重要的文件备份好&#xff0c;防止操作时数据丢失。删除.git文件夹 rm -rf .git初始化 (base) zd4090zd4090-System-Product-Name:…

6月30日作业

思维导图 一、读取文件&#xff0c;效果类似 cat 的功能 代码 #include <25041head.h>int main(int argc, const char *argv[]) {//打开文件printf("请输入你要读取的文件路径&#xff1a;");char str[128]"";scanf("%s",str);FILE *fpf…

ubuntu源码安装python3.13遇到Could not build the ssl module!解决方法

我在Ubuntu 24.04.2 LTS下载源码安装Python 3.13.5时&#xff1a; #./configure --enable-loadable-sqlite-extensions --enable-optimizations #make 显示错误信息&#xff1a; Could not build the ssl module! Python requires a OpenSSL 1.1.1 or newer 查询我的openssl版…

Ai工具分享(2):Vscode+Cline无限免费的使用教程

大家好,我是程序员寒山。 今天给大家分享一个最新的免费使用的Ai插件Cline的方法,之前也给大家分享过一些免费的方案,但是这些都是随时在变化,之前推荐的很多都不能使用了。 Ai工具分享(2):Vscode+Cline无限免费的使用教 今天再给大家推荐一个,可以免费使用,且没有token…

Docker 目录迁移脚本【Windows Junction 类型链接】

Docker 目录迁移脚本完整教程&#xff1a;从诞生到自动化使用 一、脚本诞生背景与开发历程 1. 为什么需要迁移 Docker 目录&#xff1f; 系统盘空间压力&#xff1a;Docker 镜像和容器数据通常存储在C:\Users\用户名目录下&#xff0c;随着使用时间增长会占用大量系统盘空间…

spring-ai 工作流

目录 工作流概念工作流程图spring-boot 编码定义节点 (Node)定义节点图StateGraphcontroller测试浏览器测试用户输入 工作流概念 工作流是以相对固化的模式来人为地拆解任务&#xff0c;将一个大任务拆解为包含多个分支的固化流程。工作流的优势是确定性强&#xff0c;模型作为…