我想通过WM_DEVICECHANGE来判断插入USB的操作,同时得到USB的串口,请问有没有人知道怎么实现的? 谢谢。

解决方案 »

  1.   


    LRESULT   CTestUSBDlg::WindowProc(UINT   message,   WPARAM   wParam,   LPARAM   lParam)    
      {  
      if(message   ==   WM_DEVICECHANGE)   //0x8000,0x8004  
      {  
      CString   str;  
      DEV_BROADCAST_HDR*   dhr   =   (DEV_BROADCAST_HDR   *)lParam;  
      switch(wParam)  
      {  
      case   DBT_CONFIGCHANGECANCELED:  
      TRACE("DBT_CONFIGCHANGECANCELED");  
      break;  
      case   DBT_CONFIGCHANGED:  
      TRACE("DBT_CONFIGCHANGED");  
      break;  
      case   DBT_DEVICEQUERYREMOVE:  
      TRACE("DBT_DEVICEQUERYREMOVE");  
      break;  
      case   DBT_DEVICEQUERYREMOVEFAILED:  
      TRACE("DBT_DEVICEQUERYREMOVEFAILED");  
      break;  
      case   DBT_DEVICEREMOVEPENDING:  
      TRACE("DBT_DEVICEREMOVEPENDING");  
      break;  
      case   DBT_DEVICETYPESPECIFIC:  
      TRACE("DBT_DEVICETYPESPECIFIC");  
      break;  
      case   DBT_QUERYCHANGECONFIG:  
      TRACE("DBT_QUERYCHANGECONFIG");  
      break;  
      case   DBT_USERDEFINED:  
      TRACE("DBT_USERDEFINED");  
      break;  
      case   DBT_DEVICEARRIVAL:  
      if(dhr->dbch_devicetype   ==   DBT_DEVTYP_VOLUME)  
      {  
      PDEV_BROADCAST_VOLUME   lpdbv   =   (PDEV_BROADCAST_VOLUME)dhr;  
      if(lpdbv->dbcv_flags   &   DBTF_MEDIA)  
      {  
      str.Format("Drive   %c   插入",   FirstDriveFromMask(lpdbv   ->dbcv_unitmask));  
      //AfxMessageBox(str);  
      }  
      else  
      {  
      char   ch   =   FirstDriveFromMask(lpdbv   ->dbcv_unitmask);  
      str.Format("%c:\\",ch);  
      }  
      }  
      break;  
      case   DBT_DEVICEREMOVECOMPLETE:  
      if(dhr->dbch_devicetype   ==   DBT_DEVTYP_VOLUME)  
      {  
      PDEV_BROADCAST_VOLUME   lpdbv   =   (PDEV_BROADCAST_VOLUME)dhr;  
      if(lpdbv->dbcv_flags   &   DBTF_MEDIA)  
      {  
      str.Format("Drive   %c   拔除",FirstDriveFromMask(lpdbv   ->dbcv_unitmask));  
      }  
      else  
      {  
      str.Format("Drive   %c   拔除",FirstDriveFromMask(lpdbv   ->dbcv_unitmask));  
      }  
      //AfxMessageBox(str);  
      }  
      break;  
      default:  
      break;  
      }  
      }  
      return   CDialog::WindowProc(message,   wParam,   lParam);  
      }
      

  2.   

    查询注册表HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Enum\\USB
      

  3.   


    BOOL GetExistingDevicePortName(LPTSTR dwHardwareID, LPTSTR szPortName, SIZE_T lpcbPortName)
    {
        ZeroMemory(szPortName, lpcbPortName);    HDEVINFO DeviceInfoSet = SetupDiGetClassDevs(NULL, 0, 0, DIGCF_ALLCLASSES | DIGCF_PRESENT);    if (DeviceInfoSet == INVALID_HANDLE_VALUE) 
        { 
            return FALSE; 
        }     BOOL Found = FALSE;
        DWORD i = 0, err = 0;
        SP_DEVINFO_DATA DeviceInfoData;    DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
        while ( !Found && SetupDiEnumDeviceInfo(DeviceInfoSet, i++, &DeviceInfoData)) 
        { 
            DWORD DataT = 0; 
            LPTSTR p = NULL, buffer = NULL; 
            DWORD buffersize = 0;        while (!SetupDiGetDeviceRegistryProperty(DeviceInfoSet, &DeviceInfoData, SPDRP_HARDWAREID, &DataT, (PBYTE)buffer, buffersize, &buffersize))
            {
                if (GetLastError() == ERROR_INVALID_DATA) 
                { 
                    break; 
                } 
                else if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) 
                { 
                    if (buffer) 
                        LocalFree(buffer);                 buffer = (char *)LocalAlloc(LPTR,buffersize); 
                } 
                else 
                { 
                    err = 1; 
                    break; 
                } 
            }        if (GetLastError() == ERROR_INVALID_DATA) 
                continue;         if (err) 
                break;        for (p = buffer; *p && (p < &buffer[buffersize]); p += lstrlen(p) + sizeof(TCHAR)) 
            { 
                if (!_tcsicmp(dwHardwareID, p)) 
                { 
                    Found = TRUE; 
                    break; 
                } 
            }        if (buffer) 
                LocalFree(buffer); 
        }    if (Found) 
        { 
            HKEY DeviceKey = SetupDiOpenDevRegKey(DeviceInfoSet, &DeviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_READ);
            if (DeviceKey != INVALID_HANDLE_VALUE)
            {
                TCHAR chPortName[MAX_PATH];
                DWORD lType = 0, lpcbData = MAX_PATH;            if (RegQueryValueEx(DeviceKey, "PortName", NULL, &lType, (PBYTE)chPortName, &lpcbData) == ERROR_SUCCESS)
                {
                    if (lpcbPortName >= lpcbData)
                        CopyMemory(szPortName, chPortName, lpcbData);
                }
                
                RegCloseKey(DeviceKey);
            }
        }     err = GetLastError(); 
        SetupDiDestroyDeviceInfoList(DeviceInfoSet); 
        SetLastError(err);     return err == NO_ERROR; 
    }
      

  4.   

    谢谢,但是上面的代码好象是获取所有的串口吧? 能不能得到刚插入的USB的串口?
      

  5.   

    Detecting Hardware Insertion and/or Removalhttp://www.codeproject.com/KB/system/HwDetect.aspx
    另外你说的“USB的串口”,什么意思
      

  6.   

    谢谢,这个程序我看过了,也是找不到串口,就是USB连接到的设备的串口。
      

  7.   

    有一个办法,可以得到在接收到DBT_DEVICEARRIVAL消息后,枚举所有串口, 获取串口描述信息,可以得到"USB Serial Port(COM1)"之类的信息,这个就是usb串口,最后的就是串口号了,其它一般主板上的串口都是"通信端口 (com1)"之类的,这样你就可以区分了推荐一个已经封装好的类,直接使用即可 http://www.codeguru.com/Cpp/W-P/system/hardwareinformation/article.php/c5721/ 
    添加里面的“ EnumSerial.cpp ”和“ EnumSerial.h ”两个文件,并且将 Setupapi.lib 包含进你的工程文件中就行了 调用方式如下: CArray<SSerInfo,SSerInfo&> asi;
      // Populate the list of serial ports.
      EnumSerialPorts(asi,FALSE/*include all*/);  for (int ii=0; ii<asi.GetSize(); ii++) {
        CString str = (asi[ii].strFriendlyName);
    }返回的字符串含有你需要的信息"USB Serial Port(COM1)" 
      

  8.   

    谢谢,呵呵,但这种方法可以枚举的结果应该是所有的串口吧? 好象就算没有USB线 仍然有很多的COM串口的.
      

  9.   


    没有关系,一般的串口和usb转换串口的描述信息是不一样的,
    CArray<SSerInfo,SSerInfo&> asi;
      // Populate the list of serial ports.
      EnumSerialPorts(asi,FALSE/*include all*/);  for (int ii=0; ii<asi.GetSize(); ii++) 
      {
        CString str = (asi[ii].strFriendlyName);    if (str.Find("USB Serial Port") != -1 )
        {
           MessageBox("此串口为usb串口");
        }

      } 
      

  10.   

    另外上面枚举串口可以结合WM_DEVICECHANGE消息来处理,即在WM_DEVICECHANGE消息里面进行串口枚举以及分析,
    这样如果不是插入usb串口,根本就不会进行串口枚举
      

  11.   

    谢谢ilovedrv大大,我的问题已经解决了,但是另外一种方法实现的:
    代码贴出来:
    BOOL CMainFrame::OnDeviceChange( UINT nEventType, DWORD dwData) 
    {
      PDEV_BROADCAST_HDR   pDevBroadcastHdr;    
      PDEV_BROADCAST_VOLUME   pDevBroadcastVolume;    
      PDEV_BROADCAST_PORT pDevPort;
      CString   strVolume="";    
      switch   (nEventType)    
      {    
      case   DBT_DEVICEARRIVAL:    
      pDevBroadcastHdr   =   (PDEV_BROADCAST_HDR)   dwData;    
      pDevPort = (PDEV_BROADCAST_PORT)pDevBroadcastHdr;
      if   (pDevBroadcastHdr->dbch_devicetype   ==   DBT_DEVTYP_VOLUME)    
      {    
      pDevBroadcastVolume   =   (PDEV_BROADCAST_VOLUME)pDevBroadcastHdr;    
      xJudgeDeviceChangePath(pDevBroadcastVolume->dbcv_unitmask,strVolume);    
      } 
      else if(pDevBroadcastHdr->dbch_devicetype  == DBT_DEVTYP_PORT)
      {
      //串口
       AfxMessageBox(pDevPort->dbcp_name);
      }
      break;        
      default:    
      break;   
      }     
    return TRUE;
    }
    这个代码参考了网上的还有CODEproject上的代码,揭贴了,呵呵