假设我调用的函数使用byref
修饰符。进入函数后,我想获取传递的变量的字符串值。
myvar := "george"
passit(myvar)
passit(byref whatvar){
msgbox % %whatvar% ;I should see a messagebox reporting the string "myvar"
}
如果我没有传递变量byref
,那么获取变量的字符串值就可以了。
也许我会以错误的方式解决这个问题。我希望函数知道被引用变量的字符串名称。
答案 0 :(得分:2)
此approch使用buildin 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_Dateien\ahk scripts\test3.ahk
002: myvar := "george"
003: passit(myvar)
007: MsgBox,GetOriginalVariableNameForSingleArgumentOfCurrentCall(A_ThisFunc)
012: lines := ListLines()
Press [F5] to refresh.
可以解析此数据以提取所需信息(传递给&#39; passit&#39;的内容)。 这里的一个问题是,没有以编程方式构建访问此信息的方法。 函数 ListLines 会覆盖临时 User32.ShowWindow 和 User32.SetForgroundWindow ,只返回 true ,因此buildin命令< em> ListLines 可以在不显示其窗口的情况下使用(可能会产生多线程脚本问题)。从这个隐藏的&#39;窗口接收并清理其文本。功能由Lexikos编写(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`n\K[\s\S]*(?=`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.
}
答案 1 :(得分:1)
最接近你想要的......?这让我想起了一个问题 见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"
}