Announcement

Collapse
No announcement yet.

Question for Pierre Bellisle - Re: WM_DEVICECHANGE & SHCNE_DISKEVENTS

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Question for Pierre Bellisle - Re: WM_DEVICECHANGE & SHCNE_DISKEVENTS

    Hi Pierre!
    I found this code of yours on the internet but I cant get it to compile and run in pbwin10.
    http://codesite.atwebpages.com/Power...ICECHANGE.html
    Any idea why it is failing?

    Code:
    #COMPILE EXE '#Win 8.04#
    #DIM ALL
    #INCLUDE "Win32api.inc"
    
    GLOBAL hDlg AS DWORD
    
    %Textbox = 101
    
    %WM_DEVICECHANGE             = &H219&  'Notifies application of change to hardware configuration of device or computer.
    %DBT_CONFIGCHANGECANCELED    = &H19&   'Request to change the current configuration (dock or undock) has been canceled.
    %DBT_CONFIGCHANGED           = &H18&   'Current configuration changed, due to a dock or undock.
    %DBT_CUSTOMEVENT             = &H8006& 'Custom event.
    %DBT_DEVICEARRIVAL           = &H8000& 'Device or piece of media has been inserted and is now available.
    %DBT_DEVICEQUERYREMOVE       = &H8001& 'Permission requested to remove Device or media. (Any application can deny this request and cancel the removal.)
    %DBT_DEVICEQUERYREMOVEFAILED = &H8002& 'Request to remove device or media canceled.
    %DBT_DEVICEREMOVECOMPLETE    = &H8004& 'Device or Media removed.
    %DBT_DEVICEREMOVEPENDING     = &H8003& 'Device or Media about to be removed. Cannot be denied.
    %DBT_DEVICETYPESPECIFIC      = &H8005& 'Device-specific event.
    %DBT_DEVNODES_CHANGED        = &H7&    'Device added or removed from the system.
    %DBT_QUERYCHANGECONFIG       = &H17&   'Permission requested to change current configuration, dock or undock.
    %DBT_USERDEFINED             = &HFFFF& 'User-Defined.
    
    %DBTF_MEDIA = 1 'Media comings and goings
    %DBTF_NET   = 2 'Network volume
    
    %DEVICE_NOTIFY_ALL_INTERFACE_CLASSES = &H4& 'All Interfaces.
    %DEVICE_NOTIFY_WINDOW_HANDLE         = 0    'Notifications sent using WM_POWERBROADCAST with wParam = PBT_POWERSETTINGCHANGE.
    %DEVICE_NOTIFY_SERVICE_HANDLE        = 1    'Notifications sent to HandlerEx callback function with dwControl = SERVICE_CONTROL_POWEREVENT and dwEventType = PBT_POWERSETTINGCHANGE.
    %GWL_WNDPROC                         = (-4) 'Sets new address for the window procedure. Windows NT/2000/XP: Can not change attribute if window does not belong to same process as alling thread.
    %UNSAFE_REMOVE                       = &H1C&'Unsafe removal of device.
    %SHCNRF_SHELLLEVEL                   = 2
    
    %DBT_DEVTYP_OEM             = &H0& 'Original Equipment Manufacturer(OEM) or Independent Hardware Vendor(IHV) defined device type. It's a DEV_BROADCAST_OEM structure.
    %DBT_DEVTYP_DEVNODE         = &H1& 'Devnode number, specific to Windows 95.
    %DBT_DEVTYP_VOLUME          = &H2& 'Logical volume. This structure is a DEV_BROADCAST_VOLUME structure.
    %DBT_DEVTYP_PORT            = &H3& 'Port device, serial or parallel. It's a DEV_BROADCAST_PORT structure.
    %DBT_DEVTYP_NET             = &H4& 'Network Resource UNC.
    %DBT_DEVTYP_DEVICEINTERFACE = &H5& 'Class of devices. It's a DEV_BROADCAST_DEVICEINTERFACE structure.
    %DBT_DEVTYP_HANDLE          = &H6& 'File system handle. It's a DEV_BROADCAST_HANDLE structure.
    
    TYPE DEV_BROADCAST_HDR
     DbhSize        AS DWORD 'Size of Structure. If User-Defined event, this must be size of header, plus size of variable-length data in a DEV_BROADCAST_USERDEFINED structure.
     DbhDeviceType  AS DWORD 'Device Type, could be interface, handle, OEM, port or Volume.
     DbhReserved    AS DWORD 'Reserved.
    END TYPE
    
    TYPE DEV_BROADCAST_DEVICEINTERFACE
     DbDiSize       AS DWORD 'Size of Structure.
     DbDiDeviceType AS DWORD 'Set to %DBT_DEVTYP_DEVICEINTERFACE to get Interface Type.
     DbDiReserved   AS DWORD 'Reserved.
     DbDiClassguid  AS GUID  'GUID for Interface Device Class.
     DbDiName       AS ASCIIZ * %MAX_PATH 'When returned through %WM_DEVICECHANGE message, converted to ANSI as appropriate.
    END TYPE                              'Services always receive a Unicode string with both RegisterDeviceNotificationW and RegisterDeviceNotificationA.
    
    TYPE DEV_BROADCAST_HANDLE
     DbhSize        AS DWORD 'Size of Structure.
     DbhDeviceType  AS DWORD 'Set to %DBT_DEVTYP_HANDLE.
     DbhReserved    AS DWORD 'Reserved.
     DbhHandle      AS DWORD 'Handle in RegisterDeviceNotification function.
     DbhHdevNotify  AS DWORD 'Handle to device notification, returned by the RegisterDeviceNotification.
     DbhEventGuid   AS GUID  'Custom event GUID           Valid only for DBT_CUSTOMEVENT.
     DbhNameOffset  AS LONG  'The offset to event name.   Valid only for DBT_CUSTOMEVENT.
     DbhData(0)     AS BYTE  'Optional binary data.       Valid only for DBT_CUSTOMEVENT.
    END TYPE
    
    TYPE DEV_BROADCAST_OEM
     DboSize        AS DWORD 'Size of Structure.
     DboDeviceType  AS DWORD 'Set to %DBT_DEVTYPE_OEM.
     DboReserved    AS DWORD 'Reserved.
     DboIdentifier  AS DWORD 'OEM-specific identifier for the device.
     DboSuppfunc    AS DWORD 'OEM-specific function value. Possible values depend on the device.
    END TYPE
    
    TYPE DEV_BROADCAST_VOLUME
     Dbvsize        AS DWORD 'Size of Structure.
     DbvDeviceType  AS DWORD 'Set to %DBT_DEVTYP_VOLUME.
     DbvReserved    AS DWORD 'Reserved.
     DbvUnitmask    AS DWORD 'Logical drive, bit 0 is A:, bit 1 is B:...
     DbvFlags       AS WORD  'If %DBTF_MEDIA, change affects media in drive else change affects physical device or drive. %DBTF_NET = network volume.
    END TYPE
    
    TYPE DEV_BROADCAST_PORT
     DbpSize        AS DWORD 'Size of Structure.
     DbpDeviceType  AS DWORD 'Set to %DBT_DEVTYP_PORT - Set to check if a port device, see DEV_BROADCAST_DEVICEINTERFACE to find interface.
     DbpReserved    AS DWORD 'Reserved.
     DbpName        AS ASCIIZ * %MAX_PATH 'Device friendly name such as "Com1" and "Standard 28800 bps Modem", etc.
    END TYPE
    
    TYPE SHChangeNotifyEntry
     pidl       AS ITEMIDLIST POINTER
     fRecursive AS LONG
    END TYPE
    
    DECLARE FUNCTION SHChangeNotifyRegister LIB "SHELL32.DLL" ALIAS "SHChangeNotifyRegister" _
    (BYVAL HWND AS DWORD, BYVAL fSources AS LONG, BYVAL fEvents AS LONG, BYVAL wMsg AS DWORD, _
     BYVAL cEntries AS LONG, BYREF ChangeNotifyEntry AS SHChangeNotifyEntry) AS DWORD
    
    DECLARE FUNCTION SHChangeNotifyDeregister LIB "SHELL32.DLL" ALIAS "SHChangeNotifyDeregister"(BYVAL ulID AS DWORD) AS LONG
    '______________________________________________________________________________
    
    SUB TextAdd (BYVAL sAddToText AS STRING)
     LOCAL sBuffer AS STRING
    
     CONTROL GET TEXT hDlg, %Textbox TO sBuffer
     IF LEN(sBuffer) THEN
       sBuffer = sBuffer & $CRLF & sAddToText
     ELSE
       sBuffer = sAddToText
     END IF
     CONTROL SET TEXT hDlg, %Textbox, sBuffer
     CONTROL SET FOCUS hDlg, %Textbox
     CONTROL SEND hDlg, %Textbox, %EM_SETSEL, LEN(sBuffer), LEN(sBuffer)
     CONTROL SEND hDlg, %Textbox, %EM_SCROLLCARET, 0, 0 'To scroll the caret into view
    
    END SUB
    '______________________________________________________________________________
    
    FUNCTION DeviceEventGet(BYVAL wParam AS DWORD, BYVAL pDevBroadCastHeader AS DEV_BROADCAST_HDR POINTER)AS STRING
     LOCAL pDevBroadcastDeviceinterface AS DEV_BROADCAST_DEVICEINTERFACE POINTER
     LOCAL pDevBroadcastHandle          AS DEV_BROADCAST_HANDLE POINTER
     LOCAL pDevBroadcastOem             AS DEV_BROADCAST_OEM POINTER
     LOCAL pDevBroadcastPorts           AS DEV_BROADCAST_PORT POINTER
     LOCAL pDevBroadcastVolume          AS DEV_BROADCAST_VOLUME POINTER
     LOCAL sMessage                     AS STRING
     LOCAL sDriveName                   AS STRING
     LOCAL sDriveFlags                  AS STRING
     LOCAL sManufacturer                AS STRING
     LOCAL sProduct                     AS STRING
     LOCAL sRevision                    AS STRING
     LOCAL sDiskSerial                  AS STRING
     LOCAL sTry                         AS STRING
     LOCAL Looper                       AS LONG
     LOCAL CharPos1                     AS LONG
     LOCAL CharPos2                     AS LONG
    
     SELECT CASE @pDevBroadCastHeader.DbhDevicetype
    
       CASE %DBT_DEVTYP_DEVICEINTERFACE 'DEV_BROADCAST_DEVICEINTERFACE - Device's class
         pDevBroadcastDeviceinterface = pDevBroadCastHeader
         sMessage = "DBT_DEVTYP_DEVICEINTERFACE - GUID: " & _
                    GUIDTXT$(@pDevBroadcastDeviceinterface.DbDiClassguid) & _
                    " - Interface name: " & @pDevBroadcastDeviceinterface.DbDiName
    
         sManufacturer = "None"
         sProduct      = sManufacturer
         sRevision     = sManufacturer
         sDiskSerial   = sManufacturer
         sTry = LCASE$(@pDevBroadcastDeviceinterface.DbDiName)
         CharPos1 = INSTR(sTry, "&ven_" )
         IF CharPos1 THEN
           CharPos2 = INSTR(CharPos1 ,sTry, "&prod_")
           IF CharPos2 THEN
             CharPos1 = CharPos1 + 5 'LEN("&ven_")
             IF (CharPos2 - CharPos1) THEN sManufacturer = MID$(@pDevBroadcastDeviceinterface.DbDiName, CharPos1, CharPos2 - CharPos1)
             CharPos1 = INSTR(CharPos2, sTry, "&rev_")
             IF CharPos1 THEN
               CharPos2 = CharPos2 + 6 'LEN("&prod_")
               IF (CharPos1 - CharPos2) THEN sProduct = MID$(@pDevBroadcastDeviceinterface.DbDiName, CharPos2, CharPos1 - CharPos2)
               CharPos2 = INSTR(CharPos1, sTry, "#")
               IF CharPos2 THEN
                 CharPos1 = CharPos1 + 5 'LEN("&rev_")
                 IF (CharPos2 - CharPos1) THEN sRevision = MID$(@pDevBroadcastDeviceinterface.DbDiName, CharPos1, CharPos2 - CharPos1)
                 CharPos1 = INSTR(CharPos2, sTry, "&0#")
                 IF CharPos1 THEN
                   sDiskSerial = MID$(@pDevBroadcastDeviceinterface.DbDiName, CharPos2 + 1, CharPos1 - CharPos2 - 1)
                   sMessage = sMessage & $CRLF & $TAB & $TAB & $TAB & "Manufacturer: " & sManufacturer & _
                              ", product: " & sProduct & ", revision: " & sRevision & ", serial number: " & sDiskSerial
                 END IF
               END IF
             END IF
           END IF
         END IF
    
       CASE %DBT_DEVTYP_HANDLE 'DEV_BROADCAST_HANDLE - File system handle.
         pDevBroadcastHandle = pDevBroadCastHeader
         sMessage = "DBT_DEVTYP_HANDLE - Handle: " & STR$(@pDevBroadcastHandle.DbhHandle) & _
                    " - Notify: "      & STR$(@pDevBroadcastHandle.DbhHdevNotify) & _
                    IIF$((wParam = %DBT_CUSTOMEVENT), _
                    " - Guid: "        & GUIDTXT$(@pDevBroadcastHandle.DbhEventGuid) & _  'Valid only for DBT_CUSTOMEVENT
                    " - Name offset: " & STR$(@pDevBroadcastHandle.DbhNameOffset)& _      'Valid only for DBT_CUSTOMEVENT
                    " - Data: "        & STR$(@pDevBroadcastHandle.DbhData(0)),  "")      'Valid only for DBT_CUSTOMEVENT
    
       CASE %DBT_DEVTYP_OEM 'DEV_BROADCAST_OEM - OEM or IHV device.
         pDevBroadcastOem = pDevBroadCastHeader
         sMessage = "DBT_DEVTYP_OEM - Identifier: " & STR$(@pDevBroadcastOem.DboIdentifier) & _
                    " - SuppFunc: " & STR$(@pDevBroadcastOem.DboSuppFunc)
    
       CASE %DBT_DEVTYP_PORT 'DEV_BROADCAST_PORT - Port device like serial or parallel.
         pDevBroadcastPorts = pDevBroadCastHeader
         sMessage = "DBT_DEVTYP_PORT - Port name: " & @pDevBroadcastPorts.DbpName
    
       CASE %DBT_DEVTYP_VOLUME 'DEV_BROADCAST_VOLUME - Logical volume.
         pDevBroadcastVolume = pDevBroadCastHeader
         FOR Looper = 0 TO 25
           IF BIT(@pDevBroadcastVolume.DbvUnitMask, Looper) THEN
             sDriveName = CHR$(65 + Looper) & ":" '65 = "A"
             EXIT FOR
           END IF
         NEXT
         SELECT CASE @pDevBroadcastVolume.dbvFlags
           CASE 0           : sDriveFlags = "Local Drive"   'Local Volume
           CASE %DBTF_MEDIA : sDriveFlags = "Media Drive"   'Media Volume
           CASE %DBTF_NET   : sDriveFlags = "Network Drive" 'Network volume
         END SELECT
         sMessage = "DBT_DEVTYP_VOLUME - Drive name: " & sDriveName & " - Flag: " & sDriveFlags
         sMessage = sMessage & $CRLF & $TAB & $TAB & $TAB & "Drive letter: " & sDriveName & $SPC & sDriveFlags
    
     END SELECT
     FUNCTION = sMessage
    
    END FUNCTION
    '______________________________________________________________________________
    
    CALLBACK FUNCTION ShowDIALOG1Proc()
     LOCAL  sMessage                       AS STRING
     LOCAL  DeviceBroadCastHeader          AS DEV_BROADCAST_HDR
     LOCAL  DeviceBroadCastOem             AS DEV_BROADCAST_OEM
     LOCAL  DeviceBroadCastVolume          AS DEV_BROADCAST_VOLUME
     LOCAL  DeviceBroadCastPort            AS DEV_BROADCAST_PORT
     LOCAL  DeviceBroadCastDeviceInterface AS DEV_BROADCAST_DEVICEINTERFACE
     LOCAL  DeviceBroadCastHandle          AS DEV_BROADCAST_HANDLE
     STATIC SelStart                       AS LONG
     STATIC SelEnd                         AS LONG
     LOCAL  RetVal                         AS LONG
     STATIC hFocusBak                      AS DWORD
     LOCAL  ppIdList                       AS DWORD POINTER
     LOCAL  pIdList1                       AS DWORD POINTER
     LOCAL  pIdList2                       AS DWORD POINTER
     STATIC zClass                         AS ASCIIZ * 25
     LOCAL  zPath1                         AS ASCIIZ * %MAX_PATH
     LOCAL  zPath2                         AS ASCIIZ * %MAX_PATH
    
     SELECT CASE AS LONG CBMSG
    
       CASE %WM_INITDIALOG
         CONTROL SET FOCUS hDlg, %Textbox
         CONTROL SEND hDlg, %Textbox, %WM_GETTEXTLENGTH, 0, 0 TO SelEnd
         CONTROL SEND hDlg, %Textbox, %EM_SETSEL, SelEnd, -1
    
       CASE %WM_DEVICECHANGE
    
         SELECT CASE CBWPARAM 'Event type
    
           CASE %DBT_DEVNODES_CHANGED
             sMessage = "DBT_DEVNODES_CHANGED"
    
           CASE %DBT_QUERYCHANGECONFIG
             sMessage = "DBT_QUERYCHANGECONFIG"
    
           CASE %DBT_CONFIGCHANGED
             sMessage = "DBT_CONFIGCHANGED"
    
           CASE %DBT_CONFIGCHANGECANCELED
             sMessage = "DBT_CONFIGCHANGECANCELED"
    
           CASE %DBT_DEVICEARRIVAL
             sMessage = "DBT_DEVICEARRIVAL - " & DeviceEventGet(CBWPARAM, CBLPARAM)
    
           CASE %DBT_CUSTOMEVENT
             sMessage = "DBT_CUSTOMEVENT - " & DeviceEventGet(CBWPARAM, CBLPARAM)
    
           CASE %DBT_DEVICEQUERYREMOVE
             sMessage = "DBT_DEVICEQUERYREMOVE - " & DeviceEventGet(CBWPARAM, CBLPARAM)
    
           CASE %DBT_DEVICEREMOVEPENDING
             sMessage = "DBT_DEVICEREMOVEPENDING" & DeviceEventGet(CBWPARAM, CBLPARAM)
    
           CASE %DBT_DEVICEREMOVECOMPLETE
             sMessage = "DBT_DEVICEREMOVECOMPLETE - " & DeviceEventGet(CBWPARAM, CBLPARAM)
    
           CASE %DBT_DEVICEQUERYREMOVEFAILED
             sMessage = "DBT_DEVICEQUERYREMOVEFAILED - " &  DeviceEventGet(CBWPARAM, CBLPARAM)
    
           CASE %DBT_DEVICETYPESPECIFIC
             sMessage = "DBT_DEVICETYPESPECIFIC - " & DeviceEventGet(CBWPARAM, CBLPARAM)
    
           CASE %DBT_USERDEFINED
             sMessage = "DBT_USERDEFINED - " & DeviceEventGet(CBWPARAM, CBLPARAM)
    
         END SELECT
    
         TextAdd(sMessage)
    
       CASE %WM_APP + 1 'SHChangeNotifyRegister SHCNE_DISKEVENTS notification
         'Drive and media insertion or removal
         'For media like memory card in a card reader and also for drive like a USB stick
         'wParam is a pointer to two PIDLIST_ABSOLUTE pointers that can be NULL, depending on the event
         'lParam is the event
         ppIdList = CBWPARAM
         pIdList1 = @ppIdList
         ppIdList = ppIdList + 4
         pIdList2 = @ppIdList
    
         IF pIdList1 THEN SHGetPathFromIDList(@pIdList1, zPath1) ELSE zPath1 = "Nil"
         IF pIdList2 THEN SHGetPathFromIDList(@pIdList2, zPath2) ELSE zPath2 = "Nil"
    
         SELECT CASE CBLPARAM
           CASE %SHCNE_MEDIAINSERTED : sMessage = "SHCNE_MEDIAINSERTED - Media inserted: Drive letter is " & zPath1 '& " - " & zPath2
           CASE %SHCNE_MEDIAREMOVED  : sMessage = "SHCNE_MEDIAREMOVED - Media removed: Drive letter is "   & zPath1 '& " - " & zPath2
           CASE %SHCNE_DRIVEREMOVED  : sMessage = "SHCNE_DRIVEREMOVED - Drive removed: Drive letter is  "  & zPath1 '& " - " & zPath2
           CASE %SHCNE_DRIVEADD      : sMessage = "SHCNE_DRIVEADD - Drive added: Drive letter is  "        & zPath1 '& " - " & zPath2
         END SELECT
         TextAdd(sMessage)
    
       CASE %WM_SIZE 'wParam = flag, LOWORD(lParam) = Width, HIWORD(lParam) = height
         IF CBWPARAM <> %SIZE_MINIMIZED THEN
           SetWindowPos(GetDlgItem(hDlg, %Textbox), 0, 5, 5, _
                        LO(WORD, CBLPARAM) - 10, HI(WORD, CBLPARAM) - 10, %SWP_NOZORDER)
         END IF
    
       CASE %WM_NCACTIVATE
         IF CBWPARAM = 0 THEN 'Application loose focus
           hFocusBak = GetFocus()
           GetClassName(hFocusBak, BYVAL VARPTR(zClass), SIZEOF(zClass))
           IF zClass = "Edit" OR zClass = "RICHEDIT" THEN
             SendMessage(hFocusBak, %EM_GETSEL, VARPTR(SelStart), VARPTR(SelEnd))
           END IF
         ELSEIF hFocusBak THEN
           SendMessage(hDlg, %WM_NEXTDLGCTL, hFocusBak, 1)
           IF zClass = "Edit" OR zClass = "RICHEDIT" THEN
             SendMessage(hFocusBak, %EM_SETSEL, SelStart, SelEnd)
           END IF
           hFocusBak = 0
         END IF
    
      CASE %WM_COMMAND
        SELECT CASE AS LONG CBCTL
          CASE %Textbox
    
             CASE %EN_KILLFOCUS
               SendMessage(CBLPARAM, %EM_GETSEL, SelStart, SelEnd) 'To keep textbox highlight
    
             CASE %EN_SETFOCUS
               SendMessage(CBLPARAM, %EM_SETSEL, SelStart, SelEnd) 'To keep textbox highlight
    
        END SELECT
    
     END SELECT
    
    END FUNCTION
    '______________________________________________________________________________
    
    FUNCTION PBMAIN()
     LOCAL NotificationFilter AS DEV_BROADCAST_DEVICEINTERFACE
     LOCAL hDevNotify         AS DWORD
     LOCAL wMsg               AS DWORD
     LOCAL ulID               AS DWORD
     LOCAL ppidl              AS DWORD
     LOCAL cEntries           AS LONG
    
     DIALOG NEW %HWND_DESKTOP, "WM_DEVICECHANGE & SHCNE_DISKEVENTS - Insert or remove USB device or media", , , 500, 150, %WS_POPUP OR %WS_BORDER OR _
       %WS_DLGFRAME OR %WS_THICKFRAME OR %WS_CAPTION OR %WS_SYSMENU OR %WS_MINIMIZEBOX OR %WS_MAXIMIZEBOX OR %WS_CLIPSIBLINGS OR _
       %WS_VISIBLE OR %DS_MODALFRAME OR %DS_3DLOOK OR %DS_NOFAILCREATE OR %DS_SETFONT, %WS_EX_CONTROLPARENT OR %WS_EX_LEFT OR _
       %WS_EX_LTRREADING OR %WS_EX_RIGHTSCROLLBAR, TO hDlg
    
     SetClassLong(hDlg, %GCL_HICON, ExtractIcon(GetModuleHandle(""), "Shell32.dll", 243)) 'Set an icon
    
     CONTROL ADD TEXTBOX, hDlg, %Textbox, "Insert or remove USB device...", 5, 5, 940, 225, %WS_CHILD OR %WS_VISIBLE OR _
       %WS_TABSTOP OR %WS_HSCROLL OR %WS_VSCROLL OR %ES_LEFT OR %ES_MULTILINE OR %ES_AUTOHSCROLL OR %ES_AUTOVSCROLL OR _
       %ES_WANTRETURN OR %ES_NOHIDESEL, %WS_EX_CLIENTEDGE OR %WS_EX_LEFT OR %WS_EX_RIGHTSCROLLBAR OR %WS_EX_LTRREADING
    
     NotificationFilter.DbDiSize = SIZEOF(NotificationFilter)
     NotificationFilter.DbDiDevicetype = %DBT_DEVTYP_DEVICEINTERFACE
     hDevNotify = RegisterDeviceNotification(hDlg, VARPTR(NotificationFilter), _
                  %DEVICE_NOTIFY_WINDOW_HANDLE OR %DEVICE_NOTIFY_ALL_INTERFACE_CLASSES)
    
     cEntries = 1 'Must be only one element when calling SHChangeNotifyRegister
     DIM pshcne(0 TO cEntries - 1) AS SHChangeNotifyEntry
    
     SHGetSpecialFolderLocation(hDlg, %CSIDL_DESKTOP, ppidl)
     pshcne(0).pidl = ppidl
     pshcne(0).fRecursive = %FALSE
    
     ulID = SHChangeNotifyRegister(BYVAL hDlg, %SHCNRF_SHELLLEVEL, %SHCNE_DRIVEADD OR %SHCNE_DRIVEREMOVED OR %SHCNE_MEDIAINSERTED OR %SHCNE_MEDIAREMOVED, _
                                   BYVAL %WM_APP + 1, BYVAL cEntries, BYVAL VARPTR(pshcne(0)))
    
     DIALOG SHOW MODAL hDlg, CALL ShowDIALOG1Proc
    
     IF ulID THEN SHChangeNotifyDeregister(ulID)
     IF hDevNotify THEN UnregisterDeviceNotification(hDevNotify)
    
    END FUNCTION

  • #2
    You should get a pointer to why it won't compile, in this case "Mismatch with prior definition", pointing at the declare for SHChangeNotifyRegister. Fixed by commenting out the declare for DECLARE FUNCTION SHChangeNotifyRegister, because it is already declared slightly different in later include files (ShlObj.inc - where last parameter, BYREF ChangeNotifyEntry AS SHChangeNotifyEntry has been changed to BYREF ChangeNotifyEntry AS ANY).

    PS, Pierre - nice code, can become useful. I like it - thanks!

    Comment


    • #3
      Thanks Borje! The error I was getting was pointing to a missing variable or something... I will try out your suggestions!

      Comment


      • #4
        Also, if you use JR includes change "VARPTR(NotificationFilter)" to "BYVAL VARPTR(NotificationFilter)"
        and of course, if you use PB includes follow Börje suggestion.

        P.S.: I'm glad that you like it Börje. :-)

        Comment


        • #5
          David,
          Likely it was extracted from Pierre's wonderful example. Thank you Pierre.

          If you just want Arrival and Removal notifications then this is what I use for detecting the K8055 USB device:

          Code:
          GLOBAL glngPrevDeviceNotifyProc AS LONG  'Original Proc to be notified
          GLOBAL hDevNotify               AS LONG  'Handle to RegisterDeviceNotification function
          
             CALL DoRegisterDeviceInterface(hWndMain, hDevNotify)             '<--- DBT_DEVICEARRIVAL and DBT_DEVICEREMOVECOMPLETE are automatically broadcast for port devices.
                                                                               '<--- so not necessary to RegisterDeviceNotification for DBT_DEVTYP_PORT OR DBT_DEVTYP_VOLUME OR DBT_DEVTYP_OEM
          
              glngPrevDeviceNotifyProc = GetWindowLongA(hWndMain, %GWL_WNDPROC)
              SetWindowLongPtrA hWndMain, %GWL_WNDPROC, CODEPTR(DeviceNotifyProc)
          Code:
          FUNCTION DoRegisterDeviceInterface(hWnd AS LONG, BYREF hDevNotify AS LONG) AS LONG
               LOCAL Message AS STRING
               LOCAL NotificationFilter AS DEV_BROADCAST_DEVICEINTERFACE
               NotificationFilter.DbDiSize = SIZEOF(NotificationFilter)
               NotificationFilter.DbDiDevicetype = %DBT_DEVTYP_DEVICEINTERFACE
               hDevNotify = RegisterDeviceNotificationA(hWnd, NotificationFilter, %DEVICE_NOTIFY_WINDOW_HANDLE OR %DEVICE_NOTIFY_ALL_INTERFACE_CLASSES)
               IF hDevNotify = 0 THEN
                    Message = Message + SPACE$(5) + "RegisterDeviceNotification failed: "
                    FUNCTION = %False
                    EXIT FUNCTION
               END IF
              FUNCTION = %True
          END FUNCTION
          
          
          FUNCTION DeviceNotifyProc(BYVAL hWnd AS LONG, BYVAL Msg AS LONG, BYVAL wParam AS LONG, BYVAL lParam AS LONG) AS LONG
               STATIC Message AS STRING
               LOCAL DeviceBroadCastHeader AS DEV_BROADCAST_HDR
               LOCAL DeviceBroadCastOem AS DEV_BROADCAST_OEM
               LOCAL DeviceBroadCasteDevNode AS DEV_BROADCAST_DEVNODE
               LOCAL DeviceBroadCastVolume AS DEV_BROADCAST_VOLUME
               LOCAL DeviceBroadCastPort AS DEV_BROADCAST_PORT
               LOCAL DeviceBroadCastNet AS DEV_BROADCAST_NET
               LOCAL DeviceBroadCastDeviceInterface AS DEV_BROADCAST_DEVICEINTERFACE
               LOCAL DeviceBroadCastHandle AS DEV_BROADCAST_HANDLE
          
               LOCAL TempBin AS STRING
               LOCAL i AS LONG
               LOCAL DriveName AS STRING
               LOCAL DriveFlags AS STRING
               STATIC DevNodesChanged AS LONG
               SELECT CASE Msg
                    CASE %WM_DEVICECHANGE
                         SELECT CASE wParam                                                         'Determine Event Type
          
                              CASE %DBT_DEVICEARRIVAL                                               'System uses WM_DEVICECHANGE, wParam = DBT_DEVICEARRIVAL, lParam = TBD
                                   LOCAL AZ AS STRING
                                   SELECT CASE DevNodesChanged
                                        CASE %FALSE         'Flag not set so set it
                                             DevNodesChanged = %TRUE
                                        CASE %TRUE          'Flag set
                                   END SELECT
                                   AZ = GetUdtDeviceEvent(DeviceBroadCastHeader, DeviceBroadCastOem, DeviceBroadCasteDevNode, DeviceBroadCastVolume, DeviceBroadCastPort, DeviceBroadCastNet, DeviceBroadCastDeviceInterface, DeviceBroadCastHandle, lParam)
                                   IF INSTR(AZ, "HID#VID_10CF&PID_5500") > 0 THEN Message = "Device was inserted."
          
                              CASE %DBT_DEVICEREMOVECOMPLETE                                        'System uses WM_DEVICECHANGE, wParam = DBT_DEVICEREMOVECOMPLETE, lParam = TBD
                                   LOCAL EZ AS STRING
                                   EZ = GetUdtDeviceEvent(DeviceBroadCastHeader, DeviceBroadCastOem, DeviceBroadCasteDevNode, DeviceBroadCastVolume, DeviceBroadCastPort, DeviceBroadCastNet, DeviceBroadCastDeviceInterface, DeviceBroadCastHandle, lParam)
                                   IF INSTR(EZ, "HID#VID_10CF&PID_5500") > 0 THEN Message = "Device was removed."
                                   SELECT CASE DevNodesChanged
                                        CASE %FALSE                                                 'Flag not set
                                        CASE %TRUE                                                  'Flag set so unset it
                                             DevNodesChanged = %FALSE
                                   END SELECT
          
                         END SELECT
                         SELECT CASE Message
                              CASE ""
                              CASE ELSE
                                   CaptureTheDeviceList Message    'See NOTE below
                         END SELECT
                         Message = ""
               END SELECT
               DeviceNotifyProc = CallWindowProcA(glngPrevDeviceNotifyProc, hWnd, Msg, wParam, lParam)       ' pass the rest messages to original function
          END FUNCTION
          
          
          DECLARE FUNCTION GetUdtDeviceEvent( _
                                        DeviceBroadCastHeader AS DEV_BROADCAST_HDR, _
                                        DeviceBroadCastOem AS DEV_BROADCAST_OEM, _
                                        DeviceBroadCasteDevNode AS DEV_BROADCAST_DEVNODE, _
                                        DeviceBroadCastVolume AS DEV_BROADCAST_VOLUME, _
                                        DeviceBroadCastPort AS DEV_BROADCAST_PORT, _
                                        DeviceBroadCastNet AS DEV_BROADCAST_NET, _
                                        DeviceBroadCastDeviceInterface AS DEV_BROADCAST_DEVICEINTERFACE, _
                                        DeviceBroadCastHandle AS DEV_BROADCAST_HANDLE, _
                                        BYVAL lParam AS LONG _
                                        )AS STRING
          
          FUNCTION GetUdtDeviceEvent( DeviceBroadCastHeader AS DEV_BROADCAST_HDR, _
                                      DeviceBroadCastOem AS DEV_BROADCAST_OEM, _
                                      DeviceBroadCasteDevNode AS DEV_BROADCAST_DEVNODE, _
                                      DeviceBroadCastVolume AS DEV_BROADCAST_VOLUME, _
                                      DeviceBroadCastPort AS DEV_BROADCAST_PORT, _
                                      DeviceBroadCastNet AS DEV_BROADCAST_NET, _
                                      DeviceBroadCastDeviceInterface AS DEV_BROADCAST_DEVICEINTERFACE, _
                                      DeviceBroadCastHandle AS DEV_BROADCAST_HANDLE, _
                                      BYVAL lParam AS LONG _
                                      )AS STRING
               LOCAL Message AS STRING
               LOCAL TempBin AS STRING
               LOCAL i AS LONG
               LOCAL DriveName AS STRING
               LOCAL DriveFlags AS STRING
               STATIC DevNodesChanged AS LONG
                                   CopyMemory VARPTR(DeviceBroadCastHeader), BYVAL (lParam), SIZEOF(DeviceBroadCastHeader)
                                   SELECT CASE DeviceBroadCastHeader.DbhDevicetype                  'Determine Device Type
                                        CASE %DBT_DEVTYP_DEVICEINTERFACE                            'Class of devices. This structure is a DEV_BROADCAST_DEVICEINTERFACE structure.
                                             Message = Message + SPACE$(5) + "Device Type: DBT_DEVTYP_DEVICEINTERFACE"
                                             CopyMemory VARPTR(DeviceBroadCastDeviceInterface), BYVAL (lParam), BYVAL (DeviceBroadCastHeader.DbhSize)
                                             Message = Message + SPACE$(5) + "Device Name: " & DeviceBroadCastDeviceInterface.DbDiName & $TAB & "GUID: " & GUIDTXT$(DeviceBroadCastDeviceInterface.DbDiClassguid)
                                   END SELECT
               FUNCTION = Message
          END FUNCTION

          Code:
          IF hDevNotify <> 0 THEN                                          '<--- If RegisterDeviceInterface was used, then release it (or the next compile will not find the device)
             call UnregisterDeviceNotification(hDevNotify)
          END IF

          NOTE:
          CaptureTheDeviceList is where you determine what should be done about the device change message.

          Comment


          • #6
            Thanks Jim!

            Comment


            • #7
              David,
              Glad I could help.

              NOTE:
              The code originated from Cliff Nichols work. Thank you Cliff!

              Comment

              Working...
              X