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 x
和int 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;
}
本次的教程就完成了,喜欢就关注一下吧。