You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 20:50:33