1

我正在尝试从剪贴板中获取复制文件的列表。我很清楚 WPF 对此有内置方法,但使用 API 对我来说很重要,因为 WPF 的剪贴板实现是错误的,正如 Web 上的许多地方所描述的那样。

到目前为止,我正在使用GetClipboardData返回指向内存中所需数据的指针的函数。现在,为了枚举这些数据,我发现我需要DragQueryFile在 Windows 中使用 API。

我的DragQueryFileAPI 声明如下。

[DllImport("shell32.dll", CharSet = CharSet.Auto)]
private static extern int DragQueryFile(IntPtr hDrop, int iFile, StringBuilder lpszFile, int cch);

我的GetClipboardDataAPI 声明如下。

[DllImport("user32.dll")]
static extern IntPtr GetClipboardData(uint uFormat);

现在,如果您查看DragQueryFile API 的文档,它会清楚地说明函数中的参数如下:

iFile:要查询的文件的索引。如果此参数的值为 0xFFFFFFFF,则 DragQueryFile 返回已删除文件的计数。如果此参数的值介于零和删除的文件总数之间,则 DragQueryFile 将具有相应值的文件名复制到 lpszFile 参数指向的缓冲区。

我已经使用了这些信息,并编写了这段代码(您可以复制粘贴它,它也应该在您的端运行)。

var dummyFiles = new StringCollection();
dummyFiles.Add(Path.GetTempFileName());
dummyFiles.Add(Path.GetTempFileName());

Clipboard.Clear();
Clipboard.SetFileDropList(dummyFiles);

var dataPointer = GetClipboardData(15); //15 is for CF_HDROP datatype - this does in fact return a pointer, so it's working fine
var fileCount = DragQueryFile(dataPointer, -1, null, 0);

在上面的例子fileCount0,虽然我只是在剪贴板中添加了 2 个文件,但我可以通过Clipboard.GetFileDropListWPF 中的函数来获取它们。我还检查了格式 15 (CF_HDROP) 是否确实在剪贴板中,并且确实如此。

4

1 回答 1

1

我必须调用 OpenClipboard(因此我也调用了 CloseClipboard)才能从 Win7 x64 上的 GetclipboardData 获取返回值。

我添加了

[DllImport("user32.dll", SetLastError = true)]
static extern bool OpenClipboard(IntPtr hWndNewOwner);

[DllImport("user32.dll", SetLastError = true)]
static extern bool CloseClipboard();

并更改了 DragQueryFile 以匹配我在 pinvoke.net 上找到的内容(uint 而不是 int)

[DllImport("shell32.dll", CharSet = CharSet.Auto)]
private static extern int DragQueryFile(IntPtr hDrop, uint iFile, StringBuilder lpszFile, int cch);

并使用

    var dummyFiles = new StringCollection();
    dummyFiles.Add(Path.GetTempFileName());
    dummyFiles.Add(Path.GetTempFileName());

    Clipboard.Clear();
    Clipboard.SetFileDropList(dummyFiles);   

    OpenClipboard(IntPtr.Zero);

    IntPtr hDrop = GetClipboardData(15);

    var count = DragQueryFile(hDrop, uint.MaxValue, null, 0);

    // etc.

    CloseClipboard();

为我工作(计数= 2)。

于 2012-07-25T23:27:49.317 回答