BrowserWindowTool is an Electron project designed to embed other Windows applications (such as Notepad, Paint, Calculator, etc.) within an Electron application window. By leveraging Node.js native modules, this project achieves seamless integration and control of external Windows application windows within an Electron environment.
├── binding.gyp # Node.js native module build config
├── electron-example # Electron application
│ ├── blank.html # Blank template for embedded windows
│ ├── index.html # Main interface
│ ├── main.js # Electron main process
│ ├── preload.js # Preload script
│ └── render.js # Renderer process script
└── src # Native module source code
├── main.cc # N-API module entry
├── WindowManager.cc # Window management implementation
└── WindowManager.h # Header file
├── release/BrowserWindowTool.node # This is the build product for nodegyp on Windows
If you don't have a Visual Studio environment, delete the binding.gyp file and copy `release/BrowserWindowTool.node` to `/build/Release/BrowserWindowTool.node`
demo.mp4
embed cloudmusic
embed notepad++
Electron, built on Chromium and Node.js, does not natively support embedding external Windows application windows. Due to incompatibilities between Chromium's rendering engine and Windows' native window management, native modules are necessary to bridge this gap.
The core implementation involves the following steps:
-
Container Window Creation: A transparent child window (container window) is created in the Electron window to act as the "canvas" for embedding external applications.
-
Process Initialization: Target applications are launched using Windows API.
-
Window Discovery: Target application windows are identified through window enumeration.
-
Window Embedding: The parent window of the target application is set to the container window, effectively embedding it.
-
Window Resizing: Embedded windows are dynamically resized to match the container window.
To avoid rendering conflicts, GPU acceleration is disabled with these command-line switches:
app.commandLine.appendSwitch("in-process-gpu");
app.commandLine.appendSwitch("disable-gpu-sandbox");
app.commandLine.appendSwitch("disable-direct-composition");
app.commandLine.appendSwitch("disable-gpu");
app.commandLine.appendSwitch("no-sandbox");A native module (BrowserWindowTool) using Node.js N-API provides critical functions:
createEmbeddedWindow: Creates embedded windowsupdateWindow: Updates window propertiesdestroyWindow: Destroys embedded windowsgetAllWindowIds: Retrieves all window IDscleanupAll: Cleans up resources
Key logic in WindowManager.cc:
HWND WindowManager::FindAndEmbedWindow(DWORD processId, HWND containerWindow)
{
// Window discovery loop
HWND targetWindow = NULL;
for (int i = 0; i < 50; ++i) {
EnumWindowsData data = {processId, NULL};
EnumWindows(EnumWindowsProc, reinterpret_cast<LPARAM>(&data));
if (data.targetWindow) {
targetWindow = data.targetWindow;
break;
}
Sleep(100);
}
// Style modification and embedding
LONG_PTR style = GetWindowLongPtr(targetWindow, GWL_STYLE);
style = (style & ~(WS_POPUP | WS_CAPTION | WS_THICKFRAME)) | WS_CHILD;
SetWindowLongPtr(targetWindow, GWL_STYLE, style);
SetParent(targetWindow, containerWindow);
// Size adjustment
RECT rect;
GetClientRect(containerWindow, &rect);
SetWindowPos(targetWindow, HWND_TOP, 0, 0,
rect.right - rect.left, rect.bottom - rect.top,
SWP_SHOWWINDOW | SWP_FRAMECHANGED);
return targetWindow;
}Custom window procedure in ContainerWndProc:
LRESULT CALLBACK WindowManager::ContainerWndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
switch (msg) {
case WM_SIZE:
// Size adjustment logic
return 0;
case WM_NCCALCSIZE:
return 0;
}
return DefWindowProcW(hwnd, msg, wparam, lparam);
}-
Container Window Creation:
- Electron creates transparent container window
- Retrieves native window handle
-
Native Module Invocation:
- IPC communication transfers window handle
- Native module creates container window
- Launches target process
- Embeds discovered window
-
Window Management:
- IPC interface controls window lifecycle
- Native module maintains window state
Solution:
SetWindowPos(targetWindow, HWND_TOP, ...);
BringWindowToTop(targetWindow);Solution:
// Modified window style
style = (style & ~(WS_POPUP | WS_CAPTION | WS_THICKFRAME)) | WS_CHILD;Solution:
case WM_SIZE:
SetWindowPos(childWindow, NULL, 0, 0,
rect.right - rect.left, rect.bottom - rect.top,
SWP_NOZORDER | SWP_NOACTIVATE);- Windows-Only: Relies on Windows API
- Native Applications: Only supports Windows-native applications
- Style Customization: May require special handling for different apps
- Performance: Resource-intensive applications may impact performance
- Security: Disabled security features require trusted environments
xland/ElectronGrpc: Electron comunicate with native process by grpc


