Jump to content


Recording {Modifier} as {Modifier Down/Up} when using Input


  • Please log in to reply
7 replies to this topic

#1 iammandler

iammandler
  • Guests

Posted 15 June 2012 - 03:03 PM

Hi,

I'm trying to make a simple macro recorder that records what a user types in and saves it. However, to get modifier keys to work with what I've made so far, I need to press and release the modifier and then the press and release the key. This won't do because I want to be able to record as I see what I'm doing - say, for example, I am navigating a program with various GUIs with various &hotkeys and I want to record a macro on the fly. If I press Alt+e to activate a button that opens, say, an editing window, where I will continue recording my macro, I would have to press and release alt and then press and release e, which would not press the button (in fact, it might do something else entirely, like open the edit menu).

I've noticed AutoScriptWriter adds {Control Down} and {Control Up} when Ctrl is pressed. How does it do this?

Here's the snippet of my attempts thus far:

text := ""
Again:
Input, text, V L1, {Control Down}{Control Up}{LAlt}{RAlt}{LWin}{LShift}{RShift}{BS}{RWin}{AppsKey}{F1}{F2}{F3}{F4}{F5}{F6}{F7}{F8}{F9}{F10}{F11}{F12}{Left}{Right}{Up}{Down}{Home}{End}{PgUp}{PgDn}{Del}{Ins}{Capslock}{Numlock}{PrintScreen}{Pause}{Escape}
IfInString, ErrorLevel, EndKey
{
	StringTrimLeft, ErrorLevel, ErrorLevel, 7
	If (ErrorLevel != "Pause") 
		script := script text "{" ErrorLevel "}"
	else if (ErrorLevel = "Pause")
	{
		script := script text
		goto End
	}
	ToolTip, %script%
	goto Again
}
	script := script text
	ToolTip, %script%
	goto Again


End:
Tooltip
return

Thanks!

#2 Maestr0

Maestr0
  • Members
  • 649 posts

Posted 15 June 2012 - 05:44 PM

try something like:
#InstallKeybdHook

~$shift::checkstate("shift")

return

checkstate(modifier)
{
	state := getkeystate(modifier,"P")
	if state = 1
		msgbox % modifier " down"
	loop
	{
		if getkeystate(modifier,"P") = 0
			break
	}
	msgbox % modifier " up"
	return
}

However, there's probably easier ways to do this :)
Try looking at an alternative to the screenwriter: Macro recorder: <!-- l --><a class="postlink-local" href="http://www.autohotkey.com/community/viewtopic.php?t=23671">viewtopic.php?t=23671</a><!-- l -->

#3 Guests

  • Guests

Posted 15 June 2012 - 06:26 PM

Thanks! I'll look into the snippet you posted.

I saw the Macro Recorder you linked, but I'm getting a blocked by OpenDNS warning when I try to download it.

#4 iammandler

iammandler
  • Guests

Posted 22 June 2012 - 05:38 PM

I've messed around with that snippet you posted, Maestr0, and it's getting closer, but it's also getting uglier. Is there an easier way to do this than to use Input?

#5 Maestr0

Maestr0
  • Members
  • 649 posts

Posted 22 June 2012 - 05:48 PM

Loads of ways, think a GUI might be handy. Post the (ugly?) code you have and let me get you on the right path.

#6 iammandler

iammandler
  • Guests

Posted 25 June 2012 - 03:50 PM

Thanks! Here it is. Shift works okay (although it's recording as {shiftdown}A{shiftup} which will basically force everything to be lower case. Ctrl and Alt work, but I can't get modified keystrokes like ctrl+a to be captured, and if you hold down any modifier, you get something like {shiftdown}{shiftdown}{shiftdown}{shiftdown}.

script := ""
modifiers := "shift control alt"
loop, parse, modifiers, %A_SPACE%
{
	Hotkey, ~$%A_LoopField%, ~$%A_LoopField%, Off
	Hotkey, ~$%A_LoopField% UP, ~$%A_LoopField% UP, Off
}

^[:: 
{
text := ""
loop, parse, modifiers, %A_SPACE%
{
	Hotkey, ~$%A_LoopField%, ~$%A_LoopField%, On
	Hotkey, ~$%A_LoopField% UP, ~$%A_LoopField% UP, On
}
Loop
{
Input, text, V L1, {LWin}{BS}{RWin}{AppsKey}{F1}{F2}{F3}{F4}{F5}{F6}{F7}{F8}{F9}{F10}{F11}{F12}{Left}{Right}{Up}{Down}{Home}{End}{PgUp}{PgDn}{Del}{Ins}{Capslock}{Numlock}{PrintScreen}{Pause}{Escape}
IfInString, ErrorLevel, EndKey
{
	StringTrimLeft, ErrorLevel, ErrorLevel,7
	If (ErrorLevel != "Pause") 
		script := script text "{" ErrorLevel "}" 
	else if (ErrorLevel = "Pause")
	{
		script := script text
		MsgBox %script%
		Tooltip
		break
	}
	ToolTip, %script%
	continue
}
	script := script text
	ToolTip, %script%
}
return

~$shift:: script := addMod("shift","down",script)
~$shift UP:: script := addMod("shift","up",script)
~$control:: script := addMod("control","down",script)
~$control UP:: script := addMod("control","up",script)
~$alt:: script := addMod("alt","down",script)
~$alt UP:: script := addMod("alt","up",script)
}


addMod(mod,dir,script)
{
script := script "{" mod dir "}"
Tooltip, %script%
return script
}


#7 Maestr0

Maestr0
  • Members
  • 649 posts

Posted 25 June 2012 - 07:28 PM

The code below solves the {shiftdown}{shiftdown}{shiftdown}etc, looking at your other problems now:
#Persistent

#NoEnv  						; Performance setting: http://www.autohotkey.com/docs/misc/Performance.htm

SetBatchLines -1 				; Performance setting: maximum speed for loops

ListLines Off					; Performance setting

#SingleInstance Force



script := ""

modifiers := "shift control alt"

loop, parse, modifiers, %A_SPACE%

{

   Hotkey, ~$%A_LoopField%, ~$%A_LoopField%, Off

   Hotkey, ~$%A_LoopField% UP, ~$%A_LoopField% UP, Off

}



^[:: 

{

text := ""

loop, parse, modifiers, %A_SPACE%

{

   Hotkey, ~$%A_LoopField%, ~$%A_LoopField%, On

   Hotkey, ~$%A_LoopField% UP, ~$%A_LoopField% UP, On

}

Loop

{

Input, text, V L1, {LWin}{BS}{RWin}{AppsKey}{F1}{F2}{F3}{F4}{F5}{F6}{F7}{F8}{F9}{F10}{F11}{F12}{Left}{Right}{Up}{Down}{Home}{End}{PgUp}{PgDn}{Del}{Ins}{Capslock}{Numlock}{PrintScreen}{Pause}{Escape}

IfInString, ErrorLevel, EndKey

{

   StringTrimLeft, ErrorLevel, ErrorLevel,7

   If (ErrorLevel != "Pause") 

      script := script text "{" ErrorLevel "}" 

   else if (ErrorLevel = "Pause")

   {

      script := script text

      MsgBox %script%

      Tooltip

      break

   }

   ToolTip, %script%

   continue

}

   script := script text

   ToolTip, %script%

}

return



~$shift:: script := addMod("shift","down",script)

~$shift UP:: script := addMod("shift","up",script)

~$control:: script := addMod("control","down",script)

~$control UP:: script := addMod("control","up",script)

~$alt:: script := addMod("alt","down",script)

~$alt UP:: script := addMod("alt","up",script)

}





addMod(mod,dir,script)

{

	global ; "global" so mod_old and dir_old are remembered between calls to this function

	if(mod = mod_old) and (dir = dir_old)	; this is to prevent {shiftdown}{shiftdown}{shiftdown}{shiftdown}etc

		return script

	else

	{

		mod_old := mod

		dir_old := dir

	}

	script := script "{" mod dir "}"

	Tooltip, %script%

	return script

}


#8 Maestr0

Maestr0
  • Members
  • 649 posts

Posted 25 June 2012 - 07:49 PM

I'm sorry, I don't have any more time tonight, but maybe you can build on what I managed to scrape together.
There's probably a better way to do this (keyhistory seems to see the CTRL and a just fine) but meh :D
#Persistent
#NoEnv  					; Performance setting: http://www.autohotkey.com/docs/misc/Performance.htm
SetBatchLines -1 			; Performance setting: maximum speed for loops
ListLines Off				; Performance setting
#SingleInstance Force

gosub Transcribe_ASCII	; for ctrl-c etc capture

script := ""
modifiers := "shift control alt"
loop, parse, modifiers, %A_SPACE%
{
   Hotkey, ~$%A_LoopField%, ~$%A_LoopField%, Off
   Hotkey, ~$%A_LoopField% UP, ~$%A_LoopField% UP, Off
}

^[:: 
{
text := ""
loop, parse, modifiers, %A_SPACE%
{
   Hotkey, ~$%A_LoopField%, ~$%A_LoopField%, On
   Hotkey, ~$%A_LoopField% UP, ~$%A_LoopField% UP, On
}
Loop
{
; added M to input to capture the CTRL-A through CTRL-Z, problem now is that those will generate ASCII characters, so we need to be transcribed
Input, text, M V L1, {LWin}{BS}{RWin}{AppsKey}{F1}{F2}{F3}{F4}{F5}{F6}{F7}{F8}{F9}{F10}{F11}{F12}{Left}{Right}{Up}{Down}{Home}{End}{PgUp}{PgDn}{Del}{Ins}{Capslock}{Numlock}{PrintScreen}{Pause}{Escape}
if ctrl_list contains %text%	; this checks if the input was a ctrl-combination, though ctrl-J seems to be equal to {enter}
{
	outputdebug %text% is a ctrl-combination
}
IfInString, ErrorLevel, EndKey
{
   StringTrimLeft, ErrorLevel, ErrorLevel,7
   If (ErrorLevel != "Pause")
     script := script text "{" ErrorLevel "}" 
   else if (ErrorLevel = "Pause")
   {
      script := script text
      MsgBox %script%
      Tooltip
      break
   }
   ToolTip, %script%
   continue
}
   script := script text
   ToolTip, %script%
}
return

~$shift:: script := addMod("shift","down",script)
~$shift UP:: script := addMod("shift","up",script)
~$control:: script := addMod("control","down",script)
~$control UP:: script := addMod("control","up",script)
~$alt:: script := addMod("alt","down",script)
~$alt UP:: script := addMod("alt","up",script)
}


addMod(mod,dir,script)
{
	global ; "global" so mod_old and dir_old are remembered between calls to this function
	if(mod = mod_old) and (dir = dir_old)	; this is to prevent {shiftdown}{shiftdown}{shiftdown}{shiftdown}etc
		return script
	else
	{
		mod_old := mod
		dir_old := dir
	}
	script := script "{" mod dir "}"
	Tooltip, %script%
	return script
}

Transcribe_ASCII:
	alphabet = a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z
	loop, parse, alphabet, `,
	{
		Transform, Ctrl%A_LoopField%, Chr, %A_Index% ; Store the character for Ctrl-letter in the Ctrl_ var.
		ctrl_list .= Ctrl%A_LoopField%				; to match the text-variable against
	}
	outputdebug > %ctrl_list%
return