《在 Windows 上做一枚只属于自己的小工具》的抽象头图
所有文章记录 · ARTICLE

在 Windows 上做一枚只属于自己的小工具

记录一个本地优先桌面便笺从快捷键、窗口行为到文件存储的取舍。

我需要的不是第二个知识库,只是一个按下快捷键就能接住念头的小窗口。它不要求选择目录,不提醒连续打卡,也不在我写到一半时推荐模板。

个人工具的价值,常常不是功能更多,而是它懂得哪一步不该打断你。

快捷键负责召回,窗口负责承接,文件系统负责让文字真正属于使用者。

一个十五秒的问题

这个工具起源于每天重复的小麻烦:想到一句话,解锁手机或切换应用,等界面出现,再决定它应该放到哪里。通常还没完成这些步骤,那句话已经变形。

我给第一版设了四条验收标准:

  • Win + Shift + Space 在任何窗口上方召回;
  • 光标自动落到上次编辑的位置;
  • 停止输入后自动保存,不弹成功提示;
  • 一个按钮导出当天全部内容为纯文本。

没有账户、同步和标签。不是这些功能没有价值,而是它们不属于“十五秒内接住念头”这个问题。

层次负责什么不负责什么
界面层输入、状态反馈、键盘可达性直接拼接文件路径
命令层打开窗口、保存、导出、撤销决定视觉样式
文件层原子写入、备份、恢复理解笔记含义

窗口应该怎样出现

桌面小工具最难调的不是颜色,而是窗口行为。它应该置顶,却不能抢走全屏演示;应该记住位置,却不能在拔掉外接显示器后留在看不见的坐标。

每次打开时,我都会把保存的窗口矩形与当前 workArea 求交。如果完全不相交,就把窗口放回主屏幕中央。按下 Escape 只隐藏窗口,不退出进程,以保证下一次召回足够快。

ts
type WindowSnapshot = {
  bounds: { x: number; y: number; width: number; height: number };
  displayId: string;
  updatedAt: number;
};

async function saveDraft(text: string) {
  const temp = `${draftPath}.tmp`;
  await writeTextFile(temp, text);
  await replaceFile(temp, draftPath);
}

数据为什么只存本地

便笺常常包含尚未整理的内容:门锁密码的提示、半句邮件、临时地址,甚至只是带情绪的一句话。第一版把每天的记录保存为 UTF-8 文本,并提供明确的“打开所在文件夹”。

文件命名也保持可读,例如 2024-12-08.md。即使应用以后不再维护,记事本、搜索工具和备份软件仍能继续处理这些文字。


打包以后才遇见的细节

开发环境里顺畅的功能,打包后会暴露真正的桌面问题:开机启动权限、缩放比例、多显示器坐标、杀毒软件误报,以及安装路径中出现中文字符。

我最后补上了崩溃恢复、单实例锁和便携模式,却仍然没有加入云同步。这个小工具最让我高兴的时刻,是它用了一周后开始变得“看不见”:快捷键、输入、关闭,一句话已经安全落盘,我甚至没有意识到自己打开过一个应用。