今度は、Electron+TypeScriptなアプリにメニューを追加してみます。
Electronのアプリで使えるメニューには、ウィンドウ上部(Macの場合ディスプレイの上)に表示されるアプリケーションメニューと、画面右クリック時に表示されるコンテキストメニューの2種類のものがあります。
Electronを使ってそれぞれ順番に作っていってみます。
参考
公式ドキュメントの↓あたりを参考にいろいろやってみます。
http://electron.atom.io/docs/v0.34.0/api/menu/
http://electron.atom.io/docs/v0.34.0/api/menu-item/
以下では、前回の↓サンプルコードをベースに色々やってみました。
TypeScript+Electronでデスクトップアプリを作ってみる - SourceChord
アプリケーションメニューの作成
メニューをつけるには、Menuモジュールを利用します。
このモジュールはBrowserProcess用のモジュールなので、RendererProcessから利用する場合には、remote.require('Menu')
とする必要があります。
アプリ全体のメニューを設定する
アプリのエントリポイントとなるmain.tsでメニューの設定をしてみます。
まずは、Menu.buildFromTemplateメソッドで、メニューの項目などを作成します。
そして、作ったメニューをMenu.setApplicationMenuメソッドの引数に渡すと、メニューをつけることができます。
main.ts
import app = require('app'); import BrowserWindow = require('browser-window'); import Menu = require('menu'); require('crash-reporter').start(); // メインウィンドウの参照をグローバルに持っておく。var mainWindow: GitHubElectron.BrowserWindow = null; var menu = Menu.buildFromTemplate([{ label: 'File', submenu: [{label: 'New File'}, {type: 'separator'}, {label: 'Save'}, {label: 'Save As...'}, {type: 'separator'}, {label: 'Exit', click: onExit}]}, { label: 'Edit', submenu: [{label: 'Copy', accelerator: 'CmdOrCtrl+C'}, {label: 'Paste', accelerator: 'CmdOrCtrl+V'}, ]}, { label: 'Help', submenu: [{label: 'About'}]}, ]); Menu.setApplicationMenu(menu); // すべてのウィンドウが閉じられた際の動作 app.on('window-all-closed', function() {// OS X では、ウィンドウを閉じても一般的にアプリ終了はしないので除外。if (process.platform != 'darwin') { app.quit(); }}); app.on('ready', function() {// 新規ウィンドウ作成 mainWindow = new BrowserWindow({ width: 800, height: 600 }); // index.htmlを開く mainWindow.loadUrl('file://' + __dirname + '/index.html'); // ウィンドウが閉じられたら、ウィンドウへの参照を破棄する。 mainWindow.on('closed', function() { mainWindow = null; }); }); function onExit(){ app.quit(); }
こんな風にちゃんとメニューが表示されました。
このメソッドを使ってメニューをつけた場合、BrowserWindow側で別途メニューの設定をしていない限り、すべてのウィンドウについて、ここでセットしたメニューが表示されるようです。
指定したウィンドウにメニューをつける
BrowserWindowクラスのsetMenuというメソッドでもメニューをつけることができます。
こうすると、setMenuメソッドを呼び出したウィンドウについてだけメニューをつけられるみたい。
mainWindow = new BrowserWindow({ width: 800, height: 600 }); mainWindow.setMenu(menu);
コンテキストメニューの作成
続いてコンテキストメニューを作ってみます。
ウィンドウ上を右クリックしたときの'contextmenu'イベントのタイミングでポップアップ表示をします。 UI上のイベントを拾うので、今度はRendererProcessからメニュー表示をしてみます。
コンテキストメニューも、前述のアプリケーションメニューと同じように、まずはMenu.buildFromTemplateメソッドでMenuクラスのインスタンスを作ります。
コンテキストメニューとして表示するには、Menu.popupメソッドを呼び出します。
引数には、ポップアップを表示させるウィンドウを指定します。
index.ts
var remote = require('remote'); var app = remote.require('app'); var BrowserWindow = remote.require('browser-window'); var Menu = remote.require('menu'); var menu = Menu.buildFromTemplate([{label: 'すべて選択'}, {type: 'separator'}, {label: 'Copy', accelerator: 'CmdOrCtrl+C'}, {label: 'Paste', accelerator: 'CmdOrCtrl+V'}]); window.addEventListener('contextmenu', function (e) { e.preventDefault(); menu.popup(remote.getCurrentWindow()); }, false);
その他
メニューを自動で隠す設定
アプリケーションメニューでは、BrowserWindowクラスのsetAutoHideMenuBarというメソッドを使うと、メニューを自動で隠すようにすることができます。
Altを押すとメニューが出てきます。そしてフォーカスが外れると自動で隠れます。
mainWindow.setAutoHideMenuBar(true);
そんなに頻繁には使わないかもしれないけど、ウィンドウの領域を極力広く使いたいようなケースでは使うこともあるのかな。