📄 treelistview.cs
字号:
#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 + -