277 lines
12 KiB
Plaintext
277 lines
12 KiB
Plaintext
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.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;
|
||
}
|