新增: 资源管理器文件粘贴到文件列表
- 后端 ReadClipboardFiles 读系统剪贴板 CF_HDROP 拿路径列表 - Ctrl+V 优先粘贴系统剪贴板文件,复用拖入导入链路(SFTP 上传/本机复制/目录递归) - 补齐设计文档记录的历史缺口(Wails 限制未做)
This commit is contained in:
@@ -0,0 +1,71 @@
|
||||
//go:build windows
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"runtime"
|
||||
"syscall"
|
||||
"time"
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
var (
|
||||
procIsClipboardFormatAvailable = windows.NewLazySystemDLL("user32.dll").NewProc("IsClipboardFormatAvailable")
|
||||
procOpenClipboard = windows.NewLazySystemDLL("user32.dll").NewProc("OpenClipboard")
|
||||
procCloseClipboard = windows.NewLazySystemDLL("user32.dll").NewProc("CloseClipboard")
|
||||
procGetClipboardData = windows.NewLazySystemDLL("user32.dll").NewProc("GetClipboardData")
|
||||
procDragQueryFileW = windows.NewLazySystemDLL("shell32.dll").NewProc("DragQueryFileW")
|
||||
)
|
||||
|
||||
// cfHDrop 剪贴板文件列表格式(资源管理器复制文件/文件夹),Win32 稳定 ABI 值
|
||||
const cfHDrop = 15
|
||||
|
||||
// ReadClipboardFiles 读取系统剪贴板中的文件/文件夹路径列表。
|
||||
// 剪贴板为文本/截图等非文件内容时返回空列表,前端据此回落图片粘贴等原有链路。
|
||||
func (a *App) ReadClipboardFiles() ([]string, error) {
|
||||
// OpenClipboard 与 CloseClipboard 必须同线程,否则剪贴板死锁
|
||||
runtime.LockOSThread()
|
||||
defer runtime.UnlockOSThread()
|
||||
|
||||
if r, _, _ := procIsClipboardFormatAvailable.Call(cfHDrop); r == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// 剪贴板是全局互斥资源,短重试避开其他进程的瞬时占用
|
||||
opened := false
|
||||
for i := 0; i < 20; i++ {
|
||||
if r, _, _ := procOpenClipboard.Call(0); r != 0 {
|
||||
opened = true
|
||||
break
|
||||
}
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
}
|
||||
if !opened {
|
||||
return nil, syscall.EBUSY
|
||||
}
|
||||
defer procCloseClipboard.Call()
|
||||
|
||||
h, _, _ := procGetClipboardData.Call(cfHDrop)
|
||||
if h == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
count, _, _ := procDragQueryFileW.Call(h, 0xFFFFFFFF, 0, 0)
|
||||
if count == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
paths := make([]string, 0, count)
|
||||
for i := uintptr(0); i < count; i++ {
|
||||
n, _, _ := procDragQueryFileW.Call(h, i, 0, 0)
|
||||
if n == 0 {
|
||||
continue
|
||||
}
|
||||
buf := make([]uint16, n+1)
|
||||
procDragQueryFileW.Call(h, i, uintptr(unsafe.Pointer(&buf[0])), n+1)
|
||||
paths = append(paths, syscall.UTF16ToString(buf))
|
||||
}
|
||||
return paths, nil
|
||||
}
|
||||
Reference in New Issue
Block a user