在C#中如何使用GetOpenFileName函数多选文件

在前面的文章中,https://www.cnblogs.com/zhaotianff/p/13999133.html

介绍了Windows的通用对话框,其中就包括 了打开 文件 对话框。

正常情况下,在C#中需要 浏览文件 ,直接 调用 System.Windows.Forms.OpenFileDialogMicrosoft.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         }

示例代码

life runs on code

作者: zhaotianff

转载请注明出处

原文地址:https://www.cnblogs.com/zhaotianff/p/15720189.html