关于 c++ 控制台鼠标化操作
  • 板块学术版
  • 楼主heveral
  • 当前回复3
  • 已保存回复3
  • 发布时间2021/8/17 15:41
  • 上次更新2023/11/4 10:19:35
查看原帖
关于 c++ 控制台鼠标化操作
485129
heveral楼主2021/8/17 15:41

一个学习c++的人,难免会做亿些小游戏来消遣时间,在这里,我讲解一下如何让你的控制台游戏完全鼠标化.

首先,先给大家看一下执行鼠标操作的必备头文件

#include<windows.h>
#define KEY_DOWN(VK_NONAME) ((GetAsyncKeyState(VK_NONAME) & 0x8000) ? 1:0)
CONSOLE_FONT_INFO consoleCurrentFont;
  

然后进入正题

首先我们需要解除控制台的快速编译功能,并且隐藏控制台光标(就是程序运行时那个一闪一闪的东西),下面是对应代码

HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE);  
    DWORD mode;  
    GetConsoleMode(hStdin, &mode);  
	mode &= ~ENABLE_QUICK_EDIT_MODE;  //移除快速编辑模式
	mode &= ~ENABLE_INSERT_MODE;      //移除插入模式
    mode &= ~ENABLE_MOUSE_INPUT;
    SetConsoleMode(hStdin, mode);  
	CONSOLE_CURSOR_INFO cursor_info={1,0};
	SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE),&cursor_info);

到这里,你的开始准备工作还没有做完!

你需要进行一下鼠标矫正

struct
{
	LONG x=-1,y=-1,lest_x=-1,lest_y=-1;
	double real_x,real_y;
	POINT pt= {0,0}; 
    
    void check_mouse() 
    {  
		pt.y=pt.y/real_y,pt.x=(pt.x/real_x)/**2*/;
		if(pt.y<0)pt.y=0;
		if(pt.x<0)pt.x=0;
	}
	void mouse()
	{
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),15);
		GetCursorPos(&pt);    //获取鼠标当前位置 
		ScreenToClient(FindWindow("ConsoleWindowClass", NULL), &pt); 
		check_mouse();
		lest_y=y,lest_x=x;
		x=pt.x,y=pt.y;
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),7);
	} 
	void get_real_mouse()
    {
    	basic.cls();printf("鼠标校正,请用鼠标点击右下角的\"Hi\"");
		int x=rand()%10+35,y=rand()%10+75;
		basic.gt(x,y);printf("Hi");
		while(1)
		{
			GetCursorPos(&pt);    //获取鼠标当前位置
			ScreenToClient(FindWindow("ConsoleWindowClass", NULL), &pt); 
			if(KEY_DOWN(VK_LBUTTON)&&MessageBox(0,"您确定您点击了\"Hi\"吗?\n如果您没有点击此点可能会导致程序错乱.","鼠标校正",4)==IDYES)
			{
				real_x=pt.x/y,real_y=pt.y/x;
				break;
			}
		}
		basic.wait(500); basic.cls();
	}
}mouse;

里面的" void get_real_mouse() "就是上述的鼠标定位.

然而你把它拷贝到编译器中,编译器会提示你 缺少一些东西

是的,的确缺少.所以我补一下那些缺少的部分

struct
{ 
	void color(int all){SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),all);}
	void wait(int all){Sleep(all);}
	void cls(){system("cls");}
	void b(short hz,double time){Beep(hz,time);}
	void gt(int x,int y) 
	{
		COORD coord;
		coord.X=y;//Here, the order is reversed, otherwise, the output pointer is moved to Y row and X column
		coord.Y=x;
		HANDLE a=GetStdHandle(STD_OUTPUT_HANDLE);
		SetConsoleCursorPosition(a,coord);
	}
}basic; 

好了准备工作完毕!

接下来进入到最主要的环节

如何使用?

我给大家写了一个如何使用它例子

int choose(void) 
	{
    	string whats[10]={},title="",about_things="null";
		short how_long=0,wait_=1;
		for(int i=1;i<=9;i++)
		{
			if(whats[i]!="")how_long++;
			else break;
		}
		int choose; 
		while(1) 
		{
			choose=-1; 
			basic.gt(1,0);
			mouse.mouse();
			if(mouse.y==1)choose=1;
			printf("%s",title.c_str()); 
			if(choose==1){basic.color(16+7);printf("(?)\n");} 
			else {basic.color(7);printf("     \n");} 
			short x=1;
			for(int i=1;i<=how_long;i++)
			{
				x++;
				if(mouse.y==x)choose=x;
				if(choose==i+1)basic.color(16*15);
				else basic.color(7);
				printf("%s\n",whats[i].c_str()); 
			}
			basic.color(0);printf("\n---"); 
			if(wait_==1){basic.wait(500);wait_=0;}
			if(KEY_DOWN(VK_LBUTTON)&&choose>1)break;
			else if(KEY_DOWN(VK_LBUTTON)&&choose==1)
			{
				string about="关于"+title;
				MessageBox(0,about_things.c_str(),about.c_str(),MB_OK);
			} 
		}
		for(int i=1;i<=9;i++)whats[i]="";
		title="",about_things="null";
		basic.color(7);
		basic.cls();
		return choose-1; 
	}

我讲解一下这个代码的用途 string whats[10]={},title="",about_things="null";

这个是按键内容(string whats[10]),选择界面的标题(string tittle),和关于标题的介绍(string about_things)

其余的就是基础代码了大家可以自行理解 其实我懒得打字

这个大体的运行效果就是显示一排按键,然后当你点击其中任意一个按键后会返回一个对应按键的值

最后

我把这些代码连接在一起,方便大家白嫖学习

#include<bits/stdc++.h>
#include<ctime>
#include<windows.h>
#include<stdio.h>
#include<conio.h>
#include<iostream>
#include<cstdio>
#include<time.h>
#define KEY_DOWN(VK_NONAME) ((GetAsyncKeyState(VK_NONAME) & 0x8000) ? 1:0)
CONSOLE_FONT_INFO consoleCurrentFont;
using namespace std;
string user_name;
struct
{
	void color(int all){SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),all);}
	void wait(int all){Sleep(all);}
	void cls(){system("cls");}
	void b(short hz,double time){Beep(hz,time);}
	void gt(int x,int y)
	{
		COORD coord;
		coord.X=y;//Here, the order is reversed, otherwise, the output pointer is moved to Y row and X column
		coord.Y=x;
		HANDLE a=GetStdHandle(STD_OUTPUT_HANDLE);
		SetConsoleCursorPosition(a,coord);
	}
}basic;
struct
{
	LONG x=-1,y=-1,lest_x=-1,lest_y=-1;
	double real_x,real_y;
	HANDLE hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
    POINT pt= {0,0};

    void check_mouse()
    {
    	//GetCurrentConsoleFont(hOutput, FALSE, &consoleCurrentFont); //获取字体信息
		//pt.y=((pt.y/=consoleCurrentFont.dwFontSize.Y)/1.2)+1;
		//pt.x=(pt.x/=consoleCurrentFont.dwFontSize.X)/1.25;
		pt.y=pt.y/real_y,pt.x=(pt.x/real_x)/**2*/;
		if(pt.y<0)pt.y=0;
		if(pt.x<0)pt.x=0;
	}
	void mouse()
	{
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),15);
		GetCursorPos(&pt);    //获取鼠标当前位置
		ScreenToClient(FindWindow("ConsoleWindowClass", NULL), &pt);
		check_mouse();
		lest_y=y,lest_x=x;
		x=pt.x,y=pt.y;
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),7);
	}
	void get_real_mouse()
    {
    	basic.cls();printf("鼠标校正,请用鼠标点击右下角的\"Hi\"");
		int x=rand()%10+35,y=rand()%10+75;
		basic.gt(x,y);printf("Hi");
		while(1)
		{
			GetCursorPos(&pt);    //获取鼠标当前位置
			ScreenToClient(FindWindow("ConsoleWindowClass", NULL), &pt);
			if(KEY_DOWN(VK_LBUTTON)&&MessageBox(0,"您确定您点击了\"Hi\"吗?\n如果您没有点击此点可能会导致程序错乱.","鼠标校正",4)==IDYES)
			{
				real_x=pt.x/y,real_y=pt.y/x;
				break;
			}
		}
		basic.wait(500); basic.cls();
	}
}mouse;
struct
{//移动库
	int num_get()
	{
		int num=0,ans=1,fu=0;
		int life[10]={};
		short now_key,key,lk;
		for(int i=1;i<=5;i++)
		{
			now_key=(int)getch()-48;
			key=now_key+48;
			if(key==13)break;
			else if(now_key==-40)
			{
				if(lk!=49)
				{
					i=0,ans=0,num=0,fu=0;
					for(int q=0;q<=9;q++)life[q]=0;
					printf("(重新输入)");
				}
			}
			else if(key==45){ fu=1,i--;printf("(此数已经设定为负数)");}
			else if(now_key>9||now_key<0)i--;
			else printf("%i",now_key);
			lk=now_key;
			life[i]=now_key,ans++;
		}
		int d=1;
		//for(int i=1;i<=ans;i++)d=d*10;
		for(int i=ans;i>=1;i--)
		{
			num=num+life[i]*d;
			d=d*10;
		}
		if(fu==1)num=num*-1;
		return num/10;
	}
	string whats[10]={},title="",about_things="null";
	int ai_choose(void)
	{
		basic.cls();
		short how_long=0,wait_=1;
		for(int i=1;i<=9;i++)
		{
			if(whats[i]!="")how_long++;
			else break;
		}
		int choose;
		while(1)
		{
			choose=-1;
			basic.gt(1,0);
			mouse.mouse();
			if(mouse.y==1)choose=1;
			printf("%s",title.c_str());
			if(choose==1){basic.color(16+7);printf("(?)\n");}
			else {basic.color(7);printf("     \n");}
			short x=1;
			for(int i=1;i<=how_long;i++)
			{
				x++;
				if(mouse.y==x)choose=x;
				if(choose==i+1)basic.color(16*15);
				else basic.color(7);
				printf("%s\n",whats[i].c_str());
			}
			if(wait_==1){basic.wait(500);wait_=0;}
			if(KEY_DOWN(VK_LBUTTON)&&choose>1)break;
			else if(KEY_DOWN(VK_LBUTTON)&&choose==1)
			{
				string about="关于"+title;
				if(about!="null")MessageBox(0,about_things.c_str(),about.c_str(),MB_OK);
			}
		}
		for(int i=1;i<=9;i++)whats[i]="";
		title="",about_things="null";
		basic.cls();
		return choose-1;
	}
}choose;
int main()
{
	system("mode con cols=150 lines=40");
	HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE);
    DWORD mode;
    GetConsoleMode(hStdin, &mode);
	mode &= ~ENABLE_QUICK_EDIT_MODE;  //移除快速编辑模式
	mode &= ~ENABLE_INSERT_MODE;      //移除插入模式
    mode &= ~ENABLE_MOUSE_INPUT;
    SetConsoleMode(hStdin, mode);
	CONSOLE_CURSOR_INFO cursor_info={1,0};
	SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE),&cursor_info);
	mouse.get_real_mouse();
	while(1)
	{
		choose.about_things="开始界面选择",choose.title="有什么好看的?",choose.whats[1]="开始游戏", choose.whats[2]="打开Pearl Harbor War官网", choose.whats[3]="关闭游戏";
		short a=choose.ai_choose();
		cout<<a;
	}
}


小结: 此鼠标操作有一个缺点:当你完成鼠标定位后不能修改控制台字体大小,一旦修改鼠标定位将失灵


大家拿走前请标明出处,感谢大家的配合!


文章来源:https://www.luogu.com.cn/blog/bailiwen1/guan-yu-c-kong-zhi-tai-shu-biao-hua-cao-zuo

2021/8/17 15:41
加载中...