前言
公司最近配的一台螢幕,沒辦法調整亮度,亮得要命,眼睛要瞎掉了
所以只好自立自強搞一個螢幕遮罩
第一章:顯示 Electron 視窗,可調整透明度
第二章:參數維護移植到
main/js第三章:增加調整顏色功能
本章節內容
隱藏 electron 應用程式視窗,讓他看起來就是一個遮罩
0. 開啟 src/main.js
1. 調整 BrowserWindow 設定 - frame 設成 false
移除視窗邊框
const win = new BrowserWindow({
...
frame: false,
...
})
執行 npm start
✅ 確認上方工具列消失了,試著把其他應用程式往遮罩拖,應該會被擋住因為有 win.setAlwaysOnTop(true, 'screen-saver'); 設定
...嗯, 有點困擾呢
2. 調整 BrowserWindow 設定 - transparent 設成 true
開啟視窗透明
const win = new BrowserWindow({
...
transparent: true, // 開啟視窗透明
...
})
執行 npm start
✅ 試著把其他應用程式往遮罩拖,可以看到遮罩後的應用程式了但是拖不回來因為有 win.setAlwaysOnTop(true, 'screen-saver'); 設定
被遮罩擋住了...
...嗯, 有點困擾呢
3. win 設定忽略滑鼠事件
win.once('ready-to-show', () => {
win.show()
win.setAlwaysOnTop(true, 'screen-saver')
// 當網頁載入完成後,把初始值丟給前端
win.webContents.send('init-settings', overlaySettings)
win.setIgnoreMouseEvents(true) // 👈 設定
})
執行 npm start
✅ 試著把其他應用程式往遮罩拖,可以自由拖移
✅ 試著打字也 ok
可是遮罩的右上面板點不到捏...
4. 增加 點擊穿透與互動
若要讓控制面板可點擊但背景穿透,需監聽滑鼠是否進入面板區域,並動態調用
win.setIgnoreMouseEvents(false)。
在 index.html 的面板增加 滑鼠事件監聽
- 設定面板
id="control-panel",以便抓取...
<div
id="control-panel"
class="fixed top-4 right-4 p-4 bg-white/80 backdrop-blur rounded-xl shadow hover:opacity-100 opacity-20 transition-opacity z-10"
>
<label class="block">
透明度
<input .... />
</label>
<label class="block">
顏色
<input type="color" id="colorInput" class="w-full" />
</label>
</div>
... <script>取得 面板
const controlPanel = document.getElementById('control-panel')
3. 設定面板的滑鼠事件監聽
controlPanel.onmouseenter = () => alert('滑鼠進入面板')
controlPanel.onmouseleave = () => alert('滑鼠離開面板')
執行 npm start
滑鼠移到面板沒反應捏...原因是 main.js 的 win.setIgnoreMouseEvents(true)
4. ✅ 需將 setIgnoreMouseEvents 設定改為
win.setIgnoreMouseEvents(true, { forward: true })(可詳見 📚 額外筆記)
執行 npm start
✅ 滑鼠移到面板,成功跳出 alert
- 以
onmouseenter、onmouseleave動態設定setIgnoreMouseEvents
controlPanel.onmouseenter = () => ipcRenderer.send('set-ignore-mouse', false)
controlPanel.onmouseleave = () => ipcRenderer.send('set-ignore-mouse', true)
- main.js 接收
set-ignore-mouse事件,設定setIgnoreMouseEvents
// src/main.js
ipcMain.on('set-ignore-mouse', (event, active) => {
win.setIgnoreMouseEvents(active, { forward: true })
})
📚 額外筆記
關於 setIgnoreMouseEvents 設定
setIgnoreMouseEvents 接收 2 個參數 (ignore: boolean, options: Electron.IgnoreMouseEventsOptions)
- 第一個參數如果是
true,代表
「不管滑鼠在哪裡,所有的點擊(Click)、按壓(MouseDown)都直接傳給後面的視窗。」 - 第二個參數
options含有一個 forward 的設定 - false (預設),意思是: 滑鼠點擊穿透,且你的視窗 完全不會 觸發任何滑鼠事件(如 mousemove)。
- true,意思是: 滑鼠點擊依然會穿透(點到後面的東西),但你的視窗 依然會觸發 滑鼠移動事件。
當設定 win.setIgnoreMouseEvents(true, { forward: true })
會遇到一個問題:
🧠 我可以 onmouseenter、onmouseleave,為什麼不能控制面板?
這觸及了 作業系統層級 (OS) 與 瀏覽器渲染引擎 (Chromium) 之間的分工邏輯。
簡單來說:「點擊」需要所有權(Focus/Capture),但「移動」只需要座標(Coordinates)。
當設定 { forward: true } 時,Electron 實際上是在背後做了一套「雙重轉發」:
- 作業系統端: 當滑鼠移動到你的視窗上方時,因為
setIgnoreMouseEvents(true),作業系統原本會直接把事件丟給後面的視窗(例如資料夾)。 - Electron 的轉發: 但因為有了
{ forward: true },作業系統在把事件丟給後方的同時,也會「順便」抄送一份滑鼠座標給 Electron 視窗。 - 瀏覽器解析: Electron 內部的 Chromium 引擎收到了這組座標,它會計算:「喔!滑鼠現在在座標 (100,200)(100,200),這剛好是我那個
div.control-panel的範圍內。」 - 觸發事件: Chromium 發現滑鼠從「外面」進入了「裡面」,於是幫你觸發了 mouseenter。這純粹是「資訊的共享」,不需要攔截滑鼠。
為什麼沒辦法操作拉桿(Slider)?
操作拉桿的本質不是移動,而是 「事件攔截(Event Interception)」。
- 操作 Slider 的流程: 按下鼠標 (
mousedown) → 保持按住 → 移動 (mousemove) → 鬆開 (mouseup)。 - 斷在哪裡? 斷在第一步
mousedown。 - 現實情況: 當你點擊拉桿時,作業系統看到你的視窗標記為「忽略滑鼠事件」。所以它會把這個
mousedown直接傳給後面的程式。 - 結果: 你的拉桿從頭到尾都沒收到「被點擊」的訊號,它以為沒人理它。











