본문 바로가기

Dev/[MFC]

[MFC] WM_DEVICECHANGE 메시지를 이용한 USB 디바이스 감지 Detect USB devices using WM_DEVICECHANGE messages

반응형

 

 

Step 1:

헤더파일(~~~Dlg.h)에 #include <Dbt.h> 추가

 

 

 

Step 2:

우선USB 탈 착을 감지하기위해 현재연결된 / 곧 연결될 USB 정보를 등록해야함..

함수하나 만들어서

 

bool (클래스명)::JigRegDevNoti()
{
   HDEVNOTIFY hDevNotify;
   DEV_BROADCAST_DEVICEINTERFACE NotificationFilter;
   ZeroMemory(&NotificationFilter, sizeof(NotificationFilter));
   NotificationFilter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
   NotificationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
   for (int i = 0; i<sizeof(GUID_DEVINTERFACE_LIST) / sizeof(GUID); i++) {
    	NotificationFilter.dbcc_classguid = GUID_DEVINTERFACE_LIST[i];
		hDevNotify = RegisterDeviceNotification(this->GetSafeHwnd(), &NotificationFilter, DEVICE_NOTIFY_WINDOW_HANDLE);
 		if (!hDevNotify) {
   			AfxMessageBox(CString("Can't register device notification: ")
    		+ _com_error(GetLastError()).ErrorMessage(), MB_ICONEXCLAMATION);
   			return FALSE;
  		}
 	}
}
 

 

이렇게 구현.

구현하면 GUID_DEVINTERFACE_LIST 변수가 없다는 경고가 나온다. 여기서 이 변수를 선언해줘야하는데

구글에서 RegisterDeviceNotification 함수를 검색하여 본인에 맞는 GUID 선언하면된다.

(이 부분은 각자의 사용 용도에 따라 다르기 때문에 소스를 추가 할 수 없고 필요에 맞게 검색을 통해 찾아야 한다.)

 

static const GUID GUID_DEVINTERFACE_LIST[] = { ........}
와 같이 선언/정의하면된다.

 

이 함수를 OninitDlg 에 넣어주고 프로그램 열릴때 실행되도록 한다.

 

 

 

Step 3:

소스파일(~~~Dlg.cpp)의 메시지 맵에 아래의 메시지를 추가

(디바이스 변경사항 감지하는 메시지)

ON_MESSAGE(WM_DEVICECHANGE, OnMyDeviceChange)

 

 

 

 

 

Step 4:

메시지 맵에 함께 등록한 OnMyDeviceChange 함수를 구현해야 함.

 

--> 헤더파일 (~~~Dlg.h) 에 일단 함수 원형을 선언

afx_msg LRESULT OnMyDeviceChange(UINT nEventType, LPARAM lParam);

 

--> 소스파일(~~~Dlg.cpp) 에 함수 구현

 

LRESULT (클래스명)::OnMyDeviceChange(UINT nEventType, LPARAM lParam)
{
 char msg[64];

// 메시지맵에 추가된 디바이스체인지 메시지로인해

// USB가 탈/착 될때 이 OnMyDeviceChange함수가 호출되는데

// nEventType (WParam) 값이 이게 탈 인지 착 인지에 따라

// DBT_DEVICEARRIVAL  (착), DBT_DEVICEREMOVECOMPLETE(탈)

// 로 들어온다. 더 자세한것이나 다른건 MSDN 참조하길 바람..

// 보통은 이거 두개만쓰지않을까..



// 제거 시..
 if (nEventType == DBT_DEVICEREMOVECOMPLETE) {
  PDEV_BROADCAST_HDR pHdr = (PDEV_BROADCAST_HDR)lParam;
  PDEV_BROADCAST_DEVICEINTERFACE pDevInf;
  PDEV_BROADCAST_HANDLE pDevHnd;
  PDEV_BROADCAST_OEM pDevOem;
  PDEV_BROADCAST_PORT pDevPort;
  PDEV_BROADCAST_VOLUME pDevVolume;
  switch (pHdr->dbch_devicetype) {

​

  case DBT_DEVTYP_DEVICEINTERFACE:

 // 여기로 들어온다.

// 제거되었을때 발생하는함수를

//이 updateDevice 라는 함수로 구현해주어야함
   pDevInf = (PDEV_BROADCAST_DEVICEINTERFACE)pHdr;
   UpdateDevice(pDevInf, nEventType);
   break;

  case DBT_DEVTYP_HANDLE:
   pDevHnd = (PDEV_BROADCAST_HANDLE)pHdr;
   break;

  case DBT_DEVTYP_OEM:
   pDevOem = (PDEV_BROADCAST_OEM)pHdr;
   break;

  case DBT_DEVTYP_PORT:
   if (DBT_DEVICEARRIVAL == nEventType) {
    strcpy_s(msg, 64, "Connedted.");
   }
   else {
    strcpy_s(msg, 64, "Disconnedted.");
   }
   pDevPort = (PDEV_BROADCAST_PORT)pHdr;
   //dprintf("DBT_DEVTYP_PORT=%s is %s", pDevPort->dbcp_name, msg);
   break;

  case DBT_DEVTYP_VOLUME:
   pDevVolume = (PDEV_BROADCAST_VOLUME)pHdr;
   break;
  }
 }
 else if(nEventType == DBT_DEVICEARRIVAL){
  PDEV_BROADCAST_HDR pHdr = (PDEV_BROADCAST_HDR)lParam;
  PDEV_BROADCAST_DEVICEINTERFACE pDevInf;
  PDEV_BROADCAST_HANDLE pDevHnd;
  PDEV_BROADCAST_OEM pDevOem;
  PDEV_BROADCAST_PORT pDevPort;
  PDEV_BROADCAST_VOLUME pDevVolume;
  switch (pHdr->dbch_devicetype) {
  case DBT_DEVTYP_DEVICEINTERFACE:

 // 여기로 들어온다.

// 삽입되었을때 발생하는함수를

//이 updateDeviceOn 라는 함수로 구현해주어야함
   pDevInf = (PDEV_BROADCAST_DEVICEINTERFACE)pHdr;
   UpdateDeviceOn(pDevInf, nEventType);
   break;

  case DBT_DEVTYP_HANDLE:
   pDevHnd = (PDEV_BROADCAST_HANDLE)pHdr;
   break;

  case DBT_DEVTYP_OEM:
   pDevOem = (PDEV_BROADCAST_OEM)pHdr;
   break;

  case DBT_DEVTYP_PORT:
   if (DBT_DEVICEARRIVAL == nEventType) {
    strcpy_s(msg, 64, "Connedted.");
   }
   else {
    strcpy_s(msg, 64, "Disconnedted.");
   }
   pDevPort = (PDEV_BROADCAST_PORT)pHdr;
   //dprintf("DBT_DEVTYP_PORT=%s is %s", pDevPort->dbcp_name, msg);
   break;

  case DBT_DEVTYP_VOLUME:
   pDevVolume = (PDEV_BROADCAST_VOLUME)pHdr;
   break;
  }
 }
 return 0;
}

 

 

주석 잘 보면서 하면 쉽게 이해 되도록 적어 놓았습니다.^^

 

 

Step 5:

void UpdateDevice(PDEV_BROADCAST_DEVICEINTERFACE pDevInf, WPARAM wParam);
void UpdateDeviceOn(PDEV_BROADCAST_DEVICEINTERFACE pDevInf, WPARAM wParam);

헤더파일에 위 두 함수(착/탈) 선언하고

소스파일에 이 두 함수를 구현하면 된다.

각각 함수의 용도에 맞게 제거되었을때의 할 동작, 삽입되었을때 할 동작을 본인의 스타일에 맞게

작성하면 된다.

반응형

'Dev > [MFC]' 카테고리의 다른 글

[MFC] Ping Test해보기  (0) 2020.11.13
[MFC] Grid Control 사용해보기  (0) 2020.11.13
[MFC] 멀티바이트 환경에서 유니코드 문자 set하기  (0) 2020.10.28