출처 : http://v1.autohotkey.co.kr/cgi/board.php?bo_table=script&wr_id=1987
오핫사사의 만약에님이 만드신건데 오브젝트 단위로 파일 저장 및 로딩 할수 있어서 오브젝트로 설정 관리 하시는 분들에게는 매우 편리할 것 같습니다.
TreeView() 메소드를 사용하면 오브젝트 디버깅에도 유용합니다.
;-------------------------------------------------------------------------------
; 예제
#SingleInstance Force
oTest := [{a: 123}, {b: 456}, {c: 789}]
sJson := CJson.stringify(oTest)
MsgBox % sJson
F1::
CJson.save(oTest, "oTest.ini")
return
F2::
oTest := CJson.load("oTest.ini")
CJson.TreeView(oTest)
return
ESC::ExitApp
;-------------------------------------------------------------------------------
class CJson
{
load(file)
{
if (FileExist(file))
{
FileRead text, % file
return this.parse(text)
}
return {}
}
save(obj, file)
{
if (FileExist(file))
FileDelete % file
FileAppend % res := this.stringify(obj), % file
return res
}
parse(t, r="")
{
o := {}
if (r = "")
r := {p: 1}
while (r.p := RegExMatch(t, "`as)((?<=[^\\]))""(?P<k>.*?)(?1)""\s*:\s*"
. "(?:(?P<o>(?1)\{)|(?1)""(?P<v>.*?)(?1)"")|(?P<c>(?1)\})", _, r.p)+StrLen(_))
if (_c)
return o
else
o[this.unescape(_k)] := _o ? this.parse(t, r) : this.unescape(_v)
}
stringify(o, t=" ", x="", r="")
{
if (IsObject(o))
{
if (r = "")
r := {(&o): true}
s := "{"
for k, v in o
s .= c "`n" x t """" this.escape(k) """: " (r[&v] ? """[Object]""" : this.stringify(v, t, x t, r))
, c := (r.c ? (r.c := "") : ",")
return s "`n" x "}", r.c := true
}
else
return """" this.escape(o) """"
}
escape(v)
{
return RegExReplace(v, """|\{|\}", "\$0")
}
unescape(v)
{
return RegExReplace(v, "\\(""|\{|\})", "$1")
}
TreeView(Obj, hParent="", Option="Expand", r="")
{
if (r = "")
{
Gui +LastFound
hWnd := WinExist()
loop 99
Gui % (nDefaultGui := A_Index) ":+LastFoundExist"
until (WinExist() = hWnd)
loop 99
Gui % (nGui := A_Index) ":+LastFoundExist"
until (WinExist() = 0)
Gui % nGui ":Default"
Gui +ToolWindow +Resize +LabelCJson_TreeView
Gui Margin, -1, -1
Gui Add, TreeView, w400 r40 hWndhWnd
this.hTreeView[nGui] := hWnd
Gui Show, x0 y0
}
if (IsObject(Obj))
{
if (r = "")
r := {(&Obj): true}
for k, v in Obj
{
if (r[&v])
TV_Add("[Object]", hParent, Option)
else if (IsObject(v))
this.TreeView(v, TV_Add(k, hParent, Option), Option, r)
else
TV_Add(k " : " v, hParent, Option)
}
}
if (nDefaultGui)
Gui % nDefaultGui ":Default"
}
TreeViewSize()
{
Anchor(this.hTreeView[A_Gui], "wh")
}
TreeViewClose()
{
Gui % A_Gui ":Destroy"
this.hTreeView[A_Gui] := ""
}
}
CJson_TreeViewSize:
CJson.TreeViewSize()
return
CJson_TreeViewEscape:
CJson_TreeViewClose:
CJson.TreeViewClose()
return
/*
Function: Anchor
Defines how controls should be automatically positioned relative to the new dimensions of a window when resized.
Parameters:
cl - a control HWND, associated variable name or ClassNN to operate on
a - (optional) one or more of the anchors: 'x', 'y', 'w' (width) and 'h' (height),
optionally followed by a relative factor, e.g. "x h0.5"
r - (optional) true to redraw controls, recommended for GroupBox and Button types
Examples:
> "xy" ; bounds a control to the bottom-left edge of the window
> "w0.5" ; any change in the width of the window will resize the width of the control on a 2:1 ratio
> "h" ; similar to above but directrly proportional to height
Remarks:
To assume the current window size for the new bounds of a control (i.e. resetting) simply omit the second and third parameters.
However if the control had been created with DllCall() and has its own parent window,
the container AutoHotkey created GUI must be made default with the +LastFound option prior to the call.
For a complete example see anchor-example.ahk.
License:
- Version 4.60a <http://www.autohotkey.net/~polyethene/#anchor>
- Dedicated to the public domain <http://creativecommons.org/licenses/publicdomain/>
*/
Anchor(i, a = "", r = false) {
static c, cs = 12, cx = 255, cl = 0, g, gs = 8, gl = 0, gpi, gw, gh, z = 0, k = 0xffff
If z = 0
VarSetCapacity(g, gs * 99, 0), VarSetCapacity(c, cs * cx, 0), z := true
If (!WinExist("ahk_id" . i)) {
GuiControlGet, t, Hwnd, %i%
If ErrorLevel = 0
i := t
Else ControlGet, i, Hwnd, , %i%
}
VarSetCapacity(gi, 68, 0), DllCall("GetWindowInfo", "UInt", gp := DllCall("GetParent", "UInt", i), "UInt", &gi)
, giw := NumGet(gi, 28, "Int") - NumGet(gi, 20, "Int"), gih := NumGet(gi, 32, "Int") - NumGet(gi, 24, "Int")
If (gp != gpi) {
gpi := gp
Loop, %gl%
If (NumGet(g, cb := gs * (A_Index - 1)) == gp) {
gw := NumGet(g, cb + 4, "Short"), gh := NumGet(g, cb + 6, "Short"), gf := 1
Break
}
If (!gf)
NumPut(gp, g, gl), NumPut(gw := giw, g, gl + 4, "Short"), NumPut(gh := gih, g, gl + 6, "Short"), gl += gs
}
ControlGetPos, dx, dy, dw, dh, , ahk_id %i%
Loop, %cl%
If (NumGet(c, cb := cs * (A_Index - 1)) == i) {
If a =
{
cf = 1
Break
}
giw -= gw, gih -= gh, as := 1, dx := NumGet(c, cb + 4, "Short"), dy := NumGet(c, cb + 6, "Short")
, cw := dw, dw := NumGet(c, cb + 8, "Short"), ch := dh, dh := NumGet(c, cb + 10, "Short")
Loop, Parse, a, xywh
If A_Index > 1
av := SubStr(a, as, 1), as += 1 + StrLen(A_LoopField)
, d%av% += (InStr("yh", av) ? gih : giw) * (A_LoopField + 0 ? A_LoopField : 1)
DllCall("SetWindowPos", "UInt", i, "Int", 0, "Int", dx, "Int", dy
, "Int", InStr(a, "w") ? dw : cw, "Int", InStr(a, "h") ? dh : ch, "Int", 4)
If r != 0
DllCall("RedrawWindow", "UInt", i, "UInt", 0, "UInt", 0, "UInt", 0x0101) ; RDW_UPDATENOW | RDW_INVALIDATE
Return
}
If cf != 1
cb := cl, cl += cs
bx := NumGet(gi, 48), by := NumGet(gi, 16, "Int") - NumGet(gi, 8, "Int") - gih - NumGet(gi, 52)
If cf = 1
dw -= giw - gw, dh -= gih - gh
NumPut(i, c, cb), NumPut(dx - bx, c, cb + 4, "Short"), NumPut(dy - by, c, cb + 6, "Short")
, NumPut(dw, c, cb + 8, "Short"), NumPut(dh, c, cb + 10, "Short")
Return, true
}
감사합니다^^