c# - 使用 Win32 API 的文件拖放在文件资源管理器等某些应用程序上不起作用
问题描述
我在 .NET Core 应用程序上使用 Win32 API 实现了文件拖放。问题是,它适用于某些应用程序,而不适用于其他一些应用程序。
- 作品:记事本++、记事本、写字板、MS Word、Gimp、7Zip
- 不起作用:(Windows)文件资源管理器、Chrome、FireFox、VS Code、Libre Writer、Android Studio
为什么会这样?
我实现 IDataObject 的“DataObject”FORMATETC
为EnumFormatEtc()
. 其中我只返回一个 FORMATETC。
new FORMATETC()
{
cfFormat = CF_HDROP,
ptd = IntPtr.Zero,
dwAspect = DVASPECT.DVASPECT_ICON,
lindex = -1,
tymed = TYMED.TYMED_HGLOBAL
}
On QueryGetData()
,如果格式的 tymed 是TYMED_HGLOBAL
,则返回 S_OK 表示我正在拖动文件。否则返回 DV_E_TYMED 意味着我没有那种类型的数据。
在GetData()
or GetDataHere()
, if format.cfFormat == CF_HDROP
and format.tymed == TYMED.TYMED_HGLOBAL
, 我这样填写medium
:
medium = new STGMEDIUM();
medium.tymed = TYMED.TYMED_HGLOBAL;
medium.unionmember = mem;
medium.pUnkForRelease = IntPtr.Zero;
, 这样mem
分配的内存在哪里DROPFILES
:
IntPtr CreateDropFiles(string[] strFiles)
{
var buffer = new MemoryStream();
var df = new DROPFILES();
IntPtr ipGlobal = IntPtr.Zero;
int bufferLength;
foreach(var file in strFiles)
{
var b = Encoding.Unicode.GetBytes(file);
buffer.Write(b, 0, b.Length);
buffer.WriteByte(0);
buffer.WriteByte(0);
}
buffer.WriteByte(0);
bufferLength = (int)buffer.Length;
// Allocate and get pointer to global memory
int intTotalLen = Marshal.SizeOf(df) + bufferLength;
ipGlobal = Marshal.AllocHGlobal(intTotalLen);
df.pFiles = Marshal.SizeOf(df);
df.fWide = true;
Marshal.StructureToPtr(df, ipGlobal, true);
var ipNew = new IntPtr(ipGlobal.ToInt64() + Marshal.SizeOf(df));
Marshal.Copy(buffer.ToArray(), 0, ipNew, bufferLength);
return ipGlobal;
}
相比之下,使用 WinForm 的方法将文件拖放到文件资源管理器或 VS Code 就可以了,如下所示。
var data = new System.Windows.Forms.DataObject(
System.Windows.Forms.DataFormats.FileDrop,
new string[] { file1, file2 });
dummy.DoDragDrop(data, System.Windows.Forms.DragDropEffects.Copy);
解决方案
推荐阅读
- plot - 可视化以下数据的最佳方法是什么?
- java - TextView 边框不出现
- python - jupyter notebook vs jupyter console:markdown(和latex、html等)对象的显示
- json - 将json读取到pandas DataFrame,但有数千行到pandas append
- sql - 同一记录中的 SQL Server 数据
- python - PyObject* 的“字符串”表示的生命周期
- c# - 如何在运行时显示闪烁的叠加层并再次将其关闭,由视图模型属性控制?
- azure-keyvault - 大厅与 azure key Vault 集成
- r - 在 dplyr 管道命令中应用函数
- excel - EXCEL在排序/使用公式后与单元格内容保持超链接