본문 바로가기
개발/Electron

일렉트론 - Menu 모듈로 메뉴 만들기 (Create Native Application Menus and Context Menus)

by 피로물든딸기 2024. 1. 3.
반응형

Electron 전체 링크

 

참고 

- https://www.electronjs.org/docs/latest/api/menu

 

electron.js를 아래와 같이 수정한다.

const { app, BrowserWindow, Menu } = require("electron"); // Menu 추가
const path = require("path");
const isDev = require("electron-is-dev");

function createWindow() {
  const win = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      nodeIntegration: true,
    },
  });

  win.loadURL(
    isDev
      ? "http://localhost:3000"
      : `file://${path.join(__dirname, "../build/index.html")}`
  );
}

const test = () => { // test code
  console.log("log!!", __dirname);
};

function createMyMenu() { // Customize Menu
  const template = [
    {
      label: "File",
      submenu: [
        {
          label: "새창",
          accelerator: "CmdOrCtrl+N",
          click: createWindow,
        },
        { type: "separator" },
        { label: "임시 메뉴", enabled: false },

        {
          label: "로그",
          enabled: true,
          click: test,
          icon: __dirname + "/logo16.png",
        },
      ],
    },
    {
      label: "Options",
      submenu: [
        {
          label: "토글",
          type: "checkbox",
          click: (menuItem) => {
            console.log(`Checkbox state: ${menuItem.checked}`);
          },
        },
      ],
    },
    {
      label: "Role",
      submenu: [
        { label: "복사", accelerator: "CmdOrCtrl+C", role: "copy" },
        { label: "붙여넣기", accelerator: "CmdOrCtrl+V", role: "paste" },
        { label: "잘라내기", accelerator: "CmdOrCtrl+X", role: "cut" },
        {
          label: "모두 선택하기",
          accelerator: "CmdOrCtrl+A",
          role: "selectall",
        },
        { label: "취소하기", accelerator: "CmdOrCtrl+Z", role: "undo" },
        { type: "separator" },
        { label: "다시 시도", accelerator: "CmdOrCtrl+R", role: "redo" },
        { label: "원본 서식 유지 후 붙여넣기", role: "pasteandmatchstyle" },
        { label: "윈도우 최소화", role: "minimize" },
        {
          label: "전체 화면",
          accelerator: "Alt+Enter",
          role: "togglefullscreen",
        },
        { type: "separator" },
        { label: "윈도우 닫기", accelerator: "CmdOrCtrl+W", role: "close" },
        { label: "App 종료하기", accelerator: "Alt+F4", role: "quit" },
      ],
    },
    {
      label: "View",
      submenu: [
        {
          label: "재실행",
          accelerator: "CmdOrCtrl+R",
          click: (item, focusedWindow) =>
            focusedWindow && focusedWindow.reload(),
        },
        {
          label: "개발자 모드",
          accelerator:
            process.platform === "darwin" ? "Alt+Command+I" : "Ctrl+Shift+I",
          click: (item, focusedWindow) =>
            focusedWindow && focusedWindow.toggleDevTools(),
        },
      ],
    },
  ];

  const appMenu = Menu.buildFromTemplate(template);
  Menu.setApplicationMenu(appMenu);
}

app.whenReady().then(() => {
  createWindow();
  createMyMenu();
});

app.on("window-all-closed", function () {
  if (process.platform !== "darwin") app.quit();
});

 

일렉트론에서 메뉴를 수정하기 위해 Menu 모듈을 사용한다.

const { app, BrowserWindow, Menu } = require("electron"); // Menu 추가

 

createMyMenu를 구현하고 createWindow와 같이 실행해주면 된다.

app.whenReady().then(() => {
  createWindow();
  createMyMenu();
});

 

메뉴에서는 template를 구성한 후, buildFromTemplatesetApplicationMenu로 메뉴를 만들 수 있다.

function createMyMenu() { // Customize Menu
  const template = [
    ...
  ];

  const appMenu = Menu.buildFromTemplate(template);
  Menu.setApplicationMenu(appMenu);
}

 

template을 배열로 구성하며, 아래와 같이 만들 수 있다.

label은 메뉴의 이름을 의미하며, submenu에서 해당 메뉴를 구성한다.

accelerator는 단축키를 설정하고, CmdOrCtrl은 mac에서는 command 키, window에서는 ctrl 키를 지정한다.

click은 해당 메뉴를 클릭했을 때 발생하는 이벤트를 설정한다.

type은 separator, checkbox, radio 등이 있다. (separator는 구역을 나눈다)

enabled가 false면 메뉴를 비활성화 할 수 있다.

icon을 설정하면 메뉴의 icon을 설정할 수 있다.

    {
      label: "File",
      submenu: [
        {
          label: "새창",
          accelerator: "CmdOrCtrl+N",
          click: createWindow,
        },
        { type: "separator" },
        { label: "임시 메뉴", enabled: false },
        {
          label: "로그",
          enabled: true,
          click: test,
          icon: __dirname + "/logo16.png",
        },
      ],
    },

 

실제 File 메뉴를 클릭하면 아래와 같이 설정된다.

임시 메뉴는 비활성화(enabled: false)되어 클릭해도 아무 반응이 없다.

그리고 public 폴더 아래에 있는 icon(logo16.png)이 로그 옆에 생성되었다.

 

토글 박스(type : checkbox)는 아래와 같이 사용할 수 있다.

    {
      label: "Options",
      submenu: [
        {
          label: "토글",
          type: "checkbox",
          click: (menuItem) => {
            console.log(`Checkbox state: ${menuItem.checked}`);
          },
        },
      ],
    },

 

실제로 메뉴를 클릭하면 아래와 같이 반응한다.

 

일렉트론이 제공하는 기본 role을 설정하면 메뉴를 간단히 설정할 수 있다. (링크 참고)

    {
      label: "Role",
      submenu: [
        { label: "복사", accelerator: "CmdOrCtrl+C", role: "copy" },
        { label: "붙여넣기", accelerator: "CmdOrCtrl+V", role: "paste" },
        { label: "잘라내기", accelerator: "CmdOrCtrl+X", role: "cut" },
        {
          label: "모두 선택하기",
          accelerator: "CmdOrCtrl+A",
          role: "selectall",
        },
        { label: "취소하기", accelerator: "CmdOrCtrl+Z", role: "undo" },
        { type: "separator" },
        { label: "다시 시도", accelerator: "CmdOrCtrl+R", role: "redo" },
        { label: "원본 서식 유지 후 붙여넣기", role: "pasteandmatchstyle" },
        { label: "윈도우 최소화", role: "minimize" },
        {
          label: "전체 화면",
          accelerator: "Alt+Enter",
          role: "togglefullscreen",
        },
        { type: "separator" },
        { label: "윈도우 닫기", accelerator: "CmdOrCtrl+W", role: "close" },
        { label: "App 종료하기", accelerator: "Alt+F4", role: "quit" },
      ],
    },

 

App.js에 Mui Textarea를 추가해서 설정한 role에 대해 테스트해보자.

import Box from "@mui/system/Box";
import Textarea from "@mui/joy/Textarea";

function App() {
  return (
    <div className="App">
      <div>
        <Box component="section" sx={{ m: 1 }}>
          <Textarea color="danger" minRows={3} />
        </Box>
        <Box component="section" sx={{ m: 1 }}>
          <Textarea color="primary" minRows={3} />
        </Box>
      </div>
    </div>
  );
}

export default App;

 

마지막으로 App을 재실행하거나 개발자 모드를 보려면 아래와 같이 메뉴를 구성할 수 있다.

    {
      label: "View",
      submenu: [
        {
          label: "재실행",
          accelerator: "CmdOrCtrl+R",
          click: (item, focusedWindow) =>
            focusedWindow && focusedWindow.reload(),
        },
        {
          label: "개발자 모드",
          accelerator:
            process.platform === "darwin" ? "Alt+Command+I" : "Ctrl+Shift+I",
          click: (item, focusedWindow) =>
            focusedWindow && focusedWindow.toggleDevTools(),
        },
      ],
    },

반응형

댓글