zoukankan      html  css  js  c++  java
  • 在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

    转载请注明出处

  • 相关阅读:
    python随笔:邮箱题目
    05 小程序自定义组件
    04 小程序常用组件-view text rich-text icon swiger
    03 小程序语法-WXSS样式-尺寸-样式 -选择器
    02 小程序语法-数据绑定与事件绑定
    01 小程序入门与vscode开发加装插件
    JAVA25-Git、Vue.js
    JAVA14-File类、递归、字节流、字符流、缓冲流、转换流、序列化流、Files
    JAVA13-异常、线程、同步、等待与唤醒案例、线程池、Lambda表达式
    JAVA12-Scanner类、Random类、ArrayList类、String类、static、Arrays类、Math类、静态方法
  • 原文地址:https://www.cnblogs.com/zhaotianff/p/15720189.html
Copyright © 2011-2022 走看看