⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 listviewex.cs

📁 c#编写的仿OUTLOOK工具条的Winform菜单
💻 CS
📖 第 1 页 / 共 2 页
字号:
using System;
using System.Windows.Forms;
using System.Diagnostics;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Drawing.Drawing2D;
using System.Resources;
using System.Drawing.Text;
using System.Reflection;
using System.Collections;
using System.ComponentModel;

using UtilityLibrary.Win32;
using UtilityLibrary.General;

namespace UtilityLibrary.WinControls
{
	#region Enumerations
	public enum SortedListViewFormatType
	{
		String,
		Numeric,
		Date,
		Custom
	}

	public enum SortedListViewSortDirection
	{
		Ascending,
		Descending
	}
	#endregion

	#region Delegates
	public delegate int ListSortEvent(ListViewItem item1, ListViewItem item2);	
	#endregion

	#region Helper Classes
	internal class HeaderIconHelper
	{
		#region Class Variables
		int headerIndex;
		int iconIndex;
		#endregion
		
		#region Constructor
		public HeaderIconHelper(int HeaderIndex, int IconIndex)
		{
			headerIndex = HeaderIndex;
			iconIndex = IconIndex;
		}
		#endregion

		#region Properties
		public int HeaderIndex
		{
			set { headerIndex = value; }
			get { return headerIndex; }
		}

		public int IconIndex
		{
			set { iconIndex = value; }
			get { return iconIndex; }
		}

		#endregion
	}

	internal class RowSorterHelper
	{
		#region Class Variables
		int columnIndex;
		SortedListViewFormatType format;
		ListSortEvent sortEvent = null;
		#endregion
		
		#region Constructors
		public RowSorterHelper(int columnIndex, SortedListViewFormatType format)
		{
			this.columnIndex = columnIndex;
			this.format = format;
		}

		public RowSorterHelper(int columnIndex, SortedListViewFormatType format, ListSortEvent sortEvent)
		{
			this.columnIndex = columnIndex;
			this.format = format;
			this.sortEvent = sortEvent;
		}

		#endregion

		#region Properties
		public int ColumnIndex
		{
			set { columnIndex = value; }
			get { return columnIndex; }
		}

		public SortedListViewFormatType Format
		{
			set { format = value; }
			get { return format; }
		}

		public ListSortEvent SortEvent
		{
			set { sortEvent = value; }
			get { return sortEvent; }
		}

		#endregion
	}

	internal class HeaderHook : System.Windows.Forms.NativeWindow
	{
		#region Class Variables
		ListViewEx listView = null;
		#endregion
		
		#region Constructors
		public HeaderHook(ListViewEx lv)
		{
			listView = lv;
		}
		#endregion

		#region Overrides
		protected override  void WndProc(ref Message m)
		{
			int message = m.Msg;
			Point mousePos = new Point(0,0);
			if ( message == (int)Msg.WM_LBUTTONDOWN || 
				message == (int)Msg.WM_LBUTTONUP) 
			{
				mousePos = WindowsAPI.GetPointFromLPARAM((int)m.LParam);
				listView.LastMousePosition = mousePos;
			}

			if ( message == (int)Msg.WM_LBUTTONDOWN && listView.Tracking == false ) 
			{
				for (int i = 0; i < listView.Columns.Count; i++ )
				{
					Rectangle rc = listView.GetHeaderItemRect(i);
					if ( rc.Contains(mousePos))
					{
						listView.PressedHeaderItem = i;
						WindowsAPI.InvalidateRect(m.HWnd, IntPtr.Zero, 0);
						break;
					}
				}
			}
			
			if ( message == (int)Msg.WM_LBUTTONUP && listView.Tracking == false )
			{
				listView.PressedHeaderItem = -1;
								
				for (int i = 0; i < listView.Columns.Count; i++ )
				{
					Rectangle rc = listView.GetHeaderItemRect(i);
					if ( rc.Contains(mousePos))
					{
						listView.LastSortedColumn = i;
						if ( listView.Sorting == SortOrder.None)
						{
							// We will set the sorting to descending
							// because the default sorting already took place
							// and default sorting is ascending
							listView.Sorting = SortOrder.Descending;
						}
						else 
						{
							if ( listView.Sorting == SortOrder.Ascending )
								listView.Sorting = SortOrder.Descending;
							else
								listView.Sorting = SortOrder.Ascending;
						}
						break;
					}
				}

				// update item
				WindowsAPI.InvalidateRect(m.HWnd, IntPtr.Zero, 0);

			}

			base.WndProc(ref m);

		}

		#endregion
	}
    
	public class CompareListItems : IComparer
	{
		#region Class Variables
		ListViewEx listView = null;
		#endregion
		
		#region Constructors
		public CompareListItems(ListViewEx lv)
		{
			listView = lv;
		}
		#endregion

		#region Methods
		public int Compare(object obj1, object obj2)
		{
			ListViewItem item1 = (ListViewItem)obj1;
			ListViewItem item2 = (ListViewItem)obj2;
			RowSorterHelper rs = listView.GetRowSorterHelper();
			string string1 = item1.Text;
			string string2 = item2.Text;
			int result = 0;
												
			if ( listView.LastSortedColumn != 0 )
			{
				// adjust the objets if we have to sort subitems
				string1 = item1.SubItems[listView.LastSortedColumn].Text;
				string2 = item2.SubItems[listView.LastSortedColumn].Text;
				Debug.Assert(obj1 != null && obj2 != null);
			}

			if ( rs != null )
			{
				if ( rs.Format == SortedListViewFormatType.String)
					result = CompareStrings(string1, string2, listView.Sorting);
				else if ( rs.Format == SortedListViewFormatType.Numeric )
					result = CompareNumbers(string1, string2, listView.Sorting);
				else if ( rs.Format == SortedListViewFormatType.Date )
					result = CompareDates(string1, string2, listView.Sorting);
				else if ( rs.Format == SortedListViewFormatType.Custom)
				{
					if ( rs.SortEvent != null )
					{
						result = rs.SortEvent((ListViewItem)obj1, (ListViewItem)obj2);
						if ( listView.Sorting == SortOrder.Descending )
							result *= -1;
					}
				}
			}
			else if ( rs == null )
			{
				// Consider column as strings
				result = CompareStrings(string1, string2, listView.Sorting);
			}
			
			return result;
		}

		#endregion

		#region Implementation
		int CompareStrings(string string1, string string2, SortOrder sortOrder)
		{
			int result = string.Compare(string1, string2);
			if ( sortOrder == SortOrder.Descending)
				result *= -1;
			return result;
		}

		int CompareNumbers(string string1, string string2, SortOrder sortOrder)
		{
			// Parse the object as if the were floating number that will take
			// care of both cases: integers and floats
			// -- exceptions will be thrown if they cannot be parsed
			float float1 = float.Parse(string1);
			float float2 = float.Parse(string2);
			int result = float1.CompareTo(float2);
			if ( sortOrder == SortOrder.Descending)
				result *= -1;
			return result;
			
		}

		int CompareDates(string string1, string string2, SortOrder sortOrder)
		{
			// Parse the object as if the were floating number that will take
			// care of both cases: integers and floats
			// -- exceptions will be thrown if they cannot be parsed
			DateTime date1 = DateTime.Parse(string1);
			DateTime date2 = DateTime.Parse(string2);
			int result = DateTime.Compare(date1, date2);
			if ( sortOrder == SortOrder.Descending)
				result *= -1;
			return result;
			
		}
		#endregion
	}

	#endregion

	/// <summary>
	/// Summary description for SortableListView.
	/// </summary>
	[ToolboxItem(false)]
	public class ListViewEx : ListView
	{
		
		#region Class Variables
		// Keeps track of the header control handle
		// so that we can distinguish between notification and
		// reflected messages
		IntPtr hHeader = IntPtr.Zero;

		// Keep track of what column was sorted last
		int lastSortedColumn = 0;
		bool setInitialSortColumn = false;

		HeaderHook headerHook = null;
		bool tracking = false;
		int pressedHeaderItem = -1;

		// To keep track if the cursor
		// hit a header divider
		Point lastMousePosition;

		// ImageList for the check boxes
		// in case user decide to use checkboxes
		ImageList checkBoxesImageList;

		// Header Icons
		ImageList headerImageList;
		ArrayList headerIconsList = new ArrayList();

		// Sorting helper 
		ArrayList rowSorterList = new ArrayList();
		
		// We only support small 16x16 icons
		const int IMAGE_WIDTH = 16;
		const int TEXT_TO_ARROW_GAP = 15;
		const int ARROW_WIDTH = 12;
		const int BUFFER_SIZE = 1024;

		int counter = 0;
		#endregion

		#region Constructors
		public ListViewEx()
		{
		
			SetStyle(ControlStyles.UserPaint, false);
				
			// Control needs to have full row select and detail
			// view enable otherwise it won't behave as intended
			FullRowSelect = true;
			View = View.Details;
			HeaderStyle = ColumnHeaderStyle.Nonclickable;
			InitializeCheckBoxesImageList();
			ListViewItemSorter = new CompareListItems(this);
		}

		private void InitializeCheckBoxesImageList()
		{
			checkBoxesImageList = new ImageList();
			checkBoxesImageList.ImageSize = new Size(16, 16);
			Assembly thisAssembly = Assembly.GetAssembly(Type.GetType("UtilityLibrary.WinControls.ListViewEx"));
			ResourceManager rm = new ResourceManager("UtilityLibrary.Resources.SortedListView", thisAssembly);
			Bitmap checkBox = (Bitmap)rm.GetObject("CheckBox");
			checkBox.MakeTransparent(Color.FromArgb(0, 128, 128));
			checkBoxesImageList.Images.AddStrip(checkBox);
		}
		#endregion

		#region Overrides
		protected override void OnHandleCreated(EventArgs e)
		{
			base.OnHandleCreated(e);
		
			// Now that the list control has been created
			// get a hold of the header control so that we can
			// subclass it
			// -- Header control always has a control ID equal zero
			hHeader = WindowsAPI.GetDlgItem(Handle, 0);
			Debug.Assert(hHeader != IntPtr.Zero, "Fail to get Header Control Windows Handle...");
			headerHook = new HeaderHook(this);
			headerHook.AssignHandle(hHeader);
		}
	
		protected override  void WndProc(ref Message message)
		{
			base.WndProc(ref message);
			
			switch (message.Msg)
			{
				case (int)Msg.WM_ERASEBKGND:
					IntPtr hDC = (IntPtr)message.WParam;
					PaintBackground(hDC);
					break;
				
					// Notification messages come from the header
				case (int)Msg.WM_NOTIFY:
					NMHDR nm1 = (NMHDR) message.GetLParam(typeof(NMHDR));
				switch(nm1.code)
				{
					case (int)NotificationMessages.NM_CUSTOMDRAW:
						Debug.Write("CUSTOM DRAWING");
						Debug.WriteLine(counter++);
						NotifyHeaderCustomDraw(ref message); 
						break;
					case (int)HeaderControlNotifications.HDN_BEGINTRACKW:
						Tracking = true;
						break;
					case (int)HeaderControlNotifications.HDN_ENDTRACKW:
						Tracking = false;
						break;
					default:
						break;
				}
					break;
				
					// Reflected Messages come from the list itself
				case (int)ReflectedMessages.OCM_NOTIFY:
					NMHDR nm2 = (NMHDR) message.GetLParam(typeof(NMHDR));	
				switch (nm2.code)
				{
					case (int)NotificationMessages.NM_CUSTOMDRAW:
						NotifyListCustomDraw(ref message); 
						break;
					case (int)ListViewNotifications.LVN_GETDISPINFOW:
						Debug.WriteLine("List View GetDispInfo Notifications");
						break;
					default:
						break;
				}
					break;
					// Default 
				default:
					break;
			}
		}

		#endregion

		#region Properties
		internal int LastSortedColumn
		{
			set { lastSortedColumn = value; Invalidate(); }
			get { return lastSortedColumn; }
		}

		public int InitialSortedColumn
		{
			set 
			{ 
				if ( setInitialSortColumn == false )
				{	
					setInitialSortColumn = true;
					lastSortedColumn = value; 
				}
			}
		}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -