Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/vba/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
String VBA中的GetOpenFileNameW?_String_Vba_Unicode_Getopenfilename - Fatal编程技术网

String VBA中的GetOpenFileNameW?

String VBA中的GetOpenFileNameW?,string,vba,unicode,getopenfilename,String,Vba,Unicode,Getopenfilename,好的,我在这里可能有点离题,但我想做的是使用GetOpenFileName的API调用的宽(Unicode)版本返回多个文件的列表 现在,我想这样做的原因是: 选择多个文件时,文件名的字符总数限制取决于函数的版本。 •ANSI:32k限值 •Unicode:无限制 从网络深处的目录返回大量文件选择可能很快超过ANSI 32k字符限制 所以,我所做的就是使用我正在工作的ANSI声明函数,用lngptr替换所有string声明的变量。然后,在需要为这些字符串赋值的地方,我使用了strprtr()函数

好的,我在这里可能有点离题,但我想做的是使用GetOpenFileName的API调用的宽(Unicode)版本返回多个文件的列表

现在,我想这样做的原因是: 选择多个文件时,文件名的字符总数限制取决于函数的版本。
•ANSI:32k限值
•Unicode:无限制

从网络深处的目录返回大量文件选择可能很快超过ANSI 32k字符限制

所以,我所做的就是使用我正在工作的ANSI声明函数,用
lngptr
替换所有
string
声明的变量。然后,在需要为这些字符串赋值的地方,我使用了
strprtr()
函数来转换字符串值

现在,当我尝试调用这个函数时,当它到达调用声明函数的部分时,
lReturn=GetOpenFileNameU(OpenFile)
!。没有错误,什么都没有——只要越过那条线,什么也不会发生。我做错了什么

这就是我现在的处境:

Option Explicit
'***NOTE: _
    This class object requires the following references: _
        <NONE>

'Declare the windows API function for GetOpenFileNameA
'MSDN Reference: http://msdn.microsoft.com/en-us/library/windows/desktop/ms646927(v=vs.85).aspx
Public Declare PtrSafe Function GetOpenFileNameU Lib "comdlg32.dll" Alias "GetOpenFileNameW" (pOpenfilename As OPENFILENAME) As Long

Public 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& '*see comments
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 OFN_ENABLESIZING As Long = &H800000
Public Const OFS_MAXPATHNAME As Long = 260

'Create a custom type that matches the OPENFILENAME structure
'MSDN reference: http://msdn.microsoft.com/en-us/library/windows/desktop/ms646839(v=vs.85).aspx
Public Type OPENFILENAME
    lStructSize As Long
    hwndOwner As LongPtr
    hInstance As LongPtr
    lpstrFilter As LongPtr
    lpstrCustomFilter As LongPtr
    nMaxCustFilter As Long
    nFilterIndex As Long
    lpstrFile As LongPtr
    nMaxFile As Long
    lpstrFileTitle As LongPtr
    nMaxFileTitle As Long
    lpstrInitialDir As LongPtr
    lpstrTitle As LongPtr
    flags As Long
    nFileOffset As Integer
    nFileExtension As Integer
    lpstrDefExt As LongPtr
    lCustData As Long
    lpfnHook As LongPtr
    lpTemplateName As LongPtr
End Type


'OFS_FILE_OPEN_FLAGS:
'Can view explanation of flags here on the MSDN reference: http://msdn.microsoft.com/en-us/library/windows/desktop/ms646839(v=vs.85).aspx
Public Const OFS_FILE_OPEN_FLAGS = _
                OFN_EXPLORER Or _
                OFN_LONGNAMES Or _
                OFN_CREATEPROMPT Or _
                OFN_NODEREFERENCELINKS

'Windows version constants
Private Const VER_PLATFORM_WIN32_NT As Long = 2
Private Const OSV_LENGTH As Long = 76
Private Const OSVEX_LENGTH As Long = 88
Public OSV_VERSION_LENGTH As Long

Public Const WM_INITDIALOG As Long = &H110
Private Const SW_SHOWNORMAL As Long = 1


Public Function BrowseForFile(strTitle As String, myFilter As String, Optional initialDir As String = "") As String
'This function allows you to browse for files and returns a string containing the files selected

'Declare variables
    Dim OpenFile    As OPENFILENAME
    Dim lReturn     As Long
    Dim strFile     As String


'Set the file type filter
    OpenFile.lpstrFilter = StrPtr(myFilter)

'Set the filter index.  This is the order of the filters available to select from in the dialog.  1= the first in the list (and currently active)
    OpenFile.nFilterIndex = 1

'Set the handle to the window that owns the dialog box
    OpenFile.hwndOwner = 0

'lpstrFile is a pointer to a string which contains the current directory followed by list of file names selected. _
'Create an empty string to use as buffer, it needs to be at least 256 chars plus a terminating NULL char
    strFile = String(257, 0)
'Pass the buffer string to the pointer
    OpenFile.lpstrFile = StrPtr(strFile)

'The size of nMaxFile = the size, in characters, of the string pointed to by lpstrFile (less one NULL character at the end)
'The size of lStructSize = The length, in bytes, of the structure. Use size of (OPENFILENAME) for this parameter.

'BEFORE we can set the above two properties, we need to heck which version of VBA we are working with (SW uses VBA7, Office uses VBA6) _
 The # indiicates preprocessor command, which is processed prior to compilation, which ensures that the code compiles per the correct platform
        #If VBA7 Then
        'When environment is VBA7, use LenB (binary compare)
            OpenFile.nMaxFile = LenB(strFile) - 1
            OpenFile.lStructSize = LenB(strFile)
        #Else
        'When environment is anything else, use Len (text compare)
            OpenFile.nMaxFile = Len(strFile) - 1
            OpenFile.lStructSize = Len(strFile)
        #End If

'This points to a string containing just the file name and extension (without path info), whereas lpstrFile contains the path info also.
    OpenFile.lpstrFileTitle = OpenFile.lpstrFile
'This is to lpstrFileTile what nMaxFile is to lpstrFile
    OpenFile.nMaxFileTitle = OpenFile.nMaxFile

    'Check if the calling procedure specified a starting directory
        If initialDir <> "" Then OpenFile.lpstrInitialDir = StrPtr(StrConv(initialDir, vbUnicode))

'This will be the title of the window dialog, and is an argument that must be passed by the calling procedure
    OpenFile.lpstrTitle = StrPtr(StrConv(strTitle, vbUnicode))

'Flags control how the window looks and acts. _
'Can view explanation of flags here on the MSDN reference: http://msdn.microsoft.com/en-us/library/windows/desktop/ms646839(v=vs.85).aspx
    OpenFile.flags = OFS_FILE_OPEN_FLAGS + OFN_ALLOWMULTISELECT

'Call the windows API function we delcared and get the return when it completes.
    lReturn = GetOpenFileNameU(OpenFile)

'Check the return, if 0 then no files selected or user cancelled
    If lReturn = 0 Then
        BrowseForFile = ""
    Else
    'lpstrFile contains the current directory followed by list of file names
        BrowseForFile = strFile
    End If
End Function
选项显式
“***注:_
此类对象需要以下引用:_
'为GetOpenFileNameA声明windows API函数
'MSDN参考:http://msdn.microsoft.com/en-us/library/windows/desktop/ms646927(v=vs.85).aspx
将PtrSafe函数GetOpenFileNameU Lib“comdlg32.dll”别名“GetOpenFileNameW”(pOpenfilename作为OPENFILENAME)公开声明为
n_ALLOWMULTISELECT的公共常量,长度=&H200
n_CREATEPROMPT的公共常量,长度=&H2000
n_ENABLEHOOK的公共常量,长度=&H20
n_enablemplate的公共常量,长度=&H40
n_ENABLETEMPLATEHANDLE的公共常量,长度=&H80
N_资源管理器的公共常量,长度=&H80000
n_扩展的公共常量不同于Long=&H400
n_文件的公共常量必须存在为Long=&H1000
n_隐藏的公共常量,只要长=&H4
n_LONGNAMES的公共常数为Long=&H200000
n_NOCHANGEDIR的公共常量,长度=&H8
N_NODEREFERENCELINKS的公共常数,只要长=&H100000
N_nolong名称的公共常数,长度=&H40000
N_NONETWORKBUTTON的公共常量,长度=&H20000
N_NOREADONLYRETURN的公共常数,只要=&H8000&'*参见注释
n_NOTESTFILECREATE As Long=&H10000的公共常量
N_NOVALIDATE的公共常数,长度=&H100
n_的公共常量覆盖了compt,因为Long=&H2
n_路径的公共常量必须存在为Long=&H800
n_READONLY的公共常量,长度=&H1
N_SHAREAWARE的公共常数,长度=&H4000
N_SHAREFALLTHROUGH的公共常数,只要=2
N_SHAREWARN的公共常量,只要=0
N_SHARENOWARN的公共常数等于1
N_SHOWHELP的公共常量,只要长=&H10
启用N_的公共常数长度=&H800000
S_MAXPATHNAME的公共常量,长度=260
'创建与OPENFILENAME结构匹配的自定义类型
'MSDN参考:http://msdn.microsoft.com/en-us/library/windows/desktop/ms646839(v=vs.85).aspx
公共类型OPENFILENAME
l结构尺寸与长度相同
hwndOwner作为LongPtr
hInstance As LongPtr
作为长PTR的LPSTR过滤器
lpstrCustomFilter As LongPtr
nMaxCustFilter尽可能长
n过滤器索引尽可能长
lpstrFile作为LongPtr
nMaxFile尽可能长
lpstrFileTitle作为LongPtr
nMaxFileTitle尽可能长
lpstrInitialDir作为LongPtr
lpstrTitle As LongPtr
旗子一样长
nFileOffset为整数
nFileExtension为整数
lpstrDefExt作为LongPtr
lCustData尽可能长
lpfnHook As LongPtr
lpTemplateName作为LongPtr
端型
'OFS_文件_打开_标志:
'可以在MSDN参考上的此处查看标志说明:http://msdn.microsoft.com/en-us/library/windows/desktop/ms646839(v=vs.85).aspx
文件打开标志的公共常量=_
OFN_探险家或_
N_LONGNAMES或_
OFN_CREATEPROMPT或_
N_NODEREFERENCELINKS公司
'Windows版本常量
Private Const VER_PLATFORM_WIN32_NT的长度=2
专用常量OSV_长度(长度=76)
专用常量OSVEX_长度(长度=88)
公共OSV_版本_长度为
Public Const WM_INITDIALOG的长度=&H110
专用常量SW_SHOWNORMAL,只要长=1
公共函数BrowseForFile(strTitle作为字符串,myFilter作为字符串,可选initialDir作为字符串=”)作为字符串
'此函数允许您浏览文件并返回包含所选文件的字符串
'声明变量
将OpenFile设置为OPENFILENAME
变暗,变长
作为字符串的Dim strFile
'设置文件类型筛选器
OpenFile.lpstrFilter=StrPtr(myFilter)
'设置过滤器索引。这是对话框中可供选择的过滤器的顺序。1=列表中的第一个(当前处于活动状态)
OpenFile.nFilterIndex=1
'将句柄设置为拥有该对话框的窗口
OpenFile.hwndOwner=0
'lpstrFile是指向字符串的指针,该字符串包含当前目录,后跟所选文件名列表_
'创建一个空字符串用作缓冲区,它至少需要256个字符加上一个终止的空字符
strFile=String(257,0)
'将缓冲区字符串传递给指针
OpenFile.lpstrFile=StrPtr(strFile)
'nMaxFile的大小=lpstrFile指向的字符串的大小(以字符为单位)(末尾减去一个空字符)
'lStructSize的大小=结构的长度(以字节为单位)。使用此参数的大小(OPENFILENAME)。
'在设置上述两个属性之前,我们需要检查正在使用的VBA版本(SW使用VBA7,Office使用VBA6)_
#indicates preprocessor命令在编译之前进行处理,确保代码按照正确的平台编译
#如果是VBA7,则
'当环境为VBA7时,使用LenB(二进制比较)
OpenFile.nMaxFile=LenB(strFile)-1
OpenFile.lStructSize=LenB(strFile)
#否则
'如果环境是其他内容,请使用Len(文本比较)
OpenFile.nMaxFile=Len(strFile)-1
OpenFile.lStructSize=Len(strFile)
Private Declare Sub CopyMemory Lib "kernel32.dll" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)

Function myConversion(lpstr As Long, lenStr As Integer) As String
    Dim bStr() As Byte
    On Error Resume Next

    If lenStr Then
        Dim lenBytes
        lenBytes = (lenStr) * 2
        ReDim bStr(0 To lenBytes - 1) As Byte
        Call CopyMemory(bStr(0), ByVal lpstr, lenBytes)

        Dim i
        Dim s As String
        For i = LBound(bStr) To UBound(bStr) Step 2
            s = s & Chr(bStr(i))
        Next i
    End If

    myConversion = s
End Function