npm init -y
// 安裝Electron
npm i --save-dev electron
// 建立main.js 並在package.json中設定為入口
"main":"main.js"
// 建立index.html 用來書寫頁面內容
初始化程式碼
package.json
{
"name": "myElectron",
"version": "1.0.0",
"description": "",
"main": "main.js",
"scripts": {
"start": "nodemon --watch main.js --exec npm run build",
"build": "electron ."
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"electron": "^24.4.0"
},
"dependencies": {
"@electron/remote": "^2.0.9"
}
}
main.js
const { app, BrowserWindow } = require( 'electron' )
// app 哪個控制應用程式的事件生命週期
// BrowserWindow 建立和管理應用程式Windows
const createWindow = () => {
let mainWin = new BrowserWindow( {
width: 800,
height: 600,
show: false,
backgroundColor: 'aqua',
} )
mainWin.loadFile( 'index.html' )
mainWin.on( 'ready-to-show', () => {
mainWin.show()
} )
mainWin.on( 'close', () => {
mainWin = null
} )
}
app.on( 'ready', () => {
createWindow()
} )
ready: app初始化完成
dom-ready: 一個視窗中的文字載入完成
did-finsh-load: 導航完成時觸發
closed:當視窗關閉時觸發,此時應刪除視窗參照
window-all-closed: 所有視窗關閉時觸發
before-quit: 在關閉視窗之前觸發
will-quit: 在視窗關閉並且應用退出時觸發
quit: 當所有視窗被關閉時觸發
mainWin.webContents.on( 'did-finish-load', () => {
console.log( '333-did-finish-load' );
} )
// 視窗中文字載入完成
mainWin.webContents.on( 'dom-ready', () => {
console.log( '222dom-ready' );
} )
// 主視窗關閉
mainWin.on( 'closed', () => {
console.log( '88888-事件發生' );
} )
app.on( 'window-all-closed', () => {
console.log( '444-window-all-closed' );
if ( process.platform !== 'darwin' ) app.quit()
} )
app.on( 'ready', () => {
console.log( '111- app初始化完成' );
createWindow()
} )
app.on( 'before-quit', () => {
console.log( '555-before-quit' );
} )
app.on( 'will-quit', () => {
console.log( '666-will-quit' );
} )
app.on( 'quit', () => {
console.log( '777-quit' );
} )
const mainWin = new BrowserWindow( {
x: 100, //x y 視窗開始位置
y: 100,
show: false,
width: 800,
height: 600,
minHeight: 400, // min max 最小最大寬高
minWidth: 50,
maxHeight: 1000,
maxWidth: 1200,
resizable: false, // 視窗是否可調整
minimizable: true,
maximizable: true,
title: '桌面應用',
frame: false,
// autoHideMenuBar: true,
webPreferences: {
nodeIntegration: true, // 執行渲染程序使用node
enableRemoteModule: true,
contextIsolation: false
}
} )
require( '@electron/remote/main' ).initialize()
require( "@electron/remote/main" ).enable( mainWin.webContents )
標題設定
圖示修改
icon
frame 是否顯示預設導航選單 + 標題
transparent 設定透明
autoHideMenuBar 是否隱藏 導航選單
點選開啟新視窗
備註: 在main中執行時是主程序 在index.html中執行時是渲染程序
app BrowserWindow 都屬於主程序得模組
出於安全考慮 渲染程序中沒有辦法使用require 可在main中設定
渲染程序不允許直接使用主程序模組 通過remote進行呼叫
electron 12 之後就已經廢除了 remote
// 替換為:
const { BrowserWindow } = require('@electron/remote')
// 在主程序中:
require('@electron/remote/main').initialize()
mainWin.maximize()
// 最大化還原
mainWin.restore()
mainWin.minimize()
// <div class="btnGroup">
// <button>最小</button>
// <button>最大</button>
// <button>關閉</button>
// </div>
// 獲取按鈕組
var btnGroup = document.getElementsByClassName( 'btnGroup' )[0].getElementsByTagName( 'button' )
btnGroup[0].addEventListener( 'click', () => {
if ( !mainWin.isMinimized() ) {
mainWin.minimize()
}
} )
btnGroup[1].addEventListener( 'click', () => {
console.log( '最大化', mainWin.isMaximized() );
if ( !mainWin.isMaximized() ) { // 判斷視窗是否最大化
mainWin.maximize() // 最大化
} else {
mainWin.restore()
}
} )
btnGroup[2].addEventListener( 'click', () => {
mainWin.close()
} )
window.onbeforeunload = function() {
return false
}
let menuArr = [{label:'開啟',type:'normal',role:'copy'}]
let menu = Menu.buildFromTemplate( menuArr )
Menu.setApplicationMenu( menu )
let temp = [
{
label: 'send',
click () {
BrowserWindow.getFocusedWindow().webContents.send( 'msg2', '主程序發來訊息' )
}
}
]
let tem = Menu.buildFromTemplate( temp )
Menu.setApplicationMenu( tem )
// <button id="selfMenu">自定義選單</button>
// <input type="text" value="" id="inputText">
// <button id="addMenu">加入新增選單</button>
1. 找到 Menu MenuItem
2. new Menu() 可以將 new MenuItem() 建立的選單進行新增到選單欄中
let remote = require( '@electron/remote' )
let Menu = remote.Menu
let MenuItem = remote.MenuItem
window.addEventListener( 'DOMContentLoaded', () => {
// 獲取按鈕-- 自定義選單
let selfBtn = document.getElementById( 'selfMenu' )
let inputVal = document.getElementById( 'inputText' )
let addMenu = document.getElementById( 'addMenu' )
let selfMenuItem = new Menu()
selfBtn.addEventListener( 'click', () => {
let menuFile = new MenuItem( { label: '檔案', type: 'normal' } )
let menuEdit = new MenuItem( { label: '編輯', type: 'normal' } )
let menuSelf = new MenuItem( { label: '自定義選單', submenu: selfMenuItem } )
let menu = new Menu()
menu.append( menuFile )
menu.append( menuEdit )
menu.append( menuSelf )
Menu.setApplicationMenu( menu )
} )
addMenu.addEventListener( 'click', () => {
let content = inputVal.value.trim()
if ( content ) {
selfMenuItem.append( new MenuItem( { label: content, type: 'normal' } ) )
content = ''
}
} )
})
建立選單
監聽contextmenu 事件 並阻止預設行為
menu.popup({window:remote.getCurrentWindow()})
// 右鍵選單
let rightMenu = [
{
label: 'Run Code',
type: 'normal'
},
{
label: '重新整理',
role: 'refresh'
},
{
type: 'separator'
},
{
label: '其他功能',
click () {
console.log( '其他功能已執行' );
}
}
]
let menuRight = Menu.buildFromTemplate( rightMenu )
window.addEventListener( 'contextmenu', ( e ) => {
e.preventDefault()
menuRight.popup( {
window: remote.getCurrentWindow
} )
} )
- ipcMain 內部 e.sender.send('xx',xxx)
- ipcMain 內部接收 e.returnValue
BrowserWindow.getFocusedWindow().webContents.send('mtp',來自於主程序的訊息) // 依賴按鈕之類的事件觸發‘
mainWin.contents.openDevtools() // 開啟控制檯
// main.js
let { app, BrowserWindow, ipcMain } = require( 'electron' )
ipcMain.on( 'msg1', ( e, ev ) => {
console.log( e, ev );
e.sender.send( 'msg2', 666 )
// BrowserWindow.getFocusedWindow().webContents.send( 'msg2', 666 )
} )
// index.js
let remote = require( '@electron/remote' )
let { ipcRenderer } = require( 'electron' )
window.addEventListener( 'DOMContentLoaded', () => {
console.log( 666 );
ipcRenderer.send( 'msg1', '渲染程序發來賀電' )
ipcRenderer.on( 'msg2', ( e, ev ) => {
console.log( e, ev );
} )
} )
- BrowserWindow 範例屬性 id
- BrowserWindow.fromId(mainWin.id)
通訊的時候儲存 資訊到localStorage中
新視窗開啟時取值並使用
// main.js
ipcMain.on( 'msg', ( e, data ) => {
if ( data ) {
// 開啟第二個視窗
let sub2 = new BrowserWindow( {
parent: BrowserWindow.fromId( mainId ),
width: 300,
height: 150,
webPreferences: {
nodeIntegration: true,
enableRemoteModule: true,
contextIsolation: false
}
} )
sub2.loadFile( 'sub.html' )
sub2.on( 'close', () => {
sub2 = null
} )
}
} )
// 主程序接收視窗二的資訊
ipcMain.on( 'toMain', ( e, data ) => {
// 將資料轉發給index程序
let mainOpen = BrowserWindow.fromId( mainId )
mainOpen.webContents.send( 'win2', data )
} )
// index.js
let remote = require( '@electron/remote' )
let { ipcRenderer } = require( 'electron' )
window.addEventListener( 'DOMContentLoaded', () => {
// 獲取開啟視窗按鈕
let btnOpen = document.getElementById( 'openTwo' )
btnOpen.addEventListener( 'click', () => {
localStorage.setItem( 'name', '張三' )
ipcRenderer.send( 'msg', true )
} )
ipcRenderer.on( 'win2', ( e, data ) => {
console.log( 'index程序已經接收到', data );
} )
} )
option.title,option
)
globalShortcut('ctrl + q') // 返回布林值 true/false
globalShortcut.isRegistered('ctrl + q')
- 時機 -- 在生命週期 will-quit中進行登出
- globalShortcut.unregister('ctrl + q')
- writeText
- readText
// 將剪貼版中圖片寫到DOM中
3. let oimg = clipboard.readImage()
4. let imgDom = new Image()
5. imgDom.src = oimg.toDataURL()
6. document.body.appendChild( imgDom )