mfc根据vid区分设备输入内容

做了一个mfc的外挂程序,连接了多个扫描枪以及一个键盘,需要区分哪些内容是哪个设备输入的。
网上找了很多资料,大多是在扫描枪中设置前后缀,然后使用Hook回调函数获取键盘输入,再根据前后缀判断是哪一把扫描枪。一开始我这样实现,但是发现会有换设备就要重新设置前后缀和前后缀可能与输入内容有重复的问题。
后来发现在MFC中,PreTranslateMessage是虚函数,是用来截获消息的。我们可以通过重载它来处理键盘和鼠标消息,键盘消息会存放在一个缓存池中,缓存池的名字包含了vid,我们可以根据缓存池名字判断是哪个扫描枪输入,这种方法用到的是mfc的消息处理,比上面打方法CPU占用率小,实时性高,当然这种方法现在只适用于MFC。
代码如下:

//全局扫描枪数据
//int:第i把扫码枪
//string:扫码枪积累的字符
//DWORD:上一次接收扫码枪消息的时间 超过设置的timeout,清除
std::map<int, std::pair<std::string, DWORD>> g_scaner_data;

MainFrm.cpp

extern std::map<int, std::pair<std::string, DWORD>> g_scaner_data;

BOOL CMainFrame::PreTranslateMessage(MSG* pMsg)
{
	// TODO: 在此添加专用代码和/或调用基类

	if (pMsg->message == WM_INPUT)
	{
		{
			UINT dwSize;
			GetRawInputData((HRAWINPUT)pMsg->lParam, RID_INPUT, NULL, &dwSize,
				sizeof(RAWINPUTHEADER));
			LPBYTE lpb = new BYTE[dwSize];
			if (lpb == NULL)
			{
				return 0;
			}


			if (GetRawInputData((HRAWINPUT)pMsg->lParam, RID_INPUT, lpb, &dwSize,
				sizeof(RAWINPUTHEADER)) != dwSize)
				OutputDebugString(TEXT("GetRawInputData doesn't return correct size !\n"));

			int type = 0;
			RAWINPUT* raw = (RAWINPUT*)lpb;
			{
				//为键盘设备名准备缓冲区大小
				GetRawInputDeviceInfo
					(raw->header.hDevice,
						RIDI_DEVICENAME,
						NULL,
						&dwSize);
				WCHAR stringBuffer[1024];
				//将设备名读入缓冲区stringBuffer
				GetRawInputDeviceInfo(raw->header.hDevice, RIDI_DEVICENAME, stringBuffer,
					&dwSize);

				std::string tmp = wideCharToMultiByte(stringBuffer);

				//transform(tmp.begin(), tmp.end(), tmp.begin(), ::toupper);

				//根据设备路径名称,区分扫码枪
				if (tmp.find(VID) != std::string::npos)
				{
					type = 1;
				}

				LogNode *pMsgNode = NULL;

				pMsgNode = new LogNode;
				pMsgNode->FormatMsg(LOG_SHOE_AND_PRINT, Normal, CString(tmp.c_str()));
				//::SendMessage(this->GetSafeHwnd(), WM_LOG_MSG, NULL, (LPARAM)pMsgNode);

				if (type == 0)
				{
					//无关设备输入,忽略
					delete[] lpb;
					return 0;
					type = 1;
				}
			}

			//raw->header.hDevice
			if (raw->header.dwType == RIM_TYPEKEYBOARD)
			{

				if (raw->data.keyboard.Message == WM_KEYDOWN)
				{
					char keytext[50] = { 0 };
					BYTE state[256] = { 0 };

					//通过虚拟键盘码得到名字
					ToAscii(raw->data.keyboard.VKey, raw->data.keyboard.MakeCode, state, (LPWORD)keytext, 0);

					/*if(! ((keytext[0] >= 'A'&&keytext[0] <= 'Z') || (keytext[0] >= 'a'&&keytext[0] <= 'z')))
					{
					delete[] lpb;
					return 0;
					}*/

					/*if (g_scaner_data[type].first == ""&&keytext[0] != 's')
					{

						delete[] lpb;
						return 0;
					}*/

					if (GetTickCount() - g_scaner_data[type].second > 2000)
					{
						//键盘消息超过两秒,自动清除
						g_scaner_data[type].first = "";
					}
					std::string org_text = g_scaner_data[type].first;
					g_scaner_data[type] = std::make_pair(org_text + keytext, GetTickCount());

				}

			}


			delete[] lpb;
			return 0;
		}
	}
	else
		return CFrameWnd::PreTranslateMessage(pMsg);
}
  • 2
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值