假设我调用一个使用byref
修饰符的函数。在函数中,我想获取传递的变量的字符串值。
myvar := "george"
passit(myvar)
passit(byref whatvar){
msgbox % %whatvar% ;I should see a messagebox reporting the string "myvar"
}
如果我没有传递变量byref
,则获取变量的字符串值可以正常工作。
也许我用错了方法。我希望函数知道被引用的变量的字符串名称。
这种方法使用内置的ListLines-Command来访问所需的元数据。
命令ListLines打开当前脚本的主窗口并显示最后执行的脚本行。内容看起来像这样:
Script lines most recently executed (oldest first). Press [F5] to refresh. The seconds elapsed between a line and the one after it is in parentheses to the right (if not 0). The bottommost line's elapsed time is the number of seconds since it executed.
---- D:Eigene_Dateienahk scriptstest3.ahk
002: myvar := "george"
003: passit(myvar)
007: MsgBox,GetOriginalVariableNameForSingleArgumentOfCurrentCall(A_ThisFunc)
012: lines := ListLines()
Press [F5] to refresh.
可以解析该数据以提取所需的信息(传递给'passit'的信息)。这里的一个问题是,没有内置的编程方式来访问此信息。函数ListLines覆盖临时的User32。ShowWindow和User32。SetForgroundWindow返回true,因此内置命令ListLines可以在不显示其窗口的情况下使用(可能会产生多线程脚本问题)。从这个"隐藏"窗口接收并清理其文本。函数由lexkos (http://www.autohotkey.com/board/topic/20925-listvars/#entry156570 http://www.autohotkey.com/board/topic/58110-printing-listlines-into-a-file/#entry365156)编写。
GetOriginalVariableNameForSingleArgumentOfCurrentCall使用正则表达式提取变量名,该正则表达式搜索当前调用上方传递的函数的第一个调用(调用GetOriginalVariableNameForSingleArgumentOfCurrentCall)。
myvar := "george"
passit(myvar)
return
passit(whatvar){
msgbox % GetOriginalVariableNameForSingleArgumentOfCurrentCall(A_ThisFunc)
}
GetOriginalVariableNameForSingleArgumentOfCurrentCall(callerFuncName)
{
lines := ListLines()
pattern = O)%callerFuncName%((.*?)).*?%A_ThisFunc%(.*?)
RegExMatch(lines, pattern, match)
return match[1]
}
; Originally written by Lexikos / Copy of ListGlobalVars http://www.autohotkey.com/board/topic/20925-listvars/#entry156570
; with modifications from here http://www.autohotkey.com/board/topic/58110-printing-listlines-into-a-file/#entry365156
; Tested/Modified for AHK Unicode 64bit v1.1.14.03
ListLines()
{
static hwndEdit, pSFW, pSW, bkpSFW, bkpSW
ListLines Off
if !hwndEdit
{
dhw := A_DetectHiddenWindows
DetectHiddenWindows, On
Process, Exist
ControlGet, hwndEdit, Hwnd,, Edit1, ahk_class AutoHotkey ahk_pid %ErrorLevel%
DetectHiddenWindows, %dhw%
astr := A_IsUnicode ? "astr":"str"
ptr := A_PtrSize=8 ? "ptr":"uint"
hmod := DllCall("GetModuleHandle", "str", "user32.dll")
pSFW := DllCall("GetProcAddress", ptr, hmod, astr, "SetForegroundWindow")
pSW := DllCall("GetProcAddress", ptr, hmod, astr, "ShowWindow")
DllCall("VirtualProtect", ptr, pSFW, ptr, 8, "uint", 0x40, "uint*", 0)
DllCall("VirtualProtect", ptr, pSW, ptr, 8, "uint", 0x40, "uint*", 0)
bkpSFW := NumGet(pSFW+0, 0, "int64")
bkpSW := NumGet(pSW+0, 0, "int64")
}
if (A_PtrSize=8) {
NumPut(0x0000C300000001B8, pSFW+0, 0, "int64") ; return TRUE
NumPut(0x0000C300000001B8, pSW+0, 0, "int64") ; return TRUE
} else {
NumPut(0x0004C200000001B8, pSFW+0, 0, "int64") ; return TRUE
NumPut(0x0008C200000001B8, pSW+0, 0, "int64") ; return TRUE
}
ListLines
NumPut(bkpSFW, pSFW+0, 0, "int64")
NumPut(bkpSW, pSW+0, 0, "int64")
; Retrieve ListLines text and strip out some unnecessary stuff:
ControlGetText, ListLinesText,, ahk_id %hwndEdit%
RegExMatch(ListLinesText, ".*`r`n`r`nK[sS]*(?=`r`n`r`n.*$)", ListLinesText)
StringReplace, ListLinesText, ListLinesText, `r`n, `n, All
ListLines On
return ListLinesText ; This line appears in ListLines if we're called more than once.
}
最接近你想要的…?这让我想起了一个问题。
见http://ahkscript.org/boards/viewtopic.php?f=14& t = 3651
myvar:="test"
passit("myvar") ; display value, and change it
msgbox % "myvar = " myvar
passit(byref whatvar){ ; no more need for byref here...
msgbox % whatvar " = " (%whatvar%)
%whatvar%:="blah" ; edit globalvar "hack"
}