文章目录
说明
C++语言图形编程最基本的几个函数,简略代码,仅介绍函数及参数,并举例说明。非常简单,适合新人查阅。
工具及环境
平台:Windows 10, VS2013(注:文件 -> 新建 -> 项目 -> Visual C++ -> 空项目)
主要头文件:graphics.h (百度EasyX安装依赖的库文件)
基本图形绘制
生成图形窗口
HWND initgraph(int WIDTH, int HEIGHT)
WIDTH:窗口宽度,单位:像素
HEIGHT:窗口高度
例:创建一个宽度为600像素,高度为400像素的窗口
initgraph(600,400);
closegraph(); //关闭窗口
辅助函数:
刷新(清空)屏幕:cleardevice()
绘制点
void putpixel(int X, int Y, COLORREF COLOR)
X:X 轴坐标
Y:Y 轴坐标
COLOR:点颜色,支持宏、16进制颜色代码
注:窗口左上角坐标为(0,0),横轴为 X 轴,纵轴为 Y 轴
例:在(300,200)位置生成一个蓝色点
putpixel(300, 200, 0xFF0000);
绘制线
void line(int X1, int Y1, int X2, int Y2)
X1:第一点 X 轴坐标
Y1:第一点 Y 轴坐标
X2:第二点 X 轴坐标
Y2:第二点 Y 轴坐标
注:绘制前使用 setlinecolor(COLORREF COLOR) 设置线颜色
setlinestyle(int LINE_STYLE, int THICKNESS)
STYLE:线风格,常用如
0 实线
1 点线
2 中心线
3 断续线
THICKNESS:线宽
例:绘制一个窗口左上角至窗口右下角的红色实线
setlinestyle(0, 2)
setlinecolor(0x0000FF);
line(0, 0, 600, 400);
绘制矩形
空心矩形:void rectangle(int X1, int Y1, int X2, int Y2)
注:用法如 line 函数,不再赘述
实心有边框矩形:void fillrectangle(int X1, int Y1, int X2, int Y2)
实心无边框矩形:void solidrectangle(int X1, int Y1, int X2, int Y2)
注:实心矩形颜色使用 setfillcolor(COLORREF COLOR) 设置颜色
有边框矩形(包含空心矩形)使用 setlinecolor(COLORREF COLOR) 设置颜色
例:创建一个以(100,100)为挤出点,宽度为200,高度为150的实心有边框矩形,填充颜色白色,边框红色
setlinecolor(0x0000FF);
setfillcolor(0xFFFFFF);
fillrectangle(100, 100, 100+200, 100+150);
绘制圆
空心圆:void circle(int X, int Y, int R)
X:圆心 X 轴坐标
Y:圆心 Y 轴坐标
R:半径
实心有边框圆:void fillcircle(int X, int Y, int R)
实心无边框圆:void solidcircle(int X, int Y, int R)
注:设置填充和边框颜色在矩形部分已有讲解
例:在窗口中心绘制一个半径为150的绿色实心圆
setfillcolor(0x00FF00);
solidcircle(300,200, 150);
文字输出
outtextxy(int X, int Y, char* STR)
X:文字输出位置 X 轴坐标
Y:文字输出位置 Y 轴坐标
STR:输出内容,支持明文字符串
设置字符风格:void settextstyle(int HEIGHT, int WIDTH, char* FONT)
HEIGHT:字符高
WIDTH:字符宽,为 0 则为自适应宽度,通常指定高度,宽度自适应
FONT:字体
设置字符颜色:void settextcolor(COLORREF COLOR)
设置字符背景色:void setbkcolor(COLORREF COLOR)
设置字符背景模式:void setbkmode(int MODE)
MODE:经测试值为 2 时背景为默认或者设置的字符背景色,其他值为透明
例:在(100,100)位置输出字符串,背景透明,字符颜色红色,楷体,高度30
setbkmode(1);
settextcolor(0x0000FF);
settextstyle(30,0,"楷体");
outtextxy(100, 100, "你好世界!");
注:图形化界面输出格式化数据的方法(如数字转字符串)
char str[32];
int score = 100;
sprintf(str, "分数:%d", score); //格式化数据转字符串
outtextxy(0, 0, str); //最终输出 分数:100
贴图操作
声明 IMAGE 类型变量
IMAGE IMG;
载入图片
void loadimage(IMAGE* IMG, LPCTSTR FILE, int WIDTH, int HEIGHT, bool RESIZE)
IMG:IMAGE类型变量
FILE:图片文件路径,char*类型,如果有多层目录结构,间隔符号用 / 或者 \\
文件当前路径为 .cpp 文件所在路径
WIDTH:载入图片的宽度
HEIGHT:载入图片的高度
RESIZE:缺省值为 false
注:指明了载入图片宽度和高度,图片将以缩放形式适应设定值
输出图片
void putimage(int X, int Y, const IMAGE* IMG)
X:输出至屏幕位置 X 轴坐标
Y:输出至屏幕位置 Y 轴坐标
IMG:图片变量地址,如 &img
void putimage(int X, int Y, int WIDTH, int HEIGHT, const IMAGE* IMG, int IMG_X, int IMG_Y)
X:输出至窗口起始位置 X 轴坐标
Y:输出至窗口起始位置 Y 轴坐标
WIDTH:指定绘制宽度
HEIGHT:指定绘制高度
IMG:图片变量地址,如 &img
IMG_X:图片起始打印位置的 X 轴坐标。此时图片大小为载入后的大小
IMG_Y:图片起始打印位置的 Y 轴坐标。
函数解释:从图片的 (IMG_X,IMG_Y) 位置开始截取 WIDTH 宽、HEIGHT 高的图形
输出至窗口 (X, Y) 位置
例:图片载入后拉伸与窗口(600x400)同大小,现在在窗口上半部分输出图片的下半部分
IMAGE img;
loadimage(&img, "main.jpg", 600, 400);
putimage(0, 0, 600, 400/2, &img, 0, 400/2);
其他补充
媒体控制
mciSendString(LPCTSTR lpszCommand, LPTSTR lpszReturnString, UINT cchReturn, HANDLE hwndCallback);
lpszCommand:mci命令字符串
lpszReturnString:反馈信息缓冲区
cchReturn:缓冲区长度
hwndCallback:回调窗口句柄
注:请添加如下行避免mciSendString()无法解析
#include <mmsystem.h>
#pragma comment(lib, "winmm.lib")
mci常用命令:
1、open:打开设备
open DEVICE_NAME type DEVICE_TYPE alias DEVICE_ALIAS
DEVICE_NAME:设备名,通常是文件名
type DEVICE_TYPE:指明设备类型,常省略
alias DEVICE_ALIAS:设备别名,(理解为指代设备的变量名)可在其他mci命令中使用
2、play:设备播放
play DEVICE_ALIAS from POS1 to POS2 wait|repeat
DEVICE_ALIAS:播放的设备别名
from POS1 to POS2:从POS1磁道播放至POS2磁道,省from表从头播放,省to表播放至尾部
wait|repeat:播放模式,wait播放一次后命令返回,repeat循环播放
3、暂停,恢复,停止,关闭
pause DEVICE_ALIAS
resume DEVICE_ALIAS
stop DEVICE_ALIAS:停止播放非关闭
close DEVICE_ALIAS:关闭设备
例:播放 程序路径下 music/1.mp3 文件
mciSendString("open music\\1.mp3 alias m1", 0, 0, 0); //打开设备
mciSendString("play m1 wait", 0, 0, 0); //单次播放
mciSendString("close m1", 0, 0, 0); //关闭设备
多线程
1、多线程回调函数
DWORD WINAPI fun1(LPVOID lpParame)
{
//...
//fun1()需要执行的动作
//...
return 0;
}
2、创建线程并执行回调函数
CreateThread(NULL, 0, fun1, NULL, NULL, NULL);
批处理绘制
在图形编程过程中,频繁的刷新(cleardevice()函数)会产生屏幕闪烁情况,使用批处理绘制可将特定的绘图操作事先进行缓冲,然后批量输出至屏幕。
BeginBatchDraw(); //此后绘图将不会输出至屏幕
// ...
// 大量绘图函数
// ...
EndBatchDraw(); //程序执行到此处后,将器件缓冲的信息批量输出至屏幕
时间控制
控制特定步骤的执行时间间隔,而不影响其他步骤。不同于Sleep()函数,Sleep()是将整个程序暂停特定时间。
DWORD t1, t2;
t1 = t2 = GetTickCount(); //GetTickCount():获取开机至当前时间长度,单位ms
while(1)
{
t2 = GetTickCount();
if(t2 - t1 > 50) //fun1()至少每隔 50ms 执行一次,fun2()正常执行
{
fun1();
t1 = t2;
}
fun2();
}
鼠标键盘事件
1、键盘事件
char ch;
if(_kbhit()) // 存在键盘点击事件,_kbhit()返回非0值,conio.h
ch = _getch(); // 键盘输入字符赋值给ch
2、鼠标事件
方法一:
MOUSEMSG m; //鼠标事件结构体
if(MouseHit()) // 如果存在鼠标消息则返回 true,conio.h
m = GetMouseMsg();
MOUSEMSG原型
struct MOUSEMSG{
UINT uMsg; // 当前鼠标消息
/*其中鼠标消息包含:
WM_MOUSEMOVE 鼠标移动消息
WM_MOUSEWHEEL 鼠标滚轮拨动消息
WM_LBUTTONDOWN 左键按下消息
WM_LBUTTONUP 左键弹起消息
WM_LBUTTONDBLCLK 左键双击消息
WM_MBUTTONDOWN 中键按下消息
WM_MBUTTONUP 中键弹起消息
WM_MBUTTONDBLCLK 中键双击消息
WM_RBUTTONDOWN 右键按下消息
WM_RBUTTONUP 右键弹起消息
WM_RBUTTONDBLCLK 右键双击消息
*/
bool mkCtrl; // Ctrl 键是否按下
bool mkShift; // Shift 键是否按下
bool mkLButton; // 鼠标左键是否按下
bool mkMButton; // 鼠标中键是否按下
bool mkRButton; // 鼠标右键是否按下
int x; // 当前鼠标 x 坐标 int
y; // 当前鼠标 y 坐标
int wheel; // 鼠标滚轮滚动值
};
方法二:
GetMouseMsg()仅能够在鼠标有动作的情况下获取鼠标信息,若鼠标无动作,则返回空值,m结构体中则不存在x,y值。
如果想要实时获取鼠标位置信息时,需要引入MouseHit()进行判断,存在消息才对m赋值。
以下方法也可以实时获取鼠标位置,但该法获取的位置可以超出绘图窗口,需要时要都进行判断以限制坐标值。
POINT p;
HWND hwnd;
hwnd = GetWind(); // 获取绘图窗口句柄
GetCursorPos(&p); // 获取鼠标指针位置(屏幕坐标)
ScreenToClient(hwnd, &p); // 将鼠标指针位置转换为绘图窗口坐标
此后可以使用 p.x 与 p.y 表示鼠标在绘图窗口的坐标
图形绘制工作区
intigraph(100,100);
IMAGE bkImg(200, 200); //声明一个IMAGE变量,并初始化尺寸200x200
SetWorkingImage(&bkImg); //设置工作区
/*
大量绘图操作
此时绘制的图形存在于bkImg上,而非100x100的图形窗口
*/
SetWorkingImage(); //恢复工作区为100x100窗口
游戏中窗口显示部分区域,视野随某个点移动解决方案:
1、事先绘制更大的图形(为所需地图大小),相关内容一并绘制在该图形上
2、以目标角色为中心,即窗口区域为视野
根据角色坐标、窗口大小,计算出窗口 (0, 0) 点在图形上的真实位置
假设角色坐标 (x, y),窗口宽 WIN_W、高 WIN_H,
那么窗口 (0,0) 位置真坐标为:(x - WIN_W/2, y - WIN_H/2)
3、putimage( )函数输出对应区域至窗口
putimage(0, 0, WIN_W, WIN_H, &bkImg, x - WIN_W/2, y - WIN_H/2);