 |
AutoHotkey Community Let's help each other out
|
| View previous topic :: View next topic |
| Author |
Message |
butterflysix Guest
|
Posted: Thu May 08, 2008 7:59 am Post subject: is a glowing gui even possible? |
|
|
| Hello, can a GUI, 200x200 be made to flow & glow between 4 colors smoothly, with a speed control in a loop?? I know this sounds strange, but I am wanting to use this for an effect and think this might be snazzy, but have no clue how to run this. Could someone help please? |
|
| Back to top |
|
 |
Z Gecko Guest
|
Posted: Thu May 08, 2008 3:59 pm Post subject: |
|
|
I am not shure what "glow and flow" actually is,
but a gui can change its color:
| Code: | Gui, Show, w200 h200, Fader
SetFormat, integer, hex
loop, 1000
{
Var += 16
Gui, Color, %Var%
sleep, 100
} |
only the hex-math is a little bit tricky,
youīll see, the demo shader is rather crappy. |
|
| Back to top |
|
 |
SKAN
Joined: 26 Dec 2005 Posts: 6084
|
Posted: Thu May 08, 2008 4:30 pm Post subject: |
|
|
I got curious and wanted to try.
The following changes colors as BLACK > BLUE > CYAN > WHITE > YELLOW > RED
| Code: | Gui -Caption +Border +AlwaysOnTop
Gui, Show, w200 h200
VarSetCapacity( CLR, 4,0 )
Loop
{
; Incrementing COLORREF
pos := 0, ctr := 0
Loop % 256 * 3
{
ctr += 1
if ctr > 255
ctr := 0, pos += 1
NumPut( ctr, CLR, pos, "UChar" )
Gui, Color, % Color( NumGet( CLR ) )
Sleep, 1
}
; Decrementing COLORREF
pos := 0, ctr := 255
Loop % 256 * 3
{
ctr -= 1
if ctr < 0
ctr := 255, pos += 1
NumPut( ctr, CLR, pos, "UChar" )
Gui, Color, % Color( NumGet( CLR ) )
Sleep, 1
}
}
Return ; // end of auto-execute section //
Color( i )
{
setformat, integer, hex
i += 0x1000000
setformat, integer, decimal
return substr( i, 0-5 )
} |
Please try to improvise it on your own.
 |
|
| Back to top |
|
 |
Z Gecko Guest
|
Posted: Thu May 08, 2008 5:36 pm Post subject: |
|
|
very cool, SKAN!
i am still trying to understand what you exactly did.
especially the math in the Color-function is confusing me.
could you comment it a bit, especially the part where you do
i += 0x1000000 and substr( i, 0-5 ) ? |
|
| Back to top |
|
 |
butterflysix Guest
|
Posted: Thu May 08, 2008 5:38 pm Post subject: |
|
|
Hey there SKAN.... I can only say Bravo!!! (insert loud clapping here). That is so extremely cool and smooth. May I please ask, .... , how did you got the colors? I cannot understand that Color( i ) sub-function. Do you have a exact procedure you can let me know to somehow insert fixed color patterns, like Olive, Red, Green to Orange --- for example? : |
|
| Back to top |
|
 |
SKAN
Joined: 26 Dec 2005 Posts: 6084
|
Posted: Thu May 08, 2008 6:36 pm Post subject: |
|
|
| Z Gecko wrote: | very cool, SKAN!
i am still trying to understand what you exactly did.
especially the math in the Color-function is confusing me.
could you comment it a bit, especially the part where you do
i += 0x1000000 and substr( i, 0-5 ) ? |
It was a technique introduced by Laszlo in this post : GetSysColor()
Case:
Colorref for BlueGreen ( Cyan ) is 65535
if we convert it to hex we get 0xffff ( leading two zeroes missing ) and to format it to 00FFFF :-
| Code: | BlueGreen := 65535 ; 0x00FFFF
SetFormat, Integer, Hex
BlueGreen += 0
MsgBox, % BlueGreen ; will be 0xffff whereas we need 0x00FFFF
BlueGreen += 0x1000000 ; one followed by six zeroes
MsgBox, % BlueGreen ; will be 0x100FFFF
BlueGreen := SubStr( BlueGreen, -5 ) ; retrieve the last six chars - that is - ignore the leading 0x1
StringUpper, BlueGreen, BlueGreen ; convert to upper case
MsgBox, % BlueGreen ; will be 00FFFF
SetFormat, Integer, Decimal |
Re: SubStr()
To retrieve a number of ending characters from a string we can pass a negative number - for example if we need to retrieve the last 2 chars from "Zippo()" : SubStr( "Zippo()", -1 )
0-5 is overdone. It should be just -5
Bad adaptation from this post:
 |
|
| Back to top |
|
 |
SKAN
Joined: 26 Dec 2005 Posts: 6084
|
Posted: Thu May 08, 2008 6:45 pm Post subject: |
|
|
| butterflysix wrote: | Do you have a exact procedure you can let me know to somehow insert fixed color patterns, like Olive, Red, Green to Orange --- for example? : |
I am poor in maths
here is a slightly different version that shows the colorref in the GUI so you can see how the rotation is done:
| Code: | Gui -Caption +Border +AlwaysOnTop
Gui, Font, S10, Courier New
Gui, Add, Text, w60 h20 +Border 0x6
Gui, Add, Text, xp yp w60 h20 vColor +0x201 +BackgroundTrans
Gui, Show, w200 h200
VarSetCapacity( CLR, 4,0 )
Loop
{
; Incrementing COLORREF
pos := 0, ctr := 0
Loop % 256 * 3
{
ctr += 1
if ctr > 255
ctr := 0, pos += 1
NumPut( ctr, CLR, pos, "UChar" )
Color := Color( NumGet( CLR ) )
GuiControl,, Color, %Color%
Gui, Color, % Color
Sleep, 10
}
; Decrementing COLORREF
pos := 0, ctr := 255
Loop % 256 * 3
{
ctr -= 1
if ctr < 0
ctr := 255, pos += 1
NumPut( ctr, CLR, pos, "UChar" )
Color := Color( NumGet( CLR ) )
GuiControl,, Color, %Color%
Gui, Color, % Color
Sleep, 10
}
}
Return ; // end of auto-execute section //
Color( i )
{
setformat, integer, hex
i += 0x1000000
setformat, integer, decimal
return DllCall( "CharUpperA", Str,substr( i, -5 ), Str )
} |
I can explain about colorref / numput() / numget() if you want so that you can do it yourself.
 |
|
| Back to top |
|
 |
Z Gecko Guest
|
Posted: Thu May 08, 2008 7:27 pm Post subject: |
|
|
thank you, SKAN!
i understand now much better what you did.
I didnīt realize that a negative StartingPos will make SubStr take the chars from the right-side.
btw: i found out that Gui, Color will work without the leading zeros, too.
| Code: | Gui, Color, E4
Gui, Show, w100 h100 x100 y100
Gui, 2: Color, 0000E4
Gui, 2: Show, w100 h100 x200 y200 |
|
|
| Back to top |
|
 |
butterflysix Guest
|
Posted: Thu May 08, 2008 7:40 pm Post subject: |
|
|
SKAN, that would be so cool & awesome. Thank you for your time. If you can give me a basis for comparison, I think I can figure out how to do what I was seeking. I surmise from what you suggest this will not be so easy, but I am 100% up for the challenge! What do I need to look at or think about with the colorref, + those two functions numput() / numget()? So, I mean, if I wanted to start with RED @ FF0000 and then lets say cycle to YELLOW @ FFF600... maybe if you explain the math or what I need to think about to accomplish that within the Color ( ) function.... Any help would be greatly appreciated & thank you in advance! Have very good day.
If anyone else has any pointers that would be sweet |
|
| Back to top |
|
 |
SKAN
Joined: 26 Dec 2005 Posts: 6084
|
Posted: Thu May 08, 2008 7:55 pm Post subject: |
|
|
| Z Gecko wrote: | | btw: i found out that Gui, Color will work without the leading zeros, too. |
Sure! .. and I was aware of that.
I was using a tooltip to see whether the code was rotating the colorref properly and so I needed a properly formatted hex.
@butterflysix: be informed that with bitshifting, you can have more compact code.. but NumGet/NumPut is more convenient to understand.
Allow me sometime and I will post a short tut.
 |
|
| Back to top |
|
 |
butterflysix Guest
|
Posted: Thu May 08, 2008 7:58 pm Post subject: |
|
|
thank you skan, that is awesome for you to help me with this, i appreciate it  |
|
| Back to top |
|
 |
SKAN
Joined: 26 Dec 2005 Posts: 6084
|
Posted: Thu May 08, 2008 11:23 pm Post subject: |
|
|
Abusing NumGet() and Numput() to alter ASCII value of memory bytes
Intro: In most of the programming languages, you have to declare the data type while creating a variable whereas in AHK there is only one type of data it handle by default: null terminated strings
With introduction of DllCall(), structure handling became difficult and so NumGet() and NumPut() were introduced to read/write - from/to memory.
This topic is outdated after introduction of NumGet() / NumPut(), but most of the examples would still work: How to manipulate Binary data with Pointers ?
A single byte of memory can contain only the 256 ASCII values from 0 through 255. Refer wikipedia for the chart : http://en.wikipedia.org/wiki/ASCII
So, when we initialise a variable, like: Var := "SKAN"
AHK creates Var, which uses 5 bytes and stores these ascii values: 83,75,65,78,0
The first byte ( Byte 1 ) of a variable would be referred in NumGet() / NumPut() as OffSet 0
83 is ASCII value of "S" and is stored at offset 0 of Var
75 is ASCII value of "K" and is stored at offset 1 of Var
65 is ASCII value of "A" and is stored at offset 2 of Var
78 is ASCII value of "N" and is stored at offset 3 of Var
0 is ASCII value "Null" and is stored at offset 4 of Var and let knows AHK's string commands to stop reading ahead.
In other words, if not for null, AHK string commands would never know where to stop.
NumGet() and NumPut()
| Quote: | NumGet(VarOrAddress [, Offset = 0, Type = "UInt"]) [v1.0.47+]: Returns the binary number stored at the specified address+offset. For VarOrAddress, passing MyVar is equivalent to passing &MyVar. However, omitting the "&" performs better and ensures that the target address is valid (invalid addresses return ""). By contrast, anything other than a naked variable passed to VarOrAddress is treated as a raw address; consequently, specifying MyVar+0 forces the number in MyVar to be used instead of the address of MyVar itself. For Type, specify UInt, Int, Int64, Short, UShort, Char, UChar, Double, or Float (though unlike DllCall, these must be enclosed in quotes when used as literal strings); for details see DllCall Types.
NumPut(Number, VarOrAddress [, Offset = 0, Type = "UInt"]) [v1.0.47+]: Stores Number in binary format at the specified address+offset and returns the address to the right of the item just written. For VarOrAddress, passing MyVar is equivalent to passing &MyVar. However, omitting the "&" performs better and ensures that the target address is valid (invalid addresses return ""). By contrast, anything other than a naked variable passed to VarOrAddress is treated as a raw address; consequently, specifying MyVar+0 forces the number in MyVar to be used instead of the address of MyVar itself. For Type, specify UInt, Int, Int64, Short, UShort, Char, UChar, Double, or Float (though unlike DllCall, these must be enclosed in quotes when used as literal strings); for details see DllCall Types. If an integer is too large to fit in the specified Type, its most significant bytes are ignored; e.g. NumPut(257, var, 0, "Char") would store the number 1. |
To reduce complexity, let me avoid explaining how this NumGet/NumPut stuff works and just say that we can read the binary values as follows:
To Read/Write 1 byte of memory we pass "UChar" as a parameter
To Read/Write 2 bytes of memory we pass "UShort" as a parameter
To Read/Write 4 bytes of memory we pass "UInt" as a parameter
COLORREF
One byte of data is 8 bits and a COLORREF is 32 bit and would occupy 4 bytes when NumPut() into a variable.
AHK uses RGB color containing three components Red, Green and Blue
Each component will contain a value between 0 - 255. We have already seen that 1 byte of memory can hold only a value between 0 through 255 and so a RGB color can contain :
The minimum color value of 0x0x0 = 0 ( 0x000000 )
and maximum color value of (256x256x256)-1 = 16777215 ( 0xFFFFFF )
Okay, Lets experiment by creating a variable:
| Code: | ; TASK: Create a 4 byte variable containing the string "SKAN"
; Method 1
Var1 := "SKAN"
MsgBox,0,Method 1,% Var1 "`n`nUInt:" NumGet( Var1, 0, "UInt" ) ; will be 1312901971
; Method 2
VarSetCapacity( Var2, 4 ) ; create an empty variable sized 4 bytes
NumPut( 1312901971, Var2, 0, "UInt" ) ; Put UInt 1312901971 to Var2
VarSetCapacity( Var2, -1 ) ; reset the var size
MsgBox,0,Method 2, % Var2 ; Presto! Var2 is "SKAN"
; Method 3
; Refer wikipedia ASCII : http://en.wikipedia.org/wiki/ASCII
Var3 := Chr(83) . Chr(75) . Chr(65) . Chr(78)
MsgBox,0,Method 3, % Var3
; Method 4
VarSetCapacity( Var4, 5, 0 ) ; create an empty variable sized 4 bytes
NumPut( 83, Var4, 0, "UChar" ) ; Put ASCII 83 in Var4 @ offset 0 AKA Byte 1
NumPut( 75, Var4, 1, "UChar" ) ; Put ASCII 75 in Var4 @ offset 1 AKA Byte 2
NumPut( 65, Var4, 2, "UChar" ) ; Put ASCII 65 in Var4 @ offset 2 AKA Byte 3
NumPut( 78, Var4, 3, "UChar" ) ; Put ASCII 78 in Var4 @ offset 3 AKA Byte 4
VarSetCapacity( Var4, -1 ) ; reset the var size
MsgBox,0,Method 4, % Var4 |
In the above example we see the usage of Chr() function to convert an ASCII value to a Character. To do the opposite, that is, to convert a Character to its respective ASCII value we can use Asc() function.
| Code: | MsgBox, % Asc( "A" )
MsgBox, % Chr( 65 )
MsgBox, % Asc( Chr( 65 ) ) |
Here is how we can use NumGet() and Numput() to alter a byte of data directly in memory variable:
| Code: | Var := "SKAN"
NumPut( Asc("I"), Var, 2, "UChar" ) ; Put "I" @ offset 2 ( AKA byte 3 ) of Var
VarSetCapacity( Var, -1 ) ; Reset Var
MsgBox, % Var ; will show "SKIN" |
Lets try incrementing characters with a 10 byte variable :
| Code: | Gui, Font, S24 , Courier New
Gui, Add, Text, w330 h50 vName +0x1201, ??????????
Gui, Show,, Character Incrementation with Numget() / NumPut()
Target := "AUTOHOTKEY"
StringSplit, T, Target
Loop
{
Ctr += 1
If ( Ctr > StrLen( Target ) )
Break
Loop
{
GuiControlGet, Name
Asc := NumGet( Name, Ctr-1, "UChar" )
If ( Asc < Asc(T%Ctr%) )
{
NumPut( Asc+1, Name, Ctr-1, "UChar" )
VarSetCapacity( Name, -1 )
GuiControl,, Name, %Name%
}
Else
Break
Sleep 40
}
}
Return |
| butterflysiz wrote: | | start with RED @ FF0000 and then lets say cycle to YELLOW @ FFF600 |
When we NumPut( 0xFF0000, CLR, 0, "UInt" )
CLR would contain these 4 ASCII values: 0,0,255,0
We can ignore the last byte as we are dealing with only the first three bytes which represents the components Blue, Green and Red.
We have to specifically increment the Green component which is at Offset 1 ( Byte 2 ) until it reaches 0xF6 ( decimal is 246 )
It can be done as follows:
| Code: | VarSetCapacity( CLR, 4, 0 )
NumPut( 0xFF0000, CLR, 0, "UInt" )
MsgBox,0, RGB Value
, % NumGet( CLR, 2, "UChar" )
. "," NumGet( CLR, 1, "UChar" )
. "," NumGet( CLR, 0, "UChar" )
; The above will show : 255,0,0
Green := 0xF6 + 0 ; add zero to convert it into decimal
MsgBox,0, 0xF6, The green component should be: %Green%
Gui, Color, % Color( NumGet( CLR, 0, "UInt" ) )
Gui -Caption +Border +AlwaysOnTop
Gui, Show, w200 h200
Loop {
Target := NumGet( CLR, 1, "UChar" ) ; Offset 1 ( Byte 2 ) is Green value
If ( Target >= Green ) ; Target attained
Break ; .. so break the loop
else
{
Target += 1 ; increment Target by 1
NumPut( Target, CLR, 1, "UChar" ) ; Put Target value @ Offset 1 ( Byte 2 )
Gui, Color, % Color( NumGet( CLR, 0, "UInt" ) )
Sleep 10
}
}
Color( i )
{
setformat, integer, hex
i += 0x1000000
setformat, integer, decimal
return DllCall( "CharUpperA", Str,substr( i, -5 ), Str )
} |
I hope you can handle your requirement by self..
Regards,

Last edited by SKAN on Fri May 09, 2008 8:57 am; edited 1 time in total |
|
| Back to top |
|
 |
Z Gecko Guest
|
Posted: Fri May 09, 2008 4:35 am Post subject: |
|
|
Wow, a full tutorial,
god explanation and very cool examples ,
thank you again, SKAN!
with my new knowledge, it was easy to make a
color-changer, that transforms any given color in any other given color.
But itīs still not the smothest way
| Code: | startcolor = 0x008000 ;Green
targetcolor = 0x0000FF ;Blue
Gui, Color, %startcolor%
Gui, Add, Text, x10 w70 h20 +Border, %startcolor%
Gui, Add, Text, x+5 vcurrcolor w70 h20 +Border, %startcolor%
Gui, Add, Text, x+5 w70 h20 +Border, %targetcolor%
Gui, Show, w240 h240
loop
{
startcolor := transformcolor(startcolor, targetcolor)
Gui, Color, %startcolor%
GuiControl, , currcolor, %startcolor%
sleep, 50
if (startcolor = targetcolor)
break
}
return
transformcolor( startcolor, targetcolor)
{
VarSetCapacity( SCLR, 4, 0 )
VarSetCapacity( TCLR, 4, 0 )
NumPut( startcolor, SCLR, 0, "UInt" )
NumPut( targetcolor, TCLR, 0, "UInt" )
R_color := NumGet( SCLR, 2, "UChar" )
G_color := NumGet( SCLR, 1, "UChar" )
B_color := NumGet( SCLR, 0, "UChar" )
R_target := NumGet( TCLR, 2, "UChar" )
G_target := NumGet( TCLR, 1, "UChar" )
B_target := NumGet( TCLR, 0, "UChar" )
if ( R_color < R_target )
R_color += 1
if ( R_color > R_target )
R_color -= 1
if ( G_color < G_target )
G_color += 1
if ( G_color > G_target )
G_color -= 1
if ( B_color < B_target )
B_color += 1
if ( B_color > B_target )
B_color -= 1
NumPut( R_color, SCLR, 2, "UChar" )
NumPut( G_color, SCLR, 1, "UChar" )
NumPut( B_color, SCLR, 0, "UChar" )
newcolor := "0x" . Color( NumGet( SCLR, 0, "UInt" ) )
return newcolor
}
Color( i )
{
setformat, integer, hex
i += 0x1000000
setformat, integer, decimal
return DllCall( "CharUpperA", Str,substr( i, -5 ), Str )
} |
|
|
| Back to top |
|
 |
butterflysix Guest
|
Posted: Fri May 09, 2008 1:44 pm Post subject: |
|
|
Hey thanks Z GECKO that is brilliant, and much appreciative for the tutorial as well SKAN! It was a very good read.
Have a nice weekend~  |
|
| Back to top |
|
 |
|
|
You can post new topics in this forum You can reply to topics in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|