目次
概要
これまでのチュートリアルでは単一の画面を持つ Electron アプリでしたが、本記事では、子ウィンドウを作成するための方法を解説します。
本記事で紹介するコードは以下を参照ください。
electron-examples/07_electron-create-child-dialog
子ウィンドウを作成する
メインウィンドウでボタンをクリックしたら、子ウィンドウを開くアプリを作成します。 処理の流れとしては、次のようになります。
- 親ウィンドウの HTML 上でボタンをクリックすると、IPC によりメインレンダラーに子ウィンドウを開く指示を送信する
- メインレンダラーで子ウィンドウを開く指示を受信したら、子ウィンドウを作成する
1. プリロードスクリプトを作成する
チャンネル openDialog
でメインレンダラーに子ウィンドウを開く指示を送信する openDialog()
という API を用意します。
preload.ts
import { contextBridge, ipcRenderer } from "electron";
contextBridge.exposeInMainWorld("Electron", {
// Renderer -> Main
openDialog: (title: string) => ipcRenderer.send("openDialog", title),
});
2. メインプロセスで子ウィンドウを開く処理を作成する
ipcMain.on()
でチャンネル openDialog
のデータを受信した場合のコールバック関数を登録します。
この関数では、new BrowserWindow()
で子子ウィンドウを作成し、child.html
を読み込みます。
このとき、parent
引数に親ウィンドウを指定すると、子ウィンドウは親ウィンドウより常に前面に表示されるようになります。
main.ts
import { app, BrowserWindow, ipcMain, IpcMainEvent } from "electron";
import * as path from "path";
const createWindow = () => {
const win = new BrowserWindow({
webPreferences: {
preload: path.join(__dirname, "preload.js"),
},
});
win.webContents.openDevTools();
win.loadFile("index.html");
ipcMain.on("openDialog", (event: IpcMainEvent, title: string) => {
const dialog = new BrowserWindow({
parent: win,
title: title,
});
dialog.webContents.openDevTools();
dialog.loadFile("child.html");
});
};
app.whenReady().then(createWindow);
3. 親ウィンドウと子ウィンドウの HTML ファイルを作成する
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
</head>
<body>
<h1>親ウィンドウ</h1>
<button onclick="Electron.openDialog('Child')">子ウィンドウを開く</button>
<p id="recieve"></p>
</body>
</html>
child.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
</head>
<body>
<h1>子ウィンドウ</h1>
</body>
</html>
重複起動を防止する
すでに子ウィンドウが開いている場合はウィンドウを開かないようにするには、次のようにします。
childWin
をグローバル変数にし、ウィンドウが開かれていないときは値がnull
となるようにするchildWin
がnull
でない場合は、すでにウィンドウが開かれているので、ウィンドウを開かないchildWin
のclosed
イベントを購読し、ウィンドウが閉じられた場合は、再びchildWin
にnull
を設定する
main.ts
import { app, BrowserWindow, ipcMain, IpcMainEvent } from "electron";
import * as path from "path";
let childWin: BrowserWindow | null = null;
const createWindow = () => {
const win = new BrowserWindow({
webPreferences: {
preload: path.join(__dirname, "preload.js"),
},
});
win.webContents.openDevTools();
win.loadFile("index.html");
ipcMain.on("openDialog", (event: IpcMainEvent, title: string) => {
if (childWin !== null) {
return;
}
childWin = new BrowserWindow({
parent: win,
title: title,
});
childWin.webContents.openDevTools();
childWin.loadFile("child.html");
childWin.on("closed", () => (childWin = null));
});
};
app.whenReady().then(createWindow);
モーダルダイアログを作成する
子ウィンドウが開かれているとき、親ウィンドウは操作できないようにするモーダルダイアログを作成するには、子ウィンドウ作成時に modal: true
を指定します。
main.ts
import { app, BrowserWindow, ipcMain, IpcMainEvent } from "electron";
import * as path from "path";
const createWindow = () => {
const win = new BrowserWindow({
webPreferences: {
preload: path.join(__dirname, "preload.js"),
},
});
win.webContents.openDevTools();
win.loadFile("index.html");
ipcMain.on("openDialog", (event: IpcMainEvent, title: string) => {
const childWin = new BrowserWindow({
parent: win,
title: title,
modal: true,
});
childWin.webContents.openDevTools();
childWin.loadFile("child.html");
});
};
app.whenReady().then(createWindow);
コメント