overrainy 发表于 2019-2-26 10:40:23

Settimer中持续按住鼠标按键实现[已解决]

本帖最后由 overrainy 于 2019-3-4 13:22 编辑

一个自动按键的小脚本,使用settimer定时触发器,按键都可以没有什么问题,但是想要实现鼠标左右键持续按住,不管使用mousedown+sleep+mouseup还是使用Opt("MouseClickDownDelay",xx)都不能实现持续按键。请教一下大神。示例代码如下。
#Region ACN预处理程序参数(常用参数)
#PRE_Icon=                                                                                 ;图标,支持EXE,DLL,ICO
#PRE_OutFile=                                                                        ;输出文件名
#PRE_OutFile_Type=exe                                                      ;文件类型
#PRE_Compression=4                                                                ;压缩等级
#PRE_UseUpx=y                                                                         ;使用压缩
#PRE_Res_Comment=                                                               ;程序注释
#PRE_Res_Description=                                                      ;详细信息
#PRE_Res_Fileversion=1.0.0.4
#PRE_Res_FileVersion_AutoIncrement=p                        ;自动更新版本
#PRE_Res_LegalCopyright=                                                 ;版权
#PRE_Change2CUI=N                                           ;修改输出的程序为CUI(控制台程序)
;#PRE_Res_Field=AutoIt Version|%AutoItVer%                ;自定义资源段
;#PRE_Run_Tidy=                                                   ;脚本整理
;#PRE_Run_Obfuscator=                                                      ;代码迷惑
;#PRE_Run_AU3Check=                                                         ;语法检查
;#PRE_Run_Before=                                                               ;运行前
;#PRE_Run_After=                                                                ;运行后
;#PRE_UseX64=n                                                                        ;使用64位解释器
;#PRE_Compile_Both                                                                ;进行双平台编译
#EndRegion ACN预处理程序参数设置完成
#cs ____________________________________

Au3 版本:
脚本作者:
电子邮件:
      QQ/TM:
脚本版本:
脚本功能:

#ce _______________脚本开始_________________

#include <GUIConstantsEx.au3>
#include <MsgBoxConstants.au3>
#include <Array.au3>
;Global $Paused
HotKeySet("{PAUSE}", "Terminate")
Global $flag = 0
Global $Pid = 0
Global $paused = 0
Global $hWnd_1

Example()

Func Example()
    ; Create a GUI with various controls.
    Global $hGUI = GUICreate("Game", 400, 400)

    ; Create a checkbox control.
      Global $iCheckbox_4 = GUICtrlCreateCheckbox("Mouse Left", 10, 160, 100, 25)
      Global $iCheckbox_5 = GUICtrlCreateCheckbox("Mouse Right", 10, 190, 100, 25)

      Global $Column_2 = GUICtrlCreateLabel("Key", 120, 10, 90, 25)
      Global $Input_Key_4 = GUICtrlCreateLabel("Mouse Left", 120, 170, 90, 25)
      Global $Input_Key_5 = GUICtrlCreateLabel("Mouse Right", 120, 200, 90, 25)

      Global $Column_3 = GUICtrlCreateLabel("Delay (ms)", 240, 10, 90, 25)
      Global $Input_Delay_4 = GUICtrlCreateInput("1000", 240, 160, 90, 25)
      Global $Input_Delay_5 = GUICtrlCreateInput("1000", 240, 190, 90, 25)

      Global $Process_Label = GUICtrlCreateLabel("Process", 10, 220, 200, 25)
      Global $Process_Input = GUICtrlCreateInput("*****.exe", 10, 250, 200, 25)

      Global $Tip = GUICtrlCreateLabel("Start开始脚本,Break Pause暂停继续脚本.", 10, 280, 390, 25)
      Global $Tip_1 = GUICtrlCreateLabel("", 10, 310, 390, 25)

    Global $iClose = GUICtrlCreateButton("Close", 310, 370, 85, 25)
      Global $Start = GUICtrlCreateButton("Start", 310, 340, 85, 25)

    ; Display the GUI.
    GUISetState(@SW_SHOW, $hGUI)

    While 1
      Switch GUIGetMsg()
                        Case $GUI_EVENT_CLOSE, $iClose
                              IniWrite("DefineKeyboard.ini", "Key", "mouse left", GUICtrlRead($Input_Delay_4))
                              IniWrite("DefineKeyboard.ini", "Key", "mouse right", GUICtrlRead($Input_Delay_5))
                ExitLoop
                        Case $Start
                              $flag = 0
                              _IsCheckedProcessExists(GUICtrlRead($Process_Input))
                              GUICtrlSetState($Start, $GUI_DISABLE)
                              GUICtrlSetState($iClose, $GUI_DISABLE)
                              $hWnd_1 = _ProcessGetHWnd($Pid)
                              If $hwnd_1 = 0 Then
                                        MsgBox(0,"Info", "未找到窗口")
                              Else
                                        _Start()
                              EndIf
      EndSwitch
    WEnd

    ; Delete the previous GUI and all controls.
    GUIDelete($hGUI)
EndFunc   ;==>Example

Func _Start()
      GUICtrlSetData($Tip_1, "脚本运行中...")
      ;MsgBox(4096, "Info", "脚本开始!", 1)
      $paused = Not $paused
      ConsoleWrite('Start pause: '&$paused&@CRLF)
      Global $pTimerProc5 = DLLCallbackRegister("_TimerProc","int","hwnd;uint;uint;dword")
      Global $uiTimer5 =DllCall("user32.dll","uint","SetTimer","hwnd",0,"uint",0,"int",GUICtrlRead($Input_Delay_4),"ptr",DllCallbackGetPtr ($pTimerProc5))
      Global $pTimerProc6 = DLLCallbackRegister("_TimerProc","int","hwnd;uint;uint;dword")
      Global $uiTimer6 =DllCall("user32.dll","uint","SetTimer","hwnd",0,"uint",0,"int",GUICtrlRead($Input_Delay_5),"ptr",DllCallbackGetPtr ($pTimerProc6))

      While 1
                If $flag <> 0 Then
                DllCall("user32.dll","int","KillTimer","hwnd",0,"uint",$uiTimer5)
                DllCallbackFree($pTimerProc5)
                DllCall("user32.dll","int","KillTimer","hwnd",0,"uint",$uiTimer6)
                DllCallbackFree($pTimerProc6)
                ExitLoop
                EndIf
      WEnd
      ;MsgBox(0, "提示", "脚本已结束,要重新开始请按Start.", 1)
      $paused = Not $paused
      GUICtrlSetData($Tip_1, "脚本已停止")
EndFunc

Func _TimerProc($hWnd,$uiMsg,$idEvent,$dwTime)
   ;$idEvent能分辨是哪个Timer控件调用了这个函数
   ;$dwTime表示已开机的时间
   Switch$idEvent
               Case $uiTimer5
                        If _IsChecked($iCheckbox_4) Then
                              ;;!!!!!!!!!!!!!!!使用mouseclikcdowndelay 无法实现鼠标左键持续按键
                              Opt("MouseClickDownDelay", GUICtrlRead($Input_Key_4))
                              MouseClick($MOUSE_CLICK_LEFT)
                              Opt("MouseClickDownDelay", 10)
                              ;ControlSend($hWnd_1, "", "", GUICtrlRead($Input_Key_3))
                        EndIf
               Case $uiTimer6
                        If _IsChecked($iCheckbox_5) Then
                              ;;!!!!!!!!!!!!!!!使sleep也无法实现鼠标右键持续按键
                              MouseDown($MOUSE_CLICK_RIGHT)
                              Sleep(GUICtrlRead($Input_Key_5))
                              MouseUp($MOUSE_CLICK_RIGHT)
                              ;ControlSend($hWnd_1, "", "", GUICtrlRead($Input_Key_3))
                        EndIf
   EndSwitch
EndFunc

Func _IsChecked($iControlID)
    Return BitAND(GUICtrlRead($iControlID), $GUI_CHECKED) = $GUI_CHECKED
EndFunc   ;==>_IsChecked

Func _IsCheckedProcessExists($Process)
      If (ProcessExists($Process) = 0) Then
                MsgBox(0, "Error", "进程不存在!")
                Exit
      Else
                $pid = ProcessExists($Process)
      EndIf
EndFunc


Func Terminate()
      ConsoleWrite('Pause: '&$paused&'      Flag: '&$flag&@CRLF)
      If $paused = 1 Then
                GUICtrlSetState($Start, $GUI_ENABLE)
                GUICtrlSetState($iClose, $GUI_ENABLE)
                $flag = 1
      Else
                GUICtrlSetState($Start, $GUI_DISABLE)
                GUICtrlSetState($iClose, $GUI_DISABLE)
                $flag = 0
                _IsCheckedProcessExists(GUICtrlRead($Process_Input))
                $hWnd_1 = _ProcessGetHWnd($Pid)
                If $hwnd_1 = 0 Then
                        MsgBox(0,"Info", "未找到窗口")
                Else
                        _Start()
                EndIf
      EndIf
EndFunc

Func _ProcessGetHWnd($iPid, $iOption = 1, $sTitle = "", $iTimeout = 2000)
      Local $aReturn = [], $aWin, $hTimer = TimerInit()

      While 1

                ; Get list of windows
                $aWin = WinList()
                ;_ArrayDisplay($aWin)
                ; Searches thru all windows
                For $i = 1 To $aWin

                        ; Found a window owned by the given PID
                        If $iPid = WinGetProcess($aWin[$i]) Then

                              ; Option 0 or 1 used
                              If $iOption = 1 OR ($iOption = 0 And $aWin[$i] <> "") Then
                                        Return $aWin[$i]

                              ; Option 2 is used
                              ElseIf $iOption = 2 Then
                                        ReDim $aReturn
                                        $aReturn += 1
                                        $aReturn[$aReturn] = $aWin[$i]
                                        $aReturn[$aReturn] = $aWin[$i]
                              EndIf
                        EndIf
                Next

                ; If option 2 is used and there was matches then the list is returned
                If $iOption = 2 And $aReturn > 0 Then Return $aReturn

                ; If timed out then give up
                If TimerDiff($hTimer) > $iTimeout Then ExitLoop

                ; Waits before new attempt
                Sleep(Opt("WinWaitDelay"))
      WEnd


      ; No matches
      SetError(1)
      Return 0
EndFunc关键代码部分如下:
在settimer中无法使用sleep类似的方法实现鼠标持续按键。
Switch$idEvent
               Case $uiTimer5
                        If _IsChecked($iCheckbox_4) Then
                              ;;!!!!!!!!!!!!!!!使用mouseclikcdowndelay 无法实现鼠标左键持续按键
                              Opt("MouseClickDownDelay", GUICtrlRead($Input_Key_4))
                              MouseClick($MOUSE_CLICK_LEFT)
                              Opt("MouseClickDownDelay", 10)
                              ;ControlSend($hWnd_1, "", "", GUICtrlRead($Input_Key_3))
                        EndIf
               Case $uiTimer6
                        If _IsChecked($iCheckbox_5) Then
                              ;;!!!!!!!!!!!!!!!使sleep也无法实现鼠标右键持续按键
                              MouseDown($MOUSE_CLICK_RIGHT)
                              Sleep(GUICtrlRead($Input_Key_5))
                              MouseUp($MOUSE_CLICK_RIGHT)
                              ;ControlSend($hWnd_1, "", "", GUICtrlRead($Input_Key_3))
                        EndIf
   EndSwitch求大神提示一下,应该怎么在定时器中实现鼠标的持续按键。感谢~

gyp2000 发表于 2019-3-4 01:51:15

鼠标的按下和释放函数是OK的,你代码无法正确工作的原因是你读错了控件。
延迟1000毫秒的控件名是:
$Input_Delay_4 = GUICtrlCreateInput("1000", 240, 160, 90, 25)
你代码去读的控件是:$Input_Key_4
$Input_Key_4读取到的值应该是:Mouse Left
结果就变成了
Sleep("Mouse Left")
因为字符串的值等于零。
执行结果就是
Sleep(0)
自然鼠标无法持续按下。

overrainy 发表于 2019-3-4 13:22:09

测试了一下是可以的,前提是延迟的时间要小于定时时间。关问题喽
页: [1]
查看完整版本: Settimer中持续按住鼠标按键实现[已解决]