Electron——窗口

一、渲染进程与主进程通信

// 渲染进程向主进程发送信息
window.electron.ipcRenderer.invoke('dialog:openFileWindow', {
  name: 'list'
})

二、主进程获取渲染进程发送的信息

import { app, shell, BrowserWindow, ipcMain } from 'electron'

function createWindow(): void {
  // Create the browser window.
  const mainWindow = new BrowserWindow({
    width: 900,
    height: 670,
    show: false,
    autoHideMenuBar: true,
    ...(process.platform === 'linux' ? { icon } : {}),
    webPreferences: {
      preload: join(__dirname, '../preload/index.js'),
      sandbox: false
    }
  })

  // 使用ipcMain处理渲染进程发送给主进程的消息
  ipcMain.handle('dialog:openFileWindow', async (_event, args) => {
    const listWindow = new BrowserWindow({
      width: 500,
      height: 300,
      show: false,
      autoHideMenuBar: true,
      ...(process.platform === 'linux' ? { icon } : {}),
      webPreferences: {
        preload: join(__dirname, '../preload/index.js'),
        sandbox: false
      }
    })
    listWindow.on('ready-to-show', () => {
      listWindow.show()
    })
    if (is.dev && process.env['ELECTRON_RENDERER_URL']) {
      listWindow.loadURL(process.env['ELECTRON_RENDERER_URL'] + '/list')
    } else {
      listWindow.loadFile(join(__dirname, '../renderer/index.html'))
    }
  })

  mainWindow.on('ready-to-show', () => {
    mainWindow.show()
  })

  mainWindow.webContents.setWindowOpenHandler((details) => {
    shell.openExternal(details.url)
    return { action: 'deny' }
  })

  // HMR for renderer base on electron-vite cli.
  // Load the remote URL for development or the local html file for production.
  if (is.dev && process.env['ELECTRON_RENDERER_URL']) {
    mainWindow.loadURL(process.env['ELECTRON_RENDERER_URL'])
  } else {
    mainWindow.loadFile(join(__dirname, '../renderer/index.html'))
  }
}

三、创建窗口的一些参数选项

const windowOptions = {
  // 基本窗口尺寸和位置
  width: 800,                    // 窗口宽度,默认为 800px
  height: 600,                   // 窗口高度,默认为 600px
  x: 0,                          // 窗口相对于屏幕的左上角 x 坐标
  y: 0,                          // 窗口相对于屏幕的左上角 y 坐标
  useContentSize: false,         // 是否使用内容尺寸(不包括边框)来设置窗口大小

  // 窗口外观和行为
  center: false,                 // 是否在屏幕中心显示窗口
  minWidth: 0,                   // 窗口最小宽度
  minHeight: 0,                  // 窗口最小高度
  maxWidth: 0,                   // 窗口最大宽度
  maxHeight: 0,                  // 窗口最大高度
  resizable: true,               // 窗口是否可以调整大小
  movable: true,                 // 窗口是否可以移动
  minimizable: true,             // 窗口是否可以最小化
  maximizable: true,             // 窗口是否可以最大化
  closable: true,                // 窗口是否可以关闭
  focusable: true,               // 窗口是否可以获取焦点
  alwaysOnTop: false,            // 窗口是否总是在最前面
  fullscreen: false,             // 窗口是否全屏
  fullscreenable: true,          // 窗口是否可以进入全屏模式
  simpleFullscreen: false,       // 在 macOS 上使用简单全屏模式
  skipTaskbar: false,            // 是否在任务栏中隐藏窗口
  kiosk: false,                  // 是否启用 kiosk 模式

  // 窗口标题和图标
  title: '',                     // 窗口标题
  icon: null,                    // 窗口图标路径

  // Web 页面相关
  webPreferences: {
    nodeIntegration: false,      // 是否启用 Node.js 集成
    contextIsolation: true,      // 是否启用上下文隔离
    webSecurity: true,           // 是否启用 web 安全特性
    allowRunningInsecureContent: false, // 是否允许在 HTTPS 页面中运行 HTTP 内容
    preload: '',                 // 预加载脚本路径
    zoomFactor: 1.0,             // 页面默认缩放因子
    devTools: true,              // 是否启用开发者工具
    sandbox: false,              // 是否启用沙箱模式
    enableRemoteModule: false,   // 是否启用 remote 模块(Electron 12+ 默认禁用)
    autoplayPolicy: 'no-user-gesture-required', // 自动播放策略
    spellcheck: true,            // 是否启用拼写检查
    nativeWindowOpen: false,     // 是否使用原生 window.open()
    webviewTag: false,           // 是否启用 <webview> 标签
    plugins: false,              // 是否启用插件
    experimentalFeatures: false, // 是否启用实验性功能
    scrollBounce: false,         // 是否启用滚动弹性效果(macOS)
    enableWebSQL: true,          // 是否启用 WebSQL
    defaultFontFamily: {},       // 默认字体族
    defaultFontSize: 16,         // 默认字体大小
    defaultMonospaceFontSize: 13, // 等宽字体默认大小
    minimumFontSize: 0,          // 最小字体大小
    defaultEncoding: 'ISO-8859-1', // 默认编码
    offscreen: false,            // 是否启用离屏渲染
    additionalArguments: [],     // 传递给渲染进程的额外参数
  },

  // 窗口样式和框架
  frame: true,                   // 是否显示窗口边框和标题栏
  parent: null,                  // 父窗口
  modal: false,                  // 是否为模态窗口
  acceptFirstMouse: false,       // 是否接受第一次鼠标事件
  disableAutoHideCursor: false,  // 是否在输入时自动隐藏光标
  autoHideMenuBar: false,        // 是否自动隐藏菜单栏
  enableLargerThanScreen: false, // 是否允许窗口大于屏幕
  backgroundColor: '#FFF',       // 窗口背景颜色
  hasShadow: true,               // 窗口是否有阴影
  opacity: 1.0,                  // 窗口透明度 (0.0-1.0)
  darkTheme: false,              // 是否使用深色主题
  transparent: false,            // 窗口是否透明
  type: 'desktop',               // 窗口类型(平台特定)
  titleBarStyle: 'default',      // 标题栏样式 ('default', 'hidden', 'hiddenInset')
  trafficLightPosition: null,    // 交通灯按钮位置(macOS)
  roundedCorners: true,          // 窗口是否有圆角
  thickFrame: true,              // 是否使用厚边框(Windows)
  vibrancy: null,                // 毛玻璃效果(macOS)
  visualEffectState: 'followWindow', // 视觉效果状态(macOS)

  // 显示相关
  show: true,                    // 窗口创建后是否立即显示
  paintWhenInitiallyHidden: true, // 是否在初始隐藏状态下绘制内容

  // 平台特定选项
  tabbingIdentifier: '',          // 标签页标识符(macOS)
  webContents: null,             // 使用现有的 webContents 而不是创建新的
  timeout: 30,                   // 等待页面加载的超时时间(秒)
}

四、窗口拖拽

当设置titleBarStyle: 'hidden’时,窗口无法移动

1、使用-webkit-app-region: drag

在需要移动窗口的元素上,添加这个样式,就可以移动窗口了,但是会导致其中的元素事件失效,需要在不需要移动窗口的元素上加上-webkit-app-region: no-drag;才可以使事件生效

2、与主线程通信修改窗口大小

  • 1、渲染线程添加mousedown事件
<template>
  <div class="main-container" @mousedown="onMouseDown">
    <router-view></router-view>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'
const isKeyDown = ref(false)
const distanceX = ref(0)
const distanceY = ref(0)
const onMouseDown = (event): void => {
  isKeyDown.value = true
  distanceX.value = event.x
  distanceY.value = event.y
  window.electron.ipcRenderer.invoke('window:mouseDown')
  document.onmousemove = (ev): void => {
    if (isKeyDown.value) {
      const x = ev.screenX - distanceX.value
      const y = ev.screenY - distanceY.value
      // 给主进程传入坐标
      let data = {
        appX: x,
        appY: y
      }
      window.electron.ipcRenderer.invoke('window:custom-adsorption', data)
    }
  }
  document.onmouseup = (): void => {
    isKeyDown.value = false
    // 清理事件监听器
    document.onmousemove = null
    document.onmouseup = null
  }
}
</script>

<style scoped>
.main-container {
  background-color: red;
  width: 100vw;
  height: 100vh;
  overflow: hidden;
}
</style>
  • 2、主线程处理
// 这是因为window中,调用setPosition会修改窗口尺寸,所以我们这里每次获取一次窗口尺寸,在下面进行调用
ipcMain.handle('window:mouseDown', () => {
    currentWindowSize = mainWindow.getSize()
  })

  ipcMain.handle('window:custom-adsorption', async (_event, args) => {
    const x = args.appX
    const y = args.appY
    // 因为window下设置窗口位置会导致窗口大小变化,所以如下处理
    const newBounds = {
      x,
      y,
      width: currentWindowSize[0],
      height: currentWindowSize[1]
    }
    mainWindow.setBounds(newBounds)
  })

五、自定义实现关闭、最大化、最小化功能

ipcMain.handle('window:closeApp', () => {
    // 退出程序
    app.quit()
    // 关闭窗口
    // mainWindow.close()
  })

  // 最小化
  ipcMain.handle('window:minWindow', () => {
    mainWindow.minimize()
  })
  
  // 最大化切换
  ipcMain.handle('window:maxWindow', () => {
    // 获取屏幕大小
    const screenSize = screen.getPrimaryDisplay().size
    // 设置为全屏
    if (!isFullscreen) {
      isFullscreen = true
      // 获取当前窗口位置大小信息
      currentWindowBounds = mainWindow.getBounds()
      mainWindow.setBounds(
        {
          x: 0,
          y: 0,
          width: screenSize.width,
          height: screenSize.height
        },
        true
      )
    } else {
      isFullscreen = false
      mainWindow.setBounds(currentWindowBounds, true)
    }
  })
### 如何在 Electron 中设置窗口支持中文显示 为了使 Electron窗口标题或界面能够正常显示中文字符,需要从多个方面入手,包括编码设置、字体兼容性和构建工具的支持。 #### 1. 确保项目文件采用 UTF-8 编码 所有涉及的源代码文件(如 `package.json`、`main.js` 和其他 JavaScript 文件)都应保存为 **UTF-8** 编码格式。这可以防止因编码不一致而导致的乱码问题[^3]。 #### 2. 修改系统区域设置以支持 Unicode 如果是在 Windows 平台上开发,可能会遇到终端输出或其他环境下的中文乱码现象。通过调整系统的区域设置可有效解决问题: - 打开“控制面板”,进入“区域”选项卡。 - 切换至“管理”标签页,点击“更改系统区域设置”按钮。 - 勾选“使用 Unicode UTF-8 提供全球语言支持”选项,并重启计算机完成更新[^2]。 此操作不仅解决了终端中的乱码问题,还间接提升了整个项目的国际化能力。 #### 3. 设置窗口属性支持多国语言 当创建 BrowserWindow 实例时,可以通过指定合适的参数来增强其对多种语言(含中文)的支持。例如,在初始化主进程中定义如下内容: ```javascript const { app, BrowserWindow } = require('electron'); function createWindow () { const win = new BrowserWindow({ width: 800, height: 600, webPreferences: { preload: path.join(__dirname, 'preload.js'), nodeIntegration: true // 如果需要 Node.js 集成则启用该选项 } }); win.setTitle('我的Electron应用'); // 设定窗口标题为中文字符串 win.loadFile('index.html'); } app.whenReady().then(createWindow); ``` 上述代码片段展示了如何利用 setTitle 方法赋予窗口一个带有汉字名称的标题栏。 #### 4. 使用正确的字体资源 对于某些特定场景下可能出现的文字渲染异常情况,建议预先加载适合东亚地区使用的字型库。可以在 HTML 文件头部加入 CSS 字体声明语句: ```html <link href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap" rel="stylesheet"> <style> body { font-family: 'Noto Sans SC', sans-serif; } </style> ``` 这里选用 Google Fonts 上提供的 Noto Sans SC 字体族作为例子,它专为简化汉字设计,覆盖范围广且质量高[^4]。 #### 5. 构建阶段处理潜在的语言障碍 最后一步也是至关重要的环节——即打包分发前确认目标平台上已具备良好的本地化基础。借助 electron-builder 工具链,开发者可以根据实际需求定制跨平台发行方案的同时兼顾各操作系统间的差异性[^1]。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值