How can I get the handle of each monitor? I'll need to know which monitor handle corresponds to each physical monitor. I can find this if I also have the positions and numbers of each monitor. But I'm unable to even get the handles of the monitors.
I've read the documentation for EnumDisplayMonitors dozens of times, but nothing that I have tried will work.
I tried doing this:
oEnumDisplayMonitors := RegisterCallback("EnumMonitorsProc")
DllCall("EnumDisplayMonitors", "Ptr", 0, "Ptr", 0, "Ptr", oEnumDisplayMonitors, "Ptr", 0)
omh := oEnumDisplayMonitors.monitorHandle
h := oEnumDisplayMonitors.hdc
olpr := oEnumDisplayMonitors.lpRect
EnumMonitorsProc(monitorHandle, hdc, lpRect, lParam){
}
But the values for every argument to EnumMonitorsProc are all null.
I have also tried the following, following the example from this post: https://www.autohotkey.com/boards/viewtopic.php?f=6&t=4606
However, the script just aborts as soon as it makes the DllCall("EnumDisplayMonitors",...
Monitors := MDMF_Enum("")
For HMON, M In Monitors {
l := M.Left
t := M.Top
h := HMON
}
MDMF_Enum(HMON := "") {
Static EnumProc := RegisterCallback("MDMF_EnumProc")
Static Monitors := {}
If (HMON = "") ; new enumeration
Monitors := {}
If (Monitors.MaxIndex() = "") ; enumerate
DllCall("EnumDisplayMonitors", "Ptr", 0, "Ptr", 0, "Ptr", EnumProc, "Ptr", &Monitors, "UInt")
Return (HMON = "") ? Monitors : Monitors.HasKey(HMON) ? Monitors[HMON] : False
}
I need the handles for ALL monitors, not just for the active monitor or the primary monitor.
First we define the callback function that's going to be provided for the EnumDisplayMonitors function.
Callback_Func := RegisterCallback("MONITORENUMPROC")
This could be done in-line without creating an unnecessary variable as well.
Now that we've done that, we also of course need to create the MONITORENUMPROC function we're referring to:
MONITORENUMPROC(hMonitor, hDC, pRECT, data)
{
MsgBox, % hMonitor
return true
}
We're only interested in the handle, which is the first param. We can ignore everything else in this small example.
And we're returning true to indicate that we want to keep enumerating through the rest of the display monitors, assuming there are any. This was specified in the documentation for the callback function.
Ok, that's our callback function all done, now we want to call the EnumDisplayMonitors function and pass it that callback function so it can do its trick.
DllCall("EnumDisplayMonitors", Ptr, 0, Ptr, 0, Ptr, Callback_Func, Ptr, 0)
We're passing null (pointer 0 in AHK) to the first two parameters, as the documentation suggests if one wants to enumerate through all the available monitors.
For the 3rd parameter we pass our callback function's pointer, that's stored in our Callback_Func variable. (AHK's RegisterCallback function returns a pointer to our function).
And to the 4th parameter we just pass null again because we don't care about it in this small example. You could pass whatever data you wish through there, and it'd appear in the 4th parameter of our user-defined MONITORENUMPROC function (the one I named "data").
In the library you were looking at, they pass in a pointer to their own "Monitors" object. It's just a clever way they have of making the function have a double use.
So that's basically it. We print a messagebox for each monitor's handle.
Minimal example of how it works. Assuming you probably want to know which handle is which monitor, you can pass forward the handle to yet another function.
Such as the GetMonitorInfo function, exactly as they do in that library you were looking at.
And here's the example script I produced for you:
Callback_Func := RegisterCallback("MONITORENUMPROC")
DllCall("EnumDisplayMonitors", Ptr, 0, Ptr, 0, Ptr, Callback_Func, Ptr, 0)
MONITORENUMPROC(hMonitor, hDC, pRECT, data)
{
MsgBox, % hMonitor
return true
}
Related
I need to change the length of the array dynamically.Right now the code looks like this:
VAR
arrData : ARRAY[1..200] OF INT;
length : INT := 200;
END_VAR
The size of the array depends on the length variable.Here the value of length variable can be changed during runtime using the VISU(gui). So if I change the value of the length = 180 then 20 bytes of arrData are unused.Is there a way to declare the array as variable length similar to vectors in c++ such that the memory is not assigned during declaration but during runtime.
Edit:
How to deallocate the memory safely?
PROGRAM MAIN
VAR
arrData : POINTER TO INT;
length : INT := 200; // can be changed at runtime
bNew : BOOL := TRUE;
oldLength : INT; // to hold the old length variable
isInit : BOOL := FALSE;
END_VAR
IF NOT isInit THEN
oldLength := length; // initialise only once
isInit := TRUE;
END_IF
// if length is changed during runtime then delete the array
IF oldLength <> length THEN
IF arrData <> 0 THEN
__DELETE(arrData);
bNew := TRUE;
END_IF
oldLength := length;
END_IF
// during the first run or when the length is changed
IF bNew THEN
arrData := __NEW(INT,length);
bNew := FALSE;
END_IF
// deallocate the memory when the MAIN program goes out of scope
// as we are not deleting the array when the length variable is not
// changed during runtime
END_CASE
The way to do it is to use __NEW __NEW in Infosys
pMyPointer := __NEW(INT, length);
__NEW will return a pointer to first element of an array. You can access latter elements by offsetting this pointer.
You can check if length was changed by comparing value from this and previous cycle. If so, __DELETE the old array and initialize a new one.
Edit:
I think, that you get your error the moment TwinCAT runtime is stopped, as the momory allocated by __NEW is not freed at that point.
Your code should be placed not in a Program (PRG) but in a Function Block (FB). The reason for that is that you need to implement FB_exit method (This method is called implicitly when FB instance is destroyed, i.e. when stopping TwinCAT runtime like you do by activating configuration). There is no equivalent method for a PRG as far as I know.
To do this:
Create a new FB, instantiate it and call it in your MAIN and move your code from MAIN to the FB
Add a FB_exit method to this FB. Exact naming is crucial
In your FB_exit method write the following code:
IF __ISVALIDREF(arrData) THEN
__DELETE(arrData);
END_IF
This method will be called every time you stop your runtime and free the memory.
Links to Infosys:
__ISVALIDREF - equal to pMyPointer <> 0 but more readable
FB_exit
I have a function:
NormalRand(x,y,int=1) {
Loop 12
{
Random, var,0.0,1
Num+=var
}
norm := (int) ? Round((y+x)/2+((Num-6)*(y-x))/6) : (y+x)/2+((Num-6)*(y-x))/6
Return norm < x ? x : norm > y ? y : norm
}
I have an imagesearch:
ImageSearch, FoundX, FoundY, 0, 0, A_ScreenWidth, A_ScreenWidth, *50 Okay.jpg
If ErrorLevel = 0
{
xCord = NormalRand(%FoundX%-10,%FoundX%+10)
yCord = NormalRand(%FoundY%-10,%FoundY%+10)
MsgBox, 4,, Found the image at %xCord% %yCord%
Click, %xCord%, %yCord% Left, 1
Sleep, 2000
}
I am trying to use the NormalRand function to distribute my clicks around the buttons so they are harder to detect within the program I will use this with. However, when i try to sent the cords to the click it doens't work. When i test it with msgbox i get this output Found the image at NormalRand(391-10,391+10) NormalRand(676-10,676+10)
I can't seem to figure out how to get it to send the numbers instead of the text.
What we have here, is misuse, and probably also unintentional use, of the legacy syntax.
Lets look at these two lines:
xCord = NormalRand(%FoundX%-10,%FoundX%+10)
yCord = NormalRand(%FoundY%-10,%FoundY%+10)
You're actually assigning text to those variables, not calling a function.
See this as an example:
xCord = NormalRand(%FoundX%-10,%FoundX%+10)
yCord = NormalRand(%FoundY%-10,%FoundY%+10)
MsgBox, % xCord "`n" yCord
For legacy syntax you're referencing the FoundX and FoundY variables correctly by wrapping them around %, but you're not doing that for the function name.
So in legacy syntax you'd do this:
xCord = %NormalRand%(%FoundX%-10,%FoundX%+10)
yCord = %NormalRand%(%FoundY%-10,%FoundY%+10)
However, please stop using legacy syntax. It's so ancient, bad and very different compared to other programming languages you maybe have experienced.
Expression syntax is what you want to use, so instead of legacy =, we're using := to assign an expression to our variables. (= is never ever used!)
In expression syntax your function calls look normal and nice:
xCord := NormalRand(FoundX-10, FoundX+10)
yCord := NormalRand(FoundY-10, FoundY+10)
And to preach even more about legacy syntax, you're also using it on the if-statement. To not use the legacy if-statement, use if ().
I've tried to implement a t flip flop(I think this is what it's called) into my program but am having some issues with it. The idea is to have the program start and stop while using the same hotkey. This is what I have so far.
looping := false
pass = 0
max = 2
^r::
pass++
looping := true
while(looping = true AND pass < max)
{
Send, stack overflow, save me!
}
looping := false
pass = 0
return
When I run the program and hit the hotkey the while loop starts. However, when I attempt to break the loop by pressing ^r I get no response and the program keeps looping.
I think you are referring to a "toggle" script. I am not what sure you are trying to achieve exactly, but the key is using a logical not: looping := !true. More about it here.
looping := false
pass = 0
max = 2
^r::
pass++
looping := !true
while (looping & pass < max)
{
Send, stack overflow, save me!
}
pass = 0
return
There's a lot of resources for this, here are a few:
https://autohotkey.com/boards/viewtopic.php?t=11952
http://maul-esel.github.io/ahkbook/en/toggle-autofire.html
https://www.reddit.com/r/AutoHotkey/comments/6wqgbu/how_do_i_toggle_hold_down_a_key/dmad0xx
I'd like to know the proper way to reuse the []byte buffer in go. I declare it like this
buf := make([]byte, 1024)
and then use like this
conn, _ := net.Dial("tcp", addr)
_, err = conn.read(buf)
I heard that declaring a new buffer isn't efficient since it involves memory allocations and that we should reuse existing buffers instead. However I am not sure if I just can pass the buffer again and it will be wiped or it can hold parts of previous messages (especially if the current message from socket is shorter than prev.one)?
The Read method reads up to the len(buf) bytes to the buffer and returns the number of bytes read.
The Read method does not modify length of the caller's slice. It cannot because the slice is passed by value. The application must use the returned length to get a slice of the bytes actually read.
n, err = conn.Read(buf)
bufRead := buf[:n]
The application can call Read multiple times using the the same buffer.
conn, err := net.Dial("tcp", addr)
if err != nil {
// handle error
}
buf := make([]byte, 1024)
for {
n, err = conn.Read(buf)
if err != nil {
// handle error
}
fmt.Printf("Read %s\n", buf[:n]) // buf[:n] is slice of bytes read from conn
}
In practice you rarely use io.Reader.Read(), instead you pipe it down where io.Reader needed in code.
Buffer will not be wiped, you must do it by hand. Or if you want a buffer you can use bufio
conn, _ := net.Dial("tcp", addr)
r:=bufio.NewReader(conn)
which you can
r.WriteTo(io.Writer) //for example for further processing
and you can reset
r.Reset(NewConn)
Package io
import "io"
type Reader
type Reader interface {
Read(p []byte) (n int, err error)
}
Reader is the interface that wraps the basic Read method.
Read reads up to len(p) bytes into p. It returns the number of bytes
read (0 <= n <= len(p)) and any error encountered. Even if Read
returns n < len(p), it may use all of p as scratch space during the
call. If some data is available but not len(p) bytes, Read
conventionally returns what is available instead of waiting for more.
When Read encounters an error or end-of-file condition after
successfully reading n > 0 bytes, it returns the number of bytes read.
It may return the (non-nil) error from the same call or return the
error (and n == 0) from a subsequent call. An instance of this general
case is that a Reader returning a non-zero number of bytes at the end
of the input stream may return either err == EOF or err == nil. The
next Read should return 0, EOF.
Callers should always process the n > 0 bytes returned before
considering the error err. Doing so correctly handles I/O errors that
happen after reading some bytes and also both of the allowed EOF
behaviors.
Implementations of Read are discouraged from returning a zero byte
count with a nil error, except when len(p) == 0. Callers should treat
a return of 0 and nil as indicating that nothing happened; in
particular it does not indicate EOF.
Implementations must not retain p.
Read may use all of the buffer as scratch space during the call.
For example,
buf := make([]byte, 4096)
for {
n, err := r.Read(buf[:cap(buf)])
buf = buf[:n]
if err != nil {
// handle error
}
// process buf
}
I want to implement a method dim(x,y) which will assign spaces for a matrix(y rows, x cols).
I want to make "dim(x,y)" more powerful by passing an optional function 'filler' to it and then 'dim' will set the element located at (x,y) to filler(x,y)
my code goes as below:
List2D dim := method(x, y, z,
target := list()
filler := if(z == nil,
method(return nil),
z)
for(i, 1, y,
subTarget := list()
for(j, 1, x,
subTarget append( filler(i,j) ))
target append(subTarget) )
return target)
it worked well when 'dim' is called with 2 arguments,
but failed with
List2D dim(3,2, method(x,y, 10*x+y))
which throwed an exception at line filler := if(z == nil
The exception said nil does not respond to '*'
I realized the argument 'z' got activated undesirably when comparing with nil.
So I'm wondering how to get my 'List2D dim' work properly?
Alright so basically, you'll want something like this:
List2D dim := method(x, y,
target := list
blk := call evalArgAt(2) # Get the third argument, and evaluate it in the context of the sender
if(blk isNil, blk := block setScope(call sender))
for(i, 1, y,
subTarget := list
for(j, 1, x,
subTarget append(blk call(i, j))
target append(subTarget)
)
)
target
)
Basically, what's going on here is since your filler, you want to give it arguments, the easiest method is just to pass in a Block. You can do this with messages, but you in effect, end up setting up your own duplicate of Block anyway if you introduce a new scope, which you should. If the third argument evaluates to nil, then we'll just create a new function and set its scope to the calling context; as if the user had passed in an empty function, which has no argument arty and as such, you can pass arguments to it even if it doesn't define any parameters. The fact we scope it to the caller isn't really needed, but you should always scope blocks to the calling context if you're creating the blocks inside your method call. This will give access to the lexical scope of the calling context inside that block; which you're probably shoving some message the user has supplied in it. When ready, just call that method explicitly using the call method.
If your filler method didn't require any arguments, I'd just grab the raw message argument at the 2nd index, instead of evaluating it. This would yield some major performance improvements for some large matrices.