importwin32api,win32con,win32guifromctypesimport*## Device change events (WM_DEVICECHANGE wParam)#DBT_DEVICEARRIVAL=0x8000DBT_DEVICEQUERYREMOVE=0x8001DBT_DEVICEQUERYREMOVEFAILED=0x8002DBT_DEVICEMOVEPENDING=0x8003DBT_DEVICEREMOVECOMPLETE=0x8004DBT_DEVICETYPESSPECIFIC=0x8005DBT_CONFIGCHANGED=0x0018## type of device in DEV_BROADCAST_HDR#DBT_DEVTYP_OEM=0x00000000DBT_DEVTYP_DEVNODE=0x00000001DBT_DEVTYP_VOLUME=0x00000002DBT_DEVTYPE_PORT=0x00000003DBT_DEVTYPE_NET=0x00000004## media types in DBT_DEVTYP_VOLUME#DBTF_MEDIA=0x0001DBTF_NET=0x0002WORD=c_ushort
DWORD=c_ulongclassDEV_BROADCAST_HDR(Structure):_fields_=[("dbch_size",DWORD),("dbch_devicetype",DWORD),("dbch_reserved",DWORD)]classDEV_BROADCAST_VOLUME(Structure):_fields_=[("dbcv_size",DWORD),("dbcv_devicetype",DWORD),("dbcv_reserved",DWORD),("dbcv_unitmask",DWORD),("dbcv_flags",WORD)]defdrive_from_mask(mask):n_drive=0while1:if(mask&(2**n_drive)):returnn_driveelse:n_drive+=1classNotification:def__init__(self):message_map={win32con.WM_DEVICECHANGE:self.onDeviceChange}wc=win32gui.WNDCLASS()hinst=wc.hInstance=win32api.GetModuleHandle(None)wc.lpszClassName="DeviceChangeDemo"wc.style=win32con.CS_VREDRAW|win32con.CS_HREDRAW
wc.hCursor=win32gui.LoadCursor(0,win32con.IDC_ARROW)wc.hbrBackground=win32con.COLOR_WINDOW
wc.lpfnWndProc=message_map
classAtom=win32gui.RegisterClass(wc)style=win32con.WS_OVERLAPPED|win32con.WS_SYSMENU
self.hwnd=win32gui.CreateWindow(classAtom,"Device Change Demo",style,0,0,win32con.CW_USEDEFAULT,win32con.CW_USEDEFAULT,0,0,hinst,None)defonDeviceChange(self,hwnd,msg,wparam,lparam):## WM_DEVICECHANGE:# wParam - type of change: arrival, removal etc.# lParam - what's changed?# if it's a volume then...# lParam - what's changed more exactly#dev_broadcast_hdr=DEV_BROADCAST_HDR.from_address(lparam)ifwparam==DBT_DEVICEARRIVAL:print("Something's arrived")ifdev_broadcast_hdr.dbch_devicetype==DBT_DEVTYP_VOLUME:print("It's a volume!")dev_broadcast_volume=DEV_BROADCAST_VOLUME.from_address(lparam)ifdev_broadcast_volume.dbcv_flags&DBTF_MEDIA:print("with some media")drive_letter=drive_from_mask(dev_broadcast_volume.dbcv_unitmask)print("in drive",chr(ord("A")+drive_letter))return1if__name__=='__main__':w=Notification()win32gui.PumpMessages()