> ## Documentation Index
> Fetch the complete documentation index at: https://webview.js.org/llms.txt
> Use this file to discover all available pages before exploring further.

# WebviewJS on Windows: WebView2, Taskbar and Win32 APIs

> Platform-specific setup, WebView2 requirements, and Windows-only BrowserWindow APIs including HWND access, taskbar icons, and window class names.

WebviewJS on Windows uses Microsoft's **WebView2** engine — a Chromium-based runtime that ships with Microsoft Edge. Because WebView2 is maintained by Microsoft and updated alongside Edge, you always get a modern, standards-compliant browser surface without bundling Chromium yourself.

## Prerequisites

<Info>
  **Windows 11** ships with the WebView2 runtime pre-installed. **Windows 10**
  auto-downloads and installs it the first time it is needed. You can also
  pre-install it manually using the [Evergreen
  bootstrapper](https://developer.microsoft.com/en-us/microsoft-edge/webview2/)
  from Microsoft.
</Info>

Check the installed WebView2 version at runtime:

```js theme={null}
import { getWebviewVersion } from '@webviewjs/webview';

console.log(getWebviewVersion()); // e.g. "128.0.2739.42"
```

## Supported architectures

| Target triple             | Architecture | CI |
| ------------------------- | ------------ | -- |
| `x86_64-pc-windows-msvc`  | x64          | ✅  |
| `i686-pc-windows-msvc`    | x86 (32-bit) | ✅  |
| `aarch64-pc-windows-msvc` | arm64        | ✅  |

## Windows-specific creation options

Pass these fields in the `BrowserWindowOptions` object when calling `app.createBrowserWindow()`. They are silently ignored on other platforms.

| Option                       | Type            | Description                                                                                              |
| ---------------------------- | --------------- | -------------------------------------------------------------------------------------------------------- |
| `windowsOwnerWindow`         | `bigint`        | HWND of a parent window. Makes this window a child of the specified Win32 window.                        |
| `windowsTaskbarIcon`         | `TrayIconImage` | Custom icon shown in the taskbar button at window creation time.                                         |
| `windowsNoRedirectionBitmap` | `boolean`       | Disables the redirection surface (DWM bitmap). Useful for transparent or layered windows.                |
| `windowsDragAndDrop`         | `boolean`       | Enables OLE drag-and-drop support on the window.                                                         |
| `windowsSkipTaskbar`         | `boolean`       | Hides the window from the taskbar and Alt+Tab switcher at creation time.                                 |
| `windowsClassName`           | `string`        | Win32 window class name registered for this window. Useful for shell integrations that query `WM_CLASS`. |
| `windowsUndecoratedShadow`   | `boolean`       | Adds a drop shadow to a borderless (`decorations: false`) window using DWM.                              |

```js theme={null}
import { Application } from '@webviewjs/webview';

const app = new Application();

app.whenReady().then(() => {
  const win = app.createBrowserWindow({
    decorations: false,
    windowsUndecoratedShadow: true,
    windowsClassName: 'MyAppWindow',
    windowsSkipTaskbar: false,
  });

  win.createWebview({ url: 'app://localhost/index.html' });
});
```

## Windows runtime methods

These methods are Windows-specific and safe to call on any platform — they return neutral values or do nothing outside Windows.

```js theme={null}
// Enable or disable user input for the window (grays out the window when disabled)
win.setEnable(false);
win.setEnable(true);

// Replace the taskbar button icon at runtime
// data is an RGBA Buffer; width and height default to sqrt(data.length / 4)
win.setTaskbarIcon(rgbaBuffer, 32, 32);

// Remove the custom taskbar icon and restore the default window icon
win.removeTaskbarIcon();

// Toggle DWM drop shadow on a borderless window
win.setUndecoratedShadow(true);

// Retrieve the native HWND handle as a bigint
// Safe to call from any thread (unlike getNativeHandle())
const hwnd = win.getNativeHandleAnyThread();
console.log(hwnd); // e.g. 133143624n
```

### Progress bar

Integrate with the Windows taskbar progress indicator:

```js theme={null}
import { ProgressBarState } from '@webviewjs/webview';

// Show a determinate progress ring at 42 %
win.setProgressBar({ state: ProgressBarState.Normal, progress: 42 });

// Show an indeterminate spinner
win.setProgressBar({ state: ProgressBarState.Indeterminate });

// Signal an error state (red bar)
win.setProgressBar({ state: ProgressBarState.Error, progress: 100 });

// Remove the progress indicator
win.setProgressBar({ state: ProgressBarState.None });
```

`ProgressBarState` values: `None` · `Normal` · `Indeterminate` · `Paused` · `Error`

## IPC on Windows

<Warning>
  In wry 0.53, a `file:` page that calls `window.ipc.postMessage()` can abort
  because WebView2 treats the page source as a `file:` URI and wry attempts to
  convert it to an HTTP request URI. Always load IPC-enabled pages through a
  custom protocol such as `app://` — **never** via a `file:` URL. See the
  [Custom Protocols guide](/guides/custom-protocols) for setup instructions.
</Warning>

```js theme={null}
// Register your protocol before creating the webview
win.registerProtocol('app', async (request) => {
  // serve files from ./dist
  const filePath = join(process.cwd(), 'dist', new URL(request.url).pathname);
  return new Response(await readFile(filePath), {
    headers: { 'Content-Type': 'text/html; charset=utf-8' },
  });
});

// Load from the custom protocol — IPC works correctly
win.createWebview({ url: 'app://localhost/index.html' });
```

## Menu bar

On Windows the menu bar is attached to each window's title bar following standard Win32 behaviour. Every window can carry its own independent menu or share the application-level menu set via `app.setMenu()`.

```js theme={null}
const win = app.createBrowserWindow({
  title: 'My App',
  menu: {
    items: [
      {
        label: 'File',
        submenu: {
          items: [
            { id: 'new',  label: 'New',  accelerator: 'Ctrl+N' },
            { id: 'open', label: 'Open', accelerator: 'Ctrl+O' },
            { role: 'separator' },
            { id: 'quit', label: 'Exit', accelerator: 'Alt+F4' },
          ],
        },
      },
    ],
  },
});
```

Listen for custom menu item clicks on the `Application` instance:

```js theme={null}
app.on('custom-menu-click', ({ customMenuEvent }) => {
  if (customMenuEvent.id === 'quit') app.exit();
});
```

## DPI and HiDPI scaling

Tao reads the monitor's scale factor automatically and reports it via `win.scaleFactor()`. Use logical pixels when positioning child elements:

```js theme={null}
const dpr = win.scaleFactor();
const { width, height } = win.getInnerSize(/* logical = */ true);
```

All values from window events (`resize`, `move`, `mouse-move`, etc.) arrive in **physical pixels**. Divide by `win.scaleFactor()` to convert to logical (CSS) pixels.
