【问题标题】:cut and paste clipboard exchange between Qt application and Windows Explorer在 Qt 应用程序和 Windows 资源管理器之间剪切和粘贴剪贴板交换
【发布时间】:2017-11-22 20:39:38
【问题描述】:

我有一个简单的文件处理小部件,它可以从剪贴板复制/剪切/粘贴选定的文件。我希望能够在此小部件和 Windows 资源管理器(可能是其他文件管理器,例如 Total Commander 或 Free Commander)之间使用这些命令交换文件。我已经发现我可以使用QMimeData::setUrls() 将文件名作为QList<QUrl> 存储到剪贴板并以类似方式恢复它们。这样我就可以在我的小部件和上述文件管理器之间复制和粘贴,因为它们似乎使用相同的格式来存储文件名。但我不知道如何将项目剪切到剪贴板(即粘贴文件后删除)。我假设接收者(粘贴数据的应用程序)负责删除剪切文件。在这种情况下,它必须以某种方式在剪贴板数据中编码,文件已被剪切而不是复制,接收应用程序可以检索此信息。这是怎么做到的?或者还有其他方法吗?我知道这是可能的,因为这可以在 Windows Explorer 和 Free Commander 之间完美运行。 IE。当您在 Window Explorer 中剪切文件并将其粘贴到 Free Commander 时,原始文件会被删除,反之亦然。

更新: 我发现还有另一部分 MIME 数据"Preferred DropEffect" 的值可以是5(复制)或2(剪切)。当我将QByteArray设置为4个字节,对应一个整数值52时,我可以区分Windows资源管理器是启动剪切还是复制。如果它被剪切,那么我可以移动文件而不是复制。它运作良好。不幸的是,这仍然只有从 Windows Explorer 到 Qt 应用程序的一种方式。我仍然没有找到为什么相反的方向不起作用。还有一些其他的 MIME 数据对我来说很难解码。也许有钥匙。

更新 2: 重现行为的最小代码在这里。确保程序中硬编码的文件存在。尝试运行程序,关闭窗口后打开打开 Windows 资源管理器,转到可以写入的任意文件夹,然后按 Ctrl+V... 然后文件的副本应出现在该目录中,但不会从源目录中删除.下面的程序使用常量 2 表示剪切而不是复制,这意味着原始文件应该消失。

#include <QApplication>
#include <QClipboard>
#include <QDataStream>
#include <QMimeData>
#include <QUrl>
#include <QWidget>

int main(int argc, char *argv[])
{
    QApplication application(argc, argv);

    auto mimeData = new QMimeData;

    // store the URL to files which I want to cut
    QList<QUrl> urls;
    urls.append(QUrl::fromLocalFile("C:/mypath/myfile.txt")); // use your path or make sure this file exist
    mimeData->setUrls(urls);

    // store drop effect indicating whether I want to cut or copy
    int dropEffect = 2; // 2 for cut and 5 for copy
    QByteArray data;
    QDataStream stream(&data, QIODevice::WriteOnly);
    stream << dropEffect;
    mimeData->setData("Preferred DropEffect", data);

    QApplication::clipboard()->setMimeData(mimeData);

    QWidget window;
    window.show();
    return application.exec();
}

另请参阅How to programmatically cut/copy/get files to/from the Windows clipboard in a system standard compliant form?https://msdn.microsoft.com/en-us/library/windows/desktop/bb776904(v=vs.85).aspx#delete_on_paste

【问题讨论】:

  • 为什么是减分?这个问题有什么问题?
  • 我更新了问题以包含一些最少的代码。

标签: c++ windows qt


【解决方案1】:

看来我找到了答案。字节顺序错误,由于某种原因它必须是小字节序(Qt 中的默认顺序是大字节序)。所以示例中的代码应该是:

QByteArray data;
QDataStream stream(&data, QIODevice::WriteOnly);
stream.setByteOrder(QDataStream::LittleEndian);
stream << dropEffect;

通过这种方式,其他文件管理器能够使用复制/剪切和粘贴与我的 Qt 应用程序进行互操作。解码剪贴板内容的反转过程留给读者(这并不难,只需反转将数据编码到剪贴板的操作即可)。当然,还需要处理文件的复制或移动/删除,这是更多的工作,但它很简单。

所以我错了,我实际上是在寻找错误...感谢 scopchanov 强迫我编写最少的代码! :)

【讨论】:

  • :) 我发现 "\x02\x00\x00\x00" 是正确的字节顺序。但是你更快。无论如何,我很高兴它现在正在工作。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-10-11
  • 2017-09-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多