Get real mouse displacement while dragging - mouse

I'm trying to get the final dragging point (right button) with AutoHotKey:
~RButton::
CoordMode, Mouse, Screen
MouseGetPos, x0, y0
while GetKeyState("RButton")
{
MouseGetPos, x1, y1
Sleep, 10
}
MsgBox X: %x1% Y: %y1%
return
What it does is to wait the RightButton of the mouse to be pressed, gather x0 and y0 (inicial coordinates) and while the button is still pressed it gets the position of the mouse again (each 10 miliseconds).
After that it just displays the final coordinates.
It works nicely in normal environment but in this particular case this script needs to be executed in an application that takes control of the mouse when the right button is pressed. What that particular program does is to bring the mouse pointer to the center of the screen and when the button is realised it leaves it in the initial position. (x1, y1 are always the center of my screen, in pixels).
I believe that internally this program gathers the displacement of the mouse (while dragging) and use it for user interaction.
My question is: is there a way to obtain the real mouse input rather than looking at the screen and searching for the mouse pointer ( ~MouseGetPos) ? Is that achievable with AutoHotKey?

You can use a mouse hook to get notified for every mouse movement. MSDN Hooks
To use hooks with AHK you have to use DllCall.
#Persistent
MouseHook := DllCall("SetWindowsHookEx", "int", 14 ; WH_MOUSE_LL = 14
, "uint", RegisterCallback("MouseProc"), "uint", 0, "uint", 0)
return
MouseProc(nCode, wParam, lParam)
{
global MouseHook
Critical
if wParam = 0x200 ; WM_MOUSEMOVE
{
ToolTip % NumGet(lParam+0,0,"int") ", " NumGet(lParam+4,0,"int")
}
return DllCall("CallNextHookEx", "uint", MouseHook
, "int", nCode, "uint", wParam, "uint", lParam)
}
Example Source

Related

How do I activate a script only if the mouse is at a certain coordinate of the screen without interfering with my keyboard?

I cooked up a script that lets me map my keyboard's media shortcuts to my mouse LRM buttons when they are pressed while the mouse coordinate is leftmost or rightmost of the screen. While it does work, I'm having having strange side effects:
When I have caps lock on, ever few strokes the letter comes out lowercase.
When I use shift to type capital letters for an extended period of time, this will turn on caps lock
Using the keyboard history, I see that my script is constantly sending the "Alt Up" key, I did this so that it release the "Alt Down" state, but something is off.
My goal is to send an modifier key when a mouse is over a certain coordinate, so that when I click with that mouse button, it launches another ahk-programmed shortcut. But can't figure out where the logic error is in my code or thinking process.
Here's the script:
; ------------------------
; Global Initializers
#InstallKeybdHook
#MaxThreadsPerHotkey 1
; ---------------------
; Control Spotify; position your mouse top-most edge and use L/M/R-mouse keys.
SetTimer, WatchCursorx, 1000
return
WatchCursorx:
CoordMode, Mouse, Screen
MouseGetPos, xpos, ypos
;Based on location of the mouse simulate shortcut activation
If (xpos == 2559 || xpos == 0)
{
Send {Alt Down}
}
Else
{
Send {Alt Up}
}
return
;Define shortcuts mentioned above
!RButton::
Send {Media_Next}
return
!LButton::
Send {Media_Prev}
return
!MButton::
send {Media_Play_Pause}
return
#If(docs) is meant for this.
You could use it for example like this:
CoordMode, Mouse, Screen
#If, MouseOnTheRight()
LButton::SendInput, {Media_Prev}
RButton::SendInput, {Media_Next}
MButton::SendInput, {Media_Play_Pause}
#If
MouseOnTheRight()
{
MouseGetPos, x
return x == A_ScreenWidth - 1
}
Per my comments, try it like this:
CoordMode, Mouse, Screen
~RButton::
MouseGetPos, xpos, ypos
If (xpos == 2559 || xpos == 0)
{
Send {Media_Next}
sleep, 500
Send {esc} ' this gets rid of right context menu
}
return
~LButton::
MouseGetPos, xpos, ypos
If (xpos == 2559 || xpos == 0)
Send {Media_Prev}
return
~MButton::
MouseGetPos, xpos, ypos
If (xpos == 2559 || xpos == 0)
Send {Media_Play_Pause}
return
Note, the preceding ~ lets the original mouse click go through so ordinarily the context menu will come up on right click. I add a Sleep and Send Escape key to dismiss . . . Ymmv

Move mouse between two monitors

How can I move the mouse pointer between monitors using a keyboard shortcut? I'm using autohotkey.
I didn't find a straightforward answer to it, so here's what I suggest.
Here's my approach, using Ctrl+Space for this function:
^Space::
CoordMode, Mouse, Screen ; This is needed to assure that you get your mouse coordinates related to the screen, not to the window
MouseGetPos, MouseX, MouseY
if( MouseX > 1920) ; 1920 is the Width of my monitor number 1, replace it with yours
{
MouseMove, -A_ScreenWidth, 0, 0, R
}
else
{
MouseMove, A_ScreenWidth, 0, 0, R
}
return

pixelsearch and click right pixel

IF NOT A_IsAdmin ; Runs script as Admin.
{
Run *RunAs "%A_ScriptFullPath%"
ExitApp
}
#MaxThreadsPerHotkey, 2
CoordMode, Pixel, Screen
#singleInstance, Force
toggle = 0
upperLeftX := 750
upperLeftY := 400
lowerRightX := 850
lowerRightY := 500
F8:: ; press F8 to toggle the loop on/off.
SoundBeep
Toggle := !Toggle
While Toggle
{ ;-- Begin of loop.
PixelSearch, X, Y,%upperLeftX%, %upperLeftY%, %lowerRightX%, %lowerRightY%, 0x000000, 0, Fast RGB
IF ErrorLevel = 1 ; IF NOTFound.
{
sleep, 100
}
IF ErrorLevel = 0 ; IF Found.
{
MouseClick, left
sleep, 300
}
} ;-- End of Loop.
return
F8 starts loop and this code checks specific pixel in rectangle and sends left click.
It works with [MouseClick, left, %X%, %Y%].But I want to know how can I use dllcall mouse event to click on specific pixel.
for example
DllCall("mouse_event",uint,1,int,%X%,int,%Y%,uint,0,int,0)
But its not working
I doubt that you actually want to do this via DLL calls. mouse_event doesn't even take coordinates, but values between 0-65535.
If you want to be able to click any pixel on the screen make sure you set it to be relative to the screen: CoordMode, Mouse, Screen
Then use ControlClick/PostMessage/SendMessage if you don't want to affect your mouse pointer by that click. Or use MouseClick/Click. Or MouseMove+Send, {LButton}.

change the coordmode from the active window to any window

this is the situation:
1) I have 3 Windows;
2) My mouse is positioned over any of them (active table under the mouse cursor);
3) I have the ahk_id of both Windows (stored in global variables);
4) Every 5 seconds, I would check (regardless of the movement of the mouse cursor), if a pixel of a specific window (window1, window2...) has a certain color;
5) Click with a controlclik of that pixel and regain control of the starting window under the mouse cursor.
checktime(){
var := Mod(A_Sec, 5)
if (var = 0){
checkpixel(window1) ; window1 is an ahk_id, stored in a global variable
checkpixel(window2)
checkpixel(window3)
}
checkpixel(window){
CoordMode, ToolTip, window ; this line of code is definitely wrong, what do you recommend?
pixelgetcolor, color, 440, 295
if(color=0x4E3500){
controlclick, x440 y295, ahk_id %window%
}
thanks in advance for the answers!

Script to open right-click menu and choose menu item

In a specific program, I want to assign a hotkey to the action of right clicking at the cursor's current position, then moving the cursor to choose an item on that menu, then moving the cursor again to choose an item on the sub-menu. I've gotten as far as the first two commands. When I get to the mousemove, no matter what coordinates I put in, the cursor shoots to the upper left corner of the screen, when what I would like it to do is first move 100 pixels to the right and 60 pixels up, then 100 pixels to the right, zero pixels on the y-axis. Clearly I am misunderstanding something. Please advise.
Thanks,
Ellen
s::
MouseGetPos
Click right
sleep, 100
MouseMove, 60, -60, 5, R
Sleep, 100
MouseMove, 200, 0, 5, R
MouseClick, L
return
Ellen, first of all, if at all possible try if you could use keyboard shortcuts.
Please check: Control Panel\Ease of Access Center\Make the keyboard easier to use\Underline keyboard shortcuts and access keys. This will show the shortcuts that you can use. This way you might even find the keyboard shortcut for the menu, instead of using the mouse location.
^+b:: ; Record the location of the menu at the beginnin with [Shift]+[Ctrl]+b
SoundBeep, 500, 500
ToolTip, Click on the "XYZ" Link
KeyWait, LButton, D
MouseGetPos, xPos, yPos
Send, {Esc}
ToolTip
Return
^b::
MouseClick, Right, xPos, yPos
;Mousemove, 100, 60 R
Send, e : OR WHATEVER Shortcut letter OR.....
Send, {Down 3}{Enter} ; IF you want to use down arrow 3 times to get to the item.
Return
Modified, where YOU have to position the mouse on the always changing menu position.
^b::
MouseClick, Right ; presses where the mouse is located
;Mousemove, 100, 60 R
Send, e : OR WHATEVER Shortcut letter OR.....
Send, {Down 3}{Enter} ; IF you want to use down arrow 3 times to get to the item.
Return
If you can identify the menu ID (with AHK Windows Spy, place the mouse over the menu and look at "under the mouse"), you could use controlsend. This would be location independent since controlsend will use the menu ID to send a signal. If you tell me which application you try to control, I could see if controlSend could be used....
Oh b.t.w. I did not know you used XP, the enable shortcut instructions were for Windows 7.
Shouldn't Mousemove be MouseMove instead? It's like that in the docs.
This AutoHotkey script, including a user-created AutoHotkey function should do what you require.
It automates right-clicking a program, and then selecting 3 items on subsequent menus.
The script has been written to work on Media Player Classic,
but certain lines just need to be edited to make it work for your program, TypeTool 3. You specify a comma-separated list with one or more items, i.e. the name of the item to choose in the first menu, and in the second menu item etc.
The vast majority of programs use standard context menus,
so it should work on your program; this is in contrast
to menu bars and other types of controls/resources that vary more between programs.
-
;note: requires Acc.ahk library in AutoHotkey\Lib folder
;https://github.com/Drugoy/Autohotkey-scripts-.ahk/blob/master/Libraries/Acc.ahk
;on right of screen right-click Raw, Save target as...
;the currently assigned hotkey is ctrl+q
;e.g. Media Player Classic, open right-click menu, click items
#IfWinActive, ahk_class MediaPlayerClassicW
^q::
WinGet, hWnd, ID, A
WinGetClass, vWinClass, ahk_id %hWnd%
if vWinClass not in MediaPlayerClassicW
Return
CoordMode, Mouse, Screen
MouseGetPos, vPosX2, vPosY2
WinGetPos, vPosX, vPosY, vPosW, vPosH, ahk_id %hWnd%
vPosX := Round(vPosX + vPosW/2)
vPosY := Round(vPosY + vPosH/2)
MouseMove, %vPosX%, %vPosY%
vList = View,On Top,Default
MenuRCSelectItem(vList)
MouseMove, %vPosX2%, %vPosY2%
Return
#IfWinActive
;===============
MenuRCSelectItem(vList, vDelim=",", vPosX="", vPosY="", vDelay=0)
{
DetectHiddenWindows, Off
CoordMode, Mouse, Screen
MouseGetPos, vPosX2, vPosY2
(vPosX = "") ? (vPosX := vPosX2)
(vPosY = "") ? (vPosY := vPosY2)
if !(vPosX = vPosX2) OR !(vPosY = vPosY2)
MouseMove, %vPosX%, %vPosY%
Click right
Loop, Parse, vList, %vDelim%
{
vTemp := A_LoopField
WinGet, hWnd, ID, ahk_class #32768
if !hWnd
{
MsgBox error
Return
}
oAcc := Acc_Get("Object", "1", 0, "ahk_id " hWnd)
Loop, % oAcc.accChildCount
if (Acc_Role(oAcc, A_Index) = "menu item")
if (oAcc.accName(A_Index) = vTemp)
if (1, oRect := Acc_Location(oAcc, A_Index), vIndex := A_Index)
break
vPosX := Round(oRect.x + oRect.w/2)
vPosY := Round(oRect.y + oRect.h/2)
MouseMove, %vPosX%, %vPosY%
Sleep %vDelay% ;optional delay
oAcc.accDoDefaultAction(vIndex)
WinWaitNotActive, ahk_id %hWnd%, , 6
if ErrorLevel
{
MsgBox error
Return
}
}
MouseMove, %vPosX2%, %vPosY2%
Return
}
;==================================================