C++如何获取鼠标点击位置

 更新时间:2023年08月04日 10:00:06   作者:匿名用户__  
这篇文章主要介绍了C++如何获取鼠标点击位置问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

1.检测鼠标点击事件

GetAsyncKeyState函数可以检测按键点击事件

这里是它的函数原型:

SHORT_stdcall GetAsyncKeyState(int vKey);

我们首先要根据这个函数定义一个宏KEY_DOWN,这样可以方便以后的调用

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

对于他的取值,请看下表

常量名				   对应按键						取值
—————————————————————————————————————————————————————————
VK_LBUTTON             鼠标左键                      0x01
VK_RBUTTON             鼠标右键                      0x02
VK_CANCEL              Ctrl + Break                  0x03
VK_MBUTTON             鼠标中键                      0x04
VK_BACK                Backspace 键       		     0x08
VK_TAB                 Tab 键                        0x09
VK_RETURN              回车键                        0x0D
VK_SHIFT               Shift 键                      0x10
VK_CONTROL             Ctrl 键                       0x11
VK_MENU                Alt 键                        0x12
VK_PAUSE               Pause 键                      0x13
VK_CAPITAL             Caps Lock 键                  0x14
VK_ESCAPE              Esc 键                        0x1B
VK_SPACE               空格键         				 0x20
VK_PRIOR               Page Up 键                    0x21
VK_NEXT                Page Down 键                  0x22
VK_END                 End 键                        0x23
VK_HOME                Home 键                       0x24
VK_LEFT                左箭头键                      0x25
VK_UP                  上箭头键                      0x26
VK_RIGHT               右箭头键                      0x27
VK_DOWN                下箭头键                      0x28
VK_SNAPSHOT            Print Screen 键               0x2C
VK_Insert              Insert 键                     0x2D
VK_Delete              Delete 键                     0x2E
'0' – '9'              数字 0 - 9             0x30 - 0x39
'A' – 'Z'              字母 A - Z             0x41 - 0x5A
VK_LWIN                左WinKey(104键盘才有)         0x5B
VK_RWIN                右WinKey(104键盘才有)         0x5C
VK_APPS                AppsKey(104键盘才有)          0x5D
VK_NUMPAD0            小键盘 0 键                    0x60
VK_NUMPAD1            小键盘 1 键                    0x61
VK_NUMPAD2            小键盘 2 键                    0x62
VK_NUMPAD3            小键盘 3 键                    0x63
VK_NUMPAD4            小键盘 4 键                    0x64
VK_NUMPAD5            小键盘 5 键                    0x65
VK_NUMPAD6            小键盘 6 键                    0x66
VK_NUMPAD7            小键盘 7 键                    0x67
VK_NUMPAD8            小键盘 8 键                    0x68
VK_NUMPAD9            小键盘 9 键                    0x69
VK_F1 - VK_F24        功能键F1 – F24          0x70 - 0x87
VK_NUMLOCK            Num Lock 键                   0x90
VK_SCROLL             Scroll Lock 键                0x91

这个函数可以用来检测鼠标左键的按下,我们就需要这个,先来测试一下效果

#include <windows.h>                			//GetAsyncKeyState所需头文件
#include <iostream>
#define KEY_DOWN(VK_NONAME) ((GetAsyncKeyState(VK_NONAME) & 0x8000) ? 1:0)  //用来检测按键的点击事件
int main() {
	//----------移除快速编辑模式(对于win10用户)----------
	HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE);
	DWORD mode;
	GetConsoleMode(hStdin, &mode);
	mode &= ~ENABLE_QUICK_EDIT_MODE;
	SetConsoleMode(hStdin, mode);
	//----------循环检测----------
	while(1) {                      			//循环检测
		if(KEY_DOWN(VK_LBUTTON)) {  			//鼠标左键按下
			printf("key down!\n");
		}
		Sleep(20);                  			//等待20毫秒,减少CPU占用
	}
	return 0;
}

可以看到,每次我们点击鼠标左键都会输出key down!这就说明我们的程序成功了。

当然,如果你对其他的按键检测感兴趣,你也可以试试其他的。

那么接下来接下来就是获取鼠标点击时的位置了。

2.获取鼠标位置

那么如何获取鼠标的位置呢?

C++为我们提供了GetCursorPos这个函数,它可以用来获取鼠标在屏幕上的位置。

这个函数需要提供一个POINT类型的地址,像下面这样:

POINT p;
GetCursorPos(&p);

POINT类型包含int xint y两个变量,通过GetCursorPos函数就可以获取鼠标的位置,代码很简单,先来看一下效果:

#include <windows.h>                			//所需头文件
#include <iostream>
POINT p;
int main() {
	//----------循环检测----------
	while(1) {
		GetCursorPos(&p);                       //获取鼠标在屏幕上的位置
		printf("(%d,%d)\n",p.x,p.y);
		Sleep(20);                  			//等待20毫秒,减少CPU占用
	}
	return 0;
}

现在我们已经完成了已经完成了第二步,然后我们就要获取鼠标点击位置了。

3.获取鼠标点击位置

这个也是分简单,我们只需要把刚才的两段代码合起来就行了。

#include <windows.h>                			//GetAsyncKeyState所需头文件
#include <iostream>
#define KEY_DOWN(VK_NONAME) ((GetAsyncKeyState(VK_NONAME) & 0x8000) ? 1:0)  //用来检测按键的点击事件
POINT p;
int main() {
	//----------移除快速编辑模式(对于win10用户)----------
	HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE);
	DWORD mode;
	GetConsoleMode(hStdin, &mode);
	mode &= ~ENABLE_QUICK_EDIT_MODE;
	SetConsoleMode(hStdin, mode);
	//----------循环检测----------
	while(1) {                      			//循环检测
		if(KEY_DOWN(VK_LBUTTON)) {  			//鼠标左键按下
			GetCursorPos(&p);                   //获取鼠标在屏幕上的位置
			printf("key down (%d,%d)\n",p.x,p.y);
		}
		Sleep(100);                  			//等待100毫秒,减少CPU占用
	}
	return 0;
}

现在的程序已经基本上完成了 ,但是聪明的你可能会发现,这些坐标都是整个屏幕上的,如果我只想获取鼠标在该窗口上的位置呢?

这其实很简单,C++也为我们提供了这样一个函数ScreenToClient,它用来获取鼠标在指定窗口上的位置,其使用方法与之前的差不多:

POINT p;
GetCursorPos(&p);
ScreenToClient(h,&p);

在使用该函数之前,我们要先获取一下控制台窗口的句柄,用它来指定窗口;

HWND h=GetForegroundWindow();

其中,GetForegroundWindow函数用来获取最顶层窗口的句柄,这很适合我们的程序。

那么就先上代码吧!

#include <windows.h>                			//GetAsyncKeyState所需头文件
#include <iostream>
#define KEY_DOWN(VK_NONAME) ((GetAsyncKeyState(VK_NONAME) & 0x8000) ? 1:0)  //用来检测按键的点击事件
POINT p;
HWND h=GetForegroundWindow();
int main() {
	//----------移除快速编辑模式(对于win10用户)----------
	HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE);
	DWORD mode;
	GetConsoleMode(hStdin, &mode);
	mode &= ~ENABLE_QUICK_EDIT_MODE;
	SetConsoleMode(hStdin, mode);
	//----------循环检测----------
	while(1) {                      			//循环检测
		if(KEY_DOWN(VK_LBUTTON)) {  			//鼠标左键按下
			POINT p;
			GetCursorPos(&p);
			ScreenToClient(h,&p);               //获取鼠标在窗口上的位置
			printf("key down (%d,%d)\n",p.x,p.y);
		}
		Sleep(100);                  			//等待100毫秒,减少CPU占用
	}
	return 0;
}

现在输出的就是鼠标在控制台窗口上的位置了,但是如果需要像获取光标位置一样得到鼠标位置对应的控制台窗口上输出的坐标该怎样办呢?

首先我们要获取控制台字体的高和宽,像下面这样:

HANDLE hOutput;
hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_FONT_INFO consoleCurrentFont;
GetCurrentConsoleFont(hOutput, FALSE, &consoleCurrentFont);

GetStdHandle(STD_OUTPUT_HANDLE)用来获取窗口的输出句柄,将它储存到hOutput内,consoleCurrentFont用来储存字体的信息,用GetCurrentConsoleFont函数可以获取当前控制台的字体信息。

获取字体的高和宽就像下面这样:

consoleCurrentFont.dwFontSize.X			//宽
consoleCurrentFont.dwFontSize.Y			//高

然后用鼠标的位置除以这两个之就行了,话不多说,先上代码。

#include <windows.h>                			//GetAsyncKeyState所需头文件
#include <iostream>
#define KEY_DOWN(VK_NONAME) ((GetAsyncKeyState(VK_NONAME) & 0x8000) ? 1:0)  //用来检测按键的点击事件
POINT p;
HANDLE hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
HWND h=GetForegroundWindow();
CONSOLE_FONT_INFO consoleCurrentFont;
int main() {
	//----------移除快速编辑模式(对于win10用户)----------
	HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE);
	DWORD mode;
	GetConsoleMode(hStdin, &mode);
	mode &= ~ENABLE_QUICK_EDIT_MODE;
	SetConsoleMode(hStdin, mode);
	//----------循环检测----------
	while(1) {                      			//循环检测
		if(KEY_DOWN(VK_LBUTTON)) {  			//鼠标左键按下
			POINT p;
			GetCursorPos(&p);
			ScreenToClient(h,&p);               //获取鼠标在窗口上的位置
			GetCurrentConsoleFont(hOutput, FALSE, &consoleCurrentFont); //获取字体信息
			int x=p.x/=consoleCurrentFont.dwFontSize.X;
			int y=p.y/=consoleCurrentFont.dwFontSize.Y;
			printf("key down (%d,%d)\n",x,y);
		}
		Sleep(100);                  			//等待100毫秒,减少CPU占用
	}
	return 0;
}

4.彩蛋

学习了本次的内容,我们就来做一个简单的实例,真的很简单

4.1 实例:鼠标控制绘图

在写这个程序之前,我们先来了解一下几个函数:

void gotoxy(int x, int y) {
	COORD pos = {x,y};
	HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);// 获取标准输出设备句柄
	SetConsoleCursorPosition(hOut, pos);//两个参数分别是指定哪个窗体,具体位置
}

这个函数用来移动光标来输出。

void HideTheCursor() {
	CONSOLE_CURSOR_INFO cciCursor;
	HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
	if(GetConsoleCursorInfo(hStdOut, &cciCursor)) {
		cciCursor.bVisible = FALSE;
		SetConsoleCursorInfo(hStdOut, &cciCursor);
	}
}

这个函数用来隐藏光标,这能使绘图效果更佳。

现在我们就来编写程序吧:

#include <windows.h>                			//GetAsyncKeyState所需头文件
#include <iostream>
#define KEY_DOWN(VK_NONAME) ((GetAsyncKeyState(VK_NONAME) & 0x8000) ? 1:0)  //用来检测按键的点击事件
POINT p;
HANDLE hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
HWND h=GetForegroundWindow();
CONSOLE_FONT_INFO consoleCurrentFont;
//----------移动光标----------
void gotoxy(int x, int y) {
	COORD pos = {x,y};
	HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);// 获取标准输出设备句柄
	SetConsoleCursorPosition(hOut, pos);//两个参数分别是指定哪个窗体,具体位置
}
//----------隐藏光标----------
void HideTheCursor() {
	CONSOLE_CURSOR_INFO cciCursor;
	HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
	if(GetConsoleCursorInfo(hStdOut, &cciCursor)) {
		cciCursor.bVisible = FALSE;
		SetConsoleCursorInfo(hStdOut, &cciCursor);
	}
}
int main() {
	HideTheCursor();                            //隐藏光标
	//----------移除快速编辑模式(对于win10用户)----------
	HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE);
	DWORD mode;
	GetConsoleMode(hStdin, &mode);
	mode &= ~ENABLE_QUICK_EDIT_MODE;
	SetConsoleMode(hStdin, mode);
	//----------循环检测----------
	while(1) {                      			//循环检测
		if(KEY_DOWN(VK_LBUTTON)) {  			//鼠标左键按下
			POINT p;
			GetCursorPos(&p);
			ScreenToClient(h,&p);               //获取鼠标在窗口上的位置
			GetCurrentConsoleFont(hOutput, FALSE, &consoleCurrentFont); //获取字体信息
			int x=p.x/=consoleCurrentFont.dwFontSize.X;
			int y=p.y/=consoleCurrentFont.dwFontSize.Y;
			gotoxy(x,y);                        //移动光标置鼠标位置
			printf("@");                        //在鼠标位置输出
		}
		Sleep(10);                  			//延时
	}
	return 0;
}

在这里插入图片描述

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • 全排列算法的原理和实现代码

    全排列算法的原理和实现代码

    这篇文章主要介绍了全排列算法的原理和实现代码,全排列是将一组数按一定顺序进行排列,如果这组数有n个,那么全排列数为n!个,需要的朋友可以参考下
    2014-08-08
  • C++实现动态数组功能

    C++实现动态数组功能

    这篇文章主要为大家详细介绍了C++实现动态数组功能,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-11-11
  • C语言实现动态顺序表的实现代码

    C语言实现动态顺序表的实现代码

    这篇文章主要介绍了C语言实现动态顺序表的实现代码的相关资料,动态顺序表在内存中开辟一块空间,可以随我们数据数量的增多来扩容,需要的朋友可以参考下
    2017-08-08
  • 一篇文章带你入门C语言数据结构:绪论

    一篇文章带你入门C语言数据结构:绪论

    这篇文章主要介绍了C语言的数据解构基础,希望对广大的程序爱好者有所帮助,同时祝大家有一个好成绩,需要的朋友可以参考下,希望能给你带来帮助
    2021-08-08
  • c语言中的局部跳转及全局跳转功能

    c语言中的局部跳转及全局跳转功能

    本文介绍了C语言中的goto语句,以及如何使用setjmp和longjmp实现跨函数的跳转,详细讲解了setjmp和longjmp的使用方法和注意事项,以及使用这种全局跳转后变量状态的不确定性,感兴趣的朋友一起看看吧
    2024-09-09
  • C++扫雷游戏的简单制作

    C++扫雷游戏的简单制作

    这篇文章主要为大家详细介绍了C++扫雷游戏的简单制作,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-03-03
  • 使用C++17实现JSON库设计思路示例全解

    使用C++17实现JSON库设计思路示例全解

    这篇文章主要为大家介绍了使用C++17实现JSON库设计思路示例全解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-08-08
  • C++实现并行计算的两种方式

    C++实现并行计算的两种方式

    本文介绍了使用C++实现并行计算的两种方式,包括OpenMP和MPI,文中通过示例代码介绍的非常详细,需要的朋友们下面随着小编来一起学习学习吧
    2024-03-03
  • QT的QWebEngineView类知识点详细介绍

    QT的QWebEngineView类知识点详细介绍

    QWebEngineView是Qt框架中的组件,基于Chromium内核,支持HTML5、CSS3、JavaScript等Web技术,适用于嵌入网页内容到Qt应用程序,它提供了丰富的接口如加载、导航、与JavaScript交互等,并支持信号槽机制处理各种网页事件,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2024-10-10
  • C++图文并茂分析讲解内存管理

    C++图文并茂分析讲解内存管理

    本章主要介绍C语言与C++的内存管理,以C++的内存分布作为引入,介绍C++不同于C语言的内存管理方式(new delete对比 malloc free),感兴趣的朋友来看看吧
    2022-09-09

最新评论