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



假设我调用一个使用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。ShowWindowUser32。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"
}

相关内容

  • 没有找到相关文章

最新更新