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