C++ Qt如何防止将项目从应用程序拖放到Windows文件资源管理器

C++ Qt如何防止将项目从应用程序拖放到Windows文件资源管理器,c++,qt,drag-and-drop,C++,Qt,Drag And Drop,我正在寻找一种干净且跨平台的方法,以防止将一个项目从Qt应用程序拖到Windows文件资源管理器(或其他等效操作系统) 下图显示了所需的行为: 我没有幸在网上找到例子或一起破解一个作品,但似乎这将是一个足够普遍的用例,有一个设计和实现良好的解决方案 我尝试过但没有成功的方法: 检测阻力并消除阻力: 正在检测QDragEnterEvent、QDRAGOVEREVENT、QDRAGLEAVEVENT 将事件的answerRect()或pos()与 用于检测拖动是否离开应用程序的窗口或小部件 这是

我正在寻找一种干净且跨平台的方法,以防止将一个项目从Qt应用程序拖到Windows文件资源管理器(或其他等效操作系统)

下图显示了所需的行为:

我没有幸在网上找到例子或一起破解一个作品,但似乎这将是一个足够普遍的用例,有一个设计和实现良好的解决方案

我尝试过但没有成功的方法:

  • 检测阻力并消除阻力:

  • 正在检测QDragEnterEvent、QDRAGOVEREVENT、QDRAGLEAVEVENT
  • 将事件的answerRect()或pos()与 用于检测拖动是否离开应用程序的窗口或小部件
  • 这是一个非常复杂的问题(目前还不起作用),我希望你们能给我一个更优雅的解决方案

(更新-尝试更改mimeType,但Windows文件资源管理器仍接受删除)

  • 将MIME类型更改为自定义类型:

  • 前置:上图中的“带拖放的小部件”是一个
    QTreeView
    ,带有
    QFileSystemModel
    模型
  • QFileSystemModel
    进行子分类,并覆盖
    mimeTypes()
    函数,如下面的代码所示
  • qDebug()
    输出中,似乎正确设置了mimeType,但Windows文件资源管理器仍接受删除:/
QStringList MyFileSystemModel::mimeTypes()常量
{  
QStringList自定义类型;

customMimeTypesDmitry Sazonov给出了正确的答案。我将在下面解释我是如何实现它的。Dmitry,如果您想要cred,请将其作为答案而不是评论发布,以便我可以接受它作为答案

在基于Dmitry建议的问题更新中,我犯的错误是覆盖了
QFileSystemModel::mimeTypes()
,而实际上,我不得不修改
QTreeView::mouseMoveEvent()
QTreeView::dropEvent()

//---------------------------------------------------------
void MyTreeView::mouseMoveEvent(QMouseEvent*事件)
{
if(!(事件->按钮()&Qt::LeftButton))
{
return;//我们现在只关心鼠标左键拖动
}
如果((事件->位置()-dragStartPosition).manhattanLength()getSelectedPaths();//自定义帮助程序方法
foreach(QString路径,SelectedPath)
{
data.append(path).append(;“”;//使用“;”作为路径删除器
}
数据。印章(1);
//---这将设置自定义MIME类型筛选器
mimeData->setData(自定义\u MIMETYPE\u字符串,数据);
拖动->设置mimeData(mimeData);
Qt::DropAction DropAction=拖动->执行(Qt::CopyAction);
}
//---------------------------------------------------------
void MyTreeView::dropEvent(QDropEvent*事件)
{
// ...
QList路径;
//---这个过滤器基于我们的自定义MIME类型
路径=事件->mimeData()->数据(自定义MIMETYPE_字符串)。拆分(“;”);
foreach(QByteArray路径,路径)
{
//对文件路径执行一些操作
}
}

只需将mime类型填充到任何自定义字符串。在检查了
dropEvent
上的
mimeType
之后,我发现我的上述实现没有正确设置
mimeType
。我目前从中获得了一些用于我的用例的代码,并将在清理代码后发布。谢谢Dmitry!:)还请注意愚蠢的“Widget Container Moat”不应该被使用,因为正确的解决方案是使用自定义MIME类型。我尝试了这个方法,但现在我无法在自己的应用程序中删除数据,我必须在任何地方注册这个自定义MIME类型吗?
QStringList MyFileSystemModel::mimeTypes() const  
{  
    QStringList customMimeTypes;  
    customMimeTypes << QString("UnicornsAndRainbows/uri-list");  
    qDebug() << "customMimeTypes: " << customMimeTypes;
    return customMimeTypes;  
}  
//---------------------------------------------------------
void MyTreeView::mouseMoveEvent( QMouseEvent *event )
{
    if( !(event->buttons() & Qt::LeftButton) )
    {
        return; // we only care about left mouse drags at the moment
    }

    if( (event->pos() - dragStartPosition).manhattanLength() < QApplication::startDragDistance() )
    {
        return; // a buffer when calculating waht qualifies as a "drag event"
    }

    QDrag *drag = new QDrag( this );
    QMimeData *mimeData = new QMimeData();
    QByteArray data;
    const QStringList selectedPaths = this->getSelectedPaths(); // custom helper method

    foreach( QString path, selectedPaths )
    {
        data.append( path ).append( ";" ); // using ';' as path deliminator
    }
    data.chop( 1 );

    //--- this sets the custom MIME Type filter 
    mimeData->setData( CUSTOM_MIMETYPE_STRING, data );

    drag->setMimeData( mimeData );

    Qt::DropAction dropAction = drag->exec( Qt::CopyAction );
}


//---------------------------------------------------------
void MyTreeView::dropEvent( QDropEvent *event )
{
    // ...

    QList<QByteArray> paths;

    //--- this filters based on our custom MIME Type
    paths = event->mimeData()->data( CUSTOM_MIMETYPE_STRING ).split(';');

    foreach( QByteArray path, paths )
    {
        // do something with the file paths
    }
}