【发布时间】:2019-09-05 04:57:48
【问题描述】:
简而言之,尝试在不使用System.Windows.Forms 的情况下执行以下两行 C# 代码所做的事情,因为它是 .NET Core 而不是 WinForms 项目。
var data = new System.Windows.Forms.DataObject(
System.Windows.Forms.DataFormats.FileDrop, new string[] { @"C:\test.txt"});
dummyControl.DoDragDrop(data, System.Windows.Forms.DragDropEffects.Copy);
但它不起作用。我做错了什么?我的程序是,
- 当鼠标在 UI 控件上按下时,调用
SetCapture来捕获事件。 -
IDropSource的QueryContinueDrag不断返回S_OK,直到鼠标按钮向上,然后DRAGDROP_S_DROP。 -
我的“DataObject”实现
IDataObject有EnumFormatEtc。其中我只返回一个FORMATETC。new FORMATETC() { cfFormat = CF_HDROP, ptd = IntPtr.Zero, dwAspect = DVASPECT.DVASPECT_ICON, lindex = -1, tymed = TYMED.TYMED_FILE }在
QueryGetData中,如果format的tymed是TYMED_FILE,则返回S_OK,表示我正在拖动文件。否则返回DV_E_TYMED表示我没有那种类型的数据。-
在
GetData中,如果format的tymed是TYMED_FILE,我设置一个这样的文件medium = new STGMEDIUM(); medium.tymed = TYMED.TYMED_FILE; medium.unionmember = Marshal.StringToHGlobalUni(@"C:\test.txt"); medium.pUnkForRelease = IntPtr.Zero;
我尝试拖放到记事本。问题是,
- 如果没有在鼠标按下事件上调用
DoDragDrop,则会捕获鼠标并接收鼠标向上事件。但是当DoDragDrop被调用时,QueryContinueDrag被无休止地调用并且我没有得到鼠标向上事件,即使我释放了鼠标。我尝试在另一个线程中调用DoDragDrop,但没有成功。 - 我收到类似
QueryGetData(TYMED_HGLOBAL)或QueryGetData(TYMED_HGLOBAL, TYMED_ISTREAM, TYMED_GDI, TYMED_MFPICT, TYMED_ENHMF)的回调,但不是TYMED_FILE。为什么记事本不要求这样做?
拖放似乎不必要地复杂,但目前我只对拖动文件感兴趣,所以我不想实现除此之外的部分。上述程序或假设有什么错误?
【问题讨论】:
-
当然,您更喜欢更新到 .NETCore v3.0,无需 hack。
-
我知道 .NET Core 3.0 带有 WinForms,但在这种情况下,我尝试使用 GTK# 来实现跨平台性。但是,不幸的是,GTK# 似乎不支持 Windows 文件拖放(GTK# 应用程序到 Win32 应用程序)。我想我甚至可以通过创建一个虚拟
Control在 GTK# 应用程序中使用 WinForms 的 DoDragDrop,但这样做可能会加载不必要的 DLL,所以我认为直接使用 Win32 API 会更有效。只是它比我预期的要复杂得多。 -
这很勇敢。 Mono 团队尝试过,但由于持续存在的兼容性问题,他们放弃了。你有一些;)DataObject class 完成了真正的工作。
标签: c# winapi .net-core pinvoke