A VB/VBA-style container GroupBox for AutoHotkey v2.
Native AHK GroupBox controls are purely visual — moving the frame does not move the controls placed inside it, and there is no way to hide, disable, or destroy a group and its contents as a single unit. This class wraps a GroupBox and tracks every control added to it, so the whole group behaves like a real container, similar to a Frame in VB6/VBA:
Move()moves the frame and every attached control togetherShow()/Hide()toggles visibility of the frame and its controls togetherEnable()/Disable()toggles interactivity of the frame and its controls togetherSetTitle()updates the frame captionDestroy()removes the frame and every attached control from the windowRemove()detaches a single control from the group without destroying it
- AutoHotkey v2.0 or later
Copy GroupBox.ahk into your project folder and include it:
#Requires AutoHotkey v2.0
#Include GroupBox.ahk#Requires AutoHotkey v2.0
#Include GroupBox.ahk
myGui := Gui("+Resize", "GroupBox Demo")
CreateGroup() {
global grp, lblName, edtName, chkActive
if IsSet(grp)
try grp.Destroy()
grp := GroupBox(myGui, 20, 20, 300, 150, "User Info")
lblName := myGui.AddText("x0 y0 w80", "Name:")
edtName := myGui.AddEdit("x0 y0 w180 h24")
chkActive := myGui.AddCheckbox("x0 y0", "Active")
grp.Add(lblName, 14, 30)
grp.Add(edtName, 94, 26)
grp.Add(chkActive, 14, 64)
}
CreateGroup()
myGui.AddButton("x370 y20 w120 h30", "Move Group")
.OnEvent("Click", (*) => grp.Move(50, 100))
myGui.AddButton("x370 y60 w120 h30", "Disable Group")
.OnEvent("Click", (*) => grp.Disable())
myGui.AddButton("x370 y100 w120 h30", "Enable Group")
.OnEvent("Click", (*) => grp.Enable())
myGui.AddButton("x370 y140 w120 h30", "Reset Group")
.OnEvent("Click", (*) => CreateGroup())
myGui.AddButton("x370 y180 w120 h30", "Destroy Group")
.OnEvent("Click", (*) => grp.Destroy())
myGui.Show("w520 h280")Moving, hiding, or disabling grp now affects the frame and every control added to it, as a single unit.
Creates a new GroupBox container.
| Parameter | Type | Description |
|---|---|---|
gui |
Gui | The Gui object this group belongs to. |
x, y |
Integer | Top-left position of the frame. |
w, h |
Integer | Width and height of the frame. |
title |
String | Caption text shown on the frame. Optional. |
opts |
String | Additional GuiControl options appended to the GroupBox. Optional. |
If opts includes a native state option such as +Hidden or +Disabled, the group's .Visible/.Enabled state is read back from the resulting control, so it stays accurate from the start instead of assuming defaults.
Attaches a control to the group so it moves, shows/hides, enables/disables, and gets destroyed together with the group.
ctrl— a control already created viagui.AddXxx().relX,relY— position relative to the group's top-left corner. Either give both or give neither:- Both given: the control is moved to
group.X + relX,group.Y + relY. - Both omitted: the control's current position is kept, and the offset is inferred from it.
- Giving only one of the two throws a
ValueError.
- Both given: the control is moved to
- If the group is currently hidden or disabled, the control is immediately hidden or disabled to match.
- Returns the same control, so calls can be chained.
grp.Add(edtName, 94, 26) ; explicit offset
grp.Add(edtName) ; offset inferred from edtName's current positionMoves the frame and every attached control, preserving each control's relative offset. Width and height may be changed at the same time.
grp.Move(340, 200) ; reposition only
grp.Move(340, 200, 400, 220) ; reposition and resizeShows or hides the frame and every attached control together.
Enables or disables (greys out) the frame and every attached control together.
Changes the frame's caption text.
Destroys the frame and every attached control, removing them from the window. Calling Destroy() again on an already-destroyed group is a harmless no-op. Calling any other method (Move(), Add(), Show(), Hide(), Enable(), Disable(), SetTitle(), Remove()) on a destroyed group throws a clear error instead of failing with a cryptic native one.
Detaches ctrl from the group without destroying it. The control stays on the window but no longer follows Move(), Show()/Hide(), Enable()/Disable(), or Destroy(). Returns true if the control was found and detached, false otherwise.
Retrieves the group's current position and size in one call, matching the signature of native control GetPos().
Forces a repaint of the frame and every attached control by redrawing the parent Gui window. Called automatically at the end of Move(); call it manually if a control's appearance needs refreshing without changing its position. Does nothing while the group is hidden.
| Property | Type | Description |
|---|---|---|
.X |
Integer | Current left position. |
.Y |
Integer | Current top position. |
.W |
Integer | Current width. |
.H |
Integer | Current height. |
.Title |
String | Current caption text. |
.Visible |
Boolean | Whether the group is currently shown. |
.Enabled |
Boolean | Whether the group is currently enabled. |
.Count |
Integer | Number of controls currently attached. |
GroupBox_Examples.ahk is a runnable demo covering every method above, organized into tabs:
- Basics —
Add()with an explicit offset vs. an inferred one - Move — translating and resizing a group
- Visibility —
Show()/Hide() - Enable/Disable — toggling interactivity
- Title —
SetTitle()and reading.Title - Remove — detaching a control without destroying it
- Destroy — tearing down and rebuilding a group at runtime
- Properties — reading every read-only property live
Run it with GroupBox.ahk in the same folder.
- Initial release
- AHK v2 control objects have no built-in
Destroy()method. Only theGuiobject itself does.GroupBox.Destroy()works around this internally usingDllCall("DestroyWindow", ...)on each control's handle — this is a limitation of AutoHotkey itself, not of this library, but it's worth knowing if you extend the class. - After
Destroy(), don't call other methods on the sameGroupBoxinstance without recreating it first. Doing so now throws a clear, catchable error ("This GroupBox has already been destroyed.") instead of failing silently or with a cryptic native one. If a button or event handler might run after the group could have been destroyed, either recreate the group first (see Tab 7 inGroupBox_Examples.ahk) or wrap the call intry/catch. - After
Destroy(), the destroyed controls' AHK objects may still linger in the parentGuiobject's own internalControlscollection, sinceDllCall("DestroyWindow", ...)removes the window but does not deregister it from AHK's bookkeeping. This is rarely an issue in practice, but if you iteratemyGui.Controlselsewhere in your script, be aware you may encounter a destroyed control whose.Hwndis no longer valid. - Controls created at runtime inside a
Tab3page must be created while the correct tab is the active context (tab.UseTab(n)) — including when rebuilding a group afterDestroy(). Creating controls outside that context attaches them to no tab, making them visible on every tab at once. See Tab 7 inGroupBox_Examples.ahkfor a worked example. - Nesting one
GroupBoxinside another is not directly supported.Add()expects a nativeGui.Controlobject (as returned bygui.AddXxx()), not anotherGroupBoxwrapper instance. Add(ctrl, relX, relY)requires either bothrelX/relYor neither — passing only one raises aValueErrorby design, to avoid silently guessing at a partially-specified offset.
See the LICENSE file for license details.
Contributions are welcome! If you'd like to add features, fix bugs, or improve the code, feel free to open a pull request.
Author: Mesut Akcan
Email: makcan@gmail.com
Blog: mesutakcan.blogspot.com
YouTube: youtube.com/mesutakcan
GitHub: mesutakcan