ユーザーの視点からファイルを開く方法を考えると、3つの方法があると思います。
1.Menu,ショートカットキーでファイル選択ダイアログを開いてファイルを選択する
2.開きたいファイルをWindowにドラッグ&ドロップする
3.ファイルをダブルクリックしてElectronアプリで開く
この記事では1の"Menu,ショートカットキーでファイル選択ダイアログを開いてファイルを選択する"機能の実装方法について説明します。
自分の環境はこの記事を参照。UIの作成にReactを使っています。
情報が正しくなかったり、もっとスマートな実装方法があったりするかもしれませんがあしからず。
#2実装方法
Menuとdialogは基本的にメインプロセスでしか取扱えないらしいです。なのでメインプロセスでMenuの作成とdialogを表示する処理を行います。そしてdialogを表示したあとにレンダラープロセスにイベントを飛ばします。
メインプロセスとかレンダラープロセスとか何ぞ?という方はこちら
main.js
const { Menu, dialog } = require('electron')
// メニューの作成
function createMenu() {
const template = [
{
label: 'Electron',
submenu: [
{
label: 'about'
}
]
},
{
label: 'File',
submenu: [
{
label: 'Open..',
accelerator: 'CmdOrCtrl+O', // ショートカットキーを設定
click: () => { openFile() } // 実行される関数
}
]
}
]
const menu = Menu.buildFromTemplate(template)
Menu.setApplicationMenu(menu);
}
// ファイル選択ダイアログを開く
function openFile() {
dialog.showOpenDialog({ properties: ['openFile'] }, (filePath) => {
// レンダラープロセスにイベントを飛ばす
mainWindow.webContents.send('open_file', filePath);
})
}
// 未検証だけどMenuを作成するタイミングは別にここじゃなくても良い気がする。
app.on('ready', createMenu)
そしてレンダラープロセス側でイベントを受け取る。
App.js
import '../assets/css/App.css'
import React, { Component } from 'react'
const { remote, ipcRenderer } = require('electron')
const { Menu, MenuItem } = remote
class App extends React.Component {
constructor(props) {
super(props)
this.state = { path: '' }
this.init();
}
init() {
this.setup();
}
setup() {
// イベントを受け取る
ipcRenderer.on('open_file', (event, arg) => {
// ファイルパスからファイル名を抜き取る
let filePath = arg[0];
filePath = filePath.split('\\');
const fileName = filePath[filePath.length - 1];
console.log(fileName);
// Stateの更新
this.setState({ path: fileName });
})
}
render() {
return (
<div>
<h1>Hello, Electron!</h1>
<p>{this.state.path}</p>
</div>
)
}
}
export default App
#ファイルじゃなくてフォルダを選択させたい場合
.js
dialog.showOpenDialog({ properties: ['openDirectory'] }, (filePath) => {
mainWindow.webContents.send('open_file', filePath);
})
いろいろ設定できるみたいなので公式のドキュメントを参照してください。