作品 & 能力
微信读书桌面版:贴在任务栏上的 Mini 阅读器
一个用 Electron 写的微信读书桌面阅读器。最特别的是 Mini 悬浮模式——一条和任务栏等高的横条,嵌在任务栏左侧的空白处,点任何别的窗口都盖不住它。做这个东西的过程,大半时间不是在写界面,而是在跟 Windows 的窗口层级和注册表较劲。
它是什么
粘贴书籍链接或书籍 ID 就能读,登录态持久化保存,每次启动落到书架。工具栏右侧有两个 − 100% + 控件,一个调字体缩放,一个调整个窗口的透明度(最低 30%,会透出背后的桌面,主窗口和 Mini 共用同一个值,重启后保留)。
按 Ctrl+Alt+M 切到 Mini:默认 420px 宽(避开居中的开始按钮),吸在屏幕左下角,不在任务栏显示图标,是个纯浮层;按钮那条的底色跟着系统任务栏配色走,融进任务栏里。
四个真正花时间的技术点
一、切换模式不重新加载页面
页面装在一个 WebContentsView 里。切 Mini 模式时,把这个 view 从主窗口上摘下来、挂到 Mini 窗口上——webContents 自始至终只有一个,所以阅读进度、滚动位置、登录态全都不会丢。如果用两个窗口各自加载一次页面,每次切换都要重新登录、重新翻到那一页,这个功能就没法用了。
二、真正的「永远置顶」
Windows 任务栏自己就是 HWND_TOPMOST 窗口,和普通的 alwaysOnTop 窗口处在同一层级——谁最后调用 SetWindowPos 谁在上面。所以只要点一下任务栏,你的窗口立刻就被盖住了,这是 Electron 的 alwaysOnTop 在任务栏面前失效的根本原因。
解法是持续重新抢占 z-order:定时器每 700ms 调一次 moveTop()(走 SWP_NOACTIVATE,不抢焦点),并且在窗口 blur 时立刻补一次——点任务栏必然先触发 blur,这条路径反应最快。
三、吸附位置要用 bounds 而不是 workArea
workArea 会自动避开任务栏,用它算出来的左下角只会停在任务栏上方;贴 display.bounds 的左下角才能真正压在任务栏上。Mini 的高度就取这两者的差值——那正好是任务栏的高度。
四、任务栏配色是读注册表拿的
开了「在任务栏显示强调色」时,任务栏用的是 AccentColorMenu——Windows 为任务栏和菜单预先算好的暗化后的强调色,不是原始强调色,而且注册表里按 ABGR 排列(不是常见的 RGBA,取错顺序颜色就完全不对)。没开这个选项时则跟随深浅主题。
还有一些踩过的坑
- 正文是 canvas 画的,不是 DOM 文本,排版没法用 CSS 调,只能靠缩放。Mini 里正文宽 616px 而视口只有 390px 上下,所以进 Mini 自动缩到 0.67 让一整行放得下。
- Electron 的缩放是按 origin 持久化在 session 里的,跨窗口和重启都带着走。所以两种模式的缩放必须显式设定,并在每次
did-finish-load后重申一次,不能依赖「当前值」。 - 阅读器自己的浮层要藏掉:
readerBottomBar有 56px 高,比整个 Mini 窗口还高,一冒出来就糊满视口。用insertCSS藏,但注入的 CSS 导航后会失效,每次加载完都要重新注入。 - 全局快捷键要避开别人的:特意没用
Ctrl+Shift+M——那是 VS Code 的问题面板,会误触发。
这类需求我能承接
把一个网页应用包成桌面客户端只是起点,真正的价值在系统集成:窗口层级、托盘与全局快捷键、开机自启、读写注册表、跟随系统主题、多屏适配。这些活我做过一整轮,知道哪里会卡住。
相关公众号文章:把微信读书固定到电脑角落摸鱼的小应用 ↗