Autoit get CPU temp and put it into a graph - graph

This is the code i have so far:
#RequireAdmin
#include <GUIConstants.au3>
$wbemFlagReturnImmediately = 0x10
$wbemFlagForwardOnly = 0x20
$strComputer = "."
$objWMIService = ObjGet("winmgmts:\\" & $strComputer & "\root\wmi")
$Instances = $objWMIService.InstancesOf("MSAcpi_ThermalZoneTemperature")
For $Item in $Instances
$temp=($Item.CurrentTemperature - 2732) / 10
Next
Opt("GUIOnEventMode", 1)
GUICreate("", 340, 330)
GUISetOnEvent($GUI_EVENT_CLOSE,"close")
$GraphWidth = 273
$GraphHeight = 273
$graph = GUICtrlCreateGraphic(48, 15, $GraphWidth, $GraphHeight)
GUICtrlSetBkColor(-1,0xFFFFFF)
GUICtrlSetColor(-1,0x000000)
$yMax = 100
$yMin = 0
$xMax = 100
$xMin = 0
GUICtrlCreateLabel($yMax,15,10,20,15,$SS_RIGHT)
GUICtrlCreateLabel($yMin,15,280,20,15,$SS_RIGHT)
GUICtrlCreateLabel($xMax,307,295,20,15,$SS_CENTER)
GUICtrlCreateLabel($xMin,38,295,20,15,$SS_CENTER)
GUICtrlCreateLabel("TEMP",10,120)
$tmp=GUICtrlCreateLabel($temp,20,140)
GUISetState()
while 1
sleep(10000)
$wbemFlagReturnImmediately = 0x10
$wbemFlagForwardOnly = 0x20
$strComputer = "."
$objWMIService = ObjGet("winmgmts:\\" & $strComputer & "\root\wmi")
$Instances = $objWMIService.InstancesOf("MSAcpi_ThermalZoneTemperature")
For $Item in $Instances
$temp=($Item.CurrentTemperature - 2732) / 10
Next
GUICtrlSetData($tmp, $temp)
WEnd
func close()
Exit
EndFunc
The code gets the CPU temperature and makes a graph. My questions is how do i put the temperature in to the graph and make it update every 10 seconds. Thanks for any help.

I have made this script using parts of your code, the getting of the temperature and creating and setting the event of it.
I have added the use of the library GraphGDIPlus.au3 which can be downloaded and put into your program files -> autoit -> include; link to GraphGDIPlus.
Here is the script (commented for understanding):
#RequireAdmin
#include <GraphGDIPlus.au3>
#include <GUIConstants.au3>
AdlibRegister("findTemp", 9000)
AdlibRegister("_Draw_Graph", 10000)
Local $hGUI, $hGraph, $temp, $Counter = 1, $iCheck, $msg, $xVal = 1
$hGUI = GUICreate("", 600, 350) ; create the GUI window
$iCheck = GUICtrlCreateCheckbox("Reset on next interval", 462, 1)
GUISetState() ; show the window
CreateGraph() ; create the graph
findTemp() ; find the temp
_Draw_Graph() ; draw the graph
While 1
$msg = GUIGetMsg()
Switch $msg
Case $GUI_EVENT_CLOSE
Quit()
EndSwitch
WEnd
Func CreateGraph()
If IsArray($hGraph) = 0 Then
$hGraph = _GraphGDIPlus_Create($hGUI, 37, 24, 545, 300, 0xFF000000, 0xFF88B3DD) ; create the graph
EndIf
If $Counter > 24 Then
_GraphGDIPlus_Set_RangeX($hGraph, $xVal, $Counter, 24)
$xVal += 1
Else
_GraphGDIPlus_Set_RangeX($hGraph, 0, 24, 24) ; set the x range from 0 - 24 putting all 24 ticks on screen
_GraphGDIPlus_Set_RangeY($hGraph, 0, 125, 5) ; set the y range from 0 - 125 only putting 5 ticks on screen
_GraphGDIPlus_Set_GridX($hGraph, 1, 0xFF6993BE) ; set the x grid
_GraphGDIPlus_Set_GridY($hGraph, 1, 0xFF6993BE) ; set the y grid
EndIf
EndFunc ;==>CreateGraph
Func _Draw_Graph()
Local $rCheckbox
$rCheckbox = GUICtrlRead($iCheck)
If $rCheckbox = 1 Then
ControlClick($hGUI, "Reset on next interval", $iCheck)
_GraphGDIPlus_Delete($hGUI, $hGraph) ; delete the graph
$Counter = 1 ; reset the counter
$xVal = 1 ; reset the x range counter
CreateGraph() ; and create the graph again
EndIf
If $Counter > 24 Then ; if we've reached the end
CreateGraph() ; and create the graph again
EndIf
_GraphGDIPlus_Set_PenColor($hGraph, 0xFF325D87) ; set the color of the line
_GraphGDIPlus_Set_PenSize($hGraph, 2) ; set the size of the line
_GraphGDIPlus_Plot_Start($hGraph, $Counter, 0) ; set the start on the graph plot
_GraphGDIPlus_Plot_Line($hGraph, $Counter, $temp) ; set the line ending
_GraphGDIPlus_Refresh($hGraph) ; draw it to the screen
$Counter += 1 ; add one to our counter
EndFunc ;==>_Draw_Graph
Func findTemp()
$wbemFlagReturnImmediately = 0x10
$wbemFlagForwardOnly = 0x20
$strComputer = "."
$objWMIService = ObjGet("winmgmts:\\" & $strComputer & "\root\wmi")
$Instances = $objWMIService.InstancesOf("MSAcpi_ThermalZoneTemperature")
For $Item In $Instances
$temp = ($Item.CurrentTemperature - 2732) / 10 ; set the temp
Next
EndFunc ;==>findTemp
Func Quit()
_GraphGDIPlus_Delete($hGUI, $hGraph) ; delete the graph
Exit ; get us out
EndFunc ;==>Quit

Related

What is the string compression algorithm?

I am reversing an old game for translate it, here is the compression algorithm , I want to know what algorithm this is.
the following is the python pseudocode
while True:
byte = rawdata[praw]
low_byte = byte & 0xF
high_byte = byte >> 4
for i in range(low_byte):
buffer[pbuffer] = rawdata[praw]
pbuffer += 1
praw += 1
for i in range(high_byte):
low_byte2 = rawdata[praw] & 0xF
high_byte2 = rawdata[praw] >> 4
p = pbuffer - low_byte - 1
for i in range(high_byte2):
buffer[pbuffer] = buffer[p]
pbuffer += 1
praw += 1
if low_byte or high_byte is 0, will call this function
def func(data):
# do...while...
while data is even number:
data = (data << 7) | rwadata[praw]
p += 1
if (data & 1) != 0:
break
return (data >> 1)

Octave: How can I plot unknown length serial data using the instrument-control package?

I found this example which sorta works... but it's not perfect. For starters it plots 10 at once but that's an easy fix. Problem is that it does not dynamically get line endings and instead relies on byte count.
pkg load instrument-control
s1 = serialport("/dev/ttyUSB0", 9600)
flush(s1);
y_temp = cell(10,1)
y = 0
while true
for i = 1:10
y_serial = str2num(char(fread(s1,8)))
y_temp {i,1} = y_serial
endfor
y = cat(1, y, y_temp{1:10})
plot(y)
pause(1)
endwhile
srl_close(s1)
This works... so long as the number of bytes per string is 8. How can I make this dynamic and split by line endings?
All I need to do is plot incrementing by 1 x_value and a float y_value from serial.
https://www.edn.com/read-serial-data-directly-into-octave/
Solution found.
Their is no inbuilt solution but you can make your own function like:
function [char_array] = ReadToTermination (srl_handle, term_char)
% parameter term_char is optional, if not specified
% then CR = 'r' = 13dec is the default.
if (nargin == 1)
term_char = 13;
end
not_terminated = true;
i = 1;
int_array = uint8(1);
while not_terminated
val = fread(srl_handle, 1);
if(val == term_char)
not_terminated = false;
end
% Add char received to array
int_array(i) = val;
i = i + 1;
end
% Change int array to a char array and return a string array
char_array = char(int_array);
endfunction
This does not actually work straight off and I had to add \n to my Arduino script.
disp('load instrument control:');
pkg load instrument-control
disp('SerialPort:');
serialportlist
cpx = serialport ("COM6", 57600);
disp(cpx);
disp(sprintf('InBuffer:%3d', cpx.NumBytesAvailable));
if (cpx.NumBytesAvailable > 0)
zx = read(cpx, cpx.NumBytesAvailable);
disp(sprintf("IN:\r\n%s", zx));
endif;

R randomforest package to Base SAS

Is there a way to take a randomforest built in R and convert it to SAS Code with out having to type out all the if then elses that getTree gives?
I had 30 trees that had 1900 lines in the getTree function
This is something I had lying around that should help get you started. So far only regression is supported, but classification should be do-able with a bit of extra work:
/* R code for exporting the randomForest object */
#Output dataset to csv for validation in SAS
write.csv(iris,file="C:/temp/iris.csv",row.names=FALSE)
#Train a 2-tree random forest for testing purposes
require(randomForest)
rf2 <- randomForest(iris[,-1],iris[,1],ntree=2)
# Get predictions and write to csv
write.csv(predict(rf2,iris),file="c:/temp/pred_rf2b.csv")
# Export factor levels
mydata <- iris
type <- sapply(mydata,class)
factors = type[type=="factor"]
output <- lapply(names(factors),function(x){
res <- data.frame(VarName=x,
Level=levels(mydata[,x]),
Number=1:nlevels(mydata[,x]))
return(res)
})
write.csv(do.call(rbind, output),file="c:/temp/factorlevels.csv", row.names=FALSE)
# Export all trees in one file
treeoutput <- lapply(1:rf2$ntree,function(x){
res <- getTree(rf2, x, labelVar=TRUE)
res$node <- seq.int(nrow(res))
res$treenum <- x
return(res)
})
write.csv(do.call(rbind, treeoutput),file="c:/temp/treeexport.csv", row.names=FALSE)
/*End of R code*/
/*Import into SAS, replacing . with _ so we have usable variable names*/
proc import
datafile = "c:\temp\treeexport.csv"
out = tree
dbms = csv
replace;
getnames = yes;
run;
data tree;
set tree;
SPLIT_VAR = translate(SPLIT_VAR,'_','.');
format SPLIT_POINT 8.3;
run;
proc import
datafile = "c:\temp\factorlevels.csv"
out = factorlevels
dbms = csv
replace;
getnames = yes;
run;
data _null_;
infile "c:\temp\iris.csv";
file "c:\temp\iris2.csv";
input;
if _n_ = 1 then _infile_=translate(_infile_,'_','.');
put _infile_;
run;
proc import
datafile = "c:\temp\iris2.csv"
out = iris
dbms = csv
replace;
getnames = yes;
run;
data _null_;
debug = 0;
type = "regression";
maxiterations = 10000;
file log;
if 0 then set tree factorlevels;
/*Hash to hold the whole tree*/
declare hash t(dataset:'tree');
rc = t.definekey('treenum');
rc = t.definekey('node');
rc = t.definedata(all:'yes');
rc = t.definedone();
/*Hash for looking up factor levels*/
declare hash fl(dataset:'factorlevels');
rc = fl.definekey('VARNAME','NUMBER');
rc = fl.definedata('LEVEL');
rc = fl.definedone();
do treenum = 1 by 1 while(t.find(key:treenum,key:1)=0);
/*Hash to hold the queue for current tree*/
length position qnode processed 8;
declare hash q(ordered:'a');
rc = q.definekey('position');
rc = q.definedata('qnode','position','processed');
rc = q.definedone();
declare hiter qi('q');
/*Hash for reverse queue lookup*/
declare hash q2();
rc = q2.definekey('qnode');
rc = q2.definedata('position');
rc = q2.definedone();
/*Load the starting node for the current tree*/
node = 1;
nodetype = 'L'; /*Track whether current node is a Left or Right node*/
complete = 0;
length treename $10;
treename = cats('tree',treenum);
do iteration = 1 by 1 while(complete = 0 and iteration <= maxiterations);
rc = t.find();
if debug then put "Processing node " node;
/*Logic for terminal nodes*/
if status = -1 then do;
if type ne "regression" then prediction = cats('"',prediction,'"');
put treename '=' prediction ';';
/*If current node is a right node, remove it from the queue*/
if nodetype = 'R' then do;
rc = q2.find();
if debug then put "Unqueueing node " qnode "in position " position;
processed = 1;
rc = q.replace();
end;
/*If the queue is empty, we are done*/
rc = qi.last();
do while(rc = 0 and processed = 1);
if position = 1 then complete = 1;
rc = qi.prev();
end;
/*Otherwise, process the most recently queued unprocessed node*/
if complete = 0 then do;
put "else ";
node = qnode;
nodetype = 'R';
end;
end;
/*Logic for split nodes - status ne -1*/
else do;
/*Add right_daughter to queue if present*/
position = q.num_items + 1;
qnode = right_daughter;
processed = 0;
rc = q.add();
rc = q2.add();
if debug then put "Queueing node " qnode "in position " position;
/*Check whether current split var is a (categorical) factor*/
rc = fl.find(key:split_var,key:1);
/*If yes, factor levels corresponding to 1s in the binary representation of the split point go left*/
if rc = 0 then do;
/*Get binary representation of split point (least significant bit first)*/
/*binaryw. format behaves very differently above width 58 - only 58 levels per factor supported here*/
/*This is sufficient as the R randomForest package only supports 53 levels per factor anyway*/
binarysplit = reverse(put(split_point,binary58.));
put 'if ' #;
j=0; /*Track how many levels have been encountered for this split var*/
do i = 1 to 64 while(rc = 0);
if i > 1 then rc = fl.find(key:split_var,key:i);
LEVEL = cats('"',LEVEL,'"');
if debug then put _all_;
if substr(binarysplit,i,1) = '1' then do;
if j > 0 then put ' or ' #;
put split_var ' = ' LEVEL #;
j + 1;
end;
end;
put 'then';
end;
/*If not, anything < split point goes to left child*/
else put "if " split_var "< " split_point 8.3 " then ";
if nodetype = 'R' then do;
qnode = node;
rc = q2.find();
if debug then put "Unqueueing node " qnode "in position " position;
processed = 1;
rc = q.replace();
end;
node = left_daughter;
nodetype = 'L';
end;
end;
/*End of tree function definition!*/
put ';';
/*Clear the queue between trees*/
rc = q.delete();
rc = q2.delete();
end;
/*We end up going 1 past the actual number of trees after the end of the do loop*/
treenum = treenum - 1;
if type = "regression" then do;
put 'RFprediction=(';
do i = 1 to treenum;
treename = cats('tree',i);
put treename +1 #;
if i < treenum then put '+' +1 #;
end;
put ')/' treenum ';';
end;
/*To do - write code to aggregate predictions from multiple trees for classification*/
stop;
run;
/*Sample of generated if-then-else code */
data predictions;
set iris;
if Petal_Length < 4.150 then
if Petal_Width < 1.050 then
if Petal_Width < 0.350 then
tree1 =4.91702127659574 ;
else
if Petal_Width < 0.450 then
tree1 =5.18333333333333 ;
else
if Species = "versicolor" then
tree1 =5.08888888888889 ;
else
tree1 =5.1 ;
else
if Sepal_Width < 2.550 then
tree1 =5.525 ;
else
if Petal_Length < 4.050 then
tree1 =5.8 ;
else
tree1 =5.63333333333333 ;
else
if Petal_Width < 1.950 then
if Sepal_Width < 3.050 then
if Species = "setosa" or Species = "virginica" then
if Petal_Length < 5.700 then
tree1 =6.05833333333333 ;
else
tree1 =7.2 ;
else
tree1 =6.176 ;
else
if Sepal_Width < 3.250 then
if Sepal_Width < 3.150 then
tree1 =6.62 ;
else
tree1 =6.66666666666667 ;
else
tree1 =6.3 ;
else
if Petal_Length < 6.050 then
if Petal_Width < 2.050 then
tree1 =6.275 ;
else
tree1 =6.65 ;
else
if Petal_Length < 6.550 then
tree1 =7.76666666666667 ;
else
tree1 =7.7 ;
;
if Petal_Width < 1.150 then
if Species = "setosa" then
tree2 =5.08947368421053 ;
else
tree2 =5.55714285714286 ;
else
if Species = "setosa" or Species = "versicolor" then
if Sepal_Width < 2.750 then
if Petal_Length < 4.450 then
tree2 =5.44 ;
else
tree2 =6.06666666666667 ;
else
if Petal_Width < 1.350 then
tree2 =5.85294117647059 ;
else
if Petal_Width < 1.750 then
if Petal_Width < 1.650 then
tree2 =6.3625 ;
else
tree2 =6.7 ;
else
tree2 =5.9 ;
else
if Petal_Length < 5.850 then
if Sepal_Width < 2.650 then
if Petal_Length < 4.750 then
tree2 =4.9 ;
else
if Sepal_Width < 2.350 then
tree2 =6 ;
else
if Sepal_Width < 2.550 then
tree2 =6.14 ;
else
tree2 =6.1 ;
else
tree2 =6.49166666666667 ;
else
if Petal_Length < 6.350 then
tree2 =7.125 ;
else
tree2 =7.775 ;
;
RFprediction=(
tree1 + tree2 )/2 ;
run;

Convert price values with decimals language neutral to an integer in ASP.NET

I want to convert decimal numbers (price values to be exact), which may:
a) contain 1 OR 2 decimals
b) have either a . or , as decimal separator
to an integer value in cents.
So:
3,5 becomes 350
3,50 becomes 350
3.5 becomes 350
3.50 becomes 350
1,000.34 becomes 100034
1.000,34 becomes 100034
Without building a function that does all these checks is there a way in ASP.NET to do this more quickly?
**UPDATE **
Thanks to Nicholas:
I now have this in VB.NET
Private Shared Function ConvertToPriceInCents(s As String) As Integer
If s Is Nothing Then
Throw New ArgumentNullException("s")
End If
If s = "" Then
Throw New ArgumentOutOfRangeException("s", "s must not be empty.")
End If
Dim priceInCents As Integer = 0
Dim scale As Integer = 1
Dim i As Integer = s.Length
' collect the fractional part; identify the decimal separator
While System.Threading.Interlocked.Decrement(i) >= 0
Dim n As Integer = Asc(s(i)) - Asc("0"c)
If n < 0 OrElse n > 9 Then
Exit While
End If
' bail out, we found the decimal separator
priceInCents += n * scale
scale *= 10
End While
Dim decimalSeparator As Char = s(i)
Dim groupSeparator As Char = If(decimalSeparator = "."c, ","c, "."c)
If scale <> 10 AndAlso scale <> 100 Then
Throw New FormatException("value must have 1 or 2 digits to the right of the decimal separator")
End If
If decimalSeparator <> ","c AndAlso decimalSeparator <> "."c Then
Throw New FormatException("Invalid decimal separator")
End If
' if we only found one digit to the right of the decimal separator,
' we need to normalize and scale up by a factor of 10 (so something like 3.5 represents 350 cents)
If scale = 10 Then
scale *= 10
priceInCents *= 10
End If
' get the integer portion of value
' we're being a little lax here and ignoring group separators regardless of position.
' It's a hard thing to do, especially when you consider that
' - group sizes vary across cultures, and
' - aren't necessarily uniform in size.
While System.Threading.Interlocked.Decrement(i) >= 0
Dim c As Char = s(i)
If c = groupSeparator Then
Continue While
End If
Dim n As Integer = Asc(s(i)) - Asc("0"c)
If n < 0 OrElse n > 9 Then
Throw New FormatException("invalid group separator")
End If
priceInCents += n * scale
scale *= 10
End While
' If we haven't thrown an exception yet,
' we have the value in cents: return it.
Return priceInCents
End Function
You write a method that looks something like this:
static int ConvertToPriceInCents( string s )
{
if ( s == null ) throw new ArgumentNullException("s") ;
if ( s == "" ) throw new ArgumentOutOfRangeException("s","s must not be empty." ) ;
int priceInCents = 0 ;
int scale = 1 ;
int i = s.Length ;
// collect the fractional part; identify the decimal separator
while ( --i >= 0 )
{
int n = s[i] - '0' ;
if ( n < 0 || n > 9 ) break ; // bail out, we found the decimal separator
priceInCents += n*scale ;
scale *= 10 ;
}
char decimalSeparator = s[i] ;
char groupSeparator = decimalSeparator == '.' ? ',' : '.' ;
if ( scale != 10 && scale != 100 ) throw new FormatException("value must have 1 or 2 digits to the right of the decimal separator") ;
if ( decimalSeparator != ',' && decimalSeparator != '.' ) throw new FormatException("Invalid decimal separator") ;
// if we only found one digit to the right of the decimal separator,
// we need to normalize and scale up by a factor of 10 (so something like 3.5 represents 350 cents)
if ( scale == 10 )
{
scale *= 10 ;
priceInCents *= 10 ;
}
// get the integer portion of value
// we're being a little lax here and ignoring group separators regardless of position.
// It's a hard thing to do, especially when you consider that
// - group sizes vary across cultures, and
// - aren't necessarily uniform in size.
while ( --i >= 0 )
{
char c = s[i] ;
if ( c == groupSeparator ) continue ;
int n = s[i] - '0' ;
if ( n < 0 || n > 9 ) throw new FormatException("invalid group separator") ;
priceInCents += n*scale ;
scale *= 10 ;
}
// If we haven't thrown an exception yet,
// we have the value in cents: return it.
return priceInCents ;
}

AutoIt: Find window under mouse pointer

I'm using AutoIt3 and I need a way for the user to select a window. The fastest method is, in my opinion, having them point to a window. So the question is, how do I see what window is under their mouse pointer?
I extrapolated this from some code I had laying around for selecting areas on the screen. This will just pop up the Window title thats under the mouse (hit Escape to exit the loop):
#include <WinAPI.au3>
#include <Misc.au3>
Func _WindowFromPoint($iX,$iY)
Local $stInt64,$aRet,$stPoint=DllStructCreate("long;long")
DllStructSetData($stPoint,1,$iX)
DllStructSetData($stPoint,2,$iY)
$stInt64=DllStructCreate("int64",DllStructGetPtr($stPoint))
$aRet=DllCall("user32.dll","hwnd","WindowFromPoint","int64",DllStructGetData($stInt64,1))
If #error Then Return SetError(2,#error,0)
If $aRet[0]=0 Then Return SetError(3,0,0)
Return $aRet[0]
EndFunc
Local $hControl, $hWin, $hOldWin, $aMousePos
$hOldWin = ""
While Not _IsPressed("1B")
$aMousePos = MouseGetPos()
$hControl=_WindowFromPoint($aMousePos[0],$aMousePos[1])
; Since _WindowFromPoint() can return 'sub' windows, or control handles, we should seek the owner window
$hWin=_WinAPI_GetAncestor($hControl,2)
If $hWin <> $hOldWin Then
TrayTip("Window Info","Window under mouse = " & WinGetTitle($hWin), 1)
$hOldWin = $hWin
EndIf
Sleep(10)
WEnd
Here's a complete example of a full screen GUI, displaying the actual screen and a border around the window that's topmost under the mouse pointer. This function is used to write the Title of the window to console.
#include <Misc.au3>
#include <Array.au3>
#include <GDIPlus.au3>
#include <ScreenCapture.au3>
#include <WindowsConstants.au3>
HotKeySet("{Esc}", "_Exit")
Func _Exit()
Exit 0
EndFunc
Global $xPosReminder, $yPosReminder
$dll = DllOpen("user32.dll")
$allWindows = WinList()
; exclude invisible windows from winlist
Dim $windows[1]
$windows[0] = 0
For $i = 1 to $allWindows[0][0]
; only fetches visible windows
If BitAnd(WinGetState($allWindows[$i][1]), 2) Then;AND $allWindows[$i][0] <> "" Then
ReDim $windows[$windows[UBound($windows) - 1] + 2]
$windows[UBound($windows) - 1] = $windows[UBound($windows) - 2] + 1
$windows[UBound($windows) - 2] = $allWindows[$i][1]
EndIf
Next
ReDim $windows[$windows[UBound($windows) - 1]]
_ArrayReverse($windows)
; capture screen without cursor
$pos = MouseGetPos()
MouseMove(#DesktopWidth, #DesktopHeight, 0)
$hBitmap = _ScreenCapture_Capture ("")
MouseMove($pos[0], $pos[1], 0)
; create and show new fullscreen gui
$hGUI = GUICreate("", #DesktopWidth, #DesktopHeight, 0, 0, $WS_POPUP)
GUISetState(#SW_SHOW)
; Initialize GDI+ library
_GDIPlus_StartUp()
$hImage = _GDIPlus_BitmapCreateFromHBITMAP ($hBitmap)
$hGraphics = _GDIPlus_GraphicsCreateFromHWND ($hGUI)
$hPen = _GDIPlus_PenCreate(0xFFFF0000, 3, 2)
$iX = _GDIPlus_ImageGetWidth($hImage)
$iY = _GDIPlus_ImageGetHeight($hImage)
_GDIPlus_GraphicsDrawImage($hGraphics, $hImage, 0, 0)
Global $oldWindow = 0
; Wait for Click
While True
If _IsPressed("01", $dll) Then ; left mouse button
$xPos = MouseGetPos(0)
$yPos = MouseGetPos(1)
ExitLoop
EndIf
If __MouseMoved() Then
; Erzeugt eine Kopie einer 24 bit Bitmap
$hClone = _GDIPlus_BitmapCloneArea($hImage, 0, 0, $iX, $iY, $GDIP_PXF24RGB)
$currentWindow = __GetWindowByMousePosition($windows, MouseGetPos(0), MouseGetPos(1))
If $currentWindow <> $oldWindow Then
$windowPosition = WinGetPos($currentWindow)
; reduce position and size to desktop space
$windowPosition[0] = _Iif($windowPosition[0] < 0, 0, $windowPosition[0])
$windowPosition[1] = _Iif($windowPosition[1] < 0, 0, $windowPosition[1])
$windowPosition[2] = _Iif($windowPosition[2] > #DesktopWidth, #DesktopWidth, $windowPosition[2])
$windowPosition[3] = _Iif($windowPosition[3] > #DesktopHeight, #DesktopHeight, $windowPosition[3])
_GDIPlus_GraphicsDrawImage($hGraphics, $hClone, 0, 0)
_GDIPlus_GraphicsDrawRect($hGraphics, $windowPosition[0], $windowPosition[1], $windowPosition[2], $windowPosition[3], $hPen)
$oldWindow = $currentWindow
EndIf
EndIf
Sleep(1)
WEnd
; Free Ressources
_GDIPlus_PenDispose($hPen)
_GDIPlus_BitmapDispose($hImage)
_GDIPlus_GraphicsDispose($hGraphics)
_WinAPI_DeleteObject($hBitmap)
_GDIPlus_ShutDown()
DllClose($dll)
GUISetState(#SW_HIDE)
Func __GetWindowByMousePosition($windows, $xPos, $yPos)
Local $currentWindow = 0
For $i = 0 to UBound($windows) - 1
$pos = WinGetPos($windows[$i])
If $xPos >= $pos[0] AND $xPos <= $pos[0] + $pos[2] AND $yPos >= $pos[1] AND $yPos <= $pos[1] + $pos[3] Then
$currentWindow = $windows[$i]
EndIf
Next
Return $currentWindow
EndFunc
Func __MouseMoved()
Local $actualPos = MouseGetPos()
If $xPosReminder <> $actualPos[0] OR $yPosReminder <> $actualPos[1] Then
$xPosReminder = $actualPos[0]
$yPosReminder = $actualPos[1]
Return True
Else
Return False
EndIf
EndFunc
ConsoleWrite(WinGetTitle(__GetWindowByMousePosition($windows, $xPos, $yPos)) & #CR)

Resources