.NET Drag and drop ; Show dragged borders or image such as Windows do

六眼飞鱼酱① 提交于 2019-12-23 03:10:23

问题


I was wondering if there is a way (there is always a way) or what are best approach you have to show either of the borders of my controls or an image of what user is currently draging and dropping? I only drag from within my own app so not from desktop.

I would like to have somethings similar to :

I used to try to manually draw lines to "fake" the fact that this is my control's borders and It works fine... but I had hard time showing them over others form's controls as this is a huge form with multilevel controls.

I can't really show code I currently have as this is too much huge. But, maybe if you knows some good examples to perform this on what I can base my searches on. Because so far, I can't find any way to shows a Controls Border or a Image of control when drag and dropping.


回答1:


It is, as you noted, possible, but not with one or two lines..

Here is an example, that uses a Panel dragFrame, in which an Image of the dragged control is shown.

Is is moving along with the cursor, but should not slide under it, so the DragEnter event still recognizes the Cursor coming in.

I prepare the form by setting up two list of controls: Those that can be dragged and those that can be dropped on. But for the eample I only code for one target..

We can't use a MouseMove event during the Dragging so we need a workaround with a Timer. In its Tick we either follow with the Panel or, if by now the mouse button has been released, we abort everything.

First we create the Panel and hide it. The Timer should be fast..

public Form1()
{
    InitializeComponent();
    dragFrame.Visible = false;
    dragFrame.BorderStyle = BorderStyle.FixedSingle;
    Controls.Add(dragFrame);
    timer1.Interval = 20;
}

Now we load the two lists:

private void Form1_Load(object sender, EventArgs e)
{
    foreach (Control ctl in Controls) if (ctl != dropPanel) draggables.Add(ctl);
    makeDraggable(draggables);
    dragTargets.Add(dropPanel);
}

List<Control> dragTargets = new List<Control>();
List<Control> draggables = new List<Control>();
Panel dragFrame = new Panel();
Point mDown = Point.Empty;

This function adds sa few handlers to the draggable controls. The most involved it the Mousedown. In addition to starting the Draggin we create a new BackgroundImage for the Panel and size and show it. We also start the timer.

void makeDraggable(List<Control> draggables)
{
    foreach (Control ctl in draggables)
    {
        ctl.MouseDown += (s, e) => 
            {
                mDown = e.Location;
                timer1.Start();
                dragFrame.Size = ctl.Size;

                if (dragFrame.BackgroundImage != null)
                    dragFrame.BackgroundImage.Dispose();
                Bitmap bmp = new Bitmap(dragFrame.ClientSize.Width,
                                        dragFrame.ClientSize.Height);
                ctl.DrawToBitmap(bmp, dragFrame.ClientRectangle);
                dragFrame.BackgroundImage = bmp;

                dragFrame.BringToFront();
                dragFrame.Show();
                ctl.DoDragDrop(ctl.Text, DragDropEffects.Copy | DragDropEffects.Move);
            };

        ctl.MouseUp += (s, e) =>
            {
                dragFrame.Hide();
                timer1.Stop();
            };

        ctl.Leave += (s, e) =>
        {
            dragFrame.Hide();
            timer1.Stop();
        };
    }
}

These are the events for one drop target. You will want to code the actual drop code, where you process the data..

private void dropPanel_DragEnter(object sender, DragEventArgs e)
{

    if (e.Data.GetDataPresent(DataFormats.Text))
            { e.Effect = DragDropEffects.Copy;            }
    else  { e.Effect = DragDropEffects.None; }
}

private void dropPanel_DragDrop(object sender, DragEventArgs e)
{
    dragFrame.Hide();
    timer1.Stop();
}

In the timer.Tick we do the moving and, when necessary abort the action:

private void timer1_Tick(object sender, EventArgs e)
{


    if ( (Control.MouseButtons & MouseButtons.Left) == MouseButtons.None)
    {
        dragFrame.Hide();
        timer1.Stop();
    }

    if (dragFrame.Visible)
    {
        Point pt = this.PointToClient(Cursor.Position);
        dragFrame.Location = new Point(pt.X - mDown.X, 
                                       pt.Y - dragFrame.Height);
        foreach( Control ctl  in dragTargets)
            if (ctl.ClientRectangle.Contains(pt ) )
            {
                dragFrame.Hide();
            }
    }
}

As you see it is involved and probably has a few quirks.

Still sure you need this?




回答2:


Finally, here is how we finally make it work as we want;

public Sub CreateCustomCursor(ByVal e As MouseEventArgs)
    Dim bmp As New Bitmap(Me.Width, Me.Height)
    ' ME IS A USERCONTROL '
    Me.DrawToBitmap(bmp, New Rectangle(New Point(0, 0), Me.Size))

    ' MAKE A CURSOR WITH AN IMAGE OF ME, WHICH IS A USERCONTROL '
    Dim cur As Cursor = Me.CreateCursor(bmp, e.X, e.Y)
    Cursor.Current = cur
    Me.IsCursorSet = True
End Sub

Public Structure IconInfo
    Public fIcon As Boolean
    Public xHotspot As Integer
    Public yHotspot As Integer
    Public hbmMask As IntPtr
    Public hbmColor As IntPtr
End Structure

<DllImport("user32.dll")> _
Public Shared Function GetIconInfo(ByVal hIcon As IntPtr, ByRef pIconInfo As IconInfo) As <MarshalAs(UnmanagedType.Bool)> Boolean
End Function

<DllImport("user32.dll")> _
Public Shared Function CreateIconIndirect(ByRef icon As IconInfo) As IntPtr
End Function

private Function CreateCursor(ByVal bmp As Bitmap, ByVal xHotSpot As Integer, ByVal yHotSpot As Integer) As Cursor
    Dim ptr As IntPtr = bmp.GetHicon()
    Dim tmp As New IconInfo()
    GetIconInfo(ptr, tmp)
    tmp.xHotspot = xHotSpot
    tmp.yHotspot = yHotSpot
    tmp.fIcon = False
    ptr = CreateIconIndirect(tmp)
    Return New Cursor(ptr)
End Function


来源:https://stackoverflow.com/questions/31193787/net-drag-and-drop-show-dragged-borders-or-image-such-as-windows-do

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!