项目 7 情景控制:虚拟时钟、项目资源、Windows Media Player、TrackBar
- 虚拟时钟:实训台时钟面板可拨时间、1×/10×/60× 倍速、恢复真实时间;编译时把 DateTime.Now / Today / UtcNow 改写成 SimClock;评分规则加 clock 步骤 - 项目资源(Properties.Resources):平台素材库(自绘开关图片、合成门铃声),"项目资源"对话框勾选, 平台生成 Properties/Resources.Designer.cs;设计器图片框的"图片"属性可选资源;程序目录下的 Resources 指向素材库;未添加资源时给中文提示 - Windows Media Player(AxWMPLib):设置 URL 自动播放、Ctlcontrols.play/stop,浏览器里播放声音, 实训台加广播喇叭;编译时给窗体嵌空资源,OcxState 取到 null 不报错;图片和声音统一按内容缓存(blob) - TrackBar:拖动、点轨道、方向键,先 ValueChanged 再 Scroll;设计器加"滑动条""媒体播放器" - 评分规则加 value、media 检查;示例项目 7 任务 1–3(修正书上开关灯判断写反、漏填串口列表) - 修正:Properties/ 下的资源类不当作窗体;带命名空间的 System.AppDomain.CurrentDomain.BaseDirectory 放行 - 测试:虚拟时钟、TrackBar、项目 7 示例评分、作业起点带资源类 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
a9af26c2d6
commit
eedf1aa2fb
66 files changed
+3538
-43
No files matched your search
@@ -0,0 +1,20 @@
|
||||
using System.ComponentModel;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
|
||||
namespace Sim.Host;
|
||||
|
||||
/// <summary>
|
||||
/// 项目资源(Properties.Resources)的素材库。平台为学生工程生成的 Properties/Resources.Designer.cs 通过这里读取素材,
|
||||
/// 和 VS 一样每次取图片都得到一个新的 Bitmap。
|
||||
/// </summary>
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
public static class ProjectResources
|
||||
{
|
||||
/// <summary>素材文件所在目录(运行器目录下的 Resources/gallery)</summary>
|
||||
public static string Directory { get; } = Path.Combine(Path.GetDirectoryName(typeof(ProjectResources).Assembly.Location)!, "Resources", "gallery");
|
||||
|
||||
public static Bitmap Image(string file) => (Bitmap)System.Drawing.Image.FromStream(new MemoryStream(Bytes(file)));
|
||||
|
||||
public static byte[] Bytes(string file) => File.ReadAllBytes(Path.Combine(Directory, Path.GetFileName(file)));
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Globalization;
|
||||
using System.Text.Json.Nodes;
|
||||
|
||||
namespace Sim.Host;
|
||||
|
||||
/// <summary>
|
||||
/// 虚拟时钟(实训台上可以拨时间、调倍速;教材项目 7 按时刻切换情景模式)。
|
||||
/// 编译时把学生代码里的 DateTime.Now / Today / UtcNow 改写成这里的属性(见 Sim.Runner/ClockRewriter.cs)。
|
||||
/// 没有拨过时就是真实时间。
|
||||
/// </summary>
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
public static class SimClock
|
||||
{
|
||||
private sealed record Setting(DateTime Wall, long RealAt, double Speed);
|
||||
|
||||
private static volatile Setting? _setting;
|
||||
|
||||
public static DateTime Now
|
||||
{
|
||||
get
|
||||
{
|
||||
var setting = _setting;
|
||||
if (setting == null) return DateTime.Now;
|
||||
var elapsed = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() - setting.RealAt;
|
||||
return setting.Wall.AddMilliseconds(elapsed * setting.Speed);
|
||||
}
|
||||
}
|
||||
|
||||
public static DateTime Today => Now.Date;
|
||||
|
||||
public static DateTime UtcNow => Now.ToUniversalTime();
|
||||
|
||||
/// <summary>平台内部使用:应用服务器推送的 {"wall":"2024-01-16T06:40:00","realAt":…,"speed":60},null 恢复真实时间</summary>
|
||||
public static void Update(JsonNode? clock)
|
||||
{
|
||||
if (clock is not JsonObject json
|
||||
|| !DateTime.TryParseExact((string?)json["wall"], "yyyy-MM-ddTHH:mm:ss", CultureInfo.InvariantCulture, DateTimeStyles.AssumeLocal, out var wall))
|
||||
{
|
||||
_setting = null;
|
||||
return;
|
||||
}
|
||||
_setting = new Setting(DateTime.SpecifyKind(wall, DateTimeKind.Local), (long?)json["realAt"] ?? 0, (double?)json["speed"] ?? 1);
|
||||
}
|
||||
}
|
||||
@@ -86,19 +86,23 @@ public static class SimHost
|
||||
public static string AppBaseDirectory { get; set; } = AppContext.BaseDirectory;
|
||||
|
||||
/// <summary>图片在浏览器端的编号;第一次用到时先把图片数据发过去,浏览器缓存后同一张图不再重发</summary>
|
||||
public static string ImageKey(System.Drawing.Image image)
|
||||
public static string ImageKey(System.Drawing.Image image) => DataKey(image.SimKey, image.Data, image.MimeType);
|
||||
|
||||
/// <summary>
|
||||
/// 图片、声音等数据在浏览器端的编号(key 通常是内容的哈希):第一次用到时先把数据发过去,之后只发编号。
|
||||
/// </summary>
|
||||
public static string DataKey(string key, byte[] data, string mime)
|
||||
{
|
||||
var key = image.SimKey;
|
||||
bool isNew;
|
||||
lock (SentImages) isNew = SentImages.Add(key);
|
||||
if (isNew)
|
||||
{
|
||||
Send(new JsonObject
|
||||
{
|
||||
["type"] = "image",
|
||||
["type"] = "blob",
|
||||
["key"] = key,
|
||||
["mime"] = image.MimeType,
|
||||
["data"] = Convert.ToBase64String(image.Data),
|
||||
["mime"] = mime,
|
||||
["data"] = Convert.ToBase64String(data),
|
||||
});
|
||||
}
|
||||
return key;
|
||||
|
||||
Reference in new issue
Block a user