AHK COM Passing Variable through File Path when saving - com

I would like the file to save as using the variable STYLE which the user enters at the beginning.
I also need help sending the data to a printer with variable amount of copies.
From here on is where I need help:
ComObjActive("Word.Application").ActiveDocument.SaveAs("L:\10. 2016\TKT Issued\"%Style%")
Please look at the below code for what I already have.
#NoEnv ; Recommended for performance and compatibility with future AutoHotkey releases.
; #Warn ; Enable warnings to assist with detecting common errors.
SendMode Input ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir% ; Ensures a consistent starting directory.
F12::
Gui, Add, Text,, Please enter Style:
Gui, Add, Edit, vStyle
Gui, Add, Text,, Please enter Price:
Gui, Add, Edit, vPrice
Gui, Add, Text,, Please enter Docket Number:
Gui, Add, Edit, vDocket
Gui, Add, Text,, Please enter Page Quantity:
Gui, Add, Edit, vPages
Gui, Add, Button, default, OK
Gui, Show,, Cutting Ticket Producer
return
GuiClose:
ButtonOK:
Gui, Submit
MsgBox You entered Style: %Style%, Price: %Price%, Docket Number: %Docket% and%Pages% Pages. Data will be sent to printer.
MSWordMultiReplace("STYLE",Style, "PRICE", Price, "DKT", Docket)
MSWordMultiReplace(params*) { ; by Learning one
oWord := ComObjCreate("Word.Application")
a:="L:\10. 2016\TKT Issued\TEMPLATE.doc"
oWord.Documents.Open(a)
oWord.Selection.Find.ClearFormatting
oWord.Selection.Find.Replacement.ClearFormatting
For k,v in Params
{
c++
if (c = 1)
{
st := v
continue
}
rt := v, c := 0
oWord.Selection.Find.Execute(st, 0, 0, 0, 0, 0, 1, 1, 0, rt, 2)
}
ComObjActive("Word.Application").ActiveDocument.SaveAs("L:\10. 2016\TKT Issued\"%Style%")
ExitApp
}
Reload

Try:
#NoEnv ; Recommended for performance and compatibility with future AutoHotkey releases.
; #Warn ; Enable warnings to assist with detecting common errors.
SendMode Input ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir% ; Ensures a consistent starting directory.
F12::
Gui, Add, Text,, Please enter Style:
Gui, Add, Edit, vStyle
Gui, Add, Text,, Please enter Price:
Gui, Add, Edit, vPrice
Gui, Add, Text,, Please enter Docket Number:
Gui, Add, Edit, vDocket
Gui, Add, Text,, Please enter Page Quantity:
Gui, Add, Edit, vPages
Gui, Add, Button, default, OK
Gui, Show,, Cutting Ticket Producer
return
GuiClose:
ButtonOK:
Gui, Submit
MsgBox You entered Style: %Style%, Price: %Price%, Docket Number: %Docket% and%Pages% Pages. Data will be sent to printer.
MSWordMultiReplace("STYLE",Style, "PRICE", Price, "DKT", Docket)
MSWordMultiReplace(params*) { ; by Learning one
oWord := ComObjCreate("Word.Application")
a:="L:\10. 2016\TKT Issued\TEMPLATE.doc"
oWord.Documents.Open(a)
oWord.Selection.Find.ClearFormatting
oWord.Selection.Find.Replacement.ClearFormatting
For k,v in Params
{
c++
if (c = 1)
{
st := v
continue
}
if (k == 2)
Style := v
rt := v, c := 0
oWord.Selection.Find.Execute(st, 0, 0, 0, 0, 0, 1, 1, 0, rt, 2)
}
oWord.ActiveDocument.SaveAs("L:\10. 2016\TKT Issued\" Style)
ExitApp
}
Reload

You cannot access the Style variable directly. You have to get it as the second parameter you have passed. See the below code,
For k,v in params
{
if (k = 2)
{
fileloc = L:\10. 2016\TKT Issued\%v%
ComObjActive("Word.Application").ActiveDocument.SaveAs(fileloc)
}
}
this worked for me

Related

I want a simple program to freeze/unfreeze input when I press a key

This seems like such a simple thing, yet I can't find it anywhere. I want a simple program (like AutoHotkey, but I can't find a way to do it with AutoHotkey) that will freeze my keyboard and mouse (whatever I'm pressing at the time keeps being pressed, even if I release the actual key/button) when I press a certain key, and keep it frozen until I press that key again (with the chosen key never being considered pressed by other programs).
I just want this so that if a game expects me to hold down some buttons, I can press the buttons, press the designated key, let go, then press the key again when I'm supposed to release the buttons.
This works in text editors. Not sure how it will work in games though.
#NoEnv
#Warn
#SingleInstance Force
#UseHook
SetWorkingDir %A_ScriptDir%
SendMode Input
Global isHold := false ; Alternates between "true" and "false" at each "LShift" press.
; Hotkey below will only be active if the game's window is active
#IfWinActive "PutYourGameWindowTitleHere"
; Sends {LShift Down} if isHold == false, {LShift Up} if isHold == true
; Asterisk means it will work even if other keys are held at the same time.
*LShift::Send % (isHold := !isHold) ? "{LShift Down}" : "{LShift Up}"
#IfWinActive
Update: Again, testing this in games you will have to do yourself.
#NoEnv
#Warn
#SingleInstance Force
#UseHook
SetWorkingDir %A_ScriptDir%
SendMode Input
Global aKeysToFreeze := { LShift: false, a: false }, isFreezeOn := false
`::fToggleFreeze()
^`:: ; You can use this to check the logical state of the key
If GetKeyState("a")
msgbox Key is pressed.
else msgbox Key is not pressed.
return
fToggleFreeze() {
Local
Global aKeysToFreeze, isFreezeOn
If isFreezeOn { ; If there are frozen keys,
For sKeyName, isKeyFrozen in aKeysToFreeze {
Send % "{" sKeyName " Up}" ; send key up event for each key and
aKeysToFreeze[sKeyName] := false ; set the each key's frozen state to false
}
} else {
For sKeyName, isKeyFrozen in aKeysToFreeze
If GetKeyState(sKeyName, "P") ; If the key is physically pressed
aKeysToFreeze[sKeyName] := true ; set frozen state to true
}
isFreezeOn := !isFreezeOn ; Frozen mode toggle
}
*a::Send {Blind}{a DownR}
*LShift:: Send {Blind}{LShift DownR}
#If !aKeysToFreeze["a"] ; If the key is frozen, the key up hotkey is blocked
*a Up::Send {Blind}{a Up}
#If !aKeysToFreeze["LShift"]
*LShift Up::Send {Blind}{LShift Up}
#If

AutoIt Automation - How To Simulate Human Like Cursor Movement

I wrote a question here on how to simulate human-like cursor movement with Selenium Web Driver and Java.
On this quest, I discovered that Selenium Web Driver might not be the best fit. It can't move the cursor directly. Or be able to in the fashion I need.
I don't need to physically move the mouse. Just as long as the website thinks the cursor is moving normally.
I have learned about AutoIt automation and have built some scripts. I built a script to automate the Key Strokes I require when uploading a photo. I had the idea to write the file path I need to upload to a .txt file. This is done in my Java App. Then when I call my AutoIt .exe file from Java. It then reads the .txt file. Gets the file path URL. It then does the operations necessary to paste the file path. Then click the "Open" button to upload the file to the website.
Following on from this, I could save coordinates on where I want the mouse to go. In a .txt file. Then when I fire the .exe AutoIt file. It reads this .txt file and does the "human-like" mouse behavior.
I just need to know how to simulate real mouse/cursor movement in AutoIt? A function I can give some coordinates to.
I saw an article on doing in this CSS and JS... This should give you a good idea.
Can anybody help? or offer any advice? Thank you.
Thanks to a comment made on my question. That linked to a script. It works amazingly!
It produces nonlinear mouse movements better than I ever imagined :)
; Smoother Mouse Move
; by the DtTvB
; Ease in function
func __calci1($i, $sm)
return $i ^ $sm;
endFunc
; Ease out function
func __calci2($i, $sm)
return 1 - ((1 - $i) ^ $sm);
endFunc
; Ease in out function
func __calci($i, $sm)
if ($i < 0.5) then
return __calci1($i * 2, $sm) / 2;
else
return (__calci2(($i - 0.5) * 2, $sm) / 2) + 0.5;
endIf
endFunc
; Ease backward function
func __calof($i, $sm)
if ($i < 0.5) then
return __calci($i * 2, $sm);
else
return __calci((1 - $i) * 2, $sm);
endIf
endfunc
; MAIN FUNCTION
func mouseMove2($x2, $y2)
$x1 = mouseGetPos(0);
$y1 = mouseGetPos(1);
$xv = random(-100, 100);
$yv = random(-100, 100);
$sm = random(1.5, 2.5);
$m = random(50, 160);
for $i = 0 to $m
$ci = __calci($i / $m, $sm);
$co = __calof($i / $m, $sm);
$cx = $x1 + (($x2 - $x1) * $ci) + ($xv * $co);
$cy = $y1 + (($y2 - $y1) * $ci) + ($yv * $co);
mouseMove ($cx, $cy, 1);
next
endFunc
; Test Script
mouseMove2 (512, 386);

Priority when 2 keys are pressed at the same time - script for a game

Basically, I want it so that when I have 2 keys pressed together (both A and D, specifically), the last key pressed should have priority, and the key before that should be "suppressed" (no input).
For example: in a game, when you press A, your character moves to the left, and when you press D, he moves to the right.
Pressing those 2 keys together makes the character stop.
Now the thing here is that I don't want the character to stop, I want him to continue to move, based on the last key I pressed, even though I'm holding 2 keys at the same time.
I thought this was going to be a trivial task but I actually got a little overwhelmed after trying to learn how to implement this (I'm a noob, sorry :C ), so I came here looking for some help on how to do this on AHK or any easy to compile scripting language that directly changes the input of a key. I'm not trying to modify or create a game, so a script that remaps those keys is enough!
Autohotkey example, following your "A and D, specifically" question:
for k,v in StrSplit("ad")
Hotkey, % "~$" v,Silveirous
Silveirous:
t:=SubStr(A_PriorHotkey,3)
if GetKeyState(t) and (A_ThisHotkey!=A_PriorHotkey)
Send {%t% up}
return
Documentation:
for k,v in, StrSplit(), Hotkey,,,, "~$", SubStr(), A_Prior/ThisHotkey, if, GetKeyState(), t:=... and ... !=, Send {%t% up}
Edit:
Another solution, made to be working as explained in OP's edit/comment:
#If GetKeyState("d","p")
~a::Send {d up}
~a up::Send {d down}
#If GetKeyState("a","p")
~d::Send {a up}
~d up::Send {a down}
#If
Make sure to mind the difference between #If and if (expression) usage cases.
I'm too late but this could help someone in future :)
Basically you need a variable to keep track of which direction the character faced first and act according to that. A code example could be:
let currentDir = 0;
let maxSpeed = (deltaTime * someConstant);
if (IsKeyDown(KEY_RIGHT) && IsKeyDown(KEY_LEFT))
{
if (currentDir == 1)
speed.x = -maxSpeed;
else if (currentDir == -1)
speed.x = maxSpeed;
}
else if (IsKeyDown(KEY_LEFT))
{
currentDir = -1;
speed.x = -maxSpeed;
}
else if (IsKeyDown(KEY_RIGHT))
{
currentDir = 1;
speed.x = maxSpeed;
}
else
{
speed.x = 0.0f;
currentDir = 0;
}
//And at last player's position would change every frame
player.x += speed.x;
Then when you press left while pressing right the character moves left without stopping and vice versa :)

Count the time from my last arrow key press

I was explained before on the forum how to program an autohotkey script to pause the script execution until alpha-numerical character has been entered, by using an input command:
Input, L, V L1 T2 ;wait until you start typing a letter and then proceed after the T2 pause
If (ErrorLevel = "Timeout") {
Send, {Tab 5}
Send, {Enter}
Return
}
I wonder if I can use Input or some other autohotkey command to do the same for non-alphanumerical keys, like arrow keys, or even key combinations. For example, I'd like for the script to count the time from my last arrow key press when I'm selecting an item from a drop-down list, and when the pre-set time threshold is passed to continue with the execution of the script.
EDIT:
Thanks to Blauhirn, the script works now the up and down keys are added :) (as long as the first key is typed in within the pre-set time period of two seconds in this example, notepad will be launched as soon as a pause of one second in typing is made)
!^+u::
Input, L, V L1 T2, {up} {down}
If (ErrorLevel = "Timeout") {
Send, {Esc}
Return
}
Loop { ;wait until you haven't typed an arrow key for 1seconds
Input, L, V L1 T1, {up} {down}
If (ErrorLevel = "Timeout")
Break
}
Run, %windir%\system32\notepad.exe
Return
If you state some EndKeys, the input will also terminate and ErrorLevel will be EndKey:name, thus not "Timeout".
Input, L, V L1 T2, {up}{down} ;wait until you start typing a letter -OR UP ARROW OR DOWN ARROW - and then proceed after the T2 pause
If (ErrorLevel = "Timeout") {
Send, {Tab 5}
Send, {Enter}
Return
}

Detect a double key press in AutoHotkey

I'd like to trigger an event in AutoHotkey when the user double "presses" the esc key. But let the escape keystroke go through to the app in focus if it's not a double press (say within the space of a second).
How would I go about doing this?
I've come up with this so far, but I can't work out how to check for the second escape key press:
~Esc::
Input, TextEntry1, L1 T1
endKey=%ErrorLevel%
if( endKey != "Timeout" )
{
; perform my double press operation
WinMinimize, A
}
return
Found the answer in the AutoHotkey documentation!
; Example #4: Detects when a key has been double-pressed (similar to double-click).
; KeyWait is used to stop the keyboard's auto-repeat feature from creating an unwanted
; double-press when you hold down the RControl key to modify another key. It does this by
; keeping the hotkey's thread running, which blocks the auto-repeats by relying upon
; #MaxThreadsPerHotkey being at its default setting of 1.
; Note: There is a more elaborate script to distinguish between single, double, and
; triple-presses at the bottom of the SetTimer page.
~RControl::
if (A_PriorHotkey <> "~RControl" or A_TimeSincePriorHotkey > 400)
{
; Too much time between presses, so this isn't a double-press.
KeyWait, RControl
return
}
MsgBox You double-pressed the right control key.
return
So for my case:
~Esc::
if (A_PriorHotkey <> "~Esc" or A_TimeSincePriorHotkey > 400)
{
; Too much time between presses, so this isn't a double-press.
KeyWait, Esc
return
}
WinMinimize, A
return
With the script above, i found out that the button i wanted to detect was being forwared to the program (i.e. the "~" prefix).
This seems to do the trick for me (i wanted to detect a double "d" press)
d::
keywait,d
keywait,d,d t0.5 ; Increase the "t" value for a longer timeout.
if errorlevel
{
; pretend that nothing happened and forward the single "d"
Send d
return
}
; A double "d" has been detected, act accordingly.
Send {Del}
return
Source