0

我正在更新用 VB6 编写的旧旧系统。我正在尝试使用 GetOpenFileNameW 创建文件对话框。一切都很好,除了我得到的字符串是随机垃圾。有人可以帮忙吗?谢谢...

Public Declare Function GetOpenFileNameW Lib "comdlg32.dll" (pOpenfilename As OPENFILENAME_W) As Long
Public Declare Function lstrlenW Lib "kernel32" (lpString As Any) As Long

Private Type OPENFILENAME_W
   lStructSize          As Long     'Length of structure, in bytes
   hwndOwner            As Long     'Window that owns the dialog, or NULL
   hInstance            As Long     'Handle of mem object containing template (not used)
   lpstrFilter          As Long     'File types/descriptions, delimited with vbnullchar, ends with 2xvbnullchar
   lpstrCustomFilter    As Long     'Filters typed in by user
   nMaxCustFilter       As Long     'Length of CustomFilter, min 40x chars
   nFilterIndex         As Long     'Filter Index to use (1,2,etc) or 0 for custom
   lpstrFile            As Long     'Initial file/returned file(s), delimited with vbnullchar for multi files
   nMaxFile             As Long     'Size of Initial File long  , min 256
   lpstrFileTitle       As Long     'File.ext excluding path
   nMaxFileTitle        As Long     'Length of FileTitle
   lpstrInitialDir      As Long     'Initial file dir, null for current dir
   lpstrTitle           As Long     'Title bar of dialog
   flags                As Long     'See OFN_Flags
   nFileOffset          As Integer  'Offset to file name in full path, 0-based
   nFileExtension       As Integer  'Offset to file ext in full path, 0-based (excl '.')
   lpstrDefExt          As Long     'Default ext appended, excl '.', max 3 chars
   lCustData            As Long     'Appl defined data for lpfnHook
   lpfnHook             As Long     'Pointer to hook procedure
   lpTemplateName       As Long     'Template Name (not used)
   pvReserved           As Long     'new Win2000 / WinXP members
   dwReserved           As Long     'new Win2000 / WinXP members
   FlagsEx              As Long     'new Win2000 / WinXP members
End Type

Public Function ShowOpenDialog(ByVal wHandle As Long, _
                               Optional ByVal filters As String = "", _
                               Optional ByVal initialDir As String = "", _
                               Optional ByVal dialogTitle As String = "", _
                               Optional ByVal flags As Long = 0) As String    
Dim strBuffer   As String
Dim OFN         As OPENFILENAME_W
Dim RetVal      As Long

With OFN
    .lStructSize = Len(OFN)
    .hwndOwner = wHandle
    .hInstance = App.hInstance

    filters = Trim$(Replace(filters, "|", vbNullChar))
    If right$(filters, 2) <> vbNullChar & vbNullChar Then filters = filters & vbNullChar & vbNullChar
    .lpstrFilter = StrPtr(filters)
    If LenB(filters) > 0 Then .nFilterIndex = 1

    .lpstrFile = StrPtr(String(512, vbNullChar))
    .nMaxFile = Len(.lpstrFile)

    .lpstrDefExt = StrPtr(vbNullChar)

    .lpstrFileTitle = StrPtr(String(512, vbNullChar))
    .nMaxFileTitle = Len(OFN.lpstrFileTitle)

    If AscW(right$(initialDir, 1)) <> 0& Then initialDir = initialDir & vbNullChar & vbNullChar
    .lpstrInitialDir = StrPtr(initialDir)

    If AscW(right$(dialogTitle, 1)) <> 0& Then dialogTitle = dialogTitle & vbNullChar & vbNullChar
    .lpstrTitle = StrPtr(dialogTitle)

    .flags = flags
End With

' call API dialog
If GetOpenFileNameW(OFN) Then
    'remove trailing pair of terminating nulls
    'and Trim returned file string
    Dim result  As String
    result = String$(OFN.nMaxFile, 0)

    Dim numChars    As Long
    Dim tempString  As String

    numChars = lstrlenW(OFN.lpstrFile)
    tempString = Space$(numChars)
    CopyMemory ByVal StrPtr(tempString), ByVal OFN.lpstrFile, numChars * 2

    ShowOpenDialog = tempString
End If
End Function
4

1 回答 1

4

您的代码段可能会偶然起作用。您分配的输出缓冲区lpstrFile会立即被释放。首先将其分配给本地 var,然后使用StrPtr将其分配给lpstrFile. 此外,与 longLen(.lpstrFile)一样有意义lpstrFile(不是 ANSI 版本中的字符串)。

    Dim sFileBuffer As String
    ...

    sFileBuffer = String$(512, vbNullChar)
    .lpstrFile = StrPtr(sFileBuffer)
    .nMaxFile = Len(sFileBuffer) - 1
    ...

您可以直接访问结果sFileBuffer,或在lpstrFile.

使用 -1 表示大小 ( nMaxFile),以便您以后可以轻松使用ShowOpenDialog = Left$(sFileBuffer, InStr(sFileBuffer, vbNullChar) - 1)并确保InStr永远不会返回 0(未找到子字符串)。

于 2013-09-02T13:57:27.700 回答