遇到问题
在使用Electron开发IM应用时,难免会遇到拷贝多文件并发送的需求,那么要怎样去实现呢?
打开Electron的文档[剪贴板 | Electron (electronjs.org)](https://www.electronjs.org/docs/api/clipboard)
,看一看吧!
文档中提供了 readText
、writeText
、readImage
、writeImage
...... 等等方法。呃,不过好像没有解决这个需求。😵
那要怎么办呢? 这时候就要就要找出昔日的朋友陈佳佳(C++)了
拿到剪帖板中文件的路径
打开/关闭 剪贴板
剪切板相关操作文档: 剪贴板函数 - Win32 apps | Microsoft Docs
BOOL OpenClipboard( HWND hWndNewOwner ); // 打开剪贴板
HANDLE GetClipboardData( UINT uFormat ); // 获取数据句柄
BOOL CloseClipboard(); // 关闭剪贴板
获取剪贴板中文件数量
shellapi.h
文档: DragQueryFileA function (shellapi.h) - Win32 apps | Microsoft Docs
UINT DragQueryFileA(
HDROP hDrop,
UINT iFile,
LPSTR lpszFile,
UINT cch
);
对 iFile
字段的说明如下
Index of the file to query. If the value of this parameter is 0xFFFFFFFF,
DragQueryFile
returns a count of the files dropped.
也就是说 iFile
的值设置为 0xFFFFFFFF
即可返回文件的数量
连同将数据句柄一起传入即可拿到文件的数量,如下代码
HDROP hDrop = (HDROP)::GetClipboardData(CF_HDROP); // 获取数据句柄
if (hDrop) {
UINT fileCount = ::DragQueryFile(hDrop, 0xFFFFFFFF, NULL, 0); // 获取剪贴板中文件数量
cout<<'The File in clipboard Number is: '<<fileCount<<endl;
}
获取剪贴板文件路径
对 iFile
字段的说明的后半句如下
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 thelpszFile
parameter.
也就是说 iFile
的值如果为 0 - fileCount
之间的话,返回的是被拷贝的文件的名称。
即得到如下代码:
char filePath[MAX_PATH + 1] = { 0 }; // 文件路径数组
for (UINT i = 0; i < fileCount; i++)
{
memset(filePath, 0, MAX_PATH + 1); // 清空数组
DragQueryFile(hDrop, i, filePath, MAX_PATH); // 往数组写入文件名
cout<<filePath<<endl;
}
注: MAX_PATH 为最长路径名的宏定义,定义如下 #define MAX_PATH 260
至此基本功能都实现了,代码如下,我们跑一下吧
运行结果准确
拿到文件路径后就可以交给NodeJS
的fs
模块操作了
生成 .node 文件
我们参考better-sqlite3
的源码将该项目命名为better-clipboard
,并编译生成 better_clipboard.node
。
项目路径为 simo-an/better-clipboard: A better clipboard for Electron (NodeJS). (github.com)
注: 生成过程参考 C++ 插件 | Node.js API 文档 (nodejs.cn)
安装构建better-clipboard
在你的Electron项目中安装并重新构建better_clipboard.node
npm i better-clipboard
electron-rebuild -f -w better-clipboard
如果你使用Webpack
,请添加如下代码 Help me use Electron! · Issue #126 · JoshuaWise/better-sqlite3 (github.com)
config.externals = {
'better-clipboard': 'commonjs better-clipboard'
}
注: 遇到构建的问题可参考better-sqlite3
中的解决方案,或者给我提issue
使用 better-clipboard
我在 better_clipboard.node
的基础上再次做了拓展,可以直接拿到剪贴板中的File
或者Buffer
代码参考: better-clipboard/better-clipboard.ts at master · simo-an/better-clipboard (github.com)
使用方法
import { betterClipboard } from 'better-clipboard';
betterClipboard.readFilePathList(); // get the path of file which in clipboard
betterClipboard.readBufferList();
betterClipboard.readFileList();
betterClipboard.writeFileList([]); // write file into clipboard via file path
看一下我这边在 ng-electron 中的测试结果吧
分别使用Electron
自带的剪贴板和better-clipboard
来做个比较
可见better-clipboard
出色的完成了任务。😁
更详细的代码,构建过程欢迎访问 better-clipboard: A better clipboard for Electron (NodeJS),同样欢迎star
和fork
。😁