⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 myusbhidtestappdlg.cpp

📁 对HID类设备进行读写
💻 CPP
📖 第 1 页 / 共 3 页
字号:
	GetDlgItem(IDC_LED8)->EnableWindow(FALSE);

	//开关加载弹起状态图标
	GetDlgItem(IDC_KEY1)->SendMessage(BM_SETIMAGE,IMAGE_ICON,(LPARAM)hIcon);
	GetDlgItem(IDC_KEY2)->SendMessage(BM_SETIMAGE,IMAGE_ICON,(LPARAM)hIcon);
	GetDlgItem(IDC_KEY3)->SendMessage(BM_SETIMAGE,IMAGE_ICON,(LPARAM)hIcon);
	GetDlgItem(IDC_KEY4)->SendMessage(BM_SETIMAGE,IMAGE_ICON,(LPARAM)hIcon);
	GetDlgItem(IDC_KEY5)->SendMessage(BM_SETIMAGE,IMAGE_ICON,(LPARAM)hIcon);
	GetDlgItem(IDC_KEY6)->SendMessage(BM_SETIMAGE,IMAGE_ICON,(LPARAM)hIcon);
	GetDlgItem(IDC_KEY7)->SendMessage(BM_SETIMAGE,IMAGE_ICON,(LPARAM)hIcon);
	GetDlgItem(IDC_KEY8)->SendMessage(BM_SETIMAGE,IMAGE_ICON,(LPARAM)hIcon);	

	//初始化VID、PID、PVN数据区
	SetDlgItemText(IDC_VID_EDIT,"8888");
	SetDlgItemText(IDC_PID_EDIT,"0006");
	SetDlgItemText(IDC_PVN_EDIT,"0100");

	//设置VID、PID、PVN数据区文本宽度
	((CEdit*)GetDlgItem(IDC_VID_EDIT))->SetLimitText(4);
	((CEdit*)GetDlgItem(IDC_PID_EDIT))->SetLimitText(4);
	((CEdit*)GetDlgItem(IDC_PVN_EDIT))->SetLimitText(4);

	SetTimer(1,600,NULL);	//这个定时器用来刷新图标

	//初始化写报告时用的Overlapped结构体
	//偏移量设置为0
	WriteOverlapped.Offset=0;
	WriteOverlapped.OffsetHigh=0;
	//创建一个事件,提供给WriteFile使用,当WriteFile完成时,
	//会设置该事件为触发状态。
	WriteOverlapped.hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);

	//初始化读报告时用的Overlapped结构体
	//偏移量设置为0
	ReadOverlapped.Offset=0;
	ReadOverlapped.OffsetHigh=0;
	//创建一个事件,提供给ReadFile使用,当ReadFile完成时,
	//会设置该事件为触发状态。
	ReadOverlapped.hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);

	//创建写报告的线程(处于挂起状态)
	pWriteReportThread=AfxBeginThread(WriteReportThread,
		                                this,
																																		THREAD_PRIORITY_NORMAL,
																																		0,
																																		CREATE_SUSPENDED,
																																		NULL);
	//如果创建成功,则恢复该线程的运行
	if(pWriteReportThread!=NULL)
	{
		pWriteReportThread->ResumeThread();
	}

	//创建一个读报告的线程(处于挂起状态)
 pReadReportThread=AfxBeginThread(ReadReportThread,
		                                this,
																																		THREAD_PRIORITY_NORMAL,
																																		0,
																																		CREATE_SUSPENDED,
																																		NULL);
	//如果创建成功,则恢复该线程的运行
	if(pReadReportThread!=NULL)
	{
		pReadReportThread->ResumeThread();
	}
 
	//获取HID设备的接口类GUDI
 HidD_GetHidGuid(&HidGuid);
	//设置DevBroadcastDeviceInterface结构体,用来注册设备改变时的通知
	DevBroadcastDeviceInterface.dbcc_size=sizeof(DevBroadcastDeviceInterface);
 DevBroadcastDeviceInterface.dbcc_devicetype=DBT_DEVTYP_DEVICEINTERFACE;
 DevBroadcastDeviceInterface.dbcc_classguid=HidGuid;
	//注册设备改变时收到通知
	RegisterDeviceNotification(m_hWnd,
							                    &DevBroadcastDeviceInterface,
																											DEVICE_NOTIFY_WINDOW_HANDLE);
}
//////////////////////////////End of function//////////////////////

//将信息添加到信息显示框的函数
void CMyUsbHidTestAppDlg::AddToInfOut(CString InStr, BOOL AddTime, BOOL NewLine)
{
	CString str,str1;
	UINT i;
	CHAR SysTime[10];
 
	//先获取原来显示的文本
	GetDlgItemText(IDC_INF_OUT,str);
	//将新的信息追加在最后
	str+=InStr;

	//需要添加时间信息
	if(AddTime==TRUE)
	{
		_strtime(SysTime);
		str1=SysTime;
		str1=" ("+str1+")";
		str+=str1;
	}

	//需要换行
	if(NewLine==TRUE)
	{
		str+="\r\n";
	}

	//设置新的文本
	SetDlgItemText(IDC_INF_OUT,str);
	//滚动条自动滚动到最后一行
	i=((CEdit*)GetDlgItem(IDC_INF_OUT))->GetLineCount();
	((CEdit*)GetDlgItem(IDC_INF_OUT))->LineScroll(i,0);
}
//////////////////////////////End of function//////////////////////

//重载上述函数,入口参数不一样。
void CMyUsbHidTestAppDlg::AddToInfOut(char *p, BOOL AddTime, BOOL NewLine)
{
	CString str=p;
	AddToInfOut(str,AddTime,NewLine);
}
//////////////////////////////End of function//////////////////////

void CMyUsbHidTestAppDlg::OnClearInf() 
{
	// TODO: Add your control notification handler code here
	SetDlgItemText(IDC_INF_OUT,"");
}
//////////////////////////////End of function//////////////////////

//发送LED的状态。
BOOL CMyUsbHidTestAppDlg::SendLedStatus()
{
	BOOL Result;
	UINT LastError;
	UINT i;
	CString Str;
 
	//如果设备没有找到,则返回失败
	if(MyDevFound==FALSE)
	{
  AddToInfOut("设备未找到");
		return FALSE;
	}

	//如果句柄无效,则说明打开设备失败
	if(hWriteHandle==INVALID_HANDLE_VALUE)
	{
		AddToInfOut("无效的写报告句柄,可能是打开设备时失败");
		return FALSE;
	}

	//如果数据仍在发送中,则返回失败
	if(DataInSending==TRUE)
	{
		AddToInfOut("数据正在发送中,暂时不能发送");
		return FALSE;
	}

	//设置要发送报告的数据
	WriteReportBuffer[0]=0x00;   //报告ID为0
	WriteReportBuffer[1]=LedStatus;	//将LED状态放到缓冲区中

	//显示发送数据的信息
	AddToInfOut("发送输出报告9字节");
	Str="";
	for(i=0;i<8;i++)
	{
		Str+=itos(WriteReportBuffer[i],16).Right(2)+" ";
	}
 AddToInfOut(Str,FALSE);

	//设置正在发送标志
 DataInSending=TRUE;

	//调用WriteFile函数发送数据
	Result=WriteFile(hWriteHandle,
			               WriteReportBuffer,
											       8,
											       NULL,
										       	&WriteOverlapped);

	//如果函数返回失败,则可能是真的失败,也可能是IO挂起了
	if(Result==FALSE)
	{
  //获取最后错误代码
		LastError=GetLastError();
		//看是否是真的IO挂起
		if((LastError==ERROR_IO_PENDING)||(LastError==ERROR_SUCCESS))
		{
			return TRUE;
		}
		//否则,是函数调用时发生错误,显示错误代码
		else
		{
			DataInSending=FALSE;
			AddToInfOut("发送失败,错误代码:"+itos(LastError));
   //如果最后错误为1,说明该设备不支持该函数。
			if(LastError==1)
			{
				AddToInfOut("该设备不支持WriteFile函数。", FALSE);
			}
			return FALSE;
		}
	}
	//否则,函数返回成功
	else
	{
		DataInSending=FALSE;
	 return TRUE;
	}
}
//////////////////////////////End of function//////////////////////

void CMyUsbHidTestAppDlg::SetLedStatus(INT nID, INT nLed)
{
 UCHAR Mask;
	HICON hIcon;

	//当处理某位LED时,对应的bit为1
	Mask=(1<<(nLed-1));
 
	//翻转对应的位
	LedStatus^=Mask;

	//设置LED状态成功
	if(SendLedStatus()==TRUE)
	{
		//LED处于亮状态,使用亮的图片
		if(LedStatus&Mask)
		{
			hIcon=AfxGetApp()->LoadIcon(IDI_LED_ON);
			AddToInfOut("LED" + itos(nLed) + " 点亮");
		}
		//LED处于灭状态,使用灭的图片
		else
		{
			hIcon=AfxGetApp()->LoadIcon(IDI_LED_OFF);
   AddToInfOut("LED" + itos(nLed) + " 熄灭");
		}
  GetDlgItem(nID)->SendMessage(BM_SETIMAGE,IMAGE_ICON,(LPARAM)hIcon);
	}
	else
	{
		LedStatus^=Mask;  //没有设置成功,改回原来的值
	}
}
//////////////////////////////End of function//////////////////////

//LED1按键单击
void CMyUsbHidTestAppDlg::OnLed1()
{
	SetLedStatus(IDC_LED1,1);
	return;
}
//////////////////////////////End of function//////////////////////

//LED2按键单击
void CMyUsbHidTestAppDlg::OnLed2() 
{
	SetLedStatus(IDC_LED2,2);
}
//////////////////////////////End of function//////////////////////

//LED3按键单击
void CMyUsbHidTestAppDlg::OnLed3() 
{
	SetLedStatus(IDC_LED3,3);
}
//////////////////////////////End of function//////////////////////

//LED4按键单击
void CMyUsbHidTestAppDlg::OnLed4() 
{
	SetLedStatus(IDC_LED4,4);
}
//////////////////////////////End of function//////////////////////

//LED5按键单击
void CMyUsbHidTestAppDlg::OnLed5() 
{
	SetLedStatus(IDC_LED5,5);
}
//////////////////////////////End of function//////////////////////

//LED6按键单击
void CMyUsbHidTestAppDlg::OnLed6() 
{
	SetLedStatus(IDC_LED6,6);
}
//////////////////////////////End of function//////////////////////

//LED7按键单击
void CMyUsbHidTestAppDlg::OnLed7() 
{
	SetLedStatus(IDC_LED7,7);
}
//////////////////////////////End of function//////////////////////

//LED8按键单击
void CMyUsbHidTestAppDlg::OnLed8() 
{
	SetLedStatus(IDC_LED8,8);
}
//////////////////////////////End of function//////////////////////

//显示按键情况
void CMyUsbHidTestAppDlg::SetKeyStatus()
{
	HICON hIcon;
 UCHAR Mask;
	UINT i;
 UINT nIDs[8]=
	{
		IDC_KEY1,IDC_KEY2,IDC_KEY3,IDC_KEY4,
	 IDC_KEY5,IDC_KEY6,IDC_KEY7,IDC_KEY8
	};

	//保存上一次按键的情况
	static UCHAR LastKeyStatus=0x00;

	if(LastKeyStatus==KeyStatus)
	{
		return;		//按键状态没有改变,不需要更新按键状态
	}

	//KEYi按键情况改变
	for(i=0;i<8;i++)
	{
		Mask=(1<<i);
		if((LastKeyStatus^KeyStatus)&Mask)
		{
			if(KeyStatus&Mask)
			{
				hIcon=AfxGetApp()->LoadIcon(IDI_LED_ON);
				AddToInfOut("KEY" + itos(i+1) + "按下");
			}
			else
			{
				hIcon=AfxGetApp()->LoadIcon(IDI_LED_OFF);
				AddToInfOut("KEY" + itos(i+1) +"弹起");
			}
			GetDlgItem(nIDs[i])->SendMessage(BM_SETIMAGE,IMAGE_ICON,(LPARAM)hIcon);
		}
 }

	//保存最后按键的情况
	LastKeyStatus=KeyStatus;
}
//////////////////////////////End of function//////////////////////

//点击打开设备按钮的处理函数
void CMyUsbHidTestAppDlg::OnOpenDevice()
{
 //定义一个GUID的结构体HidGuid来保存HID设备的接口类GUID。
 GUID HidGuid;
 //定义一个DEVINFO的句柄hDevInfoSet来保存获取到的设备信息集合句柄。
	HDEVINFO hDevInfoSet;
 //定义MemberIndex,表示当前搜索到第几个设备,0表示第一个设备。
	DWORD MemberIndex;
	//DevInterfaceData,用来保存设备的驱动接口信息
	SP_DEVICE_INTERFACE_DATA DevInterfaceData;
 //定义一个BOOL变量,保存函数调用是否返回成功
	BOOL Result;
 //定义一个RequiredSize的变量,用来接收需要保存详细信息的缓冲长度。
	DWORD RequiredSize;
 //定义一个指向设备详细信息的结构体指针。
 PSP_DEVICE_INTERFACE_DETAIL_DATA	pDevDetailData;
 //定义一个用来保存打开设备的句柄。
	HANDLE hDevHandle;
 //定义一个HIDD_ATTRIBUTES的结构体变量,保存设备的属性。
	HIDD_ATTRIBUTES DevAttributes;

 //初始化设备未找到
	MyDevFound=FALSE;

	//获取在文本框中设置的VID、PID、PVN。
	GetMyIDs();

	//初始化读、写句柄为无效句柄。
	hReadHandle=INVALID_HANDLE_VALUE;
	hWriteHandle=INVALID_HANDLE_VALUE;

	//对DevInterfaceData结构体的cbSize初始化为结构体大小
	DevInterfaceData.cbSize=sizeof(DevInterfaceData);
	//对DevAttributes结构体的Size初始化为结构体大小
	DevAttributes.Size=sizeof(DevAttributes);

	//调用HidD_GetHidGuid函数获取HID设备的GUID,并保存在HidGuid中。
	HidD_GetHidGuid(&HidGuid);

	//根据HidGuid来获取设备信息集合。其中Flags参数设置为
	//DIGCF_DEVICEINTERFACE|DIGCF_PRESENT,前者表示使用的GUID为
	//接口类GUID,后者表示只列举正在使用的设备,因为我们这里只
	//查找已经连接上的设备。返回的句柄保存在hDevinfo中。注意设备
	//信息集合在使用完毕后,要使用函数SetupDiDestroyDeviceInfoList
	//销毁,不然会造成内存泄漏。
	hDevInfoSet=SetupDiGetClassDevs(&HidGuid,
		                               NULL,
																			            		NULL,
																					            DIGCF_DEVICEINTERFACE|DIGCF_PRESENT);
 
	AddToInfOut("开始查找设备");
	//然后对设备集合中每个设备进行列举,检查是否是我们要找的设备
	//当找到我们指定的设备,或者设备已经查找完毕时,就退出查找。
	//首先指向第一个设备,即将MemberIndex置为0。
	MemberIndex=0;
	while(1)
	{
		//调用SetupDiEnumDeviceInterfaces在设备信息集合中获取编号为
		//MemberIndex的设备信息。
	 Result=SetupDiEnumDeviceInterfaces(hDevInfoSet,
		                                   NULL,
			 																							       			&HidGuid,
				 																									       MemberIndex,
					 																							       	&DevInterfaceData);

		//如果获取信息失败,则说明设备已经查找完毕,退出循环。
		if(Result==FALSE) break;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -