msgProc: System Messages
Reference for system and utility msgProc events including container resizing, focus tracking, and reactive data change notifications.
Size Changed (MSG_SIZE)
MSG_SIZE fires when the container element is resized. Use this to recalculate layouts, adjust canvas dimensions, or update any size-dependent state. This event uses ResizeObserver internally and fires for both programmatic and user-driven size changes.
Message Parameters
| Parameter |
Type |
Description |
wParam |
number |
Resize type constant: SIZE_RESTORED (0), SIZE_MINIMIZED (1), SIZE_MAXIMIZED (2). Currently always SIZE_RESTORED in browser context |
lParam |
number |
Packed dimensions: low 16 bits = width, high 16 bits = height (in pixels). Extract using LOWORD() and HIWORD() |
Detail Properties
| Property |
Type |
Description |
width |
number |
New container width in pixels (same as LOWORD(lParam)) |
height |
number |
New container height in pixels (same as HIWORD(lParam)) |
contentRect |
DOMRect |
Full ResizeObserver content rectangle with x, y, width, height, top, right, bottom, left properties |
borderBoxSize |
ResizeObserverSize[] |
Array of ResizeObserverSize objects with inlineSize and blockSize properties representing the full element dimensions including padding and border. Writing-mode aware (inline=horizontal in LTR, vertical in vertical writing modes). Use for calculations needing complete box size or for internationalization with vertical text layouts |
contentBoxSize |
ResizeObserverSize[] |
Array of ResizeObserverSize objects with inlineSize and blockSize properties representing the content area dimensions excluding padding and border. Writing-mode aware. Use when sizing child elements to fit exactly within the padding, or when you need the actual drawable/usable content space |
Performance Note: MSG_SIZE fires immediately during resize operations for responsive UI updates. Keep resize handlers lightweight. Only debounce expensive operations that don't need real-time feedback (heavy calculations, network requests, complex re-renders). Most resize handlers (canvas sizing, layout updates) should run immediately without debouncing.
Example: Canvas Resize
msgProc(event) {
if (event.message === wakaPAC.MSG_SIZE) {
const width = wakaPAC.LOWORD(event.lParam);
const height = wakaPAC.HIWORD(event.lParam);
this.updateLayout();
}
}
Set Focus (MSG_SETFOCUS)
MSG_SETFOCUS fires when an element within the container receives focus. Use this to track focus state, enable keyboard shortcuts, or update UI to reflect focused state.
Message Parameters
| Parameter |
Type |
Description |
wParam |
number |
Reserved (always 0) |
lParam |
number |
Reserved (always 0) |
target |
HTMLElement |
The element that received focus |
Example: Enable Keyboard Shortcuts
msgProc(event) {
if (event.message === wakaPAC.MSG_SETFOCUS) {
this.keyboardShortcutsEnabled = true;
return false;
}
if (event.message === wakaPAC.MSG_KILLFOCUS) {
this.keyboardShortcutsEnabled = false;
return false;
}
// Handle shortcuts only when focused
if (event.message === wakaPAC.MSG_KEYDOWN && this.keyboardShortcutsEnabled) {
if (event.wParam === wakaPAC.VK_S && (event.lParam & wakaPAC.KM_CONTROL)) {
this.save();
return false;
}
}
}
Kill Focus (MSG_KILLFOCUS)
MSG_KILLFOCUS fires when an element within the container loses focus. Use this to clean up focus-dependent state, disable keyboard shortcuts, or trigger validation.
Message Parameters
| Parameter |
Type |
Description |
wParam |
number |
Reserved (always 0) |
lParam |
number |
Reserved (always 0) |
target |
HTMLElement |
The element that lost focus |
Example: Save Draft on Focus Loss
msgProc(event) {
if (event.message === wakaPAC.MSG_KILLFOCUS) {
// Auto-save when editor loses focus
if (this.isDirty) {
this.saveDraft();
}
return false;
}
}
Device Pixel Ratio Changed (MSG_DPR_CHANGE)
MSG_DPR_CHANGE fires when the display's device pixel ratio changes. This happens when the user moves the browser window to a monitor with a different pixel density, or changes the OS display scaling setting. The updated ratio is available on this.browserDevicePixelRatio when the message arrives.
Message Parameters
| Parameter |
Type |
Description |
wParam |
number |
New device pixel ratio multiplied by 100 and rounded to the nearest integer (e.g. 150 for a DPR of 1.5, 200 for 2.0). Divide by 100 to recover the float value |
lParam |
number |
Reserved (always 0) |
Two ways to read the ratio: Use event.wParam / 100 for a self-contained handler, or read this.browserDevicePixelRatio directly — the abstraction property is updated before the message is dispatched.
Example: Resize Canvas for HiDPI
msgProc(event) {
switch (event.message) {
case wakaPAC.MSG_SIZE:
case wakaPAC.MSG_DPR_CHANGE: {
const dpr = this.browserDevicePixelRatio;
wakaPAC.resizeCanvas(this.pacId, this.containerWidth * dpr, this.containerHeight * dpr);
wakaPAC.invalidateRect(this.pacId);
return;
}
case wakaPAC.MSG_PAINT: {
const hdc = wakaPAC.getDC(this.pacId);
const dpr = this.browserDevicePixelRatio;
hdc.save();
hdc.scale(dpr, dpr);
// Draw using CSS pixel coordinates as normal
hdc.clearRect(0, 0, this.containerWidth, this.containerHeight);
// ... drawing code ...
hdc.restore();
return;
}
}
}
Foreach Rebuilt (MSG_FOREACH_REBUILT)
MSG_FOREACH_REBUILT fires after a foreach binding finishes rendering its items. It fires once per foreach binding, so a component with multiple foreach bindings receives a separate message for each one. Use this to update any non-reactive content that depends on the rendered DOM — such as drawing sparklines onto canvas elements inside foreach items.
Message Parameters
| Parameter |
Type |
Description |
wParam |
number |
Number of items rendered |
lParam |
number |
Reserved (always 0) |
Detail Properties
| Property |
Type |
Description |
arrayName |
string |
The foreach expression string (e.g. 'products'). Use to retrieve the source data via this[event.detail.arrayName] |
marker |
string | null |
The value of the data-pac-marker attribute on the foreach element, or null if not set. Use to distinguish between multiple foreach bindings that share the same source array |
Distinguishing multiple foreachs: If the same array is bound in more than one foreach, or if you simply want explicit identification, add data-pac-marker="myMarker" to the foreach element and check event.detail.marker in the handler.
Best Practices
- Keep resize handlers lightweight: MSG_SIZE fires frequently during resizing - avoid expensive calculations
- Handle DPR alongside resize: MSG_DPR_CHANGE and MSG_SIZE often need the same canvas resize logic — fall through both cases to a shared handler
- Track focus state: Use MSG_SETFOCUS/KILLFOCUS to enable/disable keyboard shortcuts appropriately
- Validate on blur: MSG_KILLFOCUS is a good trigger for field validation
- Consider focus scope: MSG_SETFOCUS/KILLFOCUS fire for any element within the container receiving/losing focus
- Use markers for multiple foreachs: If a component has more than one foreach binding, add
data-pac-marker to each and check event.detail.marker to route MSG_FOREACH_REBUILT to the right handler