An elegant implementation of EasyX mouse click event monitoring

An elegant implementation of EasyX mouse click event monitoring

​ Recently, the school curriculum requires the use of EasyX to implement a small game or small application. But whether it is a game or an application, it is inevitable to monitor mouse clicks, determine where the mouse clicks are, and respond accordingly.

​ Yes, this is a very simple scenario, and it is not difficult to achieve it. Refer to the examples given by the school and some implementations found on the Internet to deal with this, the basic code is as follows:

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';
    }

When I first looked, ah this, isn't it? Just write it like this? ?
Insert picture description here

Then I can write 17 cards like this for Doudizhu alone? (It can be simplified with a loop, but I still have a bunch of buttons distributed all over the world), and using if in this way is definitely not my style. So, I went to bed, after all, I have everything in my dreams.
Insert picture description here

Don't don't don't, take the knife back... Stop sleeping, stop sleeping, no difficult tasks, only brave contemporary college sacrifices! Do it...
Insert picture description here
First, we abstract out the common characteristics of all the "things" that can be clicked. First, it can be clicked and drawn (since it can be drawn, it must have x, y coordinates, length and width). Such a class is abstracted by us.

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);
};

I believe x, y, height and width needless to say. First of all,

  1. clickAction This is a function pointer, which is the action performed after the control is clicked.
  2. receiveEvent is a function that is responsible for notifying the control where the user clicked
  3. isClickMe is a private function, which is mainly responsible for judging whether the user clicks on the control

The specific implementation is as follows:


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;
}

Next we create a Button class to inherit it and implement the draw function.

//-----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);
}

As you can see, the only thing Button does is draw a rectangle with the implemented draw function, nothing special. Here comes the most exciting moment, let’s draw it in the main function! ! !

#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();
}

The above code comments are very clear, and also solved the problem we started (the problem of if disaster). You can see that I don't have an if in this branch of WM_LBUTTONDOWN. Let’s
Insert picture description here
test it.
Insert picture description here
When I click on the button on the left,
Insert picture description here
a blue ⚪ turns out. When I click on the button on the right, it’s another red ⚪
Insert picture description here

Not to mention that the code has increased, but would you try 20 buttons? Insert picture description here
Finished writing, slipped away...

Guess you like

Origin blog.csdn.net/qq_36323419/article/details/115266521