我正在制作一个带有两个函数的事件处理程序,并使用它们来处理事件(特别是键盘和鼠标)。我正在使用GetCursorPosition
来获取鼠标单击事件上的当前鼠标位置,但是它始终返回0和0作为坐标。即使我正在检查以确保调用成功(通过返回值)。
据我通过搜索可知,GetCursorPosition
不需要任何类型的初始化。我正在冒险进入(个人)未知领域,所以我需要一点帮助。
有问题的功能:
void EventHandler::actOnPressedKeys() {
for (char key : keysToCheck) {
if ( GetAsyncKeyState(key) ) {
keyHandler(key);
}
}
for (char button : mButtonsToCheck) {
if ( GetAsyncKeyState(button) ) {
POINT p;
if ( !GetCursorPos(&p) ) {
throw std::runtime_error::runtime_error(
"Cannot get cursor position: " + GetLastError()
);
}
mouseHandler(button, p.x, p.y);
}
}
}
在单独线程的循环内调用。
我知道检测到鼠标按下,因为单击后位置立即从
(0,0)
更改为(1,1)
。无论出于何种原因,它都不会报告正确的位置。其余课程:
EventHandler.h:
#ifndef EVENT_HANDLER_H
#define EVENT_HANDLER_H
#include <vector>
#include <atomic>
#include <thread>
#include <functional>
#include <windows.h>
#include <WinUser.h>
#define LEFT_MOUSE VK_LBUTTON
#define RIGHT_MOUSE VK_RBUTTON
#define MIDDLE_MOUSE VK_MBUTTON
typedef std::function<void(char)> KeyHandler;
typedef std::function<void(char,long,long)> MouseHandler;
class EventHandler {
std::thread listeningThread;
std::atomic<bool> listening = false;
std::vector<char> keysToCheck;
std::vector<char> mButtonsToCheck;
KeyHandler keyHandler = KeyHandler();
MouseHandler mouseHandler = MouseHandler();
void actOnPressedKeys();
public:
EventHandler();
~EventHandler();
void setKeyHandler(KeyHandler);
void setMouseHandler(MouseHandler);
void setKeysToListenOn(std::vector<char>);
void setButtonsToListenOn(std::vector<char>);
void listenForPresses(int loopMSDelay = 100);
void stopListening();
};
#endif
EventHandler.cpp:
#include "EventHandler.h"
#include <thread>
#include <stdexcept>
#include <cctype>
EventHandler::EventHandler() {
}
EventHandler::~EventHandler() {
stopListening();
if (listeningThread.joinable()) {
//May need to fix this. May cause the EventHandler to freeze
// on destruction if listeningThread can't join;
listeningThread.join();
}
}
void EventHandler::actOnPressedKeys() {
for (char key : keysToCheck) {
if ( GetAsyncKeyState(key) ) {
keyHandler(key);
}
}
for (char button : mButtonsToCheck) {
if ( GetAsyncKeyState(button) ) {
POINT p;
if ( !GetCursorPos(&p) ) {
throw std::runtime_error::runtime_error(
"Cannot get cursor position:" + GetLastError()
);
}
mouseHandler(button, p.x, p.y);
}
}
}
void EventHandler::setKeyHandler(KeyHandler handler) {
keyHandler = handler;
}
void EventHandler::setMouseHandler(MouseHandler handler) {
mouseHandler = handler;
}
void EventHandler::setKeysToListenOn(std::vector<char> newListenKeys) {
if (listening) {
throw std::runtime_error::runtime_error(
"Cannot change the listened-on keys while listening"
);
//This could be changed to killing the thread by setting
// listening to false, changing the keys, then restarting
// the listening thread. I can't see that being necessary though.
}
//Untested
for (char& key : newListenKeys) {
if (key >= 'a' && key <= 'z') {
key += 32;
}
}
keysToCheck = newListenKeys;
}
void EventHandler::setButtonsToListenOn(std::vector<char> newListenButtons) {
if (listening) {
throw std::runtime_error::runtime_error(
"Cannot change the listened-on buttons while listening"
);
}
mButtonsToCheck = newListenButtons;
}
void EventHandler::listenForPresses(int loopMSDelay) {
listening = true;
listeningThread = std::thread ([=]{
do {
actOnPressedKeys();
std::this_thread::sleep_for(std::chrono::milliseconds(loopMSDelay));
} while (listening);
});
}
void EventHandler::stopListening() {
listening = false;
}
而我的(混乱)测试主体:
#include <iostream>
#include <fstream>
#include <string>
#include <cstdio>
#include <thread>
#include <chrono>
#include <conio.h>
#include <windows.h>
#include <WinUser.h>
#include <memory>
#include <functional>
#include "Timer.h"
#include "Utils.h"
#include "curses.h"
#include "EventHandler.h"
int main() {
using namespace std;
int counter = 99;
KeyHandler kbHandler([&](char c){
switch (c) {
case 'A': {
counter += 1;
break;
}
case 'B': {
counter -= 1;
break;
}
case 'C': {
counter += 2;
break;
}
case 'D': {
counter -= 2;
break;
}
}
});
bool mouseX = 0, mouseY = 0;
MouseHandler mouseHandler([&](char c, long x, long y) {
switch (c) {
case LEFT_MOUSE: {
mouseX = x;
mouseY = y;
}
}
});
EventHandler eh;
eh.setKeyHandler(kbHandler);
eh.setMouseHandler(mouseHandler);
eh.setKeysToListenOn(vector<char> {'A', 'B', 'C', 'D'});
eh.setButtonsToListenOn(vector<char> { LEFT_MOUSE });
eh.listenForPresses();
while (true) {
cout << counter << " " << "(" << mouseX << "," << mouseY << ")" << endl;
std::this_thread::sleep_for(std::chrono::milliseconds(333));
}
}
这里的任何见解将不胜感激。
最佳答案
哇,我很特别(不是很好)。
由于某些原因,mouseX
和mouseY
的类型为bool
,因此显然任何非零值都将缩短为1。
我将两者都更改为long
,并且按预期方式工作。
关于c++ - 使用GetCursorPosition遇到困难,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/29885862/