protected override void HandleHitTest(Graphics g, OlvListViewHitTestInfo hti, int x, int y) { if (base.Bounds.Contains(x, y)) { hti.HitTestLocation = HitTestLocation.Text; } }
protected override void HandleHitTest(Graphics g, OlvListViewHitTestInfo hti, int x, int y) { IConvertible aspect = base.Aspect as IConvertible; if (aspect != null) { int num = aspect.ToInt32(NumberFormatInfo.InvariantInfo); Point location = base.Bounds.Location; foreach (int num2 in this.keysInOrder) { if ((num & num2) == num2) { Image image = this.GetImage(this.imageMap[num2]); if (image != null) { Rectangle rectangle = new Rectangle(location, image.Size); if (rectangle.Contains(x, y)) { hti.UserData = num2; break; } location.X += image.Width + base.Spacing; } } } } }
/// <summary> /// Do the hit test /// </summary> /// <param name="g"></param> /// <param name="hti"></param> /// <param name="x"></param> /// <param name="y"></param> protected override void HandleHitTest(Graphics g, OlvListViewHitTestInfo hti, int x, int y) { Branch br = this.Branch; Rectangle r = this.ApplyCellPadding(this.Bounds); if (br.CanExpand) { r.Offset((br.Level - 1) * PIXELS_PER_LEVEL, 0); r.Width = PIXELS_PER_LEVEL; if (r.Contains(x, y)) { hti.HitTestLocation = HitTestLocation.ExpandButton; return; } } r = this.Bounds; int indent = br.Level * PIXELS_PER_LEVEL; r.X += indent; r.Width -= indent; // Ignore events in the indent zone if (x < r.Left) { hti.HitTestLocation = HitTestLocation.Nothing; } else { this.StandardHitTest(g, hti, r, x, y); } }
protected override void HandleHitTest(Graphics g, OlvListViewHitTestInfo hti, int x, int y) { if (this.CalculateCheckBoxBounds(g, base.Bounds).Contains(x, y)) { hti.HitTestLocation = HitTestLocation.CheckBox; } }
protected override void HandleHitTest(Graphics g, OlvListViewHitTestInfo hti, int x, int y) { BrightIdeasSoftware.TreeListView.Branch branch = this.Branch; Rectangle bounds = base.Bounds; if (branch.CanExpand) { bounds.Offset((branch.Level - 1) * PIXELS_PER_LEVEL, 0); bounds.Width = PIXELS_PER_LEVEL; if (bounds.Contains(x, y)) { hti.HitTestLocation = HitTestLocation.ExpandButton; return; } } bounds = base.Bounds; int num = branch.Level * PIXELS_PER_LEVEL; bounds.X += num; bounds.Width -= num; if (x < bounds.Left) { hti.HitTestLocation = HitTestLocation.Nothing; } else { base.StandardHitTest(g, hti, bounds, x, y); } }
protected virtual void CalculateDropTarget(OlvDropEventArgs args, Point pt) { BrightIdeasSoftware.DropTargetLocation none = BrightIdeasSoftware.DropTargetLocation.None; int index = -1; int num2 = 0; if (this.CanDropOnBackground) { none = BrightIdeasSoftware.DropTargetLocation.Background; } OlvListViewHitTestInfo info = this.ListView.OlvHitTest(pt.X, pt.Y); if ((info.Item != null) && this.CanDropOnItem) { none = BrightIdeasSoftware.DropTargetLocation.Item; index = info.Item.Index; if ((info.SubItem != null) && this.CanDropOnSubItem) { num2 = info.Item.SubItems.IndexOf(info.SubItem); } } if (this.CanDropBetween && (this.ListView.GetItemCount() > 0)) { if (none == BrightIdeasSoftware.DropTargetLocation.Item) { if ((pt.Y - 3) <= info.Item.Bounds.Top) { none = BrightIdeasSoftware.DropTargetLocation.AboveItem; } if ((pt.Y + 3) >= info.Item.Bounds.Bottom) { none = BrightIdeasSoftware.DropTargetLocation.BelowItem; } } else { info = this.ListView.OlvHitTest(pt.X, pt.Y + 3); if (info.Item != null) { index = info.Item.Index; none = BrightIdeasSoftware.DropTargetLocation.AboveItem; } else { info = this.ListView.OlvHitTest(pt.X, pt.Y - 3); if (info.Item != null) { index = info.Item.Index; none = BrightIdeasSoftware.DropTargetLocation.BelowItem; } } } } args.DropTargetLocation = none; args.DropTargetIndex = index; args.DropTargetSubItemIndex = num2; }
protected override bool ProcessLButtonDown(OlvListViewHitTestInfo hti) { if (hti.HitTestLocation == HitTestLocation.ExpandButton) { this.PossibleFinishCellEditing(); this.ToggleExpansion(hti.RowObject); return(true); } return(base.ProcessLButtonDown(hti)); }
private void objList_RowNumberDblClick(BrightIdeasSoftware.OlvListViewHitTestInfo hti) { KWListDetailMD obj = (KWListDetailMD)hti.RowObject; frmKeyWordListMD frmKw = new frmKeyWordListMD(BOIDEnum.KeyWordList); frmKw.MdiParent = this.MdiParent; FormExchangeParams param = new FormExchangeParams(); param.Mode = NanCrm.FormMode.Ok; param.ReturnProc = KWLMDRetProc; param.Data = (KWListDetailMD)hti.RowObject; frmKw.SetFormExchangeParams(param); //frmKw.SetBOTable(((KWListDetailMD)hti.RowObject).GetOrignalMD()); frmKw.Show(); }
protected void StandardHitTest(Graphics g, OlvListViewHitTestInfo hti, Rectangle bounds, int x, int y) { Rectangle rectangle = bounds; int num = this.CalculateCheckBoxWidth(g); Rectangle rectangle2 = rectangle; rectangle2.Width = num; if (rectangle2.Contains(x, y)) { hti.HitTestLocation = HitTestLocation.CheckBox; } else { rectangle.X += num; rectangle.Width -= num; num = this.CalculateImageWidth(g, this.GetImageSelector()); rectangle2 = rectangle; rectangle2.Width = num; if (rectangle2.Contains(x, y)) { if ((this.Column.Index > 0) && this.Column.CheckBoxes) { hti.HitTestLocation = HitTestLocation.CheckBox; } else { hti.HitTestLocation = HitTestLocation.Image; } } else { rectangle.X += num; rectangle.Width -= num; num = this.CalculateTextWidth(g, this.GetText()); rectangle2 = rectangle; rectangle2.Width = num; if (rectangle2.Contains(x, y)) { hti.HitTestLocation = HitTestLocation.Text; } else { hti.HitTestLocation = HitTestLocation.InCell; } } } }
public override void HitTest(OlvListViewHitTestInfo hti, int x, int y) { this.ClearState(); this.ListView = hti.ListView; this.ListItem = hti.Item; this.SubItem = hti.SubItem; this.Column = hti.Column; this.RowObject = hti.RowObject; this.IsItemSelected = this.ListItem.Selected; if (this.SubItem == null) { this.Bounds = this.ListItem.Bounds; } else { this.Bounds = this.ListItem.GetSubItemBounds(this.Column.Index); } this.HandleHitTest(this.ListView.CreateGraphics(), hti, x, y); }
/// <summary> /// Do the actual work of hit testing. Subclasses should override this rather than HitTest() /// </summary> /// <param name="g"></param> /// <param name="hti"></param> /// <param name="x"></param> /// <param name="y"></param> protected virtual void HandleHitTest(Graphics g, OlvListViewHitTestInfo hti, int x, int y) { Rectangle r = this.CalculateAlignedRectangle(g, ApplyCellPadding(this.Bounds)); this.StandardHitTest(g, hti, r, x, y); }
/// <summary> /// Calculate which part of this cell was hit /// </summary> /// <param name="hti"></param> /// <param name="x"></param> /// <param name="y"></param> public override void HitTest(OlvListViewHitTestInfo hti, int x, int y) { this.ClearState(); this.ListView = hti.ListView; this.ListItem = hti.Item; this.SubItem = hti.SubItem; this.Column = hti.Column; this.RowObject = hti.RowObject; this.IsItemSelected = this.ListItem.Selected && this.ListItem.Enabled; if (this.SubItem == null) this.Bounds = this.ListItem.Bounds; else this.Bounds = this.ListItem.GetSubItemBounds(this.Column.Index); using (Graphics g = this.ListView.CreateGraphics()) { this.HandleHitTest(g, hti, x, y); } }
/// <summary> /// Perform normal hit testing relative to the given bounds /// </summary> /// <param name="g"></param> /// <param name="hti"></param> /// <param name="bounds"></param> /// <param name="x"></param> /// <param name="y"></param> protected void StandardHitTest(Graphics g, OlvListViewHitTestInfo hti, Rectangle bounds, int x, int y) { Rectangle r = bounds; // Match tweaking from renderer if (this.ColumnIsPrimary && !(this is TreeListView.TreeRenderer)) { r.X += 3; r.Width -= 1; } r = ApplyCellPadding(r); int width = 0; // Did they hit a check box on the primary column? if (this.ColumnIsPrimary && this.ListView.CheckBoxes) { Rectangle r2 = this.CalculateCheckBoxBounds(g, r); Rectangle r3 = r2; r3.Inflate(2, 2); // slightly larger hit area //g.DrawRectangle(Pens.DarkGreen, r3); if (r3.Contains(x, y)) { hti.HitTestLocation = HitTestLocation.CheckBox; return; } width = r3.Width; } // Did they hit the image? If they hit the image of a // non-primary column that has a checkbox, it counts as a // checkbox hit r.X += width; r.Width -= width; width = this.CalculateImageWidth(g, this.GetImageSelector()); Rectangle rTwo = r; rTwo.Width = width; //g.DrawRectangle(Pens.Red, rTwo); if (rTwo.Contains(x, y)) { if (this.Column != null && (this.Column.Index > 0 && this.Column.CheckBoxes)) hti.HitTestLocation = HitTestLocation.CheckBox; else hti.HitTestLocation = HitTestLocation.Image; return; } // Did they hit the text? r.X += width; r.Width -= width; width = this.CalculateTextWidth(g, this.GetText()); rTwo = r; rTwo.Width = width; //g.DrawRectangle(Pens.Blue, rTwo); if (rTwo.Contains(x, y)) { hti.HitTestLocation = HitTestLocation.Text; return; } hti.HitTestLocation = HitTestLocation.InCell; }
/// <summary> /// Calculate which part of this cell was hit /// </summary> /// <param name="hti"></param> /// <param name="x"></param> /// <param name="y"></param> public override void HitTest(OlvListViewHitTestInfo hti, int x, int y) { this.ClearState(); this.ListView = hti.ListView; this.ListItem = hti.Item; this.SubItem = hti.SubItem; this.Column = hti.Column; this.RowObject = hti.RowObject; this.IsItemSelected = this.ListItem.Selected; if (this.SubItem == null) this.Bounds = this.ListItem.Bounds; else this.Bounds = this.ListView.CalculateCellBounds(this.ListItem, this.Column.Index); this.HandleHitTest(this.ListView.CreateGraphics(), hti, x, y); }
/// <summary> /// Do the actual work of hit testing. Subclasses should override this rather than HitTest() /// </summary> /// <param name="g"></param> /// <param name="hti"></param> /// <param name="x"></param> /// <param name="y"></param> protected override void HandleHitTest(Graphics g, OlvListViewHitTestInfo hti, int x, int y) { IConvertible convertable = this.Aspect as IConvertible; if (convertable == null) return; Int32 v2 = convertable.ToInt32(NumberFormatInfo.InvariantInfo); Point pt = this.Bounds.Location; foreach (Int32 key in this.keysInOrder) { if ((v2 & key) == key) { Image image = this.GetImage(this.imageMap[key]); if (image != null) { Rectangle imageRect = new Rectangle(pt, image.Size); if (imageRect.Contains(x, y)) { hti.UserData = key; return; } pt.X += (image.Width + this.Spacing); } } } }
/// <summary> /// Handle the HitTest request /// </summary> /// <param name="g"></param> /// <param name="hti"></param> /// <param name="x"></param> /// <param name="y"></param> protected override void HandleHitTest(Graphics g, OlvListViewHitTestInfo hti, int x, int y) { Rectangle r = this.CalculateCheckBoxBounds(g, this.Bounds); if (r.Contains(x, y)) hti.HitTestLocation = HitTestLocation.CheckBox; }
protected override bool ProcessLButtonDoubleClick(OlvListViewHitTestInfo hti) { if (hti.HitTestLocation == HitTestLocation.CheckBox) { return true; } if (hti.Column == null || !hti.Column.IsRowNumberColumn || hti.Item == null || hti.Item.Index < 0) { return true; } if (RowNumberDblClick != null) { RowNumberDblClick(hti); } return true; }
protected override void HandleHitTest(Graphics g, OlvListViewHitTestInfo hti, int x, int y) { Rectangle r = CalculateAlignedRectangle(g, Bounds); // Did they hit a check box? int width = CalculateCheckBoxWidth(g); Rectangle r2 = r; r2.Width = width; if (r2.Contains(x, y)) { hti.HitTestLocation = HitTestLocation.CheckBox; return; } // Did they hit the image? If they hit the image of a // non-primary column that has a checkbox, it counts as a // checkbox hit r.X += width; r.Width -= width; width = CalculateImageWidth(g, GetImageSelector()); r2 = r; r2.Width = width; Image img = GetImageSelector() as Image; // fix for vertical hitting (w/o the entire vertical column surrounding the image) if (null != img) { r2.Y += (r.Height - img.Height)/2; r2.Height = img.Height; } // end fix if (r2.Contains(x, y)) { if (Column.Index > 0 && Column.CheckBoxes) hti.HitTestLocation = HitTestLocation.CheckBox; else hti.HitTestLocation = HitTestLocation.Image; return; } // Did they hit the text? r.X += width; r.Width -= width; width = CalculateTextWidth(g, GetText()); r2 = r; r2.Width = width; if (r2.Contains(x, y)) { hti.HitTestLocation = HitTestLocation.Text; return; } hti.HitTestLocation = HitTestLocation.InCell; }
public OLVContextMenuClickArgs(OlvListViewHitTestInfo hitInfo) { HitInfo = hitInfo; }
public virtual void HitTest(OlvListViewHitTestInfo hti, int x, int y) { }
/// <summary> /// Perform normal hit testing relative to the given bounds /// </summary> /// <param name="g"></param> /// <param name="hti"></param> /// <param name="bounds"></param> /// <param name="x"></param> /// <param name="y"></param> protected void StandardHitTest(Graphics g, OlvListViewHitTestInfo hti, Rectangle bounds, int x, int y) { Rectangle r = bounds; r = ApplyCellPadding(r); // Did they hit a check box? Rectangle r2 = this.CalculateCheckBoxBounds(g, r); Rectangle r3 = r2; r3.Inflate(2, 2); // slightly larger hit area if (r3.Contains(x, y)) { hti.HitTestLocation = HitTestLocation.CheckBox; return; } int width = r2.Width; // Did they hit the image? If they hit the image of a // non-primary column that has a checkbox, it counts as a // checkbox hit r.X += width; r.Width -= width; width = this.CalculateImageWidth(g, this.GetImageSelector()); r2 = r; r2.Width = width; if (r2.Contains(x, y)) { if (this.Column != null && (this.Column.Index > 0 && this.Column.CheckBoxes)) hti.HitTestLocation = HitTestLocation.CheckBox; else hti.HitTestLocation = HitTestLocation.Image; return; } // Did they hit the text? r.X += width; r.Width -= width; width = this.CalculateTextWidth(g, this.GetText()); r2 = r; r2.Width = width; if (r2.Contains(x, y)) { hti.HitTestLocation = HitTestLocation.Text; return; } hti.HitTestLocation = HitTestLocation.InCell; }
/// <summary> /// Handle a left mouse down at the given hit test location /// </summary> /// <remarks>Subclasses can override this to do something unique</remarks> /// <param name="hti"></param> /// <returns>True if the message has been handled</returns> protected virtual bool ProcessRButtonDown(OlvListViewHitTestInfo hti) { m_lastHitInfo = hti; if (hti.Item == null) return false; // Ignore clicks on checkboxes return (hti.HitTestLocation == HitTestLocation.CheckBox); }
/// <summary> /// Perform normal hit testing relative to the given aligned content bounds /// </summary> /// <param name="g"></param> /// <param name="hti"></param> /// <param name="bounds"></param> /// <param name="x"></param> /// <param name="y"></param> protected virtual void StandardHitTest(Graphics g, OlvListViewHitTestInfo hti, Rectangle alignedContentRectangle, int x, int y) { Rectangle r = alignedContentRectangle; // Match tweaking from renderer if (this.ColumnIsPrimary && this.CellHorizontalAlignment == HorizontalAlignment.Left && !(this is TreeListView.TreeRenderer)) { r.X += 3; r.Width -= 1; } int width = 0; // Did they hit a check box on the primary column? if (this.ColumnIsPrimary && this.ListView.CheckBoxes) { Size checkBoxSize = this.CalculateCheckBoxSize(g); int checkBoxTop = this.AlignVertically(r, checkBoxSize.Height); Rectangle r3 = new Rectangle(r.X, checkBoxTop, checkBoxSize.Width, checkBoxSize.Height); width = r3.Width + 6; // g.DrawRectangle(Pens.DarkGreen, r3); if (r3.Contains(x, y)) { hti.HitTestLocation = HitTestLocation.CheckBox; return; } } // Did they hit the image? If they hit the image of a // non-primary column that has a checkbox, it counts as a // checkbox hit r.X += width; r.Width -= width; width = this.CalculateImageWidth(g, this.GetImageSelector()); Rectangle rTwo = r; rTwo.Width = width; // g.DrawRectangle(Pens.Red, rTwo); if (rTwo.Contains(x, y)) { if (this.Column != null && (this.Column.Index > 0 && this.Column.CheckBoxes)) hti.HitTestLocation = HitTestLocation.CheckBox; else hti.HitTestLocation = HitTestLocation.Image; return; } // Did they hit the text? r.X += width; r.Width -= width; width = this.CalculateTextWidth(g, this.GetText(), r.Width); rTwo = r; rTwo.Width = width; // g.DrawRectangle(Pens.Blue, rTwo); if (rTwo.Contains(x, y)) { hti.HitTestLocation = HitTestLocation.Text; return; } hti.HitTestLocation = HitTestLocation.InCell; }
/// <summary> /// Perform a hit test when the control is owner drawn. This hands off responsibility /// to the renderer. /// </summary> /// <param name="hti"></param> /// <param name="x"></param> /// <param name="y"></param> protected virtual void CalculateOwnerDrawnHitTest(OlvListViewHitTestInfo hti, int x, int y) { // If the click wasn't on an item, give up if (hti.Item == null) return; // If the list is showing column, but they clicked outside the columns, also give up if (this.View == View.Details && hti.Column == null) return; // Which renderer was responsible for drawing that point IRenderer renderer = null; if (this.View == View.Details) { renderer = hti.Column.Renderer ?? this.DefaultRenderer; } else { renderer = this.ItemRenderer; } // We can't decide who was responsible. Give up if (renderer == null) return; // Ask the responsible renderer what is at that point renderer.HitTest(hti, x, y); }
/// <summary> /// What is under the given point? /// </summary> /// <param name="hti"></param> /// <param name="x">x co-ordinate</param> /// <param name="y">y co-ordinate</param> /// <remarks>This method should only alter HitTestLocation and/or UserData.</remarks> public virtual void HitTest(OlvListViewHitTestInfo hti, int x, int y) { }
/// <summary> /// Handle a left mouse down at the given hit test location /// </summary> /// <remarks>Subclasses can override this to do something unique</remarks> /// <param name="hti"></param> /// <returns>True if the message has been handled</returns> protected virtual bool ProcessLButtonDown(OlvListViewHitTestInfo hti) { if (hti.Item == null) return false; // If they didn't click checkbox, we can just return if (this.View != View.Details || hti.HitTestLocation != HitTestLocation.CheckBox) return false; // Did they click a sub item checkbox? if (hti.Column.Index > 0) { if (hti.Column.IsEditable) this.ToggleSubItemCheckBox(hti.RowObject, hti.Column); return true; } // They must have clicked the primary checkbox this.ToggleCheckObject(hti.RowObject); // If they change the checkbox of a selecte row, all the rows in the selection // should be given the same state if (hti.Item.Selected) { CheckState? state = this.GetCheckState(hti.RowObject); if (state.HasValue) { foreach (Object x in this.SelectedObjects) this.SetObjectCheckedness(x, state.Value); } } return true; }
/// <summary> /// What part of the control is under the given point? /// </summary> /// <param name="g"></param> /// <param name="hti"></param> /// <param name="bounds"></param> /// <param name="x"></param> /// <param name="y"></param> protected override void StandardHitTest(Graphics g, OlvListViewHitTestInfo hti, Rectangle bounds, int x, int y) { Rectangle r = ApplyCellPadding(bounds); if (r.Contains(x, y)) hti.HitTestLocation = HitTestLocation.Button; }
/// <summary> /// Handle a left mouse down at the given hit test location /// </summary> /// <remarks>Subclasses can override this to do something unique</remarks> /// <param name="hti"></param> /// <returns>True if the message has been handled</returns> protected virtual bool ProcessRButtonDown(OlvListViewHitTestInfo hti) { if (hti.Item == null) return false; // Ignore clicks on checkboxes return (this.View == View.Details && hti.HitTestLocation == HitTestLocation.CheckBox); }
/// <summary> /// Perform a hit test using the Windows control's SUBITEMHITTEST message. /// This provides information about group hits that the standard ListView.HitTest() does not. /// </summary> /// <param name="x"></param> /// <param name="y"></param> /// <returns></returns> protected OlvListViewHitTestInfo LowLevelHitTest(int x, int y) { // If it's not even in the control, don't bother with anything else if (!this.ClientRectangle.Contains(x, y)) return new OlvListViewHitTestInfo(null, null, 0, null); //if (Control.ModifierKeys == Keys.Control) // System.Diagnostics.Debugger.Break(); // Call the native hit test method, which is a little confusing. NativeMethods.LVHITTESTINFO lParam = new NativeMethods.LVHITTESTINFO(); lParam.pt_x = x; lParam.pt_y = y; int index = NativeMethods.HitTest(this, ref lParam); // Setup the various values we need to make our hit test structure bool isGroupHit = (lParam.flags & (int)HitTestLocationEx.LVHT_EX_GROUP) != 0; OLVListItem hitItem = isGroupHit || index == -1 ? null : this.GetItem(index); OLVListSubItem subItem = (this.View == View.Details && hitItem != null) ? hitItem.GetSubItem(lParam.iSubItem) : null; // Figure out which group is involved in the hit test. This is a little complicated: // If the list is virtual: // - the returned value is list view item index // - iGroup is the *index* of the hit group. // If the list is not virtual: // - iGroup is always -1. // - if the point is over a group, the returned value is the *id* of the hit group. // - if the point is not over a group, the returned value is list view item index. OLVGroup group = null; if (this.ShowGroups && this.OLVGroups != null) { if (this.VirtualMode) { group = lParam.iGroup >= 0 && lParam.iGroup < this.OLVGroups.Count ? this.OLVGroups[lParam.iGroup] : null; } else { if (isGroupHit) { foreach (OLVGroup olvGroup in this.OLVGroups) { if (olvGroup.GroupId == index) { group = olvGroup; break; } } } } } OlvListViewHitTestInfo olvListViewHitTest = new OlvListViewHitTestInfo(hitItem, subItem, lParam.flags, group); // System.Diagnostics.Debug.WriteLine(String.Format("HitTest({0}, {1})=>{2}", x, y, olvListViewHitTest)); return olvListViewHitTest; }
protected virtual void HandleHitTest(Graphics g, OlvListViewHitTestInfo hti, int x, int y) { Rectangle bounds = this.CalculateAlignedRectangle(g, this.Bounds); this.StandardHitTest(g, hti, bounds, x, y); }
protected override void HandleHitTest(Graphics g, OlvListViewHitTestInfo hti, int x, int y) { if (Bounds.Contains(x, y)) hti.HitTestLocation = HitTestLocation.Text; }
/// <summary> /// When the mouse is at the given point, what should the target of the drop be? /// </summary> /// <remarks>This method should update the DropTarget* members of the given arg block</remarks> /// <param name="pt">The mouse point, in client co-ordinates</param> protected virtual void CalculateDropTarget(OlvDropEventArgs args, Point pt) { const int SMALL_VALUE = 3; DropTargetLocation location = DropTargetLocation.None; int targetIndex = -1; int targetSubIndex = 0; if (this.CanDropOnBackground) { location = DropTargetLocation.Background; } // Which item is the mouse over? // If it is not over any item, it's over the background. //ListViewHitTestInfo info = this.ListView.HitTest(pt.X, pt.Y); OlvListViewHitTestInfo info = this.ListView.OlvHitTest(pt.X, pt.Y); if (info.Item != null && this.CanDropOnItem) { location = DropTargetLocation.Item; targetIndex = info.Item.Index; if (info.SubItem != null && this.CanDropOnSubItem) { targetSubIndex = info.Item.SubItems.IndexOf(info.SubItem); } } // Check to see if the mouse is "between" rows. // ("between" is somewhat loosely defined) if (this.CanDropBetween && this.ListView.GetItemCount() > 0) { // If the mouse is over an item, check to see if it is near the top or bottom if (location == DropTargetLocation.Item) { if (pt.Y - SMALL_VALUE <= info.Item.Bounds.Top) { location = DropTargetLocation.AboveItem; } if (pt.Y + SMALL_VALUE >= info.Item.Bounds.Bottom) { location = DropTargetLocation.BelowItem; } } else { // Is there an item a little below the mouse? // If so, we say the drop point is above that row info = this.ListView.OlvHitTest(pt.X, pt.Y + SMALL_VALUE); if (info.Item != null) { targetIndex = info.Item.Index; location = DropTargetLocation.AboveItem; } else { // Is there an item a little above the mouse? info = this.ListView.OlvHitTest(pt.X, pt.Y - SMALL_VALUE); if (info.Item != null) { targetIndex = info.Item.Index; location = DropTargetLocation.BelowItem; } } } } args.DropTargetLocation = location; args.DropTargetIndex = targetIndex; args.DropTargetSubItemIndex = targetSubIndex; }
/// <summary> /// What is under the given point? This takes the various parts of a cell into accout, including /// any custom parts that a custom renderer might use /// </summary> /// <param name="x"></param> /// <param name="y"></param> /// <returns>An information block about what is under the point</returns> public virtual OlvListViewHitTestInfo OlvHitTest(int x, int y) { ListViewHitTestInfo hitTestInfo = this.HitTest(x, y); OlvListViewHitTestInfo hti = new OlvListViewHitTestInfo(hitTestInfo); // There is a bug/"feature" of the ListView concerning hit testing. // If FullRowSelect is false and the point is over cell 0 but not on // the text or icon, HitTest will not register a hit. We could turn // FullRowSelect on, do the HitTest, and then turn it off again, but // toggling FullRowSelect in that way messes up the tooltip in the // underlying control. So we have to find another way. // // It's too hard to try to write the hit test from scratch. Grouping (for // example) makes it just too complicated. So, we have to use HitTest // but try to get around its limits. // // First step is to determine if the point was within column 0. // If it was, then we only have to determine if there is an actual row // under the point. If there is, then we know that the point is over cell 0. // So we try a Battleship-style approach: is there a subcell to the right // of cell 0? This will return a false negative if column 0 is the rightmost column, // so we also check for a subcell to the left. But if only column 0 is visible, // then that will fail too, so we check for something at the very left of the // control. // // This will still fail under pathological conditions. If column 0 fills // the whole listview and no part of the text column 0 is visible // (because it is horizontally scrolled offscreen), then the hit test will fail. // Are we in the buggy context? Details view, not full row select, and // failing to find anything if (hitTestInfo.Item == null && !this.FullRowSelect && this.View == View.Details) { // Is the point within the column 0? If it is, maybe it should have been a hit. // Let's test slightly to the right and then to left of column 0. Hopefully one // of those will hit a subitem Point sides = NativeMethods.GetScrolledColumnSides(this, 0); if (x >= sides.X && x <= sides.Y) { // We look for: // - any subitem to the right of cell 0? // - any subitem to the left of cell 0? // - cell 0 at the left edge of the screen hitTestInfo = this.HitTest(sides.Y + 4, y); if (hitTestInfo.Item == null) hitTestInfo = this.HitTest(sides.X - 4, y); if (hitTestInfo.Item == null) hitTestInfo = this.HitTest(4, y); if (hitTestInfo.Item != null) { // We hit something! So, the original point must have been in cell 0 hti.Item = (OLVListItem)hitTestInfo.Item; hti.SubItem = hti.Item.GetSubItem(0); hti.Location = ListViewHitTestLocations.None; hti.HitTestLocation = HitTestLocation.InCell; } } } if (this.OwnerDraw) this.CalculateOwnerDrawnHitTest(hti, x, y); else this.CalculateStandardHitTest(hti, x, y); return hti; }
/// <summary> /// Do the hit test /// </summary> /// <param name="g"></param> /// <param name="hti"></param> /// <param name="x"></param> /// <param name="y"></param> protected override void HandleHitTest(Graphics g, OlvListViewHitTestInfo hti, int x, int y) { Branch br = this.Branch; Rectangle r = this.Bounds; if (br.CanExpand) { r.Offset((br.Level - 1) * PIXELS_PER_LEVEL, 0); r.Width = PIXELS_PER_LEVEL; if (r.Contains(x, y)) { hti.HitTestLocation = HitTestLocation.ExpandButton; return; } } r = this.Bounds; int indent = br.Level * PIXELS_PER_LEVEL; r.X += indent; r.Width -= indent; // Ignore events in the indent zone if (x < r.Left) { hti.HitTestLocation = HitTestLocation.Nothing; } else { this.StandardHitTest(g, hti, r, x, y); } }
/// <summary> /// Perform a hit test when the control is not owner drawn /// </summary> /// <param name="hti"></param> /// <param name="x"></param> /// <param name="y"></param> protected virtual void CalculateStandardHitTest(OlvListViewHitTestInfo hti, int x, int y) { // Standard hit test works fine for the primary column if (this.View != View.Details || hti.ColumnIndex == 0 || hti.SubItem == null || hti.Column == null) return; Rectangle cellBounds = hti.SubItem.Bounds; bool hasImage = (this.GetActualImageIndex(hti.SubItem.ImageSelector) != -1); // Unless we say otherwise, it was an general incell hit hti.HitTestLocation = HitTestLocation.InCell; // Check if the point is over where an image should be. // If there is a checkbox or image there, tag it and exit. Rectangle r = cellBounds; r.Width = this.SmallImageSize.Width; if (r.Contains(x, y)) { if (hti.Column.CheckBoxes) { hti.HitTestLocation = HitTestLocation.CheckBox; return; } if (hasImage) { hti.HitTestLocation = HitTestLocation.Image; return; } } // Figure out where the text actually is and if the point is in it // The standard HitTest assumes that any point inside a subitem is // a hit on Text -- which is clearly not true. Rectangle textBounds = cellBounds; textBounds.X += 4; if (hasImage) textBounds.X += this.SmallImageSize.Width; Size proposedSize = new Size(textBounds.Width, textBounds.Height); Size textSize = TextRenderer.MeasureText(hti.SubItem.Text, this.Font, proposedSize, TextFormatFlags.EndEllipsis | TextFormatFlags.SingleLine | TextFormatFlags.NoPrefix); textBounds.Width = textSize.Width; switch (hti.Column.TextAlign) { case HorizontalAlignment.Center: textBounds.X += (cellBounds.Right - cellBounds.Left - textSize.Width) / 2; break; case HorizontalAlignment.Right: textBounds.X = cellBounds.Right - textSize.Width; break; } if (textBounds.Contains(x, y)) { hti.HitTestLocation = HitTestLocation.Text; } }
/// <summary> /// Calculate which part of this cell was hit /// </summary> /// <param name="hti"></param> /// <param name="x"></param> /// <param name="y"></param> public override void HitTest(OlvListViewHitTestInfo hti, int x, int y) { ClearState(); ListView = hti.ListView; ListItem = hti.Item; SubItem = hti.SubItem; Column = hti.Column; RowObject = hti.RowObject; IsItemSelected = ListItem.Selected; if (SubItem == null) Bounds = ListItem.Bounds; else Bounds = ListItem.GetSubItemBounds(Column.Index); //this.Bounds = this.ListView.CalculateCellBounds(this.ListItem, this.Column.Index); using (Graphics g = ListView.CreateGraphics()) { HandleHitTest(g, hti, x, y); } }
/// <summary> /// Handle a right mouse double click at the given hit test location /// </summary> /// <remarks>Subclasses can override this to do something unique</remarks> /// <param name="hti"></param> /// <returns>True if the message has been handled</returns> protected virtual bool ProcessRButtonDoubleClick(OlvListViewHitTestInfo hti) { // If the user double clicked on a checkbox, ignore it return (hti.HitTestLocation == HitTestLocation.CheckBox); }
/// <summary> /// Do the actual work of hit testing. Subclasses should override this rather than HitTest() /// </summary> /// <param name="g"></param> /// <param name="hti"></param> /// <param name="x"></param> /// <param name="y"></param> protected virtual void HandleHitTest(Graphics g, OlvListViewHitTestInfo hti, int x, int y) { Rectangle r = CalculateAlignedRectangle(g, Bounds); StandardHitTest(g, hti, r, x, y); }
/// <summary> /// The mouse has moved to the given pt. See if the hot item needs to be updated /// </summary> /// <param name="hti"></param> /// <remarks>This is the main entry point for hot item handling</remarks> protected virtual void UpdateHotItem(OlvListViewHitTestInfo hti) { if (!this.UseHotItem && !this.UseHyperlinks) return; int newHotRow = hti.RowIndex; int newHotColumn = hti.ColumnIndex; HitTestLocation newHotCellHitLocation = hti.HitTestLocation; // In non-details view, we treat any hit on a row as if it were a hit // on column 0 -- which (effectively) it is! if (newHotRow >= 0 && this.View != View.Details) newHotColumn = 0; if (this.HotRowIndex == newHotRow && this.HotColumnIndex == newHotColumn && this.HotCellHitLocation == newHotCellHitLocation) return; // Trigger the hotitem changed event HotItemChangedEventArgs args = new HotItemChangedEventArgs(); args.HotCellHitLocation = newHotCellHitLocation; args.HotColumnIndex = newHotColumn; args.HotRowIndex = newHotRow; args.OldHotCellHitLocation = this.HotCellHitLocation; args.OldHotColumnIndex = this.HotColumnIndex; args.OldHotRowIndex = this.HotRowIndex; this.OnHotItemChanged(args); // Update the state of the control this.HotRowIndex = newHotRow; this.HotColumnIndex = newHotColumn; this.HotCellHitLocation = newHotCellHitLocation; // If the event handler handled it complete, don't do anything else if (args.Handled) return; this.BeginUpdate(); try { this.Invalidate(); if (args.OldHotRowIndex != -1) this.UnapplyHotItem(args.OldHotRowIndex); if (this.HotRowIndex != -1) { // Virtual lists apply hot item style when fetching their rows if (this.VirtualMode) this.RedrawItems(this.HotRowIndex, this.HotRowIndex, true); else this.UpdateHotRow(this.HotRowIndex, this.HotColumnIndex, this.HotCellHitLocation, hti.Item); } if (this.UseHotItem && this.HotItemStyle != null && this.HotItemStyle.Overlay != null) { this.RefreshOverlays(); } } finally { this.EndUpdate(); } }
/// <summary> /// Perform normal hit testing relative to the given bounds /// </summary> /// <param name="g"></param> /// <param name="hti"></param> /// <param name="bounds"></param> /// <param name="x"></param> /// <param name="y"></param> protected void StandardHitTest(Graphics g, OlvListViewHitTestInfo hti, Rectangle bounds, int x, int y) { Rectangle r = bounds; // Did they hit a check box? int width = CalculateCheckBoxWidth(g); Rectangle r2 = r; r2.Width = width; if (r2.Contains(x, y)) { hti.HitTestLocation = HitTestLocation.CheckBox; return; } // Did they hit the image? If they hit the image of a // non-primary column that has a checkbox, it counts as a // checkbox hit r.X += width; r.Width -= width; width = CalculateImageWidth(g, GetImageSelector()); r2 = r; r2.Width = width; if (r2.Contains(x, y)) { if (Column.Index > 0 && Column.CheckBoxes) hti.HitTestLocation = HitTestLocation.CheckBox; else hti.HitTestLocation = HitTestLocation.Image; return; } // Did they hit the text? r.X += width; r.Width -= width; width = CalculateTextWidth(g, GetText()); r2 = r; r2.Width = width; if (r2.Contains(x, y)) { hti.HitTestLocation = HitTestLocation.Text; return; } hti.HitTestLocation = HitTestLocation.InCell; }