C/C++图形化编程——EasyX使用教程

LeoKing0218 2024-06-21 10:05:02 阅读 88

主打一个清晰易懂教程:

原版移步:EasyX完整版基础教程【语雀文档】

目录

1.创建图形化窗口

a. 包含头文件

ⅰ. 两种头文件:

ⅱ. 几种窗口函数

1. 打开:initgraph(int x,int y,int style);

2. 关闭窗口函数:closegraph()关闭图形库(窗口有打开就有关闭)

3. 清空绘图函数:cleardevice()

ⅲ. 窗口坐标的知识:

ⅳ. 绘制窗口例子:

2. 基本绘图函数

a. 设置填充样式函数

ⅰ. 以画圆为例

可视化例子:

b. 设置图形样式函数

ⅰ. 代码实现示例:

c. 设置颜色函数

d. 文字绘制函数

3. 图像处理函数

4. 鼠标消息函数

a. 接收鼠标消息代码示例1

b. 接收鼠标消息代码示例2

5. 鼠标画线操作

6. 音乐播放

a. 播放音乐的函数

7. 阻塞式和非阻塞式

a. 阻塞式(Blocking):

b. 非阻塞式(Non-blocking):

c. 相关函数


1.创建图形化窗口

a. 包含头文件

ⅰ. 两种头文件:

graphics.h(包含已经淘汰的函数)

easy.h(只包含最新的)

ⅱ. 几种窗口函数:

1. 打开:initgraph(int x,int y,int style);

initgraph函数的参数的解释:

x:窗口宽度,单位是像素y:窗口高度,单位是像素style:窗口样式,以下是常见窗口样式:

DEFAULT:默认样式,创建一个可关闭的窗口。NOCLOSE:创建一个无法关闭的窗口,没有关闭按钮。NOMINIMIZE:创建一个无法最小化的窗口,没有最小化按钮。NOMAXIMIZE:创建一个无法最大化的窗口,没有最大化按钮。NORESIZE:创建一个无法改变大小的窗口,没有调整大小的边框。NOCAPTION:创建一个没有标题栏的窗口,没有标题栏和边框。CUSTOMSTYLE:自定义样式,用户可以通过指定参数实现特定需求的窗口样式。

设置窗口的例子:

...#include<graphics.h>int main(){initgraph(200, 200,NOCLOSE);//设置宽度为200,高度为200,NOCLOSE指无法关闭的窗口//以下语句暂不做解释 getchar();closegraph();return 0;}...

运行截图:可以看到该窗口是无法关闭的。

2. 关闭窗口函数:closegraph()关闭图形库(窗口有打开就有关闭)
3. 清空绘图函数:cleardevice()

ⅲ. 窗口坐标的知识:

坐标系长这个样子:

确定一个矩形框,只需要给出左上角和右下角的坐标即可

ⅳ. 绘制窗口例子:

#include<stdio.h>//1.包含图形库头文件,就能使用图形库函数#include<graphics.h>int main(){initgraph(640, 480);//2.初始化图形库,确定矩形窗口大小 line(100, 100, 200, 200);//3.画图 (此处画的是由(100,100)和(200,200)这两个点构成的连线) getchar();//4.暂停,防止窗口闪退closegraph();//5.关闭图形库(窗口有打开就有关闭)return 0;} 运行截图:

2. 基本绘图函数

简介:利用不同的函数绘制各种图形

a. 设置填充样式函数

绘图函数从填充样式分类可分为无填充、有边框填充、无边框三种。

ⅰ. 以画圆为例

circle():无填充 fillcircle():有边框填充 solidcircle():无边框填充
可视化例子:

(无边框填充)↑ ↑(有边框填充)

b. 设置图形样式函数

按所画的图形形状分类,有以下常用几类图形函数
circle()画圆 elipse()画椭圆 pie()画扇形 polygon()画多边形 rectangle画矩形 roundrect画圆角矩形 line画线 putpixel画点

ⅰ. 代码实现示例:

问:如何画?怎么写代码?

答:以画圆为例:

根据数学知识,确定一个圆只需圆心坐标+半径即可:

所以输入的三个参数依次为:

圆心的x坐标(x)圆心的y坐标(y)圆的半径(radius)

这里以圆心坐标(500,500),半径为200,为例子。

运行结果截图:

c. 设置颜色函数

设置 填充颜色函数: setfillcolor(颜色)设置 线条颜色函数: setlinecolor(颜色)设置 线条样式函数: setlinestyle(线型, 宽度)

常见的线条样式:

PS_SOLID:实线型PS_DASH:短划线型PS_DOT:点线型PS_DASHDOT:短划线加点线型PS_DASHDOTDOT:短划线加两个点线型PS_NULL:不画线,只移动当前点

setlinestyle(PS_SOLID,5);//设置线条样式:实线,宽度5setfillcolor(YELLOW);//设置填充颜色:黄色setlinecolor(BLUE);//设置线条颜色:蓝色

 4.设置背景颜色函数:setbkcolor(颜色);

注意:设置背景颜色通常需要两步,简称两部曲

initgragh(200,200);设置窗口大小setbkcolor(WHITE);//第一步:设置颜色cleardevice();//第二步:清屏

注:该文章中,为了表达简洁,一般不展示头文件等其他内容,只展示重要代码

运行截图:

d. 文字绘制函数

输出字符串函数:outtextxy(int x, int y, LPCTSTR str);

作用:在指定位置输出字符串

参数解释:(x,y)是坐标,str决定文本内容

例子:outtextxy(50,50,'a');//在(50,50)位置输出字符a

若改为outtextxy(50,50,"asarfewf");即把单个字符换为字符串,可能出现错误,以下是解决方案:

在字符串前面加上大写 L用TEXT( )或_T( )把字符串括住,原理同上不需要添加任何代码,进项目→属性→配置属性→常规→项目默认值→字符集→改为多字节字符集(推荐使用这个方式)

2.设置文字样式函数:settextstyle(int font, int direction, int charsize)

参数解释:

font: 这个参数是一个整数,代表要使用的 字体类型direction: 这个参数是一个整数,用于指定 文本的方向

通常,0 表示水平方向(HORIZ_DIR),1 表示垂直方向(VERT_DIR)

     3.charsize: 这个参数是一个字符串,用于指定字体的大小

settextstyle(50,0,20)//表示字体类型为编号为50,方向水平,大小20

3.设置文字背景模式:setbkmode(int mode);

参数解释:

参数mode可以是以下两个值之一:

TRANSPARENT:表示文本绘制时背景是透明的,即文本绘制时不修改背景。这意味着文本绘制的地方保持原来的背景,不会被覆盖。 OPAQUE:表示文本绘制时背景是不透明的,即文本绘制时会先用当前背景色填充背景区域,然后在其上绘制文本。

/*...*/setbkmode(TRANSPARENT);//设置文字背景为透明outtextxy(50,50,"dsadd");//在(50,50)位置输出dsadd字样/*...*/

 4.设置文字颜色函数:settextcolor(COLORREF color);

通常使用 RGB(r, g, b) 宏来创建颜色值,其中 r、g、b 分别代表红色、绿色和蓝色的分量。

例如,如果你想要将文本颜色设置为红色,可以这样调用settextcolor() 函数:

settextcolor(RGB(255, 0, 0)); // 红色

RGB配置指颜色调色板中三原色对应的数值:

5.获取文本宽和高函数textheight(LPCTSTR str) textwidth(LPCTSTR str)

char arr[]= "我是字符串";textheight(arr);//获取字符串宽度textwidth(arr);//获取字符串高度

3. 图像处理函数

在使用图像之前,需要定义一个对象,然后把图片加载进变量才能使用。

在使用图片的时候需要EasyX提供给我们的类型:IMAGE ,如IMAGE img; 图像加载函数:loadimage(IMAGE *img, LPCTSTR filename, int width, int height, BOOL shared = FALSE);

int loadimage( IMAGE *img, // 指向 IMAGE 结构体的指针,用于存储加载的图像数据 LPCTSTR filename, // 指定图片文件的路径 int width, // 指定图片的宽度 int height, // 指定图片的高度 BOOL shared = FALSE // 指定是否加载为共享图像,默认为 FALSE);

2.图像输出函数:BOOL putimage( HDC hdcDest, int xDest, int yDest, constvoid *img, DWORD rop = SRCCOPY )

BOOL putimage( HDC hdcDest, // 目标设备上下文句柄 int xDest, // 目标矩形区域左上角的 x 坐标 int yDest, // 目标矩形区域左上角的 y 坐标 const void *img, // 要输出的图像数据 DWORD rop = SRCCOPY // 光栅操作码,指定如何将图像数据输出到目标设备上下文);

加载并输出一张图片示例:

//实例化一个img对象IMAGE img;//加载图片//相对路径:"./"表示当前文件夹,"../"表示当前文件夹的上一级文件夹,比如:./图片名.png //绝对路径:比如:D:\\biancheng\\Project31\\图片名.png,得用双反斜杠loadimage(&img,"./图片.png");//以相对路径加载一张图片//loadimage(&img,"D:\\biancheng\\Project31\\图片名.png");以绝对路径加载一张图片putimage(0,0,&img);//从窗口的(0,0)位置输出图片

4. 鼠标消息函数

//包含在easyx.h头文件中// Message Structurestruct ExMessage{USHORT message;// 用于区分鼠标消息union{// Data of the mouse messagestruct{bool ctrl:1;// 指示CTRL键是否按下bool shift:1;// 指示SHIFT键是否按下bool lbutton:1;// 指示鼠标左键是否按下bool mbutton:1;// 指示鼠标中键是否按下bool rbutton:1;// 指示鼠标右键是否按下short x;// 鼠标光标的y的坐标short y;// 鼠标光标的x的坐标short wheel;// The distance the wheel is rotated, expressed in multiples or divisions of 120};}; 常见鼠标消息宏定义:

若想了解更多的关于鼠标消息的定义,可以鼠标右键点击该定义→转到定义,即可。

#define WM_MOUSEMOVE //鼠标移动消息 #define WM_LBUTTONDOWN //鼠标左键按下消息 #define WM_LBUTTONUP //鼠标左键弹起消息 #define WM_LBUTTONDBLCLK // 鼠标左键双击消息 #define WM_RBUTTONDOWN //鼠标左键按下消息 #define WM_RBUTTONUP //鼠标左键弹起消息 #define WM_RBUTTONDBLCLK //鼠标右键双击消息 #define WM_MBUTTONDOWN //鼠标中键按下消息 #define WM_MBUTTONUP //鼠标中键弹起消息 #define WM_MBUTTONDBLCLK //鼠标中键双击消息

一般记住以下四种就行了,其他不会了可以速查:

WM_MOUSEMOVE: m.message== WM_MOUSEMOVE; //鼠标移动WM_LBUTTONDOWN: 左键按下WM_RBUTTONDOWN: 右键按下WM_LBUTTONUP: 左键弹起

a. 接收鼠标消息代码示例1

程序功能介绍:若点击左键,会在控制台打印出“左键按键......”;若点击右键,会在控制台打印出“右键按键......”

#include<stdio.h>#include<easyx.h>#include<stdbool.h>int main() { ExMessage m; // 定义一个ExMessage类型的变量m,用于存储消息 initgraph(640, 480, 1); // 初始化图形窗口,设置窗口大小为640x480像素,1表示使用默认模式 while (1) // 进入无限循环 { peekmessage(&m, EM_MOUSE); // 检查是否有鼠标消息,将消息存储在m中 if (m.message == WM_LBUTTONDOWN) // 如果检测到鼠标左键按下消息 { printf("左键按键......\n"); // 输出提示信息:左键按键 } else if (m.message == WM_RBUTTONDOWN) // 如果检测到鼠标右键按下消息 { printf("右键按键......\n"); // 输出提示信息:右键按键 } } return 0;}

b. 接收鼠标消息代码示例2

程序介绍:这个程序不显示控制台,若在淡蓝色窗口中点击左键,会立即在鼠标点击位置绘制出半径为10的红色的圆;若在窗口中点击右键,会立即在鼠标点击位置绘制出半径为10的黑色的圆;

在C++的easyx库中,当使用`flag = 1`来设置全屏模式时,控制台不会显示。全屏模式下,窗口会占据整个屏幕,控制台将不可见。

以下是一些常见的flag参数取值及其含义: flag = 0 : 普通窗口模式,窗口有标题栏和边框。 flag = 1 : 全屏模式,窗口占据整个屏幕,没有标题栏和边框。 flag = 2 : 窗口模式,窗口有标题栏但没有边框。 flag = 3 : 最大化窗口模式,窗口占据整个屏幕但有标题栏。

#include<easyx.h>#include<stdbool.h>int main() { ExMessage m; // 定义一个ExMessage类型的变量m,用于存储消息 initgraph(640, 480); // 初始化图形窗口,设置窗口大小为640x480像素,1表示使用默认模式 setbkcolor(LIGHTBLUE); // 设置背景颜色为白色cleardevice(); // 清空屏幕 while (1) // 进入无限循环 { peekmessage(&m, EM_MOUSE); // 检查是否有鼠标消息,将消息存储在m中 if (m.message == WM_LBUTTONDOWN) // 如果检测到鼠标左键按下消息 { setfillcolor(RED); // 设置填充颜色为红色 solidcircle(m.x, m.y, 10); // 绘制一个实心圆,圆心坐标为m.x, m.y,半径为10 } else if (m.message == WM_RBUTTONDOWN) // 如果检测到鼠标右键按下消息 { setfillcolor(BLACK);// 设置填充颜色为黑色 solidcircle(m.x, m.y, 10);// 绘制一个实心圆,圆心坐标为m.x, m.y,半径为10 } if (m.message == WM_MOUSEMOVE) { line(0, 0, m.x, m.y); } } closegraph(); return 0;}

知识拓展:hook(钩子)是什么?

编程中的“hook”指的是一种机制,允许你拦截和修改系统或应用程序的行为。通过使用钩子,开发人员可以在程序执行流程的特定点注入自己的代码,以执行额外的操作、改变程序的行为或响应事件。钩子通常以函数指针、回调函数、事件监听器或框架或库提供的特定接口的形式实现。在软件开发中,钩子经常用于事件驱动编程、图形用户界面、Web开发(例如React钩子)以及其他需要定制和扩展性的场景中。

比如:自动鼠标点击软件通常会使用钩子来实现自动化点击功能。通过钩子,这类软件可以拦截鼠标事件并模拟鼠标点击操作,从而实现自动点击的功能。钩子在这种情况下被用来监视和干预鼠标事件,以便程序能够自动执行点击操作。

5. 鼠标画线操作

画图功能:(定时器逻辑) 画图过程可拆解为两个步骤:鼠标点击+鼠标拖动→画线停止画线的逻辑:即鼠标停止拖动(不松开),并且再拖动可以继续画

做一个画图工具,要求包含以上逻辑示例:

#include<iostream> // 引入基本输入输出流#include<graphics.h> // 引入图形库头文件(可能是指EasyX或其他图形库)#include<stdio.h> // 引入标准输入输出库#include<stdlib.h> // 引入标准库,用于内存分配等#include<conio.h> // 引入控制台输入输出库#include<easyx.h> // 引入EasyX图形库头文件#include<stdbool.h> // 引入标准布尔库#include<assert.h>//包含assert.h以使用assert宏struct Point // 定义一个结构体,用于存储点的坐标{ int x; // 横坐标 int y; // 纵坐标};void setPoint(struct Point* point, int x, int y) // 设置点的坐标函数{ point->x = x; // 设置横坐标 point->y = y; // 设置纵坐标}struct LineTool // 定义一个画线工具的结构体{ int size; // 线的大小(粗细) COLORREF color; // 线的颜色 bool isDown; // 标记鼠标是否按下 Point begin; // 起始点坐标};// 创建画线工具的函数struct LineTool* creatLineTool(int size, COLORREF color){ struct LineTool* pLine = (struct LineTool*)malloc(sizeof(struct LineTool)); // 分配内存 assert(pLine); // 确保内存分配成功 pLine->size = size; // 设置线的大小 pLine->color = color; // 设置线的颜色 pLine->isDown = false; // 初始化鼠标未按下 return pLine; // 返回工具指针}// 设置线的颜色void setLineColor(struct LineTool* pLine, COLORREF color){ pLine->color = color;}// 设置线的粗细void setLineSize(struct LineTool* pLine, int size){ pLine->size = size;}// 根据鼠标事件绘制线条的函数void drawLine(struct LineTool* pLine, ExMessage m){ // 鼠标左键按下,记录位置 if (m.message == WM_LBUTTONDOWN) { pLine->isDown = true; pLine->begin.x = m.x; pLine->begin.y = m.y; } // 鼠标左键弹起 if (m.message == WM_LBUTTONUP) { pLine->isDown = false; } // 鼠标移动且左键按下,绘制线条 if (pLine->isDown == true && m.message == WM_MOUSEMOVE) { setlinestyle(PS_ENDCAP_ROUND, pLine->size); // 设置线条样式和粗细 setlinecolor(pLine->color); // 设置线条颜色 line(pLine->begin.x, pLine->begin.y, m.x, m.y); // 绘制线条 // 更新起始点坐标,以便连续绘制 pLine->begin.x = m.x; pLine->begin.y = m.y; } // 鼠标右键按下,清空画布 if (m.message == WM_RBUTTONDOWN) { setbkcolor(WHITE); // 设置背景色为白色 cleardevice(); // 清空画布 }}int main() { initgraph(800, 800); // 初始化图形窗口大小为800x800 setbkcolor(WHITE); // 设置背景色为白色 struct LineTool* pLine = creatLineTool(5, BLACK); // 创建一个线条工具,线条为黑色,粗细为5 ExMessage m; // 定义一个消息结构体,用于接收鼠标消息 cleardevice(); // 清空画布 while (1) // 无限循环 { peekmessage(&m, EM_MOUSE); // 获取鼠标消息 drawLine(pLine, m); // 根据鼠标消息绘制线条 if (_kbhit())//判断是否存在按键,存在按键则按键操作 返回非零值表示存在 { char userKey = _getch();//阻塞函数 switch (userKey) { case'+': //setLineSize(pLine,pLine->size++); pLine->size++; break; case'-': break; case'\r': exit(0); break; } } closegraph(); // 关闭图形窗口 return 0;}

6. 音乐播放

● #include<windows.h> //如果包含这个graphics.h,windows.h可以不包含● 包含多媒体库:#include<mmsystem.h> ● 包含静态库资源:#pragma comment("lib","winmm.lib")

a. 播放音乐的函数

mciSendString("指令",0,0,0);(只支持MP3)

指令:open:打开 pause:暂停 resume:继续 close:关闭

play:播放:repeat /wait方式

函数原型:

// 函数原型DWORD mciSendString( LPCTSTR lpszCommand, // 指向以 NULL 结尾的字符串,包含要发送的命令 LPTSTR lpszReturnString, // 接收命令执行的结果的缓冲区 UINT cchReturn, // 指定 lpszReturnString 缓冲区的大小 HANDLE hwndCallback // 指定用于接收通知消息的窗口句柄,通常为 NULL);

mciSendString函数的第一个参数是LPCWSTR类型,它是一个指向常量宽字符的指针

示例用法:做一个简单音乐播放程序

#include <Windows.h> // 包含 Windows.h 头文件,提供 Windows 平台下的 API 支持#include <stdio.h> // 包含标准输入输出库头文件#include <mmsystem.h> // 包含多媒体系统 API 头文件#pragma comment(lib,"winmm.lib") // 指定链接到 winmm.lib 库void makeMenu() // 定义函数 makeMenu,用于打印菜单{ printf("-------[音乐播放]-------\n"); // 打印菜单标题 printf("\t\t0.退出\n"); // 打印退出选项 printf("\t\t1.播放音乐\n"); // 打印播放音乐选项 printf("\t\t2.暂停音乐\n"); // 打印暂停音乐选项 printf("\t\t3.继续音乐\n"); // 打印继续音乐选项 printf("\t\t4.关闭音乐\n"); // 打印关闭音乐选项 printf("-------------------\n"); // 打印分隔线}void keyDown() // 定义函数 keyDown,用于处理用户输入并执行相应操作{ int userkey = 0; // 定义变量 userkey 存储用户输入 scanf_s("%d", &userkey); // 读取用户输入 switch (userkey) // 根据用户输入执行相应操作 { case 0: // 用户输入为 0,退出程序 exit(0); case 1: // 用户输入为 1,播放音乐 mciSendString(L"play ./music/1.mp3 repeat", NULL, 0, NULL); // 播放音乐文件,并设置为循环播放 break; case 2: // 用户输入为 2,暂停音乐 mciSendString(L"pause ./music/1.mp3 ", NULL, 0, NULL); // 暂停音乐播放 break; case 3: // 用户输入为 3,继续音乐 mciSendString(L"resume ./music/1.mp3 ", NULL, 0, NULL); // 继续音乐播放 break; case 4: // 用户输入为 4,关闭音乐 mciSendString(L"close ./music/1.mp3 ", NULL, 0, NULL); // 关闭音乐文件 break; }}int main() // 主函数{ mciSendString(L"open ./music/1.mp3", NULL, 0, NULL); // 打开音乐文件 while (1) // 进入主循环,持续显示菜单并处理用户输入 { makeMenu(); // 显示菜单 keyDown(); // 处理用户输入 }}

7. 阻塞式和非阻塞式

a. 阻塞式(Blocking):

在阻塞式事件处理中,程序会一直等待某个事件的发生,直到该事件发生后才会继续执行后续代码。例如,在游戏中,如果采用阻塞式事件处理,程序会等待玩家的按键输入,直到玩家按下某个键后才会响应并继续执行游戏逻辑。在 EasyX 中,常见的阻塞式事件处理函数是 GetMouseMsg() 和 GetKey(),它们会一直等待鼠标消息和键盘消息的到来。

b. 非阻塞式(Non-blocking):

在非阻塞式事件处理中,程序会定期地轮询或检查事件是否发生,如果发生了则立即处理,如果没有则继续执行后续代码。例如,在游戏中,如果采用非阻塞式事件处理,程序会定期检查玩家是否按下了某个键,如果按下了则立即响应,如果没有则继续执行游戏逻辑。在 EasyX 中,可以通过定时器来实现非阻塞式事件处理,比如使用 SetTimer() 设置一个定时器,然后在定时器回调函数中处理事件。

c. 相关函数

1.使用 kbhit() 等待键盘输入:

while (!kbhit()) { // 等待键盘输入事件发生}

这段代码会使程序进入一个循环,直到键盘输入事件发生(用户按下键盘上的任意键)才会跳出循环继续执行后续代码。

2. 使用 GetMouseMsg() 等待鼠标消息:

MOUSEMSG m;while (!MouseHit()) { m = GetMouseMsg(); // 获取鼠标消息 // 处理鼠标消息}

这段代码会不断地获取鼠标消息,直到有鼠标消息到达才会跳出循环继续执行后续代码。

3.使用 GetKey() 等待键盘按键消息:

while (!kbhit()) { // 等待键盘按键消息发生}



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。