electron自定义窗口和右键菜单样式

前言

electron默认沿用系统UI,并没有提供很多接口供使用者定制样式,如果想要完全自定义的样式,目前我能想到的方案只能是通过前端自定义样式,然后通过进程通信来实现系统基础功能:最大/小化、关闭、拖动窗口等。

效果图:
在这里插入图片描述
在这里插入图片描述

一、窗口自定义

通过前面系列文章我们可以了解到,窗口是通过实例化BrowserWindow对象创建的,实例化时会传入一些窗口的参数。

要实现窗口自定义,就必须把窗口默认样式都屏蔽。几个关键的参数如下:

transparent: true,
backgroundColor:'rgba(0,0,0,0)',
frame:false,

参数含义很好理解,窗体透明无边框,参数详解请查询官网。

把系统自带的窗体样式去掉后,我们会得到一个只有主体的窗口,这个主体就是前端(vue)渲染的窗口,我们可以通过控制它,来实现任何样式的窗口。

但是这会带来一个问题,那就是窗口对象提供的很多便捷功能无法使用了,所以如果需要做最大化、最小化、拖动窗口等功能,只能通过进程通信,前端发送指令,主进程接收指令后,完成相应功能。具体原理请参考本系列前面关于进程通信的文章。

这里简单列一个示例代码,以最大化为例:

//vue代码部分,在某个dom元素上监听事件
<img class="title-icon" src="@/assets/img/maxsize.png"  alt="最大化" @click="handleMaxSize()">

 function handleMaxSize(){
   
        renderApi.handleMaxSize()
    }
//preload.js中定义通信的api,下面是我项目中所有渲染进程到主进程的通信

const handleSendPageName= (pageName) => ipcRenderer.send('send-page-name', pageName) //渲染进程主动到主进程
const handleMinSize= () => ipcRenderer.send('send-min-size') //渲染进程主动到主进程
const handleMaxSize= () => ipcRenderer.send('send-max-size') //渲染进程主动到主进程
const handleRestore= () => ipcRenderer.send('send-restore') //渲染进程主动到主进程
const handleRelaunch= () => ipcRenderer.send('user-click-Dock-Icon') //渲染进程主动到主进程

const handleCloseWin=()=>{
   
    ipcRenderer.send('send-auto-close')
}

contextBridge.exposeInMainWorld('renderApi', {
   
    //监听渲染进程事件
    handleGetStoreFiles,
    handleSendPageName,
    handleMinSize,
    handleMaxSize,
    handleCloseWin,
    handleRestore,
    handleRelaunch
})
//主进程main.js中接收对应的通信
     ipcMain.on('send-max-size', () => {
   
            if(win.isMaximized()){
   
                win.unmaximize()
            }else{
   
                win.maximize()
            }
        })

至此,模拟窗口最大化功能的全部过程就打通了。

二、窗口拖拽功能

这里值得注意的是,拖拽窗口不止是要配置参数,还要给对应dom元素增加类。

比如说我想实现拖动类名为“c-drag”的元素时,拖动窗口移动,大致代码如下:

   <div class="c-drag">

 </div>
.c-drag{
  -webkit-app-region: drag;
}

-webkit-app-region: drag是electron提供的css样式,具体可查询官网。

这是一个比较小众的知识点,网上资料目前较少,这里记录一下。

三、不同窗口设置不同大小

这一部分逻辑略微复杂。

窗口大小的设置一定是在主进程中设置,如果仅仅依靠vue部分控制显示区域大小,不显示区域设置为透明,虽然视觉上可以实现不同的窗体大小,但是这是一种伪实现,因为透明部分只是人眼看不到而已,鼠标点击、拖拽等功能仍然存在,就会对软件用户造成困扰。

在主进程中设置窗口大小,最重要的就是进入不同页面时,要主动向主进程发送指令,并告诉主进程,我现在进入登录页了,我现在进入正常页了,我现在进入xx页……

主进程接收指令后,根据参数,控制窗口的大小即可。

在我的项目中,各页面有一个统一的路由跳转方法,所以我在跳转路由后,同时将活跃页面的name通handleSendPageName发送给主进程。代码如下:

function turnToPage_menu(name) {
   
  console.log(name)
  turnToPage(router, name)

  renderApi.handleSendPageName(activeName.value) //发送pageName到主进程,以此判断窗口大小

}

主进程接收到指令后,根据参数,决定窗口设置为多大,代码:

  ipcMain.on('send-page-name', (event, pageName) => {
   
            console.log('setWindowSize',pageName)
            const loginSize={
   
                width:500,
                height:580
            }
            const pageSize={
   
                width:1000,
                height: 950
            }
            if (pageName && pageName == 'normalLogin') {
   
                win.setSize(loginSize.width, loginSize.height)
                win.center()
                win.setMenuBarVisibility(false)

            } else {
   
                if(this.judgePageSet(win,pageSize,loginSize)){
   
                    win.setSize(pageSize.width, pageSize.height)
                    win.center()
                    win.setMenuBarVisibility(true)
                }

            }
        })

至此不同页面实现不同大小的窗口功能,就实现了。

其实在我们项目中,还有另一种需求场景,那就是当通过注册表把软件注册到系统右键后,上传文件时,右下角有一个简易窗口,窗口高度根据上传文件数量来计算。这就需要判断命令行参数、获取文件下载地址等操作,更加复杂,但是应用场景应该不多,有兴趣的同学可以私聊,此处不再赘述。

四、右键菜单自定义

我并没有在实际项目中真正实现过右键菜单的自定义,但是道理和窗口是相通的,如果electron提供的右键菜单样式无法满足要求,那就舍弃框架提供的便捷菜单,通过进程间通信,手动实现。

总结

  1. 舍弃系统窗口所有功能,利用通信机制,模拟实现需要的窗口功能。
  2. 判断页面发送的参数,为不同页面的窗口设置不同的样式。

相关推荐

  1. Electron无边框定义窗口拖动

    2024-01-10 11:12:03       65 阅读
  2. Electron无边框定义窗口拖动

    2024-01-10 11:12:03       34 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-01-10 11:12:03       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-01-10 11:12:03       100 阅读
  3. 在Django里面运行非项目文件

    2024-01-10 11:12:03       82 阅读
  4. Python语言-面向对象

    2024-01-10 11:12:03       91 阅读

热门阅读

  1. Rust基础类型之布尔类型和字符

    2024-01-10 11:12:03       51 阅读
  2. Electron快速上手

    2024-01-10 11:12:03       53 阅读
  3. Flink编程实践

    2024-01-10 11:12:03       57 阅读
  4. docker环境调用mysqldump进行数据备份

    2024-01-10 11:12:03       48 阅读
  5. 【技术选型】clickhouse vs starRocks

    2024-01-10 11:12:03       81 阅读
  6. 深入理解 MyBatis-Plus 批量保存方法

    2024-01-10 11:12:03       62 阅读
  7. 安卓多用户管理之IUserManager.AIDL

    2024-01-10 11:12:03       44 阅读
  8. 第十节 登陆静态页

    2024-01-10 11:12:03       52 阅读
  9. Linux环境下使用flv.js + websokect播放RTSP视频流

    2024-01-10 11:12:03       61 阅读
  10. linux发送http请求命令

    2024-01-10 11:12:03       57 阅读
  11. Docker修改数据目录

    2024-01-10 11:12:03       52 阅读
  12. 第十五章 ECMAScript6新增的常用语法

    2024-01-10 11:12:03       61 阅读