Skip to main content

메뉴

Class: Menu

기본 애플리케이션 메뉴와 컨텍스트 메뉴를 생성한다.

프로세스: Main

new Menu()는 새로운 메뉴를 생성한다.

Menu 클래스는 다음과 같은 정적 메서드를 제공한다:

  • menu Menu | null

macOS에서 menu를 애플리케이션 메뉴로 설정한다. Windows와 Linux에서는 menu가 각 윈도우의 상단 메뉴로 설정된다.

Windows와 Linux에서는 최상위 아이템 이름에 &를 사용해 특정 문자에 액셀러레이터를 자동으로 생성할 수 있다. 예를 들어, 파일 메뉴에 &File을 사용하면 Alt-F 액셀러레이터가 생성되어 해당 메뉴를 열 수 있다. 이때 버튼 레이블에서 지정된 문자에 밑줄이 생기고, & 문자는 표시되지 않는다.

아이템 이름에서 & 문자를 이스케이프하려면 &&를 사용한다. 예를 들어, &&File은 버튼 레이블에 &File로 표시된다.

null을 전달하면 기본 메뉴를 비활성화한다. Windows와 Linux에서는 이로 인해 윈도우에서 메뉴 바가 제거된다.

참고: 앱에서 메뉴를 설정하지 않으면 기본 메뉴가 자동으로 생성된다. 기본 메뉴에는 File, Edit, View, Window, Help와 같은 표준 아이템이 포함된다.

Menu | null 타입의 값을 반환한다. 설정된 애플리케이션 메뉴가 있으면 해당 Menu 인스턴스를 반환하고, 설정되지 않았다면 null을 반환한다.

참고: 반환된 Menu 인스턴스는 메뉴 아이템을 동적으로 추가하거나 제거하는 기능을 지원하지 않는다. 하지만 인스턴스 속성은 여전히 동적으로 수정할 수 있다.

  • action string

애플리케이션의 첫 번째 응답자(first responder)에게 action을 전송한다. 이 메서드는 기본 macOS 메뉴 동작을 에뮬레이트할 때 사용된다. 일반적으로는 MenuItemrole 속성을 사용하는 것이 더 일반적이다.

macOS의 기본 동작에 대한 더 자세한 정보는 macOS Cocoa Event Handling Guide를 참고한다.

  • template (MenuItemConstructorOptions | MenuItem)[]

Menu를 반환한다.

일반적으로 templateMenuItem을 생성하기 위한 options의 배열이다. 사용법은 위에서 참조할 수 있다.

template의 요소에 다른 필드를 추가할 수도 있으며, 이는 생성된 메뉴 아이템의 속성이 된다.

인스턴스 메서드

menu 객체는 다음과 같은 인스턴스 메서드를 제공한다:

  • options Object (선택 사항)
    • window BaseWindow (선택 사항) - 기본값은 현재 포커스된 윈도우.
    • x number (선택 사항) - 기본값은 현재 마우스 커서 위치. y를 선언한 경우 반드시 선언해야 함.
    • y number (선택 사항) - 기본값은 현재 마우스 커서 위치. x를 선언한 경우 반드시 선언해야 함.
    • positioningItem number (선택 사항) macOS - 지정된 좌표에서 마우스 커서 아래에 위치할 메뉴 항목의 인덱스. 기본값은 -1.
    • sourceType string (선택 사항) Windows Linux - context-menu 이벤트에서 제공되는 menuSourceType과 매핑되어야 함. 이 값을 수동으로 설정하는 것은 권장하지 않으며, 다른 API에서 받은 값만 제공하거나 undefined로 남겨둠. 가능한 값은 none, mouse, keyboard, touch, touchMenu, longPress, longTap, touchHandle, stylus, adjustSelection, adjustSelectionReset 등.
    • callback Function (선택 사항) - 메뉴가 닫힐 때 호출되는 콜백 함수.

이 메뉴를 BaseWindow에서 컨텍스트 메뉴로 팝업시킨다.

  • window BaseWindow (선택 사항) - 기본값은 현재 포커스된 윈도우입니다.

지정된 window에서 컨텍스트 메뉴를 닫습니다.

menumenuItem을 추가한다.

  • id string

MenuItem | null을 반환한다. 지정된 id를 가진 항목을 찾는다.

메뉴의 pos 위치에 menuItem을 삽입한다.

인스턴스 이벤트

new Menu로 생성하거나 Menu.buildFromTemplate를 통해 반환된 객체는 다음과 같은 이벤트를 발생시킨다.

참고: 일부 이벤트는 특정 운영체제에서만 사용 가능하며, 해당 이벤트는 별도로 표시한다.

이벤트: 'menu-will-show'

반환값:

  • event Event

menu.popup() 메서드가 호출될 때 발생한다.

이벤트: 'menu-will-close'

반환값:

  • event Event

팝업이 수동으로 닫히거나 menu.closePopup()을 통해 닫힐 때 발생한다.

인스턴스 속성

menu 객체는 다음과 같은 속성을 갖는다:

menu.items는 메뉴의 항목들을 포함하는 MenuItem[] 배열이다.

Menu는 여러 개의 MenuItem으로 구성되며, 각 MenuItem은 하위 메뉴를 가질 수 있다.

예제

간단한 템플릿 API를 사용해 애플리케이션 메뉴를 생성하는 예제:

const { app, Menu } = require('electron')

const isMac = process.platform === 'darwin'

const template = [
// { role: 'appMenu' }
...(isMac
? [{
label: app.name,
submenu: [
{ role: 'about' },
{ type: 'separator' },
{ role: 'services' },
{ type: 'separator' },
{ role: 'hide' },
{ role: 'hideOthers' },
{ role: 'unhide' },
{ type: 'separator' },
{ role: 'quit' }
]
}]
: []),
// { role: 'fileMenu' }
{
label: 'File',
submenu: [
isMac ? { role: 'close' } : { role: 'quit' }
]
},
// { role: 'editMenu' }
{
label: 'Edit',
submenu: [
{ role: 'undo' },
{ role: 'redo' },
{ type: 'separator' },
{ role: 'cut' },
{ role: 'copy' },
{ role: 'paste' },
...(isMac
? [
{ role: 'pasteAndMatchStyle' },
{ role: 'delete' },
{ role: 'selectAll' },
{ type: 'separator' },
{
label: 'Speech',
submenu: [
{ role: 'startSpeaking' },
{ role: 'stopSpeaking' }
]
}
]
: [
{ role: 'delete' },
{ type: 'separator' },
{ role: 'selectAll' }
])
]
},
// { role: 'viewMenu' }
{
label: 'View',
submenu: [
{ role: 'reload' },
{ role: 'forceReload' },
{ role: 'toggleDevTools' },
{ type: 'separator' },
{ role: 'resetZoom' },
{ role: 'zoomIn' },
{ role: 'zoomOut' },
{ type: 'separator' },
{ role: 'togglefullscreen' }
]
},
// { role: 'windowMenu' }
{
label: 'Window',
submenu: [
{ role: 'minimize' },
{ role: 'zoom' },
...(isMac
? [
{ type: 'separator' },
{ role: 'front' },
{ type: 'separator' },
{ role: 'window' }
]
: [
{ role: 'close' }
])
]
},
{
role: 'help',
submenu: [
{
label: 'Learn More',
click: async () => {
const { shell } = require('electron')
await shell.openExternal('https://electronjs.org')
}
}
]
}
]

const menu = Menu.buildFromTemplate(template)
Menu.setApplicationMenu(menu)

렌더링 프로세스

렌더러 프로세스에서 시작된 메뉴를 생성하려면, IPC를 사용해 필요한 정보를 메인 프로세스로 전송하고 메인 프로세스가 렌더러를 대신해 메뉴를 표시하도록 한다.

아래는 사용자가 페이지에서 마우스 오른쪽 버튼을 클릭했을 때 메뉴를 표시하는 예제이다:

// 렌더러
window.addEventListener('contextmenu', (e) => {
e.preventDefault()
ipcRenderer.send('show-context-menu')
})

ipcRenderer.on('context-menu-command', (e, command) => {
// ...
})

// 메인
ipcMain.on('show-context-menu', (event) => {
const template = [
{
label: 'Menu Item 1',
click: () => { event.sender.send('context-menu-command', 'menu-item-1') }
},
{ type: 'separator' },
{ label: 'Menu Item 2', type: 'checkbox', checked: true }
]
const menu = Menu.buildFromTemplate(template)
menu.popup({ window: BrowserWindow.fromWebContents(event.sender) })
})

macOS 애플리케이션 메뉴 관련 노트

macOS는 윈도우와 리눅스와는 완전히 다른 스타일의 애플리케이션 메뉴를 가지고 있다. 앱의 메뉴를 더 네이티브처럼 만들기 위한 몇 가지 사항을 정리해 보았다.

표준 메뉴

macOS에는 ServicesWindows 메뉴와 같은 시스템에서 정의한 표준 메뉴가 많이 있다. 여러분의 메뉴를 표준 메뉴로 만들려면 메뉴의 role을 다음 중 하나로 설정하면 된다. 그러면 Electron이 이를 인식하고 표준 메뉴로 만들어 준다:

  • window
  • help
  • services

표준 메뉴 항목 동작

macOS는 About xxx, Hide xxx, Hide Others와 같은 일부 메뉴 항목에 대해 표준 동작을 제공한다. 메뉴 항목의 동작을 표준 동작으로 설정하려면 해당 메뉴 항목의 role 속성을 설정해야 한다.

메인 메뉴 이름

macOS에서는 애플리케이션 메뉴의 첫 번째 항목 레이블이 항상 앱 이름으로 설정된다. 레이블을 변경하려면 앱 번들의 Info.plist 파일을 수정해야 한다. 자세한 내용은 정보 속성 목록 파일 정보를 참고한다.

특정 브라우저 윈도우의 메뉴 설정 (Linux Windows)

setMenu 메서드를 사용하면 특정 브라우저 윈도우의 메뉴를 설정할 수 있다.

메뉴 아이템 위치 설정

Menu.buildFromTemplate로 메뉴를 구성할 때, before, after, beforeGroupContaining, afterGroupContaining, 그리고 id를 사용해 아이템의 위치를 제어할 수 있다.

  • before - 지정된 id를 가진 아이템 앞에 이 아이템을 삽입한다. 참조된 아이템이 존재하지 않으면 메뉴의 끝에 삽입된다. 또한 해당 메뉴 아이템이 같은 "그룹"에 속해야 함을 의미한다.
  • after - 지정된 id를 가진 아이템 뒤에 이 아이템을 삽입한다. 참조된 아이템이 존재하지 않으면 메뉴의 끝에 삽입된다. 또한 해당 메뉴 아이템이 같은 "그룹"에 속해야 함을 의미한다.
  • beforeGroupContaining - 단일 컨텍스트 메뉴가 지정된 id를 가진 아이템의 포함 그룹 앞에 자신의 포함 그룹을 배치할 수 있도록 한다.
  • afterGroupContaining - 단일 컨텍스트 메뉴가 지정된 id를 가진 아이템의 포함 그룹 뒤에 자신의 포함 그룹을 배치할 수 있도록 한다.

기본적으로, 위치 지정 키워드를 사용하지 않으면 템플릿에 존재하는 순서대로 아이템이 삽입된다.

예제

템플릿:

[
{ id: '1', label: 'one' },
{ id: '2', label: 'two' },
{ id: '3', label: 'three' },
{ id: '4', label: 'four' }
]

메뉴:

- 1
- 2
- 3
- 4

템플릿:

[
{ id: '1', label: 'one' },
{ type: 'separator' },
{ id: '3', label: 'three', beforeGroupContaining: ['1'] },
{ id: '4', label: 'four', afterGroupContaining: ['2'] },
{ type: 'separator' },
{ id: '2', label: 'two' }
]

메뉴:

- 3
- 4
- ---
- 1
- ---
- 2

템플릿:

[
{ id: '1', label: 'one', after: ['3'] },
{ id: '2', label: 'two', before: ['1'] },
{ id: '3', label: 'three' }
]

메뉴:

- ---
- 3
- 2
- 1