; FM2.07 ;==============================================================================; ;================================ xpath v3 ====================================; ;==============================================================================; /* Title: XPath Quick Reference License: - Version 3.13c by Titan - GNU General Public License 3.0 or higher */ /* Function: xpath Selects nodes and attributes from a standard xpath expression. Parameters: doc - an xml object returned by xpath_load() step - a valid XPath 2.0 expression set - (optional) text content to replace the current selection Returns: The XML source of the selection. If the content was set to be modified the previous value will be returned. Remarks: Since multiple return values are seperated with a comma, any found within the text content will be entity escaped as ,. To get or set the text content of a node use the text function, e.g. /root/node/text(); this behaviour is always assumed within predicates. For performance reasons count() and last() do not update with the creation of new nodes so you may need to alter the results accordingly. */ xpath(ByRef doc, step, set = "") { static sc, scb = "" ; use EOT (\x04) as delimiter If step contains %scb% ; i.e. illegal character Return sid := scb . &doc . ":" ; should be unique identifier for current XML object If (InStr(step, "select:") == 1) { ; for quick selection stsl = 1 StringTrimLeft, step, step, 7 } If (InStr(step, "/") == 1) str = 1 ; root selected Else { StringGetPos, p, sc, %sid% ; retrieve previous path If ErrorLevel = 1 t = / Else StringMid, t, sc, p += StrLen(sid) + 1, InStr(sc, scb, "", p + 2) - p step = %t%/%step% } ; normalize path e.g. /root/node/../child/. becomes /root/child: step := RegExReplace(step, "(?<=^|/)(?:[^\[/@]+/\.{2}|\.)(?:/|$)|^.+(?=//)") If (str == 1 or stsl == 1) { ; if not relative path and no select: ; remove last node and trailing attributes and functions: xpr := RegExReplace(step, (str == 1 and stsl != 1 ? "/(?:\w+:)?\w+(?:\[[^\]]*])?" : "") . "(?:/@.*?|/\w+\(\))*$") StringReplace, xpr, xpr, [-1], [1], All ; -1 become just 1 StringReplace, xpr, xpr, [+1], [last()], All ; +1 becomes last() StringGetPos, p, sc, %sid% If ErrorLevel = 1 sc = %sc%%sid%%xpr%%scb% ; add record or update as necessary: Else sc := SubStr(sc, 1, p += StrLen(sid)) . xpr . SubStr(sc, InStr(sc, scb, "", p)) } ; for unions call each operand seperately and join results: If (InStr(step, "|")) { StringSplit, s, step, |, `n`t  `r Loop, %s0% res .= xpath(doc, s%A_Index%, set) . "," Return, SubStr(res, 1, -1) } Else If (InStr(step, "//") == 1) { ; for wildcard selectors use regex searching mode: StringTrimLeft, step, step, 2 re = 1 rew = 1 xp = /(?:(?:\w+:)?\w+)*/ } NumPut(160, doc, 0, "UChar") ; unmask variable ; resolve xpath components to: absolute node path, attributes and predicates (if any) Loop, Parse, step, / { s = %A_LoopField% If (InStr(s, "*") == 1) ; regex mode for wildcards { re = 1 s := "(?:\w+:)?\w+" . SubStr(s, 2) } Else If (InStr(s, "@") == 1) { ; if current step is attribute: StringTrimLeft, atr, s, 1 Continue } StringGetPos, p, s, [ ; look for predicate opening [...] If ErrorLevel = 0 { If s contains [+1],[-1] ; for child nodes record creation instructions in a list { If A_Index = 2 ; root node creation { StringLeft, t, s, p t = <%t%/:: > If (InStr(s, "+1")) { If doc = doc = . doc = %doc%%t% } Else doc = .%t%%doc% StringLeft, s, s, InStr(s, "[") - 1 } Else { nw = %nw%%s% Continue } } Else { ; i.e. for conditional predicates If (InStr(s, "last()")) { ; finding last node StringLeft, t, s, p t := "<" . SubStr(xp, 2) . t . "/:: " If re ; with regex: { os = 0 Loop If (!os := RegExMatch(doc, t, "", 1 + os)) { t = %A_Index% Break } t-- } Else { ; otherwise using StringReplace StringReplace, doc, doc, %t%, %t%, UseErrorLevel t = %ErrorLevel% } If (RegExMatch(s, "i)last\(\)\s*\-\s*(\d+)", a)) ; i.e. [last() - 2] StringReplace, s, s, %a%, % t - a1 Else StringReplace, s, s, last(), %t% } ; concat. the predicate to the list against the current absolute path: ax = %ax%%xp%%s% StringLeft, s, s, p } } Else If (InStr(s, "()")) { ; if step is function, add to list fn = %fn%+%s% ; use + prefix to prevent overlapping naming conflicts Continue } ; finally, if step is not any of the above, assume it's the name of a child node xp = %xp%%s%/ ; ... and add to list, forming the absolute path } If (xp == "" or xp == "/") ; i.e. error cases Return ; remove initial root selector (/) as this is how the parser works by default: StringTrimLeft, xp, xp, 1 StringTrimRight, ax, ax, 1 StringTrimRight, nw, nw, 1 ct = 0 ; counter os = 0 ; offset for main loop starts at zero Loop { ; find offset of next element, and its closing tag offset: If re os := RegExMatch(doc, "<" . xp . ":: ", "", 1 + os) , osx := RegExMatch(doc, "", rem, os) + StrLen(rem) Else { StringGetPos, osx, doc, , , os := InStr(doc, "<" . xp . ":: ", true, 1 + os) osx += 4 + StrLen(xp) } If os = 0 ; stop looping when no more tags are found Break ; predicate parser: If ax != { sk = 0 Loop, Parse, ax, ] ; for each predicate { ; split components to: (1) path, (2) selector, (3) operator, (4) quotation char, (5) operand If (!RegExMatch(A_LoopField, "/?(.*?)\[(.+?)(?:\s*([<>!=]{1,2})\s*(['""])?(.+)(?(4)\4))?\s*$", a)) Continue a1 = %a1%/ If re RegExMatch(rem, "(?<=^", "", os) - t xpf := "<" . a1 . ":: " ; get index of current element within parent node: StringReplace, sub, sub, %xpf%, %xpf%, UseErrorLevel If a2 != %ErrorLevel% sk = 1 Continue } StringReplace, xp, xp, /, /, UseErrorLevel t = %ErrorLevel% StringReplace, a1, a1, /, /, UseErrorLevel ; extract result for deep analysis If t = %ErrorLevel% ; i.e. /root/node[child='test'] StringMid, sub, doc, os, osx - os Else StringMid, sub, doc , t := InStr(SubStr(doc, 1, os), "<" . a1 . ":: ", true, 0) , InStr(doc, "", true, t) + 1 If a2 = position() sub = %i% Else If (InStr(a2, "@") == 1) ; when selector is an attribute: RegExMatch(SubStr(sub, 1, InStr(sub, ">")) , a3 == "" ? "\b" . SubStr(a2, 2) . "=([""'])[^\1]*?\1" : "\b(?<=" . SubStr(a2, 2) . "=([""']))[^\1]+?(?=\1)", sub) Else ; otherwise child node: { If a2 = . ; if selector is current node don't append to path: a2 = / Else a2 = %a2%/ StringMid, sub, sub , t := InStr(sub, ">", "", InStr(sub, "<" . a1 . a2 . ":: ", true) + 1) + 1 , InStr(sub, "", true) - t } ; dynamic mini expression evaluator: sk += !(a3 == "" ? (sub != "") : a3 == "=" ? sub == a5 : a3 == "!=" ? sub != a5 : a3 == ">" ? sub > a5 : a3 == ">=" ? sub >= a5 : a3 == "<" ? sub < a5 : a3 == "<=" ? sub <= a5) } If sk != 0 ; if conditions were not met for this result, skip it Continue } If nw != ; for node creation { If re nwp := SubStr(rem, 3, -1) Else nwp = %xp% Loop, Parse, nw, ] { StringLeft, nwn, A_LoopField, InStr(A_LoopField, "[") - 1 nwn = %nwn%/ nwt = <%nwp%%nwn%:: > If (t := InStr(A_LoopField, "-1") ? InStr(doc, ">", "", InStr(doc, "<" . nwp . ":: ", true, os) + 1) + 1 : InStr(doc, "", true, os)) os := t StringLen, osx, nwt osx += os doc := SubStr(doc, 1, os - 1) . nwt . SubStr(doc, os) nwp = %nwp%%nwn% } StringLen, t, nwp If (InStr(fn, "+text()") and atr == "") os += t + 5, osx -= t + 3 } If atr != { ; extract attribute offsets, with surrounding declaration if text() is not used: If (t := RegExMatch(SubStr(doc, os, InStr(doc, ">", "", os) - os), InStr(fn, "+text()") ? "(?<=\b" . atr . "=([""']))[^\1]*?(?=\1)" : "\b" . atr . "=([""'])[^\1]*?\1", rem)) os += t - 1, osx := os + StrLen(rem) Else { ; create attribute os := InStr(doc, ">", "", os + 1) , doc := SubStr(doc, 1, os - 1) . " " . atr . "=""""" . SubStr(doc, os) , osx := ++os + StrLen(atr) + 3 If (InStr(fn, "+text()")) osx := os += StrLen(atr) + 2 } } Else If (InStr(fn, "+text()") and nw == "") ; for text content: os := InStr(doc, ">", "", os) + 1, osx := InStr(doc, re ? rem : "", true, os) If InStr(fn, "+index-of()") ; get index rather than content sub = %A_Index% Else StringMid, sub, doc, os, osx - os ; extract result If (InStr(fn, "+count()")) ; increment counter if count() function is used ct++ Else res = %res%%sub%, ; ... and concat to list If (set != "" or InStr(fn, "+remove()")) ; modify or remove... setb = %setb%%os%.%osx%| ; mark for modification } If setb != { If (InStr(set, "node:") == 1) { set := SubStr(xpath(doc, SubStr(set, 6) . "/rawsrc()"), 2) StringReplace, set, set, <, <%xp%, All StringReplace, set, set, <%xp%/, ", "", setp1) + 2 doc := SubStr(doc, 1, setp1 - 1) . set . SubStr(doc, setp2) ; dissect then insert new value } } If (InStr(fn, "+count()")) res = %ct%, ; trailing char since SubStr is used below nsid := scb . &doc . ":" ; update sid as necessary If nsid != %sid% StringReplace, sc, sc, %sid%, %nsid% NumPut(0, doc, 0, "UChar") ; remask variable to prevent external editing StringTrimRight, res, res, 1 If (InStr(fn, "+rawsrc()")) { StringTrimLeft, t, xpr, 1 StringReplace, res, res, <%t%/, <, All StringReplace, res, res, ]*)><\/\1>", "<$1$2 />") ; fuse empty nodes xml := RegExReplace(xml, "\s{2,}", " ") ;xml := RegExReplace(xml, " (?=(?:\w+:)?\w+=['""])") ; remove prepending whitespace on attributes xml := RegExReplace(xml, "^\s+|\s+$") ; remove start and leading whitespace If InStr(xml, "`n%xml% xml = `n%xml% StringReplace, xml, xml, `r, , All ; normalize linefeeds: StringReplace, xml, xml, `n, `r`n, All sp := " " StringLen, sl, sp s = VarSetCapacity(sxml, StrLen(xml) * 1.1) Loop, Parse, xml, <, `n`t  `r { If A_LoopField = Continue If (sb := InStr(A_LoopField, "/") == 1) StringTrimRight, s, s, sl sxml = %sxml%`n%s%<%A_LoopField% If sb StringTrimRight, s, s, sl If (InStr(A_LoopField, "?") != 1 and InStr(A_LoopField, "!") != 1 and !InStr(A_LoopField, "/>")) s .= sp } StringTrimLeft, sxml, sxml, 1 ; sxml := RegExReplace(sxml, "(\n(?:" . sp . ")*<((?:\w+:)?\w+\b)[^<]+?)\n(?:" ; . sp . ")*", "$1") StringReplace, sxml, sxml, ,, `,, All ; unescape ',' If src = ; if save path not specified return the XML document: Return, sxml FileDelete, %src% ; delete existing file FileAppend, %sxml%, %src% ; create new one Return, ErrorLevel ; return errors, if any } /* Function: xpath_load Loads an XML document. Parameters: doc - a reference to the loaded XML file as a variable, to be used in other functions src - (optional) the document to load, this can be a file name or a string, if omitted the first paramter is used as the source Returns: False if there was an error in loading the document, true otherwise. */ xpath_load(ByRef doc, src = "") { If src = ; if source is empty assume the out variable is the one to be loaded src = %doc% Else If FileExist(src) ; otherwise read from file (if it exists) FileRead, src, %src% If src not contains <,> Return, false ; combined expressions slightly improve performance: src := RegExReplace(src, "<((?:\w+:)?\w+\b)([^>]*)\/\s*>", "<$1$2>") ; defuse nodes , VarSetCapacity(doc, VarSetCapacity(xml, StrLen(src) * 1.5) * 1.1) ; pre-allocate enough space Loop, Parse, src, < ; for each opening tag: { If (A_Index == 2 and InStr(A_LoopField, "?xml") == 1) Continue Else If (InStr(A_LoopField, "?") == 1) ; ignore all other processor instructions xml = %xml%<%A_LoopField% Else If (InStr(A_LoopField, "![CDATA[") == 1) { ; escape entities in CDATA sections cdata := SubStr(A_LoopField, 9, -3) StringReplace, cdata, cdata, ", ", All StringReplace, cdata, cdata, &, &, All StringReplace, cdata, cdata, ', ', All StringReplace, cdata, cdata, <, <, All StringReplace, cdata, cdata, >, >, All xml = %xml%%cdata% } Else If (!pos := RegExMatch(A_LoopField, "^\/?(?:\w+:)?\w+", tag)) ; if this isn't a valid tag: { If A_LoopField is not space xml = %xml%<%A_LoopField% ; convert to escaped entity value } Else { StringMid, ex, A_LoopField, pos + StrLen(tag) ; get tag name If InStr(tag, "/") = 1 { ; if this is a closing tag: xml = %xml%= 16) ;(A_TimeIdle >= 4000) { SetTimer, tipGui_killTip, Off ToolTip,,,, 20 tipGui_killTipCounter=0 } Return } tipGui_getClassNN(tipControl, g=1) ;tipControl = text/var,Hwnd ;g = gui number, default=1 { Gui,%g%:+LastFound guiID := WinExist() ;get the id for the gui WinGet, List_controls, ControlList StringReplace, List_controls, List_controls, `n, `,, All ;if id supplied do nothing special IfNotInString, tipControl, %List_controls% ;must be the text/var - get the ID { mm := A_TitleMatchMode SetTitleMatchMode, 3 ;exact match only ControlGet, o, hWnd,, %tipControl% ;get the id SetTitleMatchMode, %mm% ;restore previous setting If(o) ;found match { tipControl := o ;set sought-after id } } Loop, Parse, List_controls, CSV { ControlGet, o, hWnd,, %A_LoopField% ;get the id of current classnn If(o = tipControl) ;if it is the one we want { Return A_Loopfield ;return the classnn } } } ;==============================================================================; ;============================== TreeView eXtension ============================; ;==============================================================================; ;Title: TreeViewX ; TreeViewX extends standard TreeView control to support moving, deleting & inserting. ;---------------------------------------------------------------------------------------- ; Function: TVX ; Initialisation function. Mandatory to call before you show the TreeView. ; ; Parameters: ; pTree - AHK name of the TreeView control ; pSub - Subroutine for TreeViewX, the same rules as in g. ; pOptions - String containing space delimited options for setting up TreeViewX ; pUserData - Base name of the array holding user data. ; This array is indexed using tree view item handles. ; ; Options: ; HasRoot - TreeViewX has root item - the one containing all other items. ; Root item can't be moved, edited or delited, and items can not ; be moved or created outside of it. This option need to be set ; after root is already added to the menu, as TreeViewX need to ; know the root menu handle. ; ; CollapseOnMove - When moving item out of of its container, this option makes container collapse ; EditOnInsert - Automaticaly enters edit mode upon insertion of new item ; ; Example: ;> ;> TVX("MyTree", "Handler", "HasRoot CollapseOnMove") ;> TVX( pTree, pSub, pOptions="", pUserData="", pUserDat2="", pUserDat3="", pUserDat4="", pIconData="" ) { global if InStr(pOptions, "HasRoot") { TVX_HasRoot := 1 TVX_root := TV_GetNext() } ; if InStr(pOptions, "CollapseOnMove") ; TVX_CollapseOnMove := 1 ; if InStr(pOptions, "EditOnInsert") ; TVX_EditOnInsert := 1 TVX_userData := pUserData TVX_userDat2 := pUserDat2 TVX_userDat3 := pUserDat3 TVX_userDat4 := pUserDat4 TVX_iconData := pIconData TVX_sub := pSub GuiControl, +AltSubmit +ReadOnly +gTVX_OnEvent, %pTree% } ;---------------------------------------------------------------------------------------- ; Function: Walk ; Walk the menu and rise events ; ; Parameters: ; root - menu to iterate, can be simple item also ; label - event handler ; event_type - event argument 1 - Event type ; event_param - event argument 2 - Item upon which event is rised ; ; ; Type Param ; ; + - Iteration start, root handle ; M - Menu item, menu handle ; I - Item, item handle ; E - End of menu menu handle (pseudo item) ; - - Iteration end root handle (pseudo item) ; TVX_Walk(root, label, ByRef event_type, ByRef event_param){ local n, t, p, c, pref, bSetEnd, lastParent, rootsParent, tmp ; start event for menus event_type := "+" event_param := root GoSub %label% if !TV_GetChild(root) return ; this will be exit condition. If we come to roots parent, stop walking. rootsParent := TV_GetParent(root) lastParent := root c := root loop { c := TV_GetNext(c, "Full") TV_GetText(tmp, c) ; Check if this item is submenu. If so, set the lastParent if ( TV_GetChild(c) ){ lastParent := c event_type := "M" } else event_type := "I" ; not a submenu, it is normal item event_param := c GoSub %label% ; Check if c is the last item in the current submenu ; Do so by taking the next item and checking its parent. ; If the parent is different then "lastParent" current item is ; at the end of the its submenu. n := TV_GetNext(c, "FULL") if (n) { p := TV_GetParent(n) if ( p != lastParent){ t := lastParent lastParent := p } else continue ; It is the last child Loop { ; rise "E" (end of menu) event event_type := "E" event_param := t GoSub %label% t := TV_GetParent(t) if (t = rootsParent) { ; rise "-" (end of walk) event event_type := "-" event_param := t GoSub %label% return } if (p = t) break } } else Loop { ;this is the end of the complite menu, so close all open submenus, if any if (lastParent = root) { event_type := "-" event_param := root GoSub %label% return } event_type := "E" event_param := lastParent GoSub %label% lastParent := TV_GetParent(lastParent) } } } ;---------------------------------------------------------------------------------------------- ; Function: Move ; Moves tree view item up or down ; ; Parameters: ; item - Handle of the item to move ; direction - "u" or "d" (Up & Down) ; ; Returns: ; Handle of the item ; ; Remarks: ; Item to be moved is copied to the new place then source item is deleted. This ; creates new handle for the moved item. New handle will be returned by the function. ; TVX_Move(item, direction){ local newc, newp, t, p, n, c p := TV_GetPrev(item) n := TV_GetNext(item) if (TVX_HasRoot) { if TV_GetNext()=item return if (direction="u") { if (p = 0 && TV_GetParent(item)=TV_GetNext()) ;don't let item go above root { TV_Modify(item) TVX_sel:=item return } } } ; Do so by coping an item bellow calculated item and deleting the old one. ; Return handle of new item ; newc - calculated child after which "item" should be created. ; newp - ... and its parent ; if moving down if (direction = "d") { ; handle end of submenu if !n { newc := TV_GetParent(item) ; check the end of the entire list if (TVX_HasRoot && newc = TVX_root) return ; if TVX_CollapseOnMove ; TV_Modify(newc, "-Expand") newp := TV_GetParent(newc) } ; somewhere in the middle else { ; if submenu, go into it t := TV_Get(n, "E") if (t = n) { newp := n newc := "First" } ; not a submenu else { newc := n newp := TV_GetParent(n) } } } ; if moving up if (direction = "u") { ;going up - handle start of the submenu if !p { t := TV_GetParent(item) ; if TVX_CollapseOnMove ; TV_Modify(t, "-Expand") newc := TV_GetPrev(t) ; handle start of the menu again if !newc { newp := TV_GetParent(t) newc := "First" } else newp := TV_GetParent(newc) } ; somewhere in the middle else { ; if submenu is expanded, go into it t := TV_Get(p, "E") if (t = p) { newc := TV_GetChild(p) Loop { c := TV_GetNext(newc) if c = 0 break newc := c } ; newc := "First" newp := t } else { t := TV_GetPrev(p) ;check the top of the list if !t { newc := "First" newp := TV_GetParent(p) } else { newc := t newp := TV_GetParent(newc) } } } } newc := TVX_CopyItem(newc, newp, item) TV_Delete(item) return newc } ;--------------------------------------------------------------------------------------------- ; TVX_Walk event handler wrapped in the function ; ; Function that copies menu item to the destination item. ; Handle of destination item is specified in the global variable TVX_copyDest. ; TVX_CopyProc(iType, item) { local c, txt static lastParent TV_GetText(txt, item) if iType in + { lastParent := TVX_copyDest TV_Modify(TVX_copyDest, "Icon" . %TVX_iconData%%item%, txt) if TVX_userData { %TVX_userData%%TVX_copyDest% := %TVX_userData%%item% %TVX_userData%%item% := "" } if TVX_userDat2 { %TVX_userDat2%%TVX_copyDest% := %TVX_userDat2%%item% %TVX_userDat2%%item% := "" } if TVX_userDat3 { %TVX_userDat3%%TVX_copyDest% := %TVX_userDat3%%item% %TVX_userDat3%%item% := "" } if TVX_userDat4 { %TVX_userDat4%%TVX_copyDest% := %TVX_userDat4%%item% %TVX_userDat4%%item% := "" } if TVX_iconData { %TVX_iconData%%TVX_copyDest% := %TVX_iconData%%item% %TVX_iconData%%item% := "" } } if iType in I,M { c := TV_Add(txt, lastParent, "Icon" . %TVX_iconData%%item%) if iType = M lastParent := c if TVX_userData { %TVX_userData%%c% := %TVX_userData%%item% %TVX_userData%%item% := "" } if TVX_userDat2 { %TVX_userDat2%%c% := %TVX_userDat2%%item% %TVX_userDat2%%item% := "" } if TVX_userDat3 { %TVX_userDat3%%c% := %TVX_userDat3%%item% %TVX_userDat3%%item% := "" } if TVX_userDat4 { %TVX_userDat4%%c% := %TVX_userDat4%%item% %TVX_userDat4%%item% := "" } if TVX_iconData { %TVX_iconData%%c% := %TVX_iconData%%item% %TVX_iconData%%item% := "" } } if iType = E lastParent := TV_GetParent(lastParent) } ;---------------------------------------------- _TVX_CopyProc: TVX_CopyProc(TVX_itemType, TVX_param) return ;----------------------------------------------------------------------------------------------- ; Create new item after the child "destc" with parent "destp" and copy the "source" item into it ; TVX_CopyItem(destc, destp, source){ global ;create the holder and call the copy function TVX_copyDest := TV_Add("", destp , destc) TVX_Walk(source, "_TVX_CopyProc", TVX_itemType, TVX_param) return TVX_copyDest } ;---------------------------------------------------------------------------------------------- ; Used to control moving ; TVX_OnItemSelect(pItemId){ global if (TVX_bSelfSelect) { TVX_bSelfSelect := false return true } TVX_prevSel := TVX_sel TVX_sel := pItemId if GetKeyState("Shift") && (TVX_lastKey=38 || TVX_lastKey=40) if (pItemId != TVX_root) { TVX_sel := TVX_Move( TVX_prevSel, TVX_lastKey=40 ? "d" : "u") TVX_prevSel := pItemId TVX_bSelfSelect := true TV_Modify(TVX_sel, "Select") ; TV_Modify(TVX_sel, "Select Bold") return true } return false } ;---------------------------------------------------------------------------------------------- TVX_OnKeyPress(pKey){ Global TVX_lastKey := pKey if (TVX_bSelfPress) { TVX_bSelfPress := false return true } ;delete if pKey = 46 return TVX_Delete(GetKeyState("Shift", "P")) ;insert if pKey = 45 return TVX_Insert(GetKeyState("Shift", "P")) return false } TVX_Delete(IsSubmenu=0) { ; use GetSelection instead Editor_sel since if key is pressed and hold ; TVX_OnSelect handler may not be called before delete to set the TVX_sel Local sel := TV_GetSelection() ; don't delete root if it has root if (TVX_HasRoot && sel = TVX_root) return false ; it's submenu, delete only if IsSubmenu is true if TV_GetChild(sel) if !IsSubmenu return false TV_Delete(sel) return true } TVX_Insert(IsSubmenu=0, AtBottom=0) { Local tp, tt TVX_sel := TV_GetSelection() if (TVX_sel = TVX_root) { if AtBottom tp := TV_Add(lang_NewItem, TVX_root, "Bold") else tp := TV_Add(lang_NewItem, TVX_root, "Bold First") } else ; not root { tp := TV_GetParent(TVX_sel) if TV_Get(TVX_sel, "E") ; if select an expanded item, add into it tp := TV_Add(lang_NewItem, TVX_sel, "Bold First") else ; else add next to it tp := TV_Add(lang_NewItem, tp, "Bold " . TVX_sel) } ; clear data %TVX_userData%%tp% = %TVX_userDat2%%tp% = %TVX_userDat3%%tp% = %TVX_userDat4%%tp% = %TVX_iconData%%tp% = if IsSubmenu { tt := TV_Add(lang_NewItem, tp, "Bold First ") %TVX_userData%%tt% = %TVX_userDat2%%tt% = %TVX_userDat3%%tt% = %TVX_userDat4%%tt% = %TVX_iconData%%tt% = TV_Modify(tp,"Expand", lang_NewMenu) } TV_Modify(tp, "Select") return true } ;---------------------------------------------------------------------------------------------- ; g soubroutine for Tree View ; TVX_OnEvent: if (A_GuiEvent="S") if TVX_OnItemSelect(A_EventInfo) return if (A_GuiEvent="K") if TVX_OnKeyPress(A_EventInfo) return ;if not the Xtended property send event to the caller gosub %TVX_sub% return ;==============================================================================; ;============================= ShellContextMenu ===============================; ;==============================================================================; ShellContextMenu(sPath) { CoInitialize() If sPath Is Not Integer DllCall("shell32\SHParseDisplayName", "Uint", Unicode4Ansi(wPath,sPath), "Uint", 0, "UintP", pidl, "Uint", 0, "Uint", 0) Else DllCall("shell32\SHGetFolderLocation", "Uint", 0, "int", sPath, "Uint", 0, "Uint", 0, "UintP", pidl) DllCall("shell32\SHBindToParent", "Uint", pidl, "Uint", GUID4String(IID_IShellFolder,"{000214E6-0000-0000-C000-000000000046}"), "UintP", psf, "UintP", pidlChild) DllCall(NumGet(NumGet(1*psf)+40), "Uint", psf, "Uint", 0, "Uint", 1, "UintP", pidlChild, "Uint", GUID4String(IID_IContextMenu,"{000214E4-0000-0000-C000-000000000046}"), "Uint", 0, "UintP", pcm) Release(psf) CoTaskMemFree(pidl) hMenu := DllCall("CreatePopupMenu") DllCall(NumGet(NumGet(1*pcm)+12), "Uint", pcm, "Uint", hMenu, "Uint", 0, "Uint", 3, "Uint", 0x7FFF, "Uint", 0) ; QueryContextMenu DetectHiddenWindows, On Process, Exist WinGet, hAHK, ID, ahk_pid %ErrorLevel% WinActivate, ahk_id %hAHK% Global SCM_pcm2 := QueryInterface(pcm,IID_IContextMenu2:="{000214F4-0000-0000-C000-000000000046}") Global SCM_pcm3 := QueryInterface(pcm,IID_IContextMenu3:="{BCFCE0A0-EC17-11D0-8D10-00A0C90F2719}") Global SCM_WPOld:= DllCall("SetWindowLong", "Uint", hAHK, "int",-4, "int",RegisterCallback("WindowProc")) DllCall("GetCursorPos", "int64P", pt) DllCall("InsertMenu", "Uint", hMenu, "Uint", 0, "Uint", 0x0400|0x800, "Uint", 2, "Uint", 0) DllCall("InsertMenu", "Uint", hMenu, "Uint", 0, "Uint", 0x0400|0x002, "Uint", 1, "Uint", &sPath) idn := DllCall("TrackPopupMenu", "Uint", hMenu, "Uint", 0x0100, "int", pt << 32 >> 32, "int", pt >> 32, "Uint", 0, "Uint", hAHK, "Uint", 0) NumPut(VarSetCapacity(ici,64,0),ici), NumPut(0x4000|0x20000000,ici,4), NumPut(1,NumPut(hAHK,ici,8),12), NumPut(idn-3,NumPut(idn-3,ici,12),24), NumPut(pt,ici,56,"int64") DllCall(NumGet(NumGet(1*pcm)+16), "Uint", pcm, "Uint", &ici) ; InvokeCommand ; VarSetCapacity(sName,259), DllCall(NumGet(NumGet(1*pcm)+20), "Uint", pcm, "Uint", idn-3, "Uint", 1, "Uint", 0, "str", sName, "Uint", 260) ; GetCommandString DllCall("GlobalFree", "Uint", DllCall("SetWindowLong", "Uint", hAHK, "int", -4, "int", SCM_WPOld)) DllCall("DestroyMenu", "Uint", hMenu) Release(SCM_pcm3) Release(SCM_pcm2) Release(pcm) CoUninitialize() SCM_pcm2:=SCM_pcm3:=SCM_WPOld:=0 } WindowProc(hWnd, nMsg, wParam, lParam) { Critical Global SCM_pcm2, SCM_pcm3, SCM_WPOld If SCM_pcm3 { If !DllCall(NumGet(NumGet(1*SCM_pcm3)+28), "Uint", SCM_pcm3, "Uint", nMsg, "Uint", wParam, "Uint", lParam, "UintP", lResult) Return lResult } Else If SCM_pcm2 { If !DllCall(NumGet(NumGet(1*SCM_pcm2)+24), "Uint", SCM_pcm2, "Uint", nMsg, "Uint", wParam, "Uint", lParam) Return 0 } Return DllCall("user32.dll\CallWindowProcA", "Uint", SCM_WPOld, "Uint", hWnd, "Uint", nMsg, "Uint", wParam, "Uint", lParam) } VTable(ppv, idx) { Return NumGet(NumGet(1*ppv)+4*idx) } QueryInterface(ppv, ByRef IID) { If StrLen(IID)=38 GUID4String(IID,IID) DllCall(NumGet(NumGet(1*ppv)), "Uint", ppv, "str", IID, "UintP", ppv) Return ppv } AddRef(ppv) { Return DllCall(NumGet(NumGet(1*ppv)+4), "Uint", ppv) } Release(ppv) { Return DllCall(NumGet(NumGet(1*ppv)+8), "Uint", ppv) } QueryService(ppv, ByRef SID, ByRef IID) { If StrLen(SID)=38 GUID4String(SID,SID) If StrLen(IID)=38 GUID4String(IID,IID) GUID4String(IID_IServiceProvider,"{6D5140C1-7436-11CE-8034-00AA006009FA}") DllCall(NumGet(NumGet(1*ppv)+4*0), "Uint", ppv, "str", IID_IServiceProvider, "UintP", psp) DllCall(NumGet(NumGet(1*psp)+4*3), "Uint", psp, "str", SID, "str", IID, "UintP", ppv) DllCall(NumGet(NumGet(1*psp)+4*2), "Uint", psp) Return ppv } FindConnectionPoint(pdp, DIID) { DllCall(NumGet(NumGet(1*pdp)+ 0), "Uint", pdp, "Uint", GUID4String(IID_IConnectionPointContainer,"{B196B284-BAB4-101A-B69C-00AA00341D07}"), "UintP", pcc) DllCall(NumGet(NumGet(1*pcc)+16), "Uint", pcc, "Uint", GUID4String(DIID,DIID), "UintP", pcp) DllCall(NumGet(NumGet(1*pcc)+ 8), "Uint", pcc) Return pcp } GetConnectionInterface(pcp) { VarSetCapacity(DIID, 16, 0) DllCall(NumGet(NumGet(1*pcp)+12), "Uint", pcp, "str", DIID) Return String4GUID(&DIID) } Advise(pcp, psink) { DllCall(NumGet(NumGet(1*pcp)+20), "Uint", pcp, "Uint", psink, "UintP", nCookie) Return nCookie } Unadvise(pcp, nCookie) { Return DllCall(NumGet(NumGet(1*pcp)+24), "Uint", pcp, "Uint", nCookie) } /* Enumerate(penum, ByRef Result) { VarSetCapacity(varResult,16,0) If (0 = hResult:=DllCall(NumGet(NumGet(1*penum)+12), "Uint", penum, "Uint", 1, "Uint", &varResult, "UintP", 0)) Result:=(vt:=NumGet(varResult,0,"Ushort"))=8||vt<0x1000&&DllCall("oleaut32\VariantChangeTypeEx","Uint",&varResult,"Uint",&varResult,"Uint",LCID,"Ushort",1,"Ushort",8)=0 ? Ansi4Unicode(bstr:=NumGet(varResult,8)) . SubStr(SysFreeString(bstr),1,0) : NumGet(varResult,8) Return hResult } */ Invoke(pdisp, sName, arg1="vT_NoNe",arg2="vT_NoNe",arg3="vT_NoNe",arg4="vT_NoNe",arg5="vT_NoNe",arg6="vT_NoNe",arg7="vT_NoNe",arg8="vT_NoNe",arg9="vT_NoNe") { nParams:=0 Loop, 9 If (arg%A_Index% == "vT_NoNe") Break Else ++nParams VarSetCapacity(DispParams,16,0), VarSetCapacity(varResult,16,0), VarSetCapacity(IID_NULL,16,0), VarSetCapacity(varg,nParams*16,0) NumPut(&varg,DispParams,0), NumPut(nParams,DispParams,8) If (nFlags := SubStr(sName,0) <> "=" ? 3 : 12) = 12 NumPut(&varResult,DispParams,4), NumPut(1,DispParams,12), NumPut(-3,varResult), sName:=SubStr(sName,1,-1) Loop, % nParams If arg%A_Index% Is Not Integer NumPut(8,varg,(nParams-A_Index)*16,"Ushort"), NumPut(SysAllocString(arg%A_Index%),varg,(nParams-A_Index)*16+8) Else NumPut(SubStr(arg%A_Index%,1,1)="+" ? 9 : 3,varg,(nParams-A_Index)*16,"Ushort"), NumPut(arg%A_Index%,varg,(nParams-A_Index)*16+8) If DllCall(NumGet(NumGet(1*pdisp)+20), "Uint", pdisp, "Uint", &IID_NULL, "UintP", Unicode4Ansi(wName, sName), "Uint", 1, "Uint", LCID, "intP", dispID)=0 && DllCall(NumGet(NumGet(1*pdisp)+24), "Uint", pdisp, "int", dispID, "Uint", &IID_NULL, "Uint", LCID, "Ushort", nFlags, "Uint", &dispParams, "Uint", &varResult, "Uint", 0, "Uint", 0)=0 && nFlags = 3 Result:=(vt:=NumGet(varResult,0,"Ushort"))=8||vt<0x1000&&DllCall("oleaut32\VariantChangeTypeEx","Uint",&varResult,"Uint",&varResult,"Uint",LCID,"Ushort",1,"Ushort",8)=0 ? Ansi4Unicode(bstr:=NumGet(varResult,8)) . SubStr(SysFreeString(bstr),1,0) : NumGet(varResult,8) Loop, % nParams NumGet(varg,(A_Index-1)*16,"Ushort")=8 ? SysFreeString(NumGet(varg,(A_Index-1)*16+8)) : "" Return Result } Invoke_(pdisp, sName, type1="",arg1="",type2="",arg2="",type3="",arg3="",type4="",arg4="",type5="",arg5="",type6="",arg6="",type7="",arg7="",type8="",arg8="",type9="",arg9="") { nParams:=0 Loop, 9 If (type%A_Index% = "") Break Else ++nParams VarSetCapacity(dispParams,16,0), VarSetCapacity(varResult,16,0), VarSetCapacity(IID_NULL,16,0), VarSetCapacity(varg,nParams*16,0) NumPut(&varg,dispParams,0), NumPut(nParams,dispParams,8) If (nFlags := SubStr(sName,0) <> "=" ? 1|2 : 4|8) & 12 NumPut(&varResult,dispParams,4), NumPut(1,dispParams,12), NumPut(-3,varResult), sName:=SubStr(sName,1,-1) Loop, % nParams NumPut(type%A_Index%,varg,(nParams-A_Index)*16,"Ushort"), type%A_Index%&0x4000=0 ? NumPut(type%A_Index%=8 ? SysAllocString(arg%A_Index%) : arg%A_Index%,varg,(nParams-A_Index)*16+8,type%A_Index%=5||type%A_Index%=7 ? "double" : type%A_Index%=4 ? "float" : "int64") : type%A_Index%=0x400C||type%A_Index%=0x400E ? NumPut(arg%A_Index%,varg,(nParams-A_Index)*16+8) : VarSetCapacity(ref%A_Index%,8,0) . NumPut(&ref%A_Index%,varg,(nParams-A_Index)*16+8) . NumPut(type%A_Index%=0x4008 ? SysAllocString(arg%A_Index%) : arg%A_Index%,ref%A_Index%,0,type%A_Index%=0x4005||type%A_Index%=0x4007 ? "double" : type%A_Index%=0x4004 ? "float" : "int64") If DllCall(NumGet(NumGet(1*pdisp)+20), "Uint", pdisp, "Uint", &IID_NULL, "UintP", Unicode4Ansi(wName, sName), "Uint", 1, "Uint", LCID, "intP", dispID)=0 && DllCall(NumGet(NumGet(1*pdisp)+24), "Uint", pdisp, "int", dispID, "Uint", &IID_NULL, "Uint", LCID, "Ushort", nFlags, "Uint", &dispParams, "Uint", &varResult, "Uint", 0, "Uint", 0)=0 && nFlags = 3 Result:=(vt:=NumGet(varResult,0,"Ushort"))=8||vt<0x1000&&DllCall("oleaut32\VariantChangeTypeEx","Uint",&varResult,"Uint",&varResult,"Uint",LCID,"Ushort",1,"Ushort",8)=0 ? Ansi4Unicode(bstr:=NumGet(varResult,8)) . SubStr(SysFreeString(bstr),1,0) : NumGet(varResult,8) Loop, % nParams type%A_Index%&0x4000=0 ? (type%A_Index%=8 ? SysFreeString(NumGet(varg,(nParams-A_Index)*16+8)) : "") : type%A_Index%=0x400C||type%A_Index%=0x400E ? "" : type%A_Index%=0x4008 ? (_TEMP_VT_BYREF_%A_Index%:=Ansi4Unicode(NumGet(ref%A_Index%))) . SysFreeString(NumGet(ref%A_Index%)) : (_TEMP_VT_BYREF_%A_Index%:=NumGet(ref%A_Index%,0,type%A_Index%=0x4005||type%A_Index%=0x4007 ? "double" : type%A_Index%=0x4004 ? "float" : "int64")) Return Result } DispInterface(this, prm1="", prm2="", prm3="", prm4="", prm5="", prm6="", prm7="", prm8="") { Critical If A_EventInfo = 6 DllCall(NumGet(NumGet(NumGet(this+8))+28),"Uint",NumGet(this+8),"Uint",prm1,"UintP",pname,"Uint",1,"UintP",0), VarSetCapacity(sfn,63), DllCall("user32\wsprintfA","str",sfn,"str","%s%S","Uint",this+40,"Uint",pname,"Cdecl"), SysFreeString(pname), (pfn:=RegisterCallback(sfn,"C F")) ? (hResult:=DllCall(pfn, "Uint", prm5, "Uint", this, "Cdecl")) . DllCall("kernel32\GlobalFree", "Uint", pfn) : (hResult:=0x80020003) Else If A_EventInfo = 5 hResult:=DllCall(NumGet(NumGet(NumGet(this+8))+40),"Uint",NumGet(this+8),"Uint",prm2,"Uint",prm3,"Uint",prm5) Else If A_EventInfo = 4 NumPut(0,prm3+0), hResult:=0x80004001 Else If A_EventInfo = 3 NumPut(0,prm1+0), hResult:=0 Else If A_EventInfo = 2 NumPut(hResult:=NumGet(this+4)-1,this+4), hResult ? "" : Unadvise(NumGet(this+16),NumGet(this+20)) . Release(NumGet(this+16)) . Release(NumGet(this+8)) . CoTaskMemFree(this) Else If A_EventInfo = 1 NumPut(hResult:=NumGet(this+4)+1,this+4) Else If A_EventInfo = 0 IsEqualGUID(this+24,prm1)||InStr("{00020400-0000-0000-C000-000000000046}{00000000-0000-0000-C000-000000000046}",String4GUID(prm1)) ? NumPut(this,prm2+0) . NumPut(NumGet(this+4)+1,this+4) . (hResult:=0) : NumPut(0,prm2+0) . (hResult:=0x80004002) Return hResult } DispGetParam(pDispParams, Position = 0, vtType = 8) { VarSetCapacity(varResult,16,0) DllCall("oleaut32\DispGetParam", "Uint", pDispParams, "Uint", Position, "Ushort", vtType, "Uint", &varResult, "UintP", nArgErr) Return NumGet(varResult,0,"Ushort")=8 ? Ansi4Unicode(NumGet(varResult,8)) . SubStr(SysFreeString(NumGet(varResult,8)),1,0) : NumGet(varResult,8) } CreateIDispatch() { Static IDispatch If Not VarSetCapacity(IDispatch) { VarSetCapacity(IDispatch,28,0), nParams=3112469 Loop, Parse, nParams NumPut(RegisterCallback("DispInterface","",A_LoopField,A_Index-1),IDispatch,4*(A_Index-1)) } Return &IDispatch } GetDefaultInterface(pdisp, LCID = 0) { DllCall(NumGet(NumGet(1*pdisp) +12), "Uint", pdisp , "UintP", ctinf) If ctinf { DllCall(NumGet(NumGet(1*pdisp)+16), "Uint", pdisp, "Uint" , 0, "Uint", LCID, "UintP", ptinf) DllCall(NumGet(NumGet(1*ptinf)+12), "Uint", ptinf, "UintP", pattr) DllCall(NumGet(NumGet(1*pdisp)+ 0), "Uint", pdisp, "Uint" , pattr, "UintP", ppv) DllCall(NumGet(NumGet(1*ptinf)+76), "Uint", ptinf, "Uint" , pattr) DllCall(NumGet(NumGet(1*ptinf)+ 8), "Uint", ptinf) If ppv DllCall(NumGet(NumGet(1*pdisp)+ 8), "Uint", pdisp), pdisp := ppv } Return pdisp } GetDefaultEvents(pdisp, LCID = 0) { DllCall(NumGet(NumGet(1*pdisp)+16), "Uint", pdisp, "Uint" , 0, "Uint", LCID, "UintP", ptinf) DllCall(NumGet(NumGet(1*ptinf)+12), "Uint", ptinf, "UintP", pattr) VarSetCapacity(IID,16), DllCall("RtlMoveMemory", "Uint", &IID, "Uint", pattr, "Uint", 16) DllCall(NumGet(NumGet(1*ptinf)+76), "Uint", ptinf, "Uint" , pattr) DllCall(NumGet(NumGet(1*ptinf)+72), "Uint", ptinf, "UintP", ptlib, "UintP", idx) DllCall(NumGet(NumGet(1*ptinf)+ 8), "Uint", ptinf) Loop, % DllCall(NumGet(NumGet(1*ptlib)+12), "Uint", ptlib) { DllCall(NumGet(NumGet(1*ptlib)+20), "Uint", ptlib, "Uint", A_Index-1, "UintP", TKind) If TKind <> 5 Continue DllCall(NumGet(NumGet(1*ptlib)+16), "Uint", ptlib, "Uint", A_Index-1, "UintP", ptinf) DllCall(NumGet(NumGet(1*ptinf)+12), "Uint", ptinf, "UintP", pattr) nCount:=NumGet(pattr+48,0,"Ushort") DllCall(NumGet(NumGet(1*ptinf)+76), "Uint", ptinf, "Uint" , pattr) Loop, % nCount { DllCall(NumGet(NumGet(1*ptinf)+36), "Uint", ptinf, "Uint", A_Index-1, "UintP", nFlags) If !(nFlags & 1) Continue DllCall(NumGet(NumGet(1*ptinf)+32), "Uint", ptinf, "Uint", A_Index-1, "UintP", hRefType) DllCall(NumGet(NumGet(1*ptinf)+56), "Uint", ptinf, "Uint", hRefType , "UintP", prinf) DllCall(NumGet(NumGet(1*prinf)+12), "Uint", prinf, "UintP", pattr) nFlags & 2 ? DIID:=String4GUID(pattr) : bFind:=IsEqualGUID(pattr,&IID) DllCall(NumGet(NumGet(1*prinf)+76), "Uint", prinf, "Uint" , pattr) DllCall(NumGet(NumGet(1*prinf)+ 8), "Uint", prinf) } DllCall(NumGet(NumGet(1*ptinf)+ 8), "Uint", ptinf) If bFind Break } DllCall(NumGet(NumGet(1*ptlib)+ 8), "Uint", ptlib) Return bFind ? DIID : "{00000000-0000-0000-0000-000000000000}" } GetGuidOfName(pdisp, Name, LCID = 0) { DllCall(NumGet(NumGet(1*pdisp)+16), "Uint", pdisp, "Uint", 0, "Uint", LCID, "UintP", ptinf) DllCall(NumGet(NumGet(1*ptinf)+72), "Uint", ptinf, "UintP", ptlib, "UintP", idx) DllCall(NumGet(NumGet(1*ptinf)+ 8), "Uint", ptinf), ptinf:=0 DllCall(NumGet(NumGet(1*ptlib)+44), "Uint", ptlib, "Uint", Unicode4Ansi(Name,Name), "Uint", 0, "UintP", ptinf, "UintP", memID, "UshortP", 1) DllCall(NumGet(NumGet(1*ptlib)+ 8), "Uint", ptlib) DllCall(NumGet(NumGet(1*ptinf)+12), "Uint", ptinf, "UintP", pattr) GUID := String4GUID(pattr) DllCall(NumGet(NumGet(1*ptinf)+76), "Uint", ptinf, "Uint" , pattr) DllCall(NumGet(NumGet(1*ptinf)+ 8), "Uint", ptinf) Return GUID } GetTypeInfoOfGuid(pdisp, GUID, LCID = 0) { DllCall(NumGet(NumGet(1*pdisp)+16), "Uint", pdisp, "Uint", 0, "Uint", LCID, "UintP", ptinf) DllCall(NumGet(NumGet(1*ptinf)+72), "Uint", ptinf, "UintP", ptlib, "UintP", idx) DllCall(NumGet(NumGet(1*ptinf)+ 8), "Uint", ptinf), ptinf := 0 DllCall(NumGet(NumGet(1*ptlib)+24), "Uint", ptlib, "Uint", GUID4String(GUID,GUID), "UintP", ptinf) DllCall(NumGet(NumGet(1*ptlib)+ 8), "Uint", ptlib) Return ptinf } ; A Function Name including Prefix is limited to 63 bytes! ConnectObject(psource, prefix = "", DIID = "{00020400-0000-0000-C000-000000000046}") { If (DIID = "{00020400-0000-0000-C000-000000000046}") 0+(pconn:=FindConnectionPoint(psource,DIID)) ? (DIID:=GetConnectionInterface(pconn))="{00020400-0000-0000-C000-000000000046}" ? DIID:=GetDefaultEvents(psource) : "" : pconn:=FindConnectionPoint(psource,DIID:=GetDefaultEvents(psource)) Else pconn:=FindConnectionPoint(psource,SubStr(DIID,1,1)="{" ? DIID : DIID:=GetGuidOfName(psource,DIID)) If !pconn || !(ptinf:=GetTypeInfoOfGuid(psource,DIID)) { MsgBox, No Event Interface Exists! Now exit the application. ExitApp } psink:=CoTaskMemAlloc(40+StrLen(prefix)+1), NumPut(1,NumPut(CreateIDispatch(),psink+0)), NumPut(psource,NumPut(ptinf,psink+8)) DllCall("RtlMoveMemory", "Uint", psink+24, "Uint", GUID4String(DIID,DIID), "Uint", 16) DllCall("RtlMoveMemory", "Uint", psink+40, "Uint", &prefix, "Uint", StrLen(prefix)+1) NumPut(Advise(pconn,psink),NumPut(pconn,psink+16)) Return psink } CreateObject(ByRef CLSID, ByRef IID, CLSCTX = 5) { If StrLen(CLSID)=38 GUID4String(CLSID,CLSID) If StrLen(IID)=38 GUID4String(IID,IID) DllCall("ole32\CoCreateInstance", "str", CLSID, "Uint", 0, "Uint", CLSCTX, "str", IID, "UintP", ppv) Return ppv } ActiveXObject(ProgID) { DllCall("ole32\CoCreateInstance", "Uint", SubStr(ProgID,1,1)="{" ? GUID4String(ProgID,ProgID) : CLSID4ProgID(ProgID,ProgID), "Uint", 0, "Uint", 5, "Uint", GUID4String(IID_IDispatch,"{00020400-0000-0000-C000-000000000046}"), "UintP", pdisp) Return GetDefaultInterface(pdisp) } GetObject(Moniker) { DllCall("ole32\CoGetObject", "Uint", Unicode4Ansi(Moniker,Moniker), "Uint", 0, "Uint", GUID4String(IID_IDispatch,"{00020400-0000-0000-C000-000000000046}"), "UintP", pdisp) Return GetDefaultInterface(pdisp) } GetActiveObject(ProgID) { DllCall("oleaut32\GetActiveObject", "Uint", SubStr(ProgID,1,1)="{" ? GUID4String(ProgID,ProgID) : CLSID4ProgID(ProgID,ProgID), "Uint", 0, "UintP", punk) DllCall(NumGet(NumGet(1*punk)+0), "Uint", punk, "Uint", GUID4String(IID_IDispatch,"{00020400-0000-0000-C000-000000000046}"), "UintP", pdisp) DllCall(NumGet(NumGet(1*punk)+8), "Uint", punk) Return GetDefaultInterface(pdisp) } CLSID4ProgID(ByRef CLSID, ProgID) { VarSetCapacity(CLSID, 16) DllCall("ole32\CLSIDFromProgID", "Uint", Unicode4Ansi(ProgID,ProgID), "Uint", &CLSID) Return &CLSID } GUID4String(ByRef CLSID, String) { VarSetCapacity(CLSID, 16) DllCall("ole32\CLSIDFromString", "Uint", Unicode4Ansi(String,String,38), "Uint", &CLSID) Return &CLSID } ProgID4CLSID(pCLSID) { DllCall("ole32\ProgIDFromCLSID", "Uint", pCLSID, "UintP", pProgID) Return Ansi4Unicode(pProgID) . SubStr(CoTaskMemFree(pProgID),1,0) } String4GUID(pGUID) { VarSetCapacity(String, 38 * 2 + 1) DllCall("ole32\StringFromGUID2", "Uint", pGUID, "Uint", &String, "int", 39) Return Ansi4Unicode(&String, 38) } IsEqualGUID(pGUID1, pGUID2) { Return DllCall("ole32\IsEqualGUID", "Uint", pGUID1, "Uint", pGUID2) } CoCreateGuid() { VarSetCapacity(GUID, 16, 0) DllCall("ole32\CoCreateGuid", "Uint", &GUID) Return String4GUID(&GUID) } CoTaskMemAlloc(cb) { Return DllCall("ole32\CoTaskMemAlloc", "Uint", cb) } CoTaskMemFree(pv) { Return DllCall("ole32\CoTaskMemFree", "Uint", pv) } CoInitialize() { Return DllCall("ole32\CoInitialize", "Uint", 0) } CoUninitialize() { Return DllCall("ole32\CoUninitialize") } OleInitialize() { Return DllCall("ole32\OleInitialize", "Uint", 0) } OleUninitialize() { Return DllCall("ole32\OleUninitialize") } SysAllocString(sString) { Return DllCall("oleaut32\SysAllocString", "Uint", Ansi2Unicode(sString,wString)) } SysFreeString(bstr) { Return DllCall("oleaut32\SysFreeString", "Uint", bstr) } SysStringLen(bstr) { Return DllCall("oleaut32\SysStringLen", "Uint", bstr) } SafeArrayDestroy(psa) { Return DllCall("oleaut32\SafeArrayDestroy", "Uint", psa) } VariantClear(pvarg) { Return DllCall("oleaut32\VariantClear", "Uint", pvarg) } AtlAxWinInit(Version = "") { CoInitialize() If !DllCall("GetModuleHandle", "str", "atl" . Version) DllCall("LoadLibrary" , "str", "atl" . Version) Return DllCall("atl" . Version . "\AtlAxWinInit") } AtlAxWinTerm(Version = "") { CoUninitialize() If hModule:=DllCall("GetModuleHandle", "str", "atl" . Version) Return DllCall("FreeLibrary" , "Uint", hModule) } AtlAxGetControl(hWnd, Version = "") { DllCall("atl" . Version . "\AtlAxGetControl", "Uint", hWnd, "UintP", punk) pdsp:=QueryInterface(punk,IID_IDispatch:="{00020400-0000-0000-C000-000000000046}") Release(punk) Return pdsp } AtlAxAttachControl(pdsp, hWnd, Version = "") { punk:=QueryInterface(pdsp,IID_IUnknown:="{00000000-0000-0000-C000-000000000046}") DllCall("atl" . Version . "\AtlAxAttachControl", "Uint", punk, "Uint", hWnd, "Uint", 0) Release(punk) } AtlAxCreateControl(hWnd, Name, Version = "") { VarSetCapacity(IID_NULL, 16, 0) DllCall("atl" . Version . "\AtlAxCreateControlEx", "Uint", Unicode4Ansi(Name,Name), "Uint", hWnd, "Uint", 0, "Uint", 0, "UintP", punk, "Uint", &IID_NULL, "Uint", 0) pdsp:=QueryInterface(punk,IID_IDispatch:="{00020400-0000-0000-C000-000000000046}") Release(punk) Return pdsp } AtlAxCreateContainer(hWnd, l, t, w, h, Name = "", Version = "") { Return DllCall("CreateWindowEx", "Uint",0x200, "str", "AtlAxWin" . Version, "Uint", Name ? &Name : 0, "Uint", 0x54000000, "int", l, "int", t, "int", w, "int", h, "Uint", hWnd, "Uint", 0, "Uint", 0, "Uint", 0) } AtlAxGetContainer(pdsp) { DllCall(NumGet(NumGet(1*pdsp)+ 0), "Uint", pdsp, "Uint", GUID4String(IID_IOleWindow,"{00000114-0000-0000-C000-000000000046}"), "UintP", pwin) DllCall(NumGet(NumGet(1*pwin)+12), "Uint", pwin, "UintP", hCtrl) DllCall(NumGet(NumGet(1*pwin)+ 8), "Uint", pwin) Return DllCall("GetParent", "Uint", hCtrl) } Ansi4Unicode(pString, nSize = "") { If (nSize = "") nSize:=DllCall("kernel32\WideCharToMultiByte", "Uint", 0, "Uint", 0, "Uint", pString, "int", -1, "Uint", 0, "int", 0, "Uint", 0, "Uint", 0) VarSetCapacity(sString, nSize) DllCall("kernel32\WideCharToMultiByte", "Uint", 0, "Uint", 0, "Uint", pString, "int", -1, "str", sString, "int", nSize + 1, "Uint", 0, "Uint", 0) Return sString } Unicode4Ansi(ByRef wString, sString, nSize = "") { If (nSize = "") nSize:=DllCall("kernel32\MultiByteToWideChar", "Uint", 0, "Uint", 0, "Uint", &sString, "int", -1, "Uint", 0, "int", 0) VarSetCapacity(wString, nSize * 2 + 1) DllCall("kernel32\MultiByteToWideChar", "Uint", 0, "Uint", 0, "Uint", &sString, "int", -1, "Uint", &wString, "int", nSize + 1) Return &wString } Ansi2Unicode(ByRef sString, ByRef wString, nSize = "") { If (nSize = "") nSize:=DllCall("kernel32\MultiByteToWideChar", "Uint", 0, "Uint", 0, "Uint", &sString, "int", -1, "Uint", 0, "int", 0) VarSetCapacity(wString, nSize * 2 + 1) DllCall("kernel32\MultiByteToWideChar", "Uint", 0, "Uint", 0, "Uint", &sString, "int", -1, "Uint", &wString, "int", nSize + 1) Return &wString } Unicode2Ansi(ByRef wString, ByRef sString, nSize = "") { pString := wString + 0 > 65535 ? wString : &wString If (nSize = "") nSize:=DllCall("kernel32\WideCharToMultiByte", "Uint", 0, "Uint", 0, "Uint", pString, "int", -1, "Uint", 0, "int", 0, "Uint", 0, "Uint", 0) VarSetCapacity(sString, nSize) DllCall("kernel32\WideCharToMultiByte", "Uint", 0, "Uint", 0, "Uint", pString, "int", -1, "str", sString, "int", nSize + 1, "Uint", 0, "Uint", 0) Return &sString } DecodeInteger(ref, nSize = 4) { DllCall("RtlMoveMemory", "int64P", val, "Uint", ref, "Uint", nSize) Return val } EncodeInteger(ref, val = 0, nSize = 4) { DllCall("RtlMoveMemory", "Uint", ref, "int64P", val, "Uint", nSize) } ScriptControl(sCode, sLang = "", bExec = False, sName = "", pdisp = 0, bGlobal = False) { CoInitialize() psc := ActiveXObject("MSScriptControl.ScriptControl") Invoke(psc, "Language=", sLang ? sLang : "VBScript") sName ? Invoke(psc, "AddObject", sName, "+" . pdisp, bGlobal) : "" ret := Invoke(psc, bExec ? "ExecuteStatement" : "Eval", sCode) Release(psc) CoUninitialize() Return ret }