背景
由于资源管理器是以普通权限启动,而管理员权限启动的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延时一会去挂载拖拽事件即可