Why doesn't timer treat global variable correctly? - autohotkey

This continuously sends t:
myVar := true
SetTimer, myLoop, 0
myLoop(){
if (true) {
Send, {t down}
}
}
#Persistent
But this does nothing:
myVar := true
SetTimer, myLoop, 0
myLoop(){
if (myVar) {
Send, {t down}
}
}
#Persistent
Why? myVar and true both evaluate to true so I don't understand why it's different.

myVar := true should be:
global myVar := true
Because a global must explicitly be declared as such.

Related

Total Pages of Active Foxit Window using Autohotkey

I've searched the site to make sure my question wasn’t already answered.
My problem is I'm trying to find the total number of pages that an open PDF file contains.
I'm able to find the total number of pages if I know the file path. So that means, my problem comes down to, me not knowing how to find the file path of an open window of an (active) PDF file.
I'd like to do all this in Autohotkey and my pdf reader is Foxit PhantomPDF. I have been able to do this for Adobe Acrobat in the past, but I guess Foxit Phantom isn't as popular so I wasn't able to find a solution.
Any help would be appreciated.
Here's the code I have so far
Description of code: So if I put the file in a specific place, I can find the total page numbers by pressing F1. (Half of what I need)
F1::
pdfPath := "C:\20yorkcondofin.pdf"
VarSetCapacity(GUID, 16)
DllCall("ole32\CLSIDFromString", "wstr", IID_RandomAccessStream := "{905A0FE1-BC53-11DF-8C49-001E4FC686DA}", "ptr", &GUID)
DllCall("ShCore\CreateRandomAccessStreamOnFile", "wstr", pdfPath, "uint", Read := 0, "ptr", &GUID, "ptr*", IRandomAccessStream)
CreateClass("Windows.Data.Pdf.PdfDocument", IPdfDocumentStatics := "{433A0B5F-C007-4788-90F2-08143D922599}", PdfDocumentStatics)
DllCall(NumGet(NumGet(PdfDocumentStatics+0)+8*A_PtrSize), "ptr", PdfDocumentStatics, "ptr", IRandomAccessStream, "ptr*", PdfDocument) ; LoadFromStreamAsync
WaitForAsync(PdfDocument)
DllCall(NumGet(NumGet(PdfDocument+0)+7*A_PtrSize), "ptr", PdfDocument, "uint*", PageCount) ; get_PageCount
ObjReleaseClose(IRandomAccessStream)
ObjReleaseClose(PdfDocumentStatics)
ObjReleaseClose(PdfDocument)
msgbox % PageCount
return
CreateClass(string, interface := "", ByRef Class := "")
{
CreateHString(string, hString)
if (interface = "")
result := DllCall("Combase.dll\RoActivateInstance", "ptr", hString, "ptr*", Class, "uint")
else
{
VarSetCapacity(GUID, 16)
DllCall("ole32\CLSIDFromString", "wstr", interface, "ptr", &GUID)
result := DllCall("Combase.dll\RoGetActivationFactory", "ptr", hString, "ptr", &GUID, "ptr*", Class, "uint")
}
if (result != 0)
{
if (result = 0x80004002)
msgbox No such interface supported
else if (result = 0x80040154)
msgbox Class not registered
else
msgbox error: %result%
ExitApp
}
DeleteHString(hString)
}
CreateHString(string, ByRef hString)
{
DllCall("Combase.dll\WindowsCreateString", "wstr", string, "uint", StrLen(string), "ptr*", hString)
}
DeleteHString(hString)
{
DllCall("Combase.dll\WindowsDeleteString", "ptr", hString)
}
WaitForAsync(ByRef Object)
{
AsyncInfo := ComObjQuery(Object, IAsyncInfo := "{00000036-0000-0000-C000-000000000046}")
loop
{
DllCall(NumGet(NumGet(AsyncInfo+0)+7*A_PtrSize), "ptr", AsyncInfo, "uint*", status) ; IAsyncInfo.Status
if (status != 0)
{
if (status != 1)
{
DllCall(NumGet(NumGet(AsyncInfo+0)+8*A_PtrSize), "ptr", AsyncInfo, "uint*", ErrorCode) ; IAsyncInfo.ErrorCode
msgbox AsyncInfo status error: %ErrorCode%
ExitApp
}
ObjRelease(AsyncInfo)
break
}
sleep 10
}
DllCall(NumGet(NumGet(Object+0)+8*A_PtrSize), "ptr", Object, "ptr*", ObjectResult) ; GetResults
ObjReleaseClose(Object)
Object := ObjectResult
}
ObjReleaseClose(ByRef Object)
{
if Object
{
if (Close := ComObjQuery(Object, IClosable := "{30D5A829-7FA4-4026-83BB-D75BAE4EA99E}"))
{
DllCall(NumGet(NumGet(Close+0)+6*A_PtrSize), "ptr", Close) ; Close
ObjRelease(Close)
}
ObjRelease(Object)
}
Object := ""
}
return

Autohotkey give a change only in specific language

#If !(langID = "EN")
:?:ign::ing
#If
I've tried to make an English filter with AutoHotKey but which is not apply on other languages.
I tested to indicate LangID = 0x0409 / langID = 0000409 but no works, how to make this to work?
Try
#If !(GetKeyboardLanguage(WinActive("A")) = 0x0409) ; English ; "!" means "NOT"
:?:ign::ing
#If
GetKeyboardLanguage(_hWnd=0){
if !_hWnd
ThreadId=0
else
if !ThreadId := DllCall("user32.dll\GetWindowThreadProcessId", "Ptr", _hWnd, "UInt", 0, "UInt")
return false
if !KBLayout := DllCall("user32.dll\GetKeyboardLayout", "UInt", ThreadId, "UInt")
return false
return KBLayout & 0xFFFF
}
https://autohotkey.com/board/topic/116538-detect-which-language-is-currently-on/#entry672236

What is the correct use of select statement in Go?

Good Day everyone
I have been learning the fundaments of go and how to use its channel-based concurrency paradigm.
However, while playing with some code I wrote focusing on the select statement I found a strange behavior:
func main() {
even := make(chan int)
odd := make(chan int)
quit := make(chan bool)
//send
go send(even, odd, quit)
//receive
receive(even, odd, quit)
fmt.Println("Exiting")
}
func send(e, o chan<- int, q chan<- bool) {
for i := 0; i < 100; i++ {
if i%2 == 0 {
e <- i
} else {
o <- i
}
}
close(e)
close(o)
q <- true
close(q)
}
func receive(e, o <-chan int, q <-chan bool) {
for cont, i := true, 0; cont; i++ {
fmt.Println("value of i", i, cont)
select {
case v := <-e:
fmt.Println("From even channel:", v)
case v := <-o:
fmt.Println("from odd channel:", v)
case v := <-q:
fmt.Println("Got exit message", v)
// return // have also tried this instead
cont = false
}
}
}
when I run this simple program sometimes the i accumulator ends up with more than a 100 being printed to the console, and instead of finishing up with a "from odd channel: 99", the for loop continues on outputting one or more zeroes from even/odd channels randomly, as if the quit channel's message was being somewhat being delayed onto its case and instead the odd/even channels were sending more integers thus quitting the for loop not exactly after the odd/even channels have been closed.
value of i 97 true
from odd channel: 97
value of i 98 true
From even channel: 98
value of i 99 true
from odd channel: 99
value of i 100 true
From even channel: 0
value of i 101 true
From even channel: 0
value of i 102 true
from odd channel: 0
value of i 103 true
From even channel: 0
value of i 104 true
Got exit message true
Exiting
I have tried to search for the correct use of the case statement but I haven´t been able to find the problem with my code.
It seems like the same behavior can be reproduced on the go playground: my code
thanks for your attention put on my question.
The program is printing 0 because receive on a closed channel returns the zero value. Here's one way to accomplish your goal.
First, eliminate the q channel. Closing the o and e channels is sufficient to indicate that the sender is done.
func send(e, o chan<- int, q chan<- bool) {
for i := 0; i < 100; i++ {
if i%2 == 0 {
e <- i
} else {
o <- i
}
}
close(e)
close(o)
}
When receiving values, use the two value receive to detect when the zero value is returned because the channel is closed. Set the channel to nil when the channel is closed. Receive on a nil channel does not yield a value. Loop until both channels are nil.
func receive(e, o <-chan int, q <-chan bool) {
for e != nil && o != nil {
select {
case v, ok := <-e:
if !ok {
e = nil
continue
}
fmt.Println("From even channel:", v)
case v, ok := <-o:
if !ok {
o = nil
continue
}
fmt.Println("From odd channel:", v)
}
}
}
playground example

Autohotkey write text read from a text file

I want my script to read a textfile containing an intiger and to write this number by keyboard with out me actually touching it, but im kinda having trouble understanding the autohotkey since there is no software for it. Having some C# knowledge this is what i have:
FileRead, OutputVar, answertext.txt
sleep, 3000
;MyString = %OutputVar%
MyString = 16807
Loop, Parse, MyString
{
if (%A_LoopField% = -)
{
Send, {SC00C}
}
if (%A_LoopField% = 0)
{
Send, {SC00B}
}
if (%A_LoopField% = 1)
{
Send, {SC002}
}
if (%A_LoopField% = 2)
{
Send, {SC003}
}
if (%A_LoopField% = 3)
{
Send, {SC004}
}
if (%A_LoopField% = 4)
{
Send, {SC005}
}
if (%A_LoopField% = 5)
{
Send, {SC006}
}
if (%A_LoopField% = 6)
{
Send, {SC007}
}
if (%A_LoopField% = 7)
{
Send, {SC008}
}
if (%A_LoopField% = 8)
{
Send, {SC009}
}
if (%A_LoopField% = 9)
{
Send, {SC00A}
}
}
exit
Now this code starts but it always punches in 0 and nothing else, and if MyString = -1234, there is an error.
I will provide here some notes on improving your AutoHotkey script, and an amended version of it.
Your 'if' lines should be like this for most strings, with double quotes, and no percent signs:
if (A_LoopField = "a")
With numbers the double quotes are optional:
if (A_LoopField = "1")
if (A_LoopField = 1)
However fundamentally, your script need only be a few lines long:
FileRead, OutputVar, answertext.txt
sleep, 3000
;MyString = %OutputVar%
MyString = 16807
Send {Raw}%MyString%
You may prefer to include a key delay, to slow down the sending of text:
MyString = 16807
SetKeyDelay, 500
Send {Raw}%MyString%
Other methods for sending the text might be:
Clipboard := MyString
SendInput ^v
Or to insert text into Edit controls such as in Notepad for example without using the clipboard:
Control, EditPaste, %MyString%, Edit1, ahk_class Notepad
Or to set the entire contents of Edit controls, again without using the clipboard:
ControlSetText, Edit1, %vText%, ahk_class Notepad

Does a break statement break from a switch/select?

I know that switch/select statements break automatically after every case. I am wondering, in the following code:
for {
switch sometest() {
case 0:
dosomething()
case 1:
break
default:
dosomethingelse()
}
}
Does the break statement exit the for loop or just the switch block?
Break statements, The Go Programming Language Specification.
A "break" statement terminates execution of the innermost "for",
"switch" or "select" statement.
BreakStmt = "break" [ Label ] .
If there is a label, it must be that of an enclosing "for", "switch"
or "select" statement, and that is the one whose execution terminates
(§For statements, §Switch statements, §Select statements).
L:
for i < n {
switch i {
case 5:
break L
}
}
Therefore, the break statement in your example terminates the switch statement, the "innermost" statement.
A hopefully illustrative example:
loop:
for {
switch expr {
case foo:
if condA {
doA()
break // like 'goto A'
}
if condB {
doB()
break loop // like 'goto B'
}
doC()
case bar:
// ...
}
A:
doX()
// ...
}
B:
doY()
// ....
Yes, break breaks the inner switch.
https://play.golang.org/p/SZdDuVjic4
package main
import "fmt"
func main() {
myloop:
for x := 0; x < 7; x++ {
fmt.Printf("%d", x)
switch {
case x == 1:
fmt.Println("start")
case x == 5:
fmt.Println("stop")
break myloop
case x > 2:
fmt.Println("crunching..")
break
default:
fmt.Println("idling..")
}
}
}
0idling..
1start
2idling..
3crunching..
4crunching..
5stop
Program exited.
This question might be too old already but I still think label makes our code become harder to read.
Instead of breaking the for inside select, just set a flag for the loop and handle it inside select-case before invoking break.
For example:
loop := true
for loop {
select {
case <-msg:
// do your task here
case <-ctx.Done():
loop = false
break
}
}
Updated: Totally agree with Vaelin in the comment. Declaring that flag inside the scope of the for loop can avoid memory leak and conflict with other variables in current scope, just in case we have a same variable name already.
for loop := true; loop; {
}
Just from a switch block. There's plenty of examples in Golang own code you can examine (compare inner break with outer break).
this should explain it.
for{
x := 1
switch {
case x >0:
fmt.Println("sjus")
case x == 1:
fmt.Println("GFVjk")
default:
fmt.Println("daslkjh")
}
}
}
Runs forever
for{
x := 1
switch {
case x >0:
fmt.Println("sjus")
break
case x == 1:
fmt.Println("GFVjk")
default:
fmt.Println("daslkjh")
}
}
}
Again, runs forever
BUT
package main
import "fmt"
func main() {
d:
for{
x := 1
switch {
case x >0:
fmt.Println("sjus")
break d
case x == 1:
fmt.Println("GFVjk")
default:
fmt.Println("daslkjh")
}
}
}
will print sjus
... clear ?
http://play.golang.org/p/GOvnfI67ih
It only exits the switch block.