DragQueryFile returns 0 when I try to get file cou

2019-07-30 04:33发布

问题:

I am trying to fetch a list of copied files from the clipboard. I am well-aware that WPF has inbuilt methods for this, but it is important for me to use the API, since WPF's implementation of the clipboard is buggy, as described many places on the web.

So far I am using the GetClipboardData function which returns a pointer to the data I need in the memory. Now, to enumerate through this data, I figured out that I need to use the DragQueryFile API in Windows.

My DragQueryFile API is declared as follows.

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

And my GetClipboardData API is declared as follows.

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

Now, if you take a look at the documentation for the DragQueryFile API, it clearly states the following about the arguments in the function:

iFile: Index of the file to query. If the value of this parameter is 0xFFFFFFFF, DragQueryFile returns a count of the files dropped. If the value of this parameter is between zero and the total number of files dropped, DragQueryFile copies the file name with the corresponding value to the buffer pointed to by the lpszFile parameter.

I have used this information, and have composed this piece of code (you may copy-paste it, and it should run on your end too).

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);

In the above example, fileCount is always 0, although I just added 2 files to the clipboard, and that I can fetch them through the Clipboard.GetFileDropList function in WPF just fine. I also checked if format 15 (CF_HDROP) is indeed in the clipboard, and it is.

回答1:

I had to call OpenClipboard (and therefore I also called CloseClipboard) in order to even get a return value from GetclipboardData on win7 x64.

I added

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

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

and changed the DragQueryFile to match what I found on pinvoke.net (uint instead of int)

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

and using

    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();

worked (count = 2) for me.



标签: c# wpf clipboard