dsh-print-screen
方便大家直接截屏的提示词框快捷按钮。拉完范围框后直接截屏。自动隐藏dsh,支持多屏幕。Ctrl+Alt+1--隐藏窗口截屏;shift+点击按钮--不隐藏窗口;按住Ctrl+Alt后点击1,反复截屏。!默认以哈希值名称保存1份在DSH附件库,各会话生成索引记录图片归属(可修改为多备份一份至会话文件夹)。图片属于上下文,删除会导致会话错误,须用“删除会话”插件让图片与会话一并删除。仅 Windows。
安装
dsh plugin --profile web add dsh-print-screen
沙箱测试结果
| 阶段 | 结果 |
|---|---|
| 1 安装 | ✓ |
| 2 列装 | ✓ |
| 3 挂载 | ✓ |
| 4 启动 | — |
四阶段在隔离沙箱里跑:安装(有网)→ 列装 → 挂载 → 启动(后三步断网)。
README
dsh-Print Screen
[English](README.en.md) | 中文
dsh-print-screen 给 DSH 桌面版的输入框加一个剪刀按钮:点一下把整个虚拟桌面(所有显示器)按原位置、原像素冻结,在画面上拖一个矩形,松手后把该区域作为图片附件插入当前提示词框。截图只存一份,放在 DSH 附件库里(按内容哈希命名),不会复制到工作区。仅 Windows。
输入框左下角: [+] [✂] [工作区内修改] [计划]
│
└─ 点剪刀 → 屏幕冻结(原位、原大小)→ 拖框 → 松手 → 缩略图进输入框
功能
- 一个剪刀按钮:和普通的输入框按钮一样——透明背景、只有图标,不占额外宽度。
- 冻结屏幕再拉框:整块虚拟桌面(所有显示器)冻结,每张画面保持原位、保持原始像素大小;松手即裁剪并插入。
- 默认隐藏 DSH:截图前先隐藏 DSH 窗口,截完立即还原(最大化状态也还原),因此能截到被它挡住的窗口。
- 不隐藏的两种方式:按住
Shift点剪刀,或按Ctrl+Shift+Alt+1。 - 插入提示词框:走会话自己的附件 API,缩略图出现在输入框下方,回车随消息发出;失败时退回合成粘贴事件,再不行就复制到剪贴板并提示
Ctrl+V。 - 文件名带时间戳:附件名是
screenshot-2026-10-26_22-31-05.png(本地时间,精确到秒),多张截图不会重名。 - 只存一份,不重复占空间:图片以内容哈希命名,存在 DSH 附件库(
~/.dsh/attachments),工作区里不产生副本;同一张图传两次也只存一份。 - 按会话记账(只在图片真进了消息之后):截图成功但没插进输入框(放弃、插入失败、只落到剪贴板)时不记账,所以
screenshots.json里的每一条都对应一条看得见的附件。每条记录含时间、文件名、sha256、尺寸、会话 id/标题、via(attached=走官方附件通道,pasted=走合成粘贴事件),以及object——它只在附件库文件真的存在时才写路径,否则是null,不会让你拿着一个不存在的路径去反查。 - 可选额外备份:把
client.js里的SAVE_TO_SESSION改成true,会在会话文件夹里再存一份同名 png(代价是每张图占双份空间)。
交互一览
操作 · 行为
单击剪刀 · 截屏,先隐藏 DSH 窗口
Shift + 单击剪刀 · 截屏,不隐藏 DSH(可以连它一起截)
Ctrl+Alt+1 · 同单击:截屏并隐藏 DSH
Ctrl+Shift+Alt+1 · 截屏但不隐藏 DSH
拖框 → 松手 · 裁剪、插入当前输入框,并在 screenshots.json 记一笔(DSH 窗口在裁剪完立即还原)
Esc / 右键 · 取消
快捷键用物理键位判断(event.code),Shift+1打出!的布局也能触发;!本身不做兼容。
速度
每次截图不再重新起 powershell.exe(那要付约 1.2 秒的进程启动 + 程序集加载,火绒还会再扫一遍)。改成 DSH 启动后 2.5 秒(避开启动高峰)在后台拉起一个常驻截图助手 helper.ps1,WinForms / DPI / P-Invoke / 位图缓冲只初始化一次,之后每次只需要:
阶段 · 耗时(实测)
助手启动(每次 DSH 启动只一次,后台) · ~1.4s
点击 → 冻结画面出现(热态) · ~0.15s(关掉该窗口的 DWM 过渡后 SW_HIDE 瞬时生效,只等 30ms;画面用 BitBlt 直贴,首次绘制 ~40ms)
第一次请求(含首次绘制 JIT) · ~0.3s
拖框 → 返回裁剪图 · 保存约 0.02s + 传输/插入
具体做法:截图走 BitBlt 直接拷进常驻的 DIB(比 GDI+ 逐屏 CopyFromScreen 快 30–40ms);隐藏 DSH 用瞬时的 SW_HIDE(SW_MINIMIZE 有 150–250ms 动画);窗体、画笔字体、位图缓冲全部跨请求复用,整套流程只有 helper.ps1 一个实现。
助手起不来或中途挂掉时,宿主会自动重启它再试一次,而不是维护第二套截图脚本。
环境要求
项目 · 要求
DSH · >= 0.2.1-rc.3(engines.dsh)
系统 · 仅 Windows(10/11,需要系统自带的 Windows PowerShell 5.1 + System.Drawing/WinForms)
其它 · 无 Node 原生模块、无外部服务、无 API Key
安装
# 从 npm 安装 dsh plugin --profile web add dsh-print-screen # 或直接从 GitHub 源码安装 dsh plugin --profile web add github:zrrrrrrr77/dsh-print-screen
也可以在 DSH 里打开 插件 → 发现,用插件市场安装。
装完在输入框左侧、「工作区内修改」左边就能看到剪刀;看不到就刷新页面,必要时完全退出 DSH 再打开(宿主半边要重启才加载)。
dsh plugin --profile web里的web换成你自己的 profile 名;DSH 桌面版的 profile 由应用管理,建议直接在应用内的插件页安装。
实现要点
- DPI 是关键:截图脚本必须声明 Per-Monitor V2 DPI 感知。不声明时 Windows 会把进程按 250% 虚拟化,冻结画面被整体放大 2.5 倍——用户看到的就是「屏幕被放大、不是原样」。声明后所有坐标都是物理像素,显示与鼠标位置 1:1。
- 抓图用
BitBlt逐屏直拷进常驻的 DIB(比 GDI+CopyFromScreen快 30–40ms),屏幕尺寸变了才重建缓冲。冻结窗口也在Paint里用BitBlt直接把 DIB 贴到窗口 DC,而不是BackgroundImage——后者整屏首次绘制要 ~500ms,拖框时会明显卡住。 - 隐藏 DSH 前先
DwmSetWindowAttribute(hwnd, DWMWA_TRANSITIONS_FORCEDISABLED, TRUE)关掉这个窗口的 DWM 过渡,SW_HIDE就变成瞬时的;再等 30ms 让合成器出一帧,然后抓屏(不关过渡时窗口会渐隐 ~200ms,40ms 抓到的还是半透明残影)。窗口匹配取两条线索的并集:进程名是DeepSeek Harness的所有可见顶层窗口,以及标题以DeepSeek Harness结尾的窗口——实测 DSH 主窗口的宿主进程未必叫这个名字,只按进程名会一个窗口都匹配不到,DSH 就留在冻结画面里。截完按各自原状态SW_SHOW/SW_SHOWMAXIMIZED还原。 - 隐藏后再检查一次:如果仍有窗口可见(隐藏没生效),就把它的矩形从冻结画面里涂掉,保证截图里永远不会出现 DSH。
- 隐藏/还原的窗口列表用
ArrayList以参数传入(Get-TargetWindows -Into),不让函数直接return集合——PowerShell 会把单元素集合展开成单个对象,只匹配到主窗口时还原逻辑会整段失效(表现为截图后 DSH 停在任务栏、必须手点图标)。还原后还会SwitchToThisWindow+SetForegroundWindow把主窗口切回前台。 - 框选区域不压暗、不画阴影,只描一圈清晰的双色边框(外黑内蓝),任何背景下都能看清边界。
- DSH 桌面版的 Host 是独立的 node 进程,没有
desktopCapturer,渲染层又被contextIsolation隔离且禁用 display media,所以「冻结 + 拉框」交给随包发布的helper.ps1完成。 - 插入图片的三条通道:
ctx.get('conversation').createDrafts()+inputActions.addAttachments()→ 合成 Lexicalpaste事件 → 剪贴板兜底。 - 落盘:截图先在临时目录收尾,插入后由 DSH 自己的附件通道写入附件库(内容哈希命名、自动去重)。宿主同时算一遍 sha256,把
{时间, 文件名, 哈希, 尺寸, 会话 id/标题, 对象绝对路径}追加到会话目录的screenshots.json,用来说明“这张图属于哪个对话”;写不进去不影响截图。
隐私与安全
- 截图只在本机流转:宿主进程调用
powershell.exe起一个 WinForms 全屏窗口,画面只在内存里;选完的裁剪结果交给 DSH 附件库保存,临时目录里的中转文件读回浏览器后立即删除。插件没有网络请求。 - 插件会以你的用户权限执行
powershell.exe -File helper.ps1 -ExecutionPolicy Bypass(脚本随包发布,可自行审查);它只隐藏/还原进程名或窗口标题匹配 DSH 的窗口,不会碰别的程序。 - 插入图片复用 DSH 自己的附件通道,图片和普通粘贴的图片走同一条上传/落盘路径。
- 本地留痕只有三处:附件库里的图片本体;会话目录的
screenshots.json(文件名、哈希、尺寸、会话标题——用来回答“这张图属于哪个对话”);%TEMP%\dsh-print-screen-helper.log(只记耗时、隐藏窗口数量和标题长度,不记标题内容)。 - 诊断开关默认关闭:只有设置环境变量
DSH_SCREENSHOT_FRAME_DUMP=1后,在取消截图时才会把整块冻结画面存到%TEMP%\dsh-print-screen-last-frame.png,用于排查“DSH 有没有被截进去”。 - 截图会离开本机:图片作为消息附件发送时,会随对话内容一起发给模型服务商。那是 DSH 本身的行为,不是这个插件联网。
自测
node test.mjs # 路由注册、跨站拒绝、真实截一张(-SelfTest 固定裁剪,不弹窗) node test-client.mjs # 按钮结构、Shift / Ctrl+Alt+1 快捷键判定、时间戳文件名 node test-route.mjs # 集成:真实路由 + 常驻助手 + 模拟拖框,量冷/热延迟 node --check client.js node --check index.js
powershell -ExecutionPolicy Bypass -File test-helper.ps1 # 常驻助手:启动耗时、热态延迟、模拟拖框 powershell -ExecutionPolicy Bypass -File test-hide.ps1 # 用一个替身窗口验证「隐藏 / 还原」
助手协议支持自测模式(第 6 个字段为 1,不弹窗口、固定裁 320×200),node test.mjs 用的就是它。
改脚本注意:所有 .ps1 必须存成 UTF-8 带 BOM。Windows PowerShell 5.1 对没有 BOM 的脚本按系统 ANSI 代码页(中文系统是 GBK)解码,冻结画面左上角那行「拖动框选区域 · Esc 取消」就会变成乱码。
已知限制
- 仅 Windows。
- 冻结窗口是普通 TopMost 窗口,理论上可能被其他 TopMost 窗口盖住一角。
- 截图期间 DSH 会被隐藏;如果助手卡死(5 分钟超时会被杀掉),DSH 需要手动还原。
- 不要手动删附件库里的图片:消息里存的是哈希引用,删掉对象会让对应会话报错、历史图片无法显示。要清理就用「删除会话」插件,让图片随会话一起删。
- 实战案例 ①:删掉附件库里的对象,那个会话就报废了(实测)。 把
~/.dsh/attachments/v1/objects/下一个被消息引用的对象文件改名,历史里那张图立刻变成「图片加载失败」占位;再发任何一句话,模型请求连续重试 5 次后失败,界面只写DeepSeek Messages transport failed——从这句错误里完全看不出是附件缺失。图片按哈希引用,删对象等于把消息里的一段内容抽走,而且没有回收站;这种会话恢复不回来,只能整条删掉(用「删除会话」插件)。 - 实战案例 ②:截图途中助手被杀,DSH 停在隐藏状态。 截图时 DSH 是用
SW_HIDE隐藏的,正常情况下裁剪完立刻还原。但如果这期间助手进程被结束(任务管理器、杀毒软件拦截、或卡住 5 分钟被超时杀掉),隐藏状态就不会还原——任务栏里看不到窗口,看起来像 DSH 崩了。此时到任务管理器结束DeepSeek Harness进程,重新启动即可,不用重装、配置也不会丢。
更新记录
版本 · 变化
0.4
…(truncated)
以上内容来自 npm 上的 README,我们只做格式化,不改内容。
版本
npm 上共发布:8,最后更新 2026-11-04