C++如何獲取鼠標(biāo)點(diǎn)擊位置
1.檢測鼠標(biāo)點(diǎn)擊事件
GetAsyncKeyState
函數(shù)可以檢測按鍵點(diǎn)擊事件
這里是它的函數(shù)原型:
SHORT_stdcall GetAsyncKeyState(int vKey);
我們首先要根據(jù)這個函數(shù)定義一個宏KEY_DOWN
,這樣可以方便以后的調(diào)用
#define KEY_DOWN(VK_NONAME) ((GetAsyncKeyState(VK_NONAME) & 0x8000) ? 1:0)
對于他的取值,請看下表
常量名 對應(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 回車鍵 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鍵盤才有) 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
這個函數(shù)可以用來檢測鼠標(biāo)左鍵的按下,我們就需要這個,先來測試一下效果
#include <windows.h> //GetAsyncKeyState所需頭文件 #include <iostream> #define KEY_DOWN(VK_NONAME) ((GetAsyncKeyState(VK_NONAME) & 0x8000) ? 1:0) //用來檢測按鍵的點(diǎn)擊事件 int main() { //----------移除快速編輯模式(對于win10用戶)---------- HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE); DWORD mode; GetConsoleMode(hStdin, &mode); mode &= ~ENABLE_QUICK_EDIT_MODE; SetConsoleMode(hStdin, mode); //----------循環(huán)檢測---------- while(1) { //循環(huán)檢測 if(KEY_DOWN(VK_LBUTTON)) { //鼠標(biāo)左鍵按下 printf("key down!\n"); } Sleep(20); //等待20毫秒,減少CPU占用 } return 0; }
可以看到,每次我們點(diǎn)擊鼠標(biāo)左鍵都會輸出key down!
這就說明我們的程序成功了。
當(dāng)然,如果你對其他的按鍵檢測感興趣,你也可以試試其他的。
那么接下來接下來就是獲取鼠標(biāo)點(diǎn)擊時的位置了。
2.獲取鼠標(biāo)位置
那么如何獲取鼠標(biāo)的位置呢?
C++為我們提供了GetCursorPos
這個函數(shù),它可以用來獲取鼠標(biāo)在屏幕上的位置。
這個函數(shù)需要提供一個POINT
類型的地址,像下面這樣:
POINT p; GetCursorPos(&p);
POINT
類型包含int x
和int y
兩個變量,通過GetCursorPos
函數(shù)就可以獲取鼠標(biāo)的位置,代碼很簡單,先來看一下效果:
#include <windows.h> //所需頭文件 #include <iostream> POINT p; int main() { //----------循環(huán)檢測---------- 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)擊位置
這個也是分簡單,我們只需要把剛才的兩段代碼合起來就行了。
#include <windows.h> //GetAsyncKeyState所需頭文件 #include <iostream> #define KEY_DOWN(VK_NONAME) ((GetAsyncKeyState(VK_NONAME) & 0x8000) ? 1:0) //用來檢測按鍵的點(diǎn)擊事件 POINT p; int main() { //----------移除快速編輯模式(對于win10用戶)---------- HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE); DWORD mode; GetConsoleMode(hStdin, &mode); mode &= ~ENABLE_QUICK_EDIT_MODE; SetConsoleMode(hStdin, mode); //----------循環(huán)檢測---------- while(1) { //循環(huán)檢測 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)基本上完成了 ,但是聰明的你可能會發(fā)現(xiàn),這些坐標(biāo)都是整個屏幕上的,如果我只想獲取鼠標(biāo)在該窗口上的位置呢?
這其實很簡單,C++也為我們提供了這樣一個函數(shù)ScreenToClient
,它用來獲取鼠標(biāo)在指定窗口上的位置,其使用方法與之前的差不多:
POINT p; GetCursorPos(&p); ScreenToClient(h,&p);
在使用該函數(shù)之前,我們要先獲取一下控制臺窗口的句柄,用它來指定窗口;
HWND h=GetForegroundWindow();
其中,GetForegroundWindow
函數(shù)用來獲取最頂層窗口的句柄,這很適合我們的程序。
那么就先上代碼吧!
#include <windows.h> //GetAsyncKeyState所需頭文件 #include <iostream> #define KEY_DOWN(VK_NONAME) ((GetAsyncKeyState(VK_NONAME) & 0x8000) ? 1:0) //用來檢測按鍵的點(diǎn)擊事件 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); //----------循環(huán)檢測---------- while(1) { //循環(huán)檢測 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)在控制臺窗口上的位置了,但是如果需要像獲取光標(biāo)位置一樣得到鼠標(biāo)位置對應(yīng)的控制臺窗口上輸出的坐標(biāo)該怎樣辦呢?
首先我們要獲取控制臺字體的高和寬,像下面這樣:
HANDLE hOutput; hOutput = GetStdHandle(STD_OUTPUT_HANDLE); CONSOLE_FONT_INFO consoleCurrentFont; GetCurrentConsoleFont(hOutput, FALSE, &consoleCurrentFont);
GetStdHandle(STD_OUTPUT_HANDLE)
用來獲取窗口的輸出句柄,將它儲存到hOutput
內(nèi),consoleCurrentFont
用來儲存字體的信息,用GetCurrentConsoleFont
函數(shù)可以獲取當(dāng)前控制臺的字體信息。
獲取字體的高和寬就像下面這樣:
consoleCurrentFont.dwFontSize.X //寬 consoleCurrentFont.dwFontSize.Y //高
然后用鼠標(biāo)的位置除以這兩個之就行了,話不多說,先上代碼。
#include <windows.h> //GetAsyncKeyState所需頭文件 #include <iostream> #define KEY_DOWN(VK_NONAME) ((GetAsyncKeyState(VK_NONAME) & 0x8000) ? 1:0) //用來檢測按鍵的點(diǎn)擊事件 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); //----------循環(huán)檢測---------- while(1) { //循環(huán)檢測 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)容,我們就來做一個簡單的實例,真的很簡單
4.1 實例:鼠標(biāo)控制繪圖
在寫這個程序之前,我們先來了解一下幾個函數(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);//兩個參數(shù)分別是指定哪個窗體,具體位置 }
這個函數(shù)用來移動光標(biāo)來輸出。
void HideTheCursor() { CONSOLE_CURSOR_INFO cciCursor; HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE); if(GetConsoleCursorInfo(hStdOut, &cciCursor)) { cciCursor.bVisible = FALSE; SetConsoleCursorInfo(hStdOut, &cciCursor); } }
這個函數(shù)用來隱藏光標(biāo),這能使繪圖效果更佳。
現(xiàn)在我們就來編寫程序吧:
#include <windows.h> //GetAsyncKeyState所需頭文件 #include <iostream> #define KEY_DOWN(VK_NONAME) ((GetAsyncKeyState(VK_NONAME) & 0x8000) ? 1:0) //用來檢測按鍵的點(diǎn)擊事件 POINT p; HANDLE hOutput = GetStdHandle(STD_OUTPUT_HANDLE); HWND h=GetForegroundWindow(); CONSOLE_FONT_INFO consoleCurrentFont; //----------移動光標(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);//兩個參數(shù)分別是指定哪個窗體,具體位置 } //----------隱藏光標(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) //----------移除快速編輯模式(對于win10用戶)---------- HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE); DWORD mode; GetConsoleMode(hStdin, &mode); mode &= ~ENABLE_QUICK_EDIT_MODE; SetConsoleMode(hStdin, mode); //----------循環(huán)檢測---------- while(1) { //循環(huán)檢測 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); //移動光標(biāo)置鼠標(biāo)位置 printf("@"); //在鼠標(biāo)位置輸出 } Sleep(10); //延時 } return 0; }
總結(jié)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
C語言實現(xiàn)動態(tài)順序表的實現(xiàn)代碼
這篇文章主要介紹了C語言實現(xiàn)動態(tài)順序表的實現(xiàn)代碼的相關(guān)資料,動態(tài)順序表在內(nèi)存中開辟一塊空間,可以隨我們數(shù)據(jù)數(shù)量的增多來擴(kuò)容,需要的朋友可以參考下2017-08-08一篇文章帶你入門C語言數(shù)據(jù)結(jié)構(gòu):緒論
這篇文章主要介紹了C語言的數(shù)據(jù)解構(gòu)基礎(chǔ),希望對廣大的程序愛好者有所幫助,同時祝大家有一個好成績,需要的朋友可以參考下,希望能給你帶來幫助2021-08-08c語言中的局部跳轉(zhuǎn)及全局跳轉(zhuǎn)功能
本文介紹了C語言中的goto語句,以及如何使用setjmp和longjmp實現(xiàn)跨函數(shù)的跳轉(zhuǎn),詳細(xì)講解了setjmp和longjmp的使用方法和注意事項,以及使用這種全局跳轉(zhuǎn)后變量狀態(tài)的不確定性,感興趣的朋友一起看看吧2024-09-09使用C++17實現(xiàn)JSON庫設(shè)計思路示例全解
這篇文章主要為大家介紹了使用C++17實現(xiàn)JSON庫設(shè)計思路示例全解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-08-08QT的QWebEngineView類知識點(diǎn)詳細(xì)介紹
QWebEngineView是Qt框架中的組件,基于Chromium內(nèi)核,支持HTML5、CSS3、JavaScript等Web技術(shù),適用于嵌入網(wǎng)頁內(nèi)容到Qt應(yīng)用程序,它提供了豐富的接口如加載、導(dǎo)航、與JavaScript交互等,并支持信號槽機(jī)制處理各種網(wǎng)頁事件,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下2024-10-10