13.3 运用LyDrawLib库绘制

LyDrawLib 是一款使用C语言开发的外部图形绘制模块,该模块基于DirectX 9引擎,能够实现在已有进程之上进行动态绘制。主要的特性包括,支持绘制透视方框、实心方框、半角方框、带有血条的方框、各种准星、描边文本的显示等。无论是静态的图形还是动态的效果,都能够被完美绘制。

使用LyDrawLib库绘制时读者只需要调用Start()->createWindow()这个函数即可,该函数主要实现动态创建一个透明窗体并将该窗体附着在被附着进程的顶部,该函数需要传入四个参数,其中前两个参数用于指定被附着进程的窗体类名,第三个参数用于指定绘制时所使用的字体类型,最后一个参数用于传递一个回调函数,由于此处我们不仅仅需要实现绘制效果还需要实现动态控制,则Ptr()回调函数内可以直接指定Function()用于实现功能判断,而Draw()函数则只负责动态绘制,通过两者的组合即可实现动态绘制图形并控制的效果,如下代码所示则是一个绘制框架;

#include "LyDrawLib.h"

int w = 0;
int h = 0;

// 函数功能实现
void Function()
{

}

// 菜单绘制部分
void Draw()
{

}

// 函数中转
void Ptr()
{
Function();
Draw();
}

int main(int argc, char *argv[])
{
// 运行线程
const char* class_name = "LySharkGame";

w = LyDrawLib::Start()->GetWindowWidth(class_name, class_name);
h = LyDrawLib::Start()->GetWindowHeight(class_name, class_name);

// 开始绘制
LyDrawLib::Start()->createWindow(class_name, class_name, "黑体", Ptr);

return 0;
}

13.3.1 绘制实心矩形

当我们需要绘制各类图形时只需要在Draw()函数内调用不同的库函数即可,首先我们先来绘制两种填充矩形,所谓的填充矩形也就是实心的,对于此类矩形的绘制可通过调用DrawFilledRectangle函数实现,该函数接收五个参数,第一二个参数分别代表绘制方框的X以及Y坐标,第三四个参数则分别代表矩形的宽度与高度,最后一个参数代表的是绘制时使用的三原色,D3DCOLOR_RGBA宏定义用于指定这三种颜色。

void Draw()
{
// 实心矩形
LyDrawLib::Start()->DrawFilledRectangle(20, 20, 90, 150, D3DCOLOR_RGBA(254, 0, 0, 184));

LyDrawLib::Start()->DrawFilledRectangle(120, 20, 60, 100, D3DCOLOR_RGBA(22, 0, 0, 184));

LyDrawLib::Start()->DrawFilledRectangle(220, 20, 60, 100, D3DCOLOR_RGBA(233, 254, 0, 184));

LyDrawLib::Start()->DrawFilledRectangle(320, 20, 30, 50, D3DCOLOR_RGBA(233, 22, 112, 184));

// 实心矩形 半透明
LyDrawLib::Start()->DrawFilledRectangleB(420, 20, 40, 60, D3DCOLOR_RGBA(157, 14, 77, 184));

LyDrawLib::Start()->DrawFilledRectangleB(420, 20, 40, 60, D3DCOLOR_RGBA(157, 14, 77, 184));

LyDrawLib::Start()->DrawFilledRectangleB(520, 20, 40, 60, D3DCOLOR_RGBA(247, 55, 96, 147));
}

运行上述绘制代码,读者可看到如下图所示的实体图形输出;

13.3.2 绘制空心矩形

除此之外LyDrawLib库还支持绘制空心矩形,此处笔者提供了两个函数来实现绘制,函数DrawBorderRectangle可用于绘制一个空心矩形,当然读者也可以调用DrawFourCornersBox实现绘制四角方框,这两种方框的绘制原理都是运用了画线函数实现,只是通过数学计算得到了方框效果,读者也可以自行封装一些其他绘制方法。

void Draw()
{
// 空心矩形
LyDrawLib::Start()->DrawBorderRectangle(30, 20, 90, 150, 2, D3DCOLOR_RGBA(255, 0, 0, 184));

LyDrawLib::Start()->DrawBorderRectangle(130, 20, 60, 100, 2, D3DCOLOR_RGBA(22, 0, 0, 184));

// 绘制四角方框
LyDrawLib::Start()->DrawFourCornersBox(230, 20, 90, 150, 1, D3DCOLOR_RGBA(254, 0, 0, 25));

LyDrawLib::Start()->DrawFourCornersBox(330, 20, 90, 150, 2, D3DCOLOR_RGBA(157, 14, 77, 184));
}

运行上述绘制代码,读者可看到如下图所示的实体图形输出;

我们继续延申绘制功能,函数DrawPerspectiveRect用于绘制复合矩形,该举行的实现原理同样是两个简单的矩形组合而成,而在第一个矩形内部则使用了一个加粗线条版的直线用于描绘当前某个属性的具体参数,当某值发生变化是条形框中的颜色也会相应发生变化,该函数需要传递五个参数,分别是属性值/X坐标/Y坐标/宽度/高度传入后即可绘制出给中类型的复杂矩形;

void Draw()
{
LyDrawLib::Start()->DrawPerspectiveRect(93, 30, 30, 90, 160);

LyDrawLib::Start()->DrawPerspectiveRect(65, 160, 30, 60, 120);

LyDrawLib::Start()->DrawPerspectiveRect(10, 260, 30, 40, 100);
}

运行上述绘制代码,读者可看到如下图所示的实体图形输出;

13.3.3 绘制进度条

除了绘制矩形外,LyDrawLib库还支持绘制不同种类的血块,通过DrawBloodFrame可绘制普通血块,如果需要绘制竖向血块则可使用DrawBlood_Vertical函数,同样读者也可使用DrawBlood_Horizontal两者之间的不同在于第二个函数可以指定掉血的方向,例如是从上向下还是从下向上,基础版则不支持此类功能,此外DrawBlood_Transverse也可用于绘制血块,该函数可传递两个不同的颜色用于区别血条与血块,读者可自行更改绘制参数分别测试绘制效果;

void Draw()
{
// 普通血块(空块)
LyDrawLib::Start()->DrawBloodFrame(10, 20, 100, 15, 2, D3DCOLOR_RGBA(254, 0, 0, 184));

// 竖向血条(基础)
LyDrawLib::Start()->DrawBlood_Vertical(100, 200, 200, 100, 55, D3DCOLOR_RGBA(254, 0, 0, 184));

// 竖向血条(封装) style = 0 从下往上减血 style = 1 从上往下减血
LyDrawLib::Start()->DrawBlood_Horizontal(67, 300, 300, 22, 100, D3DCOLOR_RGBA(254, 0, 0, 184), 1);

LyDrawLib::Start()->DrawBlood_Horizontal(15, 400, 300, 22, 100, D3DCOLOR_RGBA(254, 0, 0, 184), 0);

// 中心血条
LyDrawLib::Start()->DrawCenterBlood(300, 55, 100, 25, 98, 0);

// 横向血条
LyDrawLib::Start()->DrawBlood_Transverse(83, 360, 200, 100, 22, D3DCOLOR_RGBA(254, 0, 0, 184), D3DCOLOR_RGBA(44, 0, 0, 10));

LyDrawLib::Start()->DrawBlood_Transverse(45, 400, 200, 22, 100, D3DCOLOR_RGBA(254, 0, 0, 184), D3DCOLOR_RGBA(44, 0, 0, 10));
}

运行上述绘制代码,读者可看到如下图所示的实体图形输出;

13.3.4 绘制圆形及准星

除了上述绘制矩形外,LyDrawLib库也支持绘制圆形圆角等功能,通过调用DrawCircle函数读者可实现绘制圆环,使用DrawCollimation或者DrawSuperCollimation函数,可绘制准星,此处的准星模式有三种读者可通过最后一个参数传递用于控制绘制准星的种类,最后DrawRadar函数可用于绘制雷达;

void Draw()
{
// 画圆形
LyDrawLib::Start()->DrawCircle(100, 200, 55, 3, D3DCOLOR_RGBA(255, 0, 0, 255));

// 画圆点
LyDrawLib::Start()->DrawPoint(55, 67, 2, D3DCOLOR_RGBA(255, 0, 0, 255));

// 画十字准星
LyDrawLib::Start()->DrawCollimation(255, 44, D3DCOLOR_RGBA(255, 0, 0, 255), 1);

LyDrawLib::Start()->DrawCollimation(280, 44, D3DCOLOR_RGBA(255, 0, 0, 255), 2);

LyDrawLib::Start()->DrawCollimation(350, 44, D3DCOLOR_RGBA(255, 0, 0, 255), 3);

// 超级准星
LyDrawLib::Start()->DrawSuperCollimation(255, 100, D3DCOLOR_RGBA(255, 0, 0, 255), 1);

LyDrawLib::Start()->DrawSuperCollimation(300, 100, D3DCOLOR_RGBA(255, 0, 0, 255), 2);

LyDrawLib::Start()->DrawSuperCollimation(350, 100, D3DCOLOR_RGBA(255, 0, 0, 255), 3);

// 绘制雷达
LyDrawLib::Start()->DrawRadar(400, 200);
}

运行上述绘制代码,读者可看到如下图所示的实体图形输出;

13.3.5 绘制文本字符串

有时候我们需要绘制一些文本字体等功能,LyDrawLib库同时支持绘制普通文本,描边文本,以及多重文本,读者可使用如下代码片段自行测试绘制效果;

void Draw()
{
char szBuf[256] = { 0 };

strcpy(szBuf, "hello lyshark www.lyshark.com");

// 普通文本
LyDrawLib::Start()->DrawString(szBuf, 25, 10, 20, D3DCOLOR_RGBA(255, 0, 0, 255));

// 描边文本
LyDrawLib::Start()->DrawColourString(szBuf, 30, 20, 40, D3DCOLOR_RGBA(255, 0, 0, 255), D3DCOLOR_RGBA(5, 0, 0, 2));

// 多重文本
LyDrawLib::Start()->DrawStringAndString(szBuf, szBuf, 40, 25, 50, 100, D3DCOLOR_RGBA(255, 0, 0, 255), D3DCOLOR_RGBA(5, 0, 0, 2));

LyDrawLib::Start()->DrawColourString2("hello lyshark", 50, 20, 20, D3DCOLOR_RGBA(0, 0, 255, 221));

LyDrawLib::Start()->DrawColourString3("welcome lyshark.com", 60, 40, 40, D3DCOLOR_RGBA(255, 0, 255, 255));
}

运行上述绘制代码,读者可看到如下图所示的实体图形输出;

至此绘图库的基本功能也就介绍完了,这里扩展一个知识点,在某些时候我们需要得到当前窗体中画面的FPS参数,该数据的获取可以使用timeGetTime()*0.001来实现,通过该函数计算帧数的差值,即可很容易的得到页面的FPS值,如下所示代码;

#pragma comment(lib,"winmm.lib")

typedef struct
{
DWORD 当前帧数;
FLOAT 当前时间;
FLOAT 持续时间;
FLOAT 返回FPS;
}D3DFPS;

D3DFPS fps = { 0 };

FLOAT get_fps()
{
fps.当前帧数 = fps.当前帧数 + 1;
fps.当前时间 = timeGetTime() * 0.001;
if (fps.当前时间 - fps.持续时间 > 1)
{
fps.返回FPS = fps.当前帧数 / (fps.当前时间 - fps.持续时间);
fps.持续时间 = fps.当前时间;
fps.当前帧数 = 0;
}

return fps.返回FPS;
}

void Draw()
{
char sz[256] = { 0 };

sprintf(sz, "当前 FPS: %f", get_fps());
LyDrawLib::Start()->DrawColourString2(sz, 30, 20, 20, D3DCOLOR_RGBA(0, 0, 255, 221));

char nam[256] = { 0 };
strcpy(nam, "PowerBy: lyshark");
LyDrawLib::Start()->DrawColourString2(nam, 20, 70, 70, D3DCOLOR_RGBA(0, 0, 255, 221));
}

运行上述绘制代码,读者可看到如下图所示的实体图形输出;

13.3.6 绘制功能菜单

此外LyDrawLib库还支持绘制各类复杂的图形结构,通过对本库的灵活运用,读者可是实现一个简单的功能菜单,如下所示。

void Menu()
{
int Spacingposition = 0;
int Leftmostmenu = WindowWidth / 30;
int Menuhighest = Windowheight / 3;

Spacingposition = Spacingposition + 10;

LyDrawLib::Start()->DrawBorderRectangle(Leftmostmenu + 5, Menuhighest + 9 + (2 - 1) * 25, 110, 20, 1, D3DCOLOR_XRGB(148, 0, 211));
LyDrawLib::Start()->DrawBorderRectangle(Leftmostmenu, Menuhighest, 120, 190, 1, D3DCOLOR_XRGB(255, 69, 0));

LyDrawLib::Start()->DrawStringAndString("功能A ", "[开启]", 12, 65, Leftmostmenu + 10, Menuhighest + Spacingposition, D3DCOLOR_XRGB(255, 52, 179), D3DCOLOR_XRGB(0, 255, 0));
Spacingposition = Spacingposition + 25;

LyDrawLib::Start()->DrawStringAndString("功能B ", "[开启]", 12, 65, Leftmostmenu + 10, Menuhighest + Spacingposition, D3DCOLOR_XRGB(255, 52, 179), D3DCOLOR_XRGB(0, 255, 0));
Spacingposition = Spacingposition + 25;

LyDrawLib::Start()->DrawStringAndString("功能C ", "[开启]", 12, 65, Leftmostmenu + 10, Menuhighest + Spacingposition, D3DCOLOR_XRGB(255, 52, 179), D3DCOLOR_XRGB(0, 255, 0));
Spacingposition = Spacingposition + 25;

LyDrawLib::Start()->DrawStringAndString("功能D ", "[开启]", 12, 65, Leftmostmenu + 10, Menuhighest + Spacingposition, D3DCOLOR_XRGB(255, 52, 179), D3DCOLOR_XRGB(0, 255, 0));
Spacingposition = Spacingposition + 25;

LyDrawLib::Start()->DrawStringAndString("功能E ", "[开启]", 12, 65, Leftmostmenu + 10, Menuhighest + Spacingposition, D3DCOLOR_XRGB(255, 52, 179), D3DCOLOR_XRGB(255, 250, 250));
Spacingposition = Spacingposition + 25;

LyDrawLib::Start()->DrawStringAndString("功能F ", "[开启]", 12, 65, Leftmostmenu + 10, Menuhighest + Spacingposition, D3DCOLOR_XRGB(255, 52, 179), D3DCOLOR_XRGB(255, 250, 250));
Spacingposition = Spacingposition + 25;

LyDrawLib::Start()->DrawStringAndString("功能G ", "[开启]", 12, 65, Leftmostmenu + 10, Menuhighest + Spacingposition, D3DCOLOR_XRGB(255, 52, 179), D3DCOLOR_XRGB(255, 250, 250));
Spacingposition = Spacingposition + 35;

LyDrawLib::Start()->DrawString("HOME 显示/隐藏", 15, Leftmostmenu + 9, Menuhighest + Spacingposition, D3DCOLOR_RGBA(255, 0, 0, 255));
}

读者可自行运行这段代码片段,此时在窗体中会出现一个功能菜单,如下图所示;