Click here to Skip to main content
15,879,535 members
Articles / Desktop Programming / Windows Forms

Desktop Search Application: Part 1

Rate me:
Please Sign up or sign in to vote.
4.89/5 (91 votes)
6 Jul 20063 min read 524.4K   9.3K   255  
Building an application that searches your Office documents in tenths of a second.
// Source: http://www.vbaccelerator.com/home/NET/Code/Libraries/Shell_Projects/SysImageList/article.asp

using System;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace DesktopSearch1.Icons
{
	#region Public Enumerations
	/// <summary>
	/// Available system image list sizes
	/// </summary>
	public enum SystemImageListSize : int
	{
		/// <summary>
		/// System Large Icon Size (typically 32x32)
		/// </summary>
		LargeIcons = 0x0,
		/// <summary>
		/// System Small Icon Size (typically 16x16)
		/// </summary>
		SmallIcons = 0x1,
		/// <summary>
		/// System Extra Large Icon Size (typically 48x48).
		/// Only available under XP; under other OS the
		/// Large Icon ImageList is returned.
		/// </summary>
		ExtraLargeIcons = 0x2
	}

	/// <summary>
	/// Flags controlling how the Image List item is 
	/// drawn
	/// </summary>
	[Flags]	
	public enum ImageListDrawItemConstants : int
	{
		/// <summary>
		/// Draw item normally.
		/// </summary>
		ILD_NORMAL = 0x0,
		/// <summary>
		/// Draw item transparently.
		/// </summary>
		ILD_TRANSPARENT = 0x1,
		/// <summary>
		/// Draw item blended with 25% of the specified foreground colour
		/// or the Highlight colour if no foreground colour specified.
		/// </summary>
		ILD_BLEND25 = 0x2,
		/// <summary>
		/// Draw item blended with 50% of the specified foreground colour
		/// or the Highlight colour if no foreground colour specified.
		/// </summary>
		ILD_SELECTED = 0x4,
		/// <summary>
		/// Draw the icon's mask
		/// </summary>
		ILD_MASK = 0x10,
		/// <summary>
		/// Draw the icon image without using the mask
		/// </summary>
		ILD_IMAGE = 0x20,
		/// <summary>
		/// Draw the icon using the ROP specified.
		/// </summary>
		ILD_ROP = 0x40,
		/// <summary>
		/// Preserves the alpha channel in dest. XP only.
		/// </summary>
		ILD_PRESERVEALPHA = 0x1000,
		/// <summary>
		/// Scale the image to cx, cy instead of clipping it.  XP only.
		/// </summary>
		ILD_SCALE = 0x2000,
		/// <summary>
		/// Scale the image to the current DPI of the display. XP only.
		/// </summary>
		ILD_DPISCALE = 0x4000
	}
	
	/// <summary>
	/// Enumeration containing XP ImageList Draw State options
	/// </summary>
	[Flags]	
	public enum ImageListDrawStateConstants : int
	{
		/// <summary>
		/// The image state is not modified. 
		/// </summary>
		ILS_NORMAL = (0x00000000),
		/// <summary>
		/// Adds a glow effect to the icon, which causes the icon to appear to glow 
		/// with a given color around the edges. (Note: does not appear to be
		/// implemented)
		/// </summary>
		ILS_GLOW = (0x00000001), //The color for the glow effect is passed to the IImageList::Draw method in the crEffect member of IMAGELISTDRAWPARAMS. 
		/// <summary>
		/// Adds a drop shadow effect to the icon. (Note: does not appear to be
		/// implemented)
		/// </summary>
		ILS_SHADOW = (0x00000002), //The color for the drop shadow effect is passed to the IImageList::Draw method in the crEffect member of IMAGELISTDRAWPARAMS. 
		/// <summary>
		/// Saturates the icon by increasing each color component 
		/// of the RGB triplet for each pixel in the icon. (Note: only ever appears
		/// to result in a completely unsaturated icon)
		/// </summary>
		ILS_SATURATE = (0x00000004), // The amount to increase is indicated by the frame member in the IMAGELISTDRAWPARAMS method. 
		/// <summary>
		/// Alpha blends the icon. Alpha blending controls the transparency 
		/// level of an icon, according to the value of its alpha channel. 
		/// (Note: does not appear to be implemented).
		/// </summary>
		ILS_ALPHA = (0x00000008) //The value of the alpha channel is indicated by the frame member in the IMAGELISTDRAWPARAMS method. The alpha channel can be from 0 to 255, with 0 being completely transparent, and 255 being completely opaque. 
	}
	
	/// <summary>
	/// Flags specifying the state of the icon to draw from the Shell
	/// </summary>
	[Flags]
	public enum ShellIconStateConstants
	{
		/// <summary>
		/// Get icon in normal state
		/// </summary>
		ShellIconStateNormal = 0,
		/// <summary>
		/// Put a link overlay on icon 
		/// </summary>
		ShellIconStateLinkOverlay = 0x8000,        
		/// <summary>
		/// show icon in selected state 
		/// </summary>
		ShellIconStateSelected = 0x10000,
		/// <summary>
		/// get open icon 
		/// </summary>
		ShellIconStateOpen = 0x2,              
		/// <summary>
		/// apply the appropriate overlays
		/// </summary>
		ShellIconAddOverlays = 0x000000020,
	}
	#endregion

	#region SystemImageList class
	/// <summary>
	/// Summary description for SysImageList.
	/// </summary>
	public class SystemImageList : IDisposable
	{
		#region Constants
		private const int MAX_PATH = 260;

		private const int FILE_ATTRIBUTE_NORMAL = 0x80;
		private const int FILE_ATTRIBUTE_DIRECTORY = 0x10;

		private const int FORMAT_MESSAGE_ALLOCATE_BUFFER = 0x100; 
		private const int FORMAT_MESSAGE_ARGUMENT_ARRAY = 0x2000;
		private const int FORMAT_MESSAGE_FROM_HMODULE = 0x800;
		private const int FORMAT_MESSAGE_FROM_STRING = 0x400;
		private const int FORMAT_MESSAGE_FROM_SYSTEM = 0x1000;
		private const int FORMAT_MESSAGE_IGNORE_INSERTS = 0x200;
		private const int FORMAT_MESSAGE_MAX_WIDTH_MASK = 0xFF;
		#endregion
		
		#region Fields
		private IntPtr hIml = IntPtr.Zero;
		private IImageList iImageList = null;
		private SystemImageListSize size = SystemImageListSize.SmallIcons;
		private bool disposed = false;
		#endregion

		#region Private Enumerations
		[Flags]		
			private enum SHGetFileInfoConstants : int
		{
			SHGFI_ICON = 0x100,                // get icon 
			SHGFI_DISPLAYNAME = 0x200,         // get display name 
			SHGFI_TYPENAME = 0x400,            // get type name 
			SHGFI_ATTRIBUTES = 0x800,          // get attributes 
			SHGFI_ICONLOCATION = 0x1000,       // get icon location 
			SHGFI_EXETYPE = 0x2000,            // return exe type 
			SHGFI_SYSICONINDEX = 0x4000,       // get system icon index 
			SHGFI_LINKOVERLAY = 0x8000,        // put a link overlay on icon 
			SHGFI_SELECTED = 0x10000,          // show icon in selected state 
			SHGFI_ATTR_SPECIFIED = 0x20000,    // get only specified attributes 
			SHGFI_LARGEICON = 0x0,             // get large icon 
			SHGFI_SMALLICON = 0x1,             // get small icon 
			SHGFI_OPENICON = 0x2,              // get open icon 
			SHGFI_SHELLICONSIZE = 0x4,         // get shell size icon 
			//SHGFI_PIDL = 0x8,                  // pszPath is a pidl 
			SHGFI_USEFILEATTRIBUTES = 0x10,    // use passed dwFileAttribute 
			SHGFI_ADDOVERLAYS = 0x000000020,   // apply the appropriate overlays
			SHGFI_OVERLAYINDEX = 0x000000040   // Get the index of the overlay
		}
		#endregion

		#region Private ImageList structures
		[StructLayout(LayoutKind.Sequential)]
			private struct RECT
		{
			int left;
			int top;
			int right;
			int bottom;
		}

		[StructLayout(LayoutKind.Sequential)]
			private struct POINT
		{
			int x;
			int y;
		}

		[StructLayout(LayoutKind.Sequential)]
			private struct IMAGELISTDRAWPARAMS				
		{
			public int cbSize;
			public IntPtr himl;
			public int i;
			public IntPtr hdcDst;
			public int x;
			public int y;
			public int cx;
			public int cy;
			public int xBitmap;        // x offest from the upperleft of bitmap
			public int yBitmap;        // y offset from the upperleft of bitmap
			public int rgbBk;
			public int rgbFg;
			public int fStyle;
			public int dwRop;
			public int fState;
			public int Frame;
			public int crEffect;
		}

		[StructLayout(LayoutKind.Sequential)]
			private struct IMAGEINFO
		{
			public IntPtr hbmImage;
			public IntPtr hbmMask;
			public int Unused1;
			public int Unused2;
			public RECT rcImage;
		}
		[StructLayout(LayoutKind.Sequential)]
			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;
		}
		#endregion

		#region Constructors, Dispose, Destructor
		/// <summary>
		/// Creates a Small Icons SystemImageList 
		/// </summary>
		public SystemImageList()
		{
			create();
		}
		/// <summary>
		/// Creates a SystemImageList with the specified size
		/// </summary>
		/// <param name="size">Size of System ImageList</param>
		public SystemImageList(SystemImageListSize size)
		{
			this.size = size;
			create();
		}

		/// <summary>
		/// Clears up any resources associated with the SystemImageList
		/// </summary>
		public void Dispose()
		{
			Dispose(true);
			GC.SuppressFinalize(this);
		}
		/// <summary>
		/// Clears up any resources associated with the SystemImageList
		/// when disposing is true.
		/// </summary>
		/// <param name="disposing">Whether the object is being disposed</param>
		public virtual void Dispose(bool disposing)
		{
			if (!disposed)
			{
				if (disposing) 
				{
					if (iImageList != null)
					{
						Marshal.ReleaseComObject(iImageList);
					}
					iImageList = null;
				}
			}
			disposed = true;
		}
		/// <summary>
		/// Finalise for SysImageList
		/// </summary>
		~SystemImageList()
		{
			Dispose(false);
		}	
		#endregion

		#region Implementation
		
		[DllImport("shell32")]
		private static extern IntPtr SHGetFileInfo (
			string pszPath, 
			int dwFileAttributes,
			ref SHFILEINFO psfi, 
			uint cbFileInfo, 
			uint uFlags);

		[DllImport("user32.dll")]
		private static extern int DestroyIcon(IntPtr hIcon);
		
		[DllImport("kernel32")]
		private extern static int FormatMessage (
			int dwFlags, 
			IntPtr lpSource, 
			int dwMessageId, 
			int dwLanguageId, 
			string lpBuffer,
			uint nSize, 
			int argumentsLong);

		[DllImport("kernel32")]
		private extern static int GetLastError();

		[DllImport("comctl32")]
		private extern static int ImageList_Draw(
			IntPtr hIml,
			int i,
			IntPtr hdcDst,
			int x,
			int y,
			int fStyle);

		[DllImport("comctl32")]
		private extern static int ImageList_DrawIndirect(
			ref IMAGELISTDRAWPARAMS pimldp);

		[DllImport("comctl32")]
		private extern static int ImageList_GetIconSize(
			IntPtr himl, 
			ref int cx, 
			ref int cy);

		[DllImport("comctl32")]
		private extern static IntPtr ImageList_GetIcon(
			IntPtr himl, 
			int i, 
			int flags);

		/// <summary>
		/// SHGetImageList is not exported correctly in XP.  See KB316931
		/// http://support.microsoft.com/default.aspx?scid=kb;EN-US;Q316931
		/// Apparently (and hopefully) ordinal 727 isn't going to change.
		/// </summary>
		[DllImport("shell32.dll", EntryPoint = "#727")]
		private extern static int SHGetImageList(
			int iImageList,
			ref Guid riid,
			ref IImageList ppv
			);

		[DllImport("shell32.dll", EntryPoint = "#727")]
		private extern static int SHGetImageListHandle(
			int iImageList,
			ref Guid riid,
			ref IntPtr handle
			);

		/// <summary>
		/// Determines if the system is running Windows XP
		/// or above
		/// </summary>
		/// <returns>True if system is running XP or above, False otherwise</returns>
		private bool isXpOrAbove()
		{
			bool ret = false;
			if (Environment.OSVersion.Version.Major > 5)
			{
				ret = true;
			}
			else if ((Environment.OSVersion.Version.Major == 5) &&
				(Environment.OSVersion.Version.Minor >= 1))
			{
				ret = true;
			}
			return ret;
			//return false;
		}

		/// <summary>
		/// Creates the SystemImageList
		/// </summary>
		private void create()
		{
			// forget last image list if any:
			hIml = IntPtr.Zero;

			if (isXpOrAbove())
			{
				// Get the System IImageList object from the Shell:
				Guid iidImageList = new Guid("46EB5926-582E-4017-9FDF-E8998DAA0950");
				int ret = SHGetImageList(
					(int)size,
					ref iidImageList,
					ref iImageList
					);
				// the image list handle is the IUnknown pointer, but 
				// using Marshal.GetIUnknownForObject doesn't return
				// the right value.  It really doesn't hurt to make
				// a second call to get the handle:
				SHGetImageListHandle((int)size, ref iidImageList, ref hIml);
			}
			else
			{
				// Prepare flags:
				SHGetFileInfoConstants dwFlags = SHGetFileInfoConstants.SHGFI_USEFILEATTRIBUTES | SHGetFileInfoConstants.SHGFI_SYSICONINDEX ;
				if (size == SystemImageListSize.SmallIcons)
				{
					dwFlags |= SHGetFileInfoConstants.SHGFI_SMALLICON;
				}
				// Get image list
				SHFILEINFO shfi = new SHFILEINFO();
				uint shfiSize = (uint)Marshal.SizeOf(shfi.GetType());

				// Call SHGetFileInfo to get the image list handle
				// using an arbitrary file:
				hIml = SHGetFileInfo(
					".txt", 
					FILE_ATTRIBUTE_NORMAL, 
					ref shfi, 
					shfiSize, 
					(uint)dwFlags);
				System.Diagnostics.Debug.Assert ((hIml != IntPtr.Zero),"Failed to create Image List");
			}
		}

		#region Private ImageList COM Interop (XP)
		[ComImportAttribute()]
			[GuidAttribute("46EB5926-582E-4017-9FDF-E8998DAA0950")]
			[InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
			//helpstring("Image List"),
			interface IImageList
		{
			[PreserveSig]
			int Add(
				IntPtr hbmImage, 
				IntPtr hbmMask, 
				ref int pi);

			[PreserveSig]
			int ReplaceIcon(
				int i, 
				IntPtr hicon, 
				ref int pi);

			[PreserveSig]
			int SetOverlayImage(
				int iImage, 
				int iOverlay);

			[PreserveSig]
			int Replace(
				int i,
				IntPtr hbmImage, 
				IntPtr hbmMask);

			[PreserveSig]
			int AddMasked(
				IntPtr hbmImage, 
				int crMask, 
				ref int pi);

			[PreserveSig]
			int Draw(
				ref IMAGELISTDRAWPARAMS pimldp);

			[PreserveSig]
			int Remove(
				int i);

			[PreserveSig]
			int GetIcon(
				int i, 
				int flags, 
				ref IntPtr picon);

			[PreserveSig]
			int GetImageInfo(
				int i, 
				ref IMAGEINFO pImageInfo);

			[PreserveSig]
			int Copy(
				int iDst, 
				IImageList punkSrc, 
				int iSrc, 
				int uFlags);

			[PreserveSig]
			int Merge(
				int i1, 
				IImageList punk2, 
				int i2, 
				int dx, 
				int dy, 
				ref Guid riid, 
				ref IntPtr ppv);

			[PreserveSig]
			int Clone(
				ref Guid riid, 
				ref IntPtr ppv);

			[PreserveSig]
			int GetImageRect(
				int i, 
				ref RECT prc);

			[PreserveSig]
			int GetIconSize(
				ref int cx, 
				ref int cy);

			[PreserveSig]
			int SetIconSize(
				int cx, 
				int cy);

			[PreserveSig]
			int GetImageCount(
				ref int pi);

			[PreserveSig]
			int SetImageCount(
				int uNewCount);

			[PreserveSig]
			int SetBkColor(
				int clrBk, 
				ref int pclr);

			[PreserveSig]
			int GetBkColor(
				ref int pclr);

			[PreserveSig]
			int BeginDrag(
				int iTrack, 
				int dxHotspot, 
				int dyHotspot);

			[PreserveSig]
			int EndDrag();

			[PreserveSig]
			int DragEnter(
				IntPtr hwndLock, 
				int x, 
				int y);

			[PreserveSig]
			int DragLeave(
				IntPtr hwndLock);

			[PreserveSig]
			int DragMove(
				int x, 
				int y);

			[PreserveSig]
			int SetDragCursorImage(
				ref IImageList punk, 
				int iDrag, 
				int dxHotspot, 
				int dyHotspot);

			[PreserveSig]
			int DragShowNolock(
				int fShow);

			[PreserveSig]
			int GetDragImage(
				ref POINT ppt, 
				ref POINT pptHotspot, 
				ref Guid riid, 
				ref IntPtr ppv);
			
			[PreserveSig]
			int GetItemFlags(
				int i, 
				ref int dwFlags);

			[PreserveSig]
			int GetOverlayImage(
				int iOverlay, 
				ref int piIndex);
		};
		#endregion
		#endregion
						
		#region Properties
		/// <summary>
		/// Gets the hImageList handle
		/// </summary>
		public IntPtr Handle
		{
			get
			{
				return this.hIml;				
			}
		}
		/// <summary>
		/// Gets/sets the size of System Image List to retrieve.
		/// </summary>
		public SystemImageListSize ImageListSize
		{
			get
			{
				return size;
			}
			set
			{
				size = value;
				create();
			}
		}

		/// <summary>
		/// Returns the size of the Image List Icons.
		/// </summary>
		public System.Drawing.Size Size
		{
			get
			{
				int cx = 0; 
				int cy = 0;
				
				if (iImageList == null)
					ImageList_GetIconSize(hIml, ref cx, ref cy);
				else
					iImageList.GetIconSize(ref cx, ref cy);

				System.Drawing.Size sz = new System.Drawing.Size(cx, cy);

				return sz;
			}		
		}
		#endregion

		#region Methods
		/// <summary>
		/// Returns a GDI+ copy of the icon from the ImageList
		/// at the specified index.
		/// </summary>
		/// <param name="index">The index to get the icon for</param>
		/// <returns>The specified icon</returns>
		public Icon Icon(int index)
		{
			Icon icon = null;

			IntPtr hIcon = IntPtr.Zero;
			if (iImageList == null)
			{
				hIcon = ImageList_GetIcon(
					hIml,
					index,
					(int)ImageListDrawItemConstants.ILD_TRANSPARENT);

			}
			else
			{
				iImageList.GetIcon(
					index,
					(int)ImageListDrawItemConstants.ILD_TRANSPARENT,
					ref hIcon);
			}

			if (hIcon != IntPtr.Zero)
			{
				icon = System.Drawing.Icon.FromHandle(hIcon);
			}				
			return icon;
		}

		/// <summary>
		/// Return the index of the icon for the specified file, always using 
		/// the cached version where possible.
		/// </summary>
		/// <param name="fileName">Filename to get icon for</param>
		/// <returns>Index of the icon</returns>
		public int IconIndex(string fileName)
		{
			return IconIndex(fileName, false);
		}

		/// <summary>
		/// Returns the index of the icon for the specified file
		/// </summary>
		/// <param name="fileName">Filename to get icon for</param>
		/// <param name="forceLoadFromDisk">If True, then hit the disk to get the icon,
		/// otherwise only hit the disk if no cached icon is available.</param>
		/// <returns>Index of the icon</returns>
		public int IconIndex(
			string fileName, 
			bool forceLoadFromDisk)
		{
			return IconIndex(
				fileName, 
				forceLoadFromDisk,
				ShellIconStateConstants.ShellIconStateNormal);
		}
		
		/// <summary>
		/// Returns the index of the icon for the specified file
		/// </summary>
		/// <param name="fileName">Filename to get icon for</param>
		/// <param name="forceLoadFromDisk">If True, then hit the disk to get the icon,
		/// otherwise only hit the disk if no cached icon is available.</param>
		/// <param name="iconState">Flags specifying the state of the icon
		/// returned.</param>
		/// <returns>Index of the icon</returns>
		public int IconIndex(
			string fileName,
			bool forceLoadFromDisk,
			ShellIconStateConstants iconState
			)
		{
			SHGetFileInfoConstants dwFlags = SHGetFileInfoConstants.SHGFI_SYSICONINDEX;
			int dwAttr = 0;
			if (size == SystemImageListSize.SmallIcons)
			{
				dwFlags |= SHGetFileInfoConstants.SHGFI_SMALLICON;
			}

			// We can choose whether to access the disk or not. If you don't
			// hit the disk, you may get the wrong icon if the icon is
			// not cached. Also only works for files.
			if (!forceLoadFromDisk)
			{
				dwFlags |= SHGetFileInfoConstants.SHGFI_USEFILEATTRIBUTES;
				dwAttr = FILE_ATTRIBUTE_NORMAL;
			}
			else
			{				
				dwAttr = 0;
			}

			// sFileSpec can be any file. You can specify a
			// file that does not exist and still get the
			// icon, for example sFileSpec = "C:\PANTS.DOC"
			SHFILEINFO shfi = new SHFILEINFO();
			uint shfiSize = (uint)Marshal.SizeOf(shfi.GetType());
			IntPtr retVal = SHGetFileInfo( 
				fileName, dwAttr, ref shfi, shfiSize, 
				((uint)(dwFlags) | (uint)iconState));

			if (retVal.Equals(IntPtr.Zero))
			{
				System.Diagnostics.Debug.Assert((!retVal.Equals(IntPtr.Zero)),"Failed to get icon index");
				return 0;
			}
			else
			{
				return shfi.iIcon;
			}
		}

		/// <summary>
		/// Draws an image
		/// </summary>
		/// <param name="hdc">Device context to draw to</param>
		/// <param name="index">Index of image to draw</param>
		/// <param name="x">X Position to draw at</param>
		/// <param name="y">Y Position to draw at</param>
		public void DrawImage( 
			IntPtr hdc,
			int index, 
			int x,
			int y
			)
		{
			DrawImage(hdc, index, x, y, ImageListDrawItemConstants.ILD_TRANSPARENT);
		}

		/// <summary>
		/// Draws an image using the specified flags
		/// </summary>
		/// <param name="hdc">Device context to draw to</param>
		/// <param name="index">Index of image to draw</param>
		/// <param name="x">X Position to draw at</param>
		/// <param name="y">Y Position to draw at</param>
		/// <param name="flags">Drawing flags</param>
		public void DrawImage(
			IntPtr hdc,
			int index,
			int x,
			int y,
			ImageListDrawItemConstants flags
			)
		{
			if (iImageList == null)
			{
				int ret = ImageList_Draw(
					hIml, 
					index, 
					hdc, 
					x, 
					y, 
					(int)flags);
			}
			else
			{
				IMAGELISTDRAWPARAMS pimldp = new IMAGELISTDRAWPARAMS();
				pimldp.hdcDst = hdc;
				pimldp.cbSize = Marshal.SizeOf(pimldp.GetType());
				pimldp.i = index;
				pimldp.x = x;
				pimldp.y = y;
				pimldp.rgbFg = -1;
				pimldp.fStyle = (int)flags;
				iImageList.Draw(ref pimldp);
			}
			
		}

		/// <summary>
		/// Draws an image using the specified flags and specifies
		/// the size to clip to (or to stretch to if ILD_SCALE
		/// is provided).
		/// </summary>
		/// <param name="hdc">Device context to draw to</param>
		/// <param name="index">Index of image to draw</param>
		/// <param name="x">X Position to draw at</param>
		/// <param name="y">Y Position to draw at</param>
		/// <param name="flags">Drawing flags</param>
		/// <param name="cx">Width to draw</param>
		/// <param name="cy">Height to draw</param>
		public void DrawImage(
			IntPtr hdc,
			int index,
			int x,
			int y,
			ImageListDrawItemConstants flags,
			int cx,
			int cy
			)
		{
			IMAGELISTDRAWPARAMS pimldp = new IMAGELISTDRAWPARAMS();
			pimldp.hdcDst = hdc;
			pimldp.cbSize = Marshal.SizeOf(pimldp.GetType());
			pimldp.i = index;
			pimldp.x = x;
			pimldp.y = y;
			pimldp.cx = cx;
			pimldp.cy = cy;
			pimldp.fStyle = (int)flags;
			if (iImageList == null)
			{
				pimldp.himl = hIml;
				int ret = ImageList_DrawIndirect(ref pimldp);
			}
			else
			{

				iImageList.Draw(ref pimldp);
			}
		}

		/// <summary>
		/// Draws an image using the specified flags and state on XP systems.
		/// </summary>
		/// <param name="hdc">Device context to draw to</param>
		/// <param name="index">Index of image to draw</param>
		/// <param name="x">X Position to draw at</param>
		/// <param name="y">Y Position to draw at</param>
		/// <param name="flags">Drawing flags</param>
		/// <param name="cx">Width to draw</param>
		/// <param name="cy">Height to draw</param>
		/// <param name="foreColor">Fore colour to blend with when using the 
		/// ILD_SELECTED or ILD_BLEND25 flags</param>
		/// <param name="stateFlags">State flags</param>
		/// <param name="glowOrShadowColor">If stateFlags include ILS_GLOW, then
		/// the colour to use for the glow effect.  Otherwise if stateFlags includes 
		/// ILS_SHADOW, then the colour to use for the shadow.</param>
		/// <param name="saturateColorOrAlpha">If stateFlags includes ILS_ALPHA,
		/// then the alpha component is applied to the icon. Otherwise if 
		/// ILS_SATURATE is included, then the (R,G,B) components are used
		/// to saturate the image.</param>
		public void DrawImage(
			IntPtr hdc,
			int index,
			int x,
			int y,
			ImageListDrawItemConstants flags,
			int cx,
			int cy,
			System.Drawing.Color foreColor,
			ImageListDrawStateConstants stateFlags,
			System.Drawing.Color saturateColorOrAlpha,
			System.Drawing.Color glowOrShadowColor
			)
		{
			IMAGELISTDRAWPARAMS pimldp = new IMAGELISTDRAWPARAMS();
			pimldp.hdcDst = hdc;
			pimldp.cbSize = Marshal.SizeOf(pimldp.GetType());
			pimldp.i = index;
			pimldp.x = x;
			pimldp.y = y;
			pimldp.cx = cx;
			pimldp.cy = cy;
			pimldp.rgbFg = Color.FromArgb(0, 
				foreColor.R, foreColor.G, foreColor.B).ToArgb();
			//			Console.WriteLine("{0}", pimldp.rgbFg);
			pimldp.fStyle = (int)flags;
			pimldp.fState = (int)stateFlags;
			if ((stateFlags & ImageListDrawStateConstants.ILS_ALPHA) ==
				ImageListDrawStateConstants.ILS_ALPHA)
			{
				// Set the alpha:
				pimldp.Frame = (int)saturateColorOrAlpha.A;
			}
			else if ((stateFlags & ImageListDrawStateConstants.ILS_SATURATE) ==
				ImageListDrawStateConstants.ILS_SATURATE)
			{
				// discard alpha channel:
				saturateColorOrAlpha = Color.FromArgb(0, 
					saturateColorOrAlpha.R, 
					saturateColorOrAlpha.G, 
					saturateColorOrAlpha.B);
				// set the saturate color
				pimldp.Frame = saturateColorOrAlpha.ToArgb();
			}
			glowOrShadowColor = Color.FromArgb(0, 
				glowOrShadowColor.R, 
				glowOrShadowColor.G, 
				glowOrShadowColor.B);
			pimldp.crEffect = glowOrShadowColor.ToArgb();
			if (iImageList == null)
			{
				pimldp.himl = hIml;
				int ret = ImageList_DrawIndirect(ref pimldp);
			}
			else
			{

				iImageList.Draw(ref pimldp);
			}
		}		
		#endregion				
	}

	#endregion

	#region SystemImageListHelper class
	/// <summary>
	/// Helper Methods for Connecting SystemImageList to Common Controls
	/// </summary>
	public class SystemImageListHelper
	{
		#region Constants
		private const int LVM_FIRST = 0x1000;
		private const int LVM_SETIMAGELIST = (LVM_FIRST + 3);

		private const int LVSIL_NORMAL = 0;
		private const int LVSIL_SMALL = 1;
		private const int LVSIL_STATE = 2;

		private const int TV_FIRST = 0x1100;
		private const int TVM_SETIMAGELIST = (TV_FIRST + 9);
		
		private const int TVSIL_NORMAL = 0;
		private const int TVSIL_STATE = 2;
		#endregion

		#region Implementation
		[DllImport("user32", CharSet = CharSet.Auto)]
		private static extern IntPtr SendMessage(
			IntPtr hWnd, 
			int wMsg, 
			IntPtr wParam, 
			IntPtr lParam);
		#endregion
		
		#region Methods
		/// <summary>
		/// Associates a SysImageList with a ListView control
		/// </summary>
		/// <param name="listView">ListView control to associate ImageList with</param>
		/// <param name="sysImageList">System Image List to associate</param>
		/// <param name="forStateImages">Whether to add ImageList as StateImageList</param>
		public static void SetListViewImageList(
			ListView listView,
			SystemImageList sysImageList,
			bool forStateImages
			)
		{
			IntPtr wParam = (IntPtr)LVSIL_NORMAL;
			if (sysImageList.ImageListSize == SystemImageListSize.SmallIcons)
			{
				wParam = (IntPtr)LVSIL_SMALL;
			}
			if (forStateImages)
			{
				wParam = (IntPtr)LVSIL_STATE;
			}
			SendMessage(
				listView.Handle,
				LVM_SETIMAGELIST,
				wParam,
				sysImageList.Handle);	
		}

		/// <summary>
		/// Associates a SysImageList with a TreeView control
		/// </summary>
		/// <param name="treeView">TreeView control to associated ImageList with</param>
		/// <param name="sysImageList">System Image List to associate</param>
		/// <param name="forStateImages">Whether to add ImageList as StateImageList</param>
		public static void SetTreeViewImageList(
			TreeView treeView,
			SystemImageList sysImageList,
			bool forStateImages
			)
		{
			IntPtr wParam = (IntPtr)TVSIL_NORMAL;
			if (forStateImages)
			{
				wParam = (IntPtr)TVSIL_STATE;
			}
			SendMessage(
				treeView.Handle,
				TVM_SETIMAGELIST,
				wParam,
				sysImageList.Handle);
		}	
	
		#endregion
	}
	#endregion
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Czech Republic Czech Republic
My open-source event calendar/scheduling web UI components:

DayPilot for JavaScript, Angular, React and Vue

Comments and Discussions