【C++连点器二】进阶之路--Easy-X程序实现界面美化

书接上回:框架有了,功能好了,界面很垃(这里看上回

...

正如标题所说的,界面美化需要用到Easy-X库,没有的、不会配置的,可以默默离开了。

---------------->>这里请,去下载Easy-X


目录

书接上回:框架有了,功能好了,界面很垃(这里看上回)

主要框架:

先看效果: 

​编辑

代码来了:

 Button.h头文件

showUI.h头文件

MouseClicker.h源文件

重要部分解析

再见

后续内容


主要框架:

是的,正如你所看到的,上一期的框架并不适用,由于图形化的代码量过大,需要一个新的框架。

这一次,将采用1 + 2 的方式,即一个源文件,两个头文件。

源文件:MouseClicker.cpp

        void SetObjectsStyle();//包含界面文字颜色(部分)、文字背景、文字样式、背景颜色
        void SetWindowStyle();//包含窗口风格、样式
        void SetInterval();//点击间隔设置
        void KeyChoose();//点击按键设置
        void Setting();//包含功能设置,包括点击间隔、点击按键设置
        void Home();//主界面,包含连点功能

头文件:

        1.  Button.h(按钮坐标,按钮绘制)(前方大量结构体聚集地,接好)

        关键宏定义(很多宏定义源文件中也需要):

        #define WIDTH 350       //窗口宽度  
        #define HIGH  200       //窗口高度
        #define INTERVAL 20    //间隔(很杂,按钮间隔,按钮中文字间隔......)
        #define BUTTONW  100    //按钮宽度
        #define BUTTONH  40    //按钮高度
        #define ELLIPSEW 30    //圆角宽度
        #define ELLIPSEH 30    //圆角高度

        仅此文件要用到的变量:

        COLORREF COLOR = BLACK;

        //第一部分,各个按钮坐标(每一个包含:(int类型)topX,topY,bottomX,bottomY)

                struct Button_Setting

                struct Button_SetClickInterval

                struct Button_SetKey

                struct Button_Left

                struct Button_Middle

                struct Button_Right

                struct Button_Return

        //第二部分,各个按钮的绘制

                struct DrawButton

                包含:

                        void Setting();            //绘制:设置按钮
                        void SetClickInterval();  //绘制:设置点击间隔按钮
                        void SetKey();            //绘制:设置连点按键按钮
                        void SetLeftDown();       //绘制:设置连点按键为鼠标左键按钮
                        void SetMiddleDown();     //绘制:设置连点按键为鼠标中键按钮
                        void SetRightDown();      //绘制:设置连点按键为鼠标右键按钮
                        void Return();            //绘制:返回按钮

        2.showUI.h(界面绘制)(比较轻松)

        注意:他需要包含上一个头文件

        void showHome()

        void showKeyChoose()

        void showSetting()

 关系复杂,直接放图:

界面切换演示图

先看效果: 

 

代码来了:

 Button.h头文件
#pragma once
#ifndef BUTTON_H_
#define BUTTON_H_

#define WIDTH 350       //窗口宽度  
#define HIGH  200       //窗口高度
#define INTERVAL 20    //按钮间隔
#define BUTTONW  100    //按钮宽度
#define BUTTONH  40    //按钮高度
#define ELLIPSEW 30    //圆角宽度
#define ELLIPSEH 30    //圆角高度

COLORREF COLOR = BLACK;

//设置按钮
struct Button_Setting
{
	int topX    = INTERVAL;
	int topY    = HIGH - BUTTONH - INTERVAL;
	int bottomX = WIDTH - INTERVAL;
	int bottomY = HIGH - INTERVAL;
}B_Setting;

//功能设置按钮//
struct Button_SetClickInterval
{
	int topX    = INTERVAL;
	int topY    = INTERVAL;
	int bottomX = INTERVAL + BUTTONW;
	int bottomY = INTERVAL + BUTTONH;
}B_SetInterval;
struct Button_SetKey
{
	int topX    = 2 * INTERVAL + BUTTONW;
	int topY    = INTERVAL;
	int bottomX = 2 * BUTTONW + 2 * INTERVAL;
	int bottomY = BUTTONH + INTERVAL;
}B_SetKey;

//按键切换按钮//
struct Button_Left
{
	int topX    = INTERVAL;
	int topY    = INTERVAL;
	int bottomX = INTERVAL + BUTTONW;
	int bottomY = INTERVAL + BUTTONH;
}B_MouseL;
struct Button_Middle
{
	int topX    = INTERVAL;
	int topY    = 2 * INTERVAL + BUTTONH;
	int bottomX = INTERVAL + BUTTONW;
	int bottomY = 2 * INTERVAL + 2 * BUTTONH;
}B_MouseM;
struct Button_Right
{
	int topX    = INTERVAL;
	int topY    = 3 * INTERVAL + 2 * BUTTONH;
	int bottomX = INTERVAL + BUTTONW;
	int bottomY = 3 * INTERVAL + 3 * BUTTONH;
}B_MouseR;

//返回按钮//
struct Button_Return
{
	int topX    = WIDTH - BUTTONW - INTERVAL;
	int topY    = HIGH - BUTTONH - INTERVAL;
	int bottomX = WIDTH - INTERVAL;
	int bottomY = HIGH - INTERVAL;
}B_return;




//按钮绘制类
struct DrawButton
{
	void Setting();
	void SetClickInterval();  //绘制:设置点击间隔按钮
	void SetKey();            //绘制:设置连点按键按钮
	void SetLeftDown();       //绘制:设置连点按键为鼠标左键按钮
	void SetMiddleDown();     //绘制:设置连点按键为鼠标中键按钮
	void SetRightDown();      //绘制:设置连点按键为鼠标右键按钮
	void Return();            //绘制:返回按钮
}drawButton;

//绘制:设置按钮
void DrawButton::Setting()
{
	solidroundrect(B_Setting.topX, B_Setting.topY, B_Setting.bottomX, B_Setting.bottomY, ELLIPSEW, ELLIPSEH);
	settextcolor(COLOR);
	outtextxy((WIDTH - 2 * INTERVAL) / 2, B_Setting.topY + BUTTONH / 2 - 5, L"设置");
}

//绘制:设置点击间隔按钮
void DrawButton::SetClickInterval()
{
	solidroundrect(B_SetInterval.topX, B_SetInterval.topY, B_SetInterval.bottomX, B_SetInterval.bottomY, ELLIPSEW, ELLIPSEH);
	settextcolor(COLOR);
	outtextxy(B_SetInterval.topX, B_SetInterval.topY + BUTTONH / 2 - 5, L"设置点击间隔");
}

//绘制:设置连点按键按钮
void DrawButton::SetKey()
{
	solidroundrect(B_SetKey.topX, B_SetKey.topY, B_SetKey.bottomX, B_SetKey.bottomY, ELLIPSEW, ELLIPSEH);
	settextcolor(COLOR);
	outtextxy(B_SetKey.topX, B_SetKey.topY + BUTTONH / 2 - 5, L"切换点击按键");
}

//绘制:设置连点按键为鼠标左键按钮
void DrawButton::SetLeftDown()
{
	solidroundrect(B_MouseL.topX, B_MouseL.topY, B_MouseL.bottomX, B_MouseL.bottomY, ELLIPSEW, ELLIPSEH);
	settextcolor(COLOR);
	outtextxy(B_MouseL.topX + 15, B_MouseL.topY + BUTTONH / 2 - 5, L"鼠标左键");
}

//绘制:设置连点按键为鼠标中键按钮
void DrawButton::SetMiddleDown()
{
	solidroundrect(B_MouseM.topX, B_MouseM.topY, B_MouseM.bottomX, B_MouseM.bottomY, ELLIPSEW, ELLIPSEH);
	settextcolor(COLOR);
	outtextxy(B_MouseM.topX + 15, B_MouseM.topY + BUTTONH / 2 - 5, L"鼠标中键");
}

//绘制:设置连点按键为鼠标右键按钮
void DrawButton::SetRightDown()
{
	solidroundrect(B_MouseR.topX, B_MouseR.topY, B_MouseR.bottomX, B_MouseR.bottomY, ELLIPSEW, ELLIPSEH);
	settextcolor(COLOR);
	outtextxy(B_MouseR.topX + 15, B_MouseR.topY + BUTTONH / 2 - 5, L"鼠标右键");
}

//绘制:返回按钮
void DrawButton::Return()
{
	solidroundrect(B_return.topX, B_return.topY, B_return.bottomX, B_return.bottomY, ELLIPSEW, ELLIPSEH);
	settextcolor(COLOR);
	outtextxy(B_return.topX + BUTTONW / 2 - 15, B_return.topY + BUTTONH / 2 - 5, L"返回");
}
#endif // !BUTTON_H_
showUI.h头文件
#pragma once
#ifndef SHOWUI_H_
#define SHOWUI_H_

#include "Button.h"

#define TEXTINTERVAL (4 * INTERVAL)

extern int KeyDownNum;

void showHome()
{
	settextcolor(BLACK);
	outtextxy(TEXTINTERVAL, 40, L"按下[Alt键]开始连点");
	outtextxy(TEXTINTERVAL, 60, L"松开[Alt键]结束连点");
	if (KeyDownNum == 1)
	{
		outtextxy(TEXTINTERVAL, 80, L"当前连点按键:鼠标左键");
	}
	else if (KeyDownNum == 2)
	{
		outtextxy(TEXTINTERVAL, 80, L"当前连点按键:鼠标中键");
	}
	else outtextxy(TEXTINTERVAL, 80, L"当前连点按键:鼠标右键");
	drawButton.Setting();
}

void showKeyChoose()
{
	drawButton.SetLeftDown();
	drawButton.SetMiddleDown();
	drawButton.SetRightDown();
	drawButton.Return();
}

void showSetting()
{
	drawButton.SetClickInterval();
	drawButton.SetKey();
	drawButton.Return();
}
#endif // !SHOWUI_H_
MouseClicker.h源文件
#include <iostream>
#include <Windows.h>
#include <graphics.h>
#include "showUI.h"
#include "Button.h"

#define KEY_DOWN(VK_Key) ((GetAsyncKeyState(VK_Key) & 0x8000) ? 1:0)

using namespace std;

extern int KeyDownNum = 1;
DWORD KeyDownValue[3] = { MOUSEEVENTF_LEFTDOWN ,MOUSEEVENTF_MIDDLEDOWN,MOUSEEVENTF_RIGHTDOWN };
DWORD KeyUpValue[3] = { MOUSEEVENTF_LEFTUP,MOUSEEVENTF_MIDDLEUP,MOUSEEVENTF_RIGHTUP };

int Window = 1;
ExMessage msg;
wchar_t ClickInterval[9999] = { 51 };

void SetObjectsStyle();
void SetWindowStyle();
void SetInterval();
void KeyChoose();
void Setting();
void Home();

int main() {
	initgraph(WIDTH, HIGH);
	SetWindowStyle();
	SetObjectsStyle();
	cleardevice();
	Home();
	return 0;
}

void SetObjectsStyle()
{
	LOGFONT f;
	gettextstyle(&f);
	_tcscpy_s(f.lfFaceName, _T("宋体"));
	f.lfQuality = ANTIALIASED_QUALITY;
	settextstyle(&f);
	setbkcolor(WHITE);
	setfillcolor(GREEN);
	setbkmode(TRANSPARENT);
}

void SetWindowStyle()
{
	SetWindowText(GetHWnd(), L"  ");
	int GWStyle = (int)GetWindowLong(GetHWnd(), GWL_STYLE);
	SetWindowLong(GetHWnd(), GWL_STYLE, GWStyle & ~WS_SIZEBOX & ~WS_MAXIMIZEBOX & ~WS_MINIMIZEBOX);
	SetWindowPos(GetHWnd(), HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE);
}

void SetInterval()
{
	InputBox(ClickInterval, 9999, L"输入点击间隔(单位:毫秒)(默认数值为50)", L"", L"在这里输入点击间隔(无需单位)", WIDTH, HIGH / 2, false);
	if (_wtoi(ClickInterval) < 1)
	{
		MessageBox(GetHWnd(), L"点击间隔必须大于1", L"数值警告", MB_OK | MB_SETFOREGROUND | MB_TOPMOST);
		return SetInterval();
	}
}

void KeyChoose()
{
	Window = 2;
	cleardevice();
	showKeyChoose();
	while (1)
	{
		if (peekmessage(&msg, EM_MOUSE))
		{
			if (Window == 2)
			{
				if (msg.message == WM_LBUTTONUP && msg.x > B_MouseL.topX && msg.y > B_MouseL.topY && msg.x < B_MouseL.bottomX && msg.y < B_MouseL.bottomY)
				{
					KeyDownNum = 1;
					MessageBox(GetHWnd(), L"已将连点按键改为鼠标左键", L"", MB_OK | MB_TOPMOST | MB_SETFOREGROUND);
				}
				else if (msg.message == WM_LBUTTONUP && msg.x > B_MouseM.topX && msg.y > B_MouseM.topY && msg.x < B_MouseM.bottomX && msg.y < B_MouseM.bottomY)
				{
					KeyDownNum = 2;
					MessageBox(GetHWnd(), L"已将连点按键改为鼠标中键", L"", MB_OK | MB_TOPMOST | MB_SETFOREGROUND);
				}
				else if (msg.message == WM_LBUTTONUP && msg.x > B_MouseR.topX && msg.y > B_MouseR.topY && msg.x < B_MouseR.bottomX && msg.y < B_MouseR.bottomY)
				{
					KeyDownNum = 3;
					MessageBox(GetHWnd(), L"已将连点按键改为鼠标右键", L"", MB_OK | MB_TOPMOST | MB_SETFOREGROUND);
				}
				else if (msg.message == WM_LBUTTONUP && msg.x > B_return.topX && msg.y > B_return.topY && msg.x < B_return.bottomX && msg.y < B_return.bottomY)
				{
					return Setting();
				}
			}
		}
		Sleep(1);
	}
}

void Setting()
{
	Window = 3;
	cleardevice();
	showSetting();
	while (1)
	{
		if (peekmessage(&msg, EM_MOUSE))
		{
			if (Window == 3)
			{
				if (msg.message == WM_LBUTTONUP && msg.x > B_SetInterval.topX && msg.y > B_SetInterval.topY && msg.x < B_SetInterval.bottomX && msg.y < B_SetInterval.bottomY)
				{
					SetInterval();
				}
				else if (msg.message == WM_LBUTTONUP && msg.x > B_SetKey.topX && msg.y > B_SetKey.topY && msg.x < B_SetKey.bottomX && msg.y < B_SetKey.bottomY)
				{
					KeyChoose();
				}
				else if (msg.message == WM_LBUTTONUP && msg.x > B_return.topX && msg.y > B_return.topY && msg.x < B_return.bottomX && msg.y < B_return.bottomY)
				{
					return Home();
				}
			}
		}
		Sleep(1);
	}
}

void Home()
{
	Window = 1;
	cleardevice();
	showHome();
	while (true)
	{
		while (KEY_DOWN(18))
		{
			if (Window == 1)
			{
				Sleep(_wtoi(ClickInterval) - 1);
				mouse_event(KeyDownValue[KeyDownNum - 1], 0, 0, 0, 0);
				mouse_event(KeyUpValue[KeyDownNum - 1], 0, 0, 0, 0);
				mouse_event(KeyDownValue[KeyDownNum - 1], 0, 0, 0, 0);
				mouse_event(KeyUpValue[KeyDownNum - 1], 0, 0, 0, 0);
			}
		}
		if (peekmessage(&msg, EM_MOUSE))
		{
			if (Window == 1)
			{
				if (msg.message == WM_LBUTTONUP && msg.x > B_Setting.topX && msg.y > B_Setting.topY && msg.x < B_Setting.bottomX && msg.y < B_Setting.bottomY)
				{
					Setting();
				}
			}
		}
		Sleep(1);
	}
}

重要部分解析

与上一期不同,这次KeyDownNum变量使用了extern关键字,这使得它可以再头文件showUI.h中调用(范围大一点就是跨文件调用)

通过操作ExMessage类型变量msg来实现鼠标与按钮的交互。

mouse_event()实现了模拟鼠标点击(也可以使用PostMessage(),SendMessage()不建议使用,返回较慢,会影响连点器的性能(其实影响也不大,毕竟程序本身的量就不大))

peekmessage()返回一个布偶值,当检测到用户按下指定按键是,返回true,否则返回false

获取鼠标的实时坐标(msg.x, msg.y),判断是否位于圆角矩形(按钮)内,同时判断鼠标按键是否抬起,如果两项条件同时满足,执行跳转或其他指令

通过变量Window标记当前窗口,确保按钮不会重叠,准确的说是由于界面切换是靠cleardevice()函数进行清屏实现的,当我重绘窗口后,上一个窗口按钮的点击范围依然存在,只不过没有被绘制,所以当我在当前窗口点击按钮时,会触发两种效果,或只触发一种效果。(如图所示)

值得注意的是,InputBox()在Easy-X中的定义如下:

bool InputBox(LPTSTR pString, int nMaxCount, LPCTSTR pPrompt = NULL, LPCTSTR pTitle = NULL, LPCTSTR pDefault = NULL, int width = 0, int height = 0, bool bOnlyOK = true);

 可见,InputBox()返回的是一个布尔(嘿,之前有一篇写了布偶)值,所以如何获取到啊用户输入的内容就成了难题,好在C++提供了_wtoi()函数,可将用户输入的内容(本质是字符串)转换为数字。(完美解决)

另一个值得注意的点是InputBox中的第一个参数,其类型为LPTSTR,在Visual Studio项目属性零更改的情况下,我们无法使用stringchar类型(实质是窄字符)的变量,并且试过的都知道,其传入的是一个指针,在这三个条件下,只剩下一种选择:wchar_t类型数组(本质和指针差不多,但方便初始化,对新手十分友好)。

再见

系列完结,

后续内容

1.番外制作中...(明年出吧,WinAPI太难写了)

2.代码、内容优化(毕竟谁都不愿意看到屎山或极度抽象的烂代码吧)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值