按任务抄完整可运行片段;签名细节以各专题文档为准。入门先看 最小窗口程序、语言基础。
硬约束
- 控件名来自窗口 XML 的
名称;事件形参以该控件文档为准。 - 属性用
=,方法必须();逻辑用真/假。 - 数组写
整数 arr[]/文本 list[];循环计数变量须外部先声明。 - 类名写全:
HTTP类、JSON类、绘制类、TCP类、WebSocket类、SQLite类、Excel类、Word类、打印类。 - 多窗口:
载入(窗名)/关闭(窗名)无引号。 - 网络回调用
&函数名注册;形参以该类「事件」表为准,禁止自行删改。 - 窗口随大小变化:用停靠或水平/垂直布局,见 窗口布局.md;不要用 YSS 改坐标。
1. 读控件、写控件
假定 XML 中有 标签1、文本框1、按钮1、组合框1、复选框1。
函数 主窗口.创建完毕() {
标签1.标题 = "就绪"
文本框1.文本 = ""
组合框1.清空()
组合框1.加入项目("选项A")
组合框1.加入项目("选项B")
组合框1.置当前索引(0)
复选框1.选中 = 假
}
函数 按钮1.单击(整数 X, 整数 Y) {
文本 t = 文本框1.文本
整数 i = 组合框1.取当前索引()
文本 项 = 组合框1.取项目文本(i)
如果 (复选框1.选中) {
标签1.标题 = t + " / " + 项
} 否则 {
标签1.标题 = "未勾选"
}
}
对照:label · textbox · button · combobox · checkbox
2. 分支、循环、遍历数组
整数 i = 0
循环 (5, i) {
输出(i) // 0…4
}
整数 n = 0
循环 (1, 10, 2, n) {
输出(n) // 1,3,5,7,9
}
整数 k = 0
当 (k < 3) {
k = k + 1
输出(k)
}
整数 arr[] = [10, 20, 30]
整数 项 = 0
遍历 (项, arr) {
输出(项)
}
文本 list[] = ["甲", "乙"]
文本 行 = ""
遍历 (行, list) {
输出(行)
}
// 字典:默认保序(写入顺序);可选 正序 / 倒序 按键排序
通用 配置 = 字典_批量置(["端口", "8080", "名称", "服务"])
通用 值 = 0
文本 键 = ""
遍历 (值, 配置) { // 保序:端口 → 名称
输出(值)
}
遍历 (键, 值, 配置, 正序) { // 按键升序
输出(键, "=", 值)
}
对照:basic-flow · basic-dict · basic-array · language §4.1
接收「整数数组 / 文本数组」返回值(左侧元素类型须与右侧一致;函数形参见 language.md §5.1):
整数 索引[] = 列表框1.取选中索引() // 元素为整数的数组
文本 名列表[] = 取进程列表() // 以各命令签名为准
列表框1.清空() // 列表框 / 组合框均有 清空()
3. 读写文本文件
函数 按钮保存.单击(整数 X, 整数 Y) {
如果 (写文件("note.txt", 文本框1.文本)) {
信息框("已保存")
} 否则 {
信息框("保存失败")
}
}
函数 按钮打开.单击(整数 X, 整数 Y) {
如果 (文件存在("note.txt")) {
文本框1.文本 = 读文件("note.txt")
} 否则 {
信息框("文件不存在")
}
}
对照:basic-file。二进制用 读入文件 / 写出文件 等字节集命令。
4. HTTP + JSON
函数 按钮拉取.单击(整数 X, 整数 Y) {
HTTP类 http
http.置超时(15000) // 毫秒
文本 正文 = http.提交("GET", "https://example.com/api/info")
如果 (http.取状态码() < 200 || http.取状态码() >= 300) {
标签1.标题 = "请求失败:" + http.取错误()
返回()
}
JSON类 j
如果 (j.解析(正文) == 假) {
标签1.标题 = "JSON 失败:" + j.取错误()
返回()
}
标签1.标题 = j.取文本("message", "")
}
POST 带正文:
HTTP类 http
http.置超时(15000)
文本 体 = "{\"name\":\"Y++\"}"
文本 回 = http.提交("POST", "https://example.com/api", 体)
如果 (回 == "") {
标签1.标题 = http.取错误()
}
超时、失败重试、且不卡住窗口:见 examples/http-retry。
HTTP类只做客户端(请求别人)。本机 HTTP 听端口请用 HTTP服务端类;原始字节流 / WebSocket 仍用下面的 TCP / WebSocket。
5. 多窗口
函数 按钮打开工作台.单击(整数 X, 整数 Y) {
载入(工作台) // 窗口名无引号
}
函数 按钮关闭登录.单击(整数 X, 整数 Y) {
关闭(登录窗)
}
// 在「工作台」窗口的代码里访问本窗控件可直接写名称;
// 访问其它窗:工作台.标签1.标题 = "来自别处"
对照:多窗口设计
6. 列表框 / 菜单
函数 主窗口.创建完毕() {
列表框1.清空()
列表框1.加入项目("一行")
列表框1.加入项目("二行")
列表框1.置当前索引(0)
菜单栏1.清空()
菜单栏1.加入主菜单("文件")
菜单栏1.加入子菜单(0, "打开")
菜单栏1.加入分割线(0)
}
函数 列表框1.项被单击(整数 当前索引, 文本 项目) {
标签1.标题 = 项目
}
函数 菜单栏1.项被单击(整数 索引, 文本 项目文本) {
标签1.标题 = 项目文本
}
7. 定时器
定时器类 t
函数 滴答() {
输出("tick")
}
函数 主窗口.创建完毕() {
整数 id = t.启动(1000, &滴答) // 毫秒;返回定时器 ID
}
函数 按钮停.单击(整数 X, 整数 Y) {
t.停止() // 省略 ID=停本对象全部;详见 timer-obj
}
对照:timer-obj。子程序指针写法见 callback。
8. 绘制类叠画(任意控件上)
绘制类 g
函数 按钮1.单击(整数 X, 整数 Y) {
g.绑组件(按钮1) // 组件名无引号
g.置填充色("#332D7EF7")
g.画矩形(4, 4, 40, 20)
按钮1.刷新()
}
对照:painter。画布场景编辑见 canvas / yss/canvas。
9. 自定义类型(.yt)
源代码/点.yt:
点 {
整数 x = 0,
整数 y = 0
}
main.yc:
函数 主窗口.创建完毕() {
点 p
p.x = 10
p.y = 20
点 arr[] = []
// 按 usertype 文档追加元素或字面量初始化
标签1.标题 = 到文本(p.x) + "," + 到文本(p.y)
}
对照:usertype · examples/usertype
10. 给窗口换肤(YSS)
- 读
窗口/主窗口/主窗口.xml→ 记下名称、typeId(如button、textbox)。 - 在
资源/主窗口.yss写规则(属性键必须英文):
form {
background-color: #1E1E1E;
}
button#确定 {
background-color: #007ACC;
color: #FFFFFF;
border-radius: 4;
}
button#确定:hover {
background-color: #1C97EA;
}
textbox {
background-color: #252526;
color: #E0E0E0;
border-color: #3F3F46;
}
- F5:资源复制到 exe 旁,启动自动加载
主窗口.yss,一般不用手写加载YSS()。 - 换肤 / 子目录主题:
函数 主窗口.创建完毕() {
加载YSS(":/yss/主题.yss")
}
- 查键:总览 YSS.md → 该控件「YSS 样式」分文档(如 button)。
- 不要用 YSS 改布局坐标;随窗拉伸用 窗口布局。表格格子配色用代码 API(见 datagrid / tablewidget)。
10.5 HTTP 服务端 Webhook(本机联调)
HTTP服务端类 srv
函数 收到请求(整数 请求ID, 文本 请求方法, 文本 路径, 文本 查询串,
文本 请求头, 文本 正文, 文本 IP, 整数 端口) {
标签1.标题 = 请求方法 + " " + 路径
如果 (路径 == "/hook") {
srv.应答JSON(请求ID, "{\"ok\":true}")
返回()
}
srv.置状态码(请求ID, 404)
srv.应答(请求ID, "not found")
}
函数 主窗口.创建完毕() {
srv.请求到达(&收到请求)
如果 (!srv.启动(18080, "127.0.0.1")) {
标签1.标题 = "HTTP 启动失败:" + srv.取错误()
}
}
// HTTPS:启动前 置TLS + 置TLS证书(PFX路径) 或 置PEM证书(证书路径, 私钥路径)
// 参数是文件路径(相对/绝对均可),不是证书名称;不必用「合并路径」
// 客户端访问自签证书时须 忽略证书(真)
函数 按钮HTTPS请求.单击(整数 X, 整数 Y) {
HTTP类 http
http.忽略证书(真)
文本 回 = http.提交("GET", "https://127.0.0.1:18443/ping")
标签1.标题 = 回
}
对照:httpserver。须在授权中开通 HTTP服务端类。证书支持 PFX/P12、PEM,以及 申请证书(Let’s Encrypt)。本机可用 PowerShell 自签 PFX(见该文档)。
11. TCP 服务端回显(本机联调)
假定窗体有 标签1。TCP 不是控件事件:先写回调函数,再用 &函数名 注册,最后 启动/连接。
回调形参必须与文档一致(勿自行删参数)。
TCP类 srv
TCP类 cli
函数 服务进入(整数 连接ID, 文本 IP, 整数 端口, 文本 IP端口) {
标签1.标题 = "接入 " + IP端口
}
函数 服务数据(整数 连接ID, 文本 IP, 整数 端口, 文本 IP端口, 文本 数据) {
// 服务端回发必须带 连接ID
srv.发送(连接ID, "回:" + 数据)
}
函数 服务离开(整数 连接ID, 文本 IP, 整数 端口, 文本 IP端口) {
标签1.标题 = "离开 id=" + 到文本(连接ID)
}
函数 主窗口.创建完毕() {
srv.客户进入(&服务进入)
srv.数据到达(&服务数据)
srv.客户离开(&服务离开)
srv.置分包模式(0) // 0=原始流;教学明文可先用 0
如果 (srv.启动(19000, "127.0.0.1") == 假) {
标签1.标题 = "监听失败:" + srv.取错误()
}
}
函数 按钮连.单击(整数 X, 整数 Y) {
如果 (cli.连接_同步("127.0.0.1", 19000) == 假) {
标签1.标题 = "连接失败:" + cli.取错误()
返回()
}
如果 (cli.发送("你好") <= 0) {
标签1.标题 = "发送失败"
返回()
}
文本 r = cli.接收(256)
标签1.标题 = "收到:" + r
cli.断开()
}
分包(推荐消息协议):双方 置分包模式(1),用 发送分包 / 事件里已是整帧。完整写法见 tcp。
11.1 大响应 / 自定义头 + 文件体
发送字节集返回成功后即可断开(优雅半关闭,一般不必块间延时)。- 异步
发送文件返回只表示已启动;立刻断开会取消并可能截断。要发完再断:用发送文件同步,或等发送完毕。 - HTTP 静态文件(自定义头 + 文件体)同连接:
函数 应答文件(整数 连接ID, 文本 路径, 整数 长度) {
文本 头 = "HTTP/1.1 200 OK\r\nContent-Length: " + 到文本(长度)
+ "\r\nConnection: close\r\n\r\n"
srv.发送字节集(连接ID, 到字节集(头))
srv.发送文件同步(连接ID, 路径)
srv.断开(连接ID)
}
12. WebSocket 服务端回显
WebSocket类 srv
WebSocket类 cli
函数 服务进入(整数 连接ID, 文本 IP, 整数 端口, 文本 IP端口) {
标签1.标题 = "WS 接入 " + IP端口
}
函数 服务收到(整数 连接ID, 文本 IP, 整数 端口, 文本 IP端口, 文本 数据) {
srv.发送(连接ID, "echo:" + 数据) // 返回逻辑
}
函数 服务离开(整数 连接ID, 文本 IP, 整数 端口, 文本 IP端口, 整数 状态码, 文本 原因) {
标签1.标题 = "WS 离开 code=" + 到文本(状态码)
}
函数 主窗口.创建完毕() {
srv.置路径("/chat")
srv.置允许来源("*")
srv.客户进入(&服务进入)
srv.数据到达(&服务收到)
srv.客户离开(&服务离开)
如果 (srv.启动(18765, "127.0.0.1") == 假) {
标签1.标题 = "WS 启动失败:" + srv.取错误()
}
}
函数 按钮连.单击(整数 X, 整数 Y) {
cli.置超时(3000)
如果 (cli.连接_同步("ws://127.0.0.1:18765/chat") == 假) {
标签1.标题 = "WS 连接失败:" + cli.取错误()
返回()
}
如果 (cli.发送("ping") == 假) {
标签1.标题 = "发送失败"
返回()
}
文本 r = cli.接收()
标签1.标题 = r
cli.关闭()
}
对照:websocket。UDP 监听见 udp;本机进程间通信见 pipe(创建服务端 / 连接,短名建议 ASCII,如 YppDesk)。
13. SQLite 建表、插入、查询
函数 主窗口.创建完毕() {
SQLite类 db
如果 (db.打开("data/demo.db") == 假) {
标签1.标题 = db.取错误()
返回()
}
// 旧版列定义文本亦可用(见 sqlite 文档)
如果 (db.表是否存在("用户") == 假) {
db.建表("用户", "id:主键,姓名:文本,年龄:整数")
}
db.插入("用户", "姓名,年龄", "张三,20")
如果 (db.查询("用户", "", "姓名,年龄", "年龄 DESC", 10)) {
当 (db.取下一行()) {
文本 名 = db.取文本("姓名")
文本 龄 = db.取文本("年龄")
标签1.标题 = 名 + " / " + 龄
}
}
db.关闭()
}
13.5 Excel 按表头读写
第一行当字段名,相对工程根的 data\\名单.xlsx。完整按钮代码见 examples/excel-header-map。
Excel类 book
如果 (book.打开("data\\名单.xlsx")) {
整数 列 = 0
整数 c
循环 (book.取列数(), c) {
如果 (book.取单元格(1, c + 1) == "姓名") {
列 = c + 1
}
}
标签1.标题 = book.取单元格(2, 列)
book.关闭()
}
对照:excel
13.5a 打印:画布预览 + 实打
无内置预览窗。先 打开画布(dpi 填 0 跟机)画同一套输出,取画布图片 放到图片框;再对同一打印机 打开 实打。完整 API 与自定义设置见 print.md(旁路包 supportlib.print,需授权)。示例工程:examples/打印预览。
打印类 打
打.置字体("微软雅黑", 10)
打.置页边距(1000, 1000, 1000, 1000)
函数 画一页() {
打.开始页()
打.输出文本行("对账单", 14)
打.输出表格(0, 打.取游标Y(), "品名" + 字符(9) + "数量" + 字符(10) + "苹果" + 字符(9) + "2", 2500)
打.结束页()
}
如果 (打.打开画布("", 0)) {
画一页()
图片框1.图片 = 打.取画布图片()
打.关闭()
}
如果 (打.打开()) {
画一页()
打.关闭()
}
对照:print
13.5b Word 套打 / 加密文档
模板占位符用智能替换(可跨 Word 拆开的 run)。加密 docx 与 Excel 相同,传密码即可。完整 API 见 word.md(旁路包 supportlib.word,免费)。
Word类 doc
如果 (!doc.打开(合并路径(取程序目录(), "合同模板.docx"))) {
信息框(doc.取错误(), 0)
返回
}
doc.批量替换("{{姓名}}=张三" + 字符(10) + "{{金额}}=12800")
doc.另存为(合并路径(取程序目录(), "合同_张三.docx"))
doc.关闭()
' 加密文档
Word类 sec
如果 (sec.打开("密件.docx", "我的密码")) {
sec.替换("{{姓名}}", "张三")
sec.另存为("密件_out.docx", "我的密码")
sec.关闭()
}
对照:word
13.5b 滚动区域(长设置页)
需授权开通。完整说明见 yss/scrollarea。
设计器:工具箱「布局 → 滚动区域」→ 子控件「所属容器」填滚动区域名。属性面板选滚动条策略(自动/始终/隐藏)、底部留白、平滑滚动。
函数 主窗口.创建完毕() {
滚动区域1.垂直滚动条 = 0
滚动区域1.水平滚动条 = 0
滚动区域1.底部留白 = 1
滚动区域1.平滑滚动 = 真
滚动区域1.刷新()
滚动区域1.滚到(0, 0)
}
函数 滚动区域1.滚动(整数 当前值) {
输出("垂直=" + 到文本(当前值))
}
函数 按钮到底.单击(整数 X, 整数 Y) {
整数 h = 滚动区域1.内容高度 - 滚动区域1.可视高度
如果 (h < 0) {
h = 0
}
滚动区域1.置滚动位置(h)
}
13.5c 用户组件(可视化拼接)
需授权开通。完整说明见 usercompose。
做定义: 多选控件 → 右键「另存为用户组件」→ 组件/<名>.yuc → 工具箱「用户组件」拖入。
跨工程: 拷贝 .yuc 到目标工程 组件/ 即可,不必重新拼接。
属性: 优先 实例.导出名 = 值;也可 实例.导出名.属性 / 实例__子名.属性。
事件: 函数 实例.导出事件 / 实例.导出名.单击 / 实例__子.单击;设计器进入生成完整带参桩,手写可无参。
' 假定窗体上有用户组件实例「联系人项1」,已导出 标题/预览/时间
函数 主窗口.创建完毕() {
联系人项1.标题 = "Y++ YStudio学习交流"
联系人项1.预览 = "一点滴:[动画表情]"
联系人项1.时间 = "08:28"
}
函数 联系人项1.单击 {
输出("点了整组")
}
' 动态实例(导出事件不自动挂)
文本 n = 克隆用户组件(联系人项1, 12, 200)
置用户组件属性(n, "标题", "新会话")
悬停出音量条: 另存时「悬停显示」填滑块名;竖条把滑块做成高>宽放图标上方。详见 usercompose §7。
内部布局: 另存前用水平/垂直布局+停靠排好(根布局建议停靠=填充),会写入 .yuc;宿主拉大时内部跟着排。见 usercompose §2.1。
样例:用户组件入门 · 用户组件演示·音量条 · 单文件联系人项
13.6 进程类:中文不乱码
管道按 UTF-8 读。完整对照见 examples/process-encoding。
进程类 p
如果 (p.启动("cmd.exe", "/c chcp 65001>nul & echo 你好")) {
文本框1.内容 = p.读全部(8000)
}
13.7 TLS 证书开关
自签优先 置TLS根证书;置TLS验证(假) 只给本机联调。见 examples/tls-verify。
TCP类 cli
cli.置TLS(真)
cli.置TLS根证书("ca.cer")
cli.置TLS主机名("api.internal.local")
cli.连接_同步("192.168.1.10", 443)
13.8 表格(控件名 表格1)
设计器里的 表格,不是「数据表格」。名单、订单这类一行一条记录用它。批量填充用 导入文件 / 导入行数据 / 虚拟加载(数据表格没有这些方法)。
函数 主窗口.创建完毕() {
表格1.添加列("姓名", 120)
表格1.添加列("手机", 140)
表格1.置单元格(0, 0, "张三")
表格1.置单元格(0, 1, "13800000000")
}
函数 按钮导入.单击(整数 X, 整数 Y) {
表格1.导入文件("data.txt", "----")
}
函数 表格1.单元格被单击(整数 行, 整数 列, 文本 区域) {
标签1.标题 = 区域 + " = " + 表格1.取单元格(行, 列)
}
对照:表格
13.9 数据表格(控件名 数据表格1)
设计器里的 数据表格。没有 导入文件 / 虚拟加载。少格用 置单元格;一块区域用 置区域文本;整行用 置行数据。要列字母 A/B/C 与行号时再 置工作表模式(真)。
函数 主窗口.创建完毕() {
数据表格1.置列数(3)
数据表格1.置行数(10)
数据表格1.置列头(0, "姓名")
数据表格1.置列头(1, "分数")
数据表格1.置单元格(0, 0, "张三")
数据表格1.置单元格(0, 1, "95")
数据表格1.置单元格(1, 0, "李四")
数据表格1.置单元格(1, 1, "88")
}
函数 数据表格1.单元格被单击(整数 行, 整数 列, 文本 区域) {
标签1.标题 = 区域 + " = " + 数据表格1.取单元格(行, 列)
}
对照:数据表格
13.10 选择颜色对话框
返回整数;取消是 -1。颜色选择器用 置颜色_eEx;其它控件 背景色 用 颜色值_到文本。
整数 色 = 选择颜色对话框()
如果 (色 != -1) {
颜色选择器1.置颜色_eEx(色)
按钮1.背景色 = 颜色值_到文本(色)
}
14. 查文档的固定顺序
- 打开本窗 XML → 记下控件
名称、typeId。 - 打开对应
yss/*.md→ 抄属性 / 方法 / 事件;要换肤再看该页「YSS 样式」与 YSS.md。 - 用到支持库 → 打开该库文档的方法/事件表;回调形参以事件说明为准。
- 语法拿不准 → language / basic-flow。
- 禁止在签名表外发明方法名或改事件形参。
易错对照
| 错误 | 正确 |
|---|---|
文本框1.内容 |
多数工程用 文本框1.文本(以 textbox 属性表为准) |
按钮1.被单击()(旧名) |
按钮1.单击 { } 或设计器生成的 按钮1.单击(整数 X, 整数 Y) |
HTTP http |
HTTP类 http |
载入("工作台") |
载入(工作台) |
整数[] a |
整数 a[] |
遍历(整数 项, arr) |
先 整数 项 = 0,再 遍历(项, arr) |
| 字典遍历按键字母序(默认) | 默认保序;字母序写 遍历(..., 正序) / 倒序 |
YSS 写 背景色: #fff |
background-color: #FFFFFF;(英文键 + #RRGGBB) |
button#确定:悬停 |
button#确定:hover |
| 用 YSS 精细画数据表格每一格 | 外壳用 YSS;格子用 置区域背景色 等 |
数据表格1.导入文件(...) |
导入文件 只属于 表格;数据表格用 置单元格 / 置行数据 / 置区域文本 |
按钮1.背景色 = 选择颜色对话框() |
按钮1.背景色 = 颜色值_到文本(色)(先判 != -1) |
把 表格1 写成 数据表格1(或反过来) |
XML「名称」是哪一种控件就写哪一个;方法表不要混抄 |
http.置超时(15) 当秒 |
置超时 单位是毫秒:15000 |
函数 srv.数据到达(...) 当控件事件 |
TCP/WS:srv.数据到达(&回调),回调形参按文档 |
服务端 发送("hi") 不带连接ID |
发送(连接ID, "hi") |
TCP / WebSocket |
TCP类 / WebSocket类 |
相关
最小窗口程序 · YSS 样式 · 语言基础 · 流程控制 · TCP类 · WebSocket类 · Word类 · 打印类 · 用户组件 · 工程结构 · 窗口 XML