EasyX图形库使用教程

news/2025/2/23 13:37:05

文章目录

  • EasyX 图形库基础使用教程(快速上手)
    • 前言:本文简单详细的介绍了EasyX图形库的常用函数和操作,帮助EasyX的快速上手
    • 1、绘制简单的图形窗口
      • 1.1头文件
      • 1.2创建图形化窗口
        • initgraphy函数
        • closegraph函数
      • 1.3窗口坐标
    • 2、设置图形窗口属性
      • 2.1颜色设置
        • setbkcolo
        • RGB
        • cleardevice 刷新
    • 3、使用EasyX实现基本绘图功能
      • 3.1 line 画线
      • 3.1 circle 画圆
      • 3.2 rectangle 画矩形
      • 3.3 setfillcolor 填充颜色
    • 4、使用EasyX实现贴图功能
      • 4.1 原样贴图
        • putimage 绘制图像
        • loadimage 加载图像
      • 4.2 透明贴图
      • 4.3双缓冲贴图
        • BeginBatchDraw 开始双缓冲
        • EndBatchDraw 结束双缓冲
        • FlushBatchDraw 显示一帧
    • 5、实现EasyX按键件交互功能
    • 6、在EasyX中进行鼠标操作
      • ExMessage 保存鼠标信息
      • PeekMessage 获取鼠标信息

EasyX 图形库基础使用教程(快速上手)

前言:本文简单详细的介绍了EasyX图形库的常用函数和操作,帮助EasyX的快速上手

1、绘制简单的图形窗口

1.1头文件

graphics.h :包含已经被淘汰的函数

easyx.h: 只包含最新的函数

1.2创建图形化窗口

initgraphy函数

initgraph函数

HWND initgraph(
	int width,		//绘图窗口的宽度
	int height,		//绘图窗口的高度
    int flag=NULL	//绘图窗口的样式,默认为NULL,
);

flag的值还可以为:

含义
EX_DBLCLKS在绘图窗口中支持鼠标双击事件。
EX_NOCLOSE禁用绘图窗口的关闭按钮。
EX_NOMINIMIZE禁用绘图窗口的最小化按钮。
EX_SHOWCONSOLE显示控制台窗口。

简单句两个例子,其他同理:

创建一个尺寸为 640x480 的绘图窗口:

initgraph(640, 480);

创建一个禁用绘图窗口的关闭按钮并且尺寸为 640x480 的绘图窗口:

initgraph(640, 480,EX_NOCLOSE);

closegraph函数

closegraph函数

用于关闭绘图窗口void closegraph();

1.3窗口坐标

坐标轴及原点可按如图理解:

image-20240808142835194

2、设置图形窗口属性

2.1颜色设置

setbkcolo

setbkcolor函数

void setbkcolo(COLORREF color);

注:在设置背景颜色后并不会改变现有的背景色,只是改变了背景色的值,之后再执行绘图语句,例如outtextxy,才会使用新设置的背景色值。

函数()中的值就是各种颜色对应的英文,在VS中可以右键—跳转到定义查看,以setbkcolo(RED)为例,右键RED跳转,可以看到各种颜色的值。

RGB

RGB函数

COLORREF RGB(
	BYTE byRed,		// 颜色的红色部分
	BYTE byGreen,	// 颜色的绿色部分
	BYTE byBlue		// 颜色的蓝色部分
);

使用三原色进行调光,原理同画图中的调色板,可以找到喜欢的颜色把三原色的数字输入,注意使用RGB时也要在外面加setbkcolor(),例:

setbkcolor(RGB(200,100,100));
cleardevice 刷新

cleardevice函数

void cleardevice();

使用当前别景色清空绘图设备,刷新颜色。

3、使用EasyX实现基本绘图功能

3.1 line 画线

line函数

void line(
	int x1,	 int y1,  int x2,  int y2,
);

在(x1,y1)和(x2,y2)两点间画一条线段。

3.1 circle 画圆

circle函数

void circle(
	int x,	int y,	int radius
);

以坐标(x,y)为圆心,画一个半径为radius的圆

3.2 rectangle 画矩形

rectangle函数

void rectangle(
	int left,	int top,	int right,	int bottom
);

确定举行的左上角和右下角坐标,画一个矩形

3.3 setfillcolor 填充颜色

setfillcolor函数

void setfillcolor(COLORREF color);

填充圆

  • 带线: fillcircle(int x, int y, int r);
  • 不带线: solidcircle(int x, int y, int r);

填充矩形

  • 带线: fillrectangle(int x1, int y1, int x2, int y2);

  • 不带线: solidrectangle(int x1, int y1, int x2, int y2);

代码举例:

int main()
{
	initgraph(700, 550);		//初始化图形界面尺寸
	setfillcolor(LIGHTBLUE);	//设置填充颜色
	fillcircle(150, 150, 50);	//画一个带线的圆
	solidcircle(300, 150, 50);	//画一个不带线的圆

	fillrectangle(150, 300, 280, 450);	//画一个带线的矩形
	solidrectangle(150, 300, 280, 450);	//画一个不带线的矩形

	while (1);		//防止图形化窗口一闪而过
	closegraph();	//关闭窗口
	return 0;
}

效果如图:

image-20240808211025026

4、使用EasyX实现贴图功能

4.1 原样贴图

putimage 绘制图像

putimage函数

void putimage(
	int dstX,				// 绘制位置的 x 坐标
	int dstY,				// 绘制位置的 y 坐标
	IMAGE *pSrcImg,			// 要绘制的 IMAGE 对象指针
	DWORD dwRop = SRCCOPY	// 三元光栅操作码
);
void putimage(
	int dstX,				// 绘制位置的 x 坐标
	int dstY,				// 绘制位置的 y 坐标
	int dstWidth,			// 绘制的宽度
	int dstHeight,			// 绘制的高度
	IMAGE *pSrcImg,			// 要绘制的 IMAGE 对象指针
	int srcX,				// 绘制内容在 IMAGE 对象中的左上角 x 坐标
	int srcY,				// 绘制内容在 IMAGE 对象中的左上角 y 坐标
	DWORD dwRop = SRCCOPY	// 三元光栅操作码
);

如果要实现简单的贴图只需要写putimage(0,0,&img);即在坐标(0,0)的位置绘制img图像,结合下文更清晰。

loadimage 加载图像

​ loadimage函数

loadimage(IMAGE* img,URL);//IMAGE是一种图像对象

其中,IMAGE是一种图像对象,可以参考IMAGE,URL是想要贴上的图片的相对位置,注意将图片放到源文件的路径下,如下代码中,"./Source/1.jpg"就是源文件同路径下的Source文件夹下的文件名叫做1.jpg的图片。

代码实例:

int main()
{
	initgraph(700, 600);
	int a = 1;
	IMAGE img;
	loadimage(&img, "./Source/1.jpg");
	putimage(0, 0, &img);
	while (1);
	closegraph();
	return 0;
}

效果如下:

image-20240808225522810

但是使用上述方法贴图效果无法做到合适窗口的尺寸,因此有下面的方法来进行缩放

loadimage(IMAGE* img,URL,int width,int height);

代码实例(将上面的代码中的loading函数增加两个参数即可,其余不变)

int main()
{
	initgraph(700, 600);
	int a = 1;
	IMAGE img;
	loadimage(&img, "./Source/1.jpg"700600);
	putimage(0, 0, &img);
	while (1);
	closegraph();
	return 0;
}

效果如下:

image-20240808225449772

4.2 透明贴图

  • 通过图像的二进制运算达到去背景的效果

  • 认识素材

    • 掩码图
    • 背景图
  • 三元光栅操作码(仅介绍用得上的其中两个,其余可以参考putimage和Ternary raster operations)

    • SRCAND 目标图像 = 目标图像 AND 源图像 贴掩码图
    • SRCPAINT 目标图像 = 目标图像 OR 源图像 贴背景图
  • 实例:

    int main()
    {
    	initgraph(800, 600);
    	int a = 1;
    	IMAGE img;
    	loadimage(&img, "./Source/1.jpg",1000,600);
    	putimage(0, 0, &img);
    
    	IMAGE pic[2];//创建一个IMAGE类型的数组
    	loadimage(&pic[0], "./Source/掩码图.png",400,400);
    	loadimage(&pic[1], "./Source/背景图.png", 400, 400);
    	putimage(150, 50, &pic[0],SRCAND);    //先贴掩码图
    	putimage(150, 50, &pic[1],SRCPAINT);  //再贴背景图
    
    	while (1);
    	closegraph();
    	return 0;
    }
    

    掩码图和背景图的制作等相关内容可以见

4.3双缓冲贴图

BeginBatchDraw 开始双缓冲

BeginBatchDraw函数

void BeginBatchDraw();

在一个图形化的物体移动过程中,如果直接打印,会出现明显的闪烁,如以下代码(可以实现一个圆从左到右的移动):

#include <graphics.h>

int main()
{
	initgraph(640,480);
	setlinecolor(WHITE);
	setfillcolor(RED);

	for(int i=50; i<600; i++)
	{
		cleardevice();
		circle(i, 100, 40);
		floodfill(i, 100, WHITE);
		Sleep(10);
	}
	closegraph();
}

要解决这个问题就可以使用双缓冲贴图,简单来说,开始双缓冲后,绘画操作会暂时不输出到绘画窗口上,知道执行FlusBatchDraw函数或EndBatchDraw函数才将之前的绘图输出,这两个函数见下文。

EndBatchDraw 结束双缓冲

EndBatchDraw函数

void EndBatchDraw();

当需要结束双缓存贴图并执行指定区域内未完成的绘制任务时,可参照以下:

void EndBatchDraw(
	int left,	//指定区域左边的x坐标
	int top,	//指定区域上边的y左边
	int right,	//指定区域右边的x坐标
	int bottom	//指定区域下边的y坐标
);
FlushBatchDraw 显示一帧

FlushBatchDraw函数

void FlushBatchDraw();

当需要执行指定区域内未完成的绘制任务时,可参考以下:

void FlushBatchDraw(
	int left,	//指定区域左边的x坐标
	int top,	//指定区域上边的y左边
	int right,	//指定区域右边的x坐标
	int bottom	//指定区域下边的y坐标
);

使用以上的三个函数再将上面的圆的移动的代码进行优化,如下:

#include <graphics.h>

int main()
{
	initgraph(640,480);
	BeginBatchDraw();				//开始双缓冲贴图

	setlinecolor(WHITE);
	setfillcolor(RED);

	for(int i=50; i<600; i++)
	{
		cleardevice();
		circle(i, 100, 40);
		floodfill(i, 100, WHITE);
		FlushBatchDraw();			//绘画出当前帧的图案
		Sleep(10);
	}

	EndBatchDraw();					//双缓冲贴图结束
	closegraph();
}

5、实现EasyX按键件交互功能

阻塞按键交互

简单理解就是在程序运行过程中有输入等交互环节的,会在中途暂停程序直到输入完成互动再继续

比如在一个小程序中有一个可以通过上下左右控制运动的小球,按下→键,小球向右动了一下停下,等待下面的指令,直到再按下一个按键才继续,这就是一个阻塞。

非阻塞按键交互

简单理解是在一个程序中按键输入等交互动作不中断程序的运行

我们可以使用conic.h头文件下的getch()函数来读取键盘的内容,getch()函数(详情可见getch() 函数的简单使用)

通过使用getch()和EasyX再加上打印图形的配合使用,可以达到一个通过键盘输入值控制窗口物体移动的效果。除了使用getch()函数,还可以使用Win 32 API下的GetAsyncKeyState函数来获取键盘键值达到键盘控制的效果,详情可以参考贪吃蛇小游戏中二、10下的内容。

6、在EasyX中进行鼠标操作

ExMessage 保存鼠标信息

ExMessage结构体

ExMessage是一个结构体,用来保存鼠标信息,定义如下:

struct ExMessage
{
	USHORT message;					// 消息标识
	union
	{
		// 鼠标消息的数据
		struct
		{
			bool ctrl		:1;		// Ctrl 键是否按下
			bool shift		:1;		// Shift 键是否按下
			bool lbutton	:1;		// 鼠标左键是否按下
			bool mbutton	:1;		// 鼠标中键是否按下
			bool rbutton	:1;		// 鼠标右键
			short x;				// 鼠标的 x 坐标
			short y;				// 鼠标的 y 坐标
			short wheel;			// 鼠标滚轮滚动值,为 120 的倍数
		};

		// 按键消息的数据
		struct
		{
			BYTE vkcode;			// 按键的虚拟键码
			BYTE scancode;			// 按键的扫描码(依赖于 OEM)
			bool extended	:1;		// 按键是否是扩展键
			bool prevdown	:1;		// 按键的前一个状态是否按下
		};

		// 字符消息的数据
		TCHAR ch;

		// 窗口消息的数据
		struct
		{
			WPARAM wParam;
			LPARAM lParam;
		};
	};
};

PeekMessage 获取鼠标信息

peekmessage函数

bool peekmessage(ExMessage *msg, BYTE filter = -1, bool removemsg = true);
  • msg是指向ExMessage的指针,用来保存获取到的信息

  • filter指定获取的信息范围,默认-1获取所有类别的消息,还可以用以下值:

    标志描述
    EX_MOUSE鼠标消息。
    EX_KEY按键消息。
    EX_CHAR字符消息。
    EX_WINDOW窗口消息。
  • removemsg:在peekmessage处理完消息后,是否将其从消息队列中移除

如果获取到了消息,则返回true,否则返回false

案例:

#include <graphics.h>
int main()
{
	initgraph(800, 800);
	ExMessage msg;
	while (1) {
		while (peekmessage(&msg)) {
			switch (msg.message) {
			case WM_LBUTTONDOWN: {
				circle(msg.x, msg.y, 10);
				break;
			}
				//按下左键,在鼠标按下的位置画圆
			case WM_RBUTTONDOWN: {
				rectangle(msg.x - 5, msg.y - 5, msg.x + 5, msg.y + 5);
				break;
				//按下右键,在鼠标按下的位置画方
			}
			}
		}
	}
	return 0;
}

OW | 窗口消息。 |

  • removemsg:在peekmessage处理完消息后,是否将其从消息队列中移除

如果获取到了消息,则返回true,否则返回false

案例:

#include <graphics.h>
int main()
{
	initgraph(800, 800);
	ExMessage msg;
	while (1) {
		while (peekmessage(&msg)) {
			switch (msg.message) {
			case WM_LBUTTONDOWN: {
				circle(msg.x, msg.y, 10);
				break;
			}
				//按下左键,在鼠标按下的位置画圆
			case WM_RBUTTONDOWN: {
				rectangle(msg.x - 5, msg.y - 5, msg.x + 5, msg.y + 5);
				break;
				//按下右键,在鼠标按下的位置画方
			}
			}
		}
	}
	return 0;
}

http://www.niftyadmin.cn/n/5863440.html

相关文章

go 环境准备

配置路径&#xff1a; GOROOT&#xff1a;D:\GoGOPATH&#xff1a;go的工作目录 D:\workspacego 验证版本&#xff1a;go version 配置第三方仓库&#xff1a; GO111MODULE&#xff1a;开启mod模式GOPROXY&#xff1a;go语言三方库地址GOSUMDB&#xff1a;go语言软件包的M…

【ORB-SLAM3】鲁棒核函数的阈值设置

问题背景 阈值 δ \delta δ 是 Huber 鲁棒核函数的重要参数。首先给出结论&#xff0c;在ORB-SLAM系列中&#xff0c;该阈值选取的原则为&#xff1a; 单目情况下&#xff0c;根据95%置信水平下两自由度卡方检验的临界值&#xff0c; δ \delta δ 设置为 5.991 \sqrt{5.9…

Qt中QRadioButton的样式设置

在 Qt 中&#xff0c;可以使用 Qt 样式表&#xff08;QSS&#xff09; 来自定义 QRadioButton 的外观。样式表类似于 CSS&#xff0c;允许你设置控件的颜色、字体、边框、背景等属性。 以下是如何为 QRadioButton 设置样式表的详细说明和示例。 1. 基本样式设置 你可以通过 s…

基于SpringBoot的线上汽车租赁系统的设计与实现(源码+SQL脚本+LW+部署讲解等)

专注于大学生项目实战开发,讲解,毕业答疑辅导&#xff0c;欢迎高校老师/同行前辈交流合作✌。 技术范围&#xff1a;SpringBoot、Vue、SSM、HLMT、小程序、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容&#xff1a;…

React - ajax 配置代理

React 本身只关注于界面&#xff0c;并不包含发送 ajax 请求的代码&#xff1b;前端应用需要通过 ajax 请求与后台进行交互&#xff08;json 数据&#xff09;&#xff1b;React 应用中需要集成第三方 ajax 库&#xff08;或者自己封装&#xff09;。 方法一 在 package.json …

【JT/T 808协议】808 协议开发笔记 ② ( 终端注册 | 终端注册应答 | 字符编码转换网站 )

文章目录 一、消息头 数据1、消息头拼接2、消息 ID 字段3、消息体属性 字段4、终端手机号 字段5、终端流水号 字段 二、消息体 数据三、校验码计算四、最终计算结果五、终端注册应答1、分解终端应答数据2、终端应答 消息体 数据 六、字符编码转换网站 一、消息头 数据 1、消息头…

大模型安全问题详解(攻击技术、红队测试与安全漏洞)

文章目录 大模型攻击技术提示注入攻击&#xff08;Prompt Injection&#xff09;数据投毒攻击&#xff08;Data Poisoning&#xff09;模型克隆攻击&#xff08;Model Cloning&#xff09;拒绝服务攻击&#xff08;DoS&#xff09;和拒绝钱包攻击&#xff08;DoW&#xff09;插…

OpenHarmony构建系统-GN与子系统、部件、模块理论与实践

理论 OpenHarmony源码体系 OpenHarmony的源码架构基于模块化设计&#xff0c;为了方便系统的功能的增加和裁剪&#xff0c;设计了基于GN构建的模块系统。整个模块可从大到小划分为产品(product)、领域/子系统集(domain)、子系统(sub system)、部件(component)、模块/组件(modu…