【发布时间】:2020-05-09 03:55:32
【问题描述】:
规格
- 操作系统: Windows 10
- 编程语言: C++14
- 编译器: MSVC 2019
- IDE: CLion 2019.3.3
代码:
#define WINVER 0x0500
#include <windows.h>
#include <string>
void press_enter() {
// This structure will be used to create the keyboard
// input event.
INPUT ip;
// Set up a generic keyboard event.
ip.type = INPUT_KEYBOARD;
ip.ki.wScan = 0; // hardware scan code for key
ip.ki.time = 0;
ip.ki.dwExtraInfo = 0;
// Press enter
ip.ki.wVk = 0x0D;
ip.ki.dwFlags = 0; // 0 for key press
SendInput(1, &ip, sizeof(INPUT));
// Release the key
ip.ki.dwFlags = KEYEVENTF_KEYUP; // KEYEVENTF_KEYUP for key release
SendInput(1, &ip, sizeof(INPUT));
Sleep(25);
}
void press_keys(std::string& text_to_write) {
// This structure will be used to create the keyboard
// input event.
INPUT ip;
// Load current window's keyboardLayout
HKL kbl = GetKeyboardLayout(0);
// Set up a generic keyboard event.
ip.type = INPUT_KEYBOARD;
ip.ki.wScan = 0; // hardware scan code for key
ip.ki.time = 0;
ip.ki.dwExtraInfo = 0;
for (char& c : text_to_write) {
// Press the corresponding 'c' key
ip.ki.wVk = VkKeyScanEx(c, kbl);; // virtual-key code for the "a" key
ip.ki.dwFlags = 0; // 0 for key press
SendInput(1, &ip, sizeof(INPUT));
// Release the key
ip.ki.dwFlags = KEYEVENTF_KEYUP; // KEYEVENTF_KEYUP for key release
SendInput(1, &ip, sizeof(INPUT));
Sleep(25);
}
}
void give_100000(std::string& item) {
for (int i = 0; i < 10; i++) {
press_keys(item);
Sleep(25);
press_enter();
Sleep(25);
press_enter();
Sleep(25);
}
}
int main() {
// Pause for 5 seconds.
Sleep(5000);
std::string lumber = "lumberjack";
std::string food = "cheese steak jimmy's";
std::string gold = "robin hood";
std::string stone = "rock on";
give_100000(lumber);
give_100000(food);
give_100000(gold);
give_100000(stone);
// Exit normally
return 0;
}
这个程序的作用
我仍然是 C++ 的初学者。我编写了这个程序作为一个小挑战并练习我的 C++。它模拟键盘按下,专门用于快速输入秘籍,这样我就可以在帝国时代 II 中获得大量资源。
问题
此代码按原样完美运行。它做我想让它做的事情。问题是,press_enter() 和 press_keys() 函数内部都有重复的代码,即:
INPUT ip;
// Set up a generic keyboard event.
ip.type = INPUT_KEYBOARD;
ip.ki.wScan = 0; // hardware scan code for key
ip.ki.time = 0;
ip.ki.dwExtraInfo = 0;
所以我想解决这个问题。
我尝试了什么
我想我可以把那段代码放在所有函数之外(就在#includes 下方)并让它们充当全局变量,这样所有函数都可以访问ip。但是这样做让 CLion 抱怨,编译给了我一个巨大的难以理解的错误列表(如果需要我可以发布)。当我将鼠标悬停在以ip. 开头的 4 行中的任何一行上时,CLion 会说:“未知类型名称 'ip'”。我不明白这一点,因为ip 在上面声明了两行。
我在寻找什么
正如我所说,我仍然是 C++ 的初学者,所以我真的很想了解这意味着什么,如果我缺少一些基本概念,以及一种无需重复代码即可使其工作的方法。
【问题讨论】:
-
将通用代码放入一个单独的函数中,然后在需要的地方调用该函数。例如,参见this question 中的
configure_input()函数。 -
乍一看,您的
press_enter基本上等同于press_keys("\r");... -
注意:您正在编写一些非常特定于平台的代码。如果你想让你的代码在不同的平台上工作,你我想重新评估你在做什么。
-
变量可以是全局的,但语句不能。例如,
ip.type = INPUT_KEYBOARD;行必须在某个函数内部。错误消息显示“未知 类型名称 ip。”因为编译器认为您正在尝试声明函数或变量,而声明通常以类型名称开头。它看到ip并说“好吧,规则说类型名称需要放在此处,但ip不是类型名称。” (这是一个变量名。) -
性能在这里不是问题。尤其是因为那些对
Sleep的调用!无论如何,在获得性能之前,您需要专注于基础知识。当你这样做时,不要认为你可以预测性能,总是衡量。您遇到的一个大问题是您调用SendInput只传递了一个事件。您的目的是在一个数组中提供所有事件,以便可以原子地插入它们。这就是SendInput存在的主要原因,因为keybd_event在它之前就已经存在。您有机会发现std::vector<T>。