ByVal und doch bei ByRef

  • Excel

Es gibt 4 Antworten in diesem Thema. Der letzte Beitrag () ist von petaod.

    ByVal und doch bei ByRef

    Hallo miteinand,
    einfache Fragestellung: Im Code wird "path" ByVal übergeben, wie kann es sein, dass "path" nach dem Aufruf geändert wurde?
    Danke.

    Visual Basic-Quellcode

    1. r = SHGetPathFromIDList(ByVal x, ByVal path)


    Hier das Macro zum testen:

    Visual Basic-Quellcode

    1. '----------------------------------
    2. '- macro to get a folder
    3. '--------------------------------------
    4. Option Explicit
    5. Public Type BROWSEINFO
    6. hOwner As Long
    7. pidlRoot As Long
    8. pszDisplayName As String
    9. lpszTitle As String
    10. ulFlags As Long
    11. lpfn As Long
    12. lParam As Long
    13. iImage As Long
    14. End Type
    15. '32-bit API declarations
    16. Declare Function SHGetPathFromIDList Lib "shell32.dll" _
    17. Alias "SHGetPathFromIDListA" (ByVal pidl As Long, ByVal pszPath As String) _
    18. As Long
    19. '- API function
    20. Declare Function SHBrowseForFolder Lib "shell32.dll" _
    21. Alias "SHBrowseForFolderA" (lpBrowseInfo As BROWSEINFO) As Long
    22. '=================================================
    23. '- THIS RUNS THE WHOLE MACRO TO GET THE SELECTION
    24. '=================================================
    25. Sub BrowseFolders()
    26. Dim Msg As String
    27. Msg = "Please select a folder."
    28. MsgBox GetDirectory(Msg)
    29. End Sub
    30. '
    31. '-------------------------
    32. '- this does the API call
    33. '-------------------------
    34. Function GetDirectory(Optional Msg) As String
    35. Dim bInfo As BROWSEINFO
    36. Dim path As String
    37. Dim r As Long, x As Long, pos As Integer
    38. '---------------------------
    39. ' Root folder = Desktop
    40. bInfo.pidlRoot = 0&
    41. '---------------------------
    42. ' Title in the dialog
    43. If IsMissing(Msg) Then
    44. bInfo.lpszTitle = "Select a folder."
    45. Else
    46. bInfo.lpszTitle = Msg
    47. End If
    48. '---------------------------
    49. ' Type of directory to return
    50. bInfo.ulFlags = &H1
    51. '---------------------------
    52. ' Display the dialog
    53. x = SHBrowseForFolder(bInfo)
    54. '---------------------------
    55. ' Parse the result
    56. path = Space$(512)
    57. r = SHGetPathFromIDList(ByVal x, ByVal path)
    58. If r Then
    59. pos = InStr(path, Chr$(0))
    60. GetDirectory = Left(path, pos - 1)
    61. Else
    62. GetDirectory = ""
    63. End If
    64. End Function
    65. '----------------------------------------------------

    Martin07 schrieb:

    SHGetPathFromIDList
    Die Definition:

    C-Quellcode

    1. BOOL SHGetPathFromIDList(_In_ PCIDLIST_ABSOLUTE pidl, _Out_ LPTSTR pszPath)

    pszPath ist ein Pointer auf einen String.
    Der Pointer wird nicht geändert, wohl aber der String.
    Der ist definitiv als _Out_ markiert.

    Im Gegensatz zu einem internen Aufruf, bei dem ein ByVal-String in der Sub kopiert wird, hat VBA bei einem API-Aufruf keinen Einfluss auf das Verhalten der Sub.
    In dem Fall musst du den String als Object betrachten, dessen Pointer du übergibst.
    --
    If Not Program.isWorking Then Code.Debug Else Code.DoNotTouch
    --
    Da ist gar nichts merkwürdig.
    Du machst deine API-Definition falsch.
    Declare Function SHGetPathFromIDList Lib "shell32.dll" Alias "SHGetPathFromIDListA" (ByVal pidl As Long, ByVal pszPath As String) As Long
    Wenn die externe Funktion den pszPath als Pointer auf einen Out-String verwendet, dann ist dein ByVal falsch.
    Die Deklaration muss dem Original entsprechen.
    Es nutzt nichts, die Deklaration zu verändern und dann zu erwarten, dass sich das Original anders verhält.
    --
    If Not Program.isWorking Then Code.Debug Else Code.DoNotTouch
    --