找回密码
 加入
搜索
查看: 3260|回复: 24

[AU3基础] [已解决]使用AdlibRegister来检测U盘插入、窗口出现等出现闪动

[复制链接]
发表于 2022-1-25 21:14:03 | 显示全部楼层 |阅读模式
本帖最后由 smooth 于 2022-2-4 22:59 编辑

使用AdlibRegister来检测U盘插入、做倒计时、检测窗口的出现等,然后将结果写入LABEL控件。但是很明显的看出来,界面的LABEL控件出现闪动。
最简单的就是做倒计时,函数里面只有时间宏,没有其他的代码,也会出现闪动。调用 Adlib 函数的间隔时间为默认值,没有动,AU3版本:3.3.15.3

Func _Time()
 Local $Hour, $Min, $Sec
 $nowTicks = _TimeToTicks(@HOUR, @MIN, @SEC)
 $iTicks = $nowTicks - $StartTicks
 _TicksToTime($iTicks, $Hour, $Min, $Sec)
 GUICtrlSetData($djsLabel, StringFormat("%02d:%02d:%02d\n", $Hour, $Min, $Sec))
EndFunc   ;==>_Time

发表于 2022-1-26 08:55:03 | 显示全部楼层
默认每250ms调用这个函数都更新label数据,闪烁是肯定的。正确的方法是设置一个静态变量。只有数据变化时才更新

#include <GUIConstantsEx.au3>
#include <StaticConstants.au3>
#include <WindowsConstants.au3>
#Region ### START Koda GUI section ### Form=
$Form1 = GUICreate("Form1", 615, 267, 192, 294)
$djsLabel = GUICtrlCreateLabel("Label1", 96, 80, 200, 20)
GUISetState(@SW_SHOW)
#EndRegion ### END Koda GUI section ###
$StartTicks = _TimeToTicks(@HOUR, @MIN, @SEC) - 10
AdlibRegister('_Time')

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

        EndSwitch
WEnd





Func _Time()
        Local Static $g_sTime
        Local $sTime = $g_sTime
        $g_sTime = _Now()
        If $sTime <> $g_sTime Then GUICtrlSetData($djsLabel, $g_sTime)
EndFunc   ;==>_System_Timer
 楼主| 发表于 2022-1-26 13:34:49 | 显示全部楼层
说明:_DetectHardID()用来检测U盘的插拔,如果插入,则_DetectHardID() <> "",如果拔出,_DetectHardID() = ""
请教怎么写,才能让界面不闪动,研究了一下写不出来。

Func _U_KEY_state()
 Local Static $g_sTime;定一个静态变量,防止AdlibRegister函数不断的检测导致界面闪动。
 Local $sTime = $g_sTime
 $g_sTime = _DetectHardID()
 If $sTime <> $g_sTime Then
  GUICtrlSetData($uLabel, "未插入")
 Else
  GUICtrlSetData($uLabel, "已插入")
 EndIf
EndFunc   ;==>_U_KEY_state


发表于 2022-1-26 13:57:28 | 显示全部楼层
插入、移除都是有系统消息的,不用循环检测,注册 WM_DEVICECHANGE 消息处理即可
 楼主| 发表于 2022-1-26 16:44:41 | 显示全部楼层
afan 发表于 2022-1-26 13:57
插入、移除都是有系统消息的,不用循环检测,注册 WM_DEVICECHANGE 消息处理即可

WM_DEVICECHANGE 消息只能检测某一类设备插入和移除,不是监控指定设备。
 楼主| 发表于 2022-1-26 16:57:51 | 显示全部楼层
afan 发表于 2022-1-26 13:57
插入、移除都是有系统消息的,不用循环检测,注册 WM_DEVICECHANGE 消息处理即可

$U_KEY_state = DllCallbackRegister("Timer", "int", "hwnd;uint;uint;dword")
$U_KEY_stateDLL = DllCall("user32.dll", "uint", "SetTimer", "hwnd", 0, "uint", 0, "int", 1000, "ptr", DllCallbackGetPtr($U_KEY_state))

Func Timer($hWnd, $uiMsg, $idEvent, $dwTime)
    If $idEvent = $U_KEY_stateDLL[0] Then
   ,,,,,,,,,,,,,
    endif
endfunc
请教A大,这样注册函数来做监控,有什么弊端吗?因为我发现这样注册,反应有点慢。如果用来计算器,有时候会发现卡顿。
发表于 2022-1-26 18:26:02 | 显示全部楼层
smooth 发表于 2022-1-26 16:57
$U_KEY_state = DllCallbackRegister("Timer", "int", "hwnd;uint;uint;dword")
$U_KEY_stateDLL = DllC ...

1秒1次循环检测,相对来说会显得慢,而如果函数内有较耗时的操作则会导致卡顿
发表于 2022-1-26 18:36:28 | 显示全部楼层
本帖最后由 chzj589 于 2022-1-26 20:21 编辑
smooth 发表于 2022-1-26 16:57
$U_KEY_state = DllCallbackRegister("Timer", "int", "hwnd;uint;uint;dword")
$U_KEY_stateDLL = DllC ...

这样你试试

#include <GUIConstantsEx.au3>
#include <StaticConstants.au3>
#include <WindowsConstants.au3>
#Region ### START Koda GUI section ### Form=
$Form1 = GUICreate("Form1", 615, 267, 192, 294)
$uLabel = GUICtrlCreateLabel("Label1", 96, 80, 200, 20)
GUISetState(@SW_SHOW)
GUIRegisterMsg(0x0219, '_USB_Message')
#EndRegion ### END Koda GUI section ###
While 1
        $nMsg = GUIGetMsg()
        Switch $nMsg
                Case $GUI_EVENT_CLOSE
                        Exit
        EndSwitch
WEnd
Func _USB_Message($hWnd, $Msg, $wParam, $lParam)
        Switch $wParam
                Case 0x8000;设备插入
                        Local $_DEV_BROADCAST_HDR = DllStructCreate("int dbch_size; int dbch_devicetype; int dbch_reserved;", $lParam)
                        If DllStructGetData($_DEV_BROADCAST_HDR, "dbch_devicetype") = 2 Then
                                GUICtrlSetData($uLabel, "U盘已插入")
                                GUICtrlSetColor($uLabel, 0x990000)
                                GUICtrlSetFont(-1, 12, 600, 0, 'Arial') 
                      EndIf
                Case 0x8004;设备移除
                        GUICtrlSetData($uLabel, "U盘已拔出")
                        GUICtrlSetColor($uLabel, 0x0000FF)
                GUICtrlSetFont(-1, 12, 400, 0, 'Arial')
        EndSwitch
EndFunc   ;==>_USB_Message





 楼主| 发表于 2022-1-26 20:47:07 | 显示全部楼层

谢谢大佬。

你的代码,只能检测插入和拔出,而且只能针对移动设备。我是要检测某个确定的设备是否已经插入,或者是否已经拔出。我已经用函数(假设这个函数为A)来检测出是否已经插入或者已经拔出,现在是要把“插入”或者“拔出”写到界面的LABEL上,我用AdlibRegister这个函数来检测函数A的返回值,为空就写上“已拔出”,不为空就写上“已插入”。但是发现控件上的字在闪。
 楼主| 发表于 2022-1-26 20:48:56 | 显示全部楼层
afan 发表于 2022-1-26 18:26
1秒1次循环检测,相对来说会显得慢,而如果函数内有较耗时的操作则会导致卡顿

可是我把AdlibRegister函数的参数改为5秒,控件也一样在闪,我就搞不懂了。
发表于 2022-1-26 20:54:33 | 显示全部楼层
smooth 发表于 2022-1-26 20:48
可是我把AdlibRegister函数的参数改为5秒,控件也一样在闪,我就搞不懂了。

要想尽快解决问题,要有精简、可运行、可重现问题的代码
 楼主| 发表于 2022-1-26 21:03:05 | 显示全部楼层

我现在是这样实现的,界面不闪了,但是我嫌它反应有点慢。

$U_KEY_state = DllCallbackRegister("Timer", "int", "hwnd;uint;uint;dword")
$U_KEY_stateDLL = DllCall("user32.dll", "uint", "SetTimer", "hwnd", 0, "uint", 0, "int", 1000, "ptr", DllCallbackGetPtr($U_KEY_state))

$WY_state = DllCallbackRegister("Timer", "int", "hwnd;uint;uint;dword")
$WY_stateDLL = DllCall("user32.dll", "uint", "SetTimer", "hwnd", 0, "uint", 0, "int", 1000, "ptr", DllCallbackGetPtr($WY_state))

Func Timer($hWnd, $uiMsg, $idEvent, $dwTime)
        If $idEvent = $U_KEY_stateDLL[0] Then
                If _DetectHardID() <> '' Then
                        GUICtrlSetData($uLabel, "已插入")
                Else
                        GUICtrlSetData($uLabel, "未插入")
                EndIf
        ElseIf $idEvent = $WY_stateDLL[0] Then
                If WinExists("浦发银行网银客户端") Then
                        GUICtrlSetData($vLabel, "客户端版")
                ElseIf WinExists("上海浦东发展银行公司网上银行 - Internet Explorer") Then
                        GUICtrlSetData($vLabel, "网页版(IE)")
                ElseIf WinExists("上海浦东发展银行公司网上银行 - 用户配置 1 - Microsoft​ Edge") Then
                        GUICtrlSetData($vLabel, "网页版(Edge)")
                Else
                        GUICtrlSetData($vLabel, "未登录")
                EndIf
        EndIf
EndFunc   ;==>Timer
发表于 2022-1-26 21:13:11 | 显示全部楼层
你的问题不是U盘插入后, 界面的LABEL控件出现闪动吗?
像A版说的,把要解决的问题说清楚。
要有精简、可运行、可重现问题的代码
 楼主| 发表于 2022-1-26 21:22:08 | 显示全部楼层
afan 发表于 2022-1-26 20:54
要想尽快解决问题,要有精简、可运行、可重现问题的代码

界面控件会闪动

#NoTrayIcon
#RequireAdmin
#PRE_UseX64=n
#include <SetupApi.au3>
Opt("GUIOnEventMode", 1);开启事件模式
Opt("GUICloseOnESC", 0);关闭“按ESC”退出脚本的功能
If WinExists("浦发网银付款回单自动截图") Then
        Exit
Else
        Global $hGui = GUICreate("浦发网银付款回单自动截图", 400, 370)
EndIf
GUICtrlCreateLabel("U-KEY状态:", 52, 290, 72, 12)
Global $uLabel = GUICtrlCreateLabel("", 124, 290, 72, 12)
GUICtrlCreateLabel("网银状态:", 20, 340, 60, 12)
Global $vLabel = GUICtrlCreateLabel("", 80, 340, 72, 12)
GUISetState()
GUISetOnEvent(-3, "_Exit")
AdlibRegister("Timer")
AdlibRegister('_DetectHardID', 50)

While 1
        Sleep(10)
WEnd

Func _DetectHardID();检测U-KEY设备实例ID
        Local $hDevs, $tDevInfo, $aMouse[1][2] = [[0]]
        $hDevs = _SetupDiGetClassDevs($DIGCF_PRESENT, "CDROM");DiskDrive
        While _SetupDiEnumDeviceInfo($hDevs, $aMouse[0][0], $tDevInfo)
                $aMouse[0][0] += 1
                $sDescr = _SetupDiGetDeviceRegistryProperty($hDevs, $tDevInfo, $SPDRP_DEVICEDESC)
                $sName = _SetupDiGetDeviceRegistryProperty($hDevs, $tDevInfo, $SPDRP_FRIENDLYNAME)
                If $sName <> "" Then $sDescr = $sName
                ReDim $aMouse[$aMouse[0][0] + 1][2]
                $aMouse[$aMouse[0][0]][0] = $sDescr ; 磁盘描述信息
                $aMouse[$aMouse[0][0]][1] = _SetupDiGetDeviceInstanceId($hDevs, $tDevInfo) ; 设备范例ID
        WEnd
        ; 枚举网卡只需把"DiskDrive"改为"Net",鼠标则对应Mouse,光驱则为CDROM,显卡对应Display。
        _SetupDiDestroyDeviceInfoList($hDevs)
        Local $dFindDevs = ""
        For $i = 1 To $aMouse[0][0]
                If StringInStr($aMouse[$i][1], "USBSTOR\CDROM&VEN_TENDYRON&PROD_U-DISK&REV_1.10\") Then;
                        $dFindDevs = $aMouse[$i][1]
                        ExitLoop
                EndIf
        Next
        Return $dFindDevs;把变量值返回给函数_DetectHardID()
EndFunc   ;==>_DetectHardID

Func Timer()
        If _DetectHardID() <> '' Then
                GUICtrlSetData($uLabel, "已插入")
        Else
                GUICtrlSetData($uLabel, "未插入")
        EndIf
        If WinExists("浦发银行网银客户端") Then
                GUICtrlSetData($vLabel, "客户端版")
        ElseIf WinExists("上海浦东发展银行公司网上银行 - Internet Explorer") Then
                GUICtrlSetData($vLabel, "网页版(IE)")
        ElseIf WinExists("上海浦东发展银行公司网上银行 - 用户配置 1 - Microsoft​ Edge") Then
                GUICtrlSetData($vLabel, "网页版(Edge)")
        Else
                GUICtrlSetData($vLabel, "未登录")
        EndIf
EndFunc   ;==>Timer

Func _Exit()
        Exit
EndFunc   ;==>_Exit
发表于 2022-1-26 21:26:49 | 显示全部楼层
smooth 发表于 2022-1-26 21:03
我现在是这样实现的,界面不闪了,但是我嫌它反应有点慢。

哦,明白了,你要检测的是U-KEY。
那是专用U盘。这样检测可能没辙。
您需要登录后才可以回帖 登录 | 加入

本版积分规则

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

GMT+8, 2024-12-22 21:36 , Processed in 0.080319 second(s), 20 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

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