我目前正在使用c ++和windows API创建一个需要用户从键盘输入的程序。
我目前的解决方案是有效的,但我想问一下是否有更好的方法来实现我想要做的事情。
当前解决方案
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam){
switch (message){
case WM_CHAR:
switch (wParam) {
case 119:
std::cout << "W" << std::endl;
break;
case 97:
std::cout << "A" << std::endl;
break;
case 115:
std::cout << "S" << std::endl;
break;
case 100:
std::cout << "D" << std::endl;
break;
}
break;
return 0;
}
如果我想获得键盘上的每一个键,我将不得不为每个键创建一个案例。有没有更好的办法?
另外,是否有任何在线参考,我可以获得每个密钥的代码?
编辑:我想为每个单独的密钥实现逻辑。本来应该提到的,我道歉。
谢谢
如果你真的只想打印每个键,ASCII table being mapped directly in this case,显而易见的是在case WM_CHAR:
内部,而不是整个第二个switch
:
std::wcout << static_cast<wchar_t>(wParam) << std::endl;
如果您希望能够为每个键定义单独的特定处理程序逻辑,可能以下示例将是更好的模式,因为它将简化WndProc()
的逻辑,并添加间接级别,使您能够对待处理程序本身作为第一类对象:
#include <iostream>
#include <functional>
#include <map>
#include <Windows.h>
std::map<uint32_t, std::function<void()>> gKeyCallback;
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_CHAR:
auto mapIter = gKeyCallback.find(static_cast<uint32_t>(wParam));
if (mapIter != gKeyCallback.end())
mapIter->second();
break;
}
return 0;
}
int main()
{
gKeyCallback['W'] = [] {std::cout << "Handler for 'W'" << std::endl; };
gKeyCallback['A'] = [] {std::cout << "Handler for 'A'" << std::endl; };
gKeyCallback['S'] = [] {std::cout << "Handler for 'S'" << std::endl; };
gKeyCallback['D'] = [] {std::cout << "Handler for 'D'" << std::endl; };
return 0;
}
这个想法包括持有一个映射容器,使得能够为每个给定的密钥获取适当的处理程序回调函数。您可以根据自己的需要更改原型。 lambda expression表示法用于使每个键处理程序的初始化不那么费力,在眼睛上可读并且以后更容易维护:
这一行:
std::map<uint32_t, std::function<void()>> gKeyCallback;
定义映射容器(a.k.a。字典)对象。它是type std::map
,在这里它表示从类型uint32_t
到处理程序回调函数类型的映射 - 当前是一个统一的void()
回调。
这行是做什么的:
gKeyCallback['W'] = [] {std::cout << "Handler for 'W'" << std::endl; };
是映射键值119
('W'
的ASCII值)到它所需的特定逻辑,在{}
(花括号)中指定。这里的关键语法元素是[]
。 Here you can read all about how to use this lambda expression syntax。
注意:这绝对不是使用全局变量(gKeyCallback
)的建议,它仅用于完整的代码示例简单性。