桌面摸鱼神器(PyQt5 伪装悬浮窗 + 网页拖放 + 老板键)
> 一句话定位:一个始终置顶、可拖动的"假 Office"窗口,里面其实是浏览器(QWebEngineView)。把网页/链接拖进去就在 Excel/Word 外壳里显示;老板来了按老板键隐身。
一、适用场景(触发)
- 用户要"摸鱼神器""伪装成 Excel/Word""桌面挂网页""老板键隐藏""拖拽网页进窗口"。
- 用户要 PyQt5 + PyInstaller 打包成单文件 exe 并能直接运行。
- 用户遇到"拖进去不显示网页""切换伪装后白屏/崩溃"等具体坑。
二、核心功能清单
- 黑色启动弹窗 → 点击「开启」→ 生成伪装成 Excel 的置顶可拖动悬浮窗。
- 拖拽浏览器链接 / 选中网页内容进窗口 → 自动在表格/文档框内加载显示。
- 一键切换伪装:Excel·销售数据报表 / Excel·财务对账表 / Word·项目进度文档 / Word·季度工作总结。
- 智能隐藏:鼠标移出窗口 3 秒 → 缩成右下角小图标;悬停小图标 → 恢复。
- 全局老板键:默认
Ctrl+Alt+X隐身(连托盘一起藏)、Ctrl+Alt+Q完全退出;可在设置里改。 - 自定义:文档标题、隐身延时、老板键、默认伪装方案,配置存
%APPDATA%/FishTool/config.json。
三、环境准备
# 在隔离 venv 中安装(不要污染系统 Python)
python -m venv fish_tool_venv
fish_tool_venv/Scripts/python -m pip install PyQt5 PyQtWebEngine pyinstaller
> 已在 Python 3.13 上验证:PyQt5 5.15.11 + PyQtWebEngine 5.15.7 + PyInstaller 6.x 可用。
四、文件结构(本 skill 自带可直接复用的源码)
| 文件 | 职责 |
|---|---|
main.py |
入口:黑色启动弹窗、点击开启、整合托盘与老板键 |
themes.py |
伪装主题(Excel/Word 外观 + 开箱即用的假表格/假文档 HTML) |
config.py |
配置读写(伪装方案、隐身延时、老板键、标题覆盖) |
hotkeys.py |
Windows 全局老板键(ctypes 低级键盘钩子 WH_KEYBOARD_LL) |
disguise_window.py |
核心:无边框置顶悬浮窗、伪装外壳、拖放、智能隐藏、托盘、设置 |
build.bat |
一键打包成 exe |
五、关键实现要点
- 置顶 + 可拖动 + 无边框:窗口用
FramelessWindowHint | WindowStaysOnTopHint | Tool;标题栏mousePressEvent/MoveEvent里move()实现拖动。 - 伪装外壳:标题栏 + 功能区(装饰性标签/分组)+ (Excel)列/行表头网格 或(Word)标尺+白页;中间放
QWebEngineView。 - 拖放(最容易踩坑,见第六节):在
QWebEngineView上安装eventFilter,拦截DragEnter/DragMove/Drop,自行load/setHtml,并return True阻止浏览器默认导航式拖放。 - 老板键:
SetWindowsHookExW(WH_KEYBOARD_LL)钩子线程;匹配组合键时return 1吞键,并回调隐身/退出。跨窗口生效(即使窗口隐藏也能恢复)。 - 智能隐藏:
QTimer每 200ms 检查QCursor.pos()是否在geometry()内;连续移出 ≥ 延时 → 隐藏窗口并显示迷你图标;迷你图标enterEvent→ 恢复。 - 配置:JSON 存于
%APPDATA%/FishTool/config.json,含title_overrides(按主题名存自定义标题)。
六、两个高频坑(必看)
- 拖进去不显示网页:
QWebEngineView内部会吞掉 drop,父控件收不到事件。错误写法:只给父控件setAcceptDrops(True)并指望它收到 drop。正确做法:
python self.web.setAcceptDrops(True) self.web.installEventFilter(self) # eventFilter 里对 DragEnter/DragMove/Drop 调用 acceptProposedAction() 并 return True - 切换伪装后白屏/崩溃:
build()用takeAt().widget().deleteLater()删旧框架时,会把复用的self.web一起删掉。切换主题再addWidget(self.web)就指向已销毁对象。正确做法:删除前先self.web.setParent(None)脱离旧框架,重建后再加入。
七、打包成 exe(单文件,可直接运行)
用 build.bat(等价于下面的命令),输出 dist/摸鱼神器.exe:
python -m PyInstaller --noconfirm --windowed --onefile --name "摸鱼神器" ^
--hidden-import PyQt5.QtWebEngineWidgets ^
--hidden-import PyQt5.QtWebEngineCore ^
--hidden-import PyQt5.QtWebEngine ^
--collect-all PyQt5 ^
--distpath dist --workpath build main.py
--windowed:无控制台黑窗;--collect-all PyQt5:把 Qt/WebEngine 运行时(含QtWebEngineProcess.exe、资源、翻译)一并打进包,否则网页渲染会失败。- 打包后建议无头冒烟:
QT_QPA_PLATFORM=offscreen 摸鱼神器.exe跑几秒,确认%TEMP%/_MEI*/PyQt5/Qt5/bin/QtWebEngineProcess.exe被释放。 - 注意:PyInstaller 打包的 exe 常被 Windows Defender 误报,首次运行需加白名单。
八、自定义扩展建议
- 加更多伪装方案:在
themes.py的THEMES列表追加Theme(...)。 - 真实表格样式:把
fake_html换成你公司真实的 Excel 模板截图/HTML 风格。 - 多标签页同时挂多个网页、窗口贴边自动隐藏、老板键改成一个热的组合等,都可在
disguise_window.py扩展。 - 界面仅做 Office 风格"近似还原",不含任何厂商商标/受版权保护的素材,请勿用于冒充或商业场景。