I am having some problems with my reorder / delete plugin code in UCR, so I thought I would write this to test whether this Gui setup worked properly, without having all of the rest of the project get in the way.
As it turns out, everything seems fine with this version, so I guess I must have made a mistake in UCR - but I thought it worth posting here.
If anyone can make it glitch out, lemme know.
Code: Select all
#SingleInstance force
Gui +Hwndhwnd
mc := new MainClass(hwnd)
return
^Esc::
GuiClose:
ExitApp
class MainClass {
PluginHeight := 35
PluginWidth := 450
FrameWidth := this.PluginWidth + 50
Plugins := {} ; Holds plugin instances
PluginOrder := [] ; Holds order of plugins
__New(hMainGui){
this.MainGui := new WrappedGui(hMainGui)
this.MainGui.GuiCmd("+Resize")
this.AddButton := this.MainGui.AddControl("Button", this.AddPlugin.Bind(this), "Center w" this.FrameWidth " aw", "Add Plugin")
this.PluginFrame := new WrappedGui()
this.PluginFrame.GuiCmd("-Caption")
this.PluginFrame.GuiCmd("+VScroll")
this.PluginFrame.GuiCmd("Color", "Black")
this.MainGui.GuiCmd("Add", "Gui", "xm y+5 w" this.FrameWidth " h200 aw ah", this.PluginFrame.hwnd)
; You cannot remove a Gui if you add it with Gui, Add, Gui...
; So we have to use +Parent to attach plugins to the parent Gui
; We therefore use a Spacer GuiControl in the plugin area to force the scrollbar to the desired size
this.Spacer := this.PluginFrame.AddControl("Edit", 0, "x5 y0 w5 h0")
this.SetSpacerHeight(0)
this.MainGui.GuiCmd("Show", "x0 y0")
}
AddPlugin(){
scroll_pos := this.PluginFrame.GetScrollPos()
plugin := new Plugin(this)
this.Plugins[plugin.Guid] := plugin
this.PluginOrder.Push(plugin.Guid)
plugin_height := plugin.GetHeight()
ypos := this.Spacer.Height + 5
plugin.ypos := ypos
adjusted_pos := ypos - scroll_pos
plugin.GuiCmd("Show", "x15 y" adjusted_pos " w" this.PluginWidth " h" this.PluginHeight)
this.SetSpacerHeight(this.Spacer.Height + plugin_height + 5)
}
RemovePlugin(id){
scroll_pos := this.PluginFrame.GetScrollPos()
plugin := this.Plugins[id]
plugin_height := plugin.GetHeight()
plugin.GuiCmd("Destroy")
old_guid := plugin.Guid
old_order := this.GetPluginOrder(old_guid)
this.Plugins.Delete(old_guid)
max := this.PluginOrder.Length()
Loop % max - old_order {
id := old_order + A_Index
guid := this.PluginOrder[id]
plugin := this.Plugins[guid]
plugin.ypos -= plugin_height + 4
adjusted_pos := plugin.ypos - scroll_pos
plugin.GuiCmd("Show", "x15 y" adjusted_pos)
}
this.PluginOrder.RemoveAt(old_order)
this.SetSpacerHeight(this.Spacer.Height - plugin_height - 4)
}
ReorderPlugin(guid, dir){
scroll_pos := this.PluginFrame.GetScrollPos()
; Find the order of the plugin that the user clicked on
passed_order := this.GetPluginOrder(guid)
if (passed_order == 0 || (dir == -1 && passed_order == 1) || (dir == 1 && passed_order == this.PluginOrder.Length()))
return ; top tried to move up bottom tried to move down
; Gui swapping is handled as if the user had always clicked Move Down
; If user clicks Move Up, swap the inputs
if (dir == - 1){
top_guid := this.PluginOrder[passed_order - 1]
bot_guid := guid
} else {
top_guid := guid
bot_guid := this.PluginOrder[passed_order + 1]
}
top_plugin := this.Plugins[top_guid]
bot_plugin := this.Plugins[bot_guid]
; Move the "top" gui down and the "bot" gui up
top_y := top_plugin.ypos
bot_plugin.Move(top_y, scroll_pos)
top_plugin.Move(bot_plugin.ypos + bot_plugin.GetHeight() + 4, scroll_pos) ; ToDo - Fix Bodge for GetHeight()
; Swap the PluginOrder
top_id := this.PluginOrder.RemoveAt(passed_order)
this.PluginOrder.InsertAt(passed_order + dir, top_id)
}
SetSpacerHeight(height){
this.Spacer.Height := height
this.Spacer.CtrlCmd("Move", "h" this.Spacer.Height)
}
GetPluginOrder(guid){
for i, candidate in this.PluginOrder {
if (candidate == guid){
return i
}
}
return 0
}
}
class Plugin extends WrappedGui {
ypos := 0
__New(parent){
static short_id := 1
this.Guid := CreateGuid()
this.Parent := parent
base.__New(0)
this.AddControl("Text", 0, "y10", "Plugin #" short_id " - " this.Guid)
this.AddControl("Button", parent.RemovePlugin.Bind(parent, this.Guid), "x+5 yp-5", "Remove")
this.AddControl("Button", parent.ReorderPlugin.Bind(parent, this.Guid, -1), "x+5 yp", "Up")
this.AddControl("Button", parent.ReorderPlugin.Bind(parent, this.Guid, 1), "x+5 yp", "Down")
this.GuiCmd("-Caption")
this.GuiCmd("+Parent" parent.hwnd)
this.GuiCmd("Show", "Hide") ; Force layout, so we can get size
short_id++
}
Move(ypos, scroll_pos){
this.GuiCmd("Show", "x15 y" ypos - scroll_pos)
this.ypos := ypos
}
}
class WrappedGui {
__New(hwnd := 0, options := ""){
if (hwnd == 0){
Gui, New, hwndhwnd
}
this.hwnd := hwnd
}
GuiCmd(cmd, aParams*){
Gui, % this.hwnd ":" cmd, % aParams[1], % aParams[2], % aParams[3]
}
AddControl(type, callback := 0, aParams*){
return new WrappedControl(this, type, callback, aParams*)
}
GetScrollPos(){
static SCROLLINFO:="UINT cbSize;UINT fMask;int nMin;int nMax;UINT nPage;int nPos;int nTrackPos"
,scroll:=Struct(SCROLLINFO,{cbSize:sizeof(SCROLLINFO),fMask:4})
GetScrollInfo(this.hwnd,true,scroll[])
return scroll.nPos
}
GetHeight(){
ControlGetPos,,,,h,,% "ahk_id " this.hwnd
return h
}
}
class WrappedControl {
__New(parent, type, callback := 0, aParams*){
this.Parent := parent
Gui, % this.Parent.hwnd ":Add", % type, % "hwndhwnd " aParams[1], % aParams[2]
this.hwnd := hwnd
if (callback != 0){
this.CtrlCmd("+g", callback)
}
}
CtrlCmd(cmd, param3){
GuiControl, % cmd, % this.hwnd, % param3
}
}
CreateGUID(){
VarSetCapacity(foo_guid, 16, 0)
if !(DllCall("ole32.dll\CoCreateGuid", "Ptr", &foo_guid))
{
VarSetCapacity(tmp_guid, 38 * 2 + 1)
DllCall("ole32.dll\StringFromGUID2", "Ptr", &foo_guid, "Ptr", &tmp_guid, "Int", 38 + 1)
fin_guid := StrGet(&tmp_guid, "UTF-16")
}
return SubStr(fin_guid, 2, 36)
}