Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ macOS 和 Windows 原生 API 的 Node.js 封装,使用 Swift + Win32 API + Nod
9. **鼠标监控** - 实时监听鼠标移动、点击事件
10. **鼠标模拟** - 模拟鼠标移动、点击操作
11. **取色器** - 全屏取色工具
12. **设置文件窗口地址栏** - 跳转 Finder/Explorer 或文件选择对话框到指定路径

## 🔧 系统要求

Expand Down Expand Up @@ -224,6 +225,30 @@ WindowManager.activateWindow(12345);
获取当前平台
- **返回**: `'darwin' | 'win32'`

#### `WindowManager.setAddressBar(target, address)`
设置文件资源管理器/Finder 或文件选择对话框的地址栏位置
- **参数**:
- `target` - 目标窗口
- **Windows**: `hwnd` 数字,或 `WindowManager.getActiveWindow()` 返回的窗口对象
- **macOS**: `bundleId` / `pid`,或 `WindowManager.getActiveWindow()` 返回的窗口对象
- `address` (string) - 要跳转的文件路径或 `file:///` 地址
- **返回**: `boolean` - 是否设置成功
- **平台**: ✅ Windows 和 macOS

**限制**:
- Windows 仅允许 Explorer 顶级窗口和包含 Shell 文件视图的文件选择对话框
- macOS 仅允许 Finder 和当前焦点为系统文件选择对话框的应用窗口
- 需要目标窗口可被激活;macOS 文件选择对话框场景需要辅助功能权限

**示例**:
```javascript
const current = WindowManager.getActiveWindow();
WindowManager.setAddressBar(current, process.platform === 'win32'
? 'C:\\Users\\username\\Documents'
: '/Users/username/Documents'
);
```

#### `WindowManager.simulateKeyboardTap(key, ...modifiers)`
模拟键盘按键
- **参数**:
Expand Down
58 changes: 58 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,64 @@ class WindowManager {
}
return addon.simulateKeyboardTap(key, ...modifiers);
}
/**
* 获取所有打开的文件资源管理器/Finder 窗口信息
* @returns {Array<{platform?: string, kind?: string, preciseTarget?: boolean, hwnd?: number, windowId?: number, finderId?: number, pid?: number, bundleId?: string, app?: string, title?: string, className?: string, axRole?: string, axSubrole?: string, path?: string, url?: string}>}
*/
static getAllExplorerWindows() {
return addon.getAllExplorerWindows();
}

/**
* 判断指定窗口是否是可安全修改地址栏的文件定位窗口
* @param {number} hwnd - Windows 窗口句柄
* @returns {boolean}
*/
static isFileLocationWindow(hwnd) {
if (platform !== 'win32') {
throw new Error('isFileLocationWindow is only available on Windows');
}
if (typeof hwnd !== 'number' || !Number.isFinite(hwnd) || hwnd <= 0) {
throw new TypeError('hwnd must be a positive number');
}
return addon.isFileLocationWindow(hwnd);
}

/**
* 设置指定文件资源管理器/Finder 或文件选择对话框的地址栏位置
* @param {Object|string|number} target - 目标窗口;Windows 支持 hwnd 数字或包含 hwnd 的窗口对象,macOS 支持 bundleId/pid 或窗口对象
* @param {string} address - 要跳转的文件路径或 file:/// 地址
* @returns {boolean} 是否设置成功
* @example
* const win = WindowManager.getActiveWindow();
* WindowManager.setAddressBar(win, 'C:\\Users\\username\\Documents');
*/
static setAddressBar(target, address) {
if (typeof address !== 'string' || !address) {
throw new TypeError('address must be a non-empty string');
}

let identifier = target;
if (target && typeof target === 'object') {
if (platform === 'win32') {
identifier = target.hwnd;
} else if (platform === 'darwin') {
identifier = target;
}
}

if (platform === 'win32') {
if (typeof identifier !== 'number') {
throw new TypeError('On Windows, target must be a hwnd number or a window object with hwnd');
}
} else if (platform === 'darwin') {
if (typeof identifier !== 'string' && typeof identifier !== 'number') {
throw new TypeError('On macOS, target must be a bundleId, pid, or window object with bundleId/pid');
}
Comment on lines +330 to +332

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

在 macOS 平台上,如果传入的 target 是一个窗口对象(例如 WindowManager.getActiveWindow() 返回的对象),在第 317 行代码中 identifier 会被赋值为该对象本身(identifier = target)。

然而,在第 330 行的类型检查中:

if (typeof identifier !== 'string' && typeof identifier !== 'number') {
  throw new TypeError('On macOS, target must be a bundleId, pid, or window object with bundleId/pid');
}

由于 identifier 是一个对象,typeof identifier 的值为 'object',这会导致该条件始终为真,从而无条件抛出 TypeError。这使得在 macOS 上无法直接传递窗口对象给 setAddressBar

建议修正类型检查,允许 'object' 类型通过,以便 C++ 层能够正确接收并序列化该对象。

Suggested change
if (typeof identifier !== 'string' && typeof identifier !== 'number') {
throw new TypeError('On macOS, target must be a bundleId, pid, or window object with bundleId/pid');
}
if (typeof identifier !== 'string' && typeof identifier !== 'number' && typeof identifier !== 'object') {
throw new TypeError('On macOS, target must be a bundleId, pid, or window object');
}

}

return addon.setAddressBar(identifier, address);
}
}

class MouseMonitor {
Expand Down
Loading
Loading