Electron -- 窗口焦点通知

Electron - 窗口焦点通知

本文介绍了在 Electron 应用程序中实现窗口焦点通知的方法。通过使用 IPC 机制和自定义事件,可以在多个窗口之间同步和反映窗口的聚焦状态。

1. 步骤概述

1. 创建新的浏览器窗口,并监听窗口被聚焦的 'focus' 事件。在窗口被聚焦时,发送名为 'window-focused' 的 IPC 消息给主进程。

js 复制代码
 win = new BrowserWindow({
   width: 800,
   height: 600,
 });

 // 监听窗口被聚焦事件
 win.on('focus', () => {
   const winId = win.id;
   // 向主进程发送消息,传递当前窗口的 winId
   win.webContents.send('window-focused', winId);
 });

这段代码是在 Electron 的主进程中创建一个新的 BrowserWindow 窗口,并监听窗口被聚焦的 'focus' 事件。

在 'focus' 事件的回调函数中,首先获取当前窗口的 winId,然后使用 win.webContents.send() 方法向渲染进程发送名为 'window-focused' 的 IPC 消息,并将当前窗口的 winId 作为参数传递。 这样做的目的是,在窗口被聚焦时触发 'focus' 事件,并通过 IPC 将窗口的聚焦状态通知给渲染进程,以便其他相关的窗口能够接收到该消息并响应相应的操作。

2. 在主进程中,使用 ipcMain 监听名为 'window-focused' 的 IPC 消息,并广播窗口聚焦状态给其他窗口。

js 复制代码
ipcMain.on('window-focused', (event, winId) => {
  // 广播窗口聚焦消息给其他窗口
BrowserWindow.getAllWindows().forEach(window => {
      window.webContents.send('window-focus-update', winId);
    });
});

这段代码是在 Electron 的主进程中使用 ipcMain 监听名为 'window-focused' 的 IPC 消息。当收到该消息时,它会执行回调函数。

在回调函数中,主要的逻辑是广播窗口聚焦消息给其他窗口。它通过使用 BrowserWindow.getAllWindows() 方法获取当前应用程序中的所有窗口,并遍历每个窗口发送名为 'window-focus-update' 的 IPC 消息,将聚焦的窗口的 winId 作为参数传递。

这样做可以实现窗口聚焦更新的事件通知,让其他窗口能够获取到最新的聚焦窗口的信息。

3. 通过接口registerWinFocusCallback注册回调函数 _cb,用于处理窗口聚焦更新事件。在回调函数被调用时,通过自定义事件 'window-focus-update' 分发窗口的 winId 到文档中。

js 复制代码
const _cb = winId => void document.dispatch(new CustomEvent('window-focus-update', {details:winId}));

globalThis.globalAPI?.registerWinFocusCallback(_cb);

这段代码是在渲染进程中调用 globalAPI 全局对象的 registerWinFocusCallback 方法,并传递一个回调函数 _cb 作为参数。 在回调函数 _cb 中,它创建了一个自定义事件 'window-focus-update',并通过 document.dispatch() 方法将该事件分发到文档中。事件的细节信息包含了窗口的 winId 参数。

这样做的目的是使用 registerWinFocusCallback 注册一个窗口聚焦更新的回调函数,当窗口聚焦更新事件发生时,回调函数会被调用,并触发自定义事件 'window-focus-update',从而通知其他部分(如之前提到的第一段代码)进行相应处理。

4. 在渲染进程中,使用 contextBridge 和 ipcRenderer 将 globalAPI 对象注入到前端页面的上下文中。

js 复制代码
const { contextBridge, ipcRenderer } = require('electron');

// 定义全局对象
const globalAPI = {
  registerWinFocusCallback: (cb) => {
    ipcRenderer.on('window-focus-update', (event, winId) => void cb(winId))},
};

// 将全局对象注入到渲染进程的上下文中
contextBridge.exposeInMainWorld('globalAPI', globalAPI);

这段代码是在 Electron 的渲染进程中使用 contextBridge 和 ipcRenderer,将一个名为 globalAPI 的全局对象注入到渲染进程的上下文中。

globalAPI 对象包含了一个方法 registerWinFocusCallback,它用于注册窗口聚焦更新事件的回调函数。具体来说,当收到名为 'window-focus-update' 的 IPC 消息时,该回调函数会被调用,并将窗口的 winId 作为参数传递给回调函数。

通过使用 contextBridge.exposeInMainWorld() 方法,globalAPI 全局对象被暴露给渲染进程的前端页面,在前端页面中可以直接访问和使用其中的方法。

5. 在 React 组件中使用 useEffect 钩子监听窗口聚焦更新事件。根据获取的窗口 ID 更新 SVG 元素的颜色。

js 复制代码
useEffect(() => {
    const changeSvgColor = (color) => {
    const svgElement = document.getElementById('state');
    if (svgElement) {
      svgElement.style.fill = color;
    }
  };
    const handleFocusUpdate = (event) => {
      const winId = event.detail;
      const _winId = sessionStorage.getItem("winId");
      changeSvgColor(winId===_winId?'grey':'white');
    };

    window.addEventListener('window-focus-update', handleFocusUpdate);

    return () => {
      window.removeEventListener('window-focus-update', handleFocusUpdate);
    };
  }, []);

这段代码是使用 React 的 useEffect 钩子实现了监听窗口聚焦更新事件,并根据获取的窗口 ID 更新 SVG 元素的颜色。

在 useEffect 中,首先定义了 changeSvgColor 函数,用于修改 SVG 元素的颜色。然后定义了 handleFocusUpdate 函数,它会在窗口聚焦更新事件触发时被调用。在该函数中,它通过比较传入的窗口 ID (winId) 与存储在 sessionStorage 中的窗口 ID (_winId),确定要设置的颜色,并调用 changeSvgColor 函数进行颜色的更新。 接下来,使用 window.addEventListener 方法将 handleFocusUpdate 函数注册为 'window-focus-update' 事件的监听器。

2. 总结

通过结合上述步骤和示例代码,可以实现在 Electron 应用程序中监听和处理窗口焦点更新事件,并相应地更新界面元素的颜色。这样可以提供一致的用户体验,使用户能够清晰地了解当前具有焦点的窗口。

相关推荐
LucianaiB10 小时前
【元宝搜索开发者征文大赛】AI时代,学得慢就不用学?用元宝搜索打造一个教程保质期,确保每一个教程符合你的现状
前端·人工智能·ai编程
excel10 小时前
JavaScript 对象池:减少高频对象创建与 GC 压力
前端
陈随易12 小时前
纯 Go 写的 JS 引擎,跑分超过了 C 语言的 QuickJS
前端·后端·程序员
子兮曰13 小时前
Chrome 权限元素实战:144 与 151 的渐进增强写法
前端·javascript·chrome
IT_陈寒14 小时前
Redis连接池泄漏那次,我差点把生产环境搞崩了
前端·人工智能·后端
强尼银手14 小时前
我花一天做了个格斗游戏原型,判定全对,然后被「美术」劝退了
前端·javascript
石小石Orz14 小时前
AI 正在蚕食我们的编码能力
前端·后端·算法
陈随易14 小时前
专注飞机 FocusFlight,两个人把番茄钟做成了一趟航班
前端·后端·程序员
总要学点什么15 小时前
第98篇:三维特效-材质线效果——给一条线换十种材质,虚线的图案只填了一半
开发语言·前端·javascript·ecmascript·gis·webgl·材质
10share15 小时前
基于大模型的 i18n 方案:把中文原文当 Key,轻松搞定多语言维护
前端·vue.js