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 目录下的示例获取更多实践经验。
相关推荐
蓝婷儿1 小时前
前端面试每日三题 - Day 32
前端·面试·职场和发展
星空寻流年2 小时前
CSS3(BFC)
前端·microsoft·css3
九月TTS2 小时前
开源分享:TTS-Web-Vue系列:Vue3实现固定顶部与吸顶模式组件
前端·vue.js·开源
CodeCraft Studio2 小时前
数据透视表控件DHTMLX Pivot v2.1发布,新增HTML 模板、增强样式等多个功能
前端·javascript·ui·甘特图
一把年纪学编程2 小时前
【牛马技巧】word统计每一段的字数接近“字数统计”
前端·数据库·word
llc的足迹2 小时前
el-menu 折叠后小箭头不会消失
前端·javascript·vue.js
九月TTS3 小时前
TTS-Web-Vue系列:移动端侧边栏与响应式布局深度优化
前端·javascript·vue.js
Johnstons3 小时前
AnaTraf:深度解析网络性能分析(NPM)
前端·网络·安全·web安全·npm·网络流量监控·网络流量分析
whatever who cares3 小时前
CSS3 伪元素(Pseudo-elements)大全
前端·css·css3
若愚67923 小时前
前端取经路——性能优化:唐僧的九道心经
前端·性能优化