Подпишись на наш Twitter

Быть в курсе появления новых статей!

Вы можете использовать GiveFeedback для изменения курсора во время операции drag-and-drop. Вы можете пойти немного дальше и установить в качестве курсора картинку представляющую собой пользовательский элемент, который вы тащите, отобразив UIElement как картинку (bitmap) и потом конвертировав эту картинку в курсор.

Этот пример основан на коде написанном Brandon Cannaday, http://www.switchonthecode.com/tutorials/wpf-tutorial-how-to-use-custom-cursors. Для начал здесь приводится код Brandon измененный читателем "Swythan":

public class CursorHelper
{
    private static class NativeMethods
    {
        public struct IconInfo
        {
            public bool fIcon;
            public int xHotspot;
            public int yHotspot;
            public IntPtr hbmMask;
            public IntPtr hbmColor;
        }

    [DllImport("user32.dll")]
    public static extern SafeIconHandle CreateIconIndirect(ref IconInfo icon);

    [DllImport("user32.dll")]
    public static extern bool DestroyIcon(IntPtr hIcon);

    [DllImport("user32.dll")]
    [return: MarshalAs(UnmanagedType.Bool)]
    public static extern bool GetIconInfo(IntPtr hIcon, ref IconInfo pIconInfo);
}

[SecurityPermission(SecurityAction.LinkDemand, UnmanagedCode = true)]
private class SafeIconHandle : SafeHandleZeroOrMinusOneIsInvalid
{
    public SafeIconHandle()
        : base(true)
    {
    }

    override protected bool ReleaseHandle()
    {
        return NativeMethods.DestroyIcon(handle);
    }
}

private static Cursor InternalCreateCursor(System.Drawing.Bitmap bmp)
{
    var iconInfo = new NativeMethods.IconInfo();
    NativeMethods.GetIconInfo(bmp.GetHicon(), ref iconInfo);

    iconInfo.xHotspot = 0;
    iconInfo.yHotspot = 0;
    iconInfo.fIcon = false;

    SafeIconHandle cursorHandle = NativeMethods.CreateIconIndirect(ref iconInfo);
    return CursorInteropHelper.Create(cursorHandle);
}

public static Cursor CreateCursor(UIElement element)
{
    element.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
    element.Arrange(new Rect(new Point(), element.DesiredSize));

    RenderTargetBitmap rtb =
      new RenderTargetBitmap(
        (int)element.DesiredSize.Width,
        (int)element.DesiredSize.Height,
        96, 96, PixelFormats.Pbgra32);

    rtb.Render(element);

    var encoder = new PngBitmapEncoder();
    encoder.Frames.Add(BitmapFrame.Create(rtb));

    using (var ms = new MemoryStream())
    {
        encoder.Save(ms);
        using (var bmp = new System.Drawing.Bitmap(ms))
        {
            return InternalCreateCursor(bmp);
        }
    }
}

}

Теперь, когда у нас есть вспомогательный класс, мы можем использовать его для установки изображения для Label который мы тянем. Вот пример определения XAML метки для переноса из одной в другую.


    

Это соответствующий код для реализации drag-and-drop:

private void Label_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
    DataObject data = new DataObject(DataFormats.Text, ((Label)e.Source).Content);

    DragDrop.DoDragDrop((DependencyObject)e.Source, data, DragDropEffects.Copy);
}

private void Label_Drop(object sender, DragEventArgs e)
{
    ((Label)e.Source).Content = (string)e.Data.GetData(DataFormats.Text);
}

private Cursor customCursor = null;

private void Label_GiveFeedback(object sender, GiveFeedbackEventArgs e)
{
    if (e.Effects == DragDropEffects.Copy)
    {
        if (customCursor == null)
            customCursor = CursorHelper.CreateCursor(e.Source as UIElement);

        if (customCursor != null)
        {
            e.UseDefaultCursors = false;
            Mouse.SetCursor(customCursor);
        }
    }
    else
        e.UseDefaultCursors = true;

    e.Handled = true;
}

Оригинал: #713 – Setting the Cursor to an Image of an UIElement While Dragging




Дата публикации: 17.12.2012 19:26

Ярлыки: Cursor, Drag and Drop, Events, Image, UIElement, WPF