我想在MFC中实现当接入计算机的串口有所变化时,在组合框中改变相应列表项,并且当拔出的是当前已经选择的串口时,将打开/关闭按键的显示状态改变,同时关闭相应串口,其他情况下不改变已经选择串口的状态,但是我发现不管怎么改变插入拔出哪个串口,打开/关闭按键都会变为关闭状态(当前面是打开状态时),调试了一个早上,还是没发现问题,各位大神能不能帮忙看看怎么回事,谢谢了!
这个是代码,是通过捕获WM_DEVICECHANGE消息实现的,读串口是通过读注册表实现的
BOOL CSerialPortTest2Dlg::OnDeviceChange(UINT nEventType,DWORD dwData) //有串口热拔出或插入
{
CString str;
int len,len1;
m_ctrlComboCom.GetWindowText(str);
len1 = m_ctrlComboCom.GetCount();
/**********************************************************************************************************************/
int i = 0; //通过注册表读取串口号
char Name[25];
UCHAR szPortName[25];
LONG Status;
DWORD dwIndex = 0;
DWORD dwName;
DWORD dwSizeofPortName;
DWORD Type;
HKEY hKey;
CString strSerialList[256]; // 临时定义 256 个字符串组,因为系统最多也就 256 个
LPCTSTR data_Set="HARDWARE\DEVICEMAP\SERIALCOMM\";
dwName = sizeof(Name);
dwSizeofPortName = sizeof(szPortName);
//long ret0 = (::RegOpenKeyEx(HKEY_LOCAL_MACHINE, data_Set, 0, KEY_READ, &hKey));
long ret0 = RegOpenKey(HKEY_LOCAL_MACHINE, data_Set, &hKey); //打开一个制定的注册表键,成功返回ERROR_SUCCESS即“0”值
if(ret0 == ERROR_SUCCESS)
{
do
{
Status = RegEnumValue(hKey, dwIndex++, Name, &dwName, NULL, &Type, szPortName, &dwSizeofPortName);//读取键值
if((Status == ERROR_SUCCESS)||(Status == ERROR_MORE_DATA))
{
strSerialList[i] = CString(szPortName); // 串口字符串保存
//m_ctrlComboCom.AddString(strSerialList[i]);
i++;// 串口计数
}
//每读取一次dwName和dwSizeofPortName都会被修改
//注意一定要重置,否则会出现很离奇的错误,本人就试过因没有重置,出现先插入串口号大的(如COM4),再插入串口号小的(如COM3),此时虽能发现两个串口,但都是同一串口号(COM4)的问题,同时也读不了COM大于10以上的串口
dwName = sizeof(Name);
dwSizeofPortName = sizeof(szPortName);
} while((Status == ERROR_SUCCESS)||(Status == ERROR_MORE_DATA));
RegCloseKey(hKey);
}
/*******************************************************************************************************************************/
len = i;
if(len > len1) //有新的串口插入
{
m_ctrlComboCom.ResetContent();
for(i=0;i<len;i++) //重新加载串口列表
m_ctrlComboCom.AddString(strSerialList[i]);
m_ctrlComboCom.SetWindowText(str);
}
else //少了一个串口,但仍然有串口存在
{
if(len == 0) //热拔出后不再有串口存在
{
m_ctrlComboCom.ResetContent();
}
else //热拔出后仍有串口存在
{
for(i=0;i<len;i++)
{
if(strSerialList[i] == str)
break;
}
m_ctrlComboCom.ResetContent();
int j;
for(j=0;j<len;j++) //重新加载串口列表
m_ctrlComboCom.AddString(strSerialList[j]);
if(i == len)
{//在新的串口表里没有找到编辑框中的串口
m_ctrlComboCom.SetCurSel(0); //设置默认串口
if(m_bSerialPortOpened == TRUE)
{
//m_SerialPort.StopMonitoring();
m_SerialPort.ClosePort();
m_ctrlBtnOpenClose.SetIcon(IDI_ICON2); //更换图标
m_ctrlBtnOpenClose.SetFlat(FALSE);
SetDlgItemText(IDC_BUTTON_OPEN, _T("打开串口"));
//AfxMessageBox(_T("串口关闭成功!"));
m_bSerialPortOpened = FALSE;
}
}
else if(i<len)
{
m_ctrlComboCom.SetWindowText(str);
}
//AfxMessageBox(str);
}
}
return TRUE;
}
BOOL CSerialPortTest2Dlg::OnDeviceChange(UINT nEventType,DWORD dwData) //有串口热拔出或插入
{
CString str;
int len,len1;
m_ctrlComboCom.GetWindowText(str);
len1 = m_ctrlComboCom.GetCount();
/**********************************************************************************************************************/
int i = 0; //通过注册表读取串口号
char Name[25];
UCHAR szPortName[25];
LONG Status;
DWORD dwIndex = 0;
DWORD dwName;
DWORD dwSizeofPortName;
DWORD Type;
HKEY hKey;
CString strSerialList[256]; // 临时定义 256 个字符串组,因为系统最多也就 256 个
LPCTSTR data_Set="HARDWARE\\DEVICEMAP\\SERIALCOMM\\";
dwName = sizeof(Name);
dwSizeofPortName = sizeof(szPortName);
//long ret0 = (::RegOpenKeyEx(HKEY_LOCAL_MACHINE, data_Set, 0, KEY_READ, &hKey));
long ret0 = RegOpenKey(HKEY_LOCAL_MACHINE, data_Set, &hKey); //打开一个制定的注册表键,成功返回ERROR_SUCCESS即“0”值
if(ret0 == ERROR_SUCCESS)
{
do
{
Status = RegEnumValue(hKey, dwIndex++, Name, &dwName, NULL, &Type, szPortName, &dwSizeofPortName);//读取键值
if((Status == ERROR_SUCCESS)||(Status == ERROR_MORE_DATA))
{
strSerialList[i] = CString(szPortName); // 串口字符串保存
//m_ctrlComboCom.AddString(strSerialList[i]);
i++;// 串口计数
}
//每读取一次dwName和dwSizeofPortName都会被修改
//注意一定要重置,否则会出现很离奇的错误,本人就试过因没有重置,出现先插入串口号大的(如COM4),再插入串口号小的(如COM3),此时虽能发现两个串口,但都是同一串口号(COM4)的问题,同时也读不了COM大于10以上的串口
dwName = sizeof(Name);
dwSizeofPortName = sizeof(szPortName);
} while((Status == ERROR_SUCCESS)||(Status == ERROR_MORE_DATA));
RegCloseKey(hKey);
}
/*******************************************************************************************************************************/
len = i;
if(len > len1) //有新的串口插入
{
m_ctrlComboCom.ResetContent();
for(i=0;i<len;i++) //重新加载串口列表
m_ctrlComboCom.AddString(strSerialList[i]);
m_ctrlComboCom.SetWindowText(str);
}
else //少了一个串口,但仍然有串口存在
{
if(len == 0) //热拔出后不再有串口存在
{
m_ctrlComboCom.ResetContent();
}
else //热拔出后仍有串口存在
{
for(i=0;i<len;i++)
{
if(strSerialList[i] == str)
break;
}
m_ctrlComboCom.ResetContent();
int j;
for(j=0;j<len;j++) //重新加载串口列表
m_ctrlComboCom.AddString(strSerialList[j]);
if(i == len)
{//在新的串口表里没有找到编辑框中的串口
m_ctrlComboCom.SetCurSel(0); //设置默认串口
if(m_bSerialPortOpened == TRUE)
{
//m_SerialPort.StopMonitoring();
m_SerialPort.ClosePort();
m_ctrlBtnOpenClose.SetIcon(IDI_ICON2); //更换图标
m_ctrlBtnOpenClose.SetFlat(FALSE);
SetDlgItemText(IDC_BUTTON_OPEN, _T("打开串口"));
//AfxMessageBox(_T("串口关闭成功!"));
m_bSerialPortOpened = FALSE;
}
}
else if(i<len)
{
m_ctrlComboCom.SetWindowText(str);
}
//AfxMessageBox(str);
}
}
return TRUE;
}
代码终于插入进来了,求各位大神帮忙看看吧,谢谢!