Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate
Photo

Control Anchoring v4 for resizing windows


  • Please log in to reply
78 replies to this topic
toralf
  • Moderators
  • 4035 posts
  • Last active: Aug 20 2014 04:23 PM
  • Joined: 31 Jan 2005
I have played with the code again and extended it to be more general. Please critizice the parameter handling/handover. Could you imagine a simpler, a more elegant way?

It now allows to resize controls more flexible.
Gui, 1:+Resize
Gui, 1:Add, Button, Section vBtnAddGroup , +
Gui, 1:Add, Edit,  x+1 ys+1 w200 vEdtGroupName  Disabled, 
Gui, 1:Add, Button,  x+1 ys vBtnRemoveGroup  Disabled, -
Gui, 1:Add, Button, x+40 ys vBtnAddScriptlet  Disabled, +
Gui, 1:Add, Edit,  x+1 ys+1 w150 vEdtScriptletName  Disabled, 
Gui, 1:Add, Button,  x+1 ys vBtnRemoveScriptlet  Disabled, -
Gui, 1:Add, DropDownList, x+40 ys w150 vDdbScriptletInGroup  Sort Disabled, 
Gui, 1:Add, Button, ys vBtnCopyToClipboard  Disabled, Copy to &Clipboard
Gui, 1:Add, TreeView, xs Section w250 h500 vTrvScriptlets 
Gui, 1:Add, Edit, ys w500 h500 vEdtScriptletData ,
Gui, 1:Show, %GuiSize1%, %ScriptName%
Return

GuiSize:
  ;       ControlName         ,  xwyh , [ x     w     y     h     or True for MoveDraw]
  Anchor("EdtGroupName"       , " w  ", " 1   , 0.5 ,     ,     ")
  Anchor("BtnRemoveGroup"     , "x   ", " 0.5 , 1   ,     ,     ")
  Anchor("BtnAddScriptlet"    , "x   ", " 0.5 , 1   ,     ,     ")
  Anchor("EdtScriptletName"   , "xw  ", " 0.5 , 0.25,     ,     ")
  Anchor("BtnRemoveScriptlet" , "x   ", " 0.75,     ,     ,     ")
  Anchor("DdbScriptletInGroup", "xw  ", " 0.75, 0.25,     ,     ")
  Anchor("BtnCopyToClipboard" , "x   "                           )
  Anchor("TrvScriptlets"      , " w h", "     , 0.5 ,     , 1   ")
  Anchor("EdtScriptletData"   , "xw h", " 0.5 , 0.5 ,     , 1   ")
Return

Anchor(ctrl, a, d = false) {
    static pos
    sig = `n%A_Gui%:%ctrl%=

    If (d = 1){
        draw = Draw
        d=1,1,1,1
    }Else If (d = 0)
        d=1,1,1,1
    StringSplit, q, d, `,

    If !InStr(pos, sig) {
      GuiControlGet, p, Pos, %ctrl%
      pos := pos . sig . px - A_GuiWidth * q1 . "/" . pw  - A_GuiWidth * q2 . "/"
        . py - A_GuiHeight * q3 . "/" . ph - A_GuiHeight * q4 . "/"
    }
    StringTrimLeft, p, pos, InStr(pos, sig) - 1 + StrLen(sig)
    StringSplit, p, p, /
    
    c = xwyh
    Loop, Parse, c
      If InStr(a, A_LoopField) {
        If A_Index < 3
          e := p%A_Index% + A_GuiWidth * q%A_Index%
        Else e := p%A_Index% + A_GuiHeight * q%A_Index%
        m = %m%%A_LoopField%%e%
      }
    
    GuiControl, %A_Gui%:Move%draw%, %ctrl%, %m%
  }

GuiClose:
  ExitApp

Ciao
toralf
 
I use the latest AHK version (1.1.15+)
Please ask questions in forum on ahkscript.org. Why?
For online reference please use these Docs.

polyethene
  • Members
  • 5519 posts
  • Last active: May 17 2015 06:39 AM
  • Joined: 26 Oct 2012
Thanks for the idea. I've added this to version 3.3 along with a few code simplifications. I changed the example script to show the new feature.

Anchor("DdbScriptletInGroup", "xw ", " 0.75, 0.25, , ")

I chose to use Anchor("DdbScriptletInGroup", "x0.75 w0.25") like the way AutoHotkey positions controls.

autohotkey.com/net Site Manager

 

Contact me by email (polyethene at autohotkey.net) or message tidbit


toralf
  • Moderators
  • 4035 posts
  • Last active: Aug 20 2014 04:23 PM
  • Joined: 31 Jan 2005
That is a good idea. I looked at the code, it seems to be very efficient.

Only some little things:
-The GuiControl commands should have "%A_Gui%:", shouldn't they?
GuiControlGet, e,%A_Gui%: , %ctrl%
GuiControlGet, p, %A_Gui%:Pos, %ctrl%
GuiControl, %A_Gui%:Move%d%, %ctrl%, %m%

- could you add a few comments to the code, so that we know what is going on, when we look at it in the far future?
- maybe restructure the pos string statement to
pos := pos . sig
                   . px - A_GuiWidth  * bx . s . bx . s
                   . pw - A_GuiWidth  * bw . s . bw . s
                   . py - A_GuiHeight * by . s . by . s 
                   . ph - A_GuiHeight * bh . s . bh . s
I find this easier to read and understand.

- the indentation of "If !b" is one too much, isn't it?

- i would switch the lines "e :=" and "b :=", to be
b := A_Index * 2
e := b - 1

- Since "=" is slightly faster then ":=" I would replace as many as possible of the ":=" with "="

just my thoughts, sorry for being picky/pedantic.
Ciao
toralf
 
I use the latest AHK version (1.1.15+)
Please ask questions in forum on ahkscript.org. Why?
For online reference please use these Docs.

polyethene
  • Members
  • 5519 posts
  • Last active: May 17 2015 06:39 AM
  • Joined: 26 Oct 2012

The GuiControl commands should have "%A_Gui%:", shouldn't they?

They don't need to, the GUI that launches the call becomes the current-thread default. See the example.

- could you add a few comments to the code, so that we know what is going on, when we look at it in the far future?

I fear that adding code size would make less people want to add it to their scripts.

- the indentation of "If !b" is one too much, isn't it?

Thanks I fixed this and uploaded the modified file. Since the change is very small I didn't increment the version number.

- i would switch the lines "e :=" and "b :=", to be

b := A_Index * 2
e := b - 1

Thanks for the tip, I uploaded the new file.

- Since "=" is slightly faster then ":=" I would replace as many as possible of the ":=" with "="

ressions[/url]":6oam5foq">

Performance: The expression assignment operator (:=) is optimized so that it performs just as quickly as the non-expression operator (=) for simple cases such as the following: ...


autohotkey.com/net Site Manager

 

Contact me by email (polyethene at autohotkey.net) or message tidbit


toralf
  • Moderators
  • 4035 posts
  • Last active: Aug 20 2014 04:23 PM
  • Joined: 31 Jan 2005

They don't need to, the GUI that launches the call becomes the current-thread default. See the example.

Thanks, I wasn't aware of it.

- could you add a few comments to the code, so that we know what is going on, when we look at it in the far future?

I fear that adding code size would make less people want to add it to their scripts.

I doubt that adding some small comments will have a big impact on code size or file size, not even on people wanting to use this great function. But it would help to maintain and understand the code. And when included, people will not see it anyway. When called it will also not have a speed impact.

- Since "=" is slightly faster then ":=" I would replace as many as possible of the ":=" with "="

ressions[/url]":1tumyopi">

Performance: The expression assignment operator (:=) is optimized so that it performs just as quickly as the non-expression operator (=) for simple cases such as the following: ...

Thanks for the link, I didn't see that before. I have created a small script that tested this and the "=" was a little faster. But it might not have a influence on this code. I used loops with very high counts.

Thanks for listening.
Ciao
toralf
 
I use the latest AHK version (1.1.15+)
Please ask questions in forum on ahkscript.org. Why?
For online reference please use these Docs.

polyethene
  • Members
  • 5519 posts
  • Last active: May 17 2015 06:39 AM
  • Joined: 26 Oct 2012

I have created a small script that tested this and the "=" was a little faster.

I found that := is always faster, try the following a few times:
SetBatchLines, -1

Process, Priority, , R



VarSetCapacity(const, 1024, 46)

i = 1000000



VarSetCapacity(var, 0)

st := A_TickCount

Loop, %i%

	var := const

t1 := A_TickCount - st



VarSetCapacity(var, 0)

st := A_TickCount

Loop, %i%

	var =%const%

t2 := A_TickCount - st



MsgBox, % t1 . "`n" . t2 . "`n`n" . (t2 - t1) / t2 * 100 . "%"

autohotkey.com/net Site Manager

 

Contact me by email (polyethene at autohotkey.net) or message tidbit


toralf
  • Moderators
  • 4035 posts
  • Last active: Aug 20 2014 04:23 PM
  • Joined: 31 Jan 2005
And i used this:
num = 1000

times = 10

sumtick1 = 0

sumtick2 = 0

Loop, %times% {

    DllCall("QueryPerformanceCounter", "Int64 *", tick1)

    Loop, 100000 

        s = %num%

    DllCall("QueryPerformanceCounter", "Int64 *", tick2)

    Loop, 100000 

        s := num

    DllCall("QueryPerformanceCounter", "Int64 *", tick3)

    

    sumtick1 := sumtick1 + tick2 - tick1

    sumtick2 := sumtick2 + tick3 - tick2

    MsgTxt := MsgTxt tick2 - tick1 " - " tick3 - tick2 "`n"

  }

sumtick1 /= %times%

sumtick2 /= %times%

Msgbox, %MsgTxt%`n`n%sumtick1% - %sumtick2%

Never mind, I guess it doesn't have an influence that is noticeable.
Ciao
toralf
 
I use the latest AHK version (1.1.15+)
Please ask questions in forum on ahkscript.org. Why?
For online reference please use these Docs.

Thalon
  • Members
  • 641 posts
  • Last active: Jan 02 2017 12:17 PM
  • Joined: 12 Jul 2005
I love this script, also it is quite hard to read! (I didn't try it and will not until there is a problem with it).

But I like scripts with well explanations and comments.
I also prefer more self-explaning variable-names :wink:

After some testing I have added "WinSet, Redraw" after the last Function-Call (in your example). Without this I have sometimes "old data" in my GUI.
GuiSize:
Anchor("MyEdit", "wh")
Anchor("MyButton", "xy", true)
Anchor("MyGroup", "yw", true)
Anchor("MyCombo", "y")
Anchor("LB", "w0.5 h")
Anchor("Edit", "x0.5 w0.5 h")
Anchor("CloseButton", "xy")
WinSet, Redraw
Return

Thalon

polyethene
  • Members
  • 5519 posts
  • Last active: May 17 2015 06:39 AM
  • Joined: 26 Oct 2012
With your benchmark (which seems more reliable) expressions are -6% to 17% faster. Strange.

Since Anchor only uses a few expressions I'll leave them as they are.

autohotkey.com/net Site Manager

 

Contact me by email (polyethene at autohotkey.net) or message tidbit


jballi
  • Members
  • 1029 posts
  • Last active:
  • Joined: 01 Oct 2005

I have created a small script that tested this and the "=" was a little faster.

I found that := is always faster, try the following a few times:
SetBatchLines, -1
Process, Priority, , R

VarSetCapacity(const, 1024, 46)
i = 1000000

VarSetCapacity(var, 0)
st := A_TickCount
Loop, %i%
	var := const
t1 := A_TickCount - st

VarSetCapacity(var, 0)
st := A_TickCount
Loop, %i%
	var =%const%
t2 := A_TickCount - st

MsgBox, % t1 . "`n" . t2 . "`n`n" . (t2 - t1) / t2 * 100 . "%"

Interesting test. I played around with the size of the constant (I also bumped up the loop count to 5 million) and found that ":=" is faster if the constant is 20 bytes or larger and "=" is faster if the constant is less than 20 bytes in length. Also, the performance scale improves/diminishes as the constant is increased/decreased in length. Try your test at 2 or 3 MB and you'll see the performance difference skyrocket.

Since most variable values are very short in length, I suspect that "=" will remain the overall practical winner although having this information might help someone to decide which assignment type to use, especially if the code is executed thousands or (help us all) millions of times.

Them be my thoughts...

toralf
  • Moderators
  • 4035 posts
  • Last active: Aug 20 2014 04:23 PM
  • Joined: 31 Jan 2005

Since Anchor only uses a few expressions I'll leave them as they are.

Fine.

Will you add comments? :)

If not, I'll do them for my own copy.
Ciao
toralf
 
I use the latest AHK version (1.1.15+)
Please ask questions in forum on ahkscript.org. Why?
For online reference please use these Docs.

robiandi
  • Members
  • 49 posts
  • Last active: Jul 27 2008 05:04 PM
  • Joined: 08 Aug 2006
toralf, I am interested in your comments. ( Life is easier with comments, please share them )

toralf
  • Moderators
  • 4035 posts
  • Last active: Aug 20 2014 04:23 PM
  • Joined: 31 Jan 2005
Ok, here you go, a slightly modified (not in functionality) version with comments:
Anchor(ctrl, a, draw = false) { ; v3.3 by Titan  http://www.autohotkey.com/forum/viewtopic.php?t=4348

    static pos

    

    ;controls are moved/resized by a fraction of the amount the gui changes size

    ;e.g.     New pX := orig. pX  + factor * ( current guiW - orig. guiW )

    

    ;return if control or Gui do not exist

    GuiControlGet, e, , %ctrl%

    If !A_Gui or ErrorLevel

        Return

    

    sig = `n%A_Gui%:%ctrl%=     ;unique prefix to store pos/size

    c = xwyh                    ;order pos/size is stored

    s = /                       ;data separator

    

    ;on first call for this control, remember original position, size and factor

    If !InStr(pos, sig) {

        ;get factors

        Loop, Parse, c

            If InStr(a, A_LoopField) {

                ;get factor after x/w/y/h

                StringTrimLeft, e, a, InStr(a, A_LoopField)

                b =

                Loop, Parse, e

                    If A_LoopField is not alpha

                        b = %b%%A_LoopField%

                    Else Break

                If !b                     ;when no factor given, use 1

                    b = 1

                b%A_LoopField% = %b%      ;memorize factor

              }Else b%A_LoopField% = 1    ;unnecessary, since control not moved in that pos/size, but complete

        ;get pos/size of control

        GuiControlGet, p, Pos, %ctrl%

        ;store (orig. control pos/size - orig. gui width/height * factor) and factor in one var

        pos := pos . sig . px - A_GuiWidth  * bx . s . bx . s

                         . pw - A_GuiWidth  * bw . s . bw . s

                         . py - A_GuiHeight * by . s . by . s 

                         . ph - A_GuiHeight * bh . s . bh . s

      }

    

    ;get pos/size string and split into array

    StringTrimLeft, p, pos, InStr(pos, sig) - 1 + StrLen(sig)

    StringSplit, p, p, %s%

    

    ;calculate new position and size

    Loop, Parse, c

        If InStr(a, A_LoopField) {

            If A_Index < 3          ;for x/w use current gui width

                s = %A_GuiWidth%

            Else s = %A_GuiHeight%  ;otherwise use current gui height

            b := A_Index * 2        ;get factor index 

            e := b - 1              ;get pos/size index

            ;combine "x/w/y/h" with (orig. control pos/size - orig. gui width/height * factor  + current gui width/height * factor)

            m := m . A_LoopField . p%e% + s * p%b%

          }

    

    ;move/resize control to new pos/size

    If draw

        d = Draw

    GuiControl, Move%d%, %ctrl%, %m%

  }


Ciao
toralf
 
I use the latest AHK version (1.1.15+)
Please ask questions in forum on ahkscript.org. Why?
For online reference please use these Docs.

robiandi
  • Members
  • 49 posts
  • Last active: Jul 27 2008 05:04 PM
  • Joined: 08 Aug 2006
toralf, many thanks :)

polyethene
  • Members
  • 5519 posts
  • Last active: May 17 2015 06:39 AM
  • Joined: 26 Oct 2012
Sorry for taking so long, I don't usually comment my scripts. Here is a very descriptive commented version.

autohotkey.com/net Site Manager

 

Contact me by email (polyethene at autohotkey.net) or message tidbit