键盘动态库开发(修改键值映射和键盘灯控制)

键盘动态库开发(修改键值映射和键盘灯控制)

开发需求

需求:开发一款9键键盘DLL和演示程序,要求能控制灯亮、将9个键值映射为77001-77009。
固件:USB标准键盘0-9键值。

一些重要知识:

键盘DLL功能

1. 键盘OPEN

键盘open,根据键盘固件的PID、VID和版本连接键盘,并建立keyhook抓取键值的线程。功能稍微复杂。

  • 键盘OPEN,即连接键盘,所需参数有VendorID, ProductID, VersionNumber。核对键盘的VID、PID和Version后,建立键盘输入监听线程(StartKeyHook)。
    函数OpenKeyboard:
BOOL OpenKeyboard(USHORT VendorID, USHORT ProductID, USHORT VersionNumber)
{
	if((hDevHandle != INVALID_HANDLE_VALUE))
	{
		return FALSE;
	}

	SECURITY_ATTRIBUTES SecurityAttributes;

	SecurityAttributes.nLength = sizeof(SECURITY_ATTRIBUTES);
	SecurityAttributes.lpSecurityDescriptor = NULL;
	SecurityAttributes.bInheritHandle = false;

	DevInterfaceData.cbSize = sizeof(DevInterfaceData);
	DevAttributes.Size = sizeof(DevAttributes);

	HidD_GetHidGuid(&HidGuid);
	hDevInfoSet = SetupDiGetClassDevs(&HidGuid,NULL,NULL,DIGCF_DEVICEINTERFACE|DIGCF_PRESENT);
	MemberIndex = 0;

	while(TRUE)
	{
		Result = SetupDiEnumDeviceInterfaces(hDevInfoSet, 
			NULL, 
			&HidGuid, 
			MemberIndex, 
			&DevInterfaceData);

		if (Result == FALSE)
		{
			break;
		}
		MemberIndex++;
		Result = SetupDiGetDeviceInterfaceDetail(hDevInfoSet, 
			&DevInterfaceData, 
			NULL, 
			NULL,
			&RequiredSize, 
			NULL);

		pDevDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)malloc(RequiredSize);
		if (pDevDetailData == NULL)
		{
			SetupDiDestroyDeviceInfoList(hDevInfoSet);
			return FALSE;
		}

		pDevDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
		Result = SetupDiGetDeviceInterfaceDetail(hDevInfoSet, 
			&DevInterfaceData, 
			pDevDetailData, 
			RequiredSize, 
			NULL, 
			NULL);

		MyDevPathName = pDevDetailData->DevicePath;
		free(pDevDetailData);
		if (Result == FALSE)
		{
			continue;
		}
		hDevHandle = CreateFile(MyDevPathName,
			0,//GENERIC_WRITE,//GENERIC_READ|,//只有0值时有效
			FILE_SHARE_READ |FILE_SHARE_WRITE,
			&SecurityAttributes,
			OPEN_EXISTING,
			0,//FILE_FLAG_OVERLAPPED, //只有使用同步模式有效
			NULL);

		if (hDevHandle != INVALID_HANDLE_VALUE)
		{
			DevAttributes.Size = sizeof(DevAttributes);
			Result = HidD_GetAttributes(hDevHandle, &DevAttributes);
		
			PHIDP_PREPARSED_DATA	PreparsedData;
			Result = HidD_GetPreparsedData(hDevHandle, &PreparsedData);
			HidP_GetCaps(PreparsedData, &Capabilities);
			
			HidD_FreePreparsedData(PreparsedData);	
	
			if (Result == FALSE)
			{
				continue;
			}

			if ((DevAttributes.VendorID == VendorID) && (DevAttributes.ProductID == ProductID) && (DevAttributes.VersionNumber == VersionNumber))
			{		
				//创建读线程,开始获取键盘的值存放到队列。
				//————————————————————————————————————————————
				StartKeyHook();
				//————————————————————————————————————————————
				SetupDiDestroyDeviceInfoList(hDevInfoSet);
				return TRUE;
			}
		}
	}
	SetupDiDestroyDeviceInfoList(hDevInfoSet);
	return FALSE;
}
  • StartKeyHook键盘钩子函数调用了键盘线程函数KeyboardThread:

BOOL StartKeyHook()
{
	g_hKBHookThread = CreateThread(0, 0, KeyboardThread, 0, 0, &g_nKBHookThreadId);
	return TRUE;
}
  • KeyboardThread键盘钩子函数调用了键盘Hook回调函数KeyboardProc抓取键值并修改映射:
DWORD CALLBACK KeyboardThread(PVOID param)
{
	MSG msg;
	// set low-level keyboard hook
	//	if (!IsDebuggerPresent())
	//	{
	// install the hook for *this* thread, even though it is a systemwide/global hook
		g_hKeyboard = SetWindowsHookEx(WH_KEYBOARD_LL, KeyboardProc, GetModuleHandle(0), 0);
	
	//	}

	// pump messages to stop console from locking up
	while (GetMessage(&msg, 0, 0, 0) > 0)
	{
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}

	// remove the hook just before we exit
	UnhookWindowsHookEx(g_hKeyboard);
	return 0;

}
  • KeyboardProc键盘钩子回调函数抓取键值及修改映射关系:
LRESULT CALLBACK KeyboardProc(
	int code,
	WPARAM wParam,
	LPARAM lParam
)
{
	//CString csMsg;
	//csMsg.Format(_T("KeyboardPro code=%d"),code);
	//AfxMessageBox(csMsg);
	if (code == HC_ACTION)
	{
		KBDLLHOOKSTRUCT *Key = (KBDLLHOOKSTRUCT *)lParam;
		
		if (!(Key->flags & LLKHF_UP))//
		{
			
			switch ((Key->vkCode & 0xff))//
			{
			case '1':
				dwKeyValue = 77001;
				return TRUE; //屏蔽该值;
			case '2':
				dwKeyValue = 77002;
				return TRUE; //屏蔽该值
			case '3':
				dwKeyValue = 77003;
				return TRUE; //屏蔽该值
			case '4':
				dwKeyValue = 77004;
				return TRUE; //屏蔽该值
			case '5':
				dwKeyValue = 77005;
				return TRUE; //屏蔽该值
			case '6':
				dwKeyValue = 77006;
				return TRUE; //屏蔽该值
			case '7':
				dwKeyValue = 77007;
				return TRUE; //屏蔽该值
			case '8':
				dwKeyValue = 77008;
				return TRUE; //屏蔽该值
			case '9':
				dwKeyValue = 77009;
				return TRUE; //屏蔽该值
			default:
				dwKeyValue =0;
				break;
			}
		}
	}
	return CallNextHookEx(g_hKeyboard, code, wParam, lParam);
}

2. 键盘CLOSE

键盘close,即关闭键盘,关闭devhandle并结束抓取keyvalue的线程。
函数CloseKeyboard:

BOOL CloseKeyboard()
{
	if (hDevHandle == INVALID_HANDLE_VALUE)
	{
		return FALSE;
	}

	if (!CloseHandle(hDevHandle))
	{
		return FALSE;
	}
	else
	{
		//结束线程
		StopKeyHook();
		hDevHandle = INVALID_HANDLE_VALUE;
		return TRUE;
	}
}

3. 键盘灯控制

键盘灯控制,设一个变量dwSettings[unsigned long int(DWORD)],其中每一比特位0/1对应着灭/亮。用一个字节,2个8位。

9
12345678

函数SetKeyLight:

MYLIBDLL BOOL SetKeyLight(DWORD dwSettings)
{
	USHORT usFeatureReportByteLength;
	BYTE CommandBuffer[100];

	if (hDevHandle == INVALID_HANDLE_VALUE)
	{
		return FALSE;
	}

	usFeatureReportByteLength = Capabilities.FeatureReportByteLength;

	CommandBuffer[0] = 0x00;
	CommandBuffer[1] = BYTE(0xFF&dwSettings);
	CommandBuffer[2] = BYTE((0x0100&dwSettings)>>8);
	CommandBuffer[3] = CommandBuffer[1]+CommandBuffer[2];

	return  HidD_SetFeature(hDevHandle, CommandBuffer, usFeatureReportByteLength);

}

4. 键值抓取

键值抓取,设一个参数dwTimeout[unsigned long int(DWORD)],执行抓取动作直到过时,返回tempKeyValue作为转换后的值。

函数SetKeyLight:

MYLIBDLL DWORD GetKeyValue(DWORD dwTimeout)
{
	DWORD tempKeyValue=0;
	DWORD i;
	DWORD timeOut=0;
	timeOut = dwTimeout / 10;
	
	if (hDevHandle == INVALID_HANDLE_VALUE)
	{
		return 0;
	}

	for (i = 0; i < timeOut; i++)
	{
		if (dwKeyValue == 0)
		{
			Sleep(10);
		}
		else
		{
			tempKeyValue = dwKeyValue;
			dwKeyValue = 0;
			break;
		}
	}
	return tempKeyValue;
}

这个函数非常简单,即等到timeout后将获取到的最后一个键值(dwKeyValue)返回。
其中dwKeyValue是在键盘open到键盘close的整个过程不断获取的。
在外面做一个简单的调用demo就可以使用了。
打开键盘:

读取键值如下:

点亮键灯如下:(键盘变黄色表示点亮)

最后关闭点击CLOSE即可。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

nobugirl

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值