www.pudn.com > ObjectListViewDemo.zip > ShellUtilities.cs
/*
* [File purpose]
* Author: Phillip Piper
* Date: 1 May 2007 7:44 PM
*
* CHANGE LOG:
* when who what
* 1 May 2007 JPP Initial Version
*/
using System;
using System.Drawing;
using System.IO;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace BrightIdeasSoftware
{
///
/// This helper class allows listviews and tree views to use image from the system image list.
///
/// Instances of this helper class know how to retrieve icon from the Windows shell for
/// a given file path. These icons are then added to the imagelist on the given control. ListViews need
/// special handling since they have two image lists which need to be kept in sync.
public class SysImageListHelper
{
private SysImageListHelper()
{
}
///
/// Create a SysImageListHelper that will fetch images for the given tree control
///
/// The tree view that will use the images
public SysImageListHelper(TreeView treeView)
{
if (treeView.ImageList == null) {
treeView.ImageList = new ImageList();
treeView.ImageList.ImageSize = new Size(16, 16);
}
this.smallImageCollection = treeView.ImageList.Images;
}
///
/// Create a SysImageListHelper that will fetch images for the given listview control.
///
/// The listview that will use the images
/// Listviews manage two image lists, but each item can only have one image index.
/// This means that the image for an item must occur at the same index in the two lists.
/// SysImageListHelper instances handle this requirement. However, if the listview already
/// has image lists installed, they must be of the same length.
public SysImageListHelper(ListView listView)
{
if (listView.SmallImageList == null) {
listView.SmallImageList = new ImageList();
listView.SmallImageList.ImageSize = new Size(16, 16);
}
if (listView.LargeImageList == null) {
listView.LargeImageList = new ImageList();
listView.LargeImageList.ImageSize = new Size(32, 32);
}
if (listView.SmallImageList.Images.Count != listView.LargeImageList.Images.Count)
throw new ArgumentException("Small and large image lists must have the same number of items.");
this.smallImageCollection = listView.SmallImageList.Images;
this.largeImageCollection = listView.LargeImageList.Images;
}
///
/// Return the index of the image that has the Shell Icon for the given file/directory.
///
/// The full path to the file/directory
/// The index of the image or -1 if something goes wrong.
public int GetImageIndex(string path)
{
if (System.IO.Directory.Exists(path))
path = System.Environment.SystemDirectory; // optimization! give all directories the same image
else
if (System.IO.Path.HasExtension(path))
path = System.IO.Path.GetExtension(path);
if (this.smallImageCollection.ContainsKey(path))
return this.smallImageCollection.IndexOfKey(path);
try {
this.smallImageCollection.Add(path, ShellUtilities.GetFileIcon(path, true, true));
if (this.largeImageCollection != null)
this.largeImageCollection.Add(path, ShellUtilities.GetFileIcon(path, false, true));
} catch (ArgumentNullException) {
return -1;
}
return this.smallImageCollection.IndexOfKey(path);
}
private ImageList.ImageCollection smallImageCollection = null;
private ImageList.ImageCollection largeImageCollection = null;
}
///
/// ShellUtilities contains routines to interact with the Windows Shell.
///
public static class ShellUtilities
{
///
/// Execute the default verb on the file or directory identified by the given path.
/// For documents, this will open them with their normal application. For executables,
/// this will cause them to run.
///
/// The file or directory to be executed
/// Values < 31 indicate some sort of error. See ShellExecute() documentation for specifics.
/// The same effect can be achieved by System.Diagnostics.Process.Start(path).
public static int Execute(string path)
{
return ShellUtilities.Execute(path, "");
}
///
/// Execute the given operation on the file or directory identified by the given path.
/// Example operations are "edit", "print", "explore".
///
/// The file or directory to be operated on
/// Values < 31 indicate some sort of error. See ShellExecute() documentation for specifics.
public static int Execute(string path, string operation)
{
IntPtr result = ShellUtilities.ShellExecute(0, operation, path, "", "", SW_SHOWNORMAL);
return result.ToInt32();
}
///
/// Get the string that describes the file's type.
///
/// The file or directory whose type is to be fetched
/// A string describing the type of the file, or an empty string if something goes wrong.
public static String GetFileType(string path)
{
SHFILEINFO shfi = new SHFILEINFO();
int flags = SHGFI_TYPENAME;
IntPtr result = ShellUtilities.SHGetFileInfo(path, 0, out shfi, Marshal.SizeOf(shfi), flags);
if (result.ToInt32() == 0)
return String.Empty;
else
return shfi.szTypeName;
}
///
/// Return the icon for the given file/directory.
///
/// The full path to the file whose icon is to be returned
/// True if the small (16x16) icon is required, otherwise the 32x32 icon will be returned
/// The icon of the given file, or null if something goes wrong
public static Icon GetFileIcon(string path, bool isSmallImage, bool useFileType)
{
int flags = SHGFI_ICON;
if (isSmallImage)
flags |= SHGFI_SMALLICON;
int fileAttributes = 0;
if (useFileType) {
flags |= SHGFI_USEFILEATTRIBUTES;
if (System.IO.Directory.Exists(path))
fileAttributes = FILE_ATTRIBUTE_DIRECTORY;
else
fileAttributes = FILE_ATTRIBUTE_NORMAL;
}
SHFILEINFO shfi = new SHFILEINFO();
IntPtr result = ShellUtilities.SHGetFileInfo(path, fileAttributes, out shfi, Marshal.SizeOf(shfi), flags);
if (result.ToInt32() == 0)
return null;
else
return Icon.FromHandle(shfi.hIcon);
}
///
/// Return the index into the system image list of the image that represents the given file.
///
/// The full path to the file or directory whose icon is required
/// The index of the icon, or -1 if something goes wrong
/// This is only useful if you are using the system image lists directly. Since there is
/// no way to do that in .NET, it isn't a very useful.
public static int GetSysImageIndex(string path)
{
SHFILEINFO shfi = new SHFILEINFO();
int flags = SHGFI_ICON | SHGFI_SYSICONINDEX;
IntPtr result = ShellUtilities.SHGetFileInfo(path, 0, out shfi, Marshal.SizeOf(shfi), flags);
if (result.ToInt32() == 0)
return -1;
else
return shfi.iIcon;
}
#region Native methods
private const int SHGFI_ICON = 0x00100; // get icon
private const int SHGFI_DISPLAYNAME = 0x00200; // get display name
private const int SHGFI_TYPENAME = 0x00400; // get type name
private const int SHGFI_ATTRIBUTES = 0x00800; // get attributes
private const int SHGFI_ICONLOCATION = 0x01000; // get icon location
private const int SHGFI_EXETYPE = 0x02000; // return exe type
private const int SHGFI_SYSICONINDEX = 0x04000; // get system icon index
private const int SHGFI_LINKOVERLAY = 0x08000; // put a link overlay on icon
private const int SHGFI_SELECTED = 0x10000; // show icon in selected state
private const int SHGFI_ATTR_SPECIFIED = 0x20000; // get only specified attributes
private const int SHGFI_LARGEICON = 0x00000; // get large icon
private const int SHGFI_SMALLICON = 0x00001; // get small icon
private const int SHGFI_OPENICON = 0x00002; // get open icon
private const int SHGFI_SHELLICONSIZE = 0x00004; // get shell size icon
private const int SHGFI_PIDL = 0x00008; // pszPath is a pidl
private const int SHGFI_USEFILEATTRIBUTES = 0x00010; // use passed dwFileAttribute
//if (_WIN32_IE >= 0x0500)
private const int SHGFI_ADDOVERLAYS = 0x00020; // apply the appropriate overlays
private const int SHGFI_OVERLAYINDEX = 0x00040; // Get the index of the overlay
private const int FILE_ATTRIBUTE_NORMAL = 0x00080; // Normal file
private const int FILE_ATTRIBUTE_DIRECTORY = 0x00010; // Directory
private const int MAX_PATH = 260;
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
private struct SHFILEINFO
{
public IntPtr hIcon;
public int iIcon;
public int dwAttributes;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=MAX_PATH)]
public string szDisplayName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst=80)]
public string szTypeName;
}
private const int SW_SHOWNORMAL = 1;
[DllImport("shell32.dll", CharSet = CharSet.Auto)]
private static extern IntPtr ShellExecute(int hwnd, string lpOperation, string lpFile,
string lpParameters, string lpDirectory, int nShowCmd);
[DllImport("shell32.dll", CharSet = CharSet.Auto)]
private static extern IntPtr SHGetFileInfo(string pszPath, int dwFileAttributes,
out SHFILEINFO psfi, int cbFileInfo, int uFlags);
#endregion
}
}