how to fix my AutoHotkey active window checker (fileappend) - windows

It is supposed to put an entry in a text file each time a new window is active, instead it constantly loops and puts thousands of entries while the window is active, if anyone is capable of rectifying this I would be grateful.
loop
{
if new_window = %window_title%
new_window = diff
else
{
WinGetActiveTitle, window_title
fileappend, %window_title%`n, C:\mydirectory\myname.txt
new_window = %window_title%
}
}
Any help able to be provided would be more than welcome.

This uses a timer to check for a new window every 0.5 seconds.
#Persistent
prev_window := ""
settimer, check_window, 500
return
check_window:
WinGetActiveTitle, active_window
if (active_window != prev_window) {
fileappend, %active_window%`n, myname.txt
prev_window := active_window
}
return
The same could be accomplished in a loop:
prev_window := ""
loop
{
WinGetActiveTitle, active_window
if (active_window != prev_window) {
fileappend, %active_window%`n, myname.txt
prev_window := active_window
}
sleep, 500
}
return

You should probably put a SetTimer that checks active window title in some time interval (100ms or something) and compare to previously checked window tile - and if it has changed then write to file.

Related

Pressing a key twice quickly to trigger a function in AutoHotKey

I want to bind 'jj' to Esc using AutoHotkey in my Rstudio application. Is there any way we can map 'jj' to trigger Escape in a selected windows application?
I found a solution, that worked.
#IfWinActive ahk_exe rstudio.exe
l::
{
count++
settimer, actions, 150
}
return
actions:
{
if (count = 1)
{
Send j
}
else if (count = 2)
{
Send {Esc}
}
count := 0
}
return

How to get starting time of a File Explorer window?

I'm building Autohotkey script in order to take a backup of opened File Explorer windows list.
I'm looking for a way in order to get starting time of each window (time when I've opened the window).
I've this function:
list_opened_folders(byref file_explorer_windows) {
; file_explorer_windows := [] ; array of file_explorer_windows
for window in ComObjCreate("Shell.Application").Windows {
file_explorer_windows[a_index] := {}
file_explorer_windows[a_index].path := window.Document.Folder.Self.Path
file_explorer_windows[a_index].id := window.HWND
file_explorer_windows[a_index].started_time := window.Document.Folder.Self.Time ; Line I'm trying to add (I know this is invalid but to illustrate my idea)
}
}
Try:
#Persistent
DetectHiddenWindows, On
SetTitleMatchMode, 2
file_explorer_windows := {}
SetTimer, GetExplorer, 100
GetExplorer:
Process, Exist, Explorer.exe
If ErrorLevel
{
for window in ComObjCreate("Shell.Application").Windows {
if (file_explorer_windows[window.HWND]["id"] == "") {
file_explorer_windows[window.HWND] := {id: window.HWND
, path: window.Document.Folder.Self.Path
, start: A_NowUTC}
}
}
}
Return

Super simple download with progress bar

Setting up an asynchronous download in AutoHotkey is a pain, but this is is necessary if you want to run some code during the download, like for example updating progress bar.
So the question is:
Is there a short and simple way of downloading a file with a progress bar, without including huge 1000+ lines libraries?
I came up with that code quite some time ago and you can still find it on the AHK forums, however, why not share it with the Stackoverflow community:
DownloadFile(UrlToFile, SaveFileAs, Overwrite := True, UseProgressBar := True, ExpectedFileSize := 0) {
;Check if the file already exists and if we must not overwrite it
If (!Overwrite && FileExist(SaveFileAs))
Return
;Check if the user wants a progressbar
If (UseProgressBar) {
;Initialize the WinHttpRequest Object
WebRequest := ComObjCreate("WinHttp.WinHttpRequest.5.1")
;Download the headers
WebRequest.Open("HEAD", UrlToFile)
WebRequest.Send()
try {
;Store the header which holds the file size in a variable:
FinalSize := WebRequest.GetResponseHeader("Content-Length")
} catch e {
; Cannot get "Content-Length" header
FinalSize := ExpectedFileSize
}
;Create the progressbar and the timer
Progress, , , Downloading..., %UrlToFile%
LastSizeTick := 0
LastSize := 0
; Enable progress bar updating if the system knows file size
SetTimer, __UpdateProgressBar, 1500
}
;Download the file
UrlDownloadToFile, %UrlToFile%, %SaveFileAs%
;Remove the timer and the progressbar because the download has finished
If (UseProgressBar) {
Progress, Off
SetTimer, __UpdateProgressBar, Off
}
Return
;The label that updates the progressbar
__UpdateProgressBar:
;Get the current filesize and tick
CurrentSize := FileOpen(SaveFileAs, "r").Length ;FileGetSize wouldn't return reliable results
CurrentSizeTick := A_TickCount
;Calculate the downloadspeed
SpeedOrig := Round((CurrentSize/1024-LastSize/1024)/((CurrentSizeTick-LastSizeTick)/1000))
SpeedUnit := "KB/s"
Speed := SpeedOrig
if (Speed > 1024) {
; Convert to megabytes
SpeedUnit := "MB/s"
Speed := Round(Speed/1024, 2)
}
SpeedText := Speed . " " . SpeedUnit
;Save the current filesize and tick for the next time
LastSizeTick := CurrentSizeTick
LastSize := FileOpen(SaveFileAs, "r").Length
if FinalSize = 0
{
PercentDone := 50
} else {
;Calculate percent done
PercentDone := Round(CurrentSize/FinalSize*100)
SpeedText := SpeedText . ", " . Round((FinalSize - CurrentSize) / SpeedOrig / 1024) . "s left"
}
;Update the ProgressBar
Progress, %PercentDone%, %PercentDone%`% (%SpeedText%), Downloading..., Downloading %SaveFileAs% (%PercentDone%`%)
Return
}
Here are some examples:
Example 1 - Download a firefox setup with a progressbar and overwrite it if it already exists on the disk:
DownloadFile("http://download-installer.cdn.mozilla.net/pub/firefox/releases/26.0/win32/en-US/Firefox%20Setup%2026.0.exe", "firefox_setup.exe")
Example 2 - Download Autohotkey with a progressbar and don't overwrite it if it already exists:
Url = http://ahkscript.org/download/ahk-install.exe
DownloadAs = AutoHotkey_L Installer.exe
Overwrite := False
UseProgressBar := True
DownloadFile(Url, DownloadAs, Overwrite, UseProgressBar)
Example 3 - Download a CCleaner setup and open a Save As dialog, asking the user where to save the file, overwriting it if already exists:
FileSelectFile, SaveAs, S, ccsetup410.exe
DownloadFile("http://download.piriform.com/ccsetup410.exe", SaveAs, True, True)

Determine length of time keys are pressed

Can below script be modified so that the keys
"cl" fires "www.google.com" just if the "cl" keys
are both pressed for 500 milliseconds ?
Reason for this is that as part typing text sometimes the keys "cl" are pressed in rapid succession which then fires "www.google.com"
~l::
If (GetKeyState("c","p") && GetKeyState("l","p")) {
Send, {Backspace Down}{Backspace Up}{Backspace Down}{Backspace Up}
Run, "www.google.com"
}
Return
Using A_TickCount may be a good option.
~l::
duration := 0
If (GetKeyState("c","p") && GetKeyState("l","p"))
{
start := A_TickCount
While (GetKeyState("c") && GetKeyState("l"))
Sleep, 1
duration := A_TickCount - start
}
if (duration > 500)
Run, "www.google.com"
Return
This appears to do the trick :
~c::
~l::
If (GetKeyState("c","p") && GetKeyState("l","p")) {
Send, {Backspace Down}{Backspace Up}{Backspace Down}{Backspace Up}
sleep, 100
If (GetKeyState("c","p") && GetKeyState("l","p")) {
Run, "www.google.com"
}
Return
}
Return
Per this AutoHotKey forum post:
[T]he only way to program a key down for a specific duration is to use the down command and then a wait function with a (manually entered time) and then the up command[.]
So, you could solve this problem by putting a timer and then another if block inside your current if block, although it sounds like a bad idea.
A 500 millisecond delay could cause uncontrolled key repetition sothat we can't reliably delete the pressed keys anymore. So my suggestion is to find the repeat delay and only wait for so long minus ~150 milliseconds:
~c::
~l::
If (GetKeyState("c","p") && GetKeyState("l","p")) {
If (!GetKeyState("c","p") || !GetKeyState("l","p"))
Return
DllCall("SystemParametersInfo", UInt, 0x16, UInt, 0, UIntP, RepeatDelay, UInt, 0) ;get the key repeat delay
Sleep % (RepeatDelay+1)*250-150
If (GetKeyState("c","p") && GetKeyState("l","p")) {
SendInput, {c up}{l up}{BS}{BS}
Run, www.google.com
}
}
Return
SystemParametersInfo - SPI_GETKEYBOARDDELAY

Looking for thread IDs in AutoHotkey

I thought the following code may work but did not. The reason probably lies in the fact that the Throw command is executed in the hotkey thread, not in the auto-execution section thread.
try
{
count := 0
loop {
tooltip % ++count
sleep 200
}
} catch {
}
msgbox done
Exitapp
Esc::ExitAPp
^1::throw
So is there a way to know to which thread the flow of control belongs? Does AutoHotkey have a variable for thread IDs or something similar to it?
The below code shows that the both (pseudo) threads return the same number. So I need to know the thread IDs within AutoHotkey if there are. I've read somewhere that an AutoHotkey thread is merely a function call. But I'm expecting that there might be a way to identify the pseudo threads.
try
{
count := 0
loop {
tooltip % ++count "`nThread ID: " DllCall("GetWindowThreadProcessId", "Int", A_ScriptHwnd, "Int", "0")
sleep 200
}
} catch {
}
msgbox done
Exitapp
Esc::ExitAPp
^1::
MsgBox, % DllCall("GetWindowThreadProcessId", "Int", A_ScriptHwnd, "Int", "0")
throw
Return
Is this what you are looking for?
^w::
WinGet, WinID,, A
ThreadID:=DllCall("GetWindowThreadProcessId", "Int", WinID, "Int", "0")
MsgBox, %ThreadID%
Return

Resources