Jump to content

MouseClickFast & MouseMoveFast


Zedna
 Share

Recommended Posts

Standard MouseClick & MouseMove functions have got hardcoded Sleep(10) even if you use minimal value for speed parameter (analysed from Autoit's 3.1.0 sources)

so if you need really fast mouse clicking/moving then use my MouseClickFast & MouseMoveFast

X,Y coordinates are in absolute (screen) meaning.

Func _MouseClickFast($x, $y)
    $x = $x*65535/@DesktopWidth
    $y = $y*65535/@DesktopHeight

    _WinAPI_Mouse_Event(BitOR($MOUSEEVENTF_ABSOLUTE, $MOUSEEVENTF_MOVE), $x, $y)
    _WinAPI_Mouse_Event(BitOR($MOUSEEVENTF_ABSOLUTE, $MOUSEEVENTF_LEFTDOWN), $x, $y)
    _WinAPI_Mouse_Event(BitOR($MOUSEEVENTF_ABSOLUTE, $MOUSEEVENTF_LEFTUP), $x, $y)
EndFunc 

Func _MouseMoveFast($x, $y)
    $x = $x*65535/@DesktopWidth
    $y = $y*65535/@DesktopHeight

    _WinAPI_Mouse_Event(BitOR($MOUSEEVENTF_ABSOLUTE, $MOUSEEVENTF_MOVE), $x, $y)
EndFunc

EDIT: You can speed up it little bit with this modification:

$x_koef = 65535/@DesktopWidth
$y_koef = 65535/@DesktopHeight
$User32 = DllOpen("User32.dll")

Func _MouseClickFast2($x, $y, $User32 = "User32.dll")
    $x *= $x_koef
    $y *= $y_koef

    DllCall($User32, "none", "mouse_event", "int", 32769, "int", $x, "int", $y, "int", 0, "int", 0) ; 32769 0x8001 BitOR($MOUSEEVENTF_ABSOLUTE, $MOUSEEVENTF_MOVE)
    DllCall($User32, "none", "mouse_event", "int", 32770, "int", $x, "int", $y, "int", 0, "int", 0) ; 32770 0x8002 BitOR($MOUSEEVENTF_ABSOLUTE, $MOUSEEVENTF_LEFTDOWN)
    DllCall($User32, "none", "mouse_event", "int", 32772, "int", $x, "int", $y, "int", 0, "int", 0) ; 32772 0x8004 BitOR($MOUSEEVENTF_ABSOLUTE, $MOUSEEVENTF_LEFTUP)
EndFunc 

Func _MouseMoveFast2($x, $y, $User32 = "User32.dll")
    $x *= $x_koef
    $y *= $y_koef

    DllCall($User32, "none", "mouse_event", "int", 32769, "int", $x, "int", $y, "int", 0, "int", 0) ; 32769 0x8001 BitOR($MOUSEEVENTF_ABSOLUTE, $MOUSEEVENTF_MOVE)
EndFunc

EDIT2:

Max achieved clicks per second:

MouseClick - 100

_MouseClickFast - 4000

_MouseClickFast2 - 5000

Note: these speeds are related to target app where is clicked, in some of them speed is worse because of their reaction.

Whole testing script:

#AutoIt3Wrapper_useupx=n

#include <Constants.au3>
#include <WinAPI.au3>

Opt('MouseClickDelay',0)
Opt('MouseClickDownDelay',0)
Opt('MouseClickDragDelay',0)

HotKeySet("^{F1}", "Start")
HotKeySet("{ESC}", "Terminate")

Global $User32 
Global $x_koef, $y_koef

;~ Start()
While 1
    Sleep(0)
WEnd

Func Start()
    $start = TimerInit()
    
    For $i = 1 to 1000
        MouseClick('left', 500, 500, 1, 0)
    Next
    
    ConsoleWrite('MouseClick: ' & TimerDiff($start) & @CRLF)
    $start = TimerInit()
    
    For $i = 1 to 1000
        _MouseClickFast(500, 500)
    Next
    
    ConsoleWrite('_MouseClickFast: ' & TimerDiff($start) & @CRLF)
    $start = TimerInit()
    
    $x_koef = 65535/@DesktopWidth
    $y_koef = 65535/@DesktopHeight
    $User32 = DllOpen("User32.dll")
    For $i = 1 to 1000
        _MouseClickFast2(500, 500, $User32)
    Next
    DllClose($User32)

    ConsoleWrite('_MouseClickFast2: ' & TimerDiff($start) & @CRLF)
    MsgBox(0,'Info','hotovo')
EndFunc

Func Terminate()
    Exit
EndFunc

Func OnAutoitExit() 
    HotKeySet("^{F1}")
    HotKeySet("{ESC}")
EndFunc 

Func _MouseClickFast($x, $y, $User32 = "User32.dll")
    $x = $x*65535/@DesktopWidth
    $y = $y*65535/@DesktopHeight

    DllCall($User32, "none", "mouse_event", "int", BitOR($MOUSEEVENTF_ABSOLUTE, $MOUSEEVENTF_MOVE), "int", $x, "int", $y, "int", 0, "int", 0)
    DllCall($User32, "none", "mouse_event", "int", BitOR($MOUSEEVENTF_ABSOLUTE, $MOUSEEVENTF_LEFTDOWN), "int", $x, "int", $y, "int", 0, "int", 0)
    DllCall($User32, "none", "mouse_event", "int", BitOR($MOUSEEVENTF_ABSOLUTE, $MOUSEEVENTF_LEFTUP), "int", $x, "int", $y, "int", 0, "int", 0)
EndFunc 

Func _MouseClickFast2($x, $y, $User32 = "User32.dll")
    $x *= $x_koef
    $y *= $y_koef

    DllCall($User32, "none", "mouse_event", "int", 32769, "int", $x, "int", $y, "int", 0, "int", 0) ; 32769 0x8001 BitOR($MOUSEEVENTF_ABSOLUTE, $MOUSEEVENTF_MOVE)
    DllCall($User32, "none", "mouse_event", "int", 32770, "int", $x, "int", $y, "int", 0, "int", 0) ; 32770 0x8002 BitOR($MOUSEEVENTF_ABSOLUTE, $MOUSEEVENTF_LEFTDOWN)
    DllCall($User32, "none", "mouse_event", "int", 32772, "int", $x, "int", $y, "int", 0, "int", 0) ; 32772 0x8004 BitOR($MOUSEEVENTF_ABSOLUTE, $MOUSEEVENTF_LEFTUP)
EndFunc
Edited by Zedna
Link to comment
Share on other sites

Standard MouseClick & MouseMove functions have got hardcoded Sleep(10) even if you use minimal value for speed parameter

The docs sais:

speed [optional] the speed to move the mouse in the range 1 (fastest) to 100 (slowest). A speed of 0 will move the mouse instantly. Default speed is 10.

So i don't see any reason to use something else :huh2:

P.S

Btw, the first example doesn't work, even with WinAPI.au3 included.

 

Spoiler

Using OS: Win 7 Professional, Using AutoIt Ver(s): 3.3.6.1 / 3.3.8.1

AutoIt_Rus_Community.png AutoIt Russian Community

My Work...

Spoiler

AutoIt_Icon_small.pngProjects: ATT - Application Translate Tool {new}| BlockIt - Block files & folders {new}| SIP - Selected Image Preview {new}| SISCABMAN - SciTE Abbreviations Manager {new}| AutoIt Path Switcher | AutoIt Menu for Opera! | YouTube Download Center! | Desktop Icons Restorator | Math Tasks | KeyBoard & Mouse Cleaner | CaptureIt - Capture Images Utility | CheckFileSize Program

AutoIt_Icon_small.pngUDFs: OnAutoItErrorRegister - Handle AutoIt critical errors {new}| AutoIt Syntax Highlight {new}| Opera Library! | Winamp Library | GetFolderToMenu | Custom_InputBox()! | _FileRun UDF | _CheckInput() UDF | _GUIInputSetOnlyNumbers() UDF | _FileGetValidName() UDF | _GUICtrlCreateRadioCBox UDF | _GuiCreateGrid() | _PathSplitByRegExp() | _GUICtrlListView_MoveItems - UDF | GUICtrlSetOnHover_UDF! | _ControlTab UDF! | _MouseSetOnEvent() UDF! | _ProcessListEx - UDF | GUICtrl_SetResizing - UDF! | Mod. for _IniString UDFs | _StringStripChars UDF | _ColorIsDarkShade UDF | _ColorConvertValue UDF | _GUICtrlTab_CoverBackground | CUI_App_UDF | _IncludeScripts UDF | _AutoIt3ExecuteCode | _DragList UDF | Mod. for _ListView_Progress | _ListView_SysLink | _GenerateRandomNumbers | _BlockInputEx | _IsPressedEx | OnAutoItExit Handler | _GUICtrlCreateTFLabel UDF | WinControlSetEvent UDF | Mod. for _DirGetSizeEx UDF
 
AutoIt_Icon_small.pngExamples: 
ScreenSaver Demo - Matrix included | Gui Drag Without pause the script | _WinAttach()! | Turn Off/On Monitor | ComboBox Handler Example | Mod. for "Thinking Box" | Cool "About" Box | TasksBar Imitation Demo

Like the Projects/UDFs/Examples? Please rate the topic (up-right corner of the post header: Rating AutoIt_Rating.gif)

* === My topics === *

==================================================
My_Userbar.gif
==================================================

 

 

 

AutoIt is simple, subtle, elegant. © AutoIt Team

Link to comment
Share on other sites

@MrCreatoR

No matter what helpfile say what is in my first post is true. I analysed Autoit's 3.1.0 sources to see where is problem when I needed fast clicking in one of my projects. So I discovered this issue and have made this workaround.

In my project clicking worked fine and it was really VERY fast.

Edited by Zedna
Link to comment
Share on other sites

I did also some speed tests which proved my observations

Max achieved clicks per second:

MouseClick - 100

_MouseClickFast - 4000

_MouseClickFast2 - 5000

Note: these speeds are related to target app where is clicked, in some of them speed is worse because of their reaction.

For $i = 1 to 1000
        MouseClick('left', 500, 500, 1, 0)
    Next

    For $i = 1 to 1000
        _MouseClickFast(500, 500)
    Next

    For $i = 1 to 1000
        _MouseClickFast2(500, 500, $User32)
    Next

Whole testing script:

#AutoIt3Wrapper_useupx=n

#include <Constants.au3>
#include <WinAPI.au3>

Opt('MouseClickDelay',0)
Opt('MouseClickDownDelay',0)
Opt('MouseClickDragDelay',0)

HotKeySet("^{F1}", "Start")
HotKeySet("{ESC}", "Terminate")

Global $User32 
Global $x_koef, $y_koef

;~ Start()
While 1
    Sleep(0)
WEnd

Func Start()
    $start = TimerInit()
    
    For $i = 1 to 1000
        MouseClick('left', 500, 500, 1, 0)
    Next
    
    ConsoleWrite('MouseClick: ' & TimerDiff($start) & @CRLF)
    $start = TimerInit()
    
    For $i = 1 to 1000
        _MouseClickFast(500, 500)
    Next
    
    ConsoleWrite('_MouseClickFast: ' & TimerDiff($start) & @CRLF)
    $start = TimerInit()
    
    $x_koef = 65535/@DesktopWidth
    $y_koef = 65535/@DesktopHeight
    $User32 = DllOpen("User32.dll")
    For $i = 1 to 1000
        _MouseClickFast2(500, 500, $User32)
    Next
    DllClose($User32)

    ConsoleWrite('_MouseClickFast2: ' & TimerDiff($start) & @CRLF)
    MsgBox(0,'Info','hotovo')
EndFunc

Func Terminate()
    Exit
EndFunc

Func OnAutoitExit() 
    HotKeySet("^{F1}")
    HotKeySet("{ESC}")
EndFunc 

Func _MouseClickFast($x, $y, $User32 = "User32.dll")
    $x = $x*65535/@DesktopWidth
    $y = $y*65535/@DesktopHeight

    DllCall($User32, "none", "mouse_event", "int", BitOR($MOUSEEVENTF_ABSOLUTE, $MOUSEEVENTF_MOVE), "int", $x, "int", $y, "int", 0, "int", 0)
    DllCall($User32, "none", "mouse_event", "int", BitOR($MOUSEEVENTF_ABSOLUTE, $MOUSEEVENTF_LEFTDOWN), "int", $x, "int", $y, "int", 0, "int", 0)
    DllCall($User32, "none", "mouse_event", "int", BitOR($MOUSEEVENTF_ABSOLUTE, $MOUSEEVENTF_LEFTUP), "int", $x, "int", $y, "int", 0, "int", 0)
EndFunc 

Func _MouseClickFast2($x, $y, $User32 = "User32.dll")
    $x *= $x_koef
    $y *= $y_koef

    DllCall($User32, "none", "mouse_event", "int", 32769, "int", $x, "int", $y, "int", 0, "int", 0) ; 32769 0x8001 BitOR($MOUSEEVENTF_ABSOLUTE, $MOUSEEVENTF_MOVE)
    DllCall($User32, "none", "mouse_event", "int", 32770, "int", $x, "int", $y, "int", 0, "int", 0) ; 32770 0x8002 BitOR($MOUSEEVENTF_ABSOLUTE, $MOUSEEVENTF_LEFTDOWN)
    DllCall($User32, "none", "mouse_event", "int", 32772, "int", $x, "int", $y, "int", 0, "int", 0) ; 32772 0x8004 BitOR($MOUSEEVENTF_ABSOLUTE, $MOUSEEVENTF_LEFTUP)
EndFunc
Link to comment
Share on other sites

I did also some speed tests which proved my observations

These tests only shows that your function return faster then built-in funcs, but the mouse clicks/movement is the same, well, for the eye view anyway.

What Autoit/OS version do you have?

Environment(Language:0419 Keyboard:00000409 OS:WIN_XP/Service Pack 3 CPU:X64 OS:X86)

AutoIt(3.3.6.1)

 

Spoiler

Using OS: Win 7 Professional, Using AutoIt Ver(s): 3.3.6.1 / 3.3.8.1

AutoIt_Rus_Community.png AutoIt Russian Community

My Work...

Spoiler

AutoIt_Icon_small.pngProjects: ATT - Application Translate Tool {new}| BlockIt - Block files & folders {new}| SIP - Selected Image Preview {new}| SISCABMAN - SciTE Abbreviations Manager {new}| AutoIt Path Switcher | AutoIt Menu for Opera! | YouTube Download Center! | Desktop Icons Restorator | Math Tasks | KeyBoard & Mouse Cleaner | CaptureIt - Capture Images Utility | CheckFileSize Program

AutoIt_Icon_small.pngUDFs: OnAutoItErrorRegister - Handle AutoIt critical errors {new}| AutoIt Syntax Highlight {new}| Opera Library! | Winamp Library | GetFolderToMenu | Custom_InputBox()! | _FileRun UDF | _CheckInput() UDF | _GUIInputSetOnlyNumbers() UDF | _FileGetValidName() UDF | _GUICtrlCreateRadioCBox UDF | _GuiCreateGrid() | _PathSplitByRegExp() | _GUICtrlListView_MoveItems - UDF | GUICtrlSetOnHover_UDF! | _ControlTab UDF! | _MouseSetOnEvent() UDF! | _ProcessListEx - UDF | GUICtrl_SetResizing - UDF! | Mod. for _IniString UDFs | _StringStripChars UDF | _ColorIsDarkShade UDF | _ColorConvertValue UDF | _GUICtrlTab_CoverBackground | CUI_App_UDF | _IncludeScripts UDF | _AutoIt3ExecuteCode | _DragList UDF | Mod. for _ListView_Progress | _ListView_SysLink | _GenerateRandomNumbers | _BlockInputEx | _IsPressedEx | OnAutoItExit Handler | _GUICtrlCreateTFLabel UDF | WinControlSetEvent UDF | Mod. for _DirGetSizeEx UDF
 
AutoIt_Icon_small.pngExamples: 
ScreenSaver Demo - Matrix included | Gui Drag Without pause the script | _WinAttach()! | Turn Off/On Monitor | ComboBox Handler Example | Mod. for "Thinking Box" | Cool "About" Box | TasksBar Imitation Demo

Like the Projects/UDFs/Examples? Please rate the topic (up-right corner of the post header: Rating AutoIt_Rating.gif)

* === My topics === *

==================================================
My_Userbar.gif
==================================================

 

 

 

AutoIt is simple, subtle, elegant. © AutoIt Team

Link to comment
Share on other sites

These tests only shows that your function return faster then built-in funcs, but the mouse clicks/movement is the same, well, for the eye view anyway.

You are wrong.

As I said in Autoit there is Sleep(10) no matter what speed you chose in your script so my workaround do the same as Autoit but without some internal general tests and without that Sleep(10).

If you want I can send to you related piece of source code with description where is hardcoded Sleep(10).

And as I said result in real application (in my project) was very fast compared to very slow native functions.

EDIT:

On other way. Each application has different reaction time on mouse movements/clicks

so on some applications it's not as fast as on others. But generally it's faster on each because of lacking Sleep(10).

Edited by Zedna
Link to comment
Share on other sites

What do you mean by "doesn't work"?

Maybe you only need to add right includes for constants used in script.

I can't think of a situation where I would need more than 100 mouse clicks a second, in fact I not even more than 3 for the apps I write. An application which can respond at the rate of 4000 clicks a second is mind boggling. I count my users lucky if they get any respoons at all to one click. Can you give me an example?

Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.
Link to comment
Share on other sites

You are wrong

Maybe, but if you could provide a test that shows that (what is the actual speed of mouse click), i will be convinced.

What do you mean by "doesn't work"?

I mean that there is errors related to non declared vars.

Maybe you only need to add right includes for constants used in script.

I know, but when you post an example, you should provide these includes, don't you think so? :huh2:

 

Spoiler

Using OS: Win 7 Professional, Using AutoIt Ver(s): 3.3.6.1 / 3.3.8.1

AutoIt_Rus_Community.png AutoIt Russian Community

My Work...

Spoiler

AutoIt_Icon_small.pngProjects: ATT - Application Translate Tool {new}| BlockIt - Block files & folders {new}| SIP - Selected Image Preview {new}| SISCABMAN - SciTE Abbreviations Manager {new}| AutoIt Path Switcher | AutoIt Menu for Opera! | YouTube Download Center! | Desktop Icons Restorator | Math Tasks | KeyBoard & Mouse Cleaner | CaptureIt - Capture Images Utility | CheckFileSize Program

AutoIt_Icon_small.pngUDFs: OnAutoItErrorRegister - Handle AutoIt critical errors {new}| AutoIt Syntax Highlight {new}| Opera Library! | Winamp Library | GetFolderToMenu | Custom_InputBox()! | _FileRun UDF | _CheckInput() UDF | _GUIInputSetOnlyNumbers() UDF | _FileGetValidName() UDF | _GUICtrlCreateRadioCBox UDF | _GuiCreateGrid() | _PathSplitByRegExp() | _GUICtrlListView_MoveItems - UDF | GUICtrlSetOnHover_UDF! | _ControlTab UDF! | _MouseSetOnEvent() UDF! | _ProcessListEx - UDF | GUICtrl_SetResizing - UDF! | Mod. for _IniString UDFs | _StringStripChars UDF | _ColorIsDarkShade UDF | _ColorConvertValue UDF | _GUICtrlTab_CoverBackground | CUI_App_UDF | _IncludeScripts UDF | _AutoIt3ExecuteCode | _DragList UDF | Mod. for _ListView_Progress | _ListView_SysLink | _GenerateRandomNumbers | _BlockInputEx | _IsPressedEx | OnAutoItExit Handler | _GUICtrlCreateTFLabel UDF | WinControlSetEvent UDF | Mod. for _DirGetSizeEx UDF
 
AutoIt_Icon_small.pngExamples: 
ScreenSaver Demo - Matrix included | Gui Drag Without pause the script | _WinAttach()! | Turn Off/On Monitor | ComboBox Handler Example | Mod. for "Thinking Box" | Cool "About" Box | TasksBar Imitation Demo

Like the Projects/UDFs/Examples? Please rate the topic (up-right corner of the post header: Rating AutoIt_Rating.gif)

* === My topics === *

==================================================
My_Userbar.gif
==================================================

 

 

 

AutoIt is simple, subtle, elegant. © AutoIt Team

Link to comment
Share on other sites

I mean that there is errors related to non declared vars.

I know, but when you post an example, you should provide these includes, don't you think so? :huh2:

Sorry you are right

but I don't follow standard Autoit's includes at all.

In previous versions there was GUIConstants.au3 containing ALL the constansts and I liked this approach very much.

You only added this one include and all worked fine.

In latest Autoit's versions this was changed and I stay with my old (not compatible) solution:

I maded my own modified copy of GUIConstants.au3 with this content

#include <AVIConstants.au3>
#include <ButtonConstants.au3>
#include <ComboConstants.au3>
#include <Constants.au3>
#include <DateTimeConstants.au3>
#include <EditConstants.au3>
#include <FontConstants.au3>
#include <GDIPlusConstants.au3>
#include <GUIConstantsEx.au3>
#include <HeaderConstants.au3>
#include <ImageListConstants.au3>
#include <IPAddressConstants.au3>
#include <ListBoxConstants.au3>
#include <ListViewConstants.au3>
#include <MemoryConstants.au3>
#include <MenuConstants.au3>
#include <ProgressConstants.au3>
#include <RebarConstants.au3>
#include <ScrollBarConstants.au3>
#include <SecurityConstants.au3>
#include <SliderConstants.au3>
#include <StaticConstants.au3>
#include <StatusBarConstants.au3>
#include <StructureConstants.au3>
#include <TabConstants.au3>
#include <ToolbarConstants.au3>
#include <ToolTipConstants.au3>
#include <TreeViewConstants.au3>
#include <UpDownConstants.au3>
#include <WindowsConstants.au3>

so I use only this one.

If you have problems with includes you can use Autoit3Wrapper directive FixIncludes (I don't know exact name).

The main reason why I use this my personal solution is many older scripts this is also reason for me using Autoit 3.2.12.1 too.

EDIT: I will fix includes in this my script.

EDIT2: I checked where are defined mouse event constants and it's in Constants.au3

I already have got this one included so I don't know where is source of your problem

#include <Constants.au3>

Edited by Zedna
Link to comment
Share on other sites

Maybe, but if you could provide a test that shows that (what is the actual speed of mouse click), i will be convinced.

My testing script clicks at position 500,500

I prepare different application to this position before starting of my script

so I tested by this way several applications and their reaction times (number of clicks achieved) differs very much.

So it means my script really depends on reaction time of target application it's not only syntetic test.

Here are some of my results (time in miliseconds needed to finish 1000 clicks):

Scite

MouseClick: 19594.4911993005

_MouseClickFast: 9186.45135066049

Desktop

MouseClick: 10290.8210401043

_MouseClickFast: 401.665854179791

Black

MouseClick: 10088.7093192012 --> 100/s

_MouseClickFast: 242.13496408063 --> 4000/s

_MouseClickFast2: 194.668316783278 --> 5000/s

Here is source of my Black application which I use for myself as kind of "screensaver".

#Compiler_Icon=cerna.ico

#NoTrayIcon 
#include <GUIConstants.au3>

GUICreate("Černá", @DesktopWidth, @DesktopHeight, 0, 0, $WS_POPUP)
GUISetBkColor(0x000000)
GUISetState(@SW_SHOW)

While 1
    $msg = GuiGetMsg()
    If $msg = $GUI_EVENT_CLOSE Then ExitLoop
    Sleep(100)
WEnd
Edited by Zedna
Link to comment
Share on other sites

Nice, but I have a question.

Why do we have the sleep hard-coded into Autoit anyways, if it isn't helping anything, shouldn't we toss the sleep and increase Autoit's performance speed wise.

Unless this sleep somehow makes it more accurate.

:huh2:

Link to comment
Share on other sites

Here are some of my results (time in miliseconds needed to finish 1000 clicks):

MouseClick('left', 500, 500, 1000, 0)

this will click faster than your funcs :huh2:

But it's not what i mean, i am talking about the speed of the click, the last parameter in MouseClick. So i supose your functions is to return faster, because i don't see any difference in the actualy mouse movement.

 

Spoiler

Using OS: Win 7 Professional, Using AutoIt Ver(s): 3.3.6.1 / 3.3.8.1

AutoIt_Rus_Community.png AutoIt Russian Community

My Work...

Spoiler

AutoIt_Icon_small.pngProjects: ATT - Application Translate Tool {new}| BlockIt - Block files & folders {new}| SIP - Selected Image Preview {new}| SISCABMAN - SciTE Abbreviations Manager {new}| AutoIt Path Switcher | AutoIt Menu for Opera! | YouTube Download Center! | Desktop Icons Restorator | Math Tasks | KeyBoard & Mouse Cleaner | CaptureIt - Capture Images Utility | CheckFileSize Program

AutoIt_Icon_small.pngUDFs: OnAutoItErrorRegister - Handle AutoIt critical errors {new}| AutoIt Syntax Highlight {new}| Opera Library! | Winamp Library | GetFolderToMenu | Custom_InputBox()! | _FileRun UDF | _CheckInput() UDF | _GUIInputSetOnlyNumbers() UDF | _FileGetValidName() UDF | _GUICtrlCreateRadioCBox UDF | _GuiCreateGrid() | _PathSplitByRegExp() | _GUICtrlListView_MoveItems - UDF | GUICtrlSetOnHover_UDF! | _ControlTab UDF! | _MouseSetOnEvent() UDF! | _ProcessListEx - UDF | GUICtrl_SetResizing - UDF! | Mod. for _IniString UDFs | _StringStripChars UDF | _ColorIsDarkShade UDF | _ColorConvertValue UDF | _GUICtrlTab_CoverBackground | CUI_App_UDF | _IncludeScripts UDF | _AutoIt3ExecuteCode | _DragList UDF | Mod. for _ListView_Progress | _ListView_SysLink | _GenerateRandomNumbers | _BlockInputEx | _IsPressedEx | OnAutoItExit Handler | _GUICtrlCreateTFLabel UDF | WinControlSetEvent UDF | Mod. for _DirGetSizeEx UDF
 
AutoIt_Icon_small.pngExamples: 
ScreenSaver Demo - Matrix included | Gui Drag Without pause the script | _WinAttach()! | Turn Off/On Monitor | ComboBox Handler Example | Mod. for "Thinking Box" | Cool "About" Box | TasksBar Imitation Demo

Like the Projects/UDFs/Examples? Please rate the topic (up-right corner of the post header: Rating AutoIt_Rating.gif)

* === My topics === *

==================================================
My_Userbar.gif
==================================================

 

 

 

AutoIt is simple, subtle, elegant. © AutoIt Team

Link to comment
Share on other sites

In tests, Zedna's click function is indeed faster than MouseClick(), MrCreator. I verified myself with clicks on a line sent to MS Paint (visible results).

--

Also, Zedna - the calculation for X/Y position is off. You can verify with MouseGetPos() on certain locations. Instead, use this:

; Calculation (0-1599) -> (Virtual range: 0-65535)
    If $x Then $x=($x+1)*(65536/@DesktopWidth)-1
    ; Calculation (0-1199) -> (Virtual range: 0-65535)
    If $y Then $y=($y+1)*(65536/@DesktopHeight)-1
Edited by Ascend4nt
Link to comment
Share on other sites

OK.

Here is related piece of Autoit's sources:

///////////////////////////////////////////////////////////////////////////////
// MouseClick()
// Performs a mouse click at the requested coords
// MouseClick( "left|middle|right", [x,y] [#clicks] [speed(0-100)] )
///////////////////////////////////////////////////////////////////////////////

AUT_RESULT AutoIt_Script::F_MouseClick(VectorVariant &vParams, Variant &vResult)
{
    uint    iNumParams = vParams.size();
    int     nSpeed;
    int     nClicks, nX=0, nY=0;

    // Check for x without y
    if (iNumParams == 2)
    {
        FatalError(IDS_AUT_E_FUNCTIONNUMPARAMS);
        return AUT_ERR;
    }

    // Get coords
    if (iNumParams >= 2)
    {
        nX = vParams[1].nValue();
        nY = vParams[2].nValue();
    }

    // Get number of clicks
    if (iNumParams >= 4)
    {
        nClicks = vParams[3].nValue();
        if (nClicks <= 0)
            return AUT_OK;  // 0 or less clicks specified
    }
    else
        nClicks = 1;

    // Get speed
    if (iNumParams >= 5)
        nSpeed = vParams[4].nValue();
    else
        nSpeed = -1;                            // -1 = default speed


    // Do we need to move the mouse?
    if (iNumParams > 1)
        MouseMoveExecute(nX, nY, nSpeed);


    for (int i=0; i<nClicks; ++i)
    {
        // Do the click
        if (Util_MouseDown(vParams[0].szValue()) == 0)
        {
            // not a valid click
            vResult = 0;
            return AUT_OK;
        }
        Util_Sleep(m_nMouseClickDownDelay);
        if (Util_MouseUp(vParams[0].szValue()) == 0) {
            // not a valid click
            vResult = 0;
            return AUT_OK;
        }
        Util_Sleep(m_nMouseClickDelay);
    }

    return AUT_OK;

} // MouseClick()

///////////////////////////////////////////////////////////////////////////////
// MouseMoveExecute()
// Function to actually move the mouse
///////////////////////////////////////////////////////////////////////////////

void AutoIt_Script::MouseMoveExecute(int x, int y, int nSpeed)
{
    POINT   ptCur, ptOrigin;
    RECT    rect;
    int     xCur, yCur;
    int     delta;
    const   int nMinSpeed = 32;


    // Convert coords to screen/active window/client
    ConvertCoords(m_nCoordMouseMode, ptOrigin);
    x += ptOrigin.x;
    y += ptOrigin.y;

    // Get size of desktop
    GetWindowRect(GetDesktopWindow(), &rect);

    // Sanity check coords - removed so that it works on multiple monitors where -ve values are OK
/*  if (x < 0)
        x = 0;
    else if (x > rect.right)
        x = rect.right;

    if (y < 0)
        y = 0;
    else if (y > rect.bottom)
        y = rect.bottom; */

    // Convert our coords to mouse_event coords
    x = ((65535 * x) / (rect.right-1)) + 1;
    y = ((65535 * y) / (rect.bottom-1)) + 1;


    // Are we slowly moving or insta-moving?
    if (nSpeed == 0)
    {
        mouse_event(MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE, x, y, 0, 0);
        Util_Sleep(10);                         // Hopefully fixes "clicks before moving" bug
        return;
    }

    // Sanity check for speed
    if (nSpeed < 0 || nSpeed > 100)
        nSpeed = 10;                            // Default is speed 10


    // So, it's a more gradual speed that is needed :)
    GetCursorPos(&ptCur);
    xCur = ((ptCur.x * 65535) / (rect.right-1)) + 1;
    yCur = ((ptCur.y * 65535) / (rect.bottom-1)) + 1;

    while (xCur != x || yCur != y)
    {
        if (xCur < x)
        {
            delta = (x - xCur) / nSpeed;
            if (delta == 0 || delta < nMinSpeed)
                delta = nMinSpeed;
            if ((xCur + delta) > x)
                xCur = x;
            else
                xCur += delta;
        }
        else
            if (xCur > x)
            {
                delta = (xCur - x) / nSpeed;
                if (delta == 0 || delta < nMinSpeed)
                    delta = nMinSpeed;
                if ((xCur - delta) < x)
                    xCur = x;
                else
                    xCur -= delta;
            }

        if (yCur < y)
        {
            delta = (y - yCur) / nSpeed;
            if (delta == 0 || delta < nMinSpeed)
                delta = nMinSpeed;
            if ((yCur + delta) > y)
                yCur = y;
            else
                yCur += delta;
        }
        else
            if (yCur > y)
            {
                delta = (yCur - y) / nSpeed;
                if (delta == 0 || delta < nMinSpeed)
                    delta = nMinSpeed;
                if ((yCur - delta) < y)
                    yCur = y;
                else
                    yCur -= delta;
            }

        mouse_event(MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE, xCur, yCur, 0, 0);

        Util_Sleep(10);                         // 20 ms sleep inbetween moves
    }

} // MouseMoveExecute()

///////////////////////////////////////////////////////////////////////////////
// Util_MouseDown()
//
// Produces a Mouse Down event
// Buttons recognized:  left|middle|right|main|menu|primary|secondary
///////////////////////////////////////////////////////////////////////////////

int Util_MouseDown(const char *szButton)
{
    char swapped[4];
    DWORD event=0;

    if ( szButton[0] == '\0' || stricmp(szButton, "LEFT")==0 ) // empty string or "left"
        event = MOUSEEVENTF_LEFTDOWN;
    else if ( stricmp(szButton,"RIGHT")==0 )
        event = MOUSEEVENTF_RIGHTDOWN;
    else if ( stricmp(szButton,"MIDDLE")==0 )
        event = MOUSEEVENTF_MIDDLEDOWN;
    else
    {
        Util_RegReadString(HKEY_CURRENT_USER, "Control Panel\\Mouse", "SwapMouseButtons", 4, swapped );
        if ( swapped[0] == '1') // buttons swapped
        {
            if ( stricmp(szButton,"MAIN")==0 || stricmp(szButton, "PRIMARY"))
                event = MOUSEEVENTF_RIGHTDOWN;
            else if ( stricmp(szButton,"MENU")==0 || stricmp(szButton, "SECONDARY"))
                event = MOUSEEVENTF_LEFTDOWN;
        }
        else
        {
            if ( stricmp(szButton,"MAIN")==0 || stricmp(szButton, "PRIMARY"))
                event = MOUSEEVENTF_LEFTDOWN;
            else if ( stricmp(szButton,"MENU")==0 || stricmp(szButton, "SECONDARY"))
                event = MOUSEEVENTF_RIGHTDOWN;
        }
    }
    if (event != 0) {
        mouse_event(event, 0, 0, 0, 0);
        return 1;
    }
    else
        return 0;

} // Util_MouseDown()


///////////////////////////////////////////////////////////////////////////////
// Util_MouseUp()
//
// Produces a Mouse Down event
///////////////////////////////////////////////////////////////////////////////

int Util_MouseUp(const char *szButton)
{
    char swapped[4];
    DWORD event = 0;    // default to 0 in case no strings match

    if ( szButton[0] == '\0' || stricmp(szButton, "LEFT")==0 ) // empty string or "left"
        event = MOUSEEVENTF_LEFTUP;
    else if ( stricmp(szButton,"RIGHT")==0 )
        event = MOUSEEVENTF_RIGHTUP;
    else if ( stricmp(szButton,"MIDDLE")==0 )
        event = MOUSEEVENTF_MIDDLEUP;
    else
    {
        Util_RegReadString(HKEY_CURRENT_USER, "Control Panel\\Mouse", "SwapMouseButtons", 4, swapped );
        if ( swapped[0] = '1')  // buttons swapped
        {
            if ( stricmp(szButton,"MAIN")==0 || stricmp(szButton, "PRIMARY"))
                event = MOUSEEVENTF_RIGHTUP;
            else if ( stricmp(szButton,"MENU")==0 || stricmp(szButton, "SECONDARY"))
                event = MOUSEEVENTF_LEFTUP;
        }
        else
        {
            if ( stricmp(szButton,"MAIN")==0 || stricmp(szButton, "PRIMARY"))
                event = MOUSEEVENTF_LEFTUP;
            else if ( stricmp(szButton,"MENU")==0 || stricmp(szButton, "SECONDARY"))
                event = MOUSEEVENTF_RIGHTUP;
        }
    }
    if (event != 0) {
        mouse_event(event, 0, 0, 0, 0);
        return 1;
    }
    else
        return 0;

} // Util_MouseUp()

///////////////////////////////////////////////////////////////////////////////
// Util_Sleep()
//
// A more accurate Sleep(), uses performance counters if possible, otherwise
// just does a normal sleep (timegettime no more accurate than sleep!)
//
// A thread time slice is 10ms on NT, 15ms on NT multiprocessor and 55 ms on
// 9x
///////////////////////////////////////////////////////////////////////////////

void Util_Sleep(int nTimeOut)
{
    // Handle the special cases -1 and 0 first
    if (nTimeOut < 0)
        return;                                 // No sleep at all for -ve numbers
    else if (nTimeOut == 0)
    {
        ::Sleep(0);                             // Special case for 0
        return;
    }

    __int64     start, cur, freq;
    double      diff;
    DWORD       dwMin;
    DWORD       dwTimeOut = (DWORD)nTimeOut;

    // Set the minimum Sleep accuracy
    if (g_oVersion.IsWin9x())
        dwMin = 55;
    else
        dwMin = 10;

    // If Sleep is >= dwMin or no performance counters are available then use native Sleep()
    if (dwTimeOut >= dwMin || !QueryPerformanceCounter((LARGE_INTEGER *)&start))
    {
        ::Sleep(dwTimeOut);
        return;
    }

    // Get frequency
    QueryPerformanceFrequency((LARGE_INTEGER *)&freq);

    // Note that we must at least do a Sleep(0) once otherwise the SendTo functions get out of
    // sync - especially on 9x/NT4 but also had one report for XP too (seems be on the keydowndelay)
    do
    {
        ::Sleep(0);                             // Reduce CPU usage - Sleep 0 is special
        QueryPerformanceCounter((LARGE_INTEGER *)&cur);
        diff = ((double)(cur - start) / (double)freq) * 1000.0;

    } while ((DWORD)diff < dwTimeOut);

} // Util_Sleep()

MSDN
Sleep Function
Suspends the execution of the current thread until the time-out interval elapses.

Syntax
VOID WINAPI Sleep(__in  DWORD dwMilliseconds);

dwMilliseconds [in] - The time interval for which execution is to be suspended, in milliseconds.

A value of zero causes the thread to relinquish the remainder of its time slice to any other thread that is ready to run. If there are no other threads ready to run, the function returns immediately, and the thread continues execution.
Windows XP/2000:  A value of zero causes the thread to relinquish the remainder of its time slice to any other thread of equal priority that is ready to run. If there are no other threads of equal priority ready to run, the function returns immediately, and the thread continues execution. This behavior changed starting with Windows Server 2003.

A value of INFINITE indicates that the suspension should not time out.

And here is hardcoded Sleep(10) which I was talking about:

AutoIt_Script::MouseMoveExecute --> this function is called also from AutoIt_Script::F_MouseClick

-->

// Are we slowly moving or insta-moving?
    if (nSpeed == 0)
    {
        mouse_event(MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE, x, y, 0, 0);
        Util_Sleep(10);                         // Hopefully fixes "clicks before moving" bug
        return;
    }
Link to comment
Share on other sites

Also, Zedna - the calculation for X/Y position is off. You can verify with MouseGetPos() on certain locations. Instead, use this:

; Calculation (0-1599) -> (Virtual range: 0-65535)
    If $x Then $x=($x+1)*(65536/@DesktopWidth)-1
    ; Calculation (0-1199) -> (Virtual range: 0-65535)
    If $y Then $y=($y+1)*(65536/@DesktopHeight)-1

Thanks.

I will look at this deeply later.

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...