前言
最近部门基于底层云游戏串流方案衍生出一个远程产品,既然是远程产品,定然少不了双向传输文件的功能,在windows操作系统上,相比于对话框这种形式的传文件功能,用复制粘贴快捷键自然是方便很多的,接下来分享一下怎么实现。
技术实现
先讲一下,初期实现(不使用OLE剪贴板):
如图,此过程很简单,但是其中的开发后续过程很复杂而且效果较差。我们需要通过一系列手段获取到要粘贴的目标路径,然后再拷贝文件的过程中需要手动实现界面(包括进度条、当前拷贝文件等),后来我放弃了此种方式。
下面讲利用OLE剪贴板通过COM对象调用资源管理器自动写文件并弹出进度条方式:
如图,我们要完成这个模块,可以省去后面一些步骤,只需要设置好我们的剪贴板就OK。 首先注册好监听事件,触发复制事件后发送给对端文件路径,在对端创建Dataobject(COM)对象,设置好OLE剪贴板需要的文件描述符信息,这样粘贴事件触发后就会回调到我们的处理方法中,我们只需要向对端请求文件数据,然后接收到后写入待读的缓冲区就大功告成。
注意:因为此功能依赖桌面窗口应用程序,所以注册事件以及设置Dataobject(COM)对象需要重新创建一个专门用来处理消息循环的窗口线程去做。
关键接口:
1. 注册监听事件到某个窗口线程:
HMODULE user32 = GetModuleHandle(L"user32.dll");
add_clipboard_format_listener_ =
reinterpret_cast<AddClipboardFormatListenerFn*>(
GetProcAddress(user32, "AddClipboardFormatListener"));
remove_clipboard_format_listener_ =
reinterpret_cast<RemoveClipboardFormatListenerFn*>(
GetProcAddress(user32, "RemoveClipboardFormatListener"));
HWND window_ = CreateWindow(MAKEINTATOM(g_window_class.atom()), NULL, 0, 0, 0,
0, 0, HWND_MESSAGE, 0, g_window_class.instance(), this);
*add_clipboard_format_listener_(window_)
2. 设置OLE剪贴板:
RegisterClipboardFormat(CFSTR_FILEDESCRIPTOR);
RegisterClipboardFormat(CFSTR_FILECONTENTS);
OleSetClipboard
效果图:
使用这种实现方式,不用我们关心粘贴路径、文件或文件夹是否存在等特殊情况以及弹出进度条和异常提示,更重要的是不需要我们去手动写文件。复制粘贴文件的操作和文件传输框自己手动选择文件相比也大大节省了不必要的查找时间。
这里只列举了部分接口,感兴趣的可以去git上下载我的demo程序,里面是本地固定的数据:
地址: GitHub - ZYhappy/clipboardfile
有疑问的朋友可以私信我,因为demo程序在应用到工程中时也解决了不少问题。