/// <summary>
/// 拖拽帮助类
/// </summary>
public static class DragHelper
{
/// <summary>
/// BandedGridView 拖拽
/// </summary>
/// <param name="gvMain"></param>
public static void DragGridRow<T>( this BandedGridView gvMain)
{
// 拖拽遮罩控件
DragMaster dragMaster = new DragMaster();
// 当前拖拽行绘画区域
Rectangle _DragRowRect = Rectangle.Empty;
GridControl gcMain = gvMain.GridControl;
GridHitInfo _DownHitInfo = null ;
//表格属性 允许拖拽
gcMain.AllowDrop = true ;
gvMain.OptionsDetail.EnableMasterViewMode = false ;
#region 将对象拖至边界时发生 DragOver
gcMain.DragOver += delegate ( object sender, System.Windows.Forms.DragEventArgs e)
{
if (e.Data.GetDataPresent( typeof (T)))
e.Effect = DragDropEffects.Move;
else
e.Effect = DragDropEffects.None;
};
#endregion
#region 拖拽完成时处理数据 DragDrop
gcMain.DragDrop += delegate ( object sender, System.Windows.Forms.DragEventArgs e)
{
// 拖过来的新数据
T newRow = (T)e.Data.GetData( typeof (T));
// 原来在此坐标的数据
// e的坐标是相对于屏幕的
var clientPoint = gcMain.PointToClient( new Point(e.X, e.Y));
GridHitInfo hitInfo = gvMain.CalcHitInfo( new Point(clientPoint.X, clientPoint.Y));
var oldRow = (T)gvMain.GetRow(hitInfo.RowHandle);
// 如果相等则不处理
if (oldRow == null || newRow == null ) return ;
// 且目标位置不是最后一行的话要将所有序号重排
// 原来的行号
var oldIndex = _DownHitInfo.RowHandle;
// 新的行号
var newIndex = hitInfo.RowHandle;
BindingSource bs = (BindingSource)(gcMain.DataSource);
if (bs == null )
return ;
bs.RemoveAt(oldIndex);
bs.Insert(oldIndex, oldRow);
bs.RemoveAt(newIndex);
bs.Insert(newIndex, newRow);
bs.ResetBindings( false );
};
#endregion
#region 鼠标按下 MouseDown
gcMain.MouseDown += delegate ( object sender, MouseEventArgs e)
{
_DownHitInfo = null ;
GridHitInfo hitInfo = gvMain.CalcHitInfo( new Point(e.X, e.Y));
if (Control.ModifierKeys != Keys.None) return ;
if (e.Button == MouseButtons.Left && hitInfo.RowHandle >= 0)
{
// 禁用的Grid不支持拖拽
if (!gvMain.OptionsBehavior.Editable
|| gvMain.OptionsBehavior.ReadOnly)
return ;
// 只有点击最前面才能拖拽
if (hitInfo.InRowCell)
return ;
// 缓存
_DownHitInfo = hitInfo;
}
};
#endregion
#region 鼠标移动 MouseMove
gcMain.MouseMove += delegate ( object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
if (_DownHitInfo != null )
{
Size dragSize = SystemInformation.DragSize;
// 偏离区域
Rectangle dragRect = new Rectangle( new Point(_DownHitInfo.HitPoint.X - dragSize.Width / 2, _DownHitInfo.HitPoint.Y - dragSize.Height / 2), dragSize);
if (!dragRect.Contains( new Point(e.X, e.Y)))
{
// 屏幕坐标
var p = gcMain.PointToScreen(e.Location);
// 刷新是必须要的
gcMain.Refresh();
// 获取当前行截图
var bmp = GetDragRowImage(gcMain, _DownHitInfo, _DragRowRect);
Point offSetPoint = new Point(p.X + 1, p.Y - dragMaster.DragSize.Height / 2);
// 开始显示拖拽遮罩
dragMaster.StartDrag(bmp, offSetPoint, DragDropEffects.Move);
// 获取要拖拽的数据
object row = gvMain.GetRow(_DownHitInfo.RowHandle);
// 开始拖拽
gcMain.DoDragDrop(row, DragDropEffects.Move);
// 取消事件
DevExpress.Utils.DXMouseEventArgs.GetMouseArgs(e).Handled = true ;
// 清空缓存
_DownHitInfo = null ;
}
}
}
};
#endregion
#region 在用鼠标拖动某项时发生,是否允许继续拖放 QueryContinueDrag
gcMain.QueryContinueDrag += delegate ( object sender, QueryContinueDragEventArgs e)
{
switch (e.Action)
{
case DragAction.Continue:
// 移动遮罩
Point offSetPoint = new Point(Cursor.Position.X + 1, Cursor.Position.Y - dragMaster.DragSize.Height / 2);
dragMaster.DoDrag(offSetPoint, DragDropEffects.Move, false );
break ;
default :
// 清空
_DragRowRect = Rectangle.Empty;
// 停止拖动
dragMaster.EndDrag();
break ;
}
};
#endregion
#region 点击行头移动行
gvMain.CustomDrawRowIndicator += delegate ( object sender, RowIndicatorCustomDrawEventArgs e)
{
if (_DragRowRect == Rectangle.Empty && _DownHitInfo != null && _DownHitInfo.RowHandle == e.RowHandle)
{
_DragRowRect = e.Bounds;
}
};
#endregion
}
/// <summary>
/// GridView 拖拽
/// </summary>
/// <param name="gvMain"></param>
public static void DragGridRow<T>( this GridView gvMain)
{
// 拖拽遮罩控件
DragMaster dragMaster = new DragMaster();
// 当前拖拽行绘画区域
Rectangle _DragRowRect = Rectangle.Empty;
GridControl gcMain = gvMain.GridControl;
GridHitInfo _DownHitInfo = null ;
//表格属性 允许拖拽
gcMain.AllowDrop = true ;
gvMain.OptionsDetail.EnableMasterViewMode = false ;
#region 将对象拖至边界时发生 DragOver
gcMain.DragOver += delegate ( object sender, System.Windows.Forms.DragEventArgs e)
{
if (e.Data.GetDataPresent( typeof (T)))
e.Effect = DragDropEffects.Move;
else
e.Effect = DragDropEffects.None;
};
#endregion
#region 拖拽完成时处理数据 DragDrop
gcMain.DragDrop += delegate ( object sender, System.Windows.Forms.DragEventArgs e)
{
// 拖过来的新数据
T newRow = (T)e.Data.GetData( typeof (T));
// 原来在此坐标的数据
// e的坐标是相对于屏幕的
var clientPoint = gcMain.PointToClient( new Point(e.X, e.Y));
GridHitInfo hitInfo = gvMain.CalcHitInfo( new Point(clientPoint.X, clientPoint.Y));
var oldRow = (T)gvMain.GetRow(hitInfo.RowHandle);
// 如果相等则不处理
if (oldRow == null || newRow == null ) return ;
// 且目标位置不是最后一行的话要将所有序号重排
// 原来的行号
var oldIndex = _DownHitInfo.RowHandle;
// 新的行号
var newIndex = hitInfo.RowHandle;
BindingSource bs = (BindingSource)(gcMain.DataSource);
if (bs == null )
return ;
bs.RemoveAt(oldIndex);
bs.Insert(oldIndex, oldRow);
bs.RemoveAt(newIndex);
bs.Insert(newIndex, newRow);
bs.ResetBindings( false );
};
#endregion
#region 鼠标按下 MouseDown
gcMain.MouseDown += delegate ( object sender, MouseEventArgs e)
{
_DownHitInfo = null ;
GridHitInfo hitInfo = gvMain.CalcHitInfo( new Point(e.X, e.Y));
if (Control.ModifierKeys != Keys.None) return ;
if (e.Button == MouseButtons.Left && hitInfo.RowHandle >= 0)
{
// 禁用的Grid不支持拖拽
if (!gvMain.OptionsBehavior.Editable
|| gvMain.OptionsBehavior.ReadOnly)
return ;
// 只有点击最前面才能拖拽
if (hitInfo.InRowCell)
return ;
// 缓存
_DownHitInfo = hitInfo;
}
};
#endregion
#region 鼠标移动 MouseMove
gcMain.MouseMove += delegate ( object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
if (_DownHitInfo != null )
{
Size dragSize = SystemInformation.DragSize;
// 偏离区域
Rectangle dragRect = new Rectangle( new Point(_DownHitInfo.HitPoint.X - dragSize.Width / 2, _DownHitInfo.HitPoint.Y - dragSize.Height / 2), dragSize);
if (!dragRect.Contains( new Point(e.X, e.Y)))
{
// 屏幕坐标
var p = gcMain.PointToScreen(e.Location);
// 刷新是必须要的
gcMain.Refresh();
// 获取当前行截图
var bmp = GetDragRowImage(gcMain, _DownHitInfo, _DragRowRect);
Point offSetPoint = new Point(p.X + 1, p.Y - dragMaster.DragSize.Height / 2);
// 开始显示拖拽遮罩
dragMaster.StartDrag(bmp, offSetPoint, DragDropEffects.Move);
// 获取要拖拽的数据
object row = gvMain.GetRow(_DownHitInfo.RowHandle);
// 开始拖拽
gcMain.DoDragDrop(row, DragDropEffects.Move);
// 取消事件
DevExpress.Utils.DXMouseEventArgs.GetMouseArgs(e).Handled = true ;
// 清空缓存
_DownHitInfo = null ;
}
}
}
};
#endregion
#region 在用鼠标拖动某项时发生,是否允许继续拖放 QueryContinueDrag
gcMain.QueryContinueDrag += delegate ( object sender, QueryContinueDragEventArgs e)
{
switch (e.Action)
{
case DragAction.Continue:
// 移动遮罩
Point offSetPoint = new Point(Cursor.Position.X + 1, Cursor.Position.Y - dragMaster.DragSize.Height / 2);
dragMaster.DoDrag(offSetPoint, DragDropEffects.Move, false );
break ;
default :
// 清空
_DragRowRect = Rectangle.Empty;
// 停止拖动
dragMaster.EndDrag();
break ;
}
};
#endregion
#region 点击行头移动行
gvMain.CustomDrawRowIndicator += delegate ( object sender, RowIndicatorCustomDrawEventArgs e)
{
if (_DragRowRect == Rectangle.Empty && _DownHitInfo != null && _DownHitInfo.RowHandle == e.RowHandle)
{
_DragRowRect = e.Bounds;
}
};
#endregion
}
/// <summary>
/// 获取拖拽截图
/// </summary>
/// <param name="hitInfo"></param>
/// <param name="gcMain"></param>
/// <param name="dragRowRect"></param>
/// <returns></returns>
private static Bitmap GetDragRowImage(GridControl gcMain, GridHitInfo hitInfo, Rectangle dragRowRect)
{
// 截图
var bmp = DevImageCapturer.GetControlBitmap(gcMain, null
, dragRowRect.Width + 1, dragRowRect.Top
, gcMain.Width - dragRowRect.Width - 4, dragRowRect.Height - 1);
using (Graphics g = Graphics.FromImage(bmp))
{
var p1 = new Point(1, 1);
var p2 = new Point(bmp.Width - 1, 1);
var p3 = new Point(1, bmp.Height - 2);
var p4 = new Point(bmp.Width - 1, bmp.Height - 2);
using (Pen pen = new Pen(gcMain.ForeColor))
{
g.DrawLine(pen, p1, p2);
g.DrawLine(pen, p1, p3);
g.DrawLine(pen, p2, p4);
g.DrawLine(pen, p3, p4);
}
}
return bmp;
}
}
/// <summary>
/// 拖拽窗口
/// </summary>
public partial class DragWindow : DevExpress.Utils.Win.TopFormBase
{
private Bitmap dragBitmap;
private bool dragging;
private Point hotSpot;
public static readonly Point InvisiblePoint = new Point(-100000, -100000);
public DragWindow()
{
hotSpot = Point.Empty;
dragging = false ;
SetStyle(ControlStyles.Selectable, false );
this .Size = Size.Empty;
this .ShowInTaskbar = false ;
Form prevActive = Form.ActiveForm;
InitializeComponent();
}
void ActivateForm( object sender, EventArgs e)
{
Form form = sender as Form;
if (form == null || !form.IsHandleCreated) return ;
form.Activate();
}
public void MakeTopMost()
{
UpdateZOrder();
}
private void InitializeComponent()
{
this .StartPosition = FormStartPosition.Manual;
dragBitmap = null ;
this .Enabled = false ;
this .MinimumSize = Size.Empty;
this .Size = Size.Empty;
this .Location = InvisiblePoint;
this .Visible = false ;
this .TabStop = false ;
//this.Opacity = 0.7;// DevExpress.Utils.DragDrop.DragWindow.DefaultOpacity;
}
protected void InternalMoveBitmap(Point p)
{
//p.Offset(-hotSpot.X, -hotSpot.Y);
this .SuspendLayout();
this .Location = p;
this .ResumeLayout();
}
protected override void OnResize(System.EventArgs e)
{
base .OnResize(e);
}
public bool ShowDrag(Point p)
{
if ( this .BackgroundImage == null ) return false ;
dragging = true ;
Visible = true ;
Refresh();
InternalMoveBitmap(p);
return true ;
}
public bool MoveDrag(Point p)
{
if (!dragging) return false ;
InternalMoveBitmap(p);
return true ;
}
public bool HideDrag()
{
if (!dragging) return false ;
Visible = false ;
BackgroundImage = null ;
dragging = false ;
this .SuspendLayout();
this .Size = Size.Empty;
this .Location = InvisiblePoint;
this .ResumeLayout();
return true ;
}
public Point HotSpot { get { return hotSpot; } set { hotSpot = value; } }
public Bitmap DragBitmap
{
get { return dragBitmap; }
set
{
this .BackgroundImage = value;
if (value == null )
{
HideDrag();
}
else
hotSpot = new Point(value.Size.Width / 2, value.Size.Height / 2);
dragBitmap = value;
Size = BackgroundImage.Size;
}
}
}
/// <summary>
/// 截图
/// </summary>
public class DevImageCapturer
{
[System.Runtime.InteropServices.DllImport( "USER32.dll" )]
internal static extern IntPtr GetDC(IntPtr dc);
[System.Runtime.InteropServices.DllImport( "USER32.dll" )]
internal static extern int ReleaseDC(IntPtr hWnd, IntPtr hDC);
[System.Runtime.InteropServices.DllImport( "USER32.dll" )]
internal static extern IntPtr GetDesktopWindow();
[System.Runtime.InteropServices.DllImport( "gdi32.dll" )]
internal static extern bool BitBlt(IntPtr hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, IntPtr hdcSrc, int nXSrc, int nYSrc, uint dwRop);
[System.Runtime.InteropServices.DllImport( "gdi32.dll" )]
internal static extern IntPtr CreateCompatibleDC(IntPtr hdc);
[System.Runtime.InteropServices.DllImport( "gdi32.dll" )]
internal static extern IntPtr CreateCompatibleBitmap(IntPtr hdc, int nWidth, int nHeight);
[System.Runtime.InteropServices.DllImport( "gdi32.dll" )]
internal static extern bool DeleteObject(IntPtr hObject);
[System.Runtime.InteropServices.DllImport( "gdi32.dll" )]
internal static extern IntPtr SelectObject(IntPtr hdc, IntPtr obj);
[System.Runtime.InteropServices.DllImport( "gdi32.dll" )]
internal static extern IntPtr CreateSolidBrush( int color);
[System.Runtime.InteropServices.DllImport( "gdi32.dll" )]
internal static extern IntPtr CreatePatternBrush(IntPtr hBitmap);
/// <summary>
/// 获取控件的截图
/// </summary>
/// <param name="control">控件</param>
/// <param name="pattern">图片</param>
/// <returns></returns>
public static Bitmap GetControlBitmap(Control control, Bitmap pattern)
{
int width = control.Width;
int height = control.Height;
if (control is Form)
{
width = control.ClientRectangle.Width;
height = control.ClientRectangle.Height;
}
IntPtr hdc = GetDC(control.Handle);
IntPtr compDC = CreateCompatibleDC(hdc);
IntPtr compHBmp = CreateCompatibleBitmap(hdc, width, height);
IntPtr prev = SelectObject(compDC, compHBmp);
IntPtr brush = IntPtr.Zero, prevBrush = IntPtr.Zero;
if (pattern != null )
{
brush = CreatePatternBrush(pattern.GetHbitmap());
prevBrush = SelectObject(compDC, brush);
}
Point pt = new Point(0, 0);
BitBlt(compDC, 0, 0, width, height, hdc, pt.X, pt.Y, 0x00C000CA);
SelectObject(compDC, prev);
if (prevBrush != IntPtr.Zero)
SelectObject(compDC, prevBrush);
ReleaseDC(control.Handle, hdc);
NativeMethods.DeleteDC(compDC);
Bitmap bmp = Bitmap.FromHbitmap(compHBmp);
DeleteObject(compHBmp);
if (brush != IntPtr.Zero)
DeleteObject(brush);
return bmp;
}
/// <summary>
/// 获取控件的截图
/// </summary>
/// <param name="control">控件</param>
/// <param name="pattern">图片</param>
/// <param name="offSetX">X</param>
/// <param name="offSetY">Y</param>
/// <param name="width">宽</param>
/// <param name="height">高</param>
/// <returns></returns>
public static Bitmap GetControlBitmap(Control control, Bitmap pattern, int offSetX = 0, int offSetY = 0, int width = 0, int height = 0)
{
width = width == 0 ? control.Width : width;
height = height == 0 ? control.Height : height;
if (control is Form)
{
width = control.ClientRectangle.Width;
height = control.ClientRectangle.Height;
}
IntPtr hdc = GetDC(control.Handle);
IntPtr compDC = CreateCompatibleDC(hdc);
IntPtr compHBmp = CreateCompatibleBitmap(hdc, width, height);
IntPtr prev = SelectObject(compDC, compHBmp);
IntPtr brush = IntPtr.Zero, prevBrush = IntPtr.Zero;
if (pattern != null )
{
brush = CreatePatternBrush(pattern.GetHbitmap());
prevBrush = SelectObject(compDC, brush);
}
Point pt = new Point(offSetX, offSetY);
BitBlt(compDC, 0, 0, width, height, hdc, pt.X, pt.Y, 0x00C000CA);
SelectObject(compDC, prev);
if (prevBrush != IntPtr.Zero)
SelectObject(compDC, prevBrush);
ReleaseDC(control.Handle, hdc);
NativeMethods.DeleteDC(compDC);
Bitmap bmp = Bitmap.FromHbitmap(compHBmp);
DeleteObject(compHBmp);
if (brush != IntPtr.Zero)
DeleteObject(brush);
return bmp;
}
}
public class DragMaster
{
[ThreadStatic]
static DragWindow dragWindow;
bool dragInProgress;
DragDropEffects effects;
DragDropEffects lastEffect;
static Cursor customizationCursor = null ;
double _opacity = 0.7;
public double Opacity
{
get { return _opacity; }
set { _opacity = value; }
}
public DragMaster()
{
dragInProgress = false ;
lastEffect = effects = DragDropEffects.None;
}
DragWindow DragWindow
{
get
{
if (dragWindow == null ) dragWindow = new DragWindow() { Opacity = this .Opacity };
return dragWindow;
}
}
public DragDropEffects LastEffect
{
get { return lastEffect; }
}
public bool DragInProgress
{
get { return dragInProgress; }
}
/// <summary>
/// 绘制大小
/// </summary>
public Size DragSize
{
get
{
if (DragWindow.DragBitmap == null ) return Size.Empty;
return DragWindow.DragBitmap.Size;
}
}
/// <summary>
/// 开始拖拽
/// </summary>
/// <param name="bmp"></param>
/// <param name="startPoint"></param>
/// <param name="effects"></param>
public void StartDrag(Bitmap bmp, Point startPoint, DragDropEffects effects)
{
StopDrag();
dragInProgress = true ;
this .effects = effects;
lastEffect = effects;
DragWindow.MakeTopMost();
DragWindow.DragBitmap = bmp;
DragWindow.ShowDrag(startPoint);
SetDragCursor(effects);
}
/// <summary>
/// 停止拖拽
/// </summary>
protected void StopDrag()
{
dragInProgress = false ;
lastEffect = effects = DragDropEffects.None;
DragWindow.HideDrag();
}
/// <summary>
/// 设置拖拽鼠标类型
/// </summary>
/// <param name="e"></param>
public void SetDragCursor(DragDropEffects e)
{
if (e == DragDropEffects.None)
Cursor.Current = CustomizationCursor;
else
Cursor.Current = Cursors.Default;
}
/// <summary>
/// 拖拽
/// </summary>
/// <param name="p"></param>
/// <param name="e"></param>
/// <param name="setCursor"></param>
public void DoDrag(Point p, DragDropEffects e, bool setCursor)
{
if (!dragInProgress) return ;
lastEffect = e;
if (setCursor) SetDragCursor(e);
DragWindow.MoveDrag(p);
}
/// <summary>
/// 取消拖拽
/// </summary>
public void CancelDrag()
{
if (!dragInProgress) return ;
StopDrag();
}
/// <summary>
/// 结束拖拽
/// </summary>
public void EndDrag()
{
if (!dragInProgress) return ;
StopDrag();
}
/// <summary>
/// 自定义Cursor
/// </summary>
static Cursor CustomizationCursor
{
get
{
if (customizationCursor == null ) customizationCursor = ResourceImageHelper.CreateCursorFromResources( "DevExpress.XtraTreeList.Images.customization.cur" , typeof (DragMaster).Assembly);
return customizationCursor;
}
}
}
|