在前面的文章中,https://www.cnblogs.com/zhaotianff/p/13999133.html
介绍了Windows的通用对话框,其中就包括 了打开 文件 对话框。
正常情况下,在C#中需要 浏览文件 ,直接 调用 System.Windows.Forms.OpenFileDialog或Microsoft.Win32.OpenFileDialog类即可 ,但在某些特殊情况下,无法调用这两个类,所以就需要用到API函数GetOpenFileName来浏览文件。
声明OpenFileName结构体
1 [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)] 2 public struct OpenFileName 3 { 4 public int lStructSize; 5 public IntPtr hwndOwner; 6 public IntPtr hInstance; 7 public string lpstrFilter; 8 public string lpstrCustomFilter; 9 public int nMaxCustFilter; 10 public int nFilterIndex; 11 public string lpstrFile; 12 public int nMaxFile; 13 public string lpstrFileTitle; 14 public int nMaxFileTitle; 15 public string lpstrInitialDir; 16 public string lpstrTitle; 17 public int Flags; 18 public short nFileOffset; 19 public short nFileExtension; 20 public string lpstrDefExt; 21 public IntPtr lCustData; 22 public IntPtr lpfnHook; 23 public string lpTemplateName; 24 public IntPtr pvReserved; 25 public int dwReserved; 26 public int flagsEx; 27 }
常量
1 public const int OFN_READONLY = 0x1; 2 public const int OFN_OVERWRITEPROMPT = 0x2; 3 public const int OFN_HIDEREADONLY = 0x4; 4 public const int OFN_NOCHANGEDIR = 0x8; 5 public const int OFN_SHOWHELP = 0x10; 6 public const int OFN_ENABLEHOOK = 0x20; 7 public const int OFN_ENABLETEMPLATE = 0x40; 8 public const int OFN_ENABLETEMPLATEHANDLE = 0x80; 9 public const int OFN_NOVALIDATE = 0x100; 10 public const int OFN_ALLOWMULTISELECT = 0x200; 11 public const int OFN_EXTENSIONDIFFERENT = 0x400; 12 public const int OFN_PATHMUSTEXIST = 0x800; 13 public const int OFN_FILEMUSTEXIST = 0x1000; 14 public const int OFN_CREATEPROMPT = 0x2000; 15 public const int OFN_SHAREAWARE = 0x4000; 16 public const int OFN_NOREADONLYRETURN = 0x8000; 17 public const int OFN_NOTESTFILECREATE = 0x10000; 18 public const int OFN_NONETWORKBUTTON = 0x20000; 19 public const int OFN_NOLONGNAMES = 0x40000; 20 public const int OFN_EXPLORER = 0x80000; 21 public const int OFN_NODEREFERENCELINKS = 0x100000; 22 public const int OFN_LONGNAMES = 0x200000; 23 public const int OFN_ENABLEINCLUDENOTIFY = 0x400000; 24 public const int OFN_ENABLESIZING = 0x800000; 25 public const int OFN_DONTADDTORECENT = 0x2000000; 26 public const int OFN_FORCESHOWHIDDEN = 0x10000000; 27 public const int OFN_EX_NOPLACESBAR = 0x1; 28 public const int OFN_SHAREFALLTHROUGH = 2; 29 public const int OFN_SHARENOWARN = 1; 30 public const int OFN_SHAREWARN = 0;
API函数签名
1 [DllImport("comdlg32.dll", SetLastError = true, CharSet = CharSet.Auto)] 2 static extern bool GetOpenFileName([In, Out] OpenFileName ofn);
调用示例:
1 static List<string> BrowseMultiFile(string filter) 2 { 3 int size = 1024; 4 List<string> list = new List<string>(); 5 //多选文件是传出一个指针,这里需要提前分配空间 6 //如果是单选文件,使用已经分配大小的StringBuilder或string 7 IntPtr filePtr = Marshal.AllocHGlobal(size); 8 9 //清空分配的内存区域 10 for (int i = 0; i < size; i++) 11 { 12 Marshal.WriteByte(filePtr, i, 0); 13 } 14 15 OpenFileName openFileName = new OpenFileName(); 16 openFileName.lStructSize = Marshal.SizeOf(openFileName); 17 openFileName.lpstrFilter = filter; 18 openFileName.filePtr = filePtr; 19 openFileName.nMaxFile = size; 20 openFileName.lpstrFileTitle = new string(new char[64]); 21 openFileName.nMaxFileTitle = 64; 22 openFileName.lpstrInitialDir = Environment.GetFolderPath(Environment.SpecialFolder.Desktop); 23 openFileName.lpstrFileTitle = "浏览文件"; 24 openFileName.lpstrDefExt = "*.*"; 25 openFileName.Flags = WinAPI.OFN_EXPLORER | WinAPI.OFN_FILEMUSTEXIST | WinAPI.OFN_PATHMUSTEXIST | WinAPI.OFN_ALLOWMULTISELECT| WinAPI.OFN_NOCHANGEDIR; 26 if(WinAPI.GetOpenFileName(openFileName)) 27 { 28 var file = Marshal.PtrToStringAuto(openFileName.filePtr); 29 while(!string.IsNullOrEmpty(file)) 30 { 31 list.Add(file); 32 //转换为地址 33 long filePointer = (long)openFileName.filePtr; 34 //偏移 35 filePointer += file.Length * Marshal.SystemDefaultCharSize + Marshal.SystemDefaultCharSize; 36 openFileName.filePtr = (IntPtr)filePointer; 37 file = Marshal.PtrToStringAuto(openFileName.filePtr); 38 } 39 } 40 41 //第一条字符串为文件夹路径,需要再拼成完整的文件路径 42 if (list.Count > 1) 43 { 44 for (int i = 1; i < list.Count; i++) 45 { 46 list[i] = System.IO.Path.Combine(list[0], list[i]); 47 } 48 49 list = list.Skip(1).ToList(); 50 } 51 52 Marshal.FreeHGlobal(filePtr); 53 return list; 54 }
测试 :
1 static void Main(string[] args) 2 { 3 var files = BrowseMultiFile("全部文件\0*.*\0\0"); 4 foreach (var item in files) 5 { 6 Console.WriteLine(item); 7 } 8 }