Page 1 of 6

AutoXYWH() - Move control automatically when GUI resized

Posted: 20 Dec 2013, 06:39
by tmplinshi
This is a simple version of Anchor() by Titan.
Old version
Modified version by toralf:

Code: Select all

; =================================================================================
; Function: AutoXYWH
;   Move and resize control automatically when GUI resizes.
; Parameters:
;   DimSize - Can be one or more of x/y/w/h  optional followed by a fraction
;             add a '*' to DimSize to 'MoveDraw' the controls rather then just 'Move', this is recommended for Groupboxes
;   cList   - variadic list of ControlIDs
;             ControlID can be a control HWND, associated variable name, ClassNN or displayed text.
;             The later (displayed text) is possible but not recommend since not very reliable 
; Examples:
;   AutoXYWH("xy", "Btn1", "Btn2")
;   AutoXYWH("w0.5 h 0.75", hEdit, "displayed text", "vLabel", "Button1")
;   AutoXYWH("*w0.5 h 0.75", hGroupbox1, "GrbChoices")
; ---------------------------------------------------------------------------------
; Version: 2015-5-29 / Added 'reset' option (by tmplinshi)
;          2014-7-03 / toralf
;          2014-1-2  / tmplinshi
; requires AHK version : 1.1.13.01+
; =================================================================================
AutoXYWH(DimSize, cList*){       ; http://ahkscript.org/boards/viewtopic.php?t=1079
  static cInfo := {}
 
  If (DimSize = "reset")
    Return cInfo := {}
 
  For i, ctrl in cList {
    ctrlID := A_Gui ":" ctrl
    If ( cInfo[ctrlID].x = "" ){
        GuiControlGet, i, %A_Gui%:Pos, %ctrl%
        MMD := InStr(DimSize, "*") ? "MoveDraw" : "Move"
        fx := fy := fw := fh := 0
        For i, dim in (a := StrSplit(RegExReplace(DimSize, "i)[^xywh]")))
            If !RegExMatch(DimSize, "i)" dim "\s*\K[\d.-]+", f%dim%)
              f%dim% := 1
        cInfo[ctrlID] := { x:ix, fx:fx, y:iy, fy:fy, w:iw, fw:fw, h:ih, fh:fh, gw:A_GuiWidth, gh:A_GuiHeight, a:a , m:MMD}
    }Else If ( cInfo[ctrlID].a.1) {
        dgx := dgw := A_GuiWidth  - cInfo[ctrlID].gw  , dgy := dgh := A_GuiHeight - cInfo[ctrlID].gh
        For i, dim in cInfo[ctrlID]["a"]
            Options .= dim (dg%dim% * cInfo[ctrlID]["f" dim] + cInfo[ctrlID][dim]) A_Space
        GuiControl, % A_Gui ":" cInfo[ctrlID].m , % ctrl, % Options
} } }
Example:

Code: Select all

#Include, AutoXYWH.ahk

Gui, +Resize
Gui, Add, Edit, ve1 w150 h100
Gui, Add, Button, vb1 gResize, Resize
Gui, Show
return

Resize:
	GuiControl, Move, e1, h50
	AutoXYWH("reset") ; Needs to reset if you changed the Control size manually.
return
 
GuiSize:
	If (A_EventInfo = 1) ; The window has been minimized.
		Return
	AutoXYWH("wh", "e1")
	AutoXYWH("y", "b1")
return

Re: AutoXYWH() - Move control automatically when GUI resized

Posted: 23 Dec 2013, 14:28
by Rindis
Hi
I can't get this to work. I get an error saying "Call to non existent function" in this line:

cInfo[ctrl] := { _x:(_x), _y:(_y), _w:(_w), _h:(_h), _a:StrSplit(_a) }


Cheers

Re: AutoXYWH() - Move control automatically when GUI resized

Posted: 23 Dec 2013, 14:31
by tmplinshi
Hello, Rindis
Please use latest version of AHK. Download link: http://l.autohotkey.net/AutoHotkey_L_Install.exe

Re: AutoXYWH() - Move control automatically when GUI resized

Posted: 23 Dec 2013, 14:33
by gregster
As far as I know, StrSplit() - as a function - is relatively new to AHK (the corresponding command is older) . You probably need AHK 1.1.13.01, like it is mentioned in the script header. So, update...!

Re: AutoXYWH() - Move control automatically when GUI resized

Posted: 23 Dec 2013, 14:39
by Rindis
:oops: Thank. Now updated and its working

Cheers

Re: AutoXYWH() - Move control automatically when GUI resized

Posted: 25 Jun 2014, 13:41
by toralf
Dear tmplinshi,

your code is nice, but it doesn't support fractions of dimensions, e.g. w0.5 = control gets only half of the gui width change.
Have you considered to expend your function in this direction?

Re: AutoXYWH() - Move control automatically when GUI resized

Posted: 25 Jun 2014, 15:03
by joedf
Nice!
@toralf true... But then, doesn't anchor do that?

Re: AutoXYWH() - Move control automatically when GUI resized

Posted: 25 Jun 2014, 15:37
by toralf
@joedf
Yes, but much more complicated. The lastest version of Anchor() is very complex code (i assume it got further optimized for speed). This version is simple and uses the latest features of AHK. And it allows to give a list of controls at once.

I went ahead an made a mod.

Code: Select all

; =================================================================================
; Function:     AutoXYWH
;   Move and resize control automatically when GUI resized.
; Parameters:
;   ctrl_list  - ControlID list separated by "|".
;                ControlID can be a control HWND, associated variable name or ClassNN.
;   Attributes - Can be one or more of x/y/w/h  followed by fractions
;   Redraw     - True to redraw controls
; Examples:
;   AutoXYWH("Btn1|Btn2", "xy")
;   AutoXYWH(hEdit      , "w0.5 h0.75")
; ---------------------------------------------------------------------------------
; Release date: 2014-6-25           http://ahkscript.org/boards/viewtopic.php?t=1079
; Author      : tmplinshi (mod by toralf)
; requires AHK version : 1.1.13.01+
; =================================================================================
AutoXYWH(ctrl_list, Attributes="wh", Redraw = False){
    static cInfo := {}
    Loop, Parse, ctrl_list, |
    {
        ctrl := A_Gui ":" A_LoopField
        If ( cInfo[ctrl].x = "" ){
            GuiControlGet, i, %A_Gui%:Pos, %A_LoopField%
            a := RegExReplace(Attributes, "i)[^xywh]")  
            fx := fy := fw := fh := 0
            Loop, Parse, a
                If !RegExMatch(Attributes, "i)" A_LoopField "\s*\K[\d.-]+", f%A_LoopField%)
                  f%A_LoopField% := 1
            cInfo[ctrl] := { x:ix, fx:fx, y:iy, fy:fy, w:iw, fw:fw, h:ih, fh:fh, gw:A_GuiWidth, gh:A_GuiHeight, a:StrSplit(a) }
        }Else If ( cInfo[ctrl].a.1) {
            x := (A_GuiWidth  - cInfo[ctrl].gw) * cInfo[ctrl].fx + cInfo[ctrl].x
            y := (A_GuiHeight - cInfo[ctrl].gh) * cInfo[ctrl].fy + cInfo[ctrl].y
            w := (A_GuiWidth  - cInfo[ctrl].gw) * cInfo[ctrl].fw + cInfo[ctrl].w
            h := (A_GuiHeight - cInfo[ctrl].gh) * cInfo[ctrl].fh + cInfo[ctrl].h
            For i, a in cInfo[ctrl]["a"]
                Options .= a %a% A_Space
            GuiControl, % A_Gui ":" (Redraw ? "MoveDraw" : "Move"), % A_LoopField, % Options
        }
    }
}

Re: AutoXYWH() - Move control automatically when GUI resized

Posted: 25 Jun 2014, 15:55
by joedf
nice mod! :D

Re: AutoXYWH() - Move control automatically when GUI resized

Posted: 25 Jun 2014, 16:03
by guest3456
can probably use this at the top of scripts requiring later AHK versions:

Code: Select all

if (A_AhkVersion < "1.1.13.01")
   MsgBox, This script/func requires AHK v1.1.13.01 or greater
http://ahkscript.org/docs/Variables.htm#AhkVersion

Re: AutoXYWH() - Move control automatically when GUI resized

Posted: 26 Jun 2014, 06:06
by tmplinshi
@toralf
Thanks for share. Your version looks much better.

Re: AutoXYWH() - Move control automatically when GUI resized

Posted: 26 Jun 2014, 08:06
by toralf
Fame is all to you, you started this.

here is a another mod with variadic list. I removed the redraw option.

Code: Select all

; =================================================================================
; Function: AutoXYWH
;   Move and resize control automatically when GUI resizes.
; Parameters:
;   DimSize - Can be one or more of x/y/w/h  [followed by a fraction]
;   cList   - variadic list of ControlIDs separated
;             ControlID can be a control HWND, associated variable name, ClassNN or displayed text.
; Examples:
;   AutoXYWH("xy", "Btn1", "Btn2")
;   AutoXYWH("w0.5 h 0.75", hEdit, "displayed text", "vLabel", "Button1")
; ---------------------------------------------------------------------------------
; Release date: 2014-6-26           http://ahkscript.org/boards/viewtopic.php?t=1079
; Author      : tmplinshi (mod by toralf)
; requires AHK version : 1.1.13.01+
; =================================================================================
AutoXYWH(DimSize, cList*){
    static cInfo := {}
    For i, ctrl in cList {
        ctrlID := A_Gui ":" ctrl
        If ( cInfo[ctrlID].x = "" ){
            GuiControlGet, i, %A_Gui%:Pos, %ctrl%
            fx := fy := fw := fh := 0
            For i, dim in (a := StrSplit(RegExReplace(DimSize, "i)[^xywh]")))
                If !RegExMatch(DimSize, "i)" dim "\s*\K[\d.-]+", f%dim%)
                  f%dim% := 1
            cInfo[ctrlID] := { x:ix, fx:fx, y:iy, fy:fy, w:iw, fw:fw, h:ih, fh:fh, gw:A_GuiWidth, gh:A_GuiHeight, a:a }
        }Else If ( cInfo[ctrlID].a.1) {
            dgx := dgw := A_GuiWidth  - cInfo[ctrlID].gw  , dgy := dgh := A_GuiHeight - cInfo[ctrlID].gh
            For i, dim in cInfo[ctrlID]["a"]
                Options .= dim (dg%dim% * cInfo[ctrlID]["f" dim] + cInfo[ctrlID][dim]) A_Space
            GuiControl, %A_Gui%:MoveDraw, % ctrl, % Options
}    }    }

Re: AutoXYWH() - Move control automatically when GUI resized

Posted: 26 Jun 2014, 09:42
by joedf
Nice! It's shaping!

Re: AutoXYWH() - Move control automatically when GUI resized

Posted: 27 Jun 2014, 07:38
by just me
Awesome code! But, since vLabels, ClassNNs, and text are permitted as control identifiers, I suggest to consider the Gui.

Re: AutoXYWH() - Move control automatically when GUI resized

Posted: 27 Jun 2014, 08:00
by toralf
I was thinking of it too, but GuiControlGet works on the default Gui. I decided to leave it to the user to define a differnt Gui as default

Code: Select all

Gui, GuiName:Default
just before the function is called *not tested*. I assume in most cases this will not be nessecary, because the GuiSize thread will be set it's own Gui as the default. So only in the rare cases that you want to control a second gui size by resizing the first gui you would need to define a different default gui. (do not even know if that would work, since A_GuiWidth and A_GuiHeight would be of the first gui)
Does this makes sense?
Overall, I believe it is not required. Do you agree?

Re: AutoXYWH() - Move control automatically when GUI resized

Posted: 27 Jun 2014, 08:48
by just me
It's permitted to use the same vLabel and control text in different Guis. Also, ClassNNs like Edit1 or Button1 aren't necessarily unique. But only the first of two or more identical control identifiers will be stored, and possibly used for the wrong Gui. That's what I thought about.

Re: AutoXYWH() - Move control automatically when GUI resized

Posted: 28 Jun 2014, 12:11
by toralf
Good point. I'll fix it.

Re: AutoXYWH() - Move control automatically when GUI resized

Posted: 28 Jun 2014, 20:06
by toralf
I hope I fixed both of my two functions above. Could not test it yet, I'm only on my phone.

Re: AutoXYWH() - Move control automatically when GUI resized

Posted: 30 Jun 2014, 03:21
by just me
It's working on A32, U32, and U64.

Re: AutoXYWH() - Move control automatically when GUI resized

Posted: 01 Jul 2014, 14:36
by toralf
This version removes some of the flickering by reducing the MoveDraw to only controls of class 'Button' (since Groupboxes are of class 'Button').

Code: Select all

AutoXYWH(DimSize, cList*){  ; http://ahkscript.org/boards/viewtopic.php?t=1079
  static cInfo := {}
  If !cInfo[A_Gui].ClassNN.MaxIndex() {
    WinGet, CH, ControlListHwnd, 
    WinGet, CN, ControlList, 
    ACH := StrSplit(CH, "`n"), ACN := StrSplit(CN, "`n")
    Loop, % ACH.MaxIndex()
      If InStr(ACN[A_Index], "Button")   ;GroupBox have a ClassNN of 'Button'
        cInfo[A_Gui , "ClassNN" , ACH[A_Index]] := 1
  }
  For i, ctrl in cList {
    ctrlID := A_Gui ":" ctrl
    If ( cInfo[ctrlID].x = "" ){
        GuiControlGet, i, %A_Gui%:Pos, %ctrl%
        GuiControlGet, Hwnd, %A_Gui%:Hwnd, %ctrl%
        MMD := cInfo[A_Gui,"ClassNN",Hwnd] ? "MoveDraw" : "Move"
        fx := fy := fw := fh := 0
        For i, dim in (a := StrSplit(RegExReplace(DimSize, "i)[^xywh]")))
            If !RegExMatch(DimSize, "i)" dim "\s*\K[\d.-]+", f%dim%)
              f%dim% := 1
        cInfo[ctrlID] := { x:ix, fx:fx, y:iy, fy:fy, w:iw, fw:fw, h:ih, fh:fh, gw:A_GuiWidth, gh:A_GuiHeight, a:a , m:MMD}
    }Else If ( cInfo[ctrlID].a.1) {
        dgx := dgw := A_GuiWidth  - cInfo[ctrlID].gw  , dgy := dgh := A_GuiHeight - cInfo[ctrlID].gh
        For i, dim in cInfo[ctrlID]["a"]
            Options .= dim (dg%dim% * cInfo[ctrlID]["f" dim] + cInfo[ctrlID][dim]) A_Space
        GuiControl, % A_Gui ":" cInfo[ctrlID].m , % ctrl, % Options
} } }