本文档旨在帮助前端开发者或从其他语言转向 Sciter.js 的开发者快速了解和使用 Sciter 窗口。
什么是 Sciter 窗口?
在 Sciter.js 中,Window
类的实例代表一个桌面窗口。每个加载了 HTML 文档的窗口都有一个 Window.this
引用,指向当前的窗口对象。
注意: 文档中提到的 window
指的是 Sciter 的 Window
类实例(例如 Window.this
),而不是浏览器中的 window
对象。
窗口类型 (type
)
创建窗口时,可以通过 type
参数指定窗口的类型,不同的类型适用于不同的场景:
Window.FRAME_WINDOW
: 默认的标准窗口类型,通常带有标题栏和边框,适合主界面(默认类型)。Window.POPUP_WINDOW
: 弹出式窗口,通常用于临时信息显示、菜单、提示等临时性界面等,没有标准的窗口装饰。Window.TOOL_WINDOW
: 工具窗口,类似于弹出窗口,但在某些操作系统上可能有不同的行为(例如,不显示在任务栏),适合浮动工具条、调色板等。Window.CHILD_WINDOW
: 子窗口,嵌入在父窗口的客户区内,依附于父窗口。。Window.DIALOG_WINDOW
: 对话框窗口,通常用于模态交互。
javascript
// 创建一个弹出式窗口
let toastWindow = new Window({
type: Window.POPUP_WINDOW,
url: __DIR__ + "toast.htm", // 加载内容的 HTML 文件
width: 200,
height: 100
});
ps: 非常有用的一个属性,就是窗口框架类型 (frameType
) - 创建无边框窗口,比如创建一个 360 之类的软件,我们想完全定制自己的头部的风格,这时就要使用这个方式了。
window.frameType
属性允许你控制窗口的外观,包括创建无边框或自定义形状的窗口,稍后设置窗口为无边框带阴影 如 window.frameType = "solid-with-shadow";
注意: 无边框窗口通常需要你在 HTML/CSS 中自行实现窗口的拖动和关闭等交互。 所以当你创建了无边框窗口 (frameType
不是 "standard"
),你需要自己处理窗口的拖动(通常通过在特定元素上监听 mousedown
并调用 Window.this.move()
)和关闭逻辑。
窗口创建 (new Window
)
创建新窗口的基本语法是:
javascript
let newWindow = new Window({ params: object });
params
对象可以包含多个属性来配置窗口,常用属性包括:
type
: 窗口类型 (见上文)。url
: 要加载的 HTML 文件的路径或 URL。width
,height
: 窗口的初始宽度和高度(单位:屏幕像素)。x
,y
: 窗口的初始位置(单位:屏幕像素)。caption
: 窗口标题。state
: 初始窗口状态 (见下文)。parent
: 父窗口实例,如果设置,子窗口会随父窗口最小化或关闭。parameters
: 传递给新窗口的数据,可以在新窗口中通过Window.this.parameters
访问。
js
// 创建新窗口
var win = new Window({
url: "path/to/file.htm", // 窗口内容 HTML 文件
width: 800, // 窗口宽度
height: 600, // 窗口高度
alignment: 5, // 5 表示在父窗口或屏幕中央对齐
parameters: {...} // 传递给窗口的参数
});
窗口状态管理(window.state
)
你可以读取或设置窗口的 state
属性来控制其显示状态:
Window.WINDOW_SHOWN
: 正常显示(默认)。Window.WINDOW_MINIMIZED
: 最小化到任务栏或托盘。Window.WINDOW_MAXIMIZED
: 最大化。Window.WINDOW_HIDDEN
: 隐藏窗口。Window.WINDOW_FULL_SCREEN
: 全屏显示。Window.WINDOW_SHOWN_NA
(仅写): 显示窗口但不激活它(不获取焦点)。
javascript
// 获取当前窗口状态
let currentState = Window.this.state;
// 最小化当前窗口
Window.this.state = Window.WINDOW_MINIMIZED;
// 切换窗口显示/隐藏状态
function toggleWindow() {
if (Window.this.state === Window.WINDOW_HIDDEN) {
Window.this.state = Window.WINDOW_SHOWN;
} else {
Window.this.state = Window.WINDOW_HIDDEN;
}
}
窗口控制
Window
对象提供了多种方法来控制窗口的位置、大小和行为:
- 移动和调整大小:
window.move(x, y [, width, height [, "client"]])
: 移动窗口并可选地调整大小(坐标单位:物理像素 PPX)。如果提供"client"
,则坐标相对于客户区。window.moveTo(monitor, x, y [, width, height [, "client"]])
: 移动到指定显示器(坐标单位:设备无关像素 DIPs/CSS 像素)。
- 获取窗口几何信息:
window.box(boxPart, boxOf, relTo)
: 获取窗口不同部分(边框、客户区、光标等)相对于不同参考点(桌面、显示器、自身)的几何信息(位置、尺寸)。
- 激活与关闭:
window.activate(bringToFront: boolean)
: 将输入焦点设置到窗口,true
表示同时将其带到最前。window.close([value])
: 请求关闭窗口。对于模态对话框,可以传递一个返回值。
- 更新布局:
window.update()
: 请求重新计算窗口内元素的布局。
- 模态对话框:
window.modal(JSX | {params} | new Window(...))
: 显示模态对话框。可以是预定义的 JSX(如<alert>
),创建新窗口的参数对象,或一个已创建的Window
实例。该方法会阻塞直到模态窗口关闭,并返回其关闭值。
javascript
// 将窗口移动到屏幕 (100, 100) 的位置
Window.this.move(100, 100);
// 获取窗口客户区的宽度和高度 (CSS 像素)
let [w, h] = Window.this.box("dimension", "client", "self", false);
// 显示一个简单的警告框
Window.this.modal(<alert>操作成功!</alert>);
// 关闭当前窗口
document.on("click", "#close-button", () => {
Window.this.close();
});
窗口之间的通信
Sciter 提供了几种机制进行窗口间或窗口与原生代码的交互:
-
Window.share
: 一个在应用程序所有窗口和文档间共享的全局 JavaScript 对象。你可以用它来存储共享状态或数据。javascript// 在窗口 A 中设置共享数据 Window.share.currentUser = { name: "Alice" }; // 在窗口 B 中读取共享数据 console.log(Window.share.currentUser.name); // 输出 "Alice"
注意: 使用
Window.share
时要小心,确保在窗口关闭前(例如在unload
事件中)清理不再需要的数据,避免内存泄漏。 -
参数传递 :新建窗口时通过
parameters
字段传递,子窗口可通过Window.this.parameters
读取。 -
window.xcall(name, ...args)
: 调用附加到窗口的原生行为 (Native Behavior) 中定义的函数。这是 Sciter 脚本与原生代码交互的主要方式。 -
事件通信 :
Window.post(event)
向所有窗口广播事件(异步)。Window.send(event)
向所有窗口同步发送事件,遇到第一个消费事件的窗口即停止。window.dispatchEvent(event)
向本窗口同步分发事件。window.postEvent(event)
向本窗口异步分发事件。
方式1, 使用事件通信
js
// 父窗口向子窗口传递数据
this.postEvent(
new Event('set-style-dynamic', {
bubbles: true,
data: { prop, val }
})
);
// 其它窗口或组件接收数据
["on set-style-dynamic"](evt){
const { prop, val } = evt.data;
const input = this.$(`input:not([index])[prop=${prop}]`);
if (!input) return;
input.value = false;
}
方式2, 使用传参
js
// 父窗口打开子窗口并传参
let child = new Window({
url: "child.htm",
parameters: { foo: 123 }
});
// 子窗口读取参数
console.log(Window.this.parameters.foo);
与原生代码交互
js
window.xcall("functionName", arg1, arg2); // 调用原生行为中的函数
系统交互
- 文件/文件夹选择对话框:
window.selectFile({mode, filter, ...})
: 打开系统文件选择对话框。window.selectFolder({caption, path})
: 打开系统文件夹选择对话框。
- 系统托盘图标:
window.trayIcon({image, text})
: 显示系统托盘图标。window.trayIcon("remove")
: 移除托盘图标。window.trayIcon("place")
: 获取托盘图标位置。
- 热键:
window.addHotKeyHandler(keyCombination, callback)
: 注册全局系统热键。window.removeHotKeyHandler(id)
: 移除热键。
javascript
// 注册 Ctrl+F8 热键
try {
const hotkeyId = Window.this.addHotKeyHandler("Control+F8", () => {
Window.this.modal(<alert>全局热键 Control+F8 被按下!</alert>);
});
// 保存 hotkeyId 以便之后移除
} catch (e) {
console.error("注册热键失败: ", e);
}
常用事件
-
窗口关闭拦截:
-
监听
closerequest
,可阻止关闭或自定义行为。 -
示例:
jsWindow.this.on("closerequest", event => { if(event.reason == 0) { // 用户点击关闭按钮 Window.this.state = Window.WINDOW_MINIMIZED; event.preventDefault(); } });
-
-
窗口类型与样式:
- 通过
window-frame
属性或构造参数type
指定类型,配合 CSS 自定义窗口外观。 - 示例见 samples.sciter/window/chrome-types/
- 通过
-
模态对话框:
window.modal(<alert>内容</alert>)
弹出消息框window.modal({ ... })
打开模态窗口
-
托盘图标与通知:
window.trayIcon({image, text})
设置托盘图标- 监听
trayiconclick
响应点击
-
多窗口管理:
Window.all
获取所有窗口实例Window.share
跨窗口共享数据
最佳实践
- 主窗口建议使用 FRAME_WINDOW,弹窗/工具条用 POPUP/TOOL_WINDOW。
- 窗口通信优先用事件机制,避免直接操作其它窗口实例。
- 处理窗口关闭事件: 使用
window.on("closerequest", ...)
事件可以在用户尝试关闭窗口时执行清理操作或阻止关闭(例如,提示保存未保存的更改)。 - 参数传递建议用 parameters 字段,避免全局变量污染。
- 模块化设计 :将窗口逻辑、UI 和业务逻辑分离,参考 SDK 文档 samples.app/classic 示例
- 使用 Reactor 组件 :对于复杂 UI,使用 Reactor 组件化开发
- 窗口生命周期管理 :妥善处理窗口的创建和销毁,避免资源泄漏
- 事件委托 :使用事件委托模式处理 UI 事件,提高性能
- 响应式设计 :使用 CSS 流布局和弹性布局,适应不同屏幕尺寸 可以参考 sdk/samples.app 和 sdk/samples.sciter/window 目录下的示例获取更多实践经验。