I have tried to combine several existing mouse-gesture scripts to get one more comfortable for my daily use.
Thanks to the following scripts:
1 AHK Mouse Gesture of Youfou (in Chinese). (the mostly credited)
2 Mouse Guestures Plus! v1.0 by Oasis (in Chinese).
3 deguix's MouseGestures
4 Shimanov and Metaxal's draw mouse movement on screen
5 many other MG scripts including my own original mousegesture.
I have reached a point with the following features,
1) draw mouse trace and erase ('gesture trail').
2) TrayTip prompts the identified motion seriers (e.g. DL, DR, RLR, etc) or identified code (e.g. character "C", "L", etc). So you can see what is going on. If the code is not what you want, simply move more than 3 directions, and the gesture is automatically canceled. The cancel info is also prompted by traytip.
3) Use a number of Hotkeys (e.g. ^+F12) to notify other AHK scripts, so we can implement AHK without touch the mouse gesture codes.
4) Without using 'Gui +AlwaysOnTop', so there are no mask over other windows. Better than programs like gMote where a mask is indeed visible.
5) Response speed is quite good, and CPU usage is low, even compared with other commerical couterparts.
6) Use Right Ctrl keystroke to activate on/off the mouse gesture.
Here are problems to be solved
1) EraseTrace subroutine may be better refined using CreatePolygonRgn. But I am not good at this, though I have developed program similar to Microsoft Visio before. Please provide help.
I wish experts in the forum can help to improve this, and finally get one that match Strokeit.
Best,
<!-- e --><a href="mailto:Jabobian@yahoo.com">Jabobian@yahoo.com</a><!-- e -->
#SingleInstance force
IfNotExist MGConfig.ini
{
MsgBox cannot find MGConfig.ini
ExitApp
}
#WinActivateForce
SetTitleMatchMode 2
#IfWinNotActive, (Maxthon)
loop
{
IniRead ActName%A_Index%,MGConfig.ini,ActNames,%A_Index%
IniRead act%A_Index%,MGConfig.ini,MouseGestures,%A_index%
If (act%A_Index%="ERROR")
{
n:=A_Index-1
Break
}
}
Loop %n%
{
LoopName:=ActName%A_Index%
LoopAct:=act%A_Index%
StringReplace LoopAct,LoopAct,R,→,A
StringReplace LoopAct,LoopAct,L,←,A
StringReplace LoopAct,LoopAct,U,↑,A
StringReplace LoopAct,LoopAct,D,↓,A
instructions=%instructions%%A_Index%.%A_Space%%LoopAct%%A_Space%%LoopName%`n`n
}
Menu,tray,add,Read Instruction,instructions
Menu,tray,add,View INI,runini
Menu,tray,add
Menu,tray,add,Quit,GuiClose
;--------- MouseTrace GDI Code ---------------------
color_names=0x000000,0xC0C0C0,0x808080,0xFFFFFF,0x800000,0xFF0000,0x800080,0xFF00FF,0x008000,0x00FF00,0x808000,0xFFFF00,0x000080,0x0000FF,0x008080,0x00FFFF
;Black,Silver,Gray,White,Maroon,Red,Purple,Fuchsia,Lime,Green,Olive,Yellow,Navy,Blue,Teal,Aqua
CoordMode, Mouse, Screen
Process, Exist
pid_this := ErrorLevel
hdc_screen := DllCall( "GetDC", "uint", 0 )
hdc_buffer := DllCall( "CreateCompatibleDC", "uint", hdc_screen )
hbm_buffer := DllCall( "CreateCompatibleBitmap", "uint", hdc_screen, "int", A_ScreenWidth, "int", A_ScreenHeight )
DllCall( "SelectObject", "uint", hdc_buffer, "uint", hbm_buffer )
WinGet, hw_canvas, ID, ahk_class AutoHotkeyGUI ahk_pid %pid_this%
hdc_canvas := DllCall( "GetDC", "uint", hw_canvas )
StringSplit colors, color_names, `,
color_index := 10
color := colors%color_index%
width := 2
Return
instructions:
TrayTip,MouseGesture4U,%instructions%
Return
RunIni:
Run MGConfig.ini
Return
GuiClose:
ExitApp
Return
~RCtrl::
If Disabled = 0
{
Menu, TRAY, Icon, Mouse Gestures4.ico
Menu, TRAY, Tip, Mouse Gestures (disabled)
Hotkey, RButton, Off
Disabled = 1
}
Else
{
Menu, TRAY, Icon, Mouse Gestures.ico
Menu, TRAY, Tip, Mouse Gestures
Hotkey, RButton, On
Disabled = 0
}
Return
RButton::
SetTimer TimerRButton, -1
Return
TimerRButton:
SetBatchLines -1 ;any suggestions?
MouseGetPos TX,TY,UMWID,UMC
Loop
{
MouseGetPos TXX,TYY
TR:=GetKeyState("RButton","P")
XX:=TXX-TX
YY:=TYY-TY
DS:=XX*XX+YY*YY
If ((TR=0) And (DS<=100))
{
SendPlay {RButton}
Break
}
If ((DS>100) And (TR=1))
{
Gosub Do
Break
}
}
If (GestureList=act1)
Send +{F7}
If (GestureList=act2)
Send +{F8}
If (GestureList=act3)
Send +{F9}
If (GestureList=act4)
Send +{F10}
If (GestureList=act5)
Send +{F11}
If (GestureList=act6)
Send +{F6}
If (GestureList=act7)
Send ^+{F7}
If (GestureList=act8)
Send ^+{F8}
If (GestureList=act9)
Send ^+{F9}
If (GestureList=act10)
Send ^+{F10}
If (GestureList=act11)
Send ^+{F11}
If (GestureList=act12)
{
TrayTip Instructions,%instructions%,20
SetTimer, TrayTipCheck, 200
}
GestureList=
Return
Do:
DllCall( "BitBlt", "uint", hdc_buffer, "int", 0, "int", 0, "int", A_ScreenWidth, "int", A_ScreenHeight, "uint", hdc_screen, "int", 0, "int", 0, "uint", 0x00CC0020 )
Num:=1
x_last:=TX
y_last:=TY
Rx%Num% := x_last
Ry%Num% := y_last
Loop %Count%
Gesture%A_Index%=
GestureList=
Count:=1
lx:=TX
ly:=TY
act=
Loop
{
lastGesture:=Gesture%lastcount%
TR:=GetKeyState("RButton","P")
If TR=0
Break
MouseGetPos nx,ny
xx:=nx-lx
yy:=ny-ly
;--------------------------------------------------
MouseGetPos x_new, y_new
drawLine(x_last, y_last, x_new, y_new, color, width)
x_last := x_new
y_last := y_new
Num += 1
Rx%Num% := x_new
Ry%Num% := y_new
;--------------------------------------------------
DS:=XX*XX+YY*YY
If (DS<225)
Continue
identify()
lx:=nx
ly:=ny
lastcount:=count-1
If (Gesture%count%=Gesture%lastcount%)
{
Gesture%count%=
Continue
}
If Gesture%count%=
Continue
NewMove:=Gesture%Count%
GestureList=%GestureList%%NewMove%
StringReplace rsuser,GestureList,R,→%A_Space%,A
StringReplace rsuser,rsuser,L,←%A_Space%,A
StringReplace rsuser,rsuser,U,↑%A_Space%,A
StringReplace rsuser,rsuser,D,↓%A_Space%,A
Loop %n%
{
If (GestureList=Act%A_Index%)
{
act:=ActName%A_Index%
Break
}
}
If (count > 3) ;change as you like, but 3 is enough for most people
{
TrayTip ,,%A_Space%Gesture Canceled
break
}
Else
{
TrayTip ,,%rsuser%%A_Space%%act%
SetTimer, TrayTipOff, -500
}
count++
act=
}
GoSub EraseTrace
return
TrayTipCheck:
TR:=GetKeyState("RButton","P")
If TR=0
{
SetTimer, TrayTipCheck, Off
SetTimer, TrayTipOff, -4000
}
Return
TrayTipOff:
SetTimer, TrayTipOff, Off
TrayTip
Return
EraseTrace:
Critical
If Num <> 0
{
DoingErase := 1
xmin := Rx1, ymin := Ry1, xmax := Rx1, ymax := Ry1
Loop %Num%
{
xmin := Rx%A_Index%>xmin? xmin:Rx%A_Index%
xmax := Rx%A_Index%<xmax? xmax:Rx%A_Index%
ymin := Ry%A_Index%>ymin? ymin:Ry%A_Index%
ymax := Ry%A_Index%<ymax? ymax:Ry%A_Index%
cwidth := xmax - xmin
cheight := ymax - ymin
}
DllCall( "BitBlt", "uint", hdc_canvas, "int", xmin-2, "int", ymin-2, "int", cwidth+4, "int", cheight+4, "uint", hdc_buffer, "int", xmin-2, "int", ymin-2, "uint", 0x00CC0020 )
}
Return
identify()
{
global
If ((XX>0) And (XX>Abs(YY)*2))
Gesture%Count%:="R"
If ((XX<0) And (Abs(XX)>Abs(YY)*2))
Gesture%Count%:="L"
If ((YY>0) And (YY>Abs(XX)*2))
Gesture%Count%:="D"
If ((YY<0) And (Abs(YY)>Abs(XX)*2))
Gesture%Count%:="U"
}
drawLine(x0, y0, x1, y1, color_ini=0, width=1)
{
dx := x1 - x0
dy := y1 - y0
dxy := (Abs(dx) > Abs(dy) ? Abs(dx) : Abs(dy) )
dx := dx / dxy
dy := dy / dxy
Loop %dxy%
{
x0 += dx
y0 += dy
drawCircle(Round(x0),round(y0), color_ini)
}
}
drawCircle(x,y, color_ini) {
global hdc_canvas, width, hdc_screen
cRegion := DllCall( "gdi32.dll\CreateRoundRectRgn", "int", x-width , "int", y-width , "int", x+width , "int", y+width, "int", width*2, "int", width*2 )
cBrush := DllCall("gdi32.dll\CreateSolidBrush", "uint", color_ini )
DllCall( "gdi32.dll\FillRgn" , "uint", hdc_canvas , "uint", cRegion , "uint", cBrush )
DllCall("gdi32.dll\DeleteObject", "uint", cRegion)
DllCall("gdi32.dll\DeleteObject", "uint", cBrush)
}
~^s:: ;For convenience during debug in SciTE
ExitApp
ReturnAnd the following are the MGConfig.ini file.
[MouseGestures] ### 1=0 hr 2=3 hr 3=6 hr ### 4=9 hr 5="L" 6="C" 1=U 2=R 3=D 4=L 5=DR 6=LDR [ActNames] ###here is the information to show in traytip for each hotkey!### 1=0 hr 2=3 hr 3=6 hr 4=9 hr 5="L 6="C" 12=Instruction Help




