使用GetSaveFileName时,文件名为中文时,出现错误,不弹出窗口.
那位朋友解决过此问题,请赐教.

解决方案 »

  1.   

    Option ExplicitPrivate Declare Function lstrlen Lib "kernel32" Alias "lstrlenA" (ByVal lpString As String) As Long
    Private Declare Function GetSaveFileName Lib "COMDLG32" Alias "GetSaveFileNameA" (file As OPENFILENAME) As Long
    Private Const MAX_PATH = 260
    Private Const MAX_FILE = 260Private Type OPENFILENAME
        lStructSize As Long                                    ' Filled with UDT size
        hWndOwner As Long                                      ' Tied to Owner
        hInstance As Long                                      ' Ignored (used only by templates)
        lpstrFilter As String                                  ' Tied to Filter
        lpstrCustomFilter As String                            ' Ignored (exercise for reader)
        nMaxCustFilter As Long                                 ' Ignored (exercise for reader)
        nFilterIndex As Long                                   ' Tied to FilterIndex
        lpstrFile As String                                    ' Tied to FileName
        nMaxFile As Long                                       ' Handled internally
        lpstrFileTitle As String                               ' Tied to FileTitle
        nMaxFileTitle As Long                                  ' Handled internally
        lpstrInitialDir As String                              ' Tied to InitDir
        lpstrTitle As String                                   ' Tied to DlgTitle
        flags As Long                                          ' Tied to Flags
        nFileOffset As Integer                                 ' Ignored (exercise for reader)
        nFileExtension As Integer                              ' Ignored (exercise for reader)
        lpstrDefExt As String                                  ' Tied to DefaultExt
        lCustData As Long                                      ' Ignored (needed for hooks)
        lpfnHook As Long                                       ' Ignored (good luck with hooks)
        lpTemplateName As Long                                 ' Ignored (good luck with templates)
    End TypePrivate Enum EOpenFile
        OFN_READONLY = &H1
        OFN_OVERWRITEPROMPT = &H2
        OFN_HIDEREADONLY = &H4
        OFN_NOCHANGEDIR = &H8
        OFN_SHOWHELP = &H10
        OFN_ENABLEHOOK = &H20
        OFN_ENABLETEMPLATE = &H40
        OFN_ENABLETEMPLATEHANDLE = &H80
        OFN_NOVALIDATE = &H100
        OFN_ALLOWMULTISELECT = &H200
        OFN_EXTENSIONDIFFERENT = &H400
        OFN_PATHMUSTEXIST = &H800
        OFN_FILEMUSTEXIST = &H1000
        OFN_CREATEPROMPT = &H2000
        OFN_SHAREAWARE = &H4000
        OFN_NOREADONLYRETURN = &H8000
        OFN_NOTESTFILECREATE = &H10000
        OFN_NONETWORKBUTTON = &H20000
        OFN_NOLONGNAMES = &H40000
        OFN_EXPLORER = &H80000
        OFN_NODEREFERENCELINKS = &H100000
        OFN_LONGNAMES = &H200000
    End Enum
    Function ShowSave(FileName As String, _
                               Optional FileTitle As String, _
                               Optional OverWritePrompt As Boolean = True, _
                               Optional Filter As String = "All (*.*)| *.*", _
                               Optional FilterIndex As Long = 1, _
                               Optional InitDir As String, _
                               Optional DlgTitle As String, _
                               Optional DefaultExt As String, _
                               Optional Owner As Long = -1, _
                               Optional flags As Long, _
                               Optional Hook As Boolean = False, _
                               Optional EventSink As Object _
                            ) As Boolean    Dim opfile As OPENFILENAME, S As String    With opfile
            .lStructSize = Len(opfile)        ' Add in specific flags and strip out non-VB flags
            .flags = (-OverWritePrompt * OFN_OVERWRITEPROMPT) Or _
                    OFN_HIDEREADONLY Or _
                    (flags And CLng(Not (OFN_ENABLEHOOK Or _
                    OFN_ENABLETEMPLATE)))
            ' Owner can take handle of owning window
            If Owner <> -1 Then .hWndOwner = Owner
            ' InitDir can take initial directory string
            .lpstrInitialDir = InitDir
            ' DefaultExt can take default extension
            .lpstrDefExt = DefaultExt
            ' DlgTitle can take dialog box title
            .lpstrTitle = DlgTitle        ' Make new filter with bars (|) replacing nulls and double null at end
            Dim ch As String, i As Integer
            For i = 1 To Len(Filter)
                ch = Mid$(Filter, i, 1)
                If ch = "|" Or ch = ":" Then
                    S = S & vbNullChar
                Else
                    S = S & ch
                End If
            Next
            ' Put double null at end
            S = S & vbNullChar & vbNullChar
            .lpstrFilter = S
            .nFilterIndex = FilterIndex        ' Pad file and file title buffers to maximum path
            S = FileName & String$(MAX_PATH - Len(FileName), 0)
            .lpstrFile = S
            .nMaxFile = MAX_PATH
            S = FileTitle & String$(MAX_FILE - Len(FileTitle), 0)
            .lpstrFileTitle = S
            .nMaxFileTitle = MAX_FILE
            ' All other fields zero        Dim m_lApiReturn As Long
            m_lApiReturn = GetSaveFileName(opfile)
            'ClearHookedDialog
            Select Case m_lApiReturn
            Case 1
                ShowSave = True
                FileName = StrZToStr(.lpstrFile)
                FileTitle = StrZToStr(.lpstrFileTitle)
                flags = .flags
                ' Return the filter index
                FilterIndex = .nFilterIndex
                ' Look up the filter the user selected and return that
                Filter = FilterLookup(.lpstrFilter, FilterIndex)
            Case 0
                ' Cancelled:
                ShowSave = False
                FileName = ""
                FileTitle = ""
                flags = 0
                FilterIndex = 0
                Filter = ""
            Case Else
                ' Extended error:
                ShowSave = False
                FileName = ""
                FileTitle = ""
                flags = 0
                FilterIndex = 0
                Filter = ""
            End Select
        End With
    End FunctionPrivate Function StrZToStr(S As String) As String
        StrZToStr = Left$(S, lstrlen(S))
    End FunctionPrivate Function FilterLookup(ByVal sFilters As String, ByVal iCur As Long) As String
        Dim iStart As Long, iEnd As Long, S As String
        iStart = 1
        If sFilters = "" Then Exit Function
        Do
            ' Cut out both parts ed by null character
            iEnd = InStr(iStart, sFilters, vbNullChar)
            If iEnd = 0 Then Exit Function
            iEnd = InStr(iEnd + 1, sFilters, vbNullChar)
            If iEnd Then
                S = Mid$(sFilters, iStart, iEnd - iStart)
            Else
                S = Mid$(sFilters, iStart)
            End If
            iStart = iEnd + 1
            If iCur = 1 Then
                FilterLookup = S
                Exit Function
            End If
            iCur = iCur - 1
        Loop While iCur
    End Function
      

  2.   

    可能是你的OPENFILENAME结构中的处理中文字符串的长度时出现了错误,你可以尝试使用GetSaveFileNameW而不是GetSaveFileNameA
    另外对于OPENFILENAME结构的详细解释,你可以参考:
    http://www.zahui.com/html/1/1690.htm
      

  3.   

    Public Declare Function GetSaveFileName Lib "comdlg32.dll" Alias "GetSaveFileNameW" (pOpenfilename As OPENFILENAME) As Long' Save file dialoge
    Private Function Savefiles()
        Dim sFilters As String
        
        With OFN
            .nStructSize = Len(OFN)
            .hwndOwner = Me.hwnd
            .sFilter = StrConv(FILTER, vbUnicode)
            
            .nFilterIndex = 2
            
            .sFile = StrConv(getInFileName(txtInFilePath.Text), vbUnicode) & vbNullChar & vbNullChar
            
            .nMaxFile = 512 'Len(.sFile)
            
            .sDefFileExt = "bas" & vbNullChar & vbNullChar
            
            .sFileTitle = vbNullChar & Space$(512) & vbNullChar & vbNullChar
            
            .nMaxTitle = Len(OFN.sFileTitle)
            
            .flags = &H2 Or &H4
            .sInitialDir = OutFilePath
            .sDialogTitle = StrConv("Save Windows Media File...", vbUnicode)
            
        End With
        
        If GetSaveFileName(OFN) Then
            txtOutFilePath.Text = StrConv(OFN.sFile, vbFromUnicode)
        Else
            '
        End If
    End Function
    这样能够正确弹出窗口,并正确显示汉字,但是返回的文件名错误.会丢失信息.
    如:
    应该的返回信息 D:\music\当你说爱我的时候 - 严波.wma
    现在的返回信息 D:\music\当你说爱我的时候 
      

  4.   

    "贴全" 不太好,大部分是业务代码,和本功能无关.
    我的操作系统是Win2k.
    相关代码如下:
    '-------------------------------------------------------Public Declare Function GetOpenFileName Lib "comdlg32.dll" Alias "GetOpenFileNameA" (pOpenfilename As OPENFILENAME) As Long
    Public Declare Function GetSaveFileName Lib "comdlg32.dll" Alias "GetSaveFileNameW" (pOpenfilename As OPENFILENAME) As Long
    Public Declare Function GetShortPathName Lib "kernel32" Alias "GetShortPathNameA" (ByVal lpszLongPath As String, ByVal lpszShortPath As String, ByVal cchBuffer As Long) As Long
    Public Declare Function GetParent Lib "user32" (ByVal hwnd As Long) As Long
    Public Declare Function SetWindowText Lib "user32" Alias "SetWindowTextA" (ByVal hwnd As Long, ByVal lpString As String) As Long
    Public Declare Function MoveWindow Lib "user32" (ByVal hwnd As Long, ByVal X As Long, ByVal Y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal bRepaint As Long) As Long
    Public Declare Function GetWindowRect Lib "user32" (ByVal hwnd As Long, lpRect As RECT) As LongPublic Declare Function lstrlen Lib "kernel32" Alias "lstrlenA" (ByVal lpString As String) As LongPublic Const OFN_ALLOWMULTISELECT As Long = &H200
    Public Const OFN_CREATEPROMPT As Long = &H2000
    Public Const OFN_ENABLEHOOK As Long = &H20
    Public Const OFN_ENABLETEMPLATE As Long = &H40
    Public Const OFN_ENABLETEMPLATEHANDLE As Long = &H80
    Public Const OFN_EXPLORER As Long = &H80000
    Public Const OFN_EXTENSIONDIFFERENT As Long = &H400
    Public Const OFN_FILEMUSTEXIST As Long = &H1000
    Public Const OFN_HIDEREADONLY As Long = &H4
    Public Const OFN_LONGNAMES As Long = &H200000
    Public Const OFN_NOCHANGEDIR As Long = &H8
    Public Const OFN_NODEREFERENCELINKS As Long = &H100000
    Public Const OFN_NOLONGNAMES As Long = &H40000
    Public Const OFN_NONETWORKBUTTON As Long = &H20000
    Public Const OFN_NOREADONLYRETURN As Long = &H8000
    Public Const OFN_NOTESTFILECREATE As Long = &H10000
    Public Const OFN_NOVALIDATE As Long = &H100
    Public Const OFN_OVERWRITEPROMPT As Long = &H2
    Public Const OFN_PATHMUSTEXIST As Long = &H800
    Public Const OFN_READONLY As Long = &H1
    Public Const OFN_SHAREAWARE As Long = &H4000
    Public Const OFN_SHAREFALLTHROUGH As Long = 2
    Public Const OFN_SHAREWARN As Long = 0
    Public Const OFN_SHARENOWARN As Long = 1
    Public Const OFN_SHOWHELP As Long = &H10
    Public Const OFS_MAXPATHNAME As Long = 260Public Const OFS_FILE_OPEN_FLAGS = OFN_EXPLORER _
                 Or OFN_LONGNAMES _
                 Or OFN_CREATEPROMPT _
                 Or OFN_NODEREFERENCELINKSPublic Const OFS_FILE_SAVE_FLAGS = OFN_EXPLORER _
                 Or OFN_LONGNAMES _
                 Or OFN_OVERWRITEPROMPT _
                 Or OFN_HIDEREADONLYPublic Type OPENFILENAME
      nStructSize       As Long
      hwndOwner         As Long
      hInstance         As Long
      sFilter           As String
      sCustomFilter     As String
      nMaxCustFilter    As Long
      nFilterIndex      As Long
      sFile             As String
      nMaxFile          As Long
      sFileTitle        As String
      nMaxTitle         As Long
      sInitialDir       As String
      sDialogTitle      As String
      flags             As Long
      nFileOffset       As Integer
      nFileExtension    As Integer
      sDefFileExt       As String
      nCustData         As Long
      fnHook            As Long
      sTemplateName     As String
    End TypePublic OFN As OPENFILENAMEPrivate Function Openfiles()
        Dim sFilters As String
        
        With OFN
            .nStructSize = Len(OFN)
            .hwndOwner = Me.hwnd
            .sFilter = FILTER
            
            .nFilterIndex = 2
            .sFile = Space$(1024) & vbNullChar & vbNullChar
            .nMaxFile = Len(.sFile)
            
            .sDefFileExt = "bas" & vbNullChar & vbNullChar
            .sFileTitle = vbNullChar & Space$(512) & vbNullChar & vbNullChar
            .nMaxTitle = Len(OFN.sFileTitle)
            
            .sInitialDir = InFilePath
            .sDialogTitle = "Open Windows Media File"
            '.flags = OFS_FILE_OPEN_FLAGS Or OFN_ALLOWMULTISELECT Or OFN_EXPLORER
            .flags = OFN_HIDEREADONLY + OFN_PATHMUSTEXIST + OFN_FILEMUSTEXIST
            .fnHook = FARPROC(AddressOf OFNHookProc)
        End With
        
        If GetOpenFileName(OFN) Then
            txtInFilePath.Text = Trim(OFN.sFile)
        Else
            '
        End If
    End Function
        
    ' Save file dialoge
    Private Function Savefiles()
        Dim sFilters As String
        
        With OFN
            .nStructSize = Len(OFN)
            .hwndOwner = Me.hwnd
            .sFilter = StrConv(FILTER, vbUnicode)
            
            .nFilterIndex = 2
            
            .sFile = StrConv(getInFileName(txtInFilePath.Text), vbUnicode) & vbNullChar & vbNullChar
            
            .nMaxFile = 512 'Len(.sFile)
            
            .sDefFileExt = vbNullChar & vbNullChar
            
            .sFileTitle = StrConv(vbNullChar & Space$(512) & vbNullChar & vbNullChar, vbUnicode)
            
            .nMaxTitle = Len(OFN.sFileTitle)
            
            .flags = &H4 Or &H2
            .sInitialDir = OutFilePath
            .sDialogTitle = StrConv("Save Windows Media File...", vbUnicode)
            
        End With
        
        If GetSaveFileName(OFN) Then
            'MsgBox ConvertFileName(OFN.sFile)
            txtOutFilePath.Text = StrConv(OFN.sFile, vbFromUnicode)
        Else
            '
        End If
    End FunctionPrivate Function ConvertFileName(sToConvert As String) As String
        Dim bFileName() As Byte
        Dim lRet As Long
        Dim sBuf As String
        'Get rid of the trailing Null characters
        b = InStr(sToConvert, StrConv(vbNullChar & vbNullChar, vbUnicode)) - 1
        sToConvert = Left$(sToConvert, b)
        'sToConvert = Trim(sToConvert)
        If Len(sToConvert) Mod 2 <> 0 Then
            sToConvert = sToConvert & Chr(0) 'If the file has an ANSI extension or just an ANSI last character of
                                             'a file with no extension, add one on the end
                                             'If we don't add it, the string will end one character too short
        End If
        
        bFileName = StrConv(sToConvert, vbFromUnicode) 'Put the string into a byte array
        
        sBuf = ""
        For lRet = 0 To Len(sToConvert) - 1 Step 2
            'At this point, the unicode characters will show up in sBuf as ?, but, when we actually go
            'to use this in the FSO function, it will find the right file
            sBuf = sBuf & StrConv(Chr(bFileName(lRet)) & Chr(bFileName(lRet + 1)), vbFromUnicode)
        Next    'And return the string for use
        ConvertFileName = sBuf
    End FunctionFunction getInFileName(pPath As String)
        Dim outStr As String
        Dim l As Integer
        
        l = InStrRev(pPath, "\")
        getInFileName = Trim(Right(pPath, Len(pPath) - InStrRev(pPath, "\")))
        'getInFileName = Left$(outStr, lstrlen(outStr))
    End Function