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

📄 treelistview.cs

📁 树形列表控件
💻 CS
📖 第 1 页 / 共 5 页
字号:
			#region InEdit
			private bool _inedit;
			/// <summary>
			/// Gets whether an item is currently edited
			/// </summary>
			[Browsable(false)]
			public bool InEdit
			{
				get
				{
					return _inedit;
				}
			}
			#endregion
			#region ItemsCount
			/// <summary>
			/// Get the number of items recursively
			/// </summary>
			[Browsable(false)]
			public int ItemsCount
			{
				get
				{
					TreeListViewItem[] items = _items.ToArray();
					int count = items.Length;
					foreach(TreeListViewItem item in items) count += item.ChildrenCount;
					return count;
				}
			}
			#endregion
			#region Comparer
			/// <summary>
			/// Get or set the comparer
			/// </summary>
			[Browsable(false)]
			public ITreeListViewItemComparer Comparer
			{
				get{return(Items.Comparer);}
				set{Items.Comparer = value;}
			}
			#endregion
			#region ShowPlusMinus
			private bool _showplusminus = true;
			/// <summary>
			/// Gets or sets a value indicating whether plus-sign (+) and minus-sign (-) buttons are displayed next to TreeListView that contain child TreeListViews
			/// </summary>
			[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible), DefaultValue(true)]
			[Browsable(true), Description("Gets or sets a value indicating whether plus-sign (+) and minus-sign (-) buttons are displayed next to TreeListView that contain child TreeListViews")]
			public bool ShowPlusMinus
			{
				get
				{
					return _showplusminus;
				}
				set
				{
					if(_showplusminus == value) return;
					_showplusminus = value;
					if(Created) Invoke(new MethodInvoker(VisChanged));
				}
			}
			#endregion
			#region PlusMinusLineColor
			private Color _plusMinusLineColor = Color.DarkGray;
			/// <summary>
			/// Gets or Sets the color of the lines if ShowPlusMinus property is enabled
			/// </summary>
			[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible), DefaultValue(typeof(Color), "DarkGray")]
			[Browsable(true), Description("Gets or Sets the color of the lines if ShowPlusMinus property is enabled")]
			public Color PlusMinusLineColor
			{
				get
				{
					return _plusMinusLineColor;
				}
				set
				{
					_plusMinusLineColor = value;
					if(Created) Invalidate();
				}
			}
			#endregion
			#region UseXPHighlightStyle
			private bool _useXPHighLightStyle = true;
			/// <summary>
			/// Gets or Sets whether the control draw XP-Style highlight color
			/// </summary>
			[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible), DefaultValue(true)]
			[Browsable(true), Description("Gets or Sets whether the control draw XP-Style highlight color")]
			public bool UseXPHighlightStyle
			{
				get
				{
					return _useXPHighLightStyle;
				}
				set
				{
					_useXPHighLightStyle = value;
					if(Created) Invalidate();
				}
			}
			#endregion
			#region PathSeparator
			private string _pathSeparator = "\\";
			/// <summary>
			/// Gets or sets the delimiter string that the TreeListViewItem path uses
			/// </summary>
			[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible), DefaultValue("\\")]
			[Browsable(true), Description("Gets or sets the delimiter string that the TreeListViewItem path uses")]
			public string PathSeparator
			{
				get
				{
					return _pathSeparator;
				}
				set
				{
					_pathSeparator = value;
				}
			}
			#endregion
		#endregion

		#region Constructor
		/// <summary>
		/// Create a new instance of a TreeListView
		/// </summary>
		public TreeListView()
		{
			InitializeComponent();
			if(!IsHandleCreated) CreateHandle();
			_items = new TreeListViewItemCollection(this);
			_items.SortOrder = _sorting;
			_comctl32Version = APIsComctl32.GetMajorVersion();

			int style = APIsUser32.SendMessage(Handle, (int) APIsEnums.ListViewMessages.GETEXTENDEDLISTVIEWSTYLE, 0, 0);
			style |= (int) (APIsEnums.ListViewExtendedStyles.INFOTIP | APIsEnums.ListViewExtendedStyles.LABELTIP);
			APIsUser32.SendMessage(Handle, (int) APIsEnums.ListViewMessages.SETEXTENDEDLISTVIEWSTYLE, 0, style);
		}
		#endregion
		#region WndProc
		/// <summary>
		/// WndProc
		/// </summary>
		/// <param name="m"></param>
		protected override void WndProc(ref System.Windows.Forms.Message m)
		{
			#region View messages
			if(false)
			{
				string val;
				val = Enum.GetName(typeof(APIsEnums.ListViewMessages), (APIsEnums.ListViewMessages) m.Msg);
				if(val != "" && val != null)
					Debug.WriteLine(val);
				else
				{
					val = Enum.GetName(typeof(APIsEnums.WindowMessages), (APIsEnums.WindowMessages) m.Msg);
					if(val != "" && val != null)
					Debug.WriteLine(val);
				}
				if(val != "" && val != null)
					Debug.WriteLine(m.Msg.ToString());
				if(val == "LBUTTONDOWN")
				{
					int a= 0;
					a++;
				}
			}
			#endregion


			TreeListViewItem item = null; Rectangle rec;
			switch((APIsEnums.WindowMessages) m.Msg)
			{
				#region NOTIFY
				case APIsEnums.WindowMessages.NOTIFY:
				case (APIsEnums.WindowMessages) APIsEnums.ReflectedMessages.NOTIFY:
					APIsStructs.NMHDR nmhdr = (APIsStructs.NMHDR) m.GetLParam(typeof(APIsStructs.NMHDR));
					APIsStructs.NMHEADER nmheader =(APIsStructs.NMHEADER) m.GetLParam(typeof(APIsStructs.NMHEADER));
					switch((APIsEnums.ListViewNotifications) nmhdr.code)
					{
						#region APIsEnums.ListViewNotifications.MARQUEEBEGIN
						case APIsEnums.ListViewNotifications.MARQUEEBEGIN:
							if((MouseButtons & MouseButtons.Left) != MouseButtons.Left)
								m.Result = (IntPtr)1;
							else
								_hasMarquee = true;
							break;
						#endregion
						#region APIsEnums.ListViewNotifications.ITEMCHANGING
						case APIsEnums.ListViewNotifications.ITEMCHANGING:
							APIsStructs.NMLISTVIEW nmlistview = (APIsStructs.NMLISTVIEW) m.GetLParam(typeof(APIsStructs.NMLISTVIEW));
							if(nmlistview.iItem < 0) break;
							if((item = GetTreeListViewItemFromIndex(nmlistview.iItem)) == null) break;
							bool cancel = false;
							if(nmlistview.Select)
							{
								if(_selectionMark == null) _selectionMark = item;
								else if(!_selectionMark.Visible) _selectionMark = item;
								if(HasMarquee) item.Focused = true;
							}
							else if(nmlistview.UnSelect && HasMarquee)
							{
								if(item.NextVisibleItem != null)
									if(item.NextVisibleItem.Selected)
										item.NextVisibleItem.Focused = true;
								if(item.PrevVisibleItem != null)
									if(item.PrevVisibleItem.Selected)
										item.PrevVisibleItem.Focused = true;
							}
							#region Select after dbl click
							// Disable the selection after a double click (normaly, if the control scrolls after
							// a collapse, the new item under the cursor is automatically selected...)
							if(_dblclicktime.AddMilliseconds(500).CompareTo(DateTime.Now) > 0 &&
								(nmlistview.Select || nmlistview.Focus) &&
								FocusedItem != item)
								cancel = true;
							#endregion
							#region Wrong Level Select
							if(((APIsEnums.ListViewItemStates)nmlistview.uNewState & APIsEnums.ListViewItemStates.SELECTED) == APIsEnums.ListViewItemStates.SELECTED &&
								MultiSelect)
								if(SelectedIndices.Count > 0)
									if(GetTreeListViewItemFromIndex(nmlistview.iItem).Parent != SelectedItems[0].Parent)
										cancel = true;
							#endregion
							#region Check during selection
							// Disable check boxes check when :
							// - the Marquee selection tool is being used
							// - the Ctrl or Shift keys are down
							bool state = (nmlistview.uChanged & (uint)APIsEnums.ListViewItemFlags.STATE) == (uint)APIsEnums.ListViewItemFlags.STATE;
							bool ctrlKeyDown = (ModifierKeys & Keys.Control) == Keys.Control;
							bool shiftKeyDown = (ModifierKeys & Keys.Shift) == Keys.Shift;
							if((nmlistview.Check || nmlistview.UnCheck) &&
								(HasMarquee || ctrlKeyDown || shiftKeyDown))
							{
//									MessageBox.Show(this,
//										"uChanged = " + nmlistview->uChanged.ToString() + "\n\n" + 
//										"uOld = " + nmlistview->uOldState.ToString() + "\n" + 
//										"uNew = " + nmlistview->uChanged.ToString() + "\n\n" +
//										"OldCheck : " + (oldCheck ? "true" : "false") + "\n" + 
//										"NewCheck : " + (newCheck ? "true" : "false"));
								cancel = true;
							}
							#endregion
							if(cancel)
							{
								m.Result = (IntPtr)1;
								return;
							}
							break;
						#endregion

						#region APIsEnums.ListViewNotifications.BEGINLABELEDIT
						case APIsEnums.ListViewNotifications.BEGINLABELEDIT:
							// Cancel label edit if the message is sent just after a double click
							if(_lastdoubleclick.AddMilliseconds(450) > DateTime.Now)
							{
								Message canceledit = Message.Create(Handle, (int) APIsEnums.ListViewMessages.CANCELEDITLABEL, IntPtr.Zero, IntPtr.Zero);
								WndProc(ref canceledit);
								m.Result = (IntPtr) 1;
								return;
							}
							item = _lastitemclicked.Item;
							item.EnsureVisible();
							// Add subitems if needed
							while(item.SubItems.Count-1 < _lastitemclicked.ColumnIndex) item.SubItems.Add("");
							TreeListViewBeforeLabelEditEventArgs beforeed = new TreeListViewBeforeLabelEditEventArgs(
								FocusedItem, _lastitemclicked.ColumnIndex, item.SubItems[_lastitemclicked.ColumnIndex].Text);
							OnBeforeLabelEdit(beforeed);
							if(beforeed.Cancel)
							{
								Message canceledit = Message.Create(Handle, (int) APIsEnums.ListViewMessages.CANCELEDITLABEL, IntPtr.Zero, IntPtr.Zero);
								WndProc(ref canceledit);
								m.Result = (IntPtr) 1;
								return;
							}
							_inedit = true;
							// Get edit handle
							Message mess = Message.Create(Handle, (int)APIsEnums.ListViewMessages.GETEDITCONTROL, IntPtr.Zero, IntPtr.Zero);
							WndProc(ref mess);
							IntPtr edithandle = mess.Result;
							_customedit = new CustomEdit(edithandle, this, beforeed.Editor);
							_editeditem = new EditItemInformations(
								FocusedItem, beforeed.ColumnIndex, FocusedItem.SubItems[beforeed.ColumnIndex].Text);
							m.Result = IntPtr.Zero;
							return;
						#endregion
						#region APIsEnums.ListViewNotifications.ENDLABELEDIT
						case APIsEnums.ListViewNotifications.ENDLABELEDIT:
							if(_customedit != null)
								_customedit.HideEditControl();
							_customedit = null;
							_inedit = false;
							_editeditem = new EditItemInformations();
							m.Result = IntPtr.Zero;
							return;
						#endregion
						
						#region CUSTOMDRAW
						case (APIsEnums.ListViewNotifications) APIsEnums.NotificationMessages.CUSTOMDRAW:
							base.WndProc(ref m);
							CustomDraw(ref m);
							return;
						#endregion

						#region BEGINSCROLL
						case APIsEnums.ListViewNotifications.BEGINSCROLL:
							_updating = true;
							break;
						#endregion
						#region ENDSCROLL
						case APIsEnums.ListViewNotifications.ENDSCROLL:
							_updating = false;
							// Disable display bug with vertical lines (slow...)
//							if(ShowPlusMinus)
//							{
//								DrawPlusMinusItemsLines();
//								DrawPlusMinusItems();
//							}
							break;
						#endregion

						#region APIsEnums.HeaderControlNotifications.BEGINDRAG
						case (APIsEnums.ListViewNotifications) APIsEnums.HeaderControlNotifications.BEGINDRAG:
							nmheader =(APIsStructs.NMHEADER) m.GetLParam(typeof(APIsStructs.NMHEADER));
							if(nmheader.iItem == 0)
							{
								m.Result = (IntPtr)1;
								return;
							}
							break;
						#endregion
						#region APIsEnums.HeaderControlNotifications.ENDDRAG
						case (APIsEnums.ListViewNotifications) APIsEnums.HeaderControlNotifications.ENDDRAG:
							nmheader =(APIsStructs.NMHEADER) m.GetLParam(typeof(APIsStructs.NMHEADER));
							// Get mouse position in header coordinates
							IntPtr headerHandle = (IntPtr) APIsUser32.SendMessage(Handle, (int) APIsEnums.ListViewMessages.GETHEADER, IntPtr.Zero, IntPtr.Zero);
							APIsStructs.POINTAPI pointapi = new APIsStructs.POINTAPI(MousePosition);
							APIsUser32.ScreenToClient(headerHandle, ref pointapi);
							// HeaderItem Rect
							APIsStructs.RECT headerItemRect = new APIsStructs.RECT();
							APIsUser32.SendMessage(headerHandle, (int)APIsEnums.HeaderControlMessages.GETITEMRECT, 0, ref headerItemRect);
							int headerItemWidth = headerItemRect.right - headerItemRect.left;
							// Cancel the drag operation if the first column is moved
							// or destination is the first column
							if(pointapi.x <= headerItemRect.left + headerItemWidth / 2 ||
								nmheader.iItem == 0)
							{
								m.Result = (IntPtr)1;
								return;
							}
							break;
						#endregion
						#region APIsEnums.HeaderControlNotifications.TRACK / ENDTRACK
//						case (APIsEnums.ListViewNotifications)APIsEnums.HeaderControlNotifications.TRACK:
						case (APIsEnums.ListViewNotifications)APIsEnums.HeaderControlNotifications.ENDTRACK:
							Invalidate();
							break;
						#endregion
					}
					break;
				#endregion

				#region LBUTTONDOWN
					// Cancel the click on checkboxes if the item is not "checkable"
					case APIsEnums.WindowMessages.LBUTTONDOWN:
						if(Columns.Count == 0) break;
						// Set the clickeditem and column
						int colclicked = GetColumnAt(MousePosition);
						if(colclicked == -1) colclicked = 0;
						item = GetItemAtFullRow(PointToClient(MousePosition));
						_lastitemclicked = new EditItemInformations(item, colclicked, "");
						if(_selectionMark == null || !_selectionMark.Visible) _selectionMark = item;
						if(((APIsEnums.KeyStatesMasks)(int)m.WParam & APIsEnums.KeyStatesMasks.SHIFT) != APIsEnums.KeyStatesMasks.SHIFT &&
							!(((APIsEnums.KeyStatesMasks)(int)m.WParam & APIsEnums.KeyStatesMasks.CONTROL) == APIsEnums.KeyStatesMasks.CONTROL &&
							item.Parent != _selectionMark.Parent))
							_selectionMark = item;
						// Get where the mouse has clicked
						APIsStructs.LVHITTESTINFO lvhittest = new APIsStructs.LVHITTESTINFO();
						lvhittest.pt = new APIsStructs.POINTAPI(PointToClient(MousePosition));
						APIsUser32.SendMessage(Handle, (Int32) APIsEnums.ListViewMessages.HITTEST, 0, ref lvhittest);
						if(item == null) break;
						// Plus / Minus click
						if(item.GetBounds(TreeListViewItemBoundsPortion.PlusMinus).Contains(PointToClient(MousePosition)) &&
							ShowPlusMinus && item.Items.Count > 0 &&
							Columns[0].Width > (item.Level+1)*SystemInformation.SmallIconSize.Width)
						{
							Focus();
							if(item.IsExpanded) item.Collapse();
							else item.Expand();
							OnMouseDown(new MouseEventArgs(MouseButtons.Left, 1, PointToClient(MousePosition).X, PointToClient(MousePosition).Y, 0));
							return;
						}
						// Cancel mouse click if multiselection on a wrong item
						if(SelectedIndices.Count > 0 &&
							(((APIsEnums.KeyStatesMasks)(int)m.WParam & APIsEnums.KeyStatesMasks.SHIFT) == APIsEnums.KeyStatesMasks.SHIFT ||
							((APIsEnums.KeyStatesMasks)(int)m.WParam & APIsEnums.KeyStatesMasks.CONTROL) == APIsEnums.KeyStatesMasks.CONTROL) &&
							MultiSelect)
						{

⌨️ 快捷键说明

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