EasyX 鼠标点击事件监听的一种优雅实现

EasyX 鼠标点击事件监听的一种优雅实现

​ 最近,学校课程要求使用EasyX 实现一个小游戏或者小应用。但是无论是游戏还是应用,监听鼠标点击,并判断鼠标点击到了那里,并对此做出相应的响应都是不可避免的一个场景。

​ 是的,这是个非常简单的场景,想要实现也没啥难度。参照学校给的例子和网上找到的一些实现对此的处理,基本上代码如下所示:

if (msg.uMsg==WM_LBUTTONDOWN) // 如果点左键
    {
        if((msg.x>110 && msg.x<360) && (msg.y>240 && msg.y<310))// 点击菜单1
            choose='1';
        if((msg.x>110 && msg.x<398) && (msg.y>325 && msg.y<390))// 点击菜单2
            choose='2';
        if((msg.x>110 && msg.x<458) && (msg.y>410 && msg.y<475))// 点击菜单3
            choose='3';
        if((msg.x>110 && msg.x<332) && (msg.y>500 && msg.y<550))// 点击菜单4
            choose='4';
    }

当我第一眼看上去,啊这,不是吧。就这样写??
在这里插入图片描述

那我斗地主一个人17张牌个个这样写还得了?(是可以用循环简化,但是我还有一堆分布在天南海北的按钮),而且这样用 if 绝对不是我高某人的风格。于是,我就去睡觉了,毕竟梦里啥都有。
在这里插入图片描述

别别别,把刀收回去… 不睡了,不睡了,没有困难的任务,只有勇敢的当代大学牲!办他…
在这里插入图片描述
首先我们把所有,可以被点击的“东西”所共同拥有的特性抽象出来, 首先他可以被点击, 被绘制(既然可以被绘制那么肯定拥有下x, y坐标, 长度和宽度)所以这样一个类就被我们抽象出来了。

class Clickable
{
public:
	int x;
	int y;
	int height;
	int width;
	void(*clickAction)();

	void receiveEvent(int cx, int cy);
	virtual void draw() = 0;
private:
	bool isClickMe(int cx, int cy);
};

我相信x, y, height,width 不用多说。首先说一下,

  1. clickAction这是一个函数指针,他是 控件 被点击后所执行的操作。
  2. receiveEvent 是一个函数他负责通知控件用户点击了哪里
  3. isClickMe 是一个私有函数,他主要负责判断用户是否点击到控件

具体实现如下:


void Clickable::receiveEvent(int cx, int cy)
{
	if (isClickMe(cx, cy))
	{
		clickAction();
	}

}


bool Clickable::isClickMe(int cx, int cy)
{
	return cx >= x && cy >= y && x + width >= cx && y + height >= cy;
}

下面我们创建一个Button类来继承它,实现一下draw函数。

//-----Button.h----
#include "Clickable.h"
#include <graphics.h>		// 引用图形库头文件
#include <conio.h>

class Button: public Clickable
{
public:
	Button(int x, int y, int height, int width);
	void draw() override;
};
//------Button.cpp----
#include "Button.h"

Button::Button(int x, int y, int height, int width)
{
	this->x = x;
	this->y = y;
	this->height = height;
	this->width = width;
}

void Button::draw()
{
	fillrectangle(x, y,x + width, y + height);
}

可以看到, Button做的事情只是实现的draw函数画了个 矩形 没什么特殊的。下面最激动人心的时刻来了,我们在主函数里,把他画出来吧!!!

#include "Button.h"
using namespace std;
//bt点击事件
void bt_clickAction() {
	setfillcolor(BLUE);
	fillcircle(100, 300, 25);
}
//bt2点击事件
void bt2_clickAction() {
	setfillcolor(RED);
	fillcircle(400, 300, 25);
}
int main()
{
    initgraph(640, 480);//初始化画布
    //创建两个Button 对象
    Button bt = Button(100, 100, 25, 60);
    Button bt2 = Button(400, 100, 25, 60);
    //为他们设置点击事件
    bt.clickAction = bt_clickAction;
    bt2.clickAction = bt2_clickAction;
    //把他们绘制到屏幕上
    bt.draw();
    bt2.draw();
	MOUSEMSG m;		// 定义鼠标消息
	while (true)
	{
		// 获取一条鼠标消息
		m = GetMouseMsg();
		switch (m.uMsg)
		{
		case WM_LBUTTONDOWN://按鼠标左键分发事件
			bt.receiveEvent(m.x, m.y);
			bt2.receiveEvent(m.x, m.y);
			break;
		case WM_RBUTTONUP:
			return 0;	// 按鼠标右键退出程序
		}
	}
	// 关闭图形窗口
	closegraph();
}

上面的代码注释很清楚了,也解决了我们开始的问题(if成灾的问题)可以看到在 WM_LBUTTONDOWN 这个分支里我一个 if 都没有。
在这里插入图片描述
来测试一下,
在这里插入图片描述
当我点击左边的按钮,
在这里插入图片描述
一个蓝色的⚪,横空出世. 当我点击右边的按钮,又是一个红色的⚪
在这里插入图片描述

别说代码反而变多了,20个按钮你试试?在这里插入图片描述
写完了, 溜了溜了…

猜你喜欢

转载自blog.csdn.net/qq_36323419/article/details/115266521