管理员权限下QT进程无法接受拖拽问题

2024-06-08 15:22:37 浏览数 (1)

背景

由于资源管理器是以普通权限启动,而管理员权限启动的qt进程,权限较高导致qt的setAcceptDrops(true)后依然无法触发dropEvent,导致无法接受其它程序或者资源管理器拖拽过来的文件。

解决思路

通过windows原生的事件过滤器来解决,屏蔽掉qt自带的拖拽事件过滤器,创建主窗口后启动原生事件过滤

代码语言:C 复制
void EnableDrag(QMainWindow& w) {
    ChangeWindowMessageFilter(WM_DROPFILES, 1);

    w.winId() << w.effectiveWinId();
    ChangeWindowMessageFilterEx((HWND)w.effectiveWinId(), WM_DROPFILES, MSGFLT_ALLOW, NULL);
    ChangeWindowMessageFilterEx((HWND)w.effectiveWinId(), WM_COPYDATA, MSGFLT_ALLOW, NULL);
    ChangeWindowMessageFilterEx((HWND)w.effectiveWinId(), 0x0049, MSGFLT_ALLOW, NULL);

    DragAcceptFiles((HWND)w.effectiveWinId(), true);
    RevokeDragDrop((HWND)w.winId());
}

{
  QMainWindow w;
  EnableDrag(w);
  w.setAcceptDrops(true);
  w.show();
  a.exec();
}

此时窗口已经可以接受拖拽了,重载主窗口的nativeEvent即可

代码语言:C 复制
bool QMainWindow::nativeEvent(const QByteArray& eventType, void* message, long* result) {
    if (eventType == "windows_generic_MSG" || eventType == "windows_dispatcher_MSG") {
        MSG* pMsg = reinterpret_cast<MSG*>(message);
        if (pMsg->message == WM_DROPFILES) {
            HDROP hDropInfo = (HDROP)pMsg->wParam;
            wchar_t szFilePathName[_MAX_PATH] = { 0 };
            const UINT nNumOfFiles = DragQueryFile(hDropInfo, 0xFFFFFFFF, NULL, 0);
            if (nNumOfFiles > 0) {
                // DragQueryFile第二个参数为拖入文件的索引
                DragQueryFile(hDropInfo, 0, szFilePathName, _MAX_PATH); //直接取第一个 入参UINT iFile  = 0
                const QString currentfile = QString::fromWCharArray(szFilePathName);
                // currentfile 为当前拖拽文件
                // OnDragFinished(currentfile);
            }
            DragFinish(hDropInfo);
        }
    }
    return false;
}

注意:

1、这里winId()拿到的窗口id可能无效,导致拖拽事件未挂载成功,可以使用QTimer延时一会去挂载拖拽事件即可

0 人点赞