vbAccelerator - Contents of code file: ImageListDrag.csusing System;
using System.Diagnostics;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace vbAccelerator.Components.ImageList
{
/// <summary>
/// Provides the ability to create 32-bit alpha drag images
/// using the ImageList drag functionality in .NET.
/// </summary>
public class ImageListDrag : IDisposable
{
#region Unmanaged Code
[StructLayoutAttribute(LayoutKind.Sequential)]
private struct POINTAPI
{
public int X;
public int Y;
public override string ToString()
{
return String.Format("{0} X={1},Y={2}",
this.GetType().FullName, this.X, this.Y);
}
}
/*
[StructLayoutAttribute(LayoutKind.Sequential)]
private struct RECT
{
public int Left;
public int Top;
public int Right;
public int Bottom;
public override string ToString()
{
return String.Format("{0} Left={1},Top={2},Right={3},Bottom={4}",
this.GetType().FullName, this.Left, this.Top, this.Right,
this.Bottom);
}
}
*/
[DllImport("comctl32")]
private static extern int ImageList_BeginDrag(
IntPtr himlTrack,
int iTrack,
int dxHotspot,
int dyHotspot);
[DllImport("comctl32")]
private static extern void ImageList_EndDrag();
[DllImport("comctl32")]
private static extern int ImageList_DragEnter(
IntPtr hwndLock,
int X,
int Y);
[DllImport("comctl32")]
private static extern int ImageList_DragLeave (
IntPtr hwndLock );
[DllImport("comctl32")]
private static extern int ImageList_DragMove (
int X,
int Y);
[DllImport("comctl32")]
private static extern int ImageList_SetDragCursorImage (
IntPtr himlDrag,
int iDrag,
int dxHotspot,
int dyHotspot);
[DllImport("comctl32")]
private static extern int ImageList_DragShowNolock (
int fShow );
[DllImport("comctl32")]
private static extern int ImageList_GetDragImage (
ref POINTAPI ppt,
ref POINTAPI pptHotspot);
/*
[DllImport("user32")]
static extern int GetWindowRect (
IntPtr hwnd,
ref RECT rect);
Private Declare Function GetCursorPos Lib "user32" (lpPoint As POINTAPI)
As Long
*/
#endregion
#region Member Variables
/// <summary>
/// The <code>ImageList</code> to use to source the drag-drop image from.
/// </summary>
private System.Windows.Forms.ImageList iml = null;
/// <summary>
/// The <code>Control</code> which owns this class.
/// </summary>
private Control owner = null;
/// <summary>
/// The Window handle which we're dragging over.
/// </summary>
private IntPtr hWndLast = IntPtr.Zero;
/// <summary>
/// Whether dragging is occurring or not.
/// </summary>
private bool inDrag = false;
/// <summary>
/// Whether we have suspended image
/// dragging and need to start it again when the
/// cursor next moves.
/// </summary>
private bool startDrag = false;
/// <summary>
/// Whether this class has been disposed or not.
/// </summary>
private bool disposed = false;
#endregion
#region API
/// <summary>
/// Gets/sets the ImageList used to source drag images.
/// </summary>
public System.Windows.Forms.ImageList Imagelist
{
get
{
return this.iml;
}
set
{
this.iml = value;
}
}
/// <summary>
/// Gets/sets the Owning control or form for this object.
/// </summary>
public Control Owner
{
get
{
return this.owner;
}
set
{
this.owner = value;
}
}
/// <summary>
/// Starts a dragging operation which will use
/// an ImageList to create a drag image and defaults
/// the position of the image to the cursor's drag
/// point.
/// </summary>
/// <param name="imageIndex">The index of the image in
/// the ImageList to use for the drag image.</param>
public void StartDrag(
int imageIndex
)
{
StartDrag(imageIndex, 0, 0);
}
/// <summary>
/// Starts a dragging operation which will use
/// an ImageList to create a drag image and allows
/// the offset of the Image from the drag position
/// to be specified.
/// </summary>
/// <param name="imageIndex">The index of the image in
/// the ImageList to use for the drag image.</param>
/// <param name="xOffset">The horizontal offset of the drag image
/// from the drag position. Negative values move the image
/// to the right of the cursor, positive values move it
/// to the left.</param>
/// <param name="yOffset">The vertical offset of the drag image
/// from the drag position. Negative values move the image
/// below the cursor, positive values move it above.</param>
public void StartDrag(
int imageIndex,
int xOffset,
int yOffset
)
{
int res = 0;
CompleteDrag();
res = ImageList_BeginDrag(
iml.Handle, imageIndex, xOffset, yOffset);
if (res != 0)
{
this.inDrag = true;
this.startDrag = true;
}
}
/// <summary>
/// Shows the ImageList drag image at the current
/// dragging position.
/// </summary>
public void DragDrop()
{
IntPtr hWndParent = IntPtr.Zero;
Point dst = new Point();
if (this.inDrag)
{
dst = Cursor.Position;
if (this.owner != null)
{
// Position relative to owner:
dst = this.owner.PointToClient(dst);
}
if (this.startDrag)
{
this.hWndLast = (this.owner == null ? IntPtr.Zero :
this.owner.Handle);
ImageList_DragEnter(
hWndLast,
dst.X, dst.Y);
this.startDrag = false;
}
ImageList_DragMove(dst.X, dst.Y);
}
}
/// <summary>
/// Completes a drag operation.
/// </summary>
public void CompleteDrag()
{
if (this.inDrag)
{
ImageList_EndDrag();
ImageList_DragLeave(this.hWndLast);
this.hWndLast = IntPtr.Zero;
this.inDrag = false;
}
}
/// <summary>
/// Shows or hides the drag image. This is used to prevent
/// painting problems if the area under the drag needs to
/// be repainted.
/// </summary>
/// <param name="state">True to hide the drag image and
/// allow repainting, False to show the drag image.</param>
public void HideDragImage(bool state)
{
if (this.inDrag)
{
if (state)
{
ImageList_DragLeave(this.hWndLast);
this.startDrag = true;
}
else
{
DragDrop();
}
}
}
#endregion
#region Constructor, Dispose, Finalise
/// <summary>
/// Constructs a new instance of the ImageListDrag class.
/// </summary>
public ImageListDrag()
{
// Intentionally blank
}
/// <summary>
/// Clears up any resources associated with this object.
/// Note there are only resources associated when there is
/// a drag operation in effect.
/// </summary>
public void Dispose()
{
if (!this.disposed)
{
CompleteDrag();
}
this.disposed = true;
GC.SuppressFinalize(this);
}
/// <summary>
/// Finalize calls Dispose if it hasn't already been called.
/// </summary>
~ImageListDrag()
{
if (!this.disposed)
{
Dispose();
}
}
#endregion
}
}
|
|