A modern Node.js/TypeScript library for accessing Windows Desktop Window Manager (DWM) APIs. Get live window thumbnails, icons, and manage virtual desktops with native C++ performance.
-
Default capture prefers classic DWM thumbnail and PrintWindow paths to avoid the flashing yellow border and screen flicker.
-
To opt into Windows Graphics Capture (WGC) for higher fidelity on some apps, set the environment variable
DWM_WINDOWS_USE_WGC=1
before running your app. The module will hide the capture border and cursor when supported. -
Off-screen composition is used to avoid showing the helper window. If you still observe flicker, ensure no antivirus overlays or global screen effects are active.
-
π TypeScript-first - Full type definitions and IntelliSense support
-
β‘ Native performance - C++ bindings for optimal speed
-
π― Window management - Focus, filter, and control windows programmatically
-
π Event hooks (no polling) - Created/closed/focused callbacks via native WinEvent hooks
yarn add dwm-windows
import dwmWindows from 'dwm-windows';
// Get all visible windows on current desktop
const windows = dwmWindows.getVisibleWindows();
for (const window of windows) {
console.log(`${window.title} (${window.executablePath})`);
console.log(`Icon: ${window.icon.substring(0, 50)}...`);
console.log(`Thumbnail: ${window.thumbnail.substring(0, 50)}...`);
}
// Focus a specific window
dwmWindows.openWindow(windows[0].id);
Returns visible windows. Use { includeAllDesktops: true }
to include all virtual desktops.
Returns all windows (including hidden ones).
Brings a window to the foreground and focuses it.
Refreshes and returns the PNG thumbnail as a base64 data URL.
Promise-based variants that run work off the main thread and won't block the event loop:
getWindowsAsync(options?): Promise<WindowInfo[]>
getVisibleWindowsAsync(options?): Promise<WindowInfo[]>
openWindowAsync(windowId: number): Promise<boolean>
updateThumbnailAsync(windowId: number): Promise<string>
Example:
import dwmWindows from 'dwm-windows';
const all = await dwmWindows.getWindowsAsync({ includeAllDesktops: true });
if (all.length) {
await dwmWindows.openWindowAsync(all[0].id);
const freshThumb = await dwmWindows.updateThumbnailAsync(all[0].id);
console.log('Thumb length:', freshThumb.length);
}
Subscribe to native window events without polling:
onWindowCreated(cb: (e) => void)
onWindowClosed(cb: (e) => void)
onWindowFocused(cb: (e) => void)
onWindowChange(cb: (e) => void)
// unified: e.type in {created,closed,focused,minimized,restored}stopWindowEvents()
Each event payload contains: { id, hwnd, title, executablePath, isVisible, type }
.
For closed
, title
/executablePath
may be empty because the window is already gone.
import dwmWindows from 'dwm-windows';
dwmWindows.onWindowCreated(e => console.log('Created:', e));
dwmWindows.onWindowClosed(e => console.log('Closed:', e));
dwmWindows.onWindowFocused(e => console.log('Focused:', e));
// Later, to clean up
dwmWindows.stopWindowEvents();
Filters windows by title (case-insensitive substring match).
Filters windows by executable name (e.g., "notepad.exe").
interface WindowInfo {
id: number; // HWND as number (same as hwnd)
title: string; // Window title
executablePath: string; // Full path to executable
isVisible: boolean; // Visibility state
hwnd: number; // Windows handle (same as id)
thumbnail: string; // PNG thumbnail (base64 data URL)
icon: string; // App icon (base64 data URL)
}
import dwmWindows from 'dwm-windows';
const currentDesktop = dwmWindows.getVisibleWindows();
const allDesktops = dwmWindows.getVisibleWindows({ includeAllDesktops: true });
// Find windows that exist on other desktops but not current one
// Note: id equals hwnd (native handle), which is stable for the window's lifetime
const currentWindowKeys = new Set(
currentDesktop.map(w => `${w.title}|${w.executablePath}`)
);
const hiddenWindows = allDesktops.filter(w =>
!currentWindowKeys.has(`${w.title}|${w.executablePath}`)
);
console.log(`Current desktop: ${currentDesktop.length} windows`);
console.log(`Hidden on other desktops: ${hiddenWindows.length} windows`);
// Find all Chrome windows
const chromeWindows = dwmWindows.getWindowsByExecutable('chrome.exe');
// Focus the first Chrome window
if (chromeWindows.length > 0) {
dwmWindows.openWindow(chromeWindows[0].id);
}
// Find windows by title
const codeWindows = dwmWindows.getWindowsByTitle('Visual Studio Code');
const windows = dwmWindows.getVisibleWindows();
const getDataSize = (dataUrl: string) => {
const base64 = dataUrl.split(',')[1] || '';
return Math.round(base64.length * 0.75 / 1024); // KB estimate
};
const totalIconSize = windows.reduce((sum, w) => sum + getDataSize(w.icon), 0);
const totalThumbSize = windows.reduce((sum, w) => sum + getDataSize(w.thumbnail), 0);
console.log(`Total payload: ${totalIconSize + totalThumbSize}KB`);
console.log(`Icons: ${totalIconSize}KB, Thumbnails: ${totalThumbSize}KB`);
import dwmWindows from 'dwm-windows';
const windows = new Map<number, { title: string }>();
dwmWindows.getVisibleWindows().forEach(w => windows.set(w.id, { title: w.title }));
dwmWindows.onWindowCreated(e => {
windows.set(e.id, { title: e.title });
console.log('Added', e.id, e.title);
});
dwmWindows.onWindowClosed(e => {
windows.delete(e.id);
console.log('Removed', e.id);
});
dwmWindows.onWindowFocused(e => {
console.log('Focused', e.id, e.title);
});
- Windows 10/11
- Node.js β₯ 16
- Visual Studio Build Tools or Visual Studio with C++ workload
- Python (for node-gyp)
# Install dependencies and build
yarn install
# Rebuild native module only
yarn rebuild
# Build TypeScript and native module
yarn build
# Run example
yarn example
Notes:
- Windows Graphics Capture is enabled by default for robust, flicker-free captures when supported.
- Minimized windows use DWM previews; if only a tiny title bar is available, a placeholder thumbnail (centered app icon) is shown instead of a low-quality image.
dwm-windows/
βββ src/
β βββ index.ts # Main API
β βββ types.d.ts # Type definitions
β βββ example.ts # Usage examples
βββ dwm_thumbnail.cc # C++ native bindings
βββ binding.gyp # Node-gyp build configuration
βββ build/ # Compiled binaries
- OS: Windows 10/11 (x64)
- Node.js: β₯ 16.0.0
- Architecture: x64 only
MIT Β© Giacomo Barbalinardo
Contributions welcome! Please read our contributing guidelines and submit pull requests for any improvements.