为啥我不能在程序的两个实例之间拖动一个点?

Posted

技术标签:

【中文标题】为啥我不能在程序的两个实例之间拖动一个点?【英文标题】:Why can't I drag a Point between two instances of a program?为什么我不能在程序的两个实例之间拖动一个点? 【发布时间】:2012-06-14 08:18:18 【问题描述】:

我有一个 DoDragDrop,我在其中将数据设置为 Point。当我在一个实例中拖动时 - 一切正常。但是当我在程序的两个实例之间拖动时,Visual Studio 给了我这个错误:

指定的记录无法映射到托管值类。

为什么?

编辑:这是代码:

DataObject d = new DataObject();
d.SetData("ThePoint", MyPoint);
DragDropEffects e = DoDragDrop(d, DragDropEffects.Move);

还有:

Point e2 = (Point)e.Data.GetData("ThePoint");

【问题讨论】:

请提供更多代码。您在哪里以及如何访问 DataObject? @dowhilefor 已添加到问题中。 我的猜测是您需要正确序列化该点。我不确定 Setdata 如何存储点,但我认为没有任何序列化只存储某种引用。所以尝试序列化点,存储它,然后在你的其他应用程序中反序列化它。可能有一个用于指向和指向字符串的 TypeConverter 应该可以正常工作。 @dowhilefor 听起来不错。如果 DragAndDrop 只存储一个引用——这就解释了为什么第二个实例无法访问该点本身。谢谢。 好吧,点是一个值类型,所以我不认为它是一个真正的参考,但究竟发生了什么,一些 C# 大师可能会解释得更好。 【参考方案1】:

指定的记录无法映射

请注意“记录”一词的奇怪之处。它是“结构”的以 COM 为中心的词。您尝试做的几乎有效,但不完全。 DoDragDrop() 方法将 Point 结构正确地编组为 COM 对象,这可能是因为 Point 具有 [ComVisible(true)] 属性。缺少的成分是 IRecordInfo 所需的信息,IRecordInfo 是一个描述结构布局的 COM 接口。必需,因为结构具有非常依赖于编译器的布局。

这个接口通常是通过从类型库中读取结构定义来实现的。这实际上是可用的,Point 结构在 c:\windows\microsoft.net\framework\v2.0.50727\system.drawing.tlb 中进行了描述。您可以使用 OleView.exe 工具 File + View Typelib 查看它。

一切都很好,除了 COM 对象的接收者必须将其转换回托管对象的部分,即点。这需要找出包含对象定义的类型库,这样 IRecordInfo 才能完成它的工作。其中记录在注册表中,HKCR\Record 键。 not 是否包含 Point 的条目。卡布姆。

创建你自己的类(不是结构)来存储数据,给它[Serializable]属性,这样它就可以很容易地被封送。

【讨论】:

因为它不必跨进程边界进行编组,所以数据对象指针可以直接使用。拖放管道就像一座冰山,90% 都在水下并且不可见。 .NET 事件处理程序很好,但它们没有显示 99% 的情况。【参考方案2】:

这看起来像一个 hack,但你可以这样做,我测试它是有效的。 编辑猜猜它没有回答为什么?问题。

private void panel1_MouseDown(object sender, MouseEventArgs e)
    
        Point MyPoint = new Point(100, 200);
        DoDragDrop(new string[]  MyPoint.X.ToString(), MyPoint.Y.ToString() , DragDropEffects.Copy);
    

    private void Form1_DragEnter(object sender, DragEventArgs e)
    
        e.Effect = DragDropEffects.Copy;
    

    private void Form1_DragDrop(object sender, DragEventArgs e)
    
        if (e.Data.GetDataPresent(typeof(string[])))
        
            string[] item = (string[])e.Data.GetData(typeof(string[]));
            Point e2 = new Point(Int32.Parse(item[0]), Int32.Parse(item[1]));

            MessageBox.Show(e2.X+":"+e2.Y);
        

    

【讨论】:

以上是关于为啥我不能在程序的两个实例之间拖动一个点?的主要内容,如果未能解决你的问题,请参考以下文章

为啥我电脑开了网页后用鼠标滚轮就死机?而直接点拖动条拖动却不会死机?

为啥我不能拖动跨度,而是拖动 img?

electron 在windows下窗口为啥不能拖动

为啥我不能在 C# 应用程序中使用泛型类型作为入口点?

为啥我需要创建 Line 的新实例,而不是在 Kivy 中简单地更新或添加和删除它

为啥我需要创建 Line 的新实例,而不是在 Kivy 中简单地更新或添加和删除它