smooth 发表于 2024-2-2 14:34:33

注册消息函数0x0219,怎么样能同时检测到所有变动的分区?

注册消息函数0x0219,比如插入的移动硬盘有两个分区,它只能检测到其中一个分区,拔除的时候也是一样的。怎么样能同时检测到所有变动的分区?谢谢!



#NoTrayIcon
#RequireAdmin
#PRE_UseX64 = n

$Form = GUICreate("", 800, 240)
GUIRegisterMsg(0x0219, "_WM_DEVICECHANGE");0x0219/*_WM_DEVICECHANGE*/,"当设备的硬件配置改变时,发送本消息给应用程序或设备驱动程序"

While 1
    Sleep(10)
WEnd

Func _WM_DEVICECHANGE($hWnd, $Msg, $wParam, $lParam);$hWnd:窗口句柄, $Msg:发送的消息类型, $wParam:32位消息的特定附加信息,确切含义依赖于消息值, $lParam:指向内存中数据的指针,通常用于存储消息所需要的对象。
      Switch $wParam
                Case 0x8000;设备插入
                        Local $_DEV_BROADCAST_HDR = DllStructCreate("int dbch_size; int dbch_devicetype; int dbch_reserved;", $lParam);创建一个 C/C++ 样式的数据结构,$lParam:指针,[可选参数] 如果指定的数据结构不能分配内存,则使用此指针参数。
                        If DllStructGetData($_DEV_BROADCAST_HDR, "dbch_devicetype") = 2 Then;dbch_devicetype:表示设备的类型
                              Local Const $DEV_BROADCAST_VOLUME = DllStructCreate("int dbcv_size; int dbcv_devicetype; int dbcv_reserved; int dbcv_unitmask; word dbcv_flags", $lParam)
                              Local Const $unitMask = DllStructGetData($DEV_BROADCAST_VOLUME, "dbcv_unitmask")
                              $drivers = _Get_DriverFlag($unitMask);获取插入设备的盘符
                              MsgBox(0, "", "分区 " & $drivers & " 被插入", 2)
                        EndIf
                        
                Case 0x8004;设备移除
                        Local $_DEV_BROADCAST_HDR = DllStructCreate("int dbch_size; int dbch_devicetype; int dbch_reserved;", $lParam)
                        If DllStructGetData($_DEV_BROADCAST_HDR, "dbch_devicetype") = 2 Then
                              Local Const $DEV_BROADCAST_VOLUME_yc = DllStructCreate("int dbcv_size; int dbcv_devicetype; int dbcv_reserved; int dbcv_unitmask; word dbcv_flags", $lParam)
                              Local Const $unitMask_yc = DllStructGetData($DEV_BROADCAST_VOLUME_yc, "dbcv_unitmask")
                              $drivers = _Get_Driverflag($unitMask_yc);获取拔出设备的盘符
                              MsgBox(0, "", "分区 " & $drivers & " 被移除", 2)
                        EndIf
                        
                        ;文档官网:https://learn.microsoft.com/zh-c ... vio/wm-devicechange
                        ;windows数据类型:https://learn.microsoft.com/zh-c ... /windows-data-types
                        ;$wParam的值:
            ;0x0007:设备已添加到系统或从系统中删除
            ;0x0017:请求权限以更改当前配置(停靠或取消停靠)
            ;0x0018:由于停靠或取消停靠,当前配置已更改
            ;0x0019:已取消更改当前配置(停靠或取消停靠)的请求
            ;0x8000:已插入设备或介质片段,现已可用
                        ;0x8001:请求权限以删除设备或介质。任何应用程序都可以拒绝此请求并取消删除
            ;0x8002:删除设备或介质的请求已取消
            ;0x8003:即将删除设备或介质片段。不可拒绝
            ;0x8004:已删除设备或介质片段
            ;0x8005:发生了特定于设备的事件
            ;0x8006:发生了自定义事件
            ;0xFFFF:此消息的含义是用户定义的                        
      EndSwitch
EndFunc   ;==>_WM_DEVICECHANGE

Func _Get_DriverFlag($unitMask);搭配_WM_DEVICECHANGE()使用
      Local $Count = 0
      Local $Pom = Round($unitMask / 2)

      While $Pom > 0
                $Pom = BitShift($Pom, 1)
                $Count += 1
      WEnd

      If $Count >= 1 And $Count <= 26 Then
                Return Chr(65 + $Count) & ":"
      Else
                Return '?'
      EndIf
EndFunc   ;==>_Get_DriverFlag

smooth 发表于 2024-3-2 22:58:49

本帖最后由 smooth 于 2024-3-3 07:15 编辑

没搞明白,为什么没有意义?以下代码来源于论坛,其中一个函数的写法看不懂,运行报错,所以修改了。


$DBT_DEVICEARRIVAL = 0x8000
$DBT_DEVICEQUERYREMOVE = 0x8001
$DBT_DEVICEQUERYREMOVEFAILED = 0x8002
$DBT_DEVICEREMOVEPENDING = 0x8003
$DBT_DEVICEREMOVECOMPLETE = 0x8004
$DBT_DEVICETYPESPECIFIC = 0x8005
$DBT_CUSTOMEVENT = 0x8006

$DBT_DEVTYP_OEM = 0x00000000
$DBT_DEVTYP_DEVNODE = 0x00000001
$DBT_DEVTYP_VOLUME = 0x00000002
$DBT_DEVTYP_PORT = 0x00000003
$DBT_DEVTYP_NET = 0x00000004

$DEV_BROADCAST_HDR = "DWORD size;DWORD devicetype;DWORD reserved"
$DEV_BROADCAST_VOLUME = "DWORD size;DWORD devicetype;DWORD reserved;DWORD unitmask;WORD flags"

#include <GUIConstantsEx.au3>
#include <GUIListBox.au3>
#include <WindowsConstants.au3>
#include <Misc.au3>
#Region ### START Koda GUI section ### Form=
$Form1 = GUICreate("Form1", 416, 428, 192, 132)
$List1 = GUICtrlCreateList("", 72, 40, 289, 310, BitOR($LBS_NOTIFY, $LBS_MULTIPLESEL, $LBS_DISABLENOSCROLL, $WS_VSCROLL, $WS_BORDER))
GUISetState(@SW_SHOW)
#EndRegion ### END Koda GUI section ###
GUIRegisterMsg($WM_DEVICECHANGE, "WM_DEVICECHANGE")

While 1
      $nMsg = GUIGetMsg()
      Switch $nMsg
                Case $GUI_EVENT_CLOSE
                        Exit

      EndSwitch
WEnd

Func WM_DEVICECHANGE($hWnd, $MsgID, $WParam, $LParam)
      Switch $WParam
                Case $DBT_DEVICEARRIVAL, $DBT_DEVICEREMOVECOMPLETE
                        $dbhdr = DllStructCreate($DEV_BROADCAST_HDR, $LParam)
                        $devicetype = DllStructGetData($dbhdr, "devicetype")
                        Switch $devicetype
                              Case $DBT_DEVTYP_VOLUME
                                        $dbv = DllStructCreate($DEV_BROADCAST_VOLUME, $LParam)
                                        $unitmask = DllStructGetData($dbv, "unitmask")
                                        ConsoleWrite($unitmask)
                                        For $i = 0 To 25
                                                If BitAND(BitShift(1, -$i), $unitmask) <> 0 Then print(StringFormat("磁盘已%s,盘符为:%s:", ($WParam = $DBT_DEVICEARRIVAL ? "插入" : "删除"), Chr(Asc("A") + $i)))
                                        Next
                        EndSwitch
      EndSwitch

EndFunc   ;==>WM_DEVICECHANGE

Func print($data)
      _GUICtrlListBox_AddString($List1, $data)
      _GUICtrlListBox_UpdateHScroll($List1)
EndFunc   ;==>print




页: [1]
查看完整版本: 注册消息函数0x0219,怎么样能同时检测到所有变动的分区?