C++如何獲取鼠標(biāo)點(diǎn)擊位置
1.檢測(cè)鼠標(biāo)點(diǎn)擊事件
GetAsyncKeyState函數(shù)可以檢測(cè)按鍵點(diǎn)擊事件
這里是它的函數(shù)原型:
SHORT_stdcall GetAsyncKeyState(int vKey);
我們首先要根據(jù)這個(gè)函數(shù)定義一個(gè)宏KEY_DOWN,這樣可以方便以后的調(diào)用
#define KEY_DOWN(VK_NONAME) ((GetAsyncKeyState(VK_NONAME) & 0x8000) ? 1:0)
對(duì)于他的取值,請(qǐng)看下表
常量名 對(duì)應(yīng)按鍵 取值 ————————————————————————————————————————————————————————— VK_LBUTTON 鼠標(biāo)左鍵 0x01 VK_RBUTTON 鼠標(biāo)右鍵 0x02 VK_CANCEL Ctrl + Break 0x03 VK_MBUTTON 鼠標(biāo)中鍵 0x04 VK_BACK Backspace 鍵 0x08 VK_TAB Tab 鍵 0x09 VK_RETURN 回車(chē)鍵 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' 數(shù)字 0 - 9 0x30 - 0x39 'A' – 'Z' 字母 A - Z 0x41 - 0x5A VK_LWIN 左WinKey(104鍵盤(pán)才有) 0x5B VK_RWIN 右WinKey(104鍵盤(pán)才有) 0x5C VK_APPS AppsKey(104鍵盤(pán)才有) 0x5D VK_NUMPAD0 小鍵盤(pán) 0 鍵 0x60 VK_NUMPAD1 小鍵盤(pán) 1 鍵 0x61 VK_NUMPAD2 小鍵盤(pán) 2 鍵 0x62 VK_NUMPAD3 小鍵盤(pán) 3 鍵 0x63 VK_NUMPAD4 小鍵盤(pán) 4 鍵 0x64 VK_NUMPAD5 小鍵盤(pán) 5 鍵 0x65 VK_NUMPAD6 小鍵盤(pán) 6 鍵 0x66 VK_NUMPAD7 小鍵盤(pán) 7 鍵 0x67 VK_NUMPAD8 小鍵盤(pán) 8 鍵 0x68 VK_NUMPAD9 小鍵盤(pán) 9 鍵 0x69 VK_F1 - VK_F24 功能鍵F1 – F24 0x70 - 0x87 VK_NUMLOCK Num Lock 鍵 0x90 VK_SCROLL Scroll Lock 鍵 0x91
這個(gè)函數(shù)可以用來(lái)檢測(cè)鼠標(biāo)左鍵的按下,我們就需要這個(gè),先來(lái)測(cè)試一下效果
#include <windows.h> //GetAsyncKeyState所需頭文件
#include <iostream>
#define KEY_DOWN(VK_NONAME) ((GetAsyncKeyState(VK_NONAME) & 0x8000) ? 1:0) //用來(lái)檢測(cè)按鍵的點(diǎn)擊事件
int main() {
//----------移除快速編輯模式(對(duì)于win10用戶)----------
HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE);
DWORD mode;
GetConsoleMode(hStdin, &mode);
mode &= ~ENABLE_QUICK_EDIT_MODE;
SetConsoleMode(hStdin, mode);
//----------循環(huán)檢測(cè)----------
while(1) { //循環(huán)檢測(cè)
if(KEY_DOWN(VK_LBUTTON)) { //鼠標(biāo)左鍵按下
printf("key down!\n");
}
Sleep(20); //等待20毫秒,減少CPU占用
}
return 0;
}可以看到,每次我們點(diǎn)擊鼠標(biāo)左鍵都會(huì)輸出key down!這就說(shuō)明我們的程序成功了。
當(dāng)然,如果你對(duì)其他的按鍵檢測(cè)感興趣,你也可以試試其他的。
那么接下來(lái)接下來(lái)就是獲取鼠標(biāo)點(diǎn)擊時(shí)的位置了。
2.獲取鼠標(biāo)位置
那么如何獲取鼠標(biāo)的位置呢?
C++為我們提供了GetCursorPos這個(gè)函數(shù),它可以用來(lái)獲取鼠標(biāo)在屏幕上的位置。
這個(gè)函數(shù)需要提供一個(gè)POINT類型的地址,像下面這樣:
POINT p; GetCursorPos(&p);
POINT類型包含int x和int y兩個(gè)變量,通過(guò)GetCursorPos函數(shù)就可以獲取鼠標(biāo)的位置,代碼很簡(jiǎn)單,先來(lái)看一下效果:
#include <windows.h> //所需頭文件
#include <iostream>
POINT p;
int main() {
//----------循環(huán)檢測(cè)----------
while(1) {
GetCursorPos(&p); //獲取鼠標(biāo)在屏幕上的位置
printf("(%d,%d)\n",p.x,p.y);
Sleep(20); //等待20毫秒,減少CPU占用
}
return 0;
}現(xiàn)在我們已經(jīng)完成了已經(jīng)完成了第二步,然后我們就要獲取鼠標(biāo)點(diǎn)擊位置了。
3.獲取鼠標(biāo)點(diǎn)擊位置
這個(gè)也是分簡(jiǎn)單,我們只需要把剛才的兩段代碼合起來(lái)就行了。
#include <windows.h> //GetAsyncKeyState所需頭文件
#include <iostream>
#define KEY_DOWN(VK_NONAME) ((GetAsyncKeyState(VK_NONAME) & 0x8000) ? 1:0) //用來(lái)檢測(cè)按鍵的點(diǎn)擊事件
POINT p;
int main() {
//----------移除快速編輯模式(對(duì)于win10用戶)----------
HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE);
DWORD mode;
GetConsoleMode(hStdin, &mode);
mode &= ~ENABLE_QUICK_EDIT_MODE;
SetConsoleMode(hStdin, mode);
//----------循環(huán)檢測(cè)----------
while(1) { //循環(huán)檢測(cè)
if(KEY_DOWN(VK_LBUTTON)) { //鼠標(biāo)左鍵按下
GetCursorPos(&p); //獲取鼠標(biāo)在屏幕上的位置
printf("key down (%d,%d)\n",p.x,p.y);
}
Sleep(100); //等待100毫秒,減少CPU占用
}
return 0;
}現(xiàn)在的程序已經(jīng)基本上完成了 ,但是聰明的你可能會(huì)發(fā)現(xiàn),這些坐標(biāo)都是整個(gè)屏幕上的,如果我只想獲取鼠標(biāo)在該窗口上的位置呢?
這其實(shí)很簡(jiǎn)單,C++也為我們提供了這樣一個(gè)函數(shù)ScreenToClient,它用來(lái)獲取鼠標(biāo)在指定窗口上的位置,其使用方法與之前的差不多:
POINT p; GetCursorPos(&p); ScreenToClient(h,&p);
在使用該函數(shù)之前,我們要先獲取一下控制臺(tái)窗口的句柄,用它來(lái)指定窗口;
HWND h=GetForegroundWindow();
其中,GetForegroundWindow函數(shù)用來(lái)獲取最頂層窗口的句柄,這很適合我們的程序。
那么就先上代碼吧!
#include <windows.h> //GetAsyncKeyState所需頭文件
#include <iostream>
#define KEY_DOWN(VK_NONAME) ((GetAsyncKeyState(VK_NONAME) & 0x8000) ? 1:0) //用來(lái)檢測(cè)按鍵的點(diǎn)擊事件
POINT p;
HWND h=GetForegroundWindow();
int main() {
//----------移除快速編輯模式(對(duì)于win10用戶)----------
HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE);
DWORD mode;
GetConsoleMode(hStdin, &mode);
mode &= ~ENABLE_QUICK_EDIT_MODE;
SetConsoleMode(hStdin, mode);
//----------循環(huán)檢測(cè)----------
while(1) { //循環(huán)檢測(cè)
if(KEY_DOWN(VK_LBUTTON)) { //鼠標(biāo)左鍵按下
POINT p;
GetCursorPos(&p);
ScreenToClient(h,&p); //獲取鼠標(biāo)在窗口上的位置
printf("key down (%d,%d)\n",p.x,p.y);
}
Sleep(100); //等待100毫秒,減少CPU占用
}
return 0;
}現(xiàn)在輸出的就是鼠標(biāo)在控制臺(tái)窗口上的位置了,但是如果需要像獲取光標(biāo)位置一樣得到鼠標(biāo)位置對(duì)應(yīng)的控制臺(tái)窗口上輸出的坐標(biāo)該怎樣辦呢?
首先我們要獲取控制臺(tái)字體的高和寬,像下面這樣:
HANDLE hOutput; hOutput = GetStdHandle(STD_OUTPUT_HANDLE); CONSOLE_FONT_INFO consoleCurrentFont; GetCurrentConsoleFont(hOutput, FALSE, &consoleCurrentFont);
GetStdHandle(STD_OUTPUT_HANDLE)用來(lái)獲取窗口的輸出句柄,將它儲(chǔ)存到hOutput內(nèi),consoleCurrentFont用來(lái)儲(chǔ)存字體的信息,用GetCurrentConsoleFont函數(shù)可以獲取當(dāng)前控制臺(tái)的字體信息。
獲取字體的高和寬就像下面這樣:
consoleCurrentFont.dwFontSize.X //寬 consoleCurrentFont.dwFontSize.Y //高
然后用鼠標(biāo)的位置除以這兩個(gè)之就行了,話不多說(shuō),先上代碼。
#include <windows.h> //GetAsyncKeyState所需頭文件
#include <iostream>
#define KEY_DOWN(VK_NONAME) ((GetAsyncKeyState(VK_NONAME) & 0x8000) ? 1:0) //用來(lái)檢測(cè)按鍵的點(diǎn)擊事件
POINT p;
HANDLE hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
HWND h=GetForegroundWindow();
CONSOLE_FONT_INFO consoleCurrentFont;
int main() {
//----------移除快速編輯模式(對(duì)于win10用戶)----------
HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE);
DWORD mode;
GetConsoleMode(hStdin, &mode);
mode &= ~ENABLE_QUICK_EDIT_MODE;
SetConsoleMode(hStdin, mode);
//----------循環(huán)檢測(cè)----------
while(1) { //循環(huán)檢測(cè)
if(KEY_DOWN(VK_LBUTTON)) { //鼠標(biāo)左鍵按下
POINT p;
GetCursorPos(&p);
ScreenToClient(h,&p); //獲取鼠標(biāo)在窗口上的位置
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.彩蛋
學(xué)習(xí)了本次的內(nèi)容,我們就來(lái)做一個(gè)簡(jiǎn)單的實(shí)例,真的很簡(jiǎn)單
4.1 實(shí)例:鼠標(biāo)控制繪圖
在寫(xiě)這個(gè)程序之前,我們先來(lái)了解一下幾個(gè)函數(shù):
void gotoxy(int x, int y) {
COORD pos = {x,y};
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);// 獲取標(biāo)準(zhǔn)輸出設(shè)備句柄
SetConsoleCursorPosition(hOut, pos);//兩個(gè)參數(shù)分別是指定哪個(gè)窗體,具體位置
}這個(gè)函數(shù)用來(lái)移動(dòng)光標(biāo)來(lái)輸出。
void HideTheCursor() {
CONSOLE_CURSOR_INFO cciCursor;
HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
if(GetConsoleCursorInfo(hStdOut, &cciCursor)) {
cciCursor.bVisible = FALSE;
SetConsoleCursorInfo(hStdOut, &cciCursor);
}
}這個(gè)函數(shù)用來(lái)隱藏光標(biāo),這能使繪圖效果更佳。
現(xiàn)在我們就來(lái)編寫(xiě)程序吧:
#include <windows.h> //GetAsyncKeyState所需頭文件
#include <iostream>
#define KEY_DOWN(VK_NONAME) ((GetAsyncKeyState(VK_NONAME) & 0x8000) ? 1:0) //用來(lái)檢測(cè)按鍵的點(diǎn)擊事件
POINT p;
HANDLE hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
HWND h=GetForegroundWindow();
CONSOLE_FONT_INFO consoleCurrentFont;
//----------移動(dòng)光標(biāo)----------
void gotoxy(int x, int y) {
COORD pos = {x,y};
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);// 獲取標(biāo)準(zhǔn)輸出設(shè)備句柄
SetConsoleCursorPosition(hOut, pos);//兩個(gè)參數(shù)分別是指定哪個(gè)窗體,具體位置
}
//----------隱藏光標(biāo)----------
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(); //隱藏光標(biāo)
//----------移除快速編輯模式(對(duì)于win10用戶)----------
HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE);
DWORD mode;
GetConsoleMode(hStdin, &mode);
mode &= ~ENABLE_QUICK_EDIT_MODE;
SetConsoleMode(hStdin, mode);
//----------循環(huán)檢測(cè)----------
while(1) { //循環(huán)檢測(cè)
if(KEY_DOWN(VK_LBUTTON)) { //鼠標(biāo)左鍵按下
POINT p;
GetCursorPos(&p);
ScreenToClient(h,&p); //獲取鼠標(biāo)在窗口上的位置
GetCurrentConsoleFont(hOutput, FALSE, &consoleCurrentFont); //獲取字體信息
int x=p.x/=consoleCurrentFont.dwFontSize.X;
int y=p.y/=consoleCurrentFont.dwFontSize.Y;
gotoxy(x,y); //移動(dòng)光標(biāo)置鼠標(biāo)位置
printf("@"); //在鼠標(biāo)位置輸出
}
Sleep(10); //延時(shí)
}
return 0;
}
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
C語(yǔ)言中結(jié)構(gòu)體的內(nèi)存對(duì)齊規(guī)則講解
C 數(shù)組允許定義可存儲(chǔ)相同類型數(shù)據(jù)項(xiàng)的變量,結(jié)構(gòu)是 C 編程中另一種用戶自定義的可用的數(shù)據(jù)類型,它允許你存儲(chǔ)不同類型的數(shù)據(jù)項(xiàng),本篇讓我們來(lái)了解C 的結(jié)構(gòu)體內(nèi)存對(duì)齊2022-05-05
教你Visual?Studio?2022如何新建一個(gè)C語(yǔ)言工程(圖文詳解)
這篇文章主要介紹了Visual?Studio?2022如何新建一個(gè)C語(yǔ)言工程,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-09-09
MySQL的內(nèi)存表的基礎(chǔ)學(xué)習(xí)教程
這篇文章主要介紹了MySQL的內(nèi)存表的基礎(chǔ)學(xué)習(xí)教程,包括內(nèi)存表的創(chuàng)建以及使用限制等等,需要的朋友可以參考下2015-12-12
C++ scoped_ptr 和 unique_ptr對(duì)比分析
本文介紹了C++中的`scoped_ptr`和`unique_ptr`,詳細(xì)比較了它們的特性、使用場(chǎng)景以及現(xiàn)代C++推薦的使用`unique_ptr`來(lái)管理獨(dú)占所有權(quán)的資源,感興趣的朋友跟隨小編一起看看吧2025-11-11

