MouseGestureL

Post your working scripts, libraries and tools for AHK v1.1 and older
User avatar
Pyonkichi
Posts: 107
Joined: 16 May 2017, 20:40
Contact:

MouseGestureL

Post by Pyonkichi » 17 May 2017, 04:28

Image MouseGestureL.ahk - general-purpose mouse gesture script

You can assign AHK scripts to the mouse gestures.
Image

Five types of gesture hints are implemented.
Image

Download:
 
Website:    
Settings for use in a multi-monitor environment:
Since AutoHotkey does not support Per-Monitor DPI, the problems related to cursor coordinates occur on a monitor with a different display scale than the primary monitor in a multi-monitor environment.
To avoid this, you need to change the high DPI setting for AutoHotkey as follows.
  1. Show properties of the AutoHotkey.exe (or MouseGestureL.exe) in Windows Explorer.
  2. Select "Compatibility" tab and click the "Change high DPI settings" button.
  3. Check "Override high DPI scaling behavior".
  4. Select "Application" in the "Scaling performed by:" dropdown list. (It's selected by default.)
  5. Click OK to close the properties.
The gesture function on the sub-monitor will perform properly with above settings, however when the dialog box such as the setting screen is moved to the sub-monitor, the window size is not adjusted automatically according to the display scale.
This setting also affects scripts created for AutoHotkey other than MouseGestureL, so make a decision whether to change this settings in consideration of your own usage situation.
Last edited by Pyonkichi on 22 Jun 2022, 06:54, edited 44 times in total.

User avatar
evilC
Posts: 4822
Joined: 27 Feb 2014, 12:30

Re: MouseGestureL

Post by evilC » 17 May 2017, 07:06

I already have AHK installed (AHK_H actually, but should not matter?) so I just run MouseGestureL.ahk
The GUI appears, but no gestures seem to do anything.

If I hold right mouse, move mouse left and release while in a browser or file explorer, it should go back?

Also, if I right-click the tray icon and select Exit, then the tray icon disappears, but the app is still running.

GEV
Posts: 1002
Joined: 25 Feb 2014, 00:50

Re: MouseGestureL

Post by GEV » 19 Jun 2019, 18:13

Awesome script with a lot of very usefull functions.
I'm using this simplified version in my main script:

To test my version, run this script

MAIN SCRIPT.ahk

Code: Select all

#NoEnv
#SingleInstance Force
SetWorkingDir %A_ScriptDir%
; ...
#Include %A_ScriptDir%\MG_Config.ahk
; ...

				RETURN	 ; === end of auto-execute section ===

MG_End:
#NoEnv

; ...

#Include %A_ScriptDir%\RButton.ahk
#Include %A_ScriptDir%\XButton1.ahk

; ...

#Include %A_ScriptDir%\MouseGestureL_FUNCTIONS.ahk
after putting the following files in the same directory:

INCLUDED SCRIPTS:

For some reason the whole code does not fit in one answer, so I added the included files in the next one.
Last edited by GEV on 20 Jun 2019, 01:11, edited 2 times in total.

GEV
Posts: 1002
Joined: 25 Feb 2014, 00:50

Re: MouseGestureL

Post by GEV » 19 Jun 2019, 18:15

MG_Config.ahk

Code: Select all

; MG_Config

MG_AdNaviBG=000000
MG_AdNaviFG=FFFFFF
MG_AdNaviFont=Meiryo
MG_AdNaviMargin=14
MG_AdNaviNI=7F7F7F
MG_AdNaviPaddingB=3
MG_AdNaviPaddingL=6
MG_AdNaviPaddingR=6
MG_AdNaviPaddingT=3
MG_AdNaviSize=12
MG_ExNaviBG=FFFFFF
MG_ExNaviFG=000000
MG_ExNaviMargin=8
MG_ExNaviPadding=4
MG_ExNaviSize=24
MG_ExNaviSpacing=2
MG_Interval=20
MG_LongThreshold=700
MG_MaxLength=7
MG_NaviEnabled := 1
MG_NaviInterval=10
MG_NaviPersist=0
MG_ORangeA=3
MG_ORangeB=3
MG_ORangeDefault=3
MG_Threshold=60
MG_Timeout=1000
MG_TimeoutThreshold=12

MG_IsDisable(){
	global
	return (0)
}

MG_IsTarget1(){
	global
	return ((MG_Exe="iexplore.exe") || (MG_Exe="chrome.exe") || (MG_Exe="firefox.exe"))
}

MG_IsTarget2(){
	global
	return ((MG_WClass="CabinetWClass") || (MG_WClass="ExploreWClass") || (MG_WClass="Progman") || (MG_WClass="WorkerW"))
}

MG_IsTarget3(){
	global
	return (MG_WClass="DV2ControlHost") || (MG_WClass="Shell_TrayWnd") || (MG_WClass="TaskListThuXB1nailWnd") || (MG_WClass="BaseBar") || (MG_WClass="FreeLaunchBarMenu") ||  (MG_WClass="FreeLaunchBarWindow1") || (MG_WClass="#32768") || (MG_WClass="#32770") || (MG_WClass="#43") || (MG_WClass="OwnerDrawnMenuMsgWin") || (MG_WClass="Windows.UI.Core.CoreWindow") || (MG_WClass="TTargetDlg") || (MG_WClass="InputIndicatorButton1") || (MG_WClass="TrayButton2") || (MG_WClass="SB3D_MainWindow") || (MG_WClass="MSTaskListWClass1") || (MG_WClass="ToolbarWindow321") || (MG_WClass="ToolbarWindow322") || (MG_WClass="ToolbarWindow323") || (MG_WClass="ToolbarWindow324") || (MG_WClass="ToolbarWindow327") || (MG_WClass="ToolbarWindow329") || (MG_WClass="ToolbarWindow3210") || (MG_WClass="ToolbarWindow3211") || (MG_WClass="ToolbarWindow3212") || (MG_WClass="ReBarWindow321") || (MG_WClass="SysPager1") || (MG_WClass="wxGLCanvasClass1") || (MG_WClass="wxWindowClassNR") || (MG_CClass="MultitaskingViewFrame") || (MG_WClass="N/A") || (MG_WClass="") || (MG_IsTarget2() && ((MG_TreeListHitTest())))	
}

MG_IsTarget4(){
	global
	return (MG_WClass="DV2ControlHost") || (MG_WClass="Shell_TrayWnd") || (MG_WClass="TaskListThuXB1nailWnd") || (MG_WClass="BaseBar") || (MG_WClass="FreeLaunchBarMenu") ||  (MG_WClass="FreeLaunchBarWindow1") || (MG_WClass="#32768") || (MG_WClass="#32770") || (MG_WClass="#43") || (MG_WClass="OwnerDrawnMenuMsgWin") || (MG_WClass="Windows.UI.Core.CoreWindow") || (MG_WClass="TTargetDlg") || (MG_WClass="InputIndicatorButton1") || (MG_WClass="TrayButton2") || (MG_WClass="SB3D_MainWindow") || (MG_WClass="MSTaskListWClass1") || (MG_WClass="ToolbarWindow321") || (MG_WClass="ToolbarWindow322") || (MG_WClass="ToolbarWindow323") || (MG_WClass="ToolbarWindow324") || (MG_WClass="ToolbarWindow327") || (MG_WClass="ToolbarWindow329") || (MG_WClass="ToolbarWindow3210") || (MG_WClass="ToolbarWindow3211") || (MG_WClass="ToolbarWindow3212") || (MG_WClass="ReBarWindow321") || (MG_WClass="SysPager1") || (MG_WClass="wxGLCanvasClass1") || (MG_WClass="wxWindowClassNR") || (MG_CClass="MultitaskingViewFrame") || (MG_WClass="N/A") || (MG_WClass="")	
}
;...............................................................................
; Initialization Process
;...............................................................................

MG_IsDisableObj := Func("MG_IsDisable")
;...............................................................................
; Initialize global variables
MG_TriggerCount	= 0
MG_Active		= 0
MG_Executed		= 0
MG_TimedOut		= 0
MG_LastTime		= 0
MG_ORange		= 0.3926990817
MG_ORange1		= 0
MG_ORange2		= 0.2617993878
MG_ORange3		= 0.3926990817
MG_ORange4		= 0.5235987756
MG_ORange5		= 0.7854
MG_NaviPrst		= 0
;...............................................................................
; Initialize Hints	
MG_CreateExNavi()
;...............................................................................
; End of Initialization Process
if (A_ThisLabel = "MG_Init") {
	return
}
else {
	Goto,MG_End
}

RButton.ahk

Code: Select all

; GESTURES_RButton	
#Include %A_ScriptDir%\GESTURES_RButton.ahk

MG_RB_Down:
If !CloseContextMenu 
	MG_SendButton("RB", "RButton", "Down")
return

MG_RB_Up:
If !CloseContextMenu 
	MG_SendButton("RB", "RButton", "Up")
return

*RButton::
	MG_TriggerDown("RB")
return

*RButton Up::
	Gui, MGW_ExNavi:hide
	; ToolTip
	MG_TriggerUp("RB")
	MG_SendButton("RB", "RB", "Up")
	CloseContextMenu := false
return

#If (CloseContextMenu)

	~*RButton Up:: 
		MG_TriggerUp("RB")
		MG_Abort()
		Sleep, 20
		Send, {Alt Down}{Alt Up}	; Close ContextMenu
		CloseContextMenu := false
	return

#If

;******************
	RButton & XButton1::	;XXXX	
;******************
CloseContextMenu := true
NoXButton1 := true
Gui, MGW_ExNavi:hide
MG_Abort()
ToolTip RButton & XButton1
KeyWait, RButton
ToolTip
Gui, MGW_ExNavi:hide
MsgBox, RButton & XButton1
CloseContextMenu := false
NoXButton1 := false
return

;*****************
	RButton & LButton::	;XXXX	Close Active Window
;*****************
CloseContextMenu := true
Gui, MGW_ExNavi:hide
MG_Abort()
ToolTip, Close Active Window
; KeyWait, LButton
KeyWait, RButton
Send {Blind}{LButton Up}
ToolTip
Gui, MGW_ExNavi:hide
WinClose, A
CloseContextMenu := false
return

;*******************
	RButton & WheelUp::	;XXXX	UnDO
;*******************
CloseContextMenu := true
; If WinActive("ahk_group TextEditors")
; {
    Send, {Ctrl Down}{z}{Ctrl Up} 
	ToolTip, UnDO
	SetTimer, ToolTip_UnDO_ReDO, 50
; }
return


ToolTip_UnDO_ReDO:
	If !GetKeyState("RButton","P")
	{
		SetTimer, ToolTip_UnDO_ReDO, off
		ToolTip
	}
Return

;*********************
	RButton & WheelDown::	;XXXX	ReDO
;*********************
CloseContextMenu := true
; If WinActive("ahk_group TextEditors")
; { 
    Send, {Ctrl Down}{y}{Ctrl Up}
	ToolTip, ReDO
	SetTimer, ToolTip_UnDO_ReDO, 50
; } 
return 
XButton1.ahk

Code: Select all

; GESTURES_XButton1	
#Include %A_ScriptDir%\GESTURES_XButton1.ahk

MG_XB1_Down:
If !NoXButton1 
	MG_SendButton("XB1", "XButton1", "Down")
return

MG_XB1_Up:
If !NoXButton1 
	MG_SendButton("XB1", "XButton1", "Up")
return

XButton1::
	MG_TriggerDown("XB1")
return
 
XButton1 Up::
	Gui, MGW_ExNavi:hide
	MG_TriggerUp("XB1")
	MG_SendButton("XB1", "XB1", "Up")
	NoXButton1 := false
return

#If (NoXButton1)

	~*XButton1 Up:: 
		MG_TriggerUp("XB1")
		MG_Abort()			
	return

#If
 
  
;******************
	XButton1 & RButton::	;XXXX	
;******************
NoXButton1 := true
CloseContextMenu := true
Gui, MGW_ExNavi:hide
MG_Abort()
ToolTip XButton1 & RButton
KeyWait, XButton1
Sleep, 20
Send, {Alt Down}{Alt Up}	; Close ContextMenu
ToolTip
MsgBox, XButton1 & RButton
CloseContextMenu := false
NoXButton1 := false
return

;*****************
	XButton1 & LButton::	;XXXX	
;*****************
NoXButton1 := true
Gui, MGW_ExNavi:hide
ToolTip, XButton1 & LButton
; KeyWait, LButton
KeyWait, XButton1
ToolTip
Send {Blind}{LButton Up}
Gui, MGW_ExNavi:hide
MsgBox, XButton1 & LButton
NoXButton1 := false
return

;*******************
	XButton1 & WheelUp::	;XXXX	UnDO
;*******************
NoXButton1 := true
; If WinActive("ahk_group TextEditors")
; {
    Send, {Ctrl Down}{z}{Ctrl Up} 
	ToolTip, UnDO
	SetTimer, ToolTip_UnDO_ReDO, 50
; }
return

;*********************
	XButton1 & WheelDown::	;XXXX	ReDO
;*********************
NoXButton1 := true
; If (WinActive("ahk_group TextEditors") || WinActive("- Microsoft OneNote Online -"))
; { 
    Send, {Ctrl Down}{y}{Ctrl Up}
	ToolTip, ReDO
	SetTimer, ToolTip_UnDO_ReDO, 50
; } 
return 
GESTURES_RButton.ahk

Code: Select all

MG_Gesture_RB_:
	If (MG_IsTarget3()){
		CloseContextMenu := false
		MG_Abort()
	}
return

MG_GetAction_RB_:
	If (MG_IsTarget3()){
		MG_ActionStr := "Cancel Gesture"
	}
return


;###########
;* RButton_R:	;XXXX		
;###########
MG_Gesture_RB_6_:
	MsgBox, RButton_R	
return
MG_GetAction_RB_6_:
	MG_ActionStr := "RB_Gesture__R"
return

;###########
;* RButton_L:	;XXXX		
;###########
MG_Gesture_RB_4_:
	MsgBox, RButton_L
return
MG_GetAction_RB_4_:
	MG_ActionStr := "RB_Gesture__L"
return

;###########
;* RButton_U:	;XXXX		
;###########
MG_Gesture_RB_8_:
	MsgBox, RButton_U	
return
MG_GetAction_RB_8_:
	MG_ActionStr := "RB_Gesture__U"
return

;###########
;* RButton_D:	;XXXX		
;###########
MG_Gesture_RB_2_:
	MsgBox, RButton_D
return
MG_GetAction_RB_2_:
	MG_ActionStr := "RB_Gesture__D"
return

;###########
;* RButton_UR:	;XXXX	
;###########
MG_Gesture_RB_9_:
	MsgBox, RButton_UR
return
MG_GetAction_RB_9_:
	MG_ActionStr := "RB_Gesture__UR"
return

;###########
;* RButton_DL:	;XXXX	
;###########
MG_Gesture_RB_1_:
	MsgBox, RButton_R
return
MG_GetAction_RB_1_:
	MG_ActionStr := "RB_Gesture__R"
return

;###########
;* RButton_DR:	;XXXX	
;###########
MG_Gesture_RB_3_:	
	MsgBox, RButton_DR
return
MG_GetAction_RB_3_:
	MG_ActionStr := "RB_Gesture__DR"
return


;###########
;* RButton_UL:	;XXXX		
;###########
MG_Gesture_RB_7_:
	MsgBox, RButton_UL
return
MG_GetAction_RB_7_:
	MG_ActionStr := "RB_Gesture__UL"
return

; MG_Gesture_RB__L__R:
MG_Gesture_RB_46_:
	MsgBox, RB_Gesture__L__R
return
MG_GetAction_RB_46_:
	MG_ActionStr := "RB_Gesture__L__R"
return

; MG_Gesture_RB__R__L:
MG_Gesture_RB_64_:
	MsgBox, RB_Gesture__R__L:
return
MG_GetAction_RB_64_:
	MG_ActionStr := "RB_Gesture__R__L:"
return

; MG_Gesture_RB__U__D:
MG_Gesture_RB_82_:
	MsgBox, RB_Gesture__U__D
return
MG_GetAction_RB_82_:
	MG_ActionStr := "RB_Gesture__U__D"
return

; MG_Gesture_RB__D__U:
MG_Gesture_RB_28_:
	MsgBox, RB_Gesture__D__U
return
MG_GetAction_RB_28_:
	MG_ActionStr := "RB_Gesture__D__U"
return

; MG_Gesture_RB__DL__UR:
MG_Gesture_RB_19_:
	MsgBox, RB_Gesture__DL__UR
return
MG_GetAction_RB_19_:
	MG_ActionStr := "RB_Gesture__DL__UR"
return

; MG_Gesture_RB__UR__DL:
MG_Gesture_RB_91_:
	MsgBox, RB_Gesture__UR__DL
return
MG_GetAction_RB_91_:
	MG_ActionStr := "RB_Gesture__UR__DL"
return

; MG_Gesture_RB__UL__DR:
MG_Gesture_RB_73_:
	MsgBox, RB_Gesture_UL__DR
return
MG_GetAction_RB_73_:
	MG_ActionStr := "RB_Gesture_UL__DR"
return

; MG_Gesture_RB__DR__UL:
MG_Gesture_RB_37_:
	MsgBox, RB_Gesture_DR__UL
return
MG_GetAction_RB_37_:
	MG_ActionStr := "RB_Gesture_DR__UL"
return

; MG_Gesture_RB__DL__DR:
MG_Gesture_RB_13_:
	MsgBox, RB_Gesture__DL__DR
return
MG_GetAction_RB_13_:
	MG_ActionStr := "RB_Gesture__DL__DR"
return

; MG_Gesture_RB__DR__DL:
MG_Gesture_RB_31_:
	MsgBox, RB_Gesture__DR__DL
return
MG_GetAction_RB_31_:
	MG_ActionStr := "RB_Gesture__DR__DL"
return

; MG_Gesture_RB__UR__DR:
MG_Gesture_RB_93_:
	MsgBox, RB_Gesture__UR__DR
return
MG_GetAction_RB_93_:
	MG_ActionStr := "RB_Gesture__UR__DR"
return

; MG_Gesture_RB__DR__UR:
MG_Gesture_RB_39_:
	MsgBox, RB_Gesture__DR__UR
return
MG_GetAction_RB_39_:
	MG_ActionStr := "RB_Gesture__DR__UR"
return
GESTURES_XButton1.ahk

Code: Select all

MG_Gesture_XB1_:
	If (MG_IsTarget3()){
		MG_Abort()
	}
return

MG_GetAction_XB1_:
	If (MG_IsTarget3()){
		MG_ActionStr := "Cancel Gesture"
	}
return


;###########
;* XButton1_R:	;XXXX		
;###########
MG_Gesture_XB1_6_:
	XB1_Gesture__R	
return
MG_GetAction_XB1_6_:
	MG_ActionStr := "XB1_Gesture__R"
return

;###########
;* XButton1_L:	;XXXX		
;###########
MG_Gesture_XB1_4_:
	XB1_Gesture__L
return
MG_GetAction_XB1_4_:
	MG_ActionStr := "XB1_Gesture__L"
return

;###########
;* XButton1_U:	;XXXX		
;###########
MG_Gesture_XB1_8_:
	XB1_Gesture__U	
return
MG_GetAction_XB1_8_:
	MG_ActionStr := "XB1_Gesture__U"
return

;###########
;* XButton1_D:	;XXXX		
;###########
MG_Gesture_XB1_2_:
	XB1_Gesture__D
return
MG_GetAction_XB1_2_:
	MG_ActionStr := "XB1_Gesture__D"
return

;###########
;* XButton1_UR:	;XXXX	
;###########
MG_Gesture_XB1_9_:
	XB1_Gesture__UR
return
MG_GetAction_XB1_9_:
	MG_ActionStr := "XB1_Gesture__UR"
return

;###########
;* XButton1_DL:	;XXXX	
;###########
MG_Gesture_XB1_1_:
	XB1_Gesture__R
return
MG_GetAction_XB1_1_:
	MG_ActionStr := "XB1_Gesture__R"
return

;###########
;* XButton1_DR:	;XXXX	
;###########
MG_Gesture_XB1_3_:	
	XB1_Gesture__DR
return
MG_GetAction_XB1_3_:
	MG_ActionStr := "XB1_Gesture__DR"
return


;###########
;* XButton1_UL:	;XXXX		
;###########
MG_Gesture_XB1_7_:
	XB1_Gesture__UL
return
MG_GetAction_XB1_7_:
	MG_ActionStr := "XB1_Gesture__UL"
return

; MG_Gesture_XB1__L__R:
MG_Gesture_XB1_46_:
	MsgBox, XB1_Gesture__L__R
return
MG_GetAction_XB1_46_:
	MG_ActionStr := "XB1_Gesture__L__R"
return

; MG_Gesture_XB1__R__L:
MG_Gesture_XB1_64_:
	MsgBox, XB1_Gesture__R__L:
return
MG_GetAction_XB1_64_:
	MG_ActionStr := "XB1_Gesture__R__L:"
return

; MG_Gesture_XB1__U__D:
MG_Gesture_XB1_82_:
	MsgBox, XB1_Gesture__U__D
return
MG_GetAction_XB1_82_:
	MG_ActionStr := "XB1_Gesture__U__D"
return

; MG_Gesture_XB1__D__U:
MG_Gesture_XB1_28_:
	MsgBox, XB1_Gesture__D__U
return
MG_GetAction_XB1_28_:
	MG_ActionStr := "XB1_Gesture__D__U"
return

; MG_Gesture_XB1__DL__UR:
MG_Gesture_XB1_19_:
	MsgBox, XB1_Gesture__DL__UR
return
MG_GetAction_XB1_19_:
	MG_ActionStr := "XB1_Gesture__DL__UR"
return

; MG_Gesture_XB1__UR__DL:
MG_Gesture_XB1_91_:
	MsgBox, XB1_Gesture__UR__DL
return
MG_GetAction_XB1_91_:
	MG_ActionStr := "XB1_Gesture__UR__DL"
return

; MG_Gesture_XB1__UL__DR:
MG_Gesture_XB1_73_:
	MsgBox, XB1_Gesture_UL__DR
return
MG_GetAction_XB1_73_:
	MG_ActionStr := "XB1_Gesture_UL__DR"
return

; MG_Gesture_XB1__DR__UL:
MG_Gesture_XB1_37_:
	MsgBox, XB1_Gesture_DR__UL
return
MG_GetAction_XB1_37_:
	MG_ActionStr := "XB1_Gesture_DR__UL"
return

; MG_Gesture_XB1__DL__DR:
MG_Gesture_XB1_13_:
	MsgBox, XB1_Gesture__DL__DR
return
MG_GetAction_XB1_13_:
	MG_ActionStr := "XB1_Gesture__DL__DR"
return

; MG_Gesture_XB1__DR__DL:
MG_Gesture_XB1_31_:
	MsgBox, XB1_Gesture__DR__DL
return
MG_GetAction_XB1_31_:
	MG_ActionStr := "XB1_Gesture__DR__DL"
return

; MG_Gesture_XB1__UR__DR:
MG_Gesture_XB1_93_:
	MsgBox, XB1_Gesture__UR__DR
return
MG_GetAction_XB1_93_:
	MG_ActionStr := "XB1_Gesture__UR__DR"
return

; MG_Gesture_XB1__DR__UR:
MG_Gesture_XB1_39_:
	MsgBox, XB1_Gesture__DR__UR
return
MG_GetAction_XB1_39_:
	MG_ActionStr := "XB1_Gesture__DR__UR"
return
MouseGestureL_FUNCTIONS.ahk

Code: Select all


;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
;
;	Gesture Recognition
;
;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
;---------------------------------------------------------------
; Get cursor position and target information
;														Implemented by lukewarm
;														ModIfied by Pyonkichi
;---------------------------------------------------------------
MG_GetMousePosInfo()
{
	global
	MG_TickCount:=A_TickCount
	CoordMode,Mouse,Screen
	MouseGetPos, MG_X, MG_Y, MG_HWND, MG_HCTL, 3
	SendMessage,0x84,0,% MG_Y<<16|MG_X,,ahk_id %MG_HCTL%	; %
	If (ErrorLevel == 4294967295) {
		MouseGetPos,,,,MG_HCTL, 2
	}
	IfWinExist,ahk_id %MG_HWND%,,,,{
		WinGetClass, MG_WClass
		WinGet, MG_PID, PID
		WinGet, MG_Exe, ProcessName
		WinGetTitle, MG_Title
	}
	WinGetClass, MG_CClass, ahk_id %MG_HCTL%
	If (MG_CClass = "Button") {
		MG_CorrectDlgCtrlHandle()
	}
}

;---------------------------------------------------------------
; Correct target control handle in a dialog box
;														Implemented by Pyonkichi
;---------------------------------------------------------------
MG_CorrectDlgCtrlHandle()
{
	global MG_X, MG_Y, MG_HCTL, MG_WClass
	rc := DllCall("GlobalAlloc", "UInt",0x40, "UInt",16, "Ptr")
	hParent := DllCall("GetParent", "Ptr",MG_HCTL)
	hCtrl := MG_HCTL
	while (hCtrl)
	{
		hCtrl := DllCall("FindWindowEx", "Ptr",hParent, "Ptr",hCtrl, "Ptr",0, "Ptr",0, "Ptr")
		If (!hCtrl) {
			break
		}
		DllCall("GetWindowRect", "Ptr",hCtrl, "Ptr",rc)
		If (DllCall("PtInRect", "Ptr",rc, "Int64",MG_Y<<32|MG_X, "Ptr"))
		{
			WinGet, dwStyle, Style, ahk_id %hCtrl%
			If (dwStyle & 0x10000000) {
				MG_HCTL := hCtrl
			}
		}
	}
	WinGetClass, MG_CClass, ahk_id %MG_HCTL%
	DllCall("GlobalFree", "Ptr",rc)
}

;---------------------------------------------------------------
; Process trigger-down actions
;														Implemented by lukewarm
;														ModIfied by Pyonkichi
;---------------------------------------------------------------
MG_TriggerDown(name)
{
	global
	Critical
	If (!InStr(MG_CurTriggers,name . "_"))
	{
		MG_TriggerCount++
		MG_CurTriggers=%MG_CurTriggers%%name%_
		If (MG_Active && MG_TimedOut)
		{
			GoSub,MG_%name%_Down
		}
		else If (MG_TriggerCount==1)
		{
			; Begin to process gesture at first trigger-down
			If (A_TickCount>(MG_LastTime+MG_WaitNext))
			{
				MG_Gesture = %name%_
				MG_1stTrigger := MG_Gesture
			}
			else
			{
				MG_Gesture = %MG_Gesture%%name%_
			}
			MG_GetMousePosInfo()
			MG_NowX:=MG_PreX:=MG_TX:=MG_TL:=MG_TR:=MG_X
			MG_NowY:=MG_PreY:=MG_TY:=MG_TT:=MG_TB:=MG_Y
			MG_PrevTime	   := A_TickCount
			MG_PrevGesture := ""
			MG_NaviPrstStr := ""	
			If (MG_IsDisableObj.()) {
				GoSub,MG_%name%_Down
			}
			else {
				MG_StartNavi()
				MG_Aborted:=0
				MG_Check()
				If (MG_Aborted) {
					MG_StopNavi(0)
					GoSub,MG_%name%_Down
				} else {
					MG_Recognition(1)
				}
			}
		}
		else
		{
			; Otherwise execute gesture
			MG_Recognition()
			MG_Gesture=%MG_Gesture%%name%_
			MG_Check()
			MG_PreX:=MG_NowX, MG_PreY:=MG_NowY, MG_PrevTime:=A_TickCount
		}
	}
}

;---------------------------------------------------------------
; Process trigger-up actions
;														Implemented by lukewarm
;														ModIfied by Pyonkichi
;---------------------------------------------------------------
MG_TriggerUp(name)
{
	local px, py
	Critical
	If (!RegExMatch(MG_CurTriggers,"(?<=_|^)" . name . "_")) {
		return
	}
	If (!MG_Aborted) {
		MG_Recognition()
	}
	MG_TriggerCount	:= (MG_TriggerCount>0) ? (MG_TriggerCount-1) : 0
	MG_CurTriggers	:= RegExReplace(MG_CurTriggers,"(?<=_|^)" . name . "_")
	If (!MG_Active || MG_TimedOut)
	{
		GoSub, MG_%name%_Up		
	}
	else
	{
		MG_Gesture = %MG_Gesture%_
		If (!MG_Aborted) {
			MG_Check()
		}
		If (MG_TriggerCount < 1)
		{
			If (MG_NaviPrstStr)
			{
				MG_NaviPrst := 1
				SetTimer, MG_NaviPersistTimer, %MG_NaviPersist%
			}
			MG_StopNavi(0)
			If (!MG_Executed)
			{
				; Emulate trigger If gesture is not executed
				CoordMode,Mouse,Screen
				SetMouseDelay,-1
				; WinGetActiveTitle, WinTitle				
				; If (WinTitle != "") 	; TrayMenu
				BlockInput,On
				MouseGetPos,px,py
				MouseMove,%MG_X%,%MG_Y%,0
				GoSub,MG_%name%_Down
				MouseMove,%px%,%py%,0
				Sleep,1
				GoSub,MG_%name%_Up
				BlockInput,Off
			}
		}
	}	
}
;---------------------------------------------------------------
; Check gesture updates
;														Implemented by lukewarm
;														ModIfied by Pyonkichi
;---------------------------------------------------------------
MG_Check(g="")
{
	local ges,ex,tmp
	MG_LastTime:=A_TickCount
	If (StrLen(MG_Gesture)>MG_MaxLength)
	{
		; Gesture is too long
		MG_Gesture=%MG_CurTriggers%
	}
	else
	{
		If (g) {
			ges:=g
		} else {
			ges:=MG_Gesture
		}
		If (IsLabel("MG_Gesture_" . ges))
		{
			If (MG_NaviPersist > 0) {
				MG_NaviPrstStr := MG_Gesture
			}
			IfWinExist,ahk_id %MG_HWND%,,,,{
			}
			ex := MG_Executed++
			Gosub,MG_Gesture_%ges%
			If (ex != MG_Executed) {
				If (!g) {
					MG_Gesture := MG_CurTriggers
				}
				return 1
			}
			else {
				return (MG_WaitNext != 0)
			}
		}
	}
}

;---------------------------------------------------------------
; Recognition function
;	fInit : 1 = Initialize recognition process
;			0 = Recognition only
;														Implemented by lukewarm
;														ModIfied by Pyonkichi
;---------------------------------------------------------------
MG_Recognition(fInit=0)
{
	global
	static px, py, plx, ply, d1, d2, orange, next_timeout
	local powx, powy
	;...........................................................................
	; Initialization of recognition process
	If (fInit)
	{
		MG_Active:=1, MG_Aborted:=0, MG_WaitNext:=0, MG_Executed:=0, MG_TimedOut:=0
		px:=plx:=MG_X, py:=ply:=MG_Y, d1:="", d2:=""
		orange:=MG_ORange%MG_ORangeDefault%, next_timeout:=A_TickCount+MG_Timeout
		SetTimer, MG_RecogTimer, %MG_Interval%
	}
	;...........................................................................
	; Recognition process
	CoordMode,Mouse,Screen
	MouseGetPos,MG_NowX,MG_NowY
	If (MG_TriggerCount < 1)
	{
		; Release all triggers : ???????????
		SetTimer, MG_RecogTimer, Off
		MG_Active:=0,MG_TriggerCount:=0,MG_CurTriggers:=""
		MG_StopNavi(0)
	}
	else If ((MG_X-MG_NowX)**2+(MG_Y-MG_NowY)**2 < MG_TimeoutThreshold**2)
	{
		; Tiny movement : ?????
		next_timeout:=A_TickCount+MG_Timeout
	}
	else If (!MG_TimedOut
	&&		 (MG_Aborted || ((A_TickCount>next_timeout) && (MG_Executed==0))))
	{
		; Time out when moving : ??????????
		MG_StopNavi(0)
		Critical
		SetMouseDelay,-1
		MG_TimedOut=1
		BlockInput,On
		MouseMove,%MG_X%,%MG_Y%,0
		Loop,Parse,MG_CurTriggers,_
		{
			If (A_LoopField) {
				GoSub,MG_%A_LoopField%_Down
			}
		}
		MouseMove,%MG_NowX%,%MG_NowY%,0
		BlockInput,Off
		Critical,Off
	}
	else If (!MG_TimedOut && ((powx:=(MG_NowX-px)**2)+(powy:=(MG_NowY-py)**2) >= MG_Threshold**2))
	{
		; Check Normal Movement : ????
			If (orange > Abs(0.7853981634-Abs(ATan((MG_NowX-px)/(MG_NowY-py))))) {
				d2 := (MG_NowX>px) ? ((MG_NowY>py) ? 3 : 9) : ((MG_NowY>py) ? 1 : 7)
			} else {
				d2 := (powx>powy) ? ((MG_NowX>px) ? 6 : 4) : ((MG_NowY>py) ? 2 : 8)
			}
		; Judge Normal Movement
		local fChanged := 0
		If (d1 != d2) {
			fChanged := 1
		}
		else {
			; Check Long Movement
				fChanged := ((MG_NowX-plx)**2+(MG_NowY-ply)**2 >= MG_LongThreshold**2)
		}
		; Judge Overall Movement
		If (fChanged)
		{
			MG_Gesture=%MG_Gesture%%d2%
				If (d2 & 1) {
					orange := MG_ORange%MG_ORangeB%
				} else {
					orange := MG_ORange%MG_ORangeA%
				}
			plx:=px, ply:=py
			d1 := MG_Check() ? "" : d2
			;MG_PreX:=MG_NowX, MG_PreY:=MG_NowY, MG_PrevTime:=A_TickCount
		}
		MouseGetPos,px,py
		next_timeout:=A_TickCount+MG_Timeout
		MG_PreX:=px, MG_PreY:=py, MG_PrevTime:=A_TickCount
	}
}

MG_RecogTimer:
	MG_Recognition()
return

;---------------------------------------------------------------
; Emulate the mouse button events
;														Implemented by Pyonkichi
;---------------------------------------------------------------
MG_SendButton(name, btn, mode="")
{
	global
	SetMouseDelay,-1
	Send, % "{Blind}{" . btn . (mode ? " "mode : "") . "}"	; %
	; CoordMode, ToolTip, Screen
	; ToolTip, %name%`n%mode%, 1000, 0
}

;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
;
;	Script Control Functions
;
;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
;---------------------------------------------------------------
; Abort the gesture
;														Implemented by lukewarm
;---------------------------------------------------------------
MG_Abort()
{
	global
	MG_Aborted := 1
}

;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
;
;	Retrieving Information of the Target
;
;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=


;---------------------------------------------------------------
; Hittest the target ListView
;														Implemented by lukewarm
;---------------------------------------------------------------
MG_LvHitTest()
{
	global MG_PID, MG_CClass, MG_HCTL, MG_X, MG_Y
	If (MG_CClass="SysListView32" || MG_CClass="SysListView321" || MG_CClass="TListView")
	{
		pt := DllCall("GlobalAlloc", "UInt",0x40, "UInt",8, "Ptr")
		NumPut(MG_X, pt+0, 0, "Int")
		NumPut(MG_Y, pt+0, 4, "Int")
		DllCall("ScreenToClient", "Ptr",MG_HCTL, "Ptr",pt)
		hp := DllCall("OpenProcess", "UInt",0x001F0FFF, "UInt",0, "UInt",MG_PID, "Ptr")
		size := 8 + A_PtrSize*3
		pi := DllCall("VirtualAllocEx", "Ptr",hp, "Ptr",0, "UInt",size, "UInt",0x1000, "UInt",0x4, "Ptr")
		DllCall("WriteProcessMemory", "Ptr",hp, "Ptr",pi, "Ptr",pt, "Int",8, "Ptr",0)
		SendMessage, 0x1012, 0, %pi%,, ahk_id %MG_HCTL%
		DllCall("ReadProcessMemory", "Ptr",hp, "Ptr",pi+8, "PtrP",flag, "UInt",A_PtrSize, "Ptr",0)
		DllCall("VirtualFreeEx", "Ptr",hp, "Ptr",pi, "UInt",0, "UInt",0x8000)
		DllCall("CloseHandle", Ptr,hp)
		DllCall("GlobalFree", "Ptr",pt)
		flag := flag & 15
		return (flag<4) ? ((flag<2) ? 0 : "ItemIcon") : ((flag<8) ? "ItemLabel" : "ItemState")
	}
	return 0
}

;---------------------------------------------------------------
; Hittest the target TreeView
;														Implemented by lukewarm
;---------------------------------------------------------------
MG_TvHitTest()
{
	global MG_PID, MG_CClass, MG_HCTL, MG_X, MG_Y
	If (MG_CClass="SysTreeView32"|| MG_CClass="SysListView321" || MG_CClass="TTreeView" || MG_CClass="Shell_TrayWnd" || (MG_CClass="DV2ControlHost") || (MG_CClass="TaskListThuXB1nailWnd") || (MG_CClass="BaseBar") || (MG_CClass="FreeLaunchBarMenu")  || (MG_CClass="FreeLaunchBarWindow1") || (MG_CClass="#32768") || (MG_CClass="#32770") || (MG_CClass="#43") || (MG_CClass="OwnerDrawnMenuMsgWin") || (MG_CClass="Windows.UI.Core.CoreWindow") || (MG_CClass="TTaargetDlg") || (MG_CClass="InputIndicatorButton1")  || (MG_CClass="TrayButton2") ||  || (MG_CClass="SB3D_MainWindow")  || (MG_CClass="MSTaskListWClass1") || (MG_CClass="ToolbarWindow321") || (MG_CClass="ToolbarWindow322") || (MG_CClass="ToolbarWindow323") || (MG_CClass="ToolbarWindow324") || (MG_CClass="ToolbarWindow327") || (MG_CClass="ToolbarWindow329") || (MG_CClass="ToolbarWindow3210") || (MG_CClass="ToolbarWindow3211") || (MG_CClass="ToolbarWindow3212") || (MG_CClass="ReBarWindow321") || (MG_CClass="SysPager1") || (MG_CClass="wxGLCanvasClass1") || (MG_CClass="wxWindowClassNR") || (MG_CClass="MultitaskingViewFrame") || (MG_CClass="N/A") || (MG_CClass=""))
	
	{
		pt := DllCall("GlobalAlloc", "UInt",0x40, "UInt",8, "Ptr")
		NumPut(MG_X, pt+0, 0, "Int")
		NumPut(MG_Y, pt+0, 4, "Int")
		DllCall("ScreenToClient", "Ptr",MG_HCTL, "Ptr",pt)
		hp := DllCall("OpenProcess", "UInt",0x001F0FFF, "UInt",0, "UInt",MG_PID, "Ptr")
		size := 8 + A_PtrSize*2
		pi := DllCall("VirtualAllocEx", "Ptr",hp, "Ptr",0, "UInt",size, "UInt",0x1000, "UInt",0x4, "Ptr")
		DllCall("WriteProcessMemory", "Ptr",hp, "Ptr",pi, "Ptr",pt, "Int",8, "Ptr",0)
		SendMessage, 0x1111, 0, %pi%,, ahk_id %MG_HCTL%
		DllCall("ReadProcessMemory", "Ptr",hp, "Ptr",pi+8, "PtrP",flag, "UInt",A_PtrSize, "Ptr",0)
		DllCall("VirtualFreeEx", "Ptr",hp, "Ptr",pi, "UInt",0, "UInt",0x8000)
		DllCall("CloseHandle", Ptr,hp)
		DllCall("GlobalFree", "Ptr",pt)
		flag := flag & 127
		return (flag<16) ? ((flag<4) ? ((flag<2) ? 0 : "ItemIcon") : ((flag<8) ? "ItemLabel" : "Indent")) : ((flag<32) ? "Button" : ((flag<64) ? "Right" : "ItemState"))
	}
	return 0
}

;---------------------------------------------------------------
; Hittest the DirectUIHWND
;														Implemented by Pyonkichi
;---------------------------------------------------------------
MG_DuiHitTest()
{
	global MG_CClass, MG_X, MG_Y
	If (MG_CClass = "DirectUIHWND")
	{
		uia := ComObjCreate("{ff48dba4-60ef-4201-aa87-54103eef594e}","{30cbe57d-d9d0-452a-ab13-7ac5ac4825ee}")
		If (uia)
		{
			uia := new MGC_UIAInterface(uia)
			uia.base.base.__UIA := uia
			ele := uia.FromPoint(MG_X, MG_Y)
			return (ele.id==50006 || ele.id==50007) ? "ItemIcon" : (ele.id==50004) ? "ItemLabel" : 0
		}
	}
	return 0
}

;---------------------------------------------------------------
; Check whether the cursor is on the item of the ListView and TreeView
;	fLvLabel	: 0 = Detect only icon of the ListView
;			: 1 = Include text label of the ListView
;	fTvLabel	: 0 = Detect only icon of the TreeView
;			: 1 = Include text label of the TreeView
;														Implemented by lukewarm
;													ModIfied by Pyonkichi
;---------------------------------------------------------------

MG_TreeListHitTest(fLvLabel=1, fTvLabel=1)
{
	lvht := MG_LvHitTest()
	If (!lvht) {
		lvht := MG_DuiHitTest()
	}
	If (lvht) {
		return (fLvLabel ? true : lvht!="ItemLabel")
	}
	else If (tvht := MG_TvHitTest()) {
		If (!fTvLabel && (tvht="ItemLabel")) {
			return false
		} else {
			return InStr(tvht, "Item")
		}
	}
	return false
}

;---------------------------------------------------------------
; Update Gesture Hints
;														Implemented by Pyonkichi
;---------------------------------------------------------------
MG_NaviUpdate:
	MG_UpdateAdNavi()
return

;---------------------------------------------------------------
; Hints Persistence Timer
;														Implemented by Pyonkichi
;---------------------------------------------------------------
MG_NaviPersistTimer:
	SetTimer, MG_NaviPersistTimer, Off
	MG_StopNavi(1)
return

;---------------------------------------------------------------
; Start Gesture Hints
;														Implemented by Pyonkichi
;---------------------------------------------------------------
MG_StartNavi()
{
	global
		SetTimer, MG_NaviPersistTimer, Off
		MG_NaviPrst := 0
		GoSub, MG_NaviUpdate
		SetTimer, MG_NaviUpdate, %MG_NaviInterval%
}

;---------------------------------------------------------------
; Stop Gesture Hints
;														Implemented by Pyonkichi
;---------------------------------------------------------------
MG_StopNavi(fForce=1)
{
	global	
	; ToolTip, MG_StopNavi
		SetTimer, MG_NaviUpdate, Off
			Gui, MGW_ExNavi:Show, w1 h1 Hide
}


;---------------------------------------------------------------
; Create Gesture Hints Window
;														Implemented by lukewarm
;														ModIfied by Pyonkichi
;---------------------------------------------------------------
MG_CreateExNavi()
{
	global
	; ToolTip, MG_CreateExNavi
	Gui, MGW_ExNavi:New
	Gui, MGW_ExNavi:+HwndMG_ExNaviHwnd -Caption +ToolWindow +AlwaysOnTop +LastFound
		MG_AdNavIfG2 := MG_ConvertHex(MG_AdNavIfG)
		MG_AdNaviNI2 := MG_ConvertHex(MG_AdNaviNI)
		MG_AdNaviBG2 := MG_ConvertHex(MG_AdNaviBG)
		MG_AdNaviTransClr := MG_MakeTransColor(MG_AdNaviBG)
		MG_AdNaviTransClr2 := MG_ConvertHex(MG_AdNaviTransClr)
		Gui, MGW_ExNavi:Color, %MG_AdNaviBG%
		local colorBG := MG_AdNaviTransClr
		WinSet, TransColor, %colorBG%
}

;---------------------------------------------------------------
; Make Transparent Color
;														Implemented by Pyonkichi
;---------------------------------------------------------------
MG_MakeTransColor(color)
{
	RegExMatch(color, "([a-zA-Z0-9][a-zA-Z0-9])([a-zA-Z0-9][a-zA-Z0-9])([a-zA-Z0-9][a-zA-Z0-9])", $)
	RR := "0x" . $1,	RR += (RR>0) ? -1 : 1
	GG := "0x" . $2,	GG += (GG>0) ? -1 : 1
	BB := "0x" . $3,	BB += (BB>0) ? -1 : 1
	SetFormat, IntegerFast, H
	colTrans := (RR<<16) + (GG<<8) + BB
	colTrans := RegExReplace(colTrans, "^0x")
	SetFormat, IntegerFast, D
	len := StrLen(colTrans)
	Loop, % (6 - len)	; % 
	{
		colTrans := "0" . colTrans
	}
	return colTrans
}

;---------------------------------------------------------------
; Convert String Hexadecimal
; Implemented by Pyonkichi
;---------------------------------------------------------------
MG_ConvertHex(hex)
{
	return RegExReplace(hex						,"([a-zA-Z0-9][a-zA-Z0-9])([a-zA-Z0-9][a-zA-Z0-9])([a-zA-Z0-9][a-zA-Z0-9])"
	,"0x$3$2$1")
}

;---------------------------------------------------------------
; Destroy Gesture Hints Window
;														Implemented by lukewarm
;														ModIfied by Pyonkichi
;---------------------------------------------------------------
MG_DestroyExNavi()
{
	Gui, MGW_ExNavi:Destroy
}


;---------------------------------------------------------------
; Update Arrow Hints
;														Implemented by lukewarm
;														ModIfied by Pyonkichi
;---------------------------------------------------------------
MG_UpdateExNavi()
{
	global
	static prevX:=0, prevY:=0
	;...........................................................................
	; Critical Section
	static fCritical := 0
	If (fCritical) {
		return
	}
	fCritical := 1
	;...........................................................................
	; Make Arrows String and Check Gesture Conditions
	local szGesture := MG_NaviPrst ? MG_NaviPrstStr : MG_Gesture
	; local szArrows := MG_MakeArrowsStr(szGesture)
	If (!szArrows)
	{
		fCritical := 0
		return
	}
	;...........................................................................
	; Decide Drawing Position
	local winX, winY
	If (MG_ExNaviMargin < 0)
	{
		winX:=MG_X, winY:=MG_Y
	}
	else
	{
		CoordMode, Mouse, Screen
		MouseGetPos, winX, winY
		winX += MG_ExNaviMargin
		winY += MG_ExNaviMargin
	}
	;...........................................................................
	; Draw Arrows
	If (szArrows != MG_PrevGesture)
	{
		RegExMatch(szGesture, "(\w+)_", $)
	 	local fgc := (MG_ExNavIfG_%$1% != "") ? MG_ExNaviIdvFG : MG_ExNavIfG2
		local bgc := MG_ExNaviIdvBG ? MG_ExNaviIdvBG : MG_ExNaviBG2
		local hDC := DllCall("GetWindowDC", "Ptr",MG_ExNaviHwnd, "Ptr")
		local hFont := MG_CreateFont("Wingdings", MG_ExNaviSize)
		local hFntOld := DllCall("SelectObject", "Ptr",hDC, "Ptr",hFont, "Ptr")
		DllCall("SetTextColor","Ptr",hDC, "UInt",fgc)
		DllCall("SetBkColor","Ptr",hDC, "UInt",bgc)
		DllCall("SelectObject", "Ptr",hDC, "Ptr",hFntOld)
		DllCall("DeleteObject", "Ptr",hFont)
		DllCall("ReleaseDC", "Ptr",MG_ExNaviHwnd, "Ptr",hDC)
	}
	;...........................................................................
	; Only Move Window
	else If (prevX!=winX || prevY!=winY)
	{
		Gui, MGW_ExNavi:Show, x%winX% y%winY% NA
	}
	prevX:=winX, prevY:=winY
	MG_PrevGesture := szArrows
	fCritical := 0
}
;---------------------------------------------------------------
; Update Hint Arrows Type 1
;														Implemented by Pyonkichi
;---------------------------------------------------------------
MG_UpdateArrowHints1(hDC, szGesture, szArrows, winX, winY)
{
	global
	DllCall("SetTextCharacterExtra", "Ptr",hDC, "Int",MG_ExNaviSpacing)
	local size
	VarSetCapacity(size, 8, 0)
	DllCall("GetTextExtentPoint32", "Ptr",hDC, "Str",szArrows, "Int",StrLen(szArrows), "Ptr",&size)
	local winW := NumGet(size, 0, "UInt") + MG_ExNaviPadding*2
	local winH := NumGet(size, 4, "UInt") + MG_ExNaviPadding*2
	If (winW && winH)
	{
		Gui, MGW_ExNavi:Show, x%winX% y%winY% w%winW% h%winH% NA
		DllCall("TextOut", "Ptr",hDC, "Int",MG_ExNaviPadding, "Int",MG_ExNaviPadding, "Str",szArrows, "Int",StrLen(szArrows))
	}
}
;---------------------------------------------------------------
; Update Advanced Gesture Hints
;														Implemented by Pyonkichi
;---------------------------------------------------------------
MG_UpdateAdNavi()
{
	global
	static prevX:=0, prevY:=0
	;...........................................................................
	; Critical Section
	static fCritical := 0
	If (fCritical) {
		return
	}
	fCritical := 1
	;...........................................................................
	; Check Gesture Conditions
	local szGesture := MG_NaviPrst ? MG_NaviPrstStr : MG_Gesture
	If (!szGesture)
	{
		fCritical := 0
		return
	}
	If (szGesture = MG_1stTrigger)
	{
		Gui, MGW_ExNavi:Hide
		fCritical := 0
		return
	}
	;...........................................................................
	; Decide Drawing Position
	local winX, winY
	CoordMode,Mouse,Screen
	MouseGetPos, winX, winY
	winX += MG_AdNaviMargin
	winY += MG_AdNaviMargin
	;...........................................................................
	; Draw Gesture Pattern
	If (szGesture != MG_PrevGesture)
	{
		local hDC := DllCall("GetWindowDC", "Ptr",MG_ExNaviHwnd, "Ptr")
		MG_hFntBtn := MG_CreateFont(MG_AdNavIfont, MG_AdNaviSize, 700)
		MG_hFntDir := MG_CreateFont("Wingdings", MG_AdNaviSize)
		MG_hFntAct := MG_CreateFont(MG_AdNavIfont, MG_AdNaviSize)
		DllCall("SetBkColor", "Ptr",hDC, "UInt",MG_AdNaviBG2)
			MG_UpdateAdNavi1(hDC, winX, winY, szGesture)
		DllCall("DeleteObject", "Ptr",MG_hFntBtn)
		DllCall("DeleteObject", "Ptr",MG_hFntDir)
		DllCall("DeleteObject", "Ptr",MG_hFntAct)
		DllCall("ReleaseDC", "Ptr",MG_ExNaviHwnd, "Ptr",hDC)
	}
	;...........................................................................
	; Only Move Window
	else If (prevX!=winX || prevY!=winY)
	{
		local dwStyle
		WinGet, dwStyle, Style, ahk_id %MG_ExNaviHwnd%
		If (dwStyle & 0x10000000) {
			Gui, MGW_ExNavi:Show, x%winX% y%winY% NA
		}
	}
	prevX:=winX, prevY:=winY
	MG_PrevGesture := szGesture
	fCritical := 0
}

;---------------------------------------------------------------
; Update Advanced Gesture Hints Type 1
;														Implemented by Pyonkichi
;---------------------------------------------------------------
MG_UpdateAdNavi1(hDC, winX, winY, szGesture)
{
	global
	local gesW, gesH
	MG_DrawGesture(hDC, 0, 0, szGesture, gesW, gesH, 1)
	MG_ActionStr := ""
	If (IsLabel("MG_GetAction_" . szGesture . "_")) {
		GoSub, MG_GetAction_%szGesture%_
	}
	local actW:=0, actH:=0
	If (MG_ActionStr)
	{
		MG_ActionStr := " : " . MG_ActionStr
		MG_DrawAction(hDC, 0, 0, MG_ActionStr, 1, actW, actH)
	}
	local winW := gesW + actW + MG_AdNaviPaddingL + MG_AdNaviPaddingR
	local winH := (gesH>actH ? gesH : actH) + MG_AdNaviPaddingT + MG_AdNaviPaddingB
	If (! winW || !winH) {
		return
	}
	; MG_SetAdNaviPos(winX, winY, winW, winH)
	Gui, MGW_ExNavi:Show, x%winX% y%winY% w%winW% h%winH% NA
	DllCall("SetTextColor", "Ptr",hDC, "UInt",MG_AdNavIfG2)
	MG_DrawGesture(hDC, MG_AdNaviPaddingL, MG_AdNaviPaddingT, szGesture, gesW, gesH)
	If (actW) {
		MG_DrawAction(hDC, MG_AdNaviPaddingL+gesW, MG_AdNaviPaddingT, MG_ActionStr)
	}
}


;---------------------------------------------------------------
; Draw Action String
;														Implemented by Pyonkichi
;---------------------------------------------------------------
MG_DrawAction(hDC, ptX, ptY, szAction, fMeasure=0, ByRef strW=0, ByRef strH=0)
{
	global MG_hFntAct, MG_AdNaviNI2

	hFntOld := DllCall("SelectObject", "Ptr",hDC, "Ptr",MG_hFntAct, "Ptr")
	If (fMeasure)
	{
		VarSetCapacity(size, 8, 0)
		DllCall("GetTextExtentPoint32", "Ptr",hDC, "Str",szAction, "Int",StrLen(szAction), "Ptr",&size)
		strW := NumGet(size, 0, "UInt")
		strH := NumGet(size, 4, "UInt")
	}
	else
	{
		DllCall("TextOut", "Ptr",hDC, "Int",ptX, "Int",ptY, "Str",szAction, "Int",StrLen(szAction))
	}
	DllCall("SelectObject", "Ptr",hDC, "Ptr",hFntOld)
}


;===========================================================================
;
;		MouseGestureL.ahk - Common Functions Library
;
;														Created by Pyonkichi
;===========================================================================


;------------------------------------------------------------------------
; Create Font
;														Implemented by Pyonkichi
;------------------------------------------------------------------------
MG_CreateFont(szFace, nSize, nWeight=0, nQuality=0)
{
	return DllCall("CreateFont"
					,"Int",-nSize							; nHeight
					,"Int",0								; nWidth
					,"Int",0								; nEscapement
					,"Int",0								; nOrientation
					,"Int",nWeight							; nWeight
					,"UInt",0								; fdwItalic
					,"UInt",0								; fdwUnderline
					,"UInt",0								; fdwStrikeOut
					,"UInt",(szFace="Wingdings" ? 2 : 1)	; fdwCharset
					,"UInt",0								; fdwOutPrecision
					,"UInt",0								; fdwClipPrecision
					,"UInt",nQuality						; fdwQuality
					,"UInt",0								; fdwPitchAndFamily
					,"Str",szFace							; pszFaceName
					,"Ptr")
}

;------------------------------------------------------------------------
; Draw Gesture Pattern
;														Implemented by Pyonkichi
;------------------------------------------------------------------------
MG_DrawGesture(hDC, ptX, ptY, szGesture, ByRef strW=0, ByRef strH=0, fMeasure=0, nGesLen=0)
{
	global MG_BtnNames, MG_AdNaviNI2, MG_hFntBtn, MG_hFntDir, MG_AdNaviSize
	static DirD=0xEA, DirL=0xE7, DirR=0xE8, DirU=0xE9
	static Dir1=0xED, Dir2=0xEA, Dir3=0xEE, Dir4=0xE7, Dir6=0xE8, Dir7=0xEB, Dir8=0xE9, Dir9=0xEC

	If (!fMeasure) {
		hRgn := DllCall("CreateRectRgn", "Int",ptX, "Int",ptY, "Int",ptX+strW, "Int",ptY+strH, "Ptr")
		DllCall("SelectClipRgn", "Ptr",hDC, "Ptr",hRgn)
	}
	DllCall("SetTextAlign", "Ptr",hDC, "Ptr",24)
	hFntOld := DllCall("SelectObject", "Ptr",hDC, "Ptr",MG_hFntBtn, "Ptr")
	VarSetCapacity(size, 8, 0)
	max:=StrLen(szGesture), pos:=1, preFont:=1, nowX:=ptX, strH:=0, sftBase:=MG_AdNaviSize//6
	while (pos <= max)
	{
		shIft := 0
		If (SubStr(szGesture, pos, 1) == "_")
		{
			newFont := 1
			szDraw := "_"
			offset := 1
			shIft := fDown ? 0 : (sftBase-MG_AdNaviSize)
			fDown := 0
		}
		else
		{
			fDown := 0
			Loop, Parse, MG_BtnNames, _
			{
				If (A_LoopField && InStr(SubStr(szGesture, pos), A_LoopField) == 1) {
					newFont := 1
					szDraw := A_LoopField
					offset := StrLen(A_LoopField)
					fDown := 1
					break
				}
			}
			If (!fDown) {
				newFont := 2
				dir := "Dir" . SubStr(szGesture, pos, 1)
				szDraw := Chr(%dir%)
				offset := 1
				shIft := (dir="DirD"||dir="Dir2") ? sftBase : 0
			}
		}
		If (preFont != newFont) {
			preFont := newFont
			DllCall("SelectObject", "Ptr",hDC, "Ptr",(newFont==1 ? MG_hFntBtn : MG_hFntDir))
		}
		If (!fMeasure) {
			DllCall("TextOut", "Ptr",hDC, "Int",nowX, "Int",ptY+MG_AdNaviSize+shIft, "Str",szDraw, "Int",StrLen(szDraw))
		}
		DllCall("GetTextExtentPoint32", "Ptr",hDC, "Str",szDraw, "Int",StrLen(szDraw), "Ptr",&size)
		nowX += NumGet(size, 0, "UInt")
		h := NumGet(size, 4, "UInt")
		If (h > strH) {
			strH := h
		}
		pos += offset
		If (pos == nGesLen+1) {
			DllCall("SetTextColor", "Ptr",hDC, "UInt",MG_AdNaviNI2)
		}
	}
	strW := nowX - ptX
	DllCall("SelectObject", "Ptr",hDC, "Ptr",hFntOld)
	DllCall("SetTextAlign", "Ptr",hDC, "Ptr",0)
	If (!fMeasure) {
		DllCall("SelectClipRgn", "Ptr",hDC, "Ptr",0)
		DllCall("DeleteObject", "Ptr",hRgn)
	}
}
Last edited by GEV on 20 Jun 2019, 01:53, edited 2 times in total.

iPhilip
Posts: 799
Joined: 02 Oct 2013, 12:21

Re: MouseGestureL

Post by iPhilip » 19 Jun 2019, 19:18

@GEV, Thank you for sharing your configuration files. I downloaded MouseGestureL.ahk but I am not sure how to use your files or what they do. Could you provide more information?

Thank you.
Windows 10 Pro (64 bit) - AutoHotkey v2.0+ (Unicode 64-bit)

GEV
Posts: 1002
Joined: 25 Feb 2014, 00:50

Re: MouseGestureL

Post by GEV » 20 Jun 2019, 01:18

@@iPhilip, you don't need the original for testing my script. See my (first) edited answer.

User avatar
Delta Pythagorean
Posts: 627
Joined: 13 Feb 2017, 13:44
Location: Somewhere in the US
Contact:

Re: MouseGestureL

Post by Delta Pythagorean » 20 Jun 2019, 15:55

The place in which you host the script is a little sketchy, might I recommend something with a language most users on this forum can understand..?
Image

[AHK]......: v2.0.12 | 64-bit
[OS].......: Windows 11 | 23H2 (OS Build: 22621.3296)
[GITHUB]...: github.com/DelPyth
[PAYPAL]...: paypal.me/DelPyth
[DISCORD]..: tophatcat


Renets
Posts: 36
Joined: 12 Jul 2018, 13:11

Re: MouseGestureL

Post by Renets » 30 Jul 2019, 11:04

This is awesome thanks!
I ran into one little problem though: Everything works perfectly but since have the Windows Taskbar in Auto-Hide mode I need go get the mouse into the Taskbar side of Windows, but when I run the Main Script (MouseGestureL.ahk), the functionality of the Auto-hide/show breaks (The thing is it doesn't break when I have nothing Maximized, but as I almost all the time have windows Maximized thats my problem), and I am no longer able to show the taskbar. I am presuming it has to do anything in the code that deals with the limits of the screen or something like that, but I haven't fount it yet. Also tried to tweak the Screen Edge Recognition but no success
Any suggestions? since this tool is very useful and I look forward to it

smtdba
Posts: 8
Joined: 26 Dec 2019, 18:08

Re: MouseGestureL

Post by smtdba » 08 Jan 2020, 15:55

I'm using Radial Menu, which also has a very basic gesture system.
RB_D calls up the form. Also includes events firing that you can hook onto with your code.

MouseGestureL is far more advanced in terms of being able to categorize how you identify a window and what happen for each gesture.

Unfortunately when I allow RadialMenu to run, MGL won't activate at all. I cleared out RB_R in RadialMenu and MGL still won't trigger anything for that gesture until until RadialMenu is closed.

Is there any way to both to work together? Or removing all gesture events from Radial Menu? If I had Radial Menu appear on a hotkey, I could assign RM_D to trigger that hotkey in MGL

-- edit

You can set a delay in Radial Menu, that removes the gestures. So then it just uses LeftMouse held down as the hotkey by default. I'll experiment with disabling that, changing the hotkey. I'm hoping that'll let MouseGesturesL manage the gestures and call that hotkey to activate

User avatar
Pyonkichi
Posts: 107
Joined: 16 May 2017, 20:40
Contact:

Re: MouseGestureL

Post by Pyonkichi » 12 Jan 2020, 19:41

Your problem may be solved by the script loading order that loading RM2 first and then loading MGL.

User avatar
Pyonkichi
Posts: 107
Joined: 16 May 2017, 20:40
Contact:

MouseGestureL.ahk v1.32 has been released.

Post by Pyonkichi » 28 Jan 2020, 03:21

MouseGestureL.ahk v1.32
  • High DPI environments have been supported.
  • Added hotkey setting for restart of MouseGestureL.
  • Added "Don't reproduce original mouse movements when undefined gesture is performed" option.
  • Added a setting to register windows excluded by task switching.
    (It's used by the function MG_ActivatePrevWin().)
  • The specification has been changed to force all trigger buttons to be released approximately three seconds after the gesture times out.
    (Countermeasure against freeze due to missing trigger button release event detection.)
  • Added workaround for the problem that always on top status of taskbar is released when the "Draw trail into overwrap window" option is enabled. In addition, performance of the gesture assignment actions have been improved in case of overwrap window option is enabled.
  • Fixed minor bugs.
Download:
MouseGestureL.ahk v1.32 (Jan. 28, 2020)
h t t p://pyonkichi.g1.xrea.com/archives/MGLahk132.zip
 
 
For multi-monitor users:
Gesture hints and configuration dialog box are now displayed correctly in environments where the display scale is set to more than 100% by the display settings of Windows. However, since AutoHotkey does not support Per-Monitor DPI, the problems related to cursor coordinates still occur on a monitor with a different display scale than the primary monitor in a multi-monitor environment. To avoid this, you need to change the high DPI setting for AutoHotkey as follows.
  1. Show properties of the AutoHotkey.exe (or MouseGestureL.exe) in Windows Explorer.
  2. Select "Compatibility" tab and click the "Change high DPI settings" button.
  3. Check "Override high DPI scaling behavior".
  4. Select "Application" in the "Scaling performed by:" dropdown list. (It's selected by default.)
  5. Click OK to close the properties.
The gesture function on the sub-monitor will perform properly with above settings, however when the dialog box such as the setting screen is moved to the sub-monitor, the window size is not adjusted automatically according to the display scale. This setting also affects scripts created for AutoHotkey other than MouseGestureL, so make a decision whether to change this settings in consideration of your own usage situation.

User avatar
Pyonkichi
Posts: 107
Joined: 16 May 2017, 20:40
Contact:

Small bug in v1.32

Post by Pyonkichi » 22 Feb 2020, 12:20

A small bug was found in v1.32. When a forced release of the trigger button occurs, the next forced release will be executed within a second.
You can fix it by editing MouseGestureL.ahk. Insert following code to line 505 of the MouseGestureL.ahk.

 MG_UnpressCnt%name% := 0
 
 if(!InStr(MG_CurTriggers,name . "_"))
 {
   MG_UnpressCnt%name% := 0 <------
   MG_TriggerCount++
   MG_CurTriggers=%MG_CurTriggers%%name%_
    .....

 

User avatar
Pyonkichi
Posts: 107
Joined: 16 May 2017, 20:40
Contact:

MouseGestureL.ahk v1.33 has been released.

Post by Pyonkichi » 27 Feb 2020, 05:53

MouseGestureL.ahk v1.33
  • Added the following three items to the action template.
    - Minimize all windows of the same class
    - Close all windows of the same class
    - Tile all windows of the same class
  • Added setting that number of seconds from gesture timeout to forced release of trigger buttons.
  • Fixed a bug that the right button is released forcefully while right dragging the files on Explorer.
  • Fixed a bug where the display position of the OK and Cancel buttons in the various action setting dialog boxes are shifted in a high DPI environment.
  • Other changes in internal processing.
Download:
Last edited by joedf on 03 Mar 2020, 10:33, edited 1 time in total.
Reason: fix link

WOlfen
Posts: 61
Joined: 14 Jan 2018, 16:48

Re: MouseGestureL

Post by WOlfen » 03 Mar 2020, 10:14

I wanted to try this out, but the Downloadlink is gone.

User avatar
joedf
Posts: 8940
Joined: 29 Sep 2013, 17:08
Location: Canada
Contact:

Re: MouseGestureL

Post by joedf » 03 Mar 2020, 10:34

The link was just broken. I've fixed it :+1:
Image Image Image Image Image
Windows 10 x64 Professional, Intel i5-8500, NVIDIA GTX 1060 6GB, 2x16GB Kingston FURY Beast - DDR4 3200 MHz | [About Me] | [About the AHK Foundation] | [Courses on AutoHotkey]
[ASPDM - StdLib Distribution] | [Qonsole - Quake-like console emulator] | [LibCon - Autohotkey Console Library]

WOlfen
Posts: 61
Joined: 14 Jan 2018, 16:48

Re: MouseGestureL

Post by WOlfen » 12 Mar 2020, 11:36

Thanks so much for fixing the link.
This is an awesome Script. :D
I have some questions thou which i didn´t figured out yet.
How can i exclude a specific Program from using the Gestures?
And second, i noticed it works in a normal Explorer Windows too. But it is hard to navigate with the Gestures there cause you have to find a empty spot where Windows don´t activates the Right Click Context Menu. Can i improve that somewhere in the options?
Also, i´ve seen there is a Plugin Folder with a Foobar.ahk.sample in it. But i´ve seen mention yet what it does nor how i use it.
Maybe there is a tutorial that answered my questions already, which i also didn´t find yet. :oops:

Edit:
I must been blind. There is an Help File in the Docs.
Will reading it now. I hope that my Answers are in the Docs.

User avatar
Pyonkichi
Posts: 107
Joined: 16 May 2017, 20:40
Contact:

Re: MouseGestureL

Post by Pyonkichi » 13 Mar 2020, 21:17

@WOlfen
Maybe I have to supplement. The help file written by my friend was created for v1.19, so some contents don't correspond to the current version.
1. To exclude a specific Program
Select "Target" tab and register the programs which you want to exclude to "Ignored Targets".
2. To avoid finding a empty spot in Explorer
Select "Main" tab and select the item named "Icon" under "Explorer" from the Targets list. Then delete the gesture named "RB_" from the Gestures list.
3. About plug-in
See "4.5.17. Plugin Sample Script" of help file.

User avatar
submeg
Posts: 326
Joined: 14 Apr 2017, 20:39
Contact:

Re: MouseGestureL

Post by submeg » 27 Apr 2020, 06:52

Hi all,

I might be missing something, but how do I bind an action to a gesture? In the GUI, I don't have the "actions" tab. What am I doing wrong?
____________________________________
Check out my site, submeg.com
Connect with me on LinkedIn
Courses on AutoHotkey :ugeek:

User avatar
Pyonkichi
Posts: 107
Joined: 16 May 2017, 20:40
Contact:

Re: MouseGestureL

Post by Pyonkichi » 28 Apr 2020, 19:19

@submeg,
The "Actions" tab no longer exists. You can assign action to gestures in the Main tab.
Attachments
mgl_001.jpg
mgl_001.jpg (54.75 KiB) Viewed 22160 times
Last edited by Pyonkichi on 30 Apr 2020, 09:18, edited 1 time in total.

User avatar
submeg
Posts: 326
Joined: 14 Apr 2017, 20:39
Contact:

Re: MouseGestureL

Post by submeg » 28 Apr 2020, 21:58

Thanks for that @Pyonkichi, I will have a look now.

Edit: Yep, got it working! Thanks so much for this, I've been looking for something like this for a while now!
____________________________________
Check out my site, submeg.com
Connect with me on LinkedIn
Courses on AutoHotkey :ugeek:

Post Reply

Return to “Scripts and Functions (v1)”