Описание функции


WM_DEVICECHANGE

Сообщение выполняется при подключении или отключении устройств к системе.

Параметры

Указанные параметры передаются системой.
wParam Содержит флаг подключения или отключения устройства
    DBT_DEVICEARRIVAL = $8000 ; Новое устройство подключено и готово к использованию
    DBT_DEVICEQUERYREMOVE = $8001 ; Запрос на удаление устройства. Любое приложение может отменить удаление. Чтобы разрешить удаление, надо вернуть TRUE. Чтобы отменить удаление, надо вернуть BROADCAST_QUERY_DENY
    DBT_DEVICEQUERYREMOVEFAILED = $8002 ; Удаление устройства прервано
    DBT_DEVICEREMOVEPENDING = $8003 ; Устройство сейчас будет удалено. Нельзя отменить удаление. Возвращает TRUE.
    DBT_DEVICEREMOVECOMPLETE = $8004 ; Устройство отключено
    DBT_DEVICETYPESPECIFIC = $8005 ; type specific event
    DBT_DEVNODES_CHANGED = $0007 ; любое изменение в аппаратном профиле
lParam Указатель на структуру
Структура DEV_BROADCAST_HDR задаёт тип устройств для отслеживания
    dbch_size - размер структуры в байтах.
    dbch_devicetype - тип устройства, например DBT_DEVTYP_VOLUME - логический раздел
        DBT_DEVTYP_OEM = $00000000 ; oem-defined device type
        DBT_DEVTYP_DEVNODE = $00000001 ; devnode number
        DBT_DEVTYP_VOLUME = $00000002; логический раздел
        DBT_DEVTYP_PORT = $00000003 ; serial, parallel
        DBT_DEVTYP_NET = $00000004 ; network resource
    dbch_reserved - зарезервировано, не используется
или структура DEV_BROADCAST_VOLUME, если dbch_devicetype возвращает DBT_DEVTYP_VOLUME
    dbch_size - размер структуры в байтах.
    dbch_devicetype - тип устройства (тоже что выше указанные)
    dbch_reserved - зарезервировано, не используется
    dbcv_unitmask - битовая маска, соответствие числа (бита) с буквой диска
        0 = A
        1 = B
        ...
        26 = Z
    dbcv_flags - флаг
Для отслеживания всех устройств поле dbch_devicetype должно быть равен значению DBT_DEVTYP_DEVICEINTERFACE и включать DEVICE_NOTIFY_ALL_INTERFACE_CLASSES для получения сообщений об изменении всех классов устройств.

Примечания

Смотрите функцию SetWindowCallback.

Пример

EnableExplicit

#Windows_0 = 0
#SysTrayIcon_0 = 0
#Menu = 0

Enumeration
    #About
    #Exit
EndEnumeration


Global ExeDir$, hWin_0, drives_avail, Letters$, MarkFileName$
Global StartDisk = 2

; Executable file (disk marker file)
MarkFileName$ = "Start.exe"

ExeDir$ = GetCurrentDirectory()

; here you need a code to prevent the program from restarting
Define *a = CreateSemaphore_(#Null, 0, 1, "USB5671230")
If *a And GetLastError_() = #ERROR_ALREADY_EXISTS
    CloseHandle_(*a)
;     MessageRequester("","The program is already running") ; optional, but you can report that the program is already running
    End
EndIf

Procedure Exit()
    RemoveSysTrayIcon(#SysTrayIcon_0)
    CloseWindow(#Windows_0)
    End
EndProcedure


Procedure Add_drive(Mask.l)
    Protected i, CurLetter$
    For i = StartDisk To 25
        If ((Mask >> i) & 1) ; check each flag
            CurLetter$ = Chr(i + 65)
;             Reaction to marker file
            If FileSize(CurLetter$ + ":\" + MarkFileName$) >= 0
                RunProgram(CurLetter$ + ":\" + MarkFileName$)
            EndIf
            Letters$ + CurLetter$
        EndIf
    Next
    Debug Letters$
EndProcedure

Procedure Del_drive(Mask.l)
    Protected k, Count, CurLetter$, title.s;, z
    Count = Len(Letters$)
    For k = Count To 1 Step -1
        CurLetter$ = Mid(Letters$, k, 1)
        If (Mask >> (Asc(CurLetter$) - 65)) & 1
            Letters$ = ReplaceString(Letters$, CurLetter$, "", #PB_String_NoCase, k, 1)
;             RunProgram("cmd.exe", "/c (taskkill /im " + MarkFileName$ + ")", "")
        EndIf
    Next
    Debug Letters$
EndProcedure

Procedure WinCallback(hWnd, uMsg, wParam, lParam)
    Protected Result = #PB_ProcessPureBasicEvents, Mask, Drive.s, *pDBHDR.DEV_BROADCAST_HDR, *pDBV.DEV_BROADCAST_VOLUME
    Protected tmp
    Select uMsg
;         Case #WM_UNINITMENUPOPUP
;             Debug "PopupMenu был закрыт."
             Case #WM_DEVICECHANGE ; Change when connecting external drives.
            Result = #True
            Select wParam
                Case #DBT_DEVICEARRIVAL, #DBT_DEVICEREMOVECOMPLETE
                    *pDBHDR.DEV_BROADCAST_HDR=lParam
                    If *pDBHDR\dbch_devicetype = #DBT_DEVTYP_VOLUME
                        *pDBV.DEV_BROADCAST_VOLUME=lParam
                        Mask = *pDBV\dbcv_unitmask

                        Select wParam
                            Case #DBT_DEVICEARRIVAL
                                ; Debug Bin(drives_avail)
                                ; Debug Bin(Mask)
                                tmp = drives_avail
                                drives_avail | Mask
                                If tmp <> drives_avail
                                    Add_drive(Mask)
                                EndIf
                            Case #DBT_DEVICEREMOVECOMPLETE
                                drives_avail ! (Mask & drives_avail)
                                Del_drive(Mask)
                        EndSelect
                    EndIf
            EndSelect
    EndSelect
    ProcedureReturn Result
EndProcedure

hWin_0 = OpenWindow(#Windows_0, 0, 0, 200, 20, "", #PB_Window_Invisible)

AddSysTrayIcon(#SysTrayIcon_0, hWin_0, GetClassLongPtr_(hWin_0, #GCL_HICON))
; AddSysTrayIcon(#SysTrayIcon_0, WindowID(0), LoadImage(0, ExeDir$ + "2.ico"))
SysTrayIconToolTip(#SysTrayIcon_0, "Surveillance")

CreatePopupMenu(#Menu)
MenuItem(#Exit, "Exit")

BindMenuEvent(#Menu, #Exit, @Exit())
SetWindowCallback(@WinCallback())


Repeat
    Select WaitWindowEvent()
        Case #PB_Event_SysTray
            Select EventType()
                Case #PB_EventType_RightClick
                    DisplayPopupMenu(#Menu, hWin_0)
            EndSelect
        Case #PB_Event_CloseWindow
            Exit()
    EndSelect
ForEver
Exit()