[問題解法紀錄] Electron製作桌面小工具的幾個要素

問題解法紀錄·教學 · 2024-07-01 · 163 人瀏覽過
[問題解法紀錄] Electron製作桌面小工具的幾個要素

之前有段時間在找各種可以做桌面小工具的方法,後來有發現 Rainmeter 這個工具,雖然他有自己完整的生態,但他的專案結構對我非常不友善,同時我也不熟 Lua 的開發所以其實我沒有使用這個工具做出自己喜歡的桌面小工具。

直到最近接觸到了 Electron 發現了新大陸。

要素

由於 Rainmeter 還算是有地位的桌面小工具,而他的呈現也與我對於桌面小工具應有的樣子一樣,所以這次我們借鑑 Rainmeter 來開發桌面小工具。

Snipaste_2024-07-01_23-03-02.png

可以看到他具備以下要素

  1. 工作列不顯示小工具的視窗
  2. 小工具為透明視窗
  3. 小工具的視窗沒有邊框
  4. 位置-總是在最上層
  5. 桌面選釘
  6. 點擊穿透

接著我們就來根據這些元素來嘗是用 Electron 呈現。

實作

視窗設定

Electron 可以在創建視窗的時候設定視窗的資訊 我們可以用設定的方式完成第一點到第五點

const win = new BrowserWindow({
  // 不顯示在任務欄
  skipTaskbar:true,
  // 透明背景
  transparent: true,
  // 沒有邊框
  frame: false,
  // 至頂視窗
  alwaysOnTop: true,
  // 視窗不能被最小化
  minimizable: false,
  // 視窗不能被最大化
  maximizable: false,
  // 視窗不能全螢幕
  fullscreenable: false,
  // 視窗不能被關閉
  webPreferences: {
    nodeIntegration: true,
    contextIsolation: false // 否则页面无法用require
  },
});

事件設定

我希望他可以點擊穿透,也就是讓視窗不要對滑鼠的事件做反應。這時候要用到 win.setIgnoreMouseEvents(true, { forward: true }); 方法,可是我有時候要對小工具的元件進行操作阿。那就需要頻繁的開關。

我們可以藉由 Electron 自帶的行程間通訊 ipcMain方法來進行通訊。如果收到 啟用點擊穿透 事件 ,則在主進程中忽略所有滑鼠事件。反之,如果收到 關閉點擊穿透 則重新響應滑鼠事件。

main.js

// 忽略滑鼠事件
win.setIgnoreMouseEvents(true, { forward: true });

// 處理點擊穿透
ipcMain.on('win-penetrate-true', (event, arg) => {
  BrowserWindow.fromWebContents(event.sender).setIgnoreMouseEvents(true, { forward: true });
});

ipcMain.on('win-penetrate-false', (event, arg) => {
  BrowserWindow.fromWebContents(event.sender).setIgnoreMouseEvents(false);
});

index.js

const targetElements = document.getElementsByClassName("action-element")
for (let i = 0; i < targetElements.length; i++) {
  const targetElement = targetElements[i];

  targetElement.addEventListener('mouseenter', () => {
    ipcRenderer.send('win-penetrate-false');
  });

  targetElement.addEventListener('mouseleave', () => {
    ipcRenderer.send('win-penetrate-true');
  });
}

我定義了一個 class 叫做 action-element ,這個 class 的元件會接收滑鼠事件,所以當滑鼠進入這個元素時使用IPC關閉點擊穿透,離開則開啟。

結尾

一照上面的設定這樣就可以得到一個乾淨的小工具了:D Snipaste_2024-07-01_23-29-54.png

至於移動的部分我還在研究,目前還沒找到一個我滿意的方案,等研究玩再發一篇文XD。

同場加映-自動設定小工具視窗大小

main.js

ipcMain.on('reset-window-size', (event, arg) => {
  win.setSize(arg.width, arg.height);
});

index.js

// 重置視窗大小
function resetWindowSize(body) {
  width = parseInt((body.getBoundingClientRect()).width) + parseInt(body.style.margin) * 2;
  height = parseInt((body.getBoundingClientRect()).height) + parseInt(body.style.margin) * 2;

  console.log(width, height);
  ipcRenderer.send('reset-window-size', { width, height });
}
Electron 桌面小工具
Theme Jasmine by Kent Liao