Run code only when mouse moves over GUI

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
User avatar
Scoox
Posts: 125
Joined: 11 May 2014, 09:12
Location: China

Run code only when mouse moves over GUI

21 Oct 2014, 05:56

I am working on a GUI and I want a function to be called whenever the mouse moves over the GUI.

I've tried the following code, but the function MouseMove() is invoked even when the mouse is not moving. Is it possible to achieve this using OnMessage()? Thanks

Code: Select all

#NoEnv
#SingleInstance Force

Critical

OnMessage(0x200, "MouseMove")
Gui, Show, w300 h300
Return

MouseMove()
{
	ToolTip %A_TickCount%
}

GuiClose:
	ExitApp
User avatar
Blackholyman
Posts: 1293
Joined: 29 Sep 2013, 22:57
Location: Denmark
Contact:

Re: Run code only when mouse moves over GUI

21 Oct 2014, 07:23

your script does just about what you say you need.

here i've put in a coords check for the tooltip to desplay

Code: Select all

#NoEnv
#SingleInstance Force

Critical

OnMessage(0x200, "onMouseMove")
Gui, Show, w300 h300
Return


GuiClose:
    ExitApp
    
    
onMouseMove(wParam, lParam, msg, hwnd) {
	static
    x := lParam & 0xFFFF
    y := lParam >> 16
    if (x!=x2 and y!=y2) {
        ToolTip %A_TickCount%
        SetTimer, tipOff, -500
        x2 := x , y2 := y
	}
    return
    
    tipOff:
        ToolTip
    return
}
Hope it helps
Also check out:
Courses on AutoHotkey

My Autohotkey Blog
:dance:
User avatar
Scoox
Posts: 125
Joined: 11 May 2014, 09:12
Location: China

Re: Run code only when mouse moves over GUI

21 Oct 2014, 07:44

Blackholyman wrote:your script does just about what you say you need.

here i've put in a coords check for the tooltip to desplay

Code: Select all

#NoEnv
#SingleInstance Force

Critical

OnMessage(0x200, "onMouseMove")
Gui, Show, w300 h300
Return


GuiClose:
    ExitApp
    
    
onMouseMove(wParam, lParam, msg, hwnd) {
	static
    x := lParam & 0xFFFF
    y := lParam >> 16
    if (x!=x2 and y!=y2) {
        ToolTip %A_TickCount%
        SetTimer, tipOff, -500
        x2 := x , y2 := y
	}
    return
    
    tipOff:
        ToolTip
    return
}
Hope it helps
Thank you, your code produces the desired visual effect, but the function onMouseMove() is still being called when the mouse is not moving, which seems kind of wasteful. I was hoping there was a way for the function to be called at all only if and when the mouse moves.
lexikos
Posts: 9592
Joined: 30 Sep 2013, 04:07
Contact:

Re: Run code only when mouse moves over GUI

21 Oct 2014, 19:32

The function is called whenever a WM_MOUSEMOVE message is received. WM_MOUSEMOVE is only sent to the window when the mouse moves, hence the name.

Your original code does not update the tick count while the mouse is stationary on my system. If it does on your system, I'd guess that some other software or hardware (touch screen or tablet?) is interfering.
User avatar
Scoox
Posts: 125
Joined: 11 May 2014, 09:12
Location: China

Re: Run code only when mouse moves over GUI

21 Oct 2014, 19:41

lexikos wrote:The function is called whenever a WM_MOUSEMOVE message is received. WM_MOUSEMOVE is only sent to the window when the mouse moves, hence the name.

Your original code does not update the tick count while the mouse is stationary on my system. If it does on your system, I'd guess that some other software or hardware (touch screen or tablet?) is interfering.
Thanks Lexikos! I was thinking along those lines just now. I physically unplugged the mouse and it still happens so I guess I am just going to have to do a little more digging.
User avatar
Scoox
Posts: 125
Joined: 11 May 2014, 09:12
Location: China

Re: Run code only when mouse moves over GUI

21 Oct 2014, 20:43

Just tested on another machine with a fresh OS install (no drivers installed/updated yet) and I am getting the same. Lexikos, have you guys tested the code in the first post?

I've seen other reports of this problem elsewhere:

http://stackoverflow.com/questions/1363 ... -mousemove
http://blogs.msdn.com/b/oldnewthing/arc ... 63416.aspx
http://stackoverflow.com/questions/1986 ... g-in-d2010

Interestingly, if I remove Critical from the code, the tooltip gets updated about once per second only (instead of being updated as often as possible), and it also gets updated as soon as the mouse moves. Still, not ideal.
lexikos
Posts: 9592
Joined: 30 Sep 2013, 04:07
Contact:

Re: Run code only when mouse moves over GUI

21 Oct 2014, 23:24

I wrote:Your original code does not update the tick count while the mouse is stationary on my system.
This was on Windows XP.

I ran the script on Windows 7, and got the following results:
  • If I run the script as is, I get a rapid stream of mouse move messages.
  • If I remove Critical, I get messages only when the mouse moves.
  • If I remove ToolTip and use some other method of displaying the tick count, I get messages only when the mouse moves. Critical can be on or off.
There are comments in the source code indicating that showing a ToolTip window interferes with double click timing:

Code: Select all

		// Don't call GetCursorPos() unless absolutely needed because it seems to mess
		// up double-click timing, at least on XP.  UPDATE: Is isn't GetCursorPos() that's
		// interfering with double clicks, so it seems it must be the displaying of the ToolTip
		// window itself.
Furthermore,
ControlGetFocus wrote:If ControlGetFocus is executed repeatedly at a high frequency (i.e. every 500 ms or faster), it will probably disrupt the user's ability to double-click.
A_CaretX / A_CaretY wrote:If the contents of these variables are fetched repeatedly at a high frequency (i.e. every 500 ms or faster), the user's ability to double-click will probably be disrupted. There is no known workaround.
What do they have in common? ControlGetFocus and A_CaretX both call AttachThreadInput. Calling ControlGetFocus also causes another WM_MOUSEMOVE message to be sent, even though the mouse hasn't moved. Calling ControlGetFocus from some other script has the same effect if it is targetting this script's GUI. Therefore, I assume that the ToolTip control internally uses AttachThreadInput or does something else which resets the thread's input state, thereby causing another WM_MOUSEMOVE message to be sent.
User avatar
Scoox
Posts: 125
Joined: 11 May 2014, 09:12
Location: China

Re: Run code only when mouse moves over GUI

22 Oct 2014, 00:15

Nice! I have just replaced the tooltip with a Text control to display A_TickCount and it works as expected, which is great because I don't really need the tooltip in my final script.

EDIT: The problem came back again but the code hadn't changed, so I figured the WM_MOUSEMOVE must be being sent by another application. I started closing programs one at a time and the problem stopped as soon as I closed Media Player Classic Home Cinema. When playback stops (MPC still running) the problem also goes away. I'll contact the MPC developers about it.

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: No registered users and 350 guests