Sciter.js 新手指南-GUI开发中的窗口使用指南

本文档旨在帮助前端开发者或从其他语言转向 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,可阻止关闭或自定义行为。

    • 示例:

      js 复制代码
      Window.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 跨窗口共享数据

最佳实践

  1. 主窗口建议使用 FRAME_WINDOW,弹窗/工具条用 POPUP/TOOL_WINDOW。
  2. 窗口通信优先用事件机制,避免直接操作其它窗口实例。
  3. 处理窗口关闭事件: 使用 window.on("closerequest", ...) 事件可以在用户尝试关闭窗口时执行清理操作或阻止关闭(例如,提示保存未保存的更改)。
  4. 参数传递建议用 parameters 字段,避免全局变量污染。
  5. 模块化设计 :将窗口逻辑、UI 和业务逻辑分离,参考 SDK 文档 samples.app/classic 示例
  6. 使用 Reactor 组件 :对于复杂 UI,使用 Reactor 组件化开发
  7. 窗口生命周期管理 :妥善处理窗口的创建和销毁,避免资源泄漏
  8. 事件委托 :使用事件委托模式处理 UI 事件,提高性能
  9. 响应式设计 :使用 CSS 流布局和弹性布局,适应不同屏幕尺寸 可以参考 sdk/samples.app 和 sdk/samples.sciter/window 目录下的示例获取更多实践经验。
相关推荐
崔庆才丨静觅3 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby60614 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了4 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅4 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅4 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅5 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment5 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅5 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊5 小时前
jwt介绍
前端
爱敲代码的小鱼5 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax