ipcmain.jsjavascript
var {Menu,shell,ipcMain,BrowserWindow,app} =require('electron'); var template = [ { label: '文件', submenu: [ { label: '新建', accelerator:"Ctrl+N", click: function(){ //主進程通知渲染進程操做文件 BrowserWindow.getFocusedWindow().webContents.send('action','new'); } }, { label: '打開', accelerator:"Ctrl+O", click: function(){ //主進程通知渲染進程操做文件 BrowserWindow.getFocusedWindow().webContents.send('action','open'); } }, { accelerator:"Ctrl+S", label: '保存', click: function(){ BrowserWindow.getFocusedWindow().webContents.send('action','save'); } }, { type: 'separator' }, { label: '打印', accelerator:"Ctrl+P", click: function(){ //打印功能經過 webContents https://electronjs.org/docs/api/web-contents BrowserWindow.getFocusedWindow().webContents.print(); } }, { label: '退出', accelerator:"Ctrl+Q", click: function(){ //要提示用戶保存 未保存的文件 //主進程通知渲染進程執行退出操做 BrowserWindow.getFocusedWindow().webContents.send('action','exit'); } } ] }, { label: '編輯', submenu: [ { label: '撤銷', role: 'undo' }, { label: '恢復', role: 'redo' }, { type: 'separator' }, { label: '截切', role: 'cut' }, { label: '複製', role: 'copy' }, { label: '黏貼', role: 'paste' }, { label: '刪除', role: 'delete' }, { label: '全選', role: 'selectall' } ] }, { label: '視圖', submenu: [ { label: '加載', role: 'reload' }, { label: '縮小', role: 'zoomin' }, { label: '放大', role: 'zoomout' }, { label: '重置縮放', role: 'resetzoom' }, { type: 'separator' }, { label: '全屏', role: 'togglefullscreen' } ] }, { label: '幫助', submenu: [ { label: '關於', click() { shell.openExternal('https://www.itying.com'); } } ] } ]; var m=Menu.buildFromTemplate(template); Menu.setApplicationMenu(m); //右鍵菜單 const contextMenuTemplate=[ { label: '撤銷', role: 'undo' }, { label: '恢復', role: 'redo' }, { type: 'separator' }, { label: '截切', role: 'cut' }, { label: '複製', role: 'copy' }, { label: '黏貼', role: 'paste' }, { type: 'separator' }, //分隔線 { label: '全選', role: 'selectall' } //Select All菜單項 ]; var contextMenu=Menu.buildFromTemplate(contextMenuTemplate); // 監聽右鍵事件 ipcMain.on('contextMenu',function(){ contextMenu.popup(BrowserWindow.getFocusedWindow()) }) //監聽客戶端的退出操做 ipcMain.on('exit-app',()=>{ app.quit(); })
ipcrender.jscss
var {ipcRenderer,remote}=require('electron'); var fs=require('fs'); document.title='無標題' //獲取文本框dom var textAreaDom=document.querySelector("#textArea"); /* 問題: 一、新建 打開 保存的問題 二、若是已經保存 第二次保存的時候不提示直接保存 三、判斷文件是否已經保存 改變軟件左上角的內容 */ var isSave=true; //判斷文件是否保存 var currentFile=''; //保存當前文件的路徑 //內容變化的時候 讓isSave等於false textAreaDom.oninput=function(){ if(isSave){document.title+=" *"} isSave=false; } document.addEventListener('contextmenu',function(e){ e.preventDefault(); ipcRenderer.send('contextMenu'); }) //監聽主進程的操做 ipcRenderer.on('action',function(event,action){ console.log(action); switch(action){ case "new": //判斷文件是否保存 若是沒有保存提示 並保存 askSaveDialog(); textAreaDom.value=''; break; case "open": //判斷文件是否保存 若是沒有保存提示 並保存 askSaveDialog(); //經過dialog打開文件 var dir= remote.dialog.showOpenDialog({ properties:['openFile'] }); if(dir){ var fsData=fs.readFileSync(dir[0]); //獲取文件裏面的東西 // textAreaDom.value=fsData; editor.setValue(fsData.toString()); //注意傳入的數據 } break; case "save": saveCurrentDoc(); break; case "exit": askSaveDialog(); //同步方法 //通知主進程退出應用 ipcRenderer.send('exit-app') break; } }) //判斷文件師傅保存並執行保存功能 function askSaveDialog(){ if(!isSave){ var index=remote.dialog.showMessageBox({ type:"question", message:'是否要保存此文件?', buttons:['Yes','No'] }) if(index==0){ //執行保存操做 saveCurrentDoc(); } } } //執行保存的方法 function saveCurrentDoc(){ if(!currentFile){ //當前文件路徑不存在 提示保存 var dir=remote.dialog.showSaveDialog({ defaultPath:'aaa.txt', filters: [ {name: 'All Files', extensions: ['*']} ] }); if(dir){ currentFile=dir; fs.writeFileSync(currentFile,editor.getValue()); isSave=true; //改變軟件的標題 document.title=currentFile; } }else{ // editor.getValue() 獲取編輯器的值 // fs.writeFileSync(currentFile,textAreaDom.value); fs.writeFileSync(currentFile,editor.getValue()); isSave=true; //改變軟件的標題 document.title=currentFile; } }
index.htmlhtml
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> <link rel="stylesheet" href="./static/css/index.css"> </head> <body> <textarea id="textArea"></textarea> </body> <link rel=stylesheet href="static/codemirror/doc/docs.css"> <link rel="stylesheet" href="static/codemirror/lib/codemirror.css"> <script src="static/codemirror/lib/codemirror.js"></script> <script src="static/codemirror/addon/selection/selection-pointer.js"></script> <script src="static/codemirror/mode/xml/xml.js"></script> <script src="static/codemirror/mode/javascript/javascript.js"></script> <script src="static/codemirror/mode/css/css.js"></script> <script src="static/codemirror/mode/vbscript/vbscript.js"></script> <script src="static/codemirror/mode/htmlmixed/htmlmixed.js"></script> <script> // Define an extended mixed-mode that understands vbscript and // leaves mustache/handlebars embedded templates in html mode var mixedMode = { name: "htmlmixed", scriptTypes: [{matches: /\/x-handlebars-template|\/x-mustache/i, mode: null}, {matches: /(text|application)\/(x-)?vb(a|script)/i, mode: "vbscript"}] }; var editor = CodeMirror.fromTextArea(document.getElementById("textArea"), { mode: mixedMode, selectionPointer: true }); </script> <style> .CodeMirror{ height: 100%; } </style> <script src="./renderer/ipcRenderer.js"></script> </html>
index.jsjava
import { app, BrowserWindow } from 'electron'; // Handle creating/removing shortcuts on Windows when installing/uninstalling. if (require('electron-squirrel-startup')) { // eslint-disable-line global-require app.quit(); } // Keep a global reference of the window object, if you don't, the window will // be closed automatically when the JavaScript object is garbage collected. let mainWindow; const createWindow = () => { // Create the browser window. mainWindow = new BrowserWindow({ width: 800, height: 600, webPreferences: { nodeIntegration: true } }); // and load the index.html of the app. mainWindow.loadURL(`file://${__dirname}/index.html`); // Open the DevTools. mainWindow.webContents.openDevTools(); // Emitted when the window is closed. mainWindow.on('closed', () => { // Dereference the window object, usually you would store windows // in an array if your app supports multi windows, this is the time // when you should delete the corresponding element. mainWindow = null; }); //引入icpMain require('./main/ipcMain.js'); }; // 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.on('ready', createWindow); // Quit when all windows are closed. app.on('window-all-closed', () => { // On OS X it is common for applications and their menu bar // to stay active until the user quits explicitly with Cmd + Q if (process.platform !== 'darwin') { app.quit(); } }); app.on('activate', () => { // On OS X 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 (mainWindow === null) { createWindow(); } }); // 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 import them here.
備註:node
CodeMirror在線編輯器插件: github地址:https://github.com/codemirror/CodeMirror 官網:http://codemirror.net/ CodeMirror api: http://codemirror.net/doc/manual.html#api 使用CodeMirror: 1.下載: 2、看文檔使用 http://codemirror.net/mode/index.html 注意: https://github.com/codemirror/CodeMirror CodeMirror最新版本使用的是es6的語法,可是因爲nodejs不支持 es6的import 因此咱們的項目裏面無法用最新的版本 教程使用的是codemirror-5.2 下載codemirror-5.2,而後看官方文檔使用 插件要設置和獲取值: doc.setValue設置值 doc.getValue 或獲取值 var editor = CodeMirror.fromTextArea(document.getElementById("textArea"), { mode: mixedMode, selectionPointer: true }); editor.setValue() editor.getValue() codemirror-5.2修改codemirror.js的地方: 17行左右: this.CodeMirror = mod(); 改成 window.CodeMirror = mod(); 8400行左右 return string.split(/\r\n?|\n/); 改成 return string.toString().split(/\r\n?|\n/); 或者能夠不修改,可是傳入數據必須是string fsData.toString()
運行項目:git
npm start