internal ImageListViewHitInfo HitTest(Point point) { int itemIndex = -1; //这里对X,Y坐标的减,实现目的是平移坐标 //传进来的是相对控件左上角的坐标,应平移为Padding后的内框左上角相对坐标 //但是要考虑滚动时,上面的Padding也允许显示项 //X坐标直接向右平移即可 //Y坐标在没有滚动时,直接向下平移,如果存在滚动,当滚动值小于顶部Padding时 //将Y坐标平移至项的最层端Y坐标上,即:Padding-滚动值 //相对于Padding后的内框坐标系的坐标 Point relativePoint = point; relativePoint.X -= ItemsBounds.Left; //y即平移量 //此处y坐标需要在绘制项的区域(Padding后的区域)的基础上,考虑滚动条的offset int y = ItemsArea.Top - _itemsAreaOffset; if (y < 0) { y = 0; } relativePoint.Y -= y; if (relativePoint.X > 0 && relativePoint.Y > 0) { //当前点击的行和列的索引,从0开始 int col = relativePoint.X / _itemSizeWithMargin.Width; int row = (relativePoint.Y + _itemsBoundsOffset) / _itemSizeWithMargin.Height; //判断点的是不是右边的空白,可能右边会有比较大的空白,又没大到够完整的显示一列图像 bool isNotHitRightEmptyArea = col <= _columnCount - 1; if (isNotHitRightEmptyArea) { int index = row * _columnCount + col; //判断是不是点在图像区域内,还是图像边上,四周的Margin上 Rectangle bounds = GetItemBounds(index); //判断点的坐标是不是在项的显示区域(Bounds)内,要用相对整个控件的原始坐标 //因为项的bounds是相对整个控件的 bool isHitInItem = bounds.Contains(point.X, point.Y); if (isHitInItem) { itemIndex = index; } } } //是否点击在了有效项上 bool itemHit = itemIndex >= 0 && itemIndex < _imageListView.Items.Count; ImageListViewHitInfo hitInfo = new ImageListViewHitInfo(itemIndex, itemHit); return(hitInfo); }
private void Hover(Point location) { ImageListViewHitInfo hitInfo = _layoutManager.HitTest(location); if (hitInfo.ItemHit) { HoveredItem = Items[hitInfo.ItemIndex]; } else { HoveredItem = null; } }
protected override void OnMouseDoubleClick(MouseEventArgs e) { if (ItemDoubleClick != null) { ImageListViewHitInfo hitInfo = _layoutManager.HitTest(e.Location); if (hitInfo.ItemHit) { ImageListViewItem item = Items[hitInfo.ItemIndex]; OnItemDoubleClick(item); } } base.OnMouseDoubleClick(e); }
public void MouseDown(MouseEventArgs e) { _mouseItemsAreaOffset = _itemsAreaOffset; List <ImageListViewItem> oldSelectedItems = _imageListView.GetSelectedItems(); ImageListViewHitInfo hitInfo = HitTest(e.Location); if (hitInfo.ItemHit) { ImageListViewItem item = _imageListView.Items[hitInfo.ItemIndex]; List <ImageListViewItem> allItems = _imageListView.Items.ToList(); ImageListViewItem currentFocusedItem = _imageListView.FocusedItem; if (_imageListView.LeftButton) { #region 如果不允许多选 if (_imageListView.AllowMultiSelection == false) { //如果点击的项就是当前选择的项 if (oldSelectedItems.Count > 0 && oldSelectedItems.Contains(item)) { //判断Control键是否按下,如果按下了Control键,取消当前项的选择状态 if (_imageListView.ControlKey) { item.Selected = false; } } else { //如果点击的项不是当前选择的项 //清除原选定项的选定状态 _imageListView.ClearSelect(); //设置新项为选定项 item.Selected = true; } } #endregion #region 如果允许多选 //在同时按下 Control 和 Shift 的情况下,优先考虑 Shift else { #region 如果按下 Shift //判断是否按下了 Shift ,如果按下 Shift,不考虑 Control 的状态 //也不用考虑是否点击的项是否是现有选定项之一 if (_imageListView.ShiftKey) { //如果当前存在具有输入焦点的项 if (currentFocusedItem != null && currentFocusedItem != item) { //连续选中从当前具有焦点的项至点击的项之间的所有项 //并将不在此范围内的项取消选中状态 int startIndex = Math.Min(currentFocusedItem.Index, hitInfo.ItemIndex); int endIndex = Math.Max(currentFocusedItem.Index, hitInfo.ItemIndex); foreach (var i in from c in oldSelectedItems where c.Index <startIndex || c.Index> endIndex select c) { i.Selected = false; } for (int i = startIndex; i <= endIndex; i++) { ImageListViewItem eachItem = allItems[i]; if (eachItem.Selected == false) { eachItem.Selected = true; } } } //如果当前不存在具有输入焦点的项 else { //清除原选定项的选定状态 _imageListView.ClearSelect(); item.Selected = true; } } #endregion #region 如果 Shift键没有处于按下状态 else { #region 如果点击的项 是 当前选择的项之一 if (oldSelectedItems.Count > 0 && oldSelectedItems.Contains(item)) { //判断是否按下了 Control,且没有按下 Shift if (_imageListView.ControlKey && _imageListView.ShiftKey == false) { item.Selected = false; } //判断是否什么键都没有按下 if (_imageListView.ControlKey == false && _imageListView.ShiftKey == false) { //清除原选定项的选定状态 _imageListView.ClearSelect(); item.Selected = true; } } #endregion #region 如果点击的项 不是 当前选择的项之一 else { //判断Control键是否按下,如果按下了Control键,则保持原有选择的情况把新项也设置为选中 //否则清除当前选择 if (_imageListView.ControlKey == false) { //清除原选定项的选定状态 _imageListView.ClearSelect(); } item.Selected = true; } #endregion } #endregion } #endregion } else { //如果点在未选中的项上 if (oldSelectedItems.Contains(item) == false) { _imageListView.ClearSelect(); //设置新项为选定项 item.Selected = true; } } #region 为项设置输入焦点 //设置新的输入焦点要放在后面处理,因为在使用Shift连续选择时,需要用到原具有焦点的项 if (currentFocusedItem == null || (currentFocusedItem != null && currentFocusedItem != item)) { if (currentFocusedItem != null) { currentFocusedItem.Focused = false; } item.Focused = true; } #endregion } else { _imageListView.ClearSelect(); } List <ImageListViewItem> newSelectedItems = _imageListView.GetSelectedItems(); if (oldSelectedItems.SequenceEqual(newSelectedItems) == false) { _imageListView.NeedPaint(); _imageListView.OnSelectedItemChanged(); } }