EasyX二三事

EasyX

EasyX Graphics Library 是针对 Visual C++ 的免费绘图库,支持 VC6.0 ~ VC2022,简单易用,学习成本极低,应用领域广泛。目前已有许多大学将 EasyX 应用在教学当中。

  1. EasyX其实是一个C++库,不是C库,这就像VC只有C++编译器,没有C编译器一样。

  2. EasyX最初发布于2009年,其底层是gdi,设计上和Windows API高度耦合,但在使用上基本不用了解太多的Windows API。EasyX是一个图形库,或者说只是一个绘图库,因为它相较于OpenGL以及其他的如SDL2的库而言只有一个优势——简单易用。它能让新人快速上手,了解以及学习绘图算法。

  3. 如果你是一位新人,那么EasyX对你最大的吸引力大概在于:只用学习少量内容,就能暂时摆脱烦人的黑框框程序,窥得一眼五彩斑斓的GUI世界。

  4. EasyX能干什么?EasyX可以绘图,这意味着它能实现一些图像处理功能,或者是一个游戏,一个数据分析软件,一个动画合成软件,等等等等,但需要明确的是,上述内容都不是单单一个EasyX就能完成的。

搭建EasyX的开发环境

  1. 由于与Windows API高度耦合,EasyX官方仅支持VC工具链,具体版本下至Visual C++ 6.0,上至Visual Studio 2022。(截至目前而言)

  2. 官方提供了一个安装程序来完成各个版本VC/VS上的一键式部署与卸载。(同时也提供了一个离线文档)

使用EasyX编写GUI程序的简单示例

  1. 引入EasyX库的头文件,旧版本的EasyX使用graphics.h(这也是你在网上能找到的大多数教程所用的头文件),但现在应该使用easyx.h。目前的graphics.h仅保留了若干已被easyx.h废弃的旧版功能。
#include <easyx.h>
  1. 初始化绘图窗口,创建一个指定大小(此处示例为640x480像素)的窗口。
initgraph(640, 480);
  1. 绘图,此处示例为绘制一个圆心为(200,200),半径为100的圆。
circle(200, 200, 100)
  1. 关闭绘图窗口
closegraph();
  1. 完整代码
#include <graphics.h>
#include <conio.h>
int main()
{
    initgraph(640, 480);
    circle(200, 200, 100);
    _getch();
    closegraph();
    return 0;
}
  1. 运行效果

v6xQHI.png


EasyX中的基本概念

EaysX中颜色的三种表示方式:

  1. 宏定义:EasyX内建了一些宏常量来表示颜色

    颜色
    BLACK0
    BLUE0xAA0000
    GREEN0x00AA00绿
    CYAN0xAAAA00
    RED0x0000AA
    MAGENTA0xAA00AA
    BROWN0x0055AA
    LIGHTGRAY0xAAAAAA浅灰
    DARKGRAY0x555555深灰
    LIGHTBLUE0xFF5555亮蓝
    LIGHTGREEN0x55FF55亮绿
    LIGHTCYAN0xFFFF55亮青
    LIGHTRED0x5555FF亮红
    LIGHTMAGENTA0xFF55FF亮紫
    YELLOW0x55FFFF
    WHITE0xFFFFFF
  2. 16进制:

    格式为0xbbggrr(bb=蓝,gg=绿,rr=红)

  3. RGB宏:用于将红、绿、蓝颜色分量合成RGB颜色。

    COLORREF RGB(
        BYTE byRed,        // 颜色的红色部分,取值范围:0~255,下同
        BYTE byGreen,    // 颜色的绿色部分
        BYTE byBlue        // 颜色的蓝色部分
    );
    
  4. HSLtoRGB,HSVtoRGB:用于将HSL/HSV颜色空间模型转至RGB。

坐标

  1. 物理坐标:描述设备的坐标体系,以设备左上角为原点,X轴向右为正,Y轴向下为负,度量单位为像素,不可缩放。

  2. 逻辑坐标:程序中用于绘图的坐标体系,以窗口左上角为原点,X轴向右为正,Y轴向下为正,度量单位为点。在默认情况下,逻辑坐标与物理坐标一一对应,一个逻辑点即为一个物理像素。

设备

  1. “设备”指的是绘图表面。(根据功能,可以粗略理解为画板,但是其实并不仅仅是画板)

  2. EasyX中有两种设备:默认的绘图窗口以及IMAGE对象,使用函数SetWorkingImag可更改当前用于绘图的设备,所以的绘图函数都将图形绘制在该设备上。


EasyX部分功能示例

只列出了我认为最有用的部分

清屏:cleardevice

void cleardevice();

设置当前设备绘图背景色:setbkcolor

void setbkcolor(COLORREF color);

设置当前设备图案填充和文字输出时的背景模式

void setbkmode(int mode);
mode参数的各个值说明
OPAQUE背景用当前背景色填充(默认)
TRANSPARENT背景透明

设置当前设备填充样式:setfillstyle

void setfillstyle(
    FILLSTYLE* pstyle
);
void setfillstyle(
    int style,
    long hatch = NULL,
    IMAGE* ppattern = NULL
);
void setfillstyle(
    BYTE* ppattern8x8
);
参数说明
pstyle指向填充样式 FILLSTYLE 的指针
style指定填充样式
hatch指定填充图案

具体内容请参照[官方文档](EasyX 文档 - setfillstyle)

设置当前设备画线样式:setlinestyle

void setlinestyle(
    const LINESTYLE* pstyle
);
void setlinestyle(
    int style,
    int thickness = 1,
    const DWORD *puserstyle = NULL,
    DWORD userstylecount = 0
);
参数说明
pstyle指向画线样式 LINESTYLE 的指针
style画线样式
thickness线的宽度(单位为像素)
puserstyle用户自定义样式数组
userstylecount用户自定义样式数组的元素数量。

具体内容请参照[官方文档](EasyX 文档 - setlinestyle)

设置当前设备多边形填充模式:setpolyfillmode

mode的各个值说明
ALTERNATE交替填充模式(默认值)
WINDING根据绘图方向填充的模式

详见[官方文档](EasyX 文档 - setpolyfillmode)


EasyX的部分函数文档索引

这里其实就是官方文档的内容,只是给大家引个路。

绘制图形

函数或数据类型描述
arc画椭圆弧。
circle画无填充的圆。
clearcircle清空圆形区域。
clearellipse清空椭圆区域。
clearpie清空扇形区域。
clearpolygon清空多边形区域。
clearrectangle清空矩形区域。
clearroundrect清空圆角矩形区域。
ellipse画无填充的椭圆。
fillcircle画有边框的填充圆。
fillellipse画有边框的填充椭圆。
fillpie画有边框的填充扇形。
fillpolygon画有边框的填充多边形。
fillrectangle画有边框的填充矩形。
fillroundrect画有边框的填充圆角矩形。
floodfill填充区域。
getheight获取绘图区的高度。
getpixel获取点的颜色。
getwidth获取绘图区的宽度。
line画直线。
pie画无填充的扇形。
polybezier画三次方贝塞尔曲线。
polyline画多条连续的线。
polygon画无填充的多边形。
putpixel画点。
rectangle画无填充的矩形。
roundrect画无填充的圆角矩形。
solidcircle画无边框的填充圆。
solidellipse画无边框的填充椭圆。
solidpie画无边框的填充扇形。
solidpolygon画无边框的填充多边形。
solidrectangle画无边框的填充矩形。
solidroundrect画无边框的填充圆角矩形。

文字输出

函数或数据类型描述
gettextcolor获取当前文字颜色。
gettextstyle获取当前文字样式。
LOGFONT文字样式的结构体。
outtextxy在指定位置输出字符串。
drawtext在指定区域内以指定格式输出字符串。
settextcolor设置当前文字颜色。
settextstyle设置当前文字样式。
textheight获取字符串实际占用的像素高度。
textwidth获取字符串实际占用的像素宽度。

图像处理

函数或数据类型描述
IMAGE保存图像的对象。
loadimage读取图片文件。
saveimage保存绘图内容至图片文件。
getimage从当前绘图设备中获取图像。
putimage在当前绘图设备上绘制指定图像。
GetWorkingImage获取指向当前绘图设备的指针。
rotateimage旋转 IMAGE 中的绘图内容。
SetWorkingImage设定当前绘图设备。
Resize调整指定绘图设备的尺寸。
GetImageBuffer获取绘图设备的显示缓冲区指针。
GetImageHDC获取绘图设备句柄。

消息处理

函数或数据类型描述
ExMessage消息结构体。
flushmessage清空消息缓冲区。
getmessage获取一个消息。如果当前消息缓冲区中没有,就一直等待。
peekmessage获取一个消息,并立即返回。

连续绘图

实际上貌似是启用了双缓冲,可以有效解决连续绘图时的闪烁问题,使用如下。

BeginBatchDraw();
// 绘制你的内容...
EndBatchDraw();

EndBatchDraw会将绘制的内容输出,使用FlushBatchDraw能达到同样效果。

获取窗口句柄

EasyX提供了GetHWnd函数以获得当前窗口的句柄,由此你可以使用Windows API对窗口进行进一步的操作,原型如下。

HWND GetHWnd();

输入对话框

EasyX提供了InputBox函数用于以对话框形式获取用户输入,原型如下。

bool InputBox(
    LPTSTR    pString,
    int        nMaxCount,
    LPCTSTR    pPrompt = NULL,
    LPCTSTR    pTitle = NULL,
    LPCTSTR    pDefault = NULL,
    int        width = 0,
    int        height = 0,
    bool    bHideCancelBtn = true
);

关于使用EasyX构建一个简单的游戏简述

  1. EasyX仅仅是一个绘图库,它只能完成图形的绘制以及鼠标信息的捕获任务,要构建一个完整的游戏,所需要的不仅仅是EasyX。

  2. VC/VS中提供了conio.h,能实现非阻塞式的键盘监听(非全局)。

  3. Windows API中的mmsystem.h(需要链接winmm.lib)提供了一套简单的音乐播放功能。

  4. 如果你的游戏中的对象是动态的(比如数量不确定的敌人),那么你需要用到堆内存分配,以及一些用于管理堆内存的数据结构。

  5. 我之前用EasyX写了一个游戏,有兴趣可以看看,但是代码很乱,因为我懒。

参考资料

EasyX 文档 - 基本说明

/****************************************************** * EasyX Library for C++ (Ver:20151015(beta)) * http://www.easyx.cn * * graphics.h * 基于 EasyX.h,实现在 VC 下实现简单绘图。 * 同时,为了兼容 Turbo C/C++ 和 Borland C/C++ 等一系 * 列开发环境中的 BGI 绘图库函数,做了相应扩展。 ******************************************************/ #pragma once #include <easyx.h> // 兼容 initgraph 绘图模式的宏定义(无实际意义) #define DETECT 0 #define VGA 0 #define VGALO 0 #define VGAMED 0 #define VGAHI 0 #define CGA 0 #define CGAC0 0 #define CGAC1 0 #define CGAC2 0 #define CGAC3 0 #define CGAHI 0 #define EGA 0 #define EGALO 0 #define EGAHI 0 // BGI 格式的初始化图形设备,默认 640 x 480 HWND initgraph(int* gdriver, int* gmode, char* path); void bar(int left, int top, int right, int bottom); // 画无边框填充矩形 void bar3d(int left, int top, int right, int bottom, int depth, bool topflag); // 画有边框三维填充矩形 void drawpoly(int numpoints, const int *polypoints); // 画多边形 void fillpoly(int numpoints, const int *polypoints); // 画填充的多边形 int getmaxx(); // 获取最大的宽度值 int getmaxy(); // 获取最大的高度值 COLORREF getcolor(); // 获取当前绘图前景色 void setcolor(COLORREF color); // 设置当前绘图前景色 void setwritemode(int mode); // 设置前景的二元光栅操作模式 /////////////////////////////////////////////////////////////////////////////////// // 以下函数仅为兼容早期 EasyX 的接口,不建议使用。请使用相关新函数替换。 // #if _MSC_VER > 1200 #define _EASYX_DEPRECATE(_NewFunc) __declspec(deprecated("This function is deprecated. Instead, use this new function: " #_NewFunc ". See http://www.easyx.cn/help?" #_NewFunc " for details.")) #define _EASYX_DEPRECATE_OVERLOAD(_Func) __declspec(deprecated("This overload is deprecated. See http://www.easyx.cn/help?" #_Func " for details.")) #else #define _EASYX_DEPRECATE(_NewFunc) #define _EASYX_DEPRECATE_OVERLOAD(_Func) #endif // 设置当前字体样式(该函数已不再使用,请使用 settextstyle 代替) // nHeight: 字符的平均高度; // nWidth: 字符的平均宽度(0 表示自适应); // lpszFace: 字体名称; // nEscapement: 字符串的书写角度(单位 0.1 度); // nOrientation: 每个字符的书写角度(单位 0.1 度); // nWeight: 字符的笔画粗细(0 表示默认粗细); // bItalic: 是否斜体; // bUnderline: 是否下划线; // bStrikeOut: 是否删除线; // fbCharSet: 指定字符集; // fbOutPrecision: 指定文字的输出精度; // fbClipPrecision: 指定文字的剪辑精度; // fbQuality: 指定文字的输出质量; // fbPitchAndFamily: 指定以常规方式描述字体的字体系列。 _EASYX_DEPRECATE(settextstyle) void setfont(int nHeight, int nWidth, LPCTSTR lpszFace); _EASYX_DEPRECATE(settextstyle) void setfont(int nHeight, int nWidth, LPCTSTR lpszFace, int nEscapement, int nOrientation, int nWeight, bool bItalic, bool bUnderline, bool bStrikeOut); _EASYX_DEPRECATE(settextstyle) void setfont(int nHeight, int nWidth, LPCTSTR lpszFace, int nEscapement, int nOrientation, int nWeight, bool bItalic, bool bUnderline, bool bStrikeOut, BYTE fbCharSet, BYTE fbOutPrecision, BYTE fbClipPrecision, BYTE fbQuality, BYTE fbPitchAndFamily); _EASYX_DEPRECATE(settextstyle) void setfont(const LOGFONT *font); // 设置当前字体样式 _EASYX_DEPRECATE(gettextstyle) void getfont(LOGFONT *font); // 获取当前字体样式 // 以下填充样式不再使用,新的填充样式请参见帮助文件 #define NULL_FILL BS_NULL #define EMPTY_FILL BS_NULL #define SOLID_FILL BS_SOLID // 普通一组 #define BDIAGONAL_FILL BS_HATCHED, HS_BDIAGONAL // /// 填充 (对应 BGI 的 LTSLASH_FILL) #define CROSS_FILL BS_HATCHED, HS_CROSS // +++ 填充 #define DIAGCROSS_FILL BS_HATCHED, HS_DIAGCROSS // xxx 填充 (heavy cross hatch fill) (对应 BGI 的 XHTACH_FILL) #define DOT_FILL (BYTE*)"\x80\x00\x08\x00\x80\x00\x08\x00" // xxx 填充 (对应 BGI 的 WIDE_DOT_FILL) #define FDIAGONAL_FILL BS_HATCHED, HS_FDIAGONAL // \\\ 填充 #define HORIZONTAL_FILL BS_HATCHED, HS_HORIZONTAL // === 填充 #define VERTICAL_FILL BS_HATCHED, HS_VERTICAL // ||| 填充 // 密集一组 #define BDIAGONAL2_FILL (BYTE*)"\x44\x88\x11\x22\x44\x88\x11\x22" #define CROSS2_FILL (BYTE*)"\xff\x11\x11\x11\xff\x11\x11\x11" // (对应 BGI 的 fill HATCH_FILL) #define DIAGCROSS2_FILL (BYTE*)"\x55\x88\x55\x22\x55\x88\x55\x22" #define DOT2_FILL (BYTE*)"\x88\x00\x22\x00\x88\x00\x22\x00" // (对应 BGI 的 CLOSE_DOT_FILL) #define FDIAGONAL2_FILL (BYTE*)"\x22\x11\x88\x44\x22\x11\x88\x44" #define HORIZONTAL2_FILL (BYTE*)"\x00\x00\xff\x00\x00\x00\xff\x00" #define VERTICAL2_FILL (BYTE*)"\x11\x11\x11\x11\x11\x11\x11\x11" // 粗线一组 #define BDIAGONAL3_FILL (BYTE*)"\xe0\xc1\x83\x07\x0e\x1c\x38\x70" // (对应 BGI 的 SLASH_FILL) #define CROSS3_FILL (BYTE*)"\x30\x30\x30\x30\x30\x30\xff\xff" #define DIAGCROSS3_FILL (BYTE*)"\xc7\x83\xc7\xee\x7c\x38\x7c\xee" #define DOT3_FILL (BYTE*)"\xc0\xc0\x0c\x0c\xc0\xc0\x0c\x0c" #define FDIAGONAL3_FILL (BYTE*)"\x07\x83\xc1\xe0\x70\x38\x1c\x0e" #define HORIZONTAL3_FILL (BYTE*)"\xff\xff\x00\x00\xff\xff\x00\x00" // (对应 BGI 的 LINE_FILL) #define VERTICAL3_FILL (BYTE*)"\x33\x33\x33\x33\x33\x33\x33\x33" // 其它 #define INTERLEAVE_FILL (BYTE*)"\xcc\x33\xcc\x33\xcc\x33\xcc\x33" // (对应 BGI 的 INTERLEAVE_FILL)
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值