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. 在渲染进程中,使用 contextBridgeipcRendererglobalAPI 对象注入到前端页面的上下文中。

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 的渲染进程中使用 contextBridgeipcRenderer,将一个名为 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 应用程序中监听和处理窗口焦点更新事件,并相应地更新界面元素的颜色。这样可以提供一致的用户体验,使用户能够清晰地了解当前具有焦点的窗口。

相关推荐
负责的蛋挞31 分钟前
异步HttpModule的实现方式
java·服务器·前端
丹宇码农3 小时前
把 HLS 字幕玩出花:zwPlayer 如何让 M3U8 视频支持全文搜索、翻译与码率自适应
前端·javascript·音视频·hls·视频播放器
2501_943782353 小时前
【共创季稿事节】猜数字游戏:二分法思维与交互式反馈
前端·游戏·microsoft·harmonyos·鸿蒙·鸿蒙系统
GV191rLvq3 小时前
基于Socket实现的最简单的Web服务器【ASP.NET原理分析】
服务器·前端·asp.net
吠品4 小时前
LangChain 里 tool_call_id 为空?一次 MCP 工具集成的排查记录
前端
微信开发api-视频号协议4 小时前
企业微信二次开发中的文件系统设计:媒体资源、临时文件与业务附件
前端·微信·企业微信·媒体·ipad·微信开放平台
柒和远方4 小时前
Phase 7.4 学习博客:为什么多 API 项目需要 Swagger / OpenAPI
前端·后端·架构
张龙6874 小时前
拼多多开放平台对接踩坑实录:从 CLIENT_ID 配置到 MD5 签名算法的完整填坑指南
前端
GuWenyue4 小时前
提示词彻底过时?一套上下文工程方案,3步让LLM落地生产,代码直接复用
前端·javascript·人工智能