HotDog's Blog

Hotdog (Robert Verpalen) about C# and vb.net

vbCity Blogs moved to:
http://cs.vbcity.com/blogs
  Home :: Syndication  :: Login

OctNovember 2009Dec
SMTWTFS
25262728293031
1234567
891011121314
15161718192021
22232425262728
293012345

Articles

Archives

Topics

CONTACT

Fun but useful linkies

General

VS 2005

Wolfenstein ET

Another 'old' bit of code that I'm still using a lot none the less. Whenever I needed drag and drop, it annoyed me that I had to use repetitive code to start it manually by tracing the mousedown etc. So what better place for repetitive code than in a reusable component. It isn't any highly fancy or complicated code, but a raincoat doesn't have to be pretty to keep you dry ;)
Anyway, when I was thinking when extending the AutoDragger today to alter the behaviour when dragging from a datagridview, that it was never posted on this blog. So here it is. (As far as I know it hasn't been outdated in the sense that .net now supports this out of the box)

Usage in Designer: drop the component on your form, select a control you wish to enable auto dragging for, locate the added 'UseAutoDrag' property on that control (under a 'Drag Drop' header) and set it to true.
(Of course the component can be used as a runtime class too.) The cursor can be set in the drag events or by setting a default drag cursor on the component.

Code CopyHideScrollFull

namespace
Subro.Controls
{
using System;
using
System.ComponentModel;
using
System.Windows.Forms;
using
System.Collections.Generic;
using
System.Drawing;
/// <summary>
///
Generic component that can start dragging for most control by handling
///
its mouse events.
///
Set the Controls property to indicate for which controls dragging should be handled
///
automatically. Catch the StartDrag event to alter the data which is to be dragged.
///
</summary>
[DefaultEvent("StartDrag")]
[ProvideProperty("UseAutoDrag",typeof(Control))]
public
class AutoDragger : Component,IExtenderProvider
{
public AutoDragger()
{
}
public AutoDragger(IContainer c)
: this()
{
c.Add(this);
}
public AutoDragger(Control ctr)
: this(ctr, null)
{
}
public
AutoDragger(Control ctr, EventHandler<AutoDragEventArgs> handler)
: this()
{
Register(ctr);
if
(handler != null)
StartDrag += handler;
}
List<Control> controls = new List<Control>();
public int Register(Control DragSource)
{
int i = controls.IndexOf(DragSource);
if
(i != -1) return i;
if
(!DesignMode)
{
DragSource.MouseDown += new MouseEventHandler(Control_MouseDown);
DragSource.MouseMove += new MouseEventHandler(Control_MouseMove);
DragSource.MouseUp += new MouseEventHandler(Control_MouseUp);
DragSource.GiveFeedback += new GiveFeedbackEventHandler(Control_GiveFeedback);
}
controls.Add(DragSource);
i = controls.Count - 1;
ControlAdded(DragSource);
OnControlsChanged();            
return
i;
}

protected virtual void ControlAdded(Control c)
{
}
public void UnRegister(Control DragSource)
{
DragSource.MouseDown -= new MouseEventHandler(Control_MouseDown);
DragSource.MouseMove -= new MouseEventHandler(Control_MouseMove);
DragSource.MouseUp -= new MouseEventHandler(Control_MouseUp);
DragSource.GiveFeedback -= new GiveFeedbackEventHandler(Control_GiveFeedback);
controls.Remove(DragSource);
ControlRemoved(DragSource);
OnControlsChanged();
}
protected virtual void ControlRemoved(Control c)
{
}
public void UnRegisterAll()
{
int c = controls.Count -1;
for
(int i  = c;i>=0 ;i--)
UnRegister(controls[i]);
}
const string Category = "DragDrop";
[DefaultValue(null)]
[Category(Category)]
public
Control[] Controls
{
get
{
return controls.ToArray();
}
set

{
suspendcontrolschanged = true;
while
(controls.Count > 0)
UnRegister(controls[0]);

if
(value != null)
foreach (Control c in value)
{
Register(c);
}
suspendcontrolschanged = false;
OnControlsChanged();
}
}
bool suspendcontrolschanged;
protected
virtual void OnControlsChanged()
{
if (!suspendcontrolschanged && ControlsChanged != null) ControlsChanged(this, EventArgs.Empty);
}
public event EventHandler ControlsChanged;
public Control this[int Index]
{
get
{
return controls[Index];
}
}
/// <summary>
///
The amount of registered controls used as a dragsource
///
</summary>
public
int DragSourceCount
{
get { return controls.Count; }
}
public event EventHandler<AutoDragEventArgs> StartDrag;
private DragDropEffects effects = DragDropEffects.All;
[DefaultValue(DragDropEffects.All)]
public
DragDropEffects Effects
{
get { return effects; }
set
{ effects = value; }
}
protected override void Dispose(bool disposing)
{
UnRegisterAll();
base
.Dispose(disposing);
}
int diffmin = 2;
[DefaultValue(2)]
[Category(Category)]
public
int DifferenceMinimum
{
get { return diffmin; }
set

{
diffmin = value;
}
}

AutoDragEventArgs curdrag;

void
Control_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
curdrag = new AutoDragEventArgs(sender as Control, e.Location, this);
}
else
curdrag = null;
}
void Control_MouseUp(object sender, MouseEventArgs e)
{
if (curdrag != null)
{
AutoDragEventArgs de = curdrag;
EndCurDrag();          
OnDragEnded(de);                    
}
}
protected virtual void OnDragEnded(AutoDragEventArgs e)
{
}
void Control_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left && curdrag != null)
{
curdrag.CheckStartDrag(e);
}
}

void Control_GiveFeedback(object sender, GiveFeedbackEventArgs e)
{
curdrag.SetFeedback(e);
}
private Cursor cursor;
[DefaultValue(null)]
public
Cursor DragCursor
{
get { return cursor; }
set

{
if (cursor == value) return;
cursor = value;
dragicon = null;
}
}
bool
ShouldSerializeDragCursor()
{
return cursor != null && dragicon == null;
}
private Icon dragicon;
[DefaultValue(null)]
public
Icon DragIcon
{
get { return dragicon; }
set

{
if (dragicon == value) return;
if
(value == null)
DragCursor = null;
else
DragCursor = new Cursor(value.Handle);
dragicon = value;
}
}
private bool alwaysshowcustomcursor;
[Description("Only applies when the DragCursor property is set. If this value is false, the cursor is only shown when drop is allowed")]
[DefaultValue(false)]
public
bool AlwaysShowCustomCuror
{
get { return alwaysshowcustomcursor; }
set
{ alwaysshowcustomcursor = value; }
}

void EndCurDrag()
{
if (curdrag != null)
curdrag.Dispose();
}
public class AutoDragEventArgs : EventArgs
{
public readonly Control Control;
public
readonly Point StartPoint;
public
readonly AutoDragger AutoDragger;
public
AutoDragEventArgs(Control Control, Point StartPoint, AutoDragger Owner)
{
this.Control = Control;
this
.StartPoint = StartPoint;
this
.AutoDragger = Owner;
}
private object dragobj;
public
object DragObject
{
get { return dragobj; }
set
{ dragobj = value; }
}            
private bool started;
public bool DragStarted
{
get { return started; }                
}

internal void CheckStartDrag(MouseEventArgs e)
{
int diff = Math.Abs(e.X - StartPoint.X)
+ Math.Abs(e.Y - StartPoint.Y);
if (diff >= AutoDragger.diffmin)
{
started = true;
Cursor = AutoDragger.DragCursor;
AutoDragger.OnStartDrag(this,e);
}
}
public void Dispose()
{
if (AutoDragger.curdrag == this)
AutoDragger.curdrag = null;
}
private
Cursor cursor;
public Cursor Cursor
{
get { return cursor; }
set

{
cursor = value;                    
}
}
internal void SetFeedback(GiveFeedbackEventArgs e)
{
if (cursor != null)
{
if (e.Effect != DragDropEffects.None || AutoDragger.alwaysshowcustomcursor)
{
e.UseDefaultCursors = false;
Cursor
.Current = cursor;
}
}
}
internal object GetDragObject()
{
Control c = Control;
if
(c is ListControl)
return (c as ListControl).SelectedValue;
if (c is TextBoxBase)
return GetDragObject(c as TextBoxBase);
if (c is Label)
return c.Text;
if (c is TreeView)
return GetDragObject(c as TreeView);
if (c is DataGridView)
return GetDragObject(c as DataGridView);
return null;
}
object GetDragObject(TextBoxBase tb)
{
if (!tb.ReadOnly)
{
//when in edit mode and selecting text, don't start dragging
//TODO: make optional    

return
null;
}
if
(tb.SelectionLength == 0)
return tb.Text;
return tb.SelectedText;
}
object GetDragObject(TreeView t)
{
TreeNode node = t.GetNodeAt(StartPoint);
if
(node == null) return null;
t.SelectedNode = node;
return
node;
}
object GetDragObject(DataGridView dg)
{
DataGridView.HitTestInfo ht = dg.HitTest(StartPoint.X, StartPoint.Y);
if
(ht.RowIndex == -1) return null;
if
(ht.ColumnIndex > -1 && !dg.Columns[ht.ColumnIndex].ReadOnly && dg[ht.ColumnIndex, ht.RowIndex].IsInEditMode)
return null; //when on a cell in edit mode, don't start drag drop
if (ht.ColumnIndex == -1 || dg.SelectionMode == DataGridViewSelectionMode.FullRowSelect || AutoDragger.AlwaysDragFullRow)
{
DataGridViewRow row = dg.Rows[ht.RowIndex];
if
(row.DataBoundItem != null) return row.DataBoundItem;
return
row;
}
return
dg[ht.ColumnIndex, ht.RowIndex].Value;
}
}
[Browsable(false)]
public
AutoDragEventArgs LastDragInfo
{
get
{
return curdrag;
}
}
protected virtual void OnStartDrag(AutoDragEventArgs e,MouseEventArgs me)
{
if (StartDrag != null)
StartDrag(this, e);
if (e.DragObject == null)
e.DragObject = GetDragObject(e);
if (e.DragObject != null)
{
e.Control.DoDragDrop(e.DragObject, Effects);
OnDragStarted(e);
}
else

{
//dragging not allowed
curdrag = null;
}
}
protected virtual void OnDragStarted(AutoDragEventArgs e)
{
}
protected virtual object GetDragObject(AutoDragEventArgs e)
{
return e.GetDragObject();
}
   

private bool fullrow;
[DefaultValue(false)]
[Description("Only applies when dragging on a datagridview.\r\nIf this value is not set, the full row only will be dragged if the selection mode of the grid is FullRowSelect or the rowheader is dragged and the cell value otherwise.")]
public
bool AlwaysDragFullRow
{
get { return fullrow; }
set
{ fullrow = value; }
}






#region IExtenderProvider Members
bool IExtenderProvider.CanExtend(object extendee)
{
return extendee is Control;
}
[DefaultValue(false)]
[Category(Category)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] //serialized in the control property
public
bool GetUseAutoDrag(Control c)
{
if (controls.Count == 0) return false;
return
controls.Contains(c);
}
public
void SetUseAutoDrag(Control c, bool value)
{
if (GetUseAutoDrag(c) == value) return;
if
(!value)
UnRegister(c);
else
Register(c);
}
#endregion
}
}
. . .
posted on Tuesday, February 10, 2009 10:12 PM

Feedback

No comments posted yet.

Post Feedback

Title:
Name:
Url:
Comments: 
Protected by Clearscreen.SharpHIPEnter the code you see: