msgProc: Accelerator Tables
Accelerator tables map keyboard shortcuts to command identifiers using readable strings like "Ctrl+S" and "Ctrl+Shift+Z". Register a table, handle MSG_ACCEL in msgProc, and destroy when done.
Messages
MSG_ACCEL
MSG_ACCEL fires when a registered key combination is pressed. event.wParam is the command ID assigned
to that entry. The matching MSG_KEYDOWN is automatically suppressed — the component never sees it. Tables are
checked innermost-first by walking up the container hierarchy, with the global table as final fallback. A child
container's table takes priority over its parent's, which takes priority over the global table.
Message Parameters
| Parameter | Type | Description |
|---|---|---|
wParam |
number | The command ID assigned in the table entry |
lParam |
number | Reserved (always 0) |
Example: Editor Shortcuts
const CMD_SAVE = 101;
const CMD_UNDO = 102;
const CMD_REDO = 103;
const CMD_FIND = 104;
init() {
wakaPAC.loadAcceleratorTable(this.pacId, [
{ key: 'Ctrl+S', cmdId: CMD_SAVE },
{ key: 'Ctrl+Z', cmdId: CMD_UNDO },
{ key: 'Ctrl+Shift+Z', cmdId: CMD_REDO },
{ key: 'Ctrl+F', cmdId: CMD_FIND },
]);
}
msgProc(event) {
if (event.message === wakaPAC.MSG_ACCEL) {
switch (event.wParam) {
case CMD_SAVE: this.save(); break;
case CMD_UNDO: this.undo(); break;
case CMD_REDO: this.redo(); break;
case CMD_FIND: this.openFindDialog(); break;
}
}
}
destroy() {
wakaPAC.destroyAcceleratorTable(this.pacId);
}
API
loadAcceleratorTable()
wakaPAC.loadAcceleratorTable(this.pacId, [
{ key: 'Ctrl+S', cmdId: 101 },
]);
Registers an accelerator table for a container or globally. Calling this a second time for the same pacId completely replaces the existing table — entries are not merged. Component-scoped tables are automatically removed when the container is destroyed. The global table (null) is not tied to any container lifecycle and must be destroyed explicitly.
| Parameter | Type | Description |
|---|---|---|
pacId |
string | null | Component ID to scope the table to, or null for a global application-wide table |
entries |
Array | Array of { key, cmdId } objects. key is a shortcut string; cmdId is a positive integer delivered as event.wParam when the shortcut fires |
destroyAcceleratorTable()
wakaPAC.destroyAcceleratorTable(this.pacId);
Removes the accelerator table for a container or the global scope. The shortcut keys stop firing immediately.
| Parameter | Type | Description |
|---|---|---|
pacId |
string | null | Component ID whose table should be removed, or null to remove the global table |
getAcceleratorTable()
const entries = wakaPAC.getAcceleratorTable(this.pacId);
Returns a copy of the registered entries for a container or the global scope. Each entry includes the original key string, making this suitable for rendering a keyboard shortcuts help dialog without maintaining a separate data structure. Returns null if no table is registered for the given scope.
| Parameter | Type | Description |
|---|---|---|
pacId |
string | null | Component ID to retrieve, or null for the global table |
| Returns | Type | Description |
|---|---|---|
| entries | Array | null | Copy of the registered entries as { key, cmdId } objects, or null if no table exists for this scope |
Shortcut String Format
A shortcut string consists of optional modifier tokens followed by a key name, joined by +. Parsing is case-insensitive. The key name is a VK_* constant with the VK_ prefix omitted.
| Token | Description |
|---|---|
Ctrl |
Ctrl key modifier |
Shift |
Shift key modifier |
Alt |
Alt key modifier |
| key name | Examples: S, F5, Delete, Escape, Return, Space, OEM_PLUS |
| String | Meaning |
|---|---|
"Ctrl+S" |
Ctrl + S |
"Ctrl+Shift+Z" |
Ctrl + Shift + Z |
"F5" |
F5 with no modifiers |
"Alt+F4" |
Alt + F4 |
"Ctrl+OEM_PLUS" |
Ctrl + the = / + key |
"Delete" |
Delete with no modifiers |
Nested Containers
A parent container's accelerator table automatically covers all its descendants. If focus is inside a child that has no table of its own, the parent's shortcuts still fire. This lets you define application-wide shortcuts at a high level without registering them on every child component.
// Parent registers shortcuts that apply to all children
wakaPAC('#app', {
init() {
wakaPAC.loadAcceleratorTable('app', [
{ key: 'Ctrl+S', cmdId: CMD_SAVE },
]);
},
msgProc(event) {
if (event.message === wakaPAC.MSG_ACCEL && event.wParam === CMD_SAVE) {
this.save();
}
}
});
// Child has no accelerator table — Ctrl+S still fires in the parent's msgProc
wakaPAC('#editor', { /* ... */ });
Best Practices
- Define command IDs as named constants: Magic numbers in switch statements become impossible to maintain. Define them at the top of your component
- Destroy the global table explicitly: The global table (
null) is not tied to any container lifecycle — calldestroyAcceleratorTable(null)when it is no longer needed - Use global tables sparingly: Reserve the global table for true application-level commands. Per-component tables give more control and avoid accidental shadowing
- Don't shadow browser shortcuts: Combinations like Ctrl+W and Ctrl+T are handled by the browser before wakaPAC sees them