Display ripple effect when mouse click

Post your working scripts, libraries and tools for AHK v1.1 and older
User avatar
mright
Posts: 3
Joined: 20 Jul 2015, 10:44

Display ripple effect when mouse click

20 Jul 2015, 22:02

This script can show a little ripple effect when you left/right click the mouse button.
When the mouse is idle for five seconds or you press left control key, display the ripple to indicate the location of the cursor.

Code: Select all

#NoEnv
CoordMode Mouse, Screen
Setup()

~LButton::ShowRipple(LeftClickRippleColor)
~RButton::ShowRipple(RightClickRippleColor)
~LControl Up::ShowRipple(MouseIdleRippleColor)

Setup()
{
    Global
    RippleWinSize := 200
    RippleStep := 10
    RippleMinSize := 10
    RippleMaxSize := RippleWinSize - 20
    RippleAlphaMax := 0x60
    RippleAlphaStep := RippleAlphaMax // ((RippleMaxSize - RippleMinSize) / RippleStep)
    RippleVisible := False
    LeftClickRippleColor := 0xff0000
    RightClickRippleColor := 0x0000ff
    MouseIdleRippleColor := 0x008000
    
    DllCall("LoadLibrary", Str, "gdiplus.dll")
    VarSetCapacity(buf, 16, 0)
    NumPut(1, buf)
    DllCall("gdiplus\GdiplusStartup", UIntP, pToken, UInt, &buf, UInt, 0)
    
    Gui Ripple: -Caption +LastFound +AlwaysOnTop +ToolWindow +Owner +E0x80000
    Gui Ripple: Show, NA, RippleWin
    hRippleWin := WinExist("RippleWin")
    hRippleDC := DllCall("GetDC", UInt, 0)
    VarSetCapacity(buf, 40, 0)
    NumPut(40, buf, 0)
    NumPut(RippleWinSize, buf, 4)
    NumPut(RippleWinSize, buf, 8)
    NumPut(1, buf, 12, "ushort")
    NumPut(32, buf, 14, "ushort")
    NumPut(0, buf, 16)
    hRippleBmp := DllCall("CreateDIBSection", UInt, hRippleDC, UInt, &buf, UInt, 0, UIntP, ppvBits, UInt, 0, UInt, 0)
    DllCall("ReleaseDC", UInt, 0, UInt, hRippleDC)
    hRippleDC := DllCall("CreateCompatibleDC", UInt, 0)
    DllCall("SelectObject", UInt, hRippleDC, UInt, hRippleBmp)
    DllCall("gdiplus\GdipCreateFromHDC", UInt, hRippleDC, UIntP, pRippleGraphics)
    DllCall("gdiplus\GdipSetSmoothingMode", UInt, pRippleGraphics, Int, 4)
    
    MouseGetPos _lastX, _lastY
    SetTimer MouseIdleTimer, 5000
    Return

MouseIdleTimer:
    MouseGetPos _x, _y
    if (_x == _lastX and _y == _lastY)
        ShowRipple(MouseIdleRippleColor, _interval:=20)
    else
        _lastX := _x, _lastY := _y
    Return
}

ShowRipple(_color, _interval:=10)
{
    Global
    if (RippleVisible)
    	Return
    RippleColor := _color
    RippleDiameter := RippleMinSize
    RippleAlpha := RippleAlphaMax
    RippleVisible := True

    MouseGetPos _pointerX, _pointerY
    SetTimer RippleTimer, % _interval
    Return

RippleTimer:
    DllCall("gdiplus\GdipGraphicsClear", UInt, pRippleGraphics, Int, 0)
    if ((RippleDiameter += RippleStep) < RippleMaxSize) {
        DllCall("gdiplus\GdipCreatePen1", Int, ((RippleAlpha -= RippleAlphaStep) << 24) | RippleColor, float, 3, Int, 2, UIntP, pRipplePen)
        DllCall("gdiplus\GdipDrawEllipse", UInt, pRippleGraphics, UInt, pRipplePen, float, 1, float, 1, float, RippleDiameter - 1, float, RippleDiameter - 1)
        DllCall("gdiplus\GdipDeletePen", UInt, pRipplePen)
    }
    else {
        RippleVisible := False
        SetTimer RippleTimer, Off
    }

    VarSetCapacity(buf, 8)
    NumPut(_pointerX - RippleDiameter // 2, buf, 0)
    NumPut(_pointerY - RippleDiameter // 2, buf, 4)
    DllCall("UpdateLayeredWindow", UInt, hRippleWin, UInt, 0, UInt, &buf, Int64p, (RippleDiameter + 5) | (RippleDiameter + 5) << 32, UInt, hRippleDC, Int64p, 0, UInt, 0, UIntP, 0x1FF0000, UInt, 2)
    Return
}
Last edited by mright on 24 Jul 2015, 23:17, edited 1 time in total.
User avatar
mright
Posts: 3
Joined: 20 Jul 2015, 10:44

Re: Display ripple effect when mouse click

20 Jul 2015, 22:34

And by the way, I would like to report a strange behavior:
When I was refactoring the previous code, I found that if I rename the variable name "buf" to "temp", then the DllCall("GdiplusStartup"...) function returns an error code 2, which means invalid parameter, this happend to the DllCall("CreateDIBSection",...) call too, but except the name "temp", any other variable name will be ok, is this by design or something?
User avatar
noname
Posts: 515
Joined: 19 Nov 2013, 09:15

Re: Display ripple effect when mouse click

21 Jul 2015, 03:07

nice effect :) !

I had the same with "path" variable name the solution is to add #NoEnv at the beginning of your code.
User avatar
mright
Posts: 3
Joined: 20 Jul 2015, 10:44

Re: Display ripple effect when mouse click

21 Jul 2015, 03:42

lain wrote:nice effect :) !

I had the same with "path" variable name the solution is to add #NoEnv at the beginning of your code.
Thank you very much! I never thought that environment variables would affect script code.
User avatar
jNizM
Posts: 3183
Joined: 30 Sep 2013, 01:33
Contact:

Re: Display ripple effect when mouse click

21 Jul 2015, 03:43

But there is a problem with multi-monitor...
[AHK] v2.0.5 | [WIN] 11 Pro (Version 22H2) | [GitHub] Profile
User avatar
Relayer
Posts: 160
Joined: 30 Sep 2013, 13:09
Location: Delaware, USA

Re: Display ripple effect when mouse click

21 Jul 2015, 08:23

This submission packs some of the nuts and bolts in a dll. I believe it is similar but I have not run yours yet.

http://ahkscript.org/boards/viewtopic.p ... trl#p16261

Relayer
User avatar
gwarble
Posts: 524
Joined: 30 Sep 2013, 15:01

Re: Display ripple effect when mouse click

24 Jul 2015, 12:26

cool effect... i think you need "coordmode, mouse, screen" or something because it only positions correctly on a full screen window... on a smaller window it "ripples" in the position from the screen top left corner relative to the windows top left corner if that makes sense... that could also be the multi monitor problem
Last edited by gwarble on 24 Jul 2015, 12:59, edited 1 time in total.
EitherMouse - Multiple mice, individual settings . . . . www.EitherMouse.com . . . . forum . . . .
sobuj53
Posts: 55
Joined: 19 Mar 2015, 16:08

Re: Display ripple effect when mouse click

24 Jul 2015, 12:47

Really cool effect but I'm having some issue like, in Notepad window the ripple effect doesn't correctly shows the mouse ripple effect it also happens in any autohokey generated GUI window. In those instance the mouse ripple happens in different position than actual mouse pointer position. But thanks for your great work :)
User avatar
boiler
Posts: 16709
Joined: 21 Dec 2014, 02:44

Re: Display ripple effect when mouse click

24 Jul 2015, 22:43

Yes, adding CoordMode, Mouse, Screen as the first line of the script solves the multiple monitor and the other issues for me. Neat script.
sobuj53
Posts: 55
Joined: 19 Mar 2015, 16:08

Re: Display ripple effect when mouse click

25 Jul 2015, 01:17

Thank you very much, that solves everything :bravo:
SashaChernykh
Posts: 32
Joined: 01 Sep 2016, 04:04
Contact:

Re: Display ripple effect when mouse click

17 Sep 2016, 00:18

I'm sorry, that possible separate effect, when I make double-click left mouse button?

Thanks.
robodesign
Posts: 932
Joined: 30 Sep 2017, 03:59
Location: Romania
Contact:

Re: Display ripple effect when mouse click

15 Oct 2017, 14:30

very nice.... how to make the liner thicker? [never mind; found it]

How to reverse the animation? I would like it reversed for right-click.
-------------------------
KeyPress OSD v4: GitHub or forum. (presentation video)
Quick Picto Viewer: GitHub or forum.
AHK GDI+ expanded / compilation library (on GitHub)
My home page.
User avatar
Drugwash
Posts: 850
Joined: 29 May 2014, 21:07
Location: Ploieşti, Romania
Contact:

Re: Display ripple effect when mouse click

18 Oct 2017, 03:53

Here you are, Marius. I've added the ability to modify the idle timer and the pen width besides reverse animation switch:

Code: Select all

; by mright at  https://autohotkey.com/boards/viewtopic.php?f=6&t=8963&p=176651#p176651
; modded by Drugwash 2017.10.18 for reverse animation, variable idle timer, variable pen width
#NoEnv
#SingleInstance Force
#KeyHistory 0
ListLines Off
SetBatchLines, -1
SetKeyDelay, -1, -1
SetMouseDelay, -1
SetWinDelay, -1
SetControlDelay, -1
CoordMode Mouse, Screen
Setup()

~LButton::ShowRipple(LeftClickRippleColor)
~RButton::ShowRipple(RightClickRippleColor,, 1)
~LControl Up::ShowRipple(MouseIdleRippleColor)

Setup()
{
    Global
    RippleWinSize := 200
    RippleStep := 10
    RippleMinSize := 10
    RippleMaxSize := RippleWinSize - 20
    RippleAlphaMax := 0x60
    RippleAlphaStep := RippleAlphaMax // ((RippleMaxSize - RippleMinSize) / RippleStep)
    RippleVisible := False
    LeftClickRippleColor := 0xff0000
    RightClickRippleColor := 0x0000ff
    MouseIdleRippleColor := 0x008000
    MouseIdleTimer := 5000
    PenWidth := 3
    Rev := 0
    
    DllCall("LoadLibrary", Str, "gdiplus.dll")
    VarSetCapacity(buf, 16, 0)
    NumPut(1, buf)
    DllCall("gdiplus\GdiplusStartup", UIntP, pToken, UInt, &buf, UInt, 0)
    
    Gui Ripple: -Caption +LastFound +AlwaysOnTop +ToolWindow +Owner +E0x80000
    Gui Ripple: Show, NA, RippleWin
    hRippleWin := WinExist("RippleWin")
    hRippleDC := DllCall("GetDC", UInt, 0)
    VarSetCapacity(buf, 40, 0)
    NumPut(40, buf, 0)
    NumPut(RippleWinSize, buf, 4)
    NumPut(RippleWinSize, buf, 8)
    NumPut(1, buf, 12, "ushort")
    NumPut(32, buf, 14, "ushort")
    NumPut(0, buf, 16)
    hRippleBmp := DllCall("CreateDIBSection", UInt, hRippleDC, UInt, &buf, UInt, 0, UIntP, ppvBits, UInt, 0, UInt, 0)
    DllCall("ReleaseDC", UInt, 0, UInt, hRippleDC)
    hRippleDC := DllCall("CreateCompatibleDC", UInt, 0)
    DllCall("SelectObject", UInt, hRippleDC, UInt, hRippleBmp)
    DllCall("gdiplus\GdipCreateFromHDC", UInt, hRippleDC, UIntP, pRippleGraphics)
    DllCall("gdiplus\GdipSetSmoothingMode", UInt, pRippleGraphics, Int, 4)
    
    MouseGetPos _lastX, _lastY
    SetTimer MouseIdleTimer, %MouseIdleTimer%
    Return

MouseIdleTimer:
    MouseGetPos _x, _y
    if (_x == _lastX and _y == _lastY)
        ShowRipple(MouseIdleRippleColor, _interval:=20)
    else
        _lastX := _x, _lastY := _y
    Return
}

ShowRipple(_color, _interval:=10, _rs:=0)
{
    Global
    if (RippleVisible)
    	Return
    RippleColor := _color
    RippleDiameter := _rs ? RippleMaxSize : RippleMinSize
    RippleAlpha := RippleAlphaMax
    RippleVisible := True
    Rev := _rs

    MouseGetPos _pointerX, _pointerY
    SetTimer RippleTimer, % _interval
    Return

RippleTimer:
    DllCall("gdiplus\GdipGraphicsClear", UInt, pRippleGraphics, Int, 0)
    RippleDiameter := Rev ? RippleDiameter - RippleStep : RippleDiameter + RippleStep
    if (Rev && (RippleDiameter > RippleMinSize)) OR (!Rev && (RippleDiameter < RippleMaxSize)) {
        DllCall("gdiplus\GdipCreatePen1", Int, ((RippleAlpha -= RippleAlphaStep) << 24) | RippleColor, float, PenWidth, Int, 2, UIntP, pRipplePen)
        DllCall("gdiplus\GdipDrawEllipse", UInt, pRippleGraphics, UInt, pRipplePen, float, 1, float, 1, float, RippleDiameter - 1, float, RippleDiameter - 1)
        DllCall("gdiplus\GdipDeletePen", UInt, pRipplePen)
    }
    else {
        RippleVisible := False
        SetTimer RippleTimer, Off
    }

    VarSetCapacity(buf, 8)
    NumPut(_pointerX - RippleDiameter // 2, buf, 0)
    NumPut(_pointerY - RippleDiameter // 2, buf, 4)
    DllCall("UpdateLayeredWindow", UInt, hRippleWin, UInt, 0, UInt, &buf, Int64p, (RippleDiameter + 5) | (RippleDiameter + 5) << 32, UInt, hRippleDC, Int64p, 0, UInt, 0, UIntP, 0x1FF0000, UInt, 2)
    Return
}

Part of my AHK work can be found here.
robodesign
Posts: 932
Joined: 30 Sep 2017, 03:59
Location: Romania
Contact:

Re: Display ripple effect when mouse click

18 Oct 2017, 07:31

Thank you very much Drugwash.

The main problem is that I cannot integrate it into my script, at least I failed to do so...

KeyPress uses Hotkey command to bind to the mouse buttons and this one, labels. If I invoke ShowRipple() function from different threads, other than ~LButton, it does not work.

got any suggestions? I thought of implementing visual mouse clicks in another way, without this script, because of this.

Best regards, Marius
-------------------------
KeyPress OSD v4: GitHub or forum. (presentation video)
Quick Picto Viewer: GitHub or forum.
AHK GDI+ expanded / compilation library (on GitHub)
My home page.
User avatar
Drugwash
Posts: 850
Joined: 29 May 2014, 21:07
Location: Ploieşti, Romania
Contact:

Re: Display ripple effect when mouse click

18 Oct 2017, 12:21

I'll have to check that tomorrow, time allowing; right now I'm exhausted, been working in the garden all day.
In the mean time make sure you have

Code: Select all

CoordMode Mouse, Screen
Setup()
in the autoexec section of HotkeyOSD and nothing else interferes with that CoordMode and with any of the global variables declared in Setup(). Also make sure you call ShowRipple() with a valid color as first parameter and maybe call it on a timer right before exiting the hotkey command, like SetTimer, showRipple, -1 where showRipple is a label that actually calls ShowRipple().

Just noticed the script doesn't invoke GdiplusShutdown before exit.
Part of my AHK work can be found here.
User avatar
Reloaded
Posts: 283
Joined: 25 Aug 2017, 08:48

Re: Display ripple effect when mouse click

19 Oct 2017, 13:03

Pretty Cool ! :)
asenx
Posts: 3
Joined: 13 Sep 2021, 16:11

Re: Display ripple effect when mouse click

13 Sep 2021, 16:53

Drugwash wrote:
18 Oct 2017, 03:53
Here you are, Marius. I've added the ability to modify the idle timer and the pen width besides reverse animation switch:

Code: Select all

; by mright at  https://autohotkey.com/boards/viewtopic.php?f=6&t=8963&p=176651#p176651
; modded by Drugwash 2017.10.18 for reverse animation, variable idle timer, variable pen width
#NoEnv
#SingleInstance Force
#KeyHistory 0
ListLines Off
SetBatchLines, -1
SetKeyDelay, -1, -1
SetMouseDelay, -1
SetWinDelay, -1
SetControlDelay, -1
CoordMode Mouse, Screen
Setup()

~LButton::ShowRipple(LeftClickRippleColor)
~RButton::ShowRipple(RightClickRippleColor,, 1)
~LControl Up::ShowRipple(MouseIdleRippleColor)

Setup()
{
    Global
    RippleWinSize := 200
    RippleStep := 10
    RippleMinSize := 10
    RippleMaxSize := RippleWinSize - 20
    RippleAlphaMax := 0x60
    RippleAlphaStep := RippleAlphaMax // ((RippleMaxSize - RippleMinSize) / RippleStep)
    RippleVisible := False
    LeftClickRippleColor := 0xff0000
    RightClickRippleColor := 0x0000ff
    MouseIdleRippleColor := 0x008000
    MouseIdleTimer := 5000
    PenWidth := 3
    Rev := 0
    
    DllCall("LoadLibrary", Str, "gdiplus.dll")
    VarSetCapacity(buf, 16, 0)
    NumPut(1, buf)
    DllCall("gdiplus\GdiplusStartup", UIntP, pToken, UInt, &buf, UInt, 0)
    
    Gui Ripple: -Caption +LastFound +AlwaysOnTop +ToolWindow +Owner +E0x80000
    Gui Ripple: Show, NA, RippleWin
    hRippleWin := WinExist("RippleWin")
    hRippleDC := DllCall("GetDC", UInt, 0)
    VarSetCapacity(buf, 40, 0)
    NumPut(40, buf, 0)
    NumPut(RippleWinSize, buf, 4)
    NumPut(RippleWinSize, buf, 8)
    NumPut(1, buf, 12, "ushort")
    NumPut(32, buf, 14, "ushort")
    NumPut(0, buf, 16)
    hRippleBmp := DllCall("CreateDIBSection", UInt, hRippleDC, UInt, &buf, UInt, 0, UIntP, ppvBits, UInt, 0, UInt, 0)
    DllCall("ReleaseDC", UInt, 0, UInt, hRippleDC)
    hRippleDC := DllCall("CreateCompatibleDC", UInt, 0)
    DllCall("SelectObject", UInt, hRippleDC, UInt, hRippleBmp)
    DllCall("gdiplus\GdipCreateFromHDC", UInt, hRippleDC, UIntP, pRippleGraphics)
    DllCall("gdiplus\GdipSetSmoothingMode", UInt, pRippleGraphics, Int, 4)
    
    MouseGetPos _lastX, _lastY
    SetTimer MouseIdleTimer, %MouseIdleTimer%
    Return

MouseIdleTimer:
    MouseGetPos _x, _y
    if (_x == _lastX and _y == _lastY)
        ShowRipple(MouseIdleRippleColor, _interval:=20)
    else
        _lastX := _x, _lastY := _y
    Return
}

ShowRipple(_color, _interval:=10, _rs:=0)
{
    Global
    if (RippleVisible)
    	Return
    RippleColor := _color
    RippleDiameter := _rs ? RippleMaxSize : RippleMinSize
    RippleAlpha := RippleAlphaMax
    RippleVisible := True
    Rev := _rs

    MouseGetPos _pointerX, _pointerY
    SetTimer RippleTimer, % _interval
    Return

RippleTimer:
    DllCall("gdiplus\GdipGraphicsClear", UInt, pRippleGraphics, Int, 0)
    RippleDiameter := Rev ? RippleDiameter - RippleStep : RippleDiameter + RippleStep
    if (Rev && (RippleDiameter > RippleMinSize)) OR (!Rev && (RippleDiameter < RippleMaxSize)) {
        DllCall("gdiplus\GdipCreatePen1", Int, ((RippleAlpha -= RippleAlphaStep) << 24) | RippleColor, float, PenWidth, Int, 2, UIntP, pRipplePen)
        DllCall("gdiplus\GdipDrawEllipse", UInt, pRippleGraphics, UInt, pRipplePen, float, 1, float, 1, float, RippleDiameter - 1, float, RippleDiameter - 1)
        DllCall("gdiplus\GdipDeletePen", UInt, pRipplePen)
    }
    else {
        RippleVisible := False
        SetTimer RippleTimer, Off
    }

    VarSetCapacity(buf, 8)
    NumPut(_pointerX - RippleDiameter // 2, buf, 0)
    NumPut(_pointerY - RippleDiameter // 2, buf, 4)
    DllCall("UpdateLayeredWindow", UInt, hRippleWin, UInt, 0, UInt, &buf, Int64p, (RippleDiameter + 5) | (RippleDiameter + 5) << 32, UInt, hRippleDC, Int64p, 0, UInt, 0, UIntP, 0x1FF0000, UInt, 2)
    Return
}

Do you know why your script spontaneously draws circles even without a mouse click?
asenx
Posts: 3
Joined: 13 Sep 2021, 16:11

Re: Display ripple effect when mouse click

13 Sep 2021, 16:59

@Drugwash Also, if you double-click, the script can't interrupt the animation of the first click and start the second one.
sofista
Posts: 644
Joined: 24 Feb 2020, 13:59
Location: Buenos Aires

Re: Display ripple effect when mouse click

13 Sep 2021, 17:56

asenx wrote:
13 Sep 2021, 16:53
Do you know why your script spontaneously draws circles even without a mouse click?
From the first post of this same thread: "When the mouse is idle for five seconds or you press left control key, display the ripple to indicate the location of the cursor."
User avatar
Drugwash
Posts: 850
Joined: 29 May 2014, 21:07
Location: Ploieşti, Romania
Contact:

Re: Display ripple effect when mouse click

14 Sep 2021, 03:21

asenx wrote:
13 Sep 2021, 16:59
@Drugwash Also, if you double-click, the script can't interrupt the animation of the first click and start the second one.
My apologies, it's been a long time since last working on this. I believe a better version has been implemented in @robodesign's Keypress OSD.

On a related note, in Linux under Wine after latest updates this script behaves much worse than before - not that it ever worked correctly anyway - so it would be quite hard if not impossible for me to try and fix this script now. :(
asenx wrote:
13 Sep 2021, 16:53
Do you know why your script spontaneously draws circles even without a mouse click?
As @sofista mentioned above there is an idle timer that kicks in. If you don't want that you can simply comment out this line:
SetTimer MouseIdleTimer, %MouseIdleTimer%
Part of my AHK work can be found here.

Return to “Scripts and Functions (v1)”

Who is online

Users browsing this forum: No registered users and 75 guests