Electron如何调整同Exe打开的特定外部窗口大小?(记事本示例)
实现多记事本窗口的独立尺寸调整
是的,你可以通过窗口标题(包含文件名)来区分同一程序打开的多个窗口,并在Electron中实现独立调整大小的功能。以下是具体实现方案:
核心思路
Windows系统中,记事本窗口的标题格式为 [文件名] - 记事本,因此我们可以通过枚举所有记事本窗口、匹配标题中的文件名来定位目标窗口,再调用Windows API调整其尺寸。
步骤与代码实现
1. 安装依赖
在Electron项目中安装用于调用Windows API的工具包:
npm install ffi-napi ref-napi ref-struct-napi
2. 主进程(main.js)实现窗口定位与调整
在主进程中编写Windows API调用逻辑,通过IPC接收渲染进程的指令:
const { app, ipcMain } = require('electron'); const ffi = require('ffi-napi'); const ref = require('ref-napi'); const StructType = require('ref-struct-napi'); // 定义Windows API类型 const HWND = ref.types.void; const UINT = ref.types.uint; const BOOL = ref.types.bool; const INT = ref.types.int; // 加载user32.dll并绑定所需API const user32 = new ffi.Library('user32', { EnumWindows: [BOOL, ['pointer', 'pointer']], GetWindowTextLengthW: [INT, [HWND]], GetWindowTextW: [INT, [HWND, 'pointer', INT]], GetClassNameW: [INT, [HWND, 'pointer', INT]], SetWindowPos: [BOOL, [HWND, HWND, INT, INT, INT, INT, UINT]] }); // 枚举所有窗口并筛选记事本窗口 function findNotepadWindowByFilename(filename) { let targetHwnd = null; const callback = ffi.Callback(BOOL, [HWND, 'pointer'], (hwnd, lParam) => { // 获取窗口类名 const classNameBuffer = Buffer.alloc(256); user32.GetClassNameW(hwnd, classNameBuffer, 256); const className = ref.reinterpretUntilZeros(classNameBuffer, 2).toString('ucs2'); if (className === 'Notepad') { // 获取窗口标题 const textLength = user32.GetWindowTextLengthW(hwnd); if (textLength > 0) { const titleBuffer = Buffer.alloc((textLength + 1) * 2); user32.GetWindowTextW(hwnd, titleBuffer, textLength + 1); const title = ref.reinterpretUntilZeros(titleBuffer, 2).toString('ucs2'); // 匹配标题中的文件名 if (title.startsWith(`${filename} - 记事本`)) { targetHwnd = hwnd; return false; // 找到目标后停止枚举 } } } return true; // 继续枚举 }); user32.EnumWindows(callback, null); return targetHwnd; } // 调整窗口大小 function resizeWindow(hwnd, width, height) { if (!hwnd) return; // SWP_NOMOVE: 保持当前位置,只修改尺寸;SWP_NOZORDER: 不改变窗口层级 const SWP_NOMOVE = 0x0002; const SWP_NOZORDER = 0x0004; user32.SetWindowPos(hwnd, null, -1, -1, width, height, SWP_NOMOVE | SWP_NOZORDER); } // 监听渲染进程的调整请求 ipcMain.on('resize-notepad', (event, { filename, width, height }) => { const hwnd = findNotepadWindowByFilename(filename); resizeWindow(hwnd, width, height); }); // 常规Electron启动逻辑 app.whenReady().then(() => { // 此处添加创建窗口等常规逻辑 });
3. 渲染进程(renderer.js)添加按钮交互
在渲染页面中添加按钮,并通过IPC向主进程发送指令:
<!-- index.html --> <button id="firstBtn">First (text1.txt: 600x600)</button> <button id="secondBtn">Second (text2.txt: 500x500)</button> <script src="./renderer.js"></script>
// renderer.js const { ipcRenderer } = require('electron'); document.getElementById('firstBtn').addEventListener('click', () => { ipcRenderer.send('resize-notepad', { filename: 'text1.txt', width: 600, height: 600 }); }); document.getElementById('secondBtn').addEventListener('click', () => { ipcRenderer.send('resize-notepad', { filename: 'text2.txt', width: 500, height: 500 }); });
注意事项
- 该方案仅适用于Windows系统,因为依赖Windows API。
- 确保记事本窗口使用默认标题格式
文件名 - 记事本,若用户修改了标题规则,需调整匹配逻辑。 - 若存在同名不同路径的文件(如不同文件夹下的text1.txt),可结合
GetWindowThreadProcessId和OpenProcess获取进程详情,进一步区分窗口。
内容的提问来源于stack exchange,提问作者Nikunj Chaklasiya
相关产品推荐
相关产品推荐

