22绘图工具-绘制按钮

 main.cpp

#include<stdio.h>
#include"Shape.h"
#include"Button.h"
/*
* 项目内容:绘图工具
* 开发环境:vs2019 + easyx
* 主讲老师:顽石老师
*/

//顺序表来存储所有的形状 Line  Rect ...
struct ShapeSet
{
	void* shapes[256];		//万能指针数组,所有类型的指针都可以自动转换为void*
	int size;
};
#define ShapeSet_Init(set) memset(set.shapes,0,sizeof(set.shapes));set.size = 0
#define ShapeSet_Add(set,pshape) set.shapes[set.size++] = pshape
#define ShapeSet_Pop(set) if(set.size>0){free(set.shapes[set.size-1]);set.size--;}
//快捷遍历顺序表
#define ShapeSet_Foreach(pval,set) \
for(int i = 0,cnt = 0;i < set.size;++i,cnt = 0) \
for(pval = set.shapes[i];cnt < 1;++cnt)


ShapeSet g_shapes;
POINT begPos = { 0,0 };		//鼠标点击的位置
bool isPress = false;		//鼠标左键是否按下

int curShapeType = ST_Rect;		//当前绘图的形状
COLORREF curLineColor = RED;	//当前的线条颜色
Graffiti g_graf;				//用于当前操作的涂鸦

void onMouseLButtonDown(ExMessage* msg)
{
	//记录开始点击的坐标
	begPos = { msg->x,msg->y };
	//左键按下了
	isPress = true;

	if (curShapeType == ST_Graffiti)
	{
		graf_init(&g_graf, curLineColor);
		graf_addPoint(&g_graf, msg->x, msg->y);
	}
}

void onMouseLButtonUp(ExMessage* msg)
{
	//放开的时候保存线
	isPress = false;

	//动态申请一个内存,存放形状
	if (curShapeType == ST_Line)
	{
		Line* le = (Line*)calloc(1, sizeof(Line));
		line_init(le, begPos.x, begPos.y, msg->x, msg->y, curLineColor);
		ShapeSet_Add(g_shapes, le);
	}
	else if (curShapeType == ST_Rect)
	{
		Rect* rect = (Rect*)calloc(1, sizeof(Rect));
		rect_init(rect, begPos.x, begPos.y, msg->x, msg->y, curLineColor);
		ShapeSet_Add(g_shapes, rect);
	}
	else if (curShapeType == ST_Graffiti)
	{
		Graffiti* g = (Graffiti*)calloc(1, sizeof(Graffiti));
		*g = g_graf;		//把刚才绘制的涂鸦,交给申请的内存
		ShapeSet_Add(g_shapes, g);
	}

}

void onMouseMove(ExMessage* msg)
{
	if (isPress)
	{
		cleardevice();
		setlinecolor(curLineColor);
		switch (curShapeType)
		{
		case ST_Line:
			line(begPos.x, begPos.y, msg->x, msg->y);
			break;
		case ST_Rect:
			rectangle(begPos.x, begPos.y, msg->x, msg->y);
			break;
		case ST_Graffiti:
			graf_addPoint(&g_graf, msg->x, msg->y);
			graf_draw(&g_graf);
			break;
		}
	}
}

void onMouseRButtonDown(ExMessage*msg)
{
	printf("onMouseRButtonDown  %d\n",g_shapes.size);
	ShapeSet_Pop(g_shapes);
	cleardevice();		//撤销一个清屏一下
}

int main()
{
	initgraph(640, 480,EW_SHOWCONSOLE);
	//设置窗口背景颜色
	setbkcolor(WHITE);
	cleardevice();

	ShapeSet_Init(g_shapes);

	Button* btn = createButton(0, 0, 150, 30, BT_Rect);
	btn_setText(btn, "Maye");


	//通过鼠标绘制,获取鼠标的消息
	while (true)
	{
		//双缓冲
		BeginBatchDraw();

		//绘制所有形状
		ShapeSet_Foreach(void* shape, g_shapes)
		{
			int type = ((Shape*)shape)->type;
			switch (type)
			{
			case ST_Line:
				line_draw((Line*)shape);
				break;
			case ST_Rect:
				rect_draw((Rect*)shape);
				break;
			case ST_Graffiti:
				graf_draw((Graffiti*)shape);
				break;
			}		
		}

		//绘制控件
		btn_draw(btn);

		EndBatchDraw();	//结束双缓冲

		//定义一个消息的结构体
		ExMessage msg;
		//不断地获取消息
		while (peekmessage(&msg, EM_MOUSE))
		{
			if (btn_isClicked(btn, &msg))
			{
				curLineColor = RGB(187, 136, 243);
				printf("btn_isClicked\n");
			}
			btn_msgHanding(btn, &msg);

			switch (msg.message)
			{
			case WM_LBUTTONDOWN:	//左键按下
				onMouseLButtonDown(&msg);
				break;
			case WM_MOUSEMOVE:		//鼠标移动
				onMouseMove(&msg);
				break;
			case WM_LBUTTONUP:		//左键释放
				onMouseLButtonUp(&msg);
				break;
			case WM_RBUTTONDOWN:
				onMouseRButtonDown(&msg);
				break;
			case WM_MOUSEWHEEL:
				curShapeType = (curShapeType + 1) % ST_Max;
				break;
			default:
				break;
			}
		}
	}


	return 0;
}

/*
* 1,选择形状和颜色的菜单(封装菜单)
* 2,保存图形和加载图形(文件操作)
* 3,按钮的处理之回调写法
*/

Shape.h

#ifndef  _SHAPE_H_
#define _SHAPE_H_
#include<easyx.h>
//绘制的图形有哪些,枚举
enum ShapeType
{
	ST_Line,		//线
	ST_Rect,		//矩形
	ST_Ellipse,		//圆
	ST_Graffiti,	//涂鸦
	ST_FiveStar,	//五角星
	ST_Max
};

/* @形状*/
struct Shape
{
	int type;			//形状类型
	COLORREF lineColor;	//线条颜色
};
//初始化形状的成员
void shape_init(Shape* shape, int type, COLORREF c);

/* @直线*/
struct Line
{
	Shape super;	//组合一个形状结构(相当父类)
	int x1;
	int y1;
	int x2;
	int y2;
};

void line_init(Line* pline, int x1, int y1, int x2, int y2,COLORREF c);

void line_draw(Line* pline);

/* @矩形*/
struct Rect
{
	Line super;
};

void rect_init(Rect* rect, int x1, int y1, int x2, int y2, COLORREF c);

void rect_draw(Rect* rect);


/* @涂鸦*/
struct Graffiti
{
	Shape super;	//必须是第一个成员
	POINT* points;	//数组指针
	int size;		//当前点数
	int capacity;	//容量
};

void graf_init(Graffiti* graf, COLORREF c);

void graf_draw(Graffiti* graf);

void graf_addPoint(Graffiti* graf, int x, int y);


#endif // ! _SHAPE_H_

Button.h

#pragma once
#include<easyx.h>

enum ButtonType
{
	BT_Rect,
	BT_Circle
};

struct Button
{
	int type;				//按钮形状
	int x;
	int y;
	int w;
	int h;
	COLORREF bkColor;		//背景颜色
	COLORREF borderColor;	//边框颜色
	char text[50];			//按钮文本

	COLORREF hoverColor;	//鼠标悬停颜色
	COLORREF curColor;		//当前背景颜色
};

//在堆区创建一个按钮
Button* createButton(int x, int y, int w, int h, int type);
//绘制按钮
void btn_draw(Button* btn);
//鼠标是否在按钮上
bool btn_isIn(Button* btn, ExMessage* msg);
//鼠标左键是否按下
bool btn_isClicked(Button* btn, ExMessage* msg);


//设置文本
void btn_setText(Button* btn, const char* text);

//按钮的消息处理函数
void btn_msgHanding(Button*bnt,ExMessage* msg);

Shape.cpp

#include"Shape.h"
#include<stdio.h>
void shape_init(Shape* shape, int type, COLORREF c)
{
	shape->type = type;
	shape->lineColor = c;
}

void line_init(Line* pline, int x1, int y1, int x2, int y2, COLORREF c)
{
	shape_init(&pline->super, ST_Line, c);	//初始化父类
	pline->x1 = x1;
	pline->y1 = y1;
	pline->x2 = x2;
	pline->y2 = y2;
}

void line_draw(Line* pline)
{
	setlinecolor(pline->super.lineColor);
	line(pline->x1, pline->y1, pline->x2, pline->y2);
}

void rect_init(Rect* rect, int x1, int y1, int x2, int y2, COLORREF c)
{
	line_init(&rect->super, x1, y1, x2, y2, c);
	rect->super.super.type = ST_Rect;
}

void rect_draw(Rect* rect)
{
	setlinecolor(rect->super.super.lineColor);
	rectangle(rect->super.x1, rect->super.y1, rect->super.x2, rect->super.y2);
}

void graf_init(Graffiti* graf, COLORREF c)
{
	shape_init(&graf->super, ST_Graffiti, c);
	graf->capacity = 500;	//开始容量500
	graf->size = 0;
	graf->points = (POINT*)calloc(graf->capacity, sizeof(POINT));
	if (graf->points == NULL)
	{
		printf("[error %d]memory allocated failed\n", __LINE__);
	}
}

void graf_draw(Graffiti* graf)
{
	if (graf->points)
	{
		setlinecolor(graf->super.lineColor);
		polyline(graf->points, graf->size);
	}
}

void graf_addPoint(Graffiti* graf, int x, int y)
{
	//是否能插
	if (graf->size < graf->capacity)
	{
		graf->points[graf->size++] = { x,y };
	}
	//满了,需要扩容
	else if(graf->size == graf->capacity)
	{
		graf->capacity *= 2;	//每次扩容为本身的两倍
		POINT* newPoints = (POINT*)realloc(graf->points, graf->capacity);
		if (newPoints == NULL)
		{
			printf("[error %d]扩容失败\n", __LINE__);
		}
		else
		{
			graf->points = newPoints;
		}
	}
}

Button.cpp

#include "Button.h"

Button* createButton(int x, int y, int w, int h, int type)
{
    Button* btn = (Button*)calloc(1, sizeof(Button));
    if (!btn)
        return NULL;
    btn->x = x;
    btn-> y = y;
    btn->w = w;
    btn->h = h;
    btn->type = type;
    btn->bkColor = RGB(230, 231, 232);
    btn->borderColor = RGB(50, 124, 46);
    memset(btn->text, 0, sizeof(btn->text));
    setbkmode(TRANSPARENT);


    btn->hoverColor = RGB(85, 85, 85);
    btn->curColor = btn->bkColor;

    return btn;
}

void btn_draw(Button* btn)
{
    setlinecolor(btn->borderColor);
    setfillcolor(btn->curColor);
    if (btn->type == BT_Circle)
    {
        fillellipse(btn->x, btn->y, btn->x + btn->w, btn->y + btn->h);
    }
    else if (btn->type == BT_Rect)
    {
        fillroundrect(btn->x, btn->y, btn->x + btn->w, btn->y + btn->h,5,5);
    }
    //绘制文本
    if (btn->text[0] != '\0')
    {
        settextcolor(RED);

        int hspace = (btn->w - textwidth(btn->text)) / 2;
        int vspace = (btn->h - textheight(btn->text)) / 2;

        outtextxy(btn->x + hspace, btn->y+vspace, btn->text);
    }
}

bool btn_isIn(Button* btn, ExMessage* msg)
{
    if (msg->x > btn->x && msg->x<btn->x + btn->w && msg->y>btn->y && msg->y < btn->y + btn->h)
    {
        return true;
    }
    return false;
}

bool btn_isClicked(Button* btn, ExMessage* msg)
{
    if (btn_isIn(btn, msg) && msg->message == WM_LBUTTONDOWN)
    {
        return true;
    }
    return false;
}

void btn_setText(Button* btn, const char* text)
{
    strcpy(btn->text, text);
}

void btn_msgHanding(Button* btn, ExMessage*msg)
{
    if (btn_isIn(btn, msg))
    {
        btn->curColor = btn->hoverColor;
    }
    else
    {
        btn->curColor = btn->bkColor;
    }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值