📄 myusbhidtestappdlg.cpp
字号:
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 + -