MFC中串口操作的问题,求各位大神帮忙看看 10C

我想在MFC中实现当接入计算机的串口有所变化时,在组合框中改变相应列表项,并且当拔出的是当前已经选择的串口时,将打开/关闭按键的显示状态改变,同时关闭相应串口,其他情况下不改变已经选择串口的状态,但是我发现不管怎么改变插入拔出哪个串口,打开/关闭按键都会变为关闭状态(当前面是打开状态时),调试了一个早上,还是没发现问题,各位大神能不能帮忙看看怎么回事,谢谢了!

5个回答

这个是代码,是通过捕获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;
}


  1. 是这样插入代码吗?
 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;
}

代码终于插入进来了,求各位大神帮忙看看吧,谢谢!

Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
立即提问