类似资源管理器,listview如何快速显示文件列表

chenyw2006 2009-08-12 09:18:43
在VS2005中用treeview和listview是实现了类似windows资源管理器的效果,但是在打开对象非常多的时候几乎是卡死了,比如点击treeview中的system32文件夹的时候,listview去显示该文件夹下的内容时几乎是刷不出来的,有哪位大侠有解决过类似问题的不吝赐教。
本人在显示文件的同时还显示了文件的一些属性,比如大小、修改日期、文件类型等,估计是做这些给耗费了一些性能,但是感觉必需的,要不只光光显示个文件名看起来很不舒服。所以哪位大虾做过类似的不妨提供些性能改善的思路,最好能像windows资源管理器那样就在秒级的时间里刷出类似system32几千的文件数。
还有小弟想知道资源管理是如何做到当前文件夹下新增或删除某个文件时可以实时更新文件列表的,而不是手动去更新。
希望大家能给个解决方案,解决了的本人视情况追加分,谢谢!
...全文
634 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
chenyw2006 2009-08-12
  • 打赏
  • 举报
回复
今晚再顶一下,刚才查了,是因为listview显示文件图标的问题,但是不显图标看起来太单调了,就比如:
文件名 大小 修改日期 属性
1.txt 2345 2009-08-12 只读
2.rar 12345 2009-08-11
3.exe 1253 2009-08-12
....
现在粘贴显示图标的代码,不知是否有可改进之处,望大虾指出,谢谢
 class GetSystemIcon
{
/// <summary>
/// 依据文件名读取图标,若指定文件不存在,则返回空值。
/// </summary>
/// <param name="fileName"></param>
/// <returns></returns>
public static Icon GetIconByFileName(string fileName)
{
if (fileName == null || fileName.Equals(string.Empty)) return null;
if (!File.Exists(fileName)) return null;

SHFILEINFO shinfo = new SHFILEINFO();
//Use this to get the small Icon
Win32.SHGetFileInfo(fileName, 0, ref shinfo, (uint)Marshal.SizeOf(shinfo), Win32.SHGFI_ICON | Win32.SHGFI_LARGEICON);
//The icon is returned in the hIcon member of the shinfo struct
System.Drawing.Icon myIcon = System.Drawing.Icon.FromHandle(shinfo.hIcon);
return myIcon;
}

/// <summary>
/// 给出文件扩展名(.*),返回相应图标
/// 若不以"."开头则返回文件夹的图标。
/// </summary>
/// <param name="fileType"></param>
/// <param name="isLarge"></param>
/// <returns></returns>
public static Icon GetIconByFileType(string fileType, bool isLarge)
{
if (fileType == null || fileType.Equals(string.Empty)) return null;

RegistryKey regVersion = null;
string regFileType = null;
string regIconString = null;
string systemDirectory = Environment.SystemDirectory + "\\";

if (fileType[0] == '.')
{
//读系统注册表中文件类型信息
regVersion = Registry.ClassesRoot.OpenSubKey(fileType, true);
if (regVersion != null)
{
regFileType = regVersion.GetValue("") as string;
regVersion.Close();
regVersion = Registry.ClassesRoot.OpenSubKey(regFileType + @"\DefaultIcon", true);
if (regVersion != null)
{
regIconString = regVersion.GetValue("") as string;
regVersion.Close();
}
}
if (regIconString == null)
{
//没有读取到文件类型注册信息,指定为未知文件类型的图标
regIconString = systemDirectory + "shell32.dll,0";
}
}
else
{
//直接指定为文件夹图标
regIconString = systemDirectory + "shell32.dll,3";
}
string[] fileIcon = regIconString.Split(new char[] { ',' });
if (fileIcon.Length != 2)
{
//系统注册表中注册的标图不能直接提取,则返回可执行文件的通用图标
fileIcon = new string[] { systemDirectory + "shell32.dll", "2" };
}
Icon resultIcon = null;
try
{
//调用API方法读取图标
int[] phiconLarge = new int[1];
int[] phiconSmall = new int[1];
uint count = Win32.ExtractIconEx(fileIcon[0], Int32.Parse(fileIcon[1]), phiconLarge, phiconSmall, 1);
IntPtr IconHnd = new IntPtr(isLarge ? phiconLarge[0] : phiconSmall[0]);
resultIcon = Icon.FromHandle(IconHnd);
}
catch { }
return resultIcon;
}
}

[StructLayout(LayoutKind.Sequential)]
public struct SHFILEINFO
{
public IntPtr hIcon;
public IntPtr iIcon;
public uint dwAttributes;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
public string szDisplayName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)]
public string szTypeName;
};

/// <summary>
/// 定义调用的API方法
/// </summary>
class Win32
{
public const uint SHGFI_ICON = 0x100;
public const uint SHGFI_LARGEICON = 0x0; // 'Large icon
public const uint SHGFI_SMALLICON = 0x1; // 'Small icon

[DllImport("shell32.dll")]
public static extern IntPtr SHGetFileInfo(string pszPath, uint dwFileAttributes, ref SHFILEINFO psfi, uint cbSizeFileInfo, uint uFlags);
[DllImport("shell32.dll")]
public static extern uint ExtractIconEx(string lpszFile, int nIconIndex, int[] phiconLarge, int[] phiconSmall, uint nIcons);

}
q512362091 2009-08-12
  • 打赏
  • 举报
回复
收藏了 同样的问题
chenyw2006 2009-08-12
  • 打赏
  • 举报
回复
谢谢!
显示文件的时候写的函数
public void selectcom(TreeNode tn, DirectoryInfo dire)
{
DirectoryInfo[] dir = dire.GetDirectories();
FileInfo[] fil = dire.GetFiles();
foreach (DirectoryInfo d in dir)
{
TreeNode tn1 = new TreeNode();
tn1.Text = d.Name;
tn1.ImageIndex = 1;
tn.Nodes.Add(tn1);
tn1.Nodes.Add("");
ListViewItem li = new ListViewItem();
li.Text = d.Name;
li.ImageIndex = 1;
li.SubItems.Add("");
li.SubItems.Add("文件夹");
li.SubItems.Add(d.LastWriteTimeUtc.ToString());
li.SubItems.Add("");
li.Tag = d.FullName.ToString() ;
this.listView1.Items.Add(li);
}
foreach (FileInfo f in fil)
{
Icon ic = GetSystemIcon.GetIconByFileName(f.FullName); ;
imageList1.Images.Add(f.Name, ic);
ListViewItem li = new ListViewItem();
li.Text = f.Name;
li.ImageKey = f.Name;
li.SubItems.Add(f.Length.ToString());
li.SubItems.Add(f.Extension.ToString() + "文件");
li.SubItems.Add(f.LastWriteTimeUtc.ToString());
string a;
if (f.IsReadOnly == false)
{
a = "";
}
else
{
a = "只读";
}
li.SubItems.Add(a);
li.Tag = f.FullName.ToString();
this.listView1.Items.Add(li);
}
}
类GetSystemIcon是根据文件类型去访问系统shell32.dll获得相应图标,单独写成一个CS文件,应该不算是递归,是不断去循环获得这个目录下的文件和目录,这样不行是吗?
或者不用treeview和listview,用什么组件同样实现资源管理器效果也可以,只要能够显示目录树和文件列表,单击某个目录或者文件时可以获取到名字和路径即可,或者能够像flashfxp那样也可以,试过flashfxp显示文件数很多的时候也是只需秒级的时间,知道的给个参考资料。
xuyiazl 2009-08-12
  • 打赏
  • 举报
回复
但是你可以使用线程来度过这个卡的问题
xuyiazl 2009-08-12
  • 打赏
  • 举报
回复
只显示第一级,需要详细显示根据具体的目录定位。具体看你的算法怎么写的。

递归?递归肯定慢
十八道胡同 2009-08-12
  • 打赏
  • 举报
回复
帮你顶个,没做过

110,502

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧