C# .NET拖放;显示拖动的边框或图像,如Windows

C# .NET拖放;显示拖动的边框或图像,如Windows,c#,vb.net,winforms,visual-studio-2008,drag-and-drop,C#,Vb.net,Winforms,Visual Studio 2008,Drag And Drop,我想知道是否有一种方法(总是有一种方法)或者什么是最好的方法来显示我的控件的边框或者用户当前拖放的图像?我只能从自己的应用程序中拖动,所以不能从桌面拖动 我想要一些类似的东西: 我曾经尝试手动绘制线条来“伪造”这是我控件的边界,并且效果很好。。。但是我很难在其他窗体的控件上显示它们,因为这是一个带有多级控件的巨大窗体 我无法真正显示我目前拥有的代码,因为这太庞大了。但是,如果你知道一些很好的例子,可以在我搜索的基础上实现这一点。因为到目前为止,我找不到任何方法在拖放时显示控件边框或控件图像。正

我想知道是否有一种方法(总是有一种方法)或者什么是最好的方法来显示我的控件的边框或者用户当前拖放的图像?我只能从自己的应用程序中拖动,所以不能从桌面拖动

我想要一些类似的东西:

我曾经尝试手动绘制线条来“伪造”这是我控件的边界,并且效果很好。。。但是我很难在其他窗体的控件上显示它们,因为这是一个带有多级控件的巨大窗体


我无法真正显示我目前拥有的代码,因为这太庞大了。但是,如果你知道一些很好的例子,可以在我搜索的基础上实现这一点。因为到目前为止,我找不到任何方法在拖放时显示控件边框或控件图像。

正如您所指出的,这是可能的,但不需要一两行

这里是一个使用
面板dragFrame
的示例,其中显示了拖动控件的
图像

Is随光标移动,但不应在其下方滑动,因此
DragEnter
事件仍能识别光标进入

我通过设置两个控件列表来准备表单:可以拖动的控件和可以拖放的控件。但是对于eample,我只为一个目标编写代码

在拖动过程中,我们不能使用
MouseMove
事件,因此我们需要使用
计时器解决问题。在它的滴答声中,我们要么跟随面板,要么,如果现在鼠标按钮已经被释放,我们中止一切

首先,我们创建面板并隐藏它。计时器应该很快

public Form1()
{
    InitializeComponent();
    dragFrame.Visible = false;
    dragFrame.BorderStyle = BorderStyle.FixedSingle;
    Controls.Add(dragFrame);
    timer1.Interval = 20;
}
现在我们加载两个列表:

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;
在计时器中。勾选我们进行移动,必要时中止操作:

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();
            }
    }
}
正如你所看到的,这是一个复杂的过程,可能有一些怪癖


你确定你需要这个吗?

最后,这里是我们最终如何让它按我们想要的方式工作

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
public Sub-CreateCustomCursor(将值e作为MouseEventArgs)
将bmp设置为新位图(Me.Width、Me.Height)
'我是一个用户控件'
Me.DrawToBitmap(bmp,新矩形(新点(0,0),Me.Size))
'使用我的图像制作一个光标,这是一个用户控件'
Dim cur As Cursor=Me.CreateCursor(bmp,e.X,e.Y)
Cursor.Current=cur
Me.IsCursorSet=真
端接头
公共结构图标信息
公共fIcon作为布尔函数
作为整数的公共xHotspot
公共点为整数
作为IntPtr的公共hbmMask
公共hbmColor作为IntPtr
端部结构
_
作为布尔值的公共共享函数GetIconInfo(ByVal hIcon作为IntPtr,ByRef pIconInfo作为IconInfo)
端函数
_
公共共享函数CreateIconIndirect(ByRef图标作为IconInfo)作为IntPtr
端函数
专用函数CreateCursor(ByVal bmp作为位图,ByVal xHotSpot作为整数,ByVal yHotSpot作为整数)作为光标
Dim ptr为IntPtr=bmp.GetHicon()
将tmp调整为新图标()
GetIconInfo(ptr、tmp)
tmp.xHotspot=xHotspot
tmp.yHotspot=yHotspot
tmp.fIcon=False
ptr=CreateIconIndirect(tmp)
返回新光标(ptr)
端函数

有DrawgEnter和DrawLeave事件。在这里,您可以尝试设置控件的样式。这取决于你想让它看起来怎么样。对于某些控件,您可以尝试使用选择/取消选择或焦点;对于其他人,你会改变背景色,使其无效,或者你甚至可以在其顶部画一个边框。你是说DragLeave/DragEnter?但这些拖动的事件不是在控件上接收到的拖动项在/hover上吗?我真的想让拖动控件的形状不再是containerAh,在这种情况下,您可能希望从拖放切换到使用鼠标事件移动控件。有关示例,请参见。。!非常感谢你在这方面花时间。我带来了一些好东西,很快我会给你看的。它似乎工作得很好,易于实现。顺便说一句,这是一个融合了以下代码的过程:
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();
            }
    }
}
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