// Modules to control application life and create native browser windowconst { app, BrowserWindow, screen, ipcMain } = require('electron')const path = require('path')function createWindow() { // Create the browser window. const mainWindow = new BrowserWindow({ width: 200, height: 200, frame: false, webPreferences: { // node默认会被关掉,但是我们用的是本地文件。开启没事儿 nodeIntegration: false, preload: path.join(__dirname, 'preload.js') } }) // and load the index.html of the app. mainWindow.loadFile('index.html') ipcMain.handle('window-close', () => { mainWindow.close() }) windowMove(mainWindow) // Open the DevTools. // mainWindow.webContents.openDevTools()}// This method will be called when Electron has finished// initialization and is ready to create browser windows.// Some APIs can only be used after this event occurs.app.whenReady().then(() => { createWindow() app.on('activate', function () { // On macOS it's common to re-create a window in the app when the // dock icon is clicked and there are no other windows open. if (BrowserWindow.getAllWindows().length === 0) createWindow() })})// Quit when all windows are closed, except on macOS. There, it's common// for applications and their menu bar to stay active until the user quits// explicitly with Cmd + Q.app.on('window-all-closed', function () { if (process.platform !== 'darwin') app.quit()})// In this file you can include the rest of your app's specific main process// code. You can also put them in separate files and require them here./** * 窗口移动 * @param win */function windowMove(win) { let winStartPosition = { x: 0, y: 0 }; let mouseStartPosition = { x: 0, y: 0 }; let movingInterval = null; /** * 窗口移动事件 */ ipcMain.handle("window-move-open", (events, canMoving) => { if (canMoving) { // 读取原位置 const winPosition = win.getPosition(); winStartPosition = { x: winPosition[0], y: winPosition[1] }; mouseStartPosition = screen.getCursorScreenPoint(); // 清除 if (movingInterval) { clearInterval(movingInterval); } // 新开 movingInterval = setInterval(() => { // 实时更新位置 const cursorPosition = screen.getCursorScreenPoint(); const originX = winStartPosition.x + cursorPosition.x - mouseStartPosition.x; const originY = winStartPosition.y + cursorPosition.y - mouseStartPosition.y; console.log(originX, originX) const { workArea, id } = screen.getDisplayNearestPoint({ x: originX, y: originY }) const { x, y, width, height } = workArea // 自定义 const winWidth = 200 const winHeight = 200 const peekX = originX + winWidth const peekY = originY + winHeight if (originX - x > width - winWidth || originX - x < 0 || originY - y > height - winHeight || originY - y < 0) { const { id: xOtherId } = screen.getDisplayNearestPoint({ x: peekX, y: originY }) const { id: yOtherId } = screen.getDisplayNearestPoint({ x: originX, y: peekY }) console.log('边界', id, xOtherId, yOtherId) if (xOtherId !== id && yOtherId === id) { if (originY - y > height - winHeight || originY - y < 0) { console.log('边界,y轴动') } else { win.setPosition(originX, originY); } } if (yOtherId !== id && xOtherId === id) { if (originX - x > width - winWidth || originX - x < 0) { console.log('边界,x轴动') } else { win.setPosition(originX, originY); } } } else { win.setPosition(originX, originY); } }, 16); } else { clearInterval(movingInterval); movingInterval = null; } });}
<!DOCTYPE html><html> <head> <meta charset="UTF-8"> <!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP --> <meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'"> <link href="./styles.css" rel="stylesheet"> <title>Hello World!</title> </head> <body> <div class="blank">导航条</div> <button id="close">Close</button> <h1>Hello World!</h1> We are using Node.js <span id="node-version"></span>, Chromium <span id="chrome-version"></span>, and Electron <span id="electron-version"></span>. <!-- You can also require other files to run in this process --> <script src="./renderer.js"></script> </body></html>
// All of the Node.js APIs are available in the preload process.// It has the same sandbox as a Chrome extension.const { contextBridge, ipcRenderer} = require("electron");contextBridge.exposeInMainWorld( "api", { async aa() { await ipcRenderer.invoke('window-close') }, async move(canMoving) { await ipcRenderer.invoke('window-move-open', canMoving) } });window.addEventListener('DOMContentLoaded', () => { const replaceText = (selector, text) => { const element = document.getElementById(selector) if (element) element.innerText = text } for (const type of ['chrome', 'node', 'electron']) { replaceText(`${type}-version`, process.versions[type]) } console.log('preload')})
// This file is required by the index.html file and will// be executed in the renderer process for that window.// No Node.js APIs are available in this process because// `nodeIntegration` is turned off. Use `preload.js` to// selectively enable features needed in the rendering// process.const close = document.querySelector("#close")close.addEventListener("click", () => { console.log('close') window.api.aa()})const blank = document.querySelector('.blank')let prevent = function (e) { e.preventDefault() }window.addEventListener('mousedown', (e) => { debugger if (e.target instanceof HTMLInputElement || e.target instanceof HTMLButtonElement || e.target instanceof HTMLTextAreaElement ) { window.addEventListener("selectstart", prevent); window.api.move(false); return; } window.api.move(true);})window.addEventListener('mouseup', (e) => { debugger window.removeEventListener("selectstart", prevent); window.api.move(false);})window.addEventListener('mouseup', () => { window.removeEventListener("selectstart", prevent); window.api.move(false);})
/* styles.css *//* Add styles here to customize the appearance of your app */* { padding: 0; margin: 0; box-sizing: border-box;}.blank { width: 100%; height: 20px; background: red;}html,body{ -moz-user-select: none; -khtml-user-select: none; user-select: none;}