C# 拖放:拖动时显示拖动的项目

2023-12-30

我正在使用 C# 和 Windows 窗体构建桌面应用程序。我有一个自定义控件,我希望能够将其拖放到我的应用程序内(而不是外部)。现在我正在使用通常的 DoDragDrop/OnDragOver/OnDragDrop 方法来实现它。有没有什么方法可以在控件被拖动时连续绘制控件——就像您在 JQuery 的拖放中看到的那样?我希望实际控件保持在原位,但我想在用户拖动它时绘制其外观的副本。理想情况下,副本甚至是半透明的,但这更“有好处”。

我能想到的唯一方法是将绘制代码放入主窗体的 OnPaint 方法中,但这似乎是一个不优雅的解决方案。还有其他想法吗?如果控件将自身绘制为位图,事情会更容易吗?


我想我应该自己回来回答这个问题,因为我最终确实让它发挥了作用。

我创建了一个包含以下函数的 CursorUtil 类:

public struct IconInfo {
    public bool fIcon;
    public int xHotspot;
    public int yHotspot;
    public IntPtr hbmMask;
    public IntPtr hbmColor;
}

public class CursorUtil {
    [DllImport("user32.dll")]
    public static extern IntPtr CreateIconIndirect(ref IconInfo icon);

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

    [DllImport("gdi32.dll")]
    public static extern bool DeleteObject(IntPtr handle);

    [DllImport("user32.dll", CharSet = CharSet.Auto)]
    extern static bool DestroyIcon(IntPtr handle);

    // Based on the article and comments here:
    // http://www.switchonthecode.com/tutorials/csharp-tutorial-how-to-use-custom-cursors
    // Note that the returned Cursor must be disposed of after use, or you'll leak memory!
    public static Cursor CreateCursor(Bitmap bm, int xHotspot, int yHotspot) {
        IntPtr cursorPtr;
        IntPtr ptr = bm.GetHicon();
        IconInfo tmp = new IconInfo();
        GetIconInfo(ptr, ref tmp);
        tmp.xHotspot = xHotspot;
        tmp.yHotspot = yHotspot;
        tmp.fIcon = false;
        cursorPtr = CreateIconIndirect(ref tmp);

        if (tmp.hbmColor != IntPtr.Zero) DeleteObject(tmp.hbmColor);
        if (tmp.hbmMask != IntPtr.Zero) DeleteObject(tmp.hbmMask);
        if (ptr != IntPtr.Zero) DestroyIcon(ptr);

        return new Cursor(cursorPtr);
    }

    public static Bitmap AsBitmap(Control c) {
        Bitmap bm = new Bitmap(c.Width, c.Height);
        c.DrawToBitmap(bm, new Rectangle(0, 0, c.Width, c.Height));
        return bm;
    }

然后我编写了一个 Drag 类(唉,也不是面向对象的,但我认为在桌面应用程序中一次只能拖动一个东西)。这是该代码的一部分:

    public static void StartDragging(Control c) {
        Dragged = c;
        DisposeOldCursors();
        Bitmap bm = CursorUtil.AsBitmap(c);
        DragCursorMove = CursorUtil.CreateCursor((Bitmap)bm.Clone(), DragStart.X, DragStart.Y);      
        DragCursorLink = CursorUtil.CreateCursor((Bitmap)bm.Clone(), DragStart.X, DragStart.Y);      
        DragCursorCopy = CursorUtil.CreateCursor(CursorUtil.AddCopySymbol(bm), DragStart.X, DragStart.Y);
        DragCursorNo = CursorUtil.CreateCursor(CursorUtil.AddNoSymbol(bm), DragStart.X, DragStart.Y);
        //Debug.WriteLine("Starting drag");
    }   

    // This gets called once when we move over a new control,
    // or continuously if that control supports dropping.
    public static void UpdateCursor(object sender, GiveFeedbackEventArgs fea) {
        //Debug.WriteLine(MainForm.MousePosition);
        fea.UseDefaultCursors = false;
        //Debug.WriteLine("effect = " + fea.Effect);
        if (fea.Effect == DragDropEffects.Move) {
            Cursor.Current = DragCursorMove;

        } else if (fea.Effect == DragDropEffects.Copy) {
            Cursor.Current = DragCursorCopy;

        } else if (fea.Effect == DragDropEffects.None) {
            Cursor.Current = DragCursorNo;

        } else if (fea.Effect == DragDropEffects.Link) {
            Cursor.Current = DragCursorLink;

        } else {
            Cursor.Current = DragCursorMove;
        }
    }

您可以在设置控件时使用这些方法,例如在构造函数中:

GiveFeedback += new GiveFeedbackEventHandler(Drag.UpdateCursor);

在这个方法中:

    protected override void OnMouseMove(MouseEventArgs mea) {
        if (Drag.IsDragging(mea)) {
            Drag.StartDragging(this);
            DragDropEffects dde = DoDragDrop(Plan, DragDropEffects.Move | DragDropEffects.Copy);
            Drag.StopDragging();
        }
    }
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C# 拖放:拖动时显示拖动的项目 的相关文章

  • 无法在 QGLWidget 中设置所需的 OpenGL 版本

    我正在尝试在 Qt 4 8 2 中使用 QGLWidget 我注意到 QGLWidget 创建的默认上下文不显示 OpenGL 3 1 以上的任何输出 Qt wiki 有一个教程 http qt project org wiki How t
  • 为什么 std::vector 可以处理类定义中的不完整类型?

    出现了以下问题 C 标准似乎说 std vector需要一个完整的类型才能工作 看https en cppreference com w cpp container vector https en cppreference com w cp
  • 带有 ASP.NET 按钮回发的 jQuery UI 对话框

    我的 ASP NET 页面上有一个运行良好的 jQuery UI 对话框 jQuery function jQuery dialog dialog draggable true resizable true show Transfer hi
  • 未找到 DEADLINE 调度策略

    我想在 C 中实现 DEADLINE 调度策略 我知道该功能已实现Linux 3 14 10我正在使用 Ubuntu 14 04Linux 3 17 0 031700 lowlatency 201410060605 SMP PREEMPT这
  • 来自 double 的 static_cast 可以优化分配给 double 吗?

    我偶然发现了一个我认为不必要的功能 并且通常让我感到害怕 float coerceToFloat double x volatile float y static cast
  • 如何在 C++ 中为指针“this”赋值

    在函数中 如何分配this一个新的价值 您可以分配对象this点于 this XY 但你不能分配直接值this this XY Error Expression is not assignable
  • 每个元素的 asp.net Web 表单自定义错误消息

    我创建了一个 Web 应用程序 表单 以及后端 SQL 插入和查询 目前我正在显示所有用户错误消息 div style padding 1em div
  • Windows Phone 7 - ScrollViewer 值已更改

    我一直在寻找解决方案 但无法找到正确的解决方案 我的网格宽度为 960 并且有ScrollViewer在里面 现在我想知道滚动时滚动的值 水平偏移 我找到的所有解决方案都是针对 wpf silverlight 的 它对我不起作用 Edit
  • 如何在 Linux 上重新实现(或包装)系统调用函数?

    假设我想完全接管 open 系统调用 也许要包装实际的系统调用并执行一些日志记录 一种方法是使用 LD PRELOAD http scaryreasoner wordpress com 2007 11 17 using ld preload
  • 重载算术运算符

    赋值运算符可以声明为 T 运算符 const t 在类中 但不能以这种方式定义算术运算符 它必须是友元函数 我不明白为什么 你能解释一下吗 算术运算符不必须是友元 那么你可以这样定义 MyClass MyClass operator con
  • DateTime.ParseExact - 为什么 yy 变成 2015 而不是 1915

    为什么 NET 假定以下年份是 2015 年 而不是 1915 年 var d DateTime ParseExact 20 11 15 dd MM yy new CultureInfo en GB 我想 它会尝试接近 但其背后是否有合理的
  • 如何在 C++ 中正确使用 cin.fail()

    我正在编写一个程序 从用户那里获取整数输入cin gt gt iUserSel 如果用户输入一个字母 程序就会进入无限循环 我试图用下面的代码来阻止这种情况 但程序进入无限循环并打印出 错误 输入 我该如何修复我的程序 cin gt gt
  • 如何从 Powerpoint 2010 导出电影?

    如何使用 MS Office PIA 主互操作程序集 或其他方式以编程方式将嵌入视频从 powerpoint 2010 导出到外部文件 在演示文稿中嵌入视频是 Powerpoint 2010 中的一项新功能 我找不到解决方案 PPTX 文件
  • main.cpp 是必需的吗?

    我试图编译一个程序cmake 我最终删除了我的main cpp文件 我刚刚将其复合到另一个包含我的项目名称的文件中 即 我刚刚将主函数剪切并粘贴到该文件中 问题是我有一个main cpp未发现错误 不确定是否在C 一个名为main cpp是
  • 如何在VS2005中使用从.bat而不是.exe启动的外部程序进行调试?

    在我的 c 项目的调试属性中 我选择了 启动外部程序 并选择了我希望将调试器附加到的程序的 exe 但是 现在我需要从 bat 文件而不是 exe 启动程序 但 VS2005 似乎不允许这样做 这可能吗 编辑 为了澄清 我需要调试从 bat
  • 在 clang 中向量化函数

    我正在尝试根据此用 clang 对以下函数进行矢量化铿锵参考 http llvm org docs Vectorizers html 它采用字节数组向量并根据以下条件应用掩码this RFC https www rfc editor org
  • Clang 5.0 上的 vsprintf 和 vsnprintf [-Wformat-nonliteral] 警告

    我有这段代码 static void err doit int errnoflag int level const char fmt va list ap int errno save unsigned long n char buf MA
  • 使用未命名命名空间而不是静态命名空间

    我可以假设在未命名命名空间中声明的对象相当于static namespace int x 1 static int x 2 FWIK 在这两种情况下 x将具有静态存储期限和内部链接 声明为的对象的所有规则也是如此static适用于未命名名称
  • 异步/等待 - 是*并发*吗?

    我一直在考虑 C 5 中新的异步内容 并且出现了一个特殊问题 据我了解 await关键字是一个简洁的编译器技巧 语法糖来实现连续传递 http en wikipedia org wiki Continuation passing style
  • NHibernate:无状态会话错误消息无法获取代理

    我正在使用 nHibernate 无状态会话来获取对象 更新一个属性并将对象保存回数据库 我不断收到错误消息 无状态会话无法获取代理 我在其他地方有类似的代码 所以我不明白为什么这不起作用 有谁知道问题可能是什么 我正在尝试更新Screen

随机推荐

  • 如何在React js文本区域内渲染漂亮的json数据?

    我是 React js 新手 我在渲染文本区域内漂亮的 json 数据时遇到问题 我不知道哪一部分是错误的 我希望我的 Prettyjson 像这样在 textarea 内渲染 email email protected cdn cgi l
  • 首先使用代码禁用整数主键上的标识(自动递增)

    我在 ASP NET MVC 3 应用程序中使用代码优先方法 并在模型中使用所有整数主键 public int Id get set 默认情况下配置为自动递增的身份 如何禁用此功能并启用手动输入主键整数的方法 实际情况是Id整数具有特殊的含
  • 如何摆脱这个 Do-While 循环?

    我有这个基本的 Arduino 代码 我想要退出此 Do While 循环的 2 个选项 我简化了原始代码以突出真正的问题 Do While无法识别 OR 退出循环的条件 在此代码中 我从两个等于 0 的整数变量开始 一旦它们进入 Do W
  • Git 推送结果致命:协议错误:错误的行长度字符:这

    我正在尝试让 GitLab 在我的服务器上运行 运行 CentOS 6 5 我跟着gitlab 菜谱 https github com gitlabhq gitlab recipes blob master install centos R
  • 如何创建一个包含纬度和经度的数组,并使用for循环来标记android中谷歌地图上的位置

    我刚刚开始在 android 中编码 经过很长一段时间 我让我的谷歌地图可以工作 并且能够在上面放置标记 接下来我想做的是创建一个 latlng 数组并使用 for 循环在谷歌地图上放置一个标记 我不知道该怎么做 有人可以帮助我吗 到目前为
  • 更改 Windows 中的默认 MySQL 用户

    如果我运行mysql or mysqldump从命令提示符运行程序 我在 Windows 中得到这个 ERROR 1045 28000 Access denied for user ODBC localhost using password
  • 内联三元运算符不起作用

    由于某种原因 我的三元运算符分配不适用于数组的第二部分 有人看到我做错了什么吗 它应该只是查看永久链接字段是否有值 如果没有则插入link url进入数组 function getSiteMap this gt db gt select s
  • Firefox 中的文本描边和阴影 CSS3

    我想知道是否有一种方法可以在文本中添加描边和阴影 我可以让它在 Chrome 和 Safari 中工作 因为 webkit 支持文本描边和文本阴影 我可以在 Firefox 中显示笔划 但那是使用文本阴影并使用偏移量 那么有人知道解决这个问
  • 将日期和时间数字转换为 time_t 并指定时区

    我有以下整数 int y mon d h min s 他们的价值观是 2012 06 27 12 47 53分别 如果我在应用程序中的其他地方选择了 UTC 我想表示 2012 06 27 12 47 53 UTC 的日期时间 或者如果我在
  • 如何通过 SAX XML Schema Validator 的验证消息进行内部化?

    我使用此代码根据 XSD 验证 XML SchemaFactory factory SchemaFactory newInstance http www w3 org 2001 XMLSchema Schema schema factory
  • Excel 复制到 Word VBA

    我正在使用宏记录器处理一些代码 在单词中 它总是以选择开头 本文说我应该能够将文档分配给一个变量 然后将其插入到 Selection 之前 但是 在我输入文档变量后 选择方法不会出现在 VBE 中 第一次使用 Selection 对象 Se
  • 如何在 VB.NET 中使用多种字体样式组合?

    如果我想设置我的字体 我可以使用 new Font Times New Roman 12 Drawing FontStyle Bold 我可以使用斜体 常规或下划线代替粗体 但我想同时使用粗体和斜体 我怎样才能做到这一点 The FontS
  • wx 0.90.0.1 无法在 Haskell Platform 2012.2.0.0 (WinXP) 上安装

    我尝试使用 cabal install wx 在 Haskell Platform 2012 2 0 0 上安装 WX 0 90 0 1 但得到以下结果 Configuring wxc 0 90 0 4 setup exe wx confi
  • AspectJ:验证错误

    我正在尝试面向方面的编程 我已经安装了AspectJ 插件 http eclipse org aspectj index php在 Eclipse 中并遵循本中提到的所有步骤tutorial http sites google com si
  • 无效的二进制或无效的 Swift 支持

    将应用程序发送到应用程序商店以供批准后 我在 iTunes Connect 中收到消息 无效的二进制文件 然后我在 Apple 发来的电子邮件中收到以下消息 无效的 Swift 支持 该捆绑包包含无效的 Swift 实现 该应用程序可能是使
  • Chart.js x 轴线性比例:奇怪的行为

    我正在尝试在 Chart js 图表中的 x 轴上使用线性刻度 我添加了一些代码 因为 stackoverflow 使其在添加 jsfiddle url 时必须这样做 但我不明白这一点 var options scales xAxes ty
  • 相当于其他编译器中 MSVC 的 _countof 吗?

    是否有任何内置的等价物 countof http msdn microsoft com en us library ms175773 v VS 100 aspx由其他编译器提供 特别是 GCC 和 Clang 有没有非宏观形式 使用C 11
  • 理解 sklearn CountVectorizer 中的“ngram_range”参数

    我对如何在 Python 的 scikit learn 库中使用 ngrams 有点困惑 具体来说 如何ngram range参数在 CountVectorizer 中工作 运行这段代码 from sklearn feature extra
  • 等待 Task.Run 与等待

    我在网上搜索了一下 看到很多关于Task Run与await async相比 但是有一个特定的使用场景 我不太理解其中的区别 我相信场景很简单 await Task Run gt LongProcess vs await LongProce
  • C# 拖放:拖动时显示拖动的项目

    我正在使用 C 和 Windows 窗体构建桌面应用程序 我有一个自定义控件 我希望能够将其拖放到我的应用程序内 而不是外部 现在我正在使用通常的 DoDragDrop OnDragOver OnDragDrop 方法来实现它 有没有什么方