找回密码
 加入
搜索
查看: 130|回复: 1

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

[复制链接]
发表于 2024-2-2 14:34:33 | 显示全部楼层 |阅读模式
注册消息函数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

 楼主| 发表于 前天 22:58 | 显示全部楼层
本帖最后由 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



您需要登录后才可以回帖 登录 | 加入

本版积分规则

QQ|手机版|小黑屋|AUTOIT CN ( 鲁ICP备19019924号-1 )谷歌 百度

GMT+8, 2024-3-4 23:36 , Processed in 0.073605 second(s), 20 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表