获取传递的ByRef变量的字符串值

时间:2014-05-30 22:40:35

标签: autohotkey byref

假设我调用的函数使用byref修饰符。进入函数后,我想获取传递的变量的字符串值。

myvar := "george"
passit(myvar)

passit(byref whatvar){
    msgbox % %whatvar%    ;I should see a messagebox reporting the string "myvar"
}

如果我没有传递变量byref,那么获取变量的字符串值就可以了。

也许我会以错误的方式解决这个问题。我希望函数知道被引用变量的字符串名称。

2 个答案:

答案 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"
}