2013-03-29 245 views
0

FindFirstFileA(ANSI)按原样工作,而不是FindFirstFileW(Unicode)。 Wide版本总是返回-1(INVALID_HANDLE_VALUE),但为什么?为什么FindFirstFileW总是返回-1?

'Declarations: 
Option Explicit 

Private Const MAX_PATH As Long = 260 
Private Const ALTERNATE As Long = 14 
Private Const INVALID_HANDLE_VALUE As Long = -1 

Private Type FILETIME 
    dwLowDateTime As Long 
    dwHighDateTime As Long 
End Type 

Private Type WIN32_FIND_DATA 
     dwFileAttributes As Long 
     ftCreationTime As FILETIME 
     ftLastAccessTime As FILETIME 
     ftLastWriteTime As FILETIME 
     nFileSizeHigh As Long 
     nFileSizeLow As Long 
     dwReserved0 As Long 
     dwReserved1 As Long 
     cFileName As String * MAX_PATH 
     cAlternate As String * ALTERNATE 
End Type 

Private Declare Function FindFirstFileW Lib "kernel32" _ 
    (ByVal lpFileName As String, _ 
    ByRef lpFindFileData As WIN32_FIND_DATA) As Long 

Private Declare Function FindFirstFileA Lib "kernel32" _ 
    (ByVal lpFileName As String, _ 
    ByRef lpFindFileData As WIN32_FIND_DATA) As Long 

Private Declare Function FindClose Lib "kernel32" _ 
    (ByVal hFindFile As Long) As Long 

Public Declare Function GetLastError Lib "kernel32"() As Integer 

'Test Functions: 
Public Function TestA(ByVal sf As String) As Long 
    If Len(sf) < 3 Then Exit Function 
    Dim wfd As WIN32_FIND_DATA 
    TestA = FindFirstFileA(sf, wfd) 
    'Debug.Print "AE:" & GetLastError() 
    If TestA <> INVALID_HANDLE_VALUE Then FindClose TestA 
End Function 

Public Function TestW(ByVal sf As String) As Long 
    If Len(sf) < 3 Then Exit Function 
    Dim wfd As WIN32_FIND_DATA 
    TestW = FindFirstFileW(sf, wfd) 
    'Debug.Print "WE:" & GetLastError() 
    If TestW <> INVALID_HANDLE_VALUE Then FindClose TestW 
End Function 

'Example test 
Private Sub Command1_Click() 
    Dim sDir As String 
    sDir = "C:\new" 
    MsgBox "A: " & TestA(sDir) & vbCrLf _ 
     & "W: " & TestW(sDir) 
End Sub 

P.S.感谢Carey Gregory,但我仍然需要一些帮助来翻译Wide版本。 VB6中的C/C++ WCHAR等效于什么?

//WinBase.h 
typedef struct _WIN32_FIND_DATAA { 
    DWORD dwFileAttributes; 
    FILETIME ftCreationTime; 
    FILETIME ftLastAccessTime; 
    FILETIME ftLastWriteTime; 
    DWORD nFileSizeHigh; 
    DWORD nFileSizeLow; 
    DWORD dwReserved0; 
    DWORD dwReserved1; 
    CHAR cFileName[ MAX_PATH ]; 
    CHAR cAlternateFileName[ 14 ]; 
#ifdef _MAC 
    DWORD dwFileType; 
    DWORD dwCreatorType; 
    WORD wFinderFlags; 
#endif 
} WIN32_FIND_DATAA, *PWIN32_FIND_DATAA, *LPWIN32_FIND_DATAA; 
typedef struct _WIN32_FIND_DATAW { 
    DWORD dwFileAttributes; 
    FILETIME ftCreationTime; 
    FILETIME ftLastAccessTime; 
    FILETIME ftLastWriteTime; 
    DWORD nFileSizeHigh; 
    DWORD nFileSizeLow; 
    DWORD dwReserved0; 
    DWORD dwReserved1; 
    WCHAR cFileName[ MAX_PATH ]; //WCHAR in VB6? 
    WCHAR cAlternateFileName[ 14 ]; //WCHAR in VB6? 
#ifdef _MAC 
    DWORD dwFileType; 
    DWORD dwCreatorType; 
    WORD wFinderFlags; 
#endif 
} WIN32_FIND_DATAW, *PWIN32_FIND_DATAW, *LPWIN32_FIND_DATAW; 

回答

2

WIN32_FIND_DATA有两个版本,就像使用它们的函数一样:ANSI版本和Unicode版本。您需要定义WIN32_FIND_DATAA和WIN32_FIND_DATAW,并使用它们适当的'A'和'W'功能。

+0

你能详细说一下,W版本怎么样? –

+0

正如你明白的,因为你的'TestA'和'TestW'函数,ANSI和Unicode文本都有独立的Win32 API函数。这些函数还需要单独的WIN32_FIND_DATA结构,因为该结构包含文本数据。看看winbase.h中的WIN32_FIND_DATA定义,应该明白你需要做什么。 –

+0

感谢您的回答!我仍然需要一点帮助。看到我更新的问题。 –

2

那么,重新阅读this article后,我发现我的错误。这不是关于单独的WIN32_FIND_DATAW类型,而是需要声明FindFirstFileW参数为LongByVal

Private Declare Function FindFirstFileW Lib "kernel32" _ 
    (ByVal lpFileName As Long, _ 
    ByVal lpFindFileData As Long) As Long 

而且还需要给他们打电话与StrPtr和。

TestW = FindFirstFileW(StrPtr(sf), VarPtr(wfd)) 
+0

您仍然需要定义两个单独的WIN32_FIND_DATA结构,因为Unicode版本的FindFirstFile将返回一个WIN32_FIND_DATAW结构。我不是VB专家,但我的理解是你可以使用ChrW在VB中定义一个WCHAR。 –

+0

@CareyGregory - 我认为VB版本的WIN32_FIND_DATAW是不可能的,当然,如果有人知道方式,我会感激更正。 –

+0

这根本不是不可能的。只需将cFileName和cAlternateFileName分别声明为长度为MAX_PATH * 2和14 * 2的Byte即可。在VB6中使用WCHAR类型的例子遍布整个网络。例如,[这里](http://www.vbforums.com/showthread.php?365738-Classic-VB-Does-Visual-Basic-6-support-Unicode)。 –