메뉴
Class: Menu
기본 애플리케이션 메뉴와 컨텍스트 메뉴를 생성한다.
프로세스: Main
new Menu()
는 새로운 메뉴를 생성한다.
Menu
클래스는 다음과 같은 정적 메서드를 제공한다:
Menu.setApplicationMenu(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.getApplicationMenu()
Menu | null
타입의 값을 반환한다. 설정된 애플리케이션 메뉴가 있으면 해당 Menu
인스턴스를 반환하고, 설정되지 않았다면 null
을 반환한다.
참고: 반환된 Menu
인스턴스는 메뉴 아이템을 동적으로 추가하거나 제거하는 기능을 지원하지 않는다. 하지만 인스턴스 속성은 여전히 동적으로 수정할 수 있다.
Menu.sendActionToFirstResponder(action)
macOS
action
string
애플리케이션의 첫 번째 응답자(first responder)에게 action
을 전송한다. 이 메서드는 기본 macOS 메뉴 동작을 에뮬레이트할 때 사용된다. 일반적으로는 MenuItem
의 role
속성을 사용하는 것이 더 일반적이다.
macOS의 기본 동작에 대한 더 자세한 정보는 macOS Cocoa Event Handling Guide를 참고한다.
Menu.buildFromTemplate(template)
template
(MenuItemConstructorOptions | MenuItem)[]
Menu
를 반환한다.
일반적으로 template
은 MenuItem을 생성하기 위한 options
의 배열이다. 사용법은 위에서 참조할 수 있다.
template
의 요소에 다른 필드를 추가할 수도 있으며, 이는 생성된 메뉴 아이템의 속성이 된다.
인스턴스 메서드
menu
객체는 다음과 같은 인스턴스 메서드를 제공한다:
menu.popup([options])
이 메뉴를 BaseWindow
에서 컨텍스트 메뉴로 팝업시킨다.
menu.closePopup([window])
window
BaseWindow (선택 사항) - 기본값은 현재 포커스된 윈도우입니다.
지정된 window
에서 컨텍스트 메뉴를 닫습니다.
menu.append(menuItem)
menuItem
MenuItem
menu
에 menuItem
을 추가한다.
menu.getMenuItemById(id)
id
string
MenuItem | null
을 반환한다. 지정된 id
를 가진 항목을 찾는다.
menu.insert(pos, menuItem)
pos
IntegermenuItem
MenuItem
메뉴의 pos
위치에 menuItem
을 삽입한다.
인스턴스 이벤트
new Menu
로 생성하거나 Menu.buildFromTemplate
를 통해 반환된 객체는 다음과 같은 이벤트를 발생시킨다.
참고: 일부 이벤트는 특정 운영체제에서만 사용 가능하며, 해당 이벤트는 별도로 표시한다.
이벤트: 'menu-will-show'
반환값:
event
Event
menu.popup()
메서드가 호출될 때 발생한다.
이벤트: 'menu-will-close'
반환값:
event
Event
팝업이 수동으로 닫히거나 menu.closePopup()
을 통해 닫힐 때 발생한다.
인스턴스 속성
menu
객체는 다음과 같은 속성을 갖는다:
menu.items
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에는 Services
나 Windows
메뉴와 같은 시스템에서 정의한 표준 메뉴가 많이 있다. 여러분의 메뉴를 표준 메뉴로 만들려면 메뉴의 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