C# 模拟 Windows 中的默认拖放功能(拖动过程中的透明图像)

Posted

技术标签:

【中文标题】C# 模拟 Windows 中的默认拖放功能(拖动过程中的透明图像)【英文标题】:C# emulating the default drag-drop functionality in windows (transparent image during drag) 【发布时间】:2019-04-15 09:11:23 【问题描述】:

我有一个带有图像单元格(和隐藏的文本单元格)的数据网格,我希望能够在其中将图像从一个单元格拖放到另一个单元格,这部分我正在工作,我无法工作的是光标在拖放过程中。拖动时,我希望图像替换光标,类似于在 Windows 桌面上拖动文件时发生的情况。目前正在发生的是光标在我想使用的自定义图像和默认拖动光标(带有小矩形的指针)之间闪烁。我对如何解决这个问题有点迷茫。请注意,我不是编码方面的专家,我的大部分代码都是通过谷歌搜索我想要完成的内容并将它们拼凑在一起的。

问题的 GIF:https://gfycat.com/AgileImpressiveHermitcrab 请注意,我的记录器并没有捕获所有内容,它的闪烁速度比显示的要快得多,并且在鼠标不移动时也会不停地闪烁(仅在按住鼠标按钮时)

    private DataGridViewCell drag_Image; //This is the initial image dragged
    private object HoldingImage;        //Stored target image
    private DataGridViewCell drag_ID;       //ID tied with initial image
    private object HoldingID;           //ID tied with stored target image
    private Bitmap DragCursor;  //This is the initial dragged image, set as the cursor
    private string DragIndicator;       //Attempting a new trigger for drag event

    private void dataGridView1_MouseMove(object sender, MouseEventArgs e)
    //This code is not needed for functionality, what is the point here?

        //if ((e.Button & MouseButtons.Left) == MouseButtons.Left)
        
            // If the mouse moves outside the rectangle, start the drag.
            //if (dragBoxFromMouseDown != Rectangle.Empty && !dragBoxFromMouseDown.Contains(e.X, e.Y))
            

                // Proceed with the drag and drop, passing in the list item.                    
                //DragDropEffects dropEffect = dataGridView1.DoDragDrop(dataGridView1.Rows[dataGridView1.CurrentRow.Index],DragDropEffects.Move);
            
        
    

    private void dataGridView1_DragOver(object sender, DragEventArgs e)
    
       //This is where the cursor begins to flicker in the debugger, it cycles through this code
        Bitmap DragCursor = new Bitmap(@"C: \Users\******\Desktop\Items\Organizer\Planner\Planner\1.png");
        DragCursor.MakeTransparent(Color.White);

        Cursor cur = new Cursor(DragCursor.GetHicon());
        Cursor.Current = cur;

        e.Effect = DragDropEffects.Move;

        DragIndicator = "1";

    

    private void dataGridView1_DragDrop(object sender, DragEventArgs e)
    
        // The mouse locations are relative to the screen, so they must be 
        // converted to client coordinates.
        Point clientPoint = dataGridView1.PointToClient(new Point(e.X, e.Y));

        // Get the row index of the item the mouse is below. 
        DataGridView.HitTestInfo hti = dataGridView1.HitTest(clientPoint.X, clientPoint.Y);
        DataGridViewCell targetCell = dataGridView1[hti.ColumnIndex, hti.RowIndex];
        DataGridViewCell targetCellID = dataGridView1[hti.ColumnIndex + 1, hti.RowIndex];


        // If the drag operation was a move then remove and insert the row.
        //if (e.Effect == DragDropEffects.Move)
        if (DragIndicator == "1") //The new trigger works though we still can not removed all DragDropEffect.Move lines, as this disables dragging
        
            if (SwapBtn.Enabled == false)
            
                //Swap mode 
                HoldingImage = targetCell.Value;
                targetCell.Value = drag_Image.Value;
                drag_Image.Value = HoldingImage;

                HoldingID = targetCellID.Value;
                targetCellID.Value = drag_ID.Value;
                drag_ID.Value = HoldingID;
                dataGridView1.Refresh();
                DragIndicator = "0";
            
            else
            
                //TODO Insert mode

            
        
    


    public void dataGridView1_MouseDown(object sender, MouseEventArgs e)
    

        if (e.Button == System.Windows.Forms.MouseButtons.Left)
        
            DataGridView.HitTestInfo hti = dataGridView1.HitTest(e.X, e.Y);
            drag_Image = dataGridView1[hti.ColumnIndex, hti.RowIndex];
            drag_ID = dataGridView1[hti.ColumnIndex + 1, hti.RowIndex];
            // Proceed with the drag and drop, passing in the list item.                    
            DragDropEffects dropEffect = dataGridView1.DoDragDrop(drag_Image, DragDropEffects.Move);
        

    

【问题讨论】:

【参考方案1】:

所以我没有 100% 解决我的问题,但我会接受。更改光标并避免自定义光标与默认值冲突时闪烁的解决方案是...

    private void dataGridView1_GiveFeedback(object sender, GiveFeedbackEventArgs e)
    
        e.UseDefaultCursors = false;
    

图像上没有箭头指针,与 Windows 拖放功能一样,但现在可以使用。

【讨论】:

以上是关于C# 模拟 Windows 中的默认拖放功能(拖动过程中的透明图像)的主要内容,如果未能解决你的问题,请参考以下文章

WPF 拖放 C# 也可以拖动图像

使用 JQuery“模拟”拖放的简单方法?

javascript中ondragover是啥事件

在 C# 中的面板上拖放时移动控件

H5拖动事件复习

jQuery 拖放模拟对最后一个可拖动对象不起作用