【发布时间】:2016-12-03 14:21:55
【问题描述】:
我想从拖到列表视图中的多个文件中加载图标以及这些文件的一些信息,但过程非常缓慢。
在我的测试中,拖了一个包含 381 个文件的列表(有些不是 exe,所以我的代码中跳过了这些文件),需要 2 多分钟才能从文件中加载图标,并将它们添加到列表视图中。
以下是我的代码的精简版:
public Form1()
{
InitializeComponent();
listView1.DragEnter += ListView1_DragEnter;
listView1.DragDrop += ListView1_DragDrop;
listView1.LargeImageList = new ImageList() { ImageSize = new Size( 64, 64) };
listView1.SmallImageList = new ImageList();
listView1.AllowDrop = true;
}
private void ListView1_DragDrop(object sender, DragEventArgs e)
{
if(e.Data.GetDataPresent(DataFormats.FileDrop))
{
string[] values = (string[])e.Data.GetData(DataFormats.FileDrop);
Convert.IconExtractor i = new Convert.IconExtractor();
foreach (var v in values)
{
var info = new FileInfo(v);
if(info.Extension.ToLower() == ".exe")
{
ListViewItem item = new ListViewItem();
listView1.LargeImageList.Images.Add(i.Extract(info.FullName, Convert.IconSize.Large));
listView1.SmallImageList.Images.Add(i.Extract(info.FullName, Convert.IconSize.Small));
item.Text = Path.GetFileNameWithoutExtension(info.FullName);
item.ImageIndex = listView1.SmallImageList.Images.Count -1;
item.Tag = info.FullName;
listView1.Items.Add(item);
}
}
listView1.Refresh();
}
}
private void ListView1_DragEnter(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent(DataFormats.FileDrop))
{
e.Effect = DragDropEffects.All;
}
}
为了方便,这里贴上提取的方法:
public enum IconSize
{
Small,
Large
}
public class IconExtractor
{
//----------------------------------------------------------------------------
//
// Description: Extracts the icon associated with any file on your system.
// Author: WidgetMan http://softwidgets.com
//
// Remarks...
//
// Class requires the IconSize enumeration that is implemented in this
// same file. For best results, draw an icon from within a control's Paint
// event via the e.Graphics.DrawIcon method.
//
//----------------------------------------------------------------------------
private const int SHGFI_ICON = 0x100;
private const int SHGFI_SMALLICON = 0x1;
private const int SHGFI_LARGEICON = 0x0;
private struct SHFILEINFO
{
public IntPtr hIcon;
public int iIcon;
public int dwAttributes;
[VBFixedString(260), MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
public string szDisplayName;
[VBFixedString(80), MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)]
public string szTypeName;
}
[DllImport("shell32", EntryPoint = "SHGetFileInfoA", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
private static extern int SHGetFileInfo(string pszPath, int dwFileAttributes, ref SHFILEINFO psfi, int ByValcbFileInfo, int uFlags);
public IconExtractor()
{
}
public System.Drawing.Icon Extract(string File, IconSize Size)
{
SHFILEINFO aSHFileInfo = default(SHFILEINFO);
int cbFileInfo = 0;
int uflags = 0;
System.Drawing.Icon Icon = default(System.Drawing.Icon);
switch (Size)
{
case IconSize.Large:
uflags = SHGFI_ICON | SHGFI_LARGEICON;
break;
default:
uflags = SHGFI_ICON | SHGFI_SMALLICON;
break;
}
cbFileInfo = Marshal.SizeOf(aSHFileInfo);
SHGetFileInfo(File, 0, ref aSHFileInfo, cbFileInfo, uflags);
Icon = System.Drawing.Icon.FromHandle(aSHFileInfo.hIcon);
return Icon;
}
public System.Drawing.Icon Extract(string File)
{
return this.Extract(File, IconSize.Small);
}
}
}
我能做些什么来加快这个过程。这个概念是为多个应用程序制作一个快速启动器。
另外值得注意的是,当这个过程发生时,在拖放任务完全完成(循环遍历所有文件)之前,Windows 资源管理器上的拖放集合图标仍然“挂起”。
这是一个粗略的草稿,用于展示应用程序的视觉效果:
(是的,我知道提取的图标看起来也很垃圾,但我认为这是与我遇到的缓慢问题不同的问题)
【问题讨论】:
标签: c# winforms listview drag-and-drop