剪贴板中的.xlsx文件不在FileDropList,如何从DataObject获取路径?
解决方法
当剪贴板中的.xlsx文件未被ContainsFileDropList()识别时,可通过以下步骤获取文件路径:
1. 先排查剪贴板支持的所有格式
在代码的Else块中添加遍历逻辑,输出DataObject包含的所有格式,确认可用的文件相关格式:
Dim data = Clipboard.GetDataObject() ' 遍历并输出所有剪贴板格式 For Each format As String In data.GetFormats() Debug.WriteLine($"剪贴板格式: {format}") Next
运行后查看调试窗口,你可能会看到FileNameW(Unicode文件名)、FileDrop或Shell IDList Array等文件相关格式。
2. 根据格式提取文件路径
根据调试输出的格式,选择对应方式提取路径:
情况1:存在FileNameW或FileName格式
直接通过GetData获取并转换为字符串:
If data.GetDataPresent("FileNameW") Then Dim filePath As String = DirectCast(data.GetData("FileNameW"), String) Debug.WriteLine($"文件路径: {filePath}") ElseIf data.GetDataPresent("FileName") Then Dim filePath As String = DirectCast(data.GetData("FileName"), String) Debug.WriteLine($"文件路径: {filePath}") End If
情况2:存在FileDrop格式但ContainsFileDropList()未识别
部分场景下ContainsFileDropList()会误判,但实际FileDrop格式存在,可直接尝试获取:
If data.GetDataPresent(DataFormats.FileDrop) Then Dim files As String() = DirectCast(data.GetData(DataFormats.FileDrop), String()) If files IsNot Nothing AndAlso files.Length > 0 Then Debug.WriteLine($"文件路径: {files(0)}") End If End If
情况3:存在Shell IDList Array格式
从资源管理器复制文件时常会出现该格式,需通过Windows API解析:
' 先在类中声明API函数 <DllImport("shell32.dll", CharSet:=CharSet.Unicode)> Private Shared Function SHGetPathFromIDList(ByVal pidl As IntPtr, ByVal pszPath As StringBuilder) As Boolean End Function <DllImport("shell32.dll")> Private Shared Function ILFree(ByVal pidl As IntPtr) As IntPtr End Function ' 提取路径逻辑 If data.GetDataPresent("Shell IDList Array") Then Dim pidl As IntPtr = DirectCast(data.GetData("Shell IDList Array"), IntPtr) If pidl <> IntPtr.Zero Then Dim sb As New StringBuilder(260) If SHGetPathFromIDList(pidl, sb) Then Debug.WriteLine($"文件路径: {sb.ToString()}") End If ILFree(pidl) End If End If
修改后的完整代码
Private Sub btnImport_Click(sender As Object, e As RoutedEventArgs) Handles btnImport.Click Try Debug.WriteLine(".....") If Clipboard.ContainsFileDropList() Then Dim filesArray = Clipboard.GetFileDropList() Debug.WriteLine(String.Join(", ", filesArray.Cast(Of String))) ElseIf Clipboard.ContainsText() Then Dim fileName = Clipboard.GetText() Debug.WriteLine(fileName) ElseIf Clipboard.ContainsImage() Then Debug.WriteLine("Image") Else Dim data = Clipboard.GetDataObject() ' 输出所有剪贴板格式 For Each format As String In data.GetFormats() Debug.WriteLine($"剪贴板格式: {format}") Next ' 从FileNameW提取路径 If data.GetDataPresent("FileNameW") Then Dim filePath As String = DirectCast(data.GetData("FileNameW"), String) Debug.WriteLine($"从FileNameW获取的路径: {filePath}") End If ' 从FileDrop提取路径 If data.GetDataPresent(DataFormats.FileDrop) Then Dim files As String() = DirectCast(data.GetData(DataFormats.FileDrop), String()) If files IsNot Nothing AndAlso files.Length > 0 Then Debug.WriteLine($"从FileDrop获取的路径: {files(0)}") End If End If ' 从Shell IDList Array提取路径 If data.GetDataPresent("Shell IDList Array") Then Dim pidl As IntPtr = DirectCast(data.GetData("Shell IDList Array"), IntPtr) If pidl <> IntPtr.Zero Then Dim sb As New StringBuilder(260) If SHGetPathFromIDList(pidl, sb) Then Debug.WriteLine($"从Shell IDList获取的路径: {sb.ToString()}") End If ILFree(pidl) End If End If End If Catch ex As Exception Exceptions.LogAndShow(ex) End Try End Sub ' API函数声明 <DllImport("shell32.dll", CharSet:=CharSet.Unicode)> Private Shared Function SHGetPathFromIDList(ByVal pidl As IntPtr, ByVal pszPath As StringBuilder) As Boolean End Function <DllImport("shell32.dll")> Private Shared Function ILFree(ByVal pidl As IntPtr) As IntPtr End Function
内容的提问来源于stack exchange,提问作者Jim
相关产品推荐
相关产品推荐

