DevC++ easyx实现悬浮窗放入网格,与在函数分离过程中遇到的BUG下理解 函数的作用时域 以及 初始化与复位的关系。

news2025/2/5 19:47:03

这次就着上上上篇的悬浮窗代码DevC++ easyx实现图片拖动,一种悬浮窗实现原理与完整代码-CSDN博客

继续实现效果。

基本背景是搓出来图片拖动了,然后想把图片暂存到另一块。再细说背景的背景就是之前提到Unity复刻瓦片地图,想着整合一个铅笔绘制功能,就是绘制瓦片和瓦片粘贴都在同一个程序里运行。正是这一系列文案所追溯的故事——做一个绘图板,连同绘图,贴片。当时实现了图片缩小,然后要把这个缩小的图片的数据放到网格里面。这个网格作为备选的贴片。这就是文案所去描述的故事,只不过现在回想起来,发现以前推动代码翻新过程中,有了比较有意思的意识到矛盾的新情况。

这次直接上最终代码,然后直接解释代码是怎么来的。

#include<stdio.h>
#include<conio.h>
#include<graphics.h>
#include<windows.h>
struct picsave {
	int lx;
	int ly;
	int rx;
	int ry;
	int  useflag=0;
} a[10];

struct pircle {
	IMAGE img2;
	IMAGE img3;
	const int orilx=100,orily=100;
	int nowlx=100,nowly=100;
	const int a=100,h=100;
//	原有图片的左上角坐标
	int m1x=0,m1y=0;

	int  putflag=0;
	int  drawflag=0;


} save;



void draw(struct ExMessage m,struct pircle *save) {
	if(save->drawflag==true) {

		putpixel(m.x,m.y,RGB(255,155,4));
	}


	switch(m.message) {
		case WM_LBUTTONDOWN:
			if(m.x>save->nowlx&&m.x<save->nowlx+save->a&&m.y>save->nowly&&m.y<save->nowly+save->h&&m.ctrl) {
//				检测不在图片里面
			} else {
				printf("m.x = %d\tm.y = %d\t%d\t%d\n",m.x,m.y,save->m1x,save->m1y);
				save->drawflag=true;
//				printf("drawflag = %d\n",save->drawflag);
			}

			break;

		case WM_LBUTTONUP:

			save->drawflag=false;
//			printf("%d\n",save->drawflag);
			break;
	}

}


void check(struct ExMessage m,struct pircle *save,struct picsave a[]) {
	printf("putflag = %d\n",save->putflag);
	printf("%d %d\n",m.x,m.y);
	printf("%d %d\n",save->nowlx,save->nowly);

	if(save->putflag==true) {
		BeginBatchDraw();

		putimage(save->nowlx,save->nowly,&save->img3);

		save->nowlx=save->nowlx+m.x-save->m1x;
		save->nowly=save->nowly+m.y-save->m1y;
		save->m1x=m.x;
		save->m1y=m.y;
		getimage(&save->img3,save->nowlx,save->nowly,save->a,save->h);

		putimage(save->nowlx,save->nowly,&save->img2);

		EndBatchDraw();

//			一次绘图出来,没有屏闪了
	}
	switch(m.message) {

		case WM_LBUTTONDOWN:
			if(m.x>save->nowlx&&m.x<save->nowlx+save->a&&m.y>save->nowly&&m.y<save->nowly+save->h) {
				save->putflag=true;
//					启动批复制粘贴
				getimage(&save->img2,save->nowlx,save->nowly,save->a,save->h);
				save->m1x=m.x;
				save->m1y=m.y;

			}
			break;
		case WM_LBUTTONUP:

			save->putflag=0;


//			int i;
//			for(i=0; i<6; i++) {
//
//				if(a[i].useflag==0) {
//					if(m.x>a[i].lx&&m.x<a[i].rx&&m.y>a[i].ly&&m.y<a[i].ry) {
//						BeginBatchDraw();
//
//						putimage(save->nowlx,save->nowly,&save->img3);
//
//						save->nowlx=save->nowlx+m.x-save->m1x;
//						save->nowly=save->nowly+m.y-save->m1y;
//						save->m1x=m.x;
//						save->m1y=m.y;
//						getimage(&save->img3,save->orilx,save->orily,save->a,save->h);
//
//						putimage(a[i].lx,a[i].ly,&save->img2);
//
//						EndBatchDraw();
//
//						save->nowlx=save->orilx;
//						save->nowly=save->orily;
//						save->m1x=0;
//						save->m1y=0;
//
//						a[i].useflag=1;
//						break;
//					}
//				}
//	}

//			实现一次性存档

			break;
	}

}

void flow(ExMessage m,struct picsave a[],struct pircle *save) {
	if(save->putflag==0&&m.message==WM_LBUTTONUP) {
		int i;
		for(i=0; i<6; i++) {

			if(a[i].useflag==0) {
				if(m.x>a[i].lx&&m.x<a[i].rx&&m.y>a[i].ly&&m.y<a[i].ry) {
					BeginBatchDraw();

					putimage(save->nowlx,save->nowly,&save->img3);

//					save->nowlx=save->nowlx+m.x-save->m1x;
//					save->nowly=save->nowly+m.y-save->m1y;
//					save->m1x=m.x;
//					save->m1y=m.y;

					getimage(&save->img3,save->orilx,save->orily,save->a,save->h);

					putimage(a[i].lx,a[i].ly,&save->img2);

					EndBatchDraw();

					save->nowlx=save->orilx;
					save->nowly=save->orily;
					save->m1x=0;
					save->m1y=0;

					a[i].useflag=1;
					break;
				}
			}
		}
	}

}

int main() {
	initgraph(640,640,EX_SHOWCONSOLE);
	setbkcolor(WHITE);
	cleardevice();


	setfillcolor(BLACK);
	setlinecolor(BLACK);
	fillrectangle(100,100,200,200);
//	这是初始图片左上角位置,以后都是新图片左上角的位置
	int i;
//	setlinecolor(WHITE);
	setfillcolor(GREEN);
	int q=100;
	for(i=1; i<5; i++) {
		a[i].lx=q;
		a[i].ly=400;
		a[i].rx=q+100;
		a[i].ry=500;
		q=q+100;
		fillrectangle(a[i].lx,a[i].ly,a[i].rx,a[i].ry);
	}
//	save.drawflag=1;

	ExMessage m;
	while(1) {
		m=getmessage(EX_MOUSE|EX_KEY);


		if(save.drawflag==false||save.drawflag==true) {
			draw(m,&save);

		}
		if(save.putflag==true||save.putflag==false) {
			check(m,&save,a);
			flow(m,a,&save);

		}


	}
	closegraph();
	return 0;
}


由于鼠标检测实现原理是,通过鼠标坐标m.x  m.y和鼠标事件如左键按下,右键按下,实际上延续这个问题就是坐标的问题,不断穷举坐标的各种相关、各种不知道相关不相关的判断。

想象中的需求经过几次描述出来就是,图片到了网格,图片就被网格吸收。

换成坐标来说,图片的坐标进了网格,图片就停在网格里。

但是想象一下图片只是黏在网格上,而不是正好嵌入,就单纯的坐标检测是否重叠也不好想象代码。

这里是参考UNITY,想起来以鼠标为主,就是鼠标在哪个网格,图片就嵌进去哪个网格,这样也能接受,那如此这样,只要能实现检测鼠标的位置就可以了。正好之前的代码check负责拖动,只要拖动结束的时候直接检测就行了,这样代码位置也解决了。于是就直接在check函数里的case LW_LBUTTONUP:这个分支下去写,就是check()函数那一大片注释处。只要全部取消,就能直接使用那部分代码实现检测。

后来是想着,由于地图实现拖动了,图片也实现的网格吸收,就想着独立出来这部分吸收代码,希望以后能够直接使用,或者减少函数长度,一个函数一个功能,减少脑子别扭难受的情况。于是就分离出来flow()函数,这就是专门处理图片嵌入网格存储的。flow()有一堆空白图片数组,然后每个数组的一项单元里,都有这个项对应的坐标,每一个网格的左上角坐标就都在这个项目里面。

然后运行成功,但是,鼠标一碰到网格图片就自己进去了。

这个BUG的效果是无论鼠标点没点击,只要鼠标拖动过图片,然后鼠标移动到网格上,就会有图片贴上去。

然后当时不知道哪里出问题了,唯一确定的是代码没复制粘贴整合成新函数的时候是正常的,于是就检测数据,相当于把有关拖动的变量内容都打印出来,先是在flow()里面增加打印的坐标信息语句,发现随着鼠标移动,就会一直打印鼠标坐标,而按照原计划,是只有鼠标松动的时候才进行检测,相当于打印鼠标只有在鼠标松开,而不是鼠标一移动就打印。flow函数失去了限制功能。

然后扩大范围,相当于发现if(save->putflag==0)失效了,之前想着不是鼠标松开,上一个函数直接就把save->putflag变成0,但是实际上这样却失败了,最后只能再就加上重复的&&m.message==LW_LBUTTONUP,才解决问题,但是没有理解bug。明明上个函数也已经用过一次m.message==LW_LBUTTONUP了。

现在来看,原来是鼠标松开,实现了flag变化,但是flag变化后是长期的,而鼠标松开是一瞬间相等。显然这样一看才理解,作用时间不一样导致了函数运行情况不同。也就是说,根本是没有意识到范围,默认中范围就已经不包含了一瞬间的变化,和长期状态的影响。只能通过矛盾来主动意识到意料之外,强行拓宽思考范围。

当然,文案不只是说为了解决BUG,可以看出来,刚才的BUG就是意外实现了鼠标拖动批量绘制,而这其实这也是以后像素绘画的原理。但是由于在这里能够主动意识到矛盾,对矛盾开发一下,自然而然就是另一个文案了。实际上无中生有的BUG和无中生有的解决方案,其实是同根同源的。他们都脱离过主动意识,而是从一些没来得及,或者以为不相关的情况里自然而然的穷举产生的。

人和BUG和谐共生可还行?但是一般都是BUG得不到理解,BUG也放不到合适的地方去应用emm。

理解BUG可以成为灵感的来源,但是理解bug比解决bug还要费劲,几乎把整个代码用人脑跑一边才能理解问题现象,确实代价比较大。

注意到if(save->putflag==0)和if(save->putflag==0&&m.message==WM.LBUTTONUP)的区别。

第一个BUG完事儿。

另一个BUG是在函数flow分离之前发生的。但是由于代码是复制粘贴,把原来函数的限制条件也复制粘贴过来,其实问题一样。

先看BUG效果

黑色方块变绿色了

纹理和第一幅图的比较像

答案解密:

注意旁边浅蓝色的代码

注意到坐标信息是原图的坐标

相当于又把原图复制粘贴到img3上。

按照惯例,前三章博客里img3含义都是底图,

这里也是一样,描述出来就是,原图变成了底图,

原来根本原因就是悬浮窗的底图把图片放置位置的网格复制了,

然后图片恢复到原处,借用悬浮窗先恢复原图,结果成了原图位置恢复网格纹理

所以需要清空img3,或者说不能清空的话,就把原来的图复制粘贴上。

这就是所谓复位——初始化所解决的矛盾的另一种表现形式。

初始化可以说是在旧数据矛盾不明显下的解决方案,因为不能解释旧数据是什么,

而复位,可以说是在旧数据矛盾明显下的解决方案,因为知道旧数据是上一次图片,而不需要使用这上一次图片,或者说不得不使用粘贴功能,但是可以更改粘贴的内容,把粘贴原来的旧图片变成粘贴相同的图片。

复位就是同样是图片,但是图片里面的数据清除。

而初始化,则是这个存数据的地方,曾经是存过图片的,但是这个数据现在已经不用来存图片,可以存其他的数据,但是里面存的图片数据还没清楚,就需要初始化,在不知道里面存的是什么的情况下直接清除数据,或者用新数据覆盖旧的乱七八糟的数据。

这就是从相同图片变量复位,同一个内存的重写,实现对危险数据的清除;到不同变量类型,使用相同内存,对内存重写数据,所描述出的初始化。

这就是复位和初始化的关系。

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

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

相关文章

web前端 JQuery下拉菜单的案例

浏览器运行结果&#xff1a; JQuery下载&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/17LXZigLQ8yau0toTGj4P_Q?pwd4332 提取码&#xff1a;4332 代码&#xff1a; <!doctype html> <html> <head> <meta charset"UTF-8"><…

Emu2:37亿参数开创多模态生成新篇章

引言 多模态任务在人工智能领域一直是极具挑战性的「技术高地」。智源研究院最近开源发布的新一代多模态基础模型Emu2&#xff0c;在这一领域取得了突破性进展。Emu2以其庞大的37亿参数规模和强大的多模态生成能力&#xff0c;为AI的多模态理解和生成开启了新的篇章。 模型概…

【重点!!!】【贪心】45.跳跃游戏II

题目 法1&#xff1a;贪心 贪心是最优解法&#xff0c;必须掌握&#xff01;重点理解&#xff0c;看B站视频辅助&#xff01;&#xff01;&#xff01; 在具体的实现中&#xff0c;我们维护当前能够到达的最大下标位置&#xff0c;记为边界。我们从左到右遍历数组&#xff0…

记账导出excel表格,用表格导出账目数据

我们每天都在跟金钱打交道,记账则是更好地管理自己财务的一种方式&#xff0c;传统记账不仅繁琐&#xff0c;还容易出错。那么&#xff0c;有没有简单、高效的记账方式呢&#xff1f;答案是肯定的&#xff01;今天&#xff0c;我们就向大家推荐一款全新的记账软件——晨曦记账本…

Windows系统重启Redis服务

Windows系统 在安装Redis的目录下打开终端 执行 redis-cli.exe shutdown先停止 Redis 服务 然后 执行 redis-server.exe启动Redis服务

数字 IC 设计职位经典笔/面试题,建议收藏!

共100道经典笔试、面试题目&#xff08;文末可全领&#xff09; 什么是同步逻辑和异步逻辑&#xff1f; 同步逻辑是时钟之间有固定的因果关系。异步逻辑是各时钟之间没有固定的因果关系。同步时序逻辑电路的特点&#xff1a;各触发器的时钟端全部连接在一起&#xff0c;并接在…

[大厂实践] DoorDash基于eBPF的监控实践

eBPF是监控云原生应用的强大工具&#xff0c;本文介绍了DoorDash构建基于eBPF的监控系统的实践。原文: BPFAgent: eBPF for Monitoring at DoorDash 随着DoorDash在过去几年中经历了快速增长&#xff0c;我们开始看到传统监控方法的局限性。度量、日志和跟踪提供了服务生态系统…

el-table中表头自定义动态渲染

el-table中有时候我们可能遇到需要表头自定义以数组的形式进行循环显示 当我们改变tableHead时我们自定义的表头没有跟随渲染 有人会使用this.$refs.table.doLayout这个只能动态渲染更换数据布局 会对 Table 进行重新布局。当 Table 或其祖先元素由隐藏切换为显示时&#xff…

论文分享 | SINGFAKE:歌声深度伪造检测

以下文章来源于智能语音新青年 &#xff0c;作者ttslr 论文地址&#xff1a; https://arxiv.org/pdf/2309.07525.pdf 合成歌声的兴起给艺术家和行业利益相关者带来了未经授权使用歌声的严峻挑战。与合成语音不同&#xff0c;合成歌声通常是在含有强烈背景音乐的歌曲中发布的&a…

2024年最新的人工智能工程师证书 已经开始报名了

2024年最新的人工智能工程师证书 已经开始报名了&#xff0c;以下有报考条件和证书样式可做参考&#xff1a; 计算机自然语言及语音处理设计开发工程师&#xff08;中级&#xff09; 计算机视觉处理设计开发工程师&#xff08;中级&#xff09; 1.人工智能工程师证书培训对象 …

Codeforces Round 917 (Div. 2)

Codeforces Round 917 (Div. 2) Codeforces Round 917 (Div. 2) A. Least Product 题意&#xff1a; 给出整数数组a&#xff0c;现在可以执行任意次数以下操作&#xff1a;任意选择数组a的一个元素 a i a_i ai​&#xff0c;若 a i a_i ai​>0可以任意替换为[0, a i a_i…

网络的七层结构模型

网络的七层结构模型&#xff0c;亦称OSI&#xff08;Open Systems Interconnection&#xff09;模型&#xff0c;包括物理层、数据链路层、网络层、传输层、会话层、表示层和应用层。以下是各层的主要功能&#xff1a; 从下往上分别是1-7&#xff0c;总共7层&#xff0c;每一层…

【NI-RIO入门】记录和监控数据

1.内部存储器 可以使用常规文件 I/O VI 在嵌入式程序中以编程方式访问实时控制器的内部存储。文件路径结构根据控制器运行的实时操作系统 (RTOS) 的不同而有所不同。 该文件路径语法记录在教程&#xff1a;使用实时目标上的文件路径 中。 可以通过在Measurement & Automati…

全国5米土地利用遥感监测数据(GB/T 21010-2017)

全国5米土地利用遥感监测数据 全国5米土地利用类型遥感监测空间分布数据&#xff0c;是基于谷歌高分辨率影像数据人机交互解译形成&#xff0c;并使用POI数据、ROI数据进行数据修正。根据GB/T 21010-2017《土地利用现状分类》将土地利用类型分为12个一级类&#xff0c;73个二级…

SpringBoot 3.2.0 基于Logback定制日志框架

依赖版本 JDK 17 Spring Boot 3.2.0 工程源码&#xff1a;Gitee 日志门面和日志实现 日志门面&#xff08;如Slf4j&#xff09;就是一个标准&#xff0c;同JDBC一样来制定“规则”&#xff0c;把不同的日志系统的实现进行了具体的抽象化&#xff0c;只提供了统一的日志使用接…

SAP ME21/22/23N 创建增强ME_PROCESS_PO_CUST

增强ME_PROCESS_PO_CUST 二、实现方式&#xff1a;实现的方式可以有很多种&#xff0c;这里讲一下用BADI增强ME_PROCESS_PO_CUST实现的方式 第一步&#xff1a;执行事务码se19,在BAdI Name处输入&#xff1a;ME_PROCESS_PO_CUST&#xff0c;然后点“Create Impl”按钮 第二步…

鸿蒙列表,item组件封装传参问题?@ObjectLink 和@Observerd

鸿蒙列表渲染&#xff0c;封装内容组件&#xff0c;进行item传参会报错&#xff1f; class FoodClass {order_id: number 0food_name: string ""food_price: number 0food_count: number 0 }Entry Component struct Demo07 {State message: string Hello World…

C练习——不创建临时变量,交换两个数值

面试可能会问 方法一&#xff08;有缺陷&#xff0c;int 型数值有上限&#xff0c;ab可能超范围&#xff09; // int 型数值有上限&#xff0c;ab可能超范围 #include <stdio.h> int main() {int a 2;int b 3;printf("交换前&#xff1a;%d %d\n", a, b);a…

SpringBoot整合JWT+Spring Security+Redis实现登录拦截(一)登录认证

一、JWT简介 JWT 全称 JSON Web Token&#xff0c;JWT 主要用于用户登录鉴权&#xff0c;当用户登录之后&#xff0c;返回给前端一个Token&#xff0c;之后用户利用Token进行信息交互。 除了JWT认证之外&#xff0c;比较传统的还有Session认证&#xff0c;如何选择可以查看之前…

基于单片机的语音识别自动避障小车(论文+源码)

1.系统设计 此次基于单片机的语音识别自动避障小车&#xff0c;以STC89C52单片机作为系统的主控制器&#xff0c;利用超声波模块来实现小车与障碍物距离的测量并通过LCD液晶显示&#xff0c;当距离低于阈值时会通过WT588语音模块进行报警提示&#xff0c;并且小车会后退来躲避…