# 五、窗口
# 5.1 BrowserWindow
主进程模块BrowserWindow
用于创建和控制浏览器窗口。
mainWindow = new BrowserWindow({
width: 1000,
height: 800,
// ...
});
mainWindow.loadURL("http://www.conardli.top/");
2
3
4
5
6
你可以在这里 (opens new window)查看它所有的构造参数。
# 5.2 无框窗口
无框窗口是没有镶边的窗口,窗口的部分(如工具栏)不属于网页的一部分。
在BrowserWindow
的构造参数中,将frame
设置为false
可以指定窗口为无边框窗口,将工具栏隐藏后,就会产生两个问题:
- 1.窗口控制按钮(最小化、全屏、关闭按钮)会被隐藏
- 2.无法拖拽移动窗口
可以通过指定titleBarStyle
选项来再将工具栏按钮显示出来,将其设置为hidden
表示返回一个隐藏标题栏的全尺寸内容窗口,在左上角仍然有标准的窗口控制按钮。
new BrowserWindow({
width: 200,
height: 200,
titleBarStyle: "hidden",
frame: false,
});
2
3
4
5
6
# 5.3 窗口拖拽
默认情况下, 无边框窗口是不可拖拽的。我们可以在界面中通过CSS
属性-webkit-app-region: drag
手动制定拖拽区域。
在无框窗口中, 拖动行为可能与选择文本冲突,可以通过设定-webkit-user-select: none;
禁用文本选择:
.header {
-webkit-user-select: none;
-webkit-app-region: drag;
}
2
3
4
相反的,在可拖拽区域内部设置
-webkit-app-region: no-drag
则可以指定特定不可拖拽区域。
# 5.4 透明窗口
通过将transparent
选项设置为true
, 还可以使无框窗口透明:
new BrowserWindow({
transparent: true,
frame: false,
});
2
3
4
# 5.5 Webview
使用 webview
标签在Electron
应用中嵌入 "外来" 内容。外来内容包含在 webview
容器中。 应用中的嵌入页面可以控制外来内容的布局和重绘。
与 iframe
不同, webview
在与应用程序不同的进程中运行。它与您的网页没有相同的权限, 应用程序和嵌入内容之间的所有交互都将是异步的。
# 六、对话框
dialog
模块提供了api
来展示原生的系统对话框,例如打开文件框,alert
框,所以web
应用可以给用户带来跟系统应用相同的体验。
注意:dialog 是主进程模块,想要在渲染进程调用可以使用 remote
# 6.1 错误提示
dialog.showErrorBox
用于显示一个显示错误消息的模态对话框。
remote.dialog.showErrorBox("错误", "这是一个错误弹框!");
# 6.2 对话框
dialog.showErrorBox
用于调用系统对话框,可以为指定几种不同的类型: "none
", "info
", "error
", "question
" 或者 "warning
"。
在 Windows 上, "question" 与"info"显示相同的图标, 除非你使用了 "icon" 选项设置图标。 在 macOS 上, "warning" 和 "error" 显示相同的警告图标
remote.dialog.showMessageBox(
{
type: "info",
title: "提示信息",
message: "这是一个对话弹框!",
buttons: ["确定", "取消"],
},
(index) => {
this.setState({
dialogMessage: `【你点击了${index ? "取消" : "确定"}!!】`,
});
}
);
2
3
4
5
6
7
8
9
10
11
12
13
# 6.3 文件框
dialog.showOpenDialog
用于打开或选择系统目录。
remote.dialog.showOpenDialog(
{
properties: ["openDirectory", "openFile"],
},
(data) => {
this.setState({ filePath: `【选择路径:${data[0]}】 ` });
}
);
2
3
4
5
6
7
8
# 6.4 信息框
这里推荐直接使用HTML5 API
,它只能在渲染器进程中使用。
let options = {
title: "信息框标题",
body: "我是一条信息~~~",
};
let myNotification = new window.Notification(options.title, options);
myNotification.onclick = () => {
this.setState({ message: "【你点击了信息框!!】" });
};
2
3
4
5
6
7
8
# 七、系统
# 7.1 获取系统信息
通过remote
获取到主进程的process
对象,可以获取到当前应用的各个版本信息:
process.versions.electron
:electron
版本信息process.versions.chrome
:chrome
版本信息process.versions.node
:node
版本信息process.versions.v8
:v8
版本信息
获取当前应用根目录:
remote.app.getAppPath();
使用node
的os
模块获取当前系统根目录:
os.homedir();
# 7.2 复制粘贴
Electron
提供的clipboard
在渲染进程和主进程都可使用,用于在系统剪贴板上执行复制和粘贴操作。
以纯文本的形式写入剪贴板:
clipboard.writeText(text[, type])
以纯文本的形式获取剪贴板的内容:
clipboard.readText([type]);
# 7.3 截图
desktopCapturer
用于从桌面捕获音频和视频的媒体源的信息。它只能在渲染进程中被调用。
下面的代码是一个获取屏幕截图并保存的实例:
getImg = () => {
this.setState({ imgMsg: "正在截取屏幕..." });
const thumbSize = this.determineScreenShotSize();
let options = { types: ["screen"], thumbnailSize: thumbSize };
desktopCapturer.getSources(options, (error, sources) => {
if (error) return console.log(error);
sources.forEach((source) => {
if (source.name === "Entire screen" || source.name === "Screen 1") {
const screenshotPath = path.join(os.tmpdir(), "screenshot.png");
fs.writeFile(screenshotPath, source.thumbnail.toPNG(), (error) => {
if (error) return console.log(error);
shell.openExternal(`file://${screenshotPath}`);
this.setState({ imgMsg: `截图保存到: ${screenshotPath}` });
});
}
});
});
};
determineScreenShotSize = () => {
const screenSize = screen.getPrimaryDisplay().workAreaSize;
const maxDimension = Math.max(screenSize.width, screenSize.height);
return {
width: maxDimension * window.devicePixelRatio,
height: maxDimension * window.devicePixelRatio,
};
};
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# 八、菜单
应用程序的菜单可以帮助我们快捷的到达某一功能,而不借助客户端的界面资源,一般菜单分为两种:
- 应用程序菜单:位于应用程序顶部,在全局范围内都能使用
- 上下文菜单:可自定义任意页面显示,自定义调用,如右键菜单
Electron
为我们提供了Menu
模块用于创建本机应用程序菜单和上下文菜单,它是一个主进程模块。
你可以通过Menu
的静态方法buildFromTemplate(template)
,使用自定义菜单模版来构造一个菜单对象。
template
是一个MenuItem
的数组,我们来看看MenuItem
的几个重要参数:
label
:菜单显示的文字click
:点击菜单后的事件处理函数role
:系统预定义的菜单,例如copy
(复制)、paste
(粘贴)、minimize
(最小化)...enabled
:指示是否启用该项目,此属性可以动态更改submenu
:子菜单,也是一个MenuItem
的数组
推荐:最好指定 role 与标准角色相匹配的任何菜单项,而不是尝试手动实现 click 函数中的行为。内置 role 行为将提供最佳的本地体验。
下面的实例是一个简单的额菜单template
。
const template = [
{
label: "文件",
submenu: [
{
label: "新建文件",
click: function () {
dialog.showMessageBox({
type: "info",
message: "嘿!",
detail: "你点击了新建文件!",
});
},
},
],
},
{
label: "编辑",
submenu: [
{
label: "剪切",
role: "cut",
},
{
label: "复制",
role: "copy",
},
{
label: "粘贴",
role: "paste",
},
],
},
{
label: "最小化",
role: "minimize",
},
];
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# 8.1 应用程序菜单
使用Menu
的静态方法setApplicationMenu
,可创建一个应用程序菜单,在 Windows
和 Linux
上,menu
将被设置为每个窗口的顶层菜单。
注意:必须在模块 ready 事件后调用此 API app。
我们可以根据应用程序不同的的生命周期,不同的系统对菜单做不同的处理。
app.on("ready", function () {
const menu = Menu.buildFromTemplate(template);
Menu.setApplicationMenu(menu);
});
app.on("browser-window-created", function () {
let reopenMenuItem = findReopenMenuItem();
if (reopenMenuItem) reopenMenuItem.enabled = false;
});
app.on("window-all-closed", function () {
let reopenMenuItem = findReopenMenuItem();
if (reopenMenuItem) reopenMenuItem.enabled = true;
});
if (process.platform === "win32") {
const helpMenu = template[template.length - 1].submenu;
addUpdateMenuItems(helpMenu, 0);
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 8.2 上下文菜单
使用Menu
的实例方法menu.popup
可自定义弹出上下文菜单。
let m = Menu.buildFromTemplate(template);
document
.getElementById("menuDemoContainer")
.addEventListener("contextmenu", (e) => {
e.preventDefault();
m.popup({ window: remote.getCurrentWindow() });
});
2
3
4
5
6
7
# 8.3 快捷键
在菜单选项中,我们可以指定一个accelerator
属性来指定操作的快捷键:
{
label: '最小化',
accelerator: 'CmdOrCtrl+M',
role: 'minimize'
}
2
3
4
5
另外,我们还可以使用globalShortcut
来注册全局快捷键。
globalShortcut.register("CommandOrControl+N", () => {
dialog.showMessageBox({
type: "info",
message: "嘿!",
detail: "你触发了手动注册的快捷键.",
});
});
2
3
4
5
6
7
CommandOrControl 代表在 macOS 上为 Command 键,以及在 Linux 和 Windows 上为 Control 键。
文中如有错误,欢迎在评论区指正,如果这篇文章帮助到了你,欢迎点赞和关注。