- Код: Выделить всё
<StructLayout(LayoutKind.Sequential, pack:=1)> Private Structure OPENFILENAME1
Public lStructSize As Integer
Public hwndOwner As IntPtr
Public hInstance As IntPtr
<MarshalAs(UnmanagedType.LPWStr)> Public lpstrFilter As String
<MarshalAs(UnmanagedType.LPWStr)> Public lpstrCustomFilter As String
Public nMaxCustFilter As Integer
Public nFilterIndex As Integer
<MarshalAs(UnmanagedType.LPWStr)> Public lpstrFile As String
Public nMaxFile As Integer
<MarshalAs(UnmanagedType.LPWStr)> Public lpstrFileTitle As String
Public nMaxFileTitle As Integer
<MarshalAs(UnmanagedType.LPWStr)> Public lpstrInitialDir As String
<MarshalAs(UnmanagedType.LPWStr)> Public lpstrTitle As String
Public Flags As Integer
Public nFileOffset As Short
Public nFileExtension As Short
<MarshalAs(UnmanagedType.LPWStr)> Public lpstrDefExt As String
Public lCustData As Integer
Public lpfnHook As IntPtr
Public lpTemplateName As Integer
Public pvReserved As IntPtr
Public dwReserved As Integer
Public FlagsEx As Integer
End Structure
Private Declare Unicode Function GetOpenFileName Lib "comdlg32" Alias "GetOpenFileNameW" (ByRef ofn As OPENFILENAME1) As Integer
Private Const OFN_READONLY As Integer = &H1
Private Const OFN_OVERWRITEPROMPT As Integer = &H2
Private Const OFN_HIDEREADONLY As Integer = &H4
Private Const OFN_NOCHANGEDIR As Integer = &H8
Private Const OFN_SHOWHELP As Integer = &H10
Private Const OFN_ENABLEHOOK As Integer = &H20
Private Const OFN_ENABLETEMPLATE As Integer = &H40
Private Const OFN_ENABLETEMPLATEHANDLE As Integer = &H80
Private Const OFN_NOVALIDATE As Integer = &H100
Private Const OFN_ALLOWMULTISELECT As Integer = &H200
Private Const OFN_EXTENSIONDIFFERENT As Integer = &H400
Private Const OFN_PATHMUSTEXIST As Integer = &H800
Private Const OFN_FILEMUSTEXIST As Integer = &H1000
Private Const OFN_CREATEPROMPT As Integer = &H2000
Private Const OFN_SHAREAWARE As Integer = &H4000
Private Const OFN_NOREADONLYRETURN As Integer = &H8000
Private Const OFN_NOTESTFILECREATE As Integer = &H10000
Private Const OFN_NONETWORKBUTTON As Integer = &H20000
Private Const OFN_NOLONGNAMES As Integer = &H40000
Private Const OFN_EXPLORER As Integer = &H80000
Private Const OFN_NODEREFERENCELINKS As Integer = &H100000
Private Const OFN_LONGNAMES As Integer = &H200000
Private Const OFN_ENABLEINCLUDENOTIFY As Integer = &H400000
Private Const OFN_ENABLESIZING As Integer = &H800000
Private Const OFN_DONTADDTORECENT As Integer = &H2000000
Private Const OFN_FORCESHOWHIDDEN As Integer = &H10000000
'FlagsEx Values
Private Const OFN_EX_NOPLACESBAR As Integer = &H1
Private ReadOnly cNull As Char = ChrW(0)
Function Main() As Integer
Dim ofn As OPENFILENAME1
ofn.lStructSize = Marshal.SizeOf(ofn)
ofn.Flags = OFN_ALLOWMULTISELECT Or OFN_EXPLORER
ofn.lpstrFile = New String(cNull, 256)
ofn.nMaxFile = 256
ofn.lpstrFileTitle = New String(cNull, 256)
ofn.nMaxFileTitle = 256
ofn.lpstrFilter = "Текстовые файлы" & cNull & "*.txt" & cNull & "Все файлы" & cNull & "*.*" & cNull
ofn.nFilterIndex = 1
If GetOpenFileName(ofn) <> 0 Then
Console.WriteLine("Имя файла: {0}", ofn.lpstrFile)
Console.WriteLine("Длина строки: {0}", ofn.lpstrFile.Length)
End If
End Function
Если в диалоге выбрать несколько файлов, то в ofn.lpstrFile будет содержаться только путь к папке из которой были выбраны файлы. Длина сей строки будет соответствующей.
В соответствии с MSDN при установки флагов OFN_ALLOWMULTISELECT и OFN_EXPLORER в ofn.lpstrFile должны возвращаться путь к папке и собственно файлы, разделенные нуль-терминатороми. После нескольких попыток выснить в чем тут дело, оказалось, что ВСЕ элементы структуры, являющиеся строками обрезаются до ближайщего нуль-терминатора. Дальше выяснилось, что таким образом обрабатываются ВСЕ аналогичные API функции, то есть функции использующие в качестве параметра структуры, содержащие указатели на строки.
Для интереса я сменил определение структуры и получил более приемлимые результаты:
- Код: Выделить всё
<StructLayout(LayoutKind.Sequential, pack:=1)> Private Structure OPENFILENAME2
Public lStructSize As Integer
Public hwndOwner As IntPtr
Public hInstance As IntPtr
Public lpstrFilter As IntPtr
Public lpstrCustomFilter As IntPtr
Public nMaxCustFilter As Integer
Public nFilterIndex As Integer
Public lpstrFile As IntPtr
Public nMaxFile As Integer
Public lpstrFileTitle As IntPtr
Public nMaxFileTitle As Integer
Public lpstrInitialDir As IntPtr
Public lpstrTitle As IntPtr
Public Flags As Integer
Public nFileOffset As Short
Public nFileExtension As Short
Public lpstrDefExt As IntPtr
Public lCustData As Integer
Public lpfnHook As IntPtr
Public lpTemplateName As Integer
Public pvReserved As IntPtr
Public dwReserved As Integer
Public FlagsEx As Integer
End Structure
Private Declare Unicode Function GetOpenFileName Lib "comdlg32" Alias "GetOpenFileNameW" (ByRef ofn As OPENFILENAME2) As Integer
Private Sub Main()
Dim ofn As OPENFILENAME2
ofn.lStructSize = Marshal.SizeOf(ofn)
ofn.Flags = OFN_ALLOWMULTISELECT Or OFN_EXPLORER
Dim sFile(255) As Char
Dim sFileTitle(255) As Char
Dim sFilter() As Char = ("Текстовые файлы" & cNull & "*.txt" & cNull & "Все файлы" & cNull & "*.*" & cNull).ToCharArray
ofn.lpstrFile = Marshal.UnsafeAddrOfPinnedArrayElement(sFile, 0)
ofn.nMaxFile = 256
ofn.lpstrFileTitle = Marshal.UnsafeAddrOfPinnedArrayElement(sFileTitle, 0)
ofn.nMaxFileTitle = 256
ofn.lpstrFilter = Marshal.UnsafeAddrOfPinnedArrayElement(sFilter, 0)
ofn.nFilterIndex = 1
If GetOpenFileName(ofn) <> 0 Then
Console.WriteLine("Имя файла: {0}", New String(sFile))
Console.WriteLine("Длина строки: {0}", sFile.Length)
End If
End Sub
То есть во втором варианте вместо строк передается указатель на первый элемент символьного массива, что для C в принципе тоже самое. Длина символьного массива после возвращения из функции здесь не меняется и он содержит то что должен содержать.
Может ли кто-нить что-нить сказать по этому поводу?
P.S. Про существование OpenFileDialog я знаю