【问题标题】:Get String Value of passed ByRef Variable获取传递的 ByRef 变量的字符串值
【发布时间】:2014-07-20 18:58:30
【问题描述】:

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

myvar := "george"
passit(myvar)

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

如果我没有传递变量byref,则获取变量的字符串值可以正常工作。

也许我用错了方法。我希望函数知道被引用变量的字符串名称。

【问题讨论】:

    标签: autohotkey byref


    【解决方案1】:

    此方法使用内置 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.
    

    可以解析此数据以提取所需信息(传递给“passit”的信息)。 这里的一个问题是,没有以编程方式访问此信息的内置方式。 函数 ListLines 覆盖临时 User32.ShowWindowUser32.SetForgroundWindow 以简单地返回 true,因此内置命令 ListLines 可以在不显示其窗口的情况下使用(多线程脚本可能会产生问题)。从这个“隐藏”窗口接收并清理其文本。函数由 Lexikos (http://www.autohotkey.com/board/topic/20925-listvars/#entry156570http://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.
    }
    

    【讨论】:

    • 说,这似乎有效。谢谢!那里发生了很多事情,你能解释一下发生了什么吗?为了让它更有趣,我这样做了:global myvar msgbox % GetOriginalVariableNameForSingleArgumentOfCurrentCall(A_ThisFunc) . "=" . myvar 让消息框说:myvar=george
    • @BGM 我加了解释
    • 太棒了!非常感谢 - 我明白,这对我来说和 sn-p 一样值钱。
    【解决方案2】:

    最接近您想要的...?这让我想起了一个问题。
    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"
    }
    

    【讨论】:

    • JoeDF - 很接近。问题是我想将变量作为变量传递,而不是作为字符串传递。然后我希望函数能够知道传递变量的字符串名称。
    • @BGM 嗯不知道有没有可能……变量实际是怎么创建的?
    • @BGM 好的,我明白了...如果它绝对不能作为字符串传递,我真的不知道是否有可能...
    • 我认为他需要byref 以便passit 可以修改指定的变量。我同意如果有一些结构可以将变量名称作为字符串获取会很方便,但那是论坛的 Wish List 部分……如果还没有建议的话——我无法确定它是否有。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-08
    • 2013-10-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多