翼度科技»论坛 编程开发 .net 查看内容

WPF 应用迁移到 Electron 框架过程记录

5

主题

5

帖子

15

积分

新手上路

Rank: 1

积分
15
前一段时间我用 WPF 开发了一个查看 emoji 表情的小工具 https://github.com/he55/EmojiViewer ,由于最近我使用 macOS 系统比较多,我想能在 macOS 系统上也能使用这个工具。于是我尝试将 WPF 应用迁移到 Electron 框架,感觉这个框架很强大,在这里记录一下应用迁移的过程。

安装 Electron 环境


  • 安装 nodejs。到官网 https://nodejs.org/en 下载最新的 nodejs,然后安装

  • 打开命令行输入 git clone https://github.com/electron/electron-quick-start.git 命令克隆 Electron 模板项目,使用模板可以快速搭建应用。
  • 然后使用 cd electron-quick-start 目录进入到目录,接着运行 npm install 命令还原项目。
  • 使用 vscode 打开文件夹,项目文件如下

编写代码


  • Electron 分为主进程和渲染进程,对文件、系统和窗口的操作需要在主线程,界面渲染在渲染进程。创建窗口属于主进程的工作,需要到 main.js 文件编写代码。创建窗口使用 BrowserWindow 对象,width 和 height 分别设置窗口宽度和高度,autoHideMenuBar 设置是否隐藏菜单,最后使用 loadFile 加载页面文件并显示窗口。
  1. function createWindow() {
  2.   const mainWindow = new BrowserWindow({
  3.     width: 915,
  4.     height: 560,
  5.     autoHideMenuBar: true,
  6.     webPreferences: {
  7.       preload: path.join(__dirname, 'preload.js')
  8.     }
  9.   })
  10.   mainWindow.loadFile('index.html')
  11. }
复制代码

  • 监听 whenReady 事件,等待应用初始化完成后显示窗口
  1. app.whenReady().then(() => {
  2.   createWindow()
  3.   app.on('activate', function () {
  4.     if (BrowserWindow.getAllWindows().length === 0) createWindow()
  5.   })
  6. })
复制代码

  • 修改 index.html 文件,界面部分使用了 vue 进行渲染
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4.   <meta charset="UTF-8">
  5.   
  6.   <link href="./styles.css" rel="stylesheet">
  7.   <title>EmojiViewer</title>
  8. </head>
  9. <body>
  10.   
  11.     <ul >
  12.       <li v-for="(item, key) in categories" : @click="catetoryItemClick(item)">{{ key }}</li>
  13.     </ul>
  14.     <ul  ref="mainElement">
  15.       <li v-for="emoji in emojis" : @click="emojiItemClick(emoji)">
  16.         <img :src="emoji.previewImage" alt="">
  17.         <p>{{emoji.name}}</p>
  18.       </li>
  19.     </ul>
  20.    
  21.       <img :src="selectedEmoji.previewImage">
  22.       <p>{{ selectedEmoji.name }}</p>
  23.       <button @click="copyEmoji(selectedEmoji)" type="button">Copy Emoji</button>
  24.       <button @click="copyImage(selectedEmoji)" type="button">Copy Image</button>
  25.       <button @click="openFile(selectedEmoji)" type="button">Open File</button>
  26.    
  27.   
  28.   
  29. </body>
  30. </html>
复制代码

  • 在 renderer.js 文件中编写页面处理代码
  1. window.addEventListener('DOMContentLoaded', async () => {
  2.     const { createApp, ref, onMounted } = Vue
  3.     let emojiData = await ipc.getData()
  4.     createApp({
  5.         setup() {
  6.             const mainElement = ref(null)
  7.             const categories = ref(emojiData)
  8.             const emojis = ref([])
  9.             const selectedEmoji = ref({})
  10.             function copyEmoji(emoji) {
  11.                 ipc.ipc('writeText', emoji.metadata.glyph)
  12.             }
  13.             function copyImage(emoji) {
  14.                 ipc.ipc('writeImage', emoji.previewImage)
  15.             }
  16.             function openFile(emoji) {
  17.                 ipc.ipc('showItemInFolder', emoji.previewImage)
  18.             }
  19.             let lastSelectedEmojis
  20.             function catetoryItemClick(items) {
  21.                 if (lastSelectedEmojis) {
  22.                     lastSelectedEmojis.isActive = false
  23.                 }
  24.                 items.isActive = true
  25.                 lastSelectedEmojis = items
  26.                 // const main = document.querySelector('.main')
  27.                 mainElement.value.scrollTop = 0
  28.                 emojis.value = items
  29.             }
  30.             function emojiItemClick(emoji) {
  31.                 if (selectedEmoji.value) {
  32.                     selectedEmoji.value.isActive = false
  33.                 }
  34.                 emoji.isActive = true
  35.                 selectedEmoji.value = emoji
  36.             }
  37.             onMounted(() => {
  38.                 catetoryItemClick(emojiData['Activities'])
  39.                 emojiItemClick(emojiData['Activities'][0])
  40.             })
  41.             return {
  42.                 mainElement,
  43.                 categories,
  44.                 emojis,
  45.                 selectedEmoji,
  46.                 catetoryItemClick,
  47.                 emojiItemClick,
  48.                 copyEmoji,
  49.                 copyImage,
  50.                 openFile,
  51.             }
  52.         }
  53.     }).mount('#app')
  54. })
复制代码

  • 读取文件,node 提供了文件操作相关的 api 可以很方便的操作文件系统。
  1. function loadData(assetPath) {
  2.   const dirs = fs.readdirSync(assetPath)
  3.   const data = []
  4.   const groupData = {}
  5.   for (const dir of dirs) {
  6.     const fullPath = path.resolve(assetPath, dir)
  7.     const metadata = require(path.resolve(fullPath, 'metadata.json'))
  8.     let previewImage
  9.     let imagePaths = [path.resolve(fullPath, '3D'), path.resolve(fullPath, 'Default', '3D')]
  10.     for (const imagePath of imagePaths) {
  11.       if (fs.existsSync(imagePath)) {
  12.         let files = fs.readdirSync(imagePath)
  13.         if (files.length === 0)
  14.           return
  15.         previewImage = path.resolve(imagePath, files[0])
  16.       }
  17.     }
  18.     const { unicode, group } = metadata
  19.     const obj = {
  20.       metadata,
  21.       id: unicode,
  22.       name: dir,
  23.       previewImage,
  24.     }
  25.     data.push(obj)
  26.     if (!groupData[group])
  27.       groupData[group] = []
  28.     groupData[group].push(obj)
  29.   }
  30.   return groupData
  31. }
复制代码
完整代码(WPF 版本) https://github.com/he55/EmojiViewer
完整代码(vue 版本) https://github.com/he55/web-learn/tree/main/9.electron-emoji-viewer(vue)
完整代码(js 原生版本) https://github.com/he55/web-learn/tree/main/6.electron-emoji-viewer

来源:https://www.cnblogs.com/he55/p/18046511
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x

举报 回复 使用道具