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ます。また、長い (ANSI バージョンのような文字列ではない)Len(.lpstrFile)として意味があります。lpstrFile

    Dim sFileBuffer As String
    ...

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

で結果に直接アクセスするsFileBufferか、で API 呼び出しを使用できますlpstrFile

size ( ) に -1 を使用すると、nMaxFile後で簡単に使用でき、 が0 を返さないようにすることができます (部分文字列が見つかりません)。ShowOpenDialog = Left$(sFileBuffer, InStr(sFileBuffer, vbNullChar) - 1)InStr

于 2013-09-02T13:57:27.700 に答える