KeyboardCore 1.0.1
dotnet add package KeyboardCore --version 1.0.1
NuGet\Install-Package KeyboardCore -Version 1.0.1
<PackageReference Include="KeyboardCore" Version="1.0.1" />
<PackageVersion Include="KeyboardCore" Version="1.0.1" />
<PackageReference Include="KeyboardCore" />
paket add KeyboardCore --version 1.0.1
#r "nuget: KeyboardCore, 1.0.1"
#:package KeyboardCore@1.0.1
#addin nuget:?package=KeyboardCore&version=1.0.1
#tool nuget:?package=KeyboardCore&version=1.0.1
KeyboardCore 浮动屏幕键盘
KeyboardCore.Control.Keyboard 是独立的 WPF Window,不是 UserControl,也不需要放进页面布局或 WinForms Controls。应用内所有输入框通过 Keyboard.Shared 共用一个键盘窗口,WPF 和 WinForms 使用同一共享入口。构造函数不再公开,不支持自行 new 多个键盘。
功能
KeyboardType.Numbers:数字键盘,包含数字、小数点、正负号。KeyboardType.LettersNumbers:QWERTY 字母数字键盘,包含数字行与标点。- 两种布局均通过
#+=打开符号页,支持标准美式键盘全部 32 个 ASCII 标点符号;123/ABC返回。 - Shift 一次性切换、Caps 大小写锁定;退格、Delete、空格、左右光标、行首/行尾、Enter;字母布局支持 Tab。
- 点击输入框或获得焦点时弹出;键盘使用
ShowActivated=false、WS_EX_NOACTIVATE和WM_MOUSEACTIVATE防止按键点击抢走输入焦点。 - 默认出现在输入框下方,空间不足时尝试上方,限制在目标屏幕工作区内。标题栏可拖动,“收起”隐藏窗口,再次点击输入框可重新打开。
- 键盘属于调用方窗口,不在任务栏出现,不全局置顶;宿主关闭时一起关闭。
- 支持选区替换、光标处插入、MaxLength、只读/禁用保护、CharacterCasing;按钮文字色和背景色可自定义。
离线中文拼音
字母数字布局底部的 EN / CN 按钮切换英文与中文模式,默认英文。也可以在 UI 线程设置:
Keyboard.Shared.IsChineseInputEnabled = true;
- 中文模式显示拼音预编辑区和候选栏,每页 6 项;点击候选或屏幕键盘的
1–6选字,‹ / ›翻页。 Space选择当前页第一个候选;无候选时提交原拼音;没有拼音时输入普通空格。Enter在有拼音时提交原拼音,不触发目标输入框的 Enter;没有拼音时保持原有行为。Backspace优先删除拼音;Del/ 候选栏Esc取消当前组合。输入标点时提交当前页首个候选再追加标点。- 使用
v输入ü,例如nv→ 女、lv→ 绿;输入不区分大小写。支持完整拼音和前缀查询,完整匹配排在前面。 - 切换中英文、符号页、布局或输入目标,以及隐藏键盘时,取消未提交拼音;数字布局不启用中文输入。
- 沿用现有 WPF / WinForms 输入适配器;
KeyPressed接收最终提交的文本,不发送预编辑字母。此功能处理屏幕键盘点击,不接管实体键盘或系统输入法。
数据来自 KeyboardCore/Resources/chinese-xinhua.db 的 word 表。原库主要是单字,没有词频:现在使用本地 KeyboardCore/Resources/pinyin-priority.tsv 为同一拼音的常用字优先排序,例如 ni 优先“你、泥、拟、逆、妮、倪”,hao 优先“好、号、浩、豪、耗、毫”。这是人工维护的常用字优先表,不是统计语料词频或用户学习模型。完整拼音匹配仍优先于前缀匹配,未列入优先表的字保留原记录顺序;优先表不会新增或修改数据库中的读音映射。修改优先表后重新编译即可生效,无需重新生成索引。
目前不提供多音字补全、词组联想或整句转换。需要输入“你好”时,分别输入 ni 选“你”,再输入 hao 选“好”。候选准确性以原词库为准。
运行时只读取 DLL 内嵌的拼音索引和常用字优先表,不访问网络、不下载词库、不依赖系统输入法或外部 SQLite 组件。索引从数据库生成,去除声调,保留 ü 与 u 的区别,并将特殊字符 ɡ 转为 ASCII g;无法解析的记录会跳过并报告数量。
更新数据库后,先保存数据库编辑器中的修改,再在仓库根目录执行以下命令并重新编译;Python 仅在更新索引时需要,使用标准库,无需安装第三方包:
python tools/build_pinyin_index.py
dotnet build KeyboardCore/KeyboardCore.csproj
分发词库或生成索引前,请确认原词库的授权允许相应用途。
WPF 调用
在窗口构造函数的 InitializeComponent() 之后注册整个 Window,无需逐个注册 TextBox,也无需添加键盘 XAML:
using KeyboardCore.Control;
using KeyboardCore.WpfExtensions;
this.Register();
支持 Window、UserControl、Control、Grid、StackPanel 等 FrameworkElement。注册容器后,其后代 TextBox 获得焦点或被点击就会自动弹出共享键盘,动态添加的输入框也适用。只想为局部区域启用键盘时注册该容器即可:
numberPanel.Register(KeyboardType.Numbers);
嵌套注册按距离输入框最近的容器优先;例如 Window 默认字母数字布局,内部 numberPanel 使用数字布局。也保留单个 TextBox 注册作为特殊覆盖。重复注册同一容器会替换旧注册。
所有 Register 调用自动共享键盘,切换输入框只更新输入目标、布局和宿主,无需传入实例:
KeyboardCore.Control.Keyboard.Shared.Theme.ButtonBackground = System.Windows.Media.Colors.White;
WinForms 调用
在窗体构造函数的 InitializeComponent() 之后:
using KeyboardCore.Control;
using KeyboardCore.FrmExtensions;
this.Register();
numberPanel.Register(KeyboardType.Numbers);
WinForms 支持 Form、UserControl、Panel、GroupBox 等任意 Control,自动覆盖后代 TextBoxBase(包括 RichTextBox),监听动态增删并清理移除控件的事件。嵌套注册同样使用最近容器的配置。不使用 ElementHost,也不向 Controls 添加键盘。
自定义键盘颜色
KeyboardTheme 支持整体背景色 Background、标题文字色 Foreground、按钮文字色 ButtonForeground 和按钮背景色 ButtonBackground,没有明暗主题或预设。WPF 和 WinForms 使用相同的配置方式,颜色类型为 System.Windows.Media.Color:
KeyboardCore.Control.Keyboard.Shared.Theme = new KeyboardTheme {
Background = System.Windows.Media.Color.FromRgb(24, 34, 49),
Foreground = System.Windows.Media.Colors.White,
ButtonForeground = System.Windows.Media.Colors.White,
ButtonBackground = System.Windows.Media.Color.FromRgb(40, 100, 180)
};
KeyboardCore.Control.Keyboard.Shared.Theme.ButtonBackground = System.Windows.Media.Colors.SteelBlue;
在 UI 线程修改颜色立即生效,无需重新打开窗口。默认整体背景色为 #EAF0F6,标题与按钮文字色为 #23344A,按钮背景色为白色,全应用使用同一份配置。退格 Path 图标跟随按钮文字色;数字、字母、符号页及收起按钮均生效。悬停、按下和 Caps / Shift 激活使用边框反馈,不再通过透明度混合改变用户设置的颜色。窗口和内部背景同时使用 Background,标题使用 Foreground。
示例窗口构造函数中有 Theme 赋值示范,后执行的赋值会覆盖之前的全局配置。请直接修改该配置,或将配置统一移至应用初始化处,避免多处重复赋值。修改源码或升级库后需重新构建宿主并重启,正在运行的旧进程不会自动加载新 DLL。
手动显示与生命周期
KeyboardCore.Control.Keyboard.Shared.ShowFor(textBox, KeyboardType.Numbers);
KeyboardCore.Control.Keyboard.Shared.Hide();
ShowFor同时支持 WPF TextBox 和 WinForms TextBoxBase。目标须位于已显示的窗口中。手动调用前可先对目标调用 Focus();ShowFor 本身不主动抢焦点。Register返回 IDisposable;同一窗口/容器重复注册自动替换旧注册,不重复响应。Dispose 取消该容器对内部输入框的自动支持,不关闭共享键盘,不影响独立注册的其他容器。- WPF Window 关闭、WinForms 注册容器销毁时自动注销;WPF 容器 Unloaded 时释放当前目标但保留注册以支持重新加载。永久移除单独注册的 WPF 容器时应 Dispose。
- 只读、禁用或不可见输入框不会弹出键盘。WPF 使用路由事件覆盖同一控件树,不覆盖独立 Popup、ContextMenu 或新窗口;这些独立区域需要自行注册。WinForms 控件移出注册范围后不再弹出键盘。
- 当前宿主关闭会关闭其键盘窗口;其他输入框的注册仍然有效,下次使用 Shared 自动创建唯一的新窗口,并保留颜色配置。临时收起请用 Hide。不要缓存窗口实例跨越宿主关闭;每次通过 Shared 获取。实例上的 KeyPressed / EnterPressed 事件若需要跨窗口重建使用,需在新实例上重新订阅。
- 所有输入框必须位于同一个 STA UI 线程。跨 UI 线程调用会明确抛出异常,不会偷偷创建第二个键盘。这里的“全局”指当前进程;分别运行 WpfDemo 和 FrmDemo 是两个进程,各自有一个键盘。
- 推荐通过 Register / ShowFor 显示,使键盘始终归属于当前宿主;不要直接 Show 一个无宿主窗口。
输入事件与边界
KeyPressed 在编辑前触发,可设置 args.Handled = true 阻止默认输入。EnterPressed 在 KeyPressed 后通知按下 Enter;单行框不插入换行,可在该事件处理提交,多行框正常换行。
PressKey(action, text) 可程序化输入;Text 按原样输入,不应用 Shift/Caps。自定义控件可实现 IKeyboardInputTarget 并赋给 keyboard.InputTarget,其优先于 WPF Target。
默认适配 WPF TextBox、WinForms TextBoxBase(包括 RichTextBox)。不默认支持 WPF PasswordBox、WPF RichTextBox、中文输入法、Ctrl/Alt 快捷键或向其他应用发送系统按键。文本编辑不触发物理键盘 KeyDown / KeyPress / PreviewTextInput,请通过 KeyPressed、TextChanged 或绑定校验。WPF 需要实时更新绑定源时使用 UpdateSourceTrigger=PropertyChanged。
数字布局仍允许符号和空格,并非数值校验器。窗口不自动追踪输入框滚动/宿主移动,再次点击输入框会重新定位。
框架与演示
KeyboardCore.csproj 目标为 net48;net6.0-windows;net8.0-windows;net10.0-windows,分别适配 .NET Framework 4.8 和 .NET 6 / 8 / 10。UI 无法使用 netstandard2.0 目标,仅支持 Windows。
WpfDemo:.NET 10 WPF 独立键盘窗口演示。FrmDemo:保留 .NET Framework 4.8 WinForms,直接显示相同键盘窗口。- 现代 .NET WinForms 项目需要同时启用 UseWindowsForms 和 UseWPF;旧式 .NET Framework WinForms 项目添加 WindowsBase、PresentationCore、PresentationFramework、System.Xaml 引用(参见 FrmDemo)。
- 仅支持 Windows;构建需要 .NET 10 SDK 和 .NET Framework 4.8 Developer Pack。三个项目均已使用 dotnet build 验证,也可使用完整安装的 Visual Studio MSBuild。
dotnet build KeyboardCore/KeyboardCore.csproj
dotnet build WpfDemo/WpfDemo.csproj
dotnet build FrmDemo/FrmDemo.csproj
NuGet 打包与安装
包名 KeyboardCore,默认版本 1.0.0,一个包内包含四个目标框架的程序集和本使用说明。构建需要对应版本的 Windows Desktop targeting pack;SDK 还原时会在需要时下载缺少的引用包。使用 .NET 6 的宿主仍需安装对应的 Windows Desktop Runtime;兼容 .NET 6 不代表该版本仍处于官方支持期。
dotnet pack KeyboardCore/KeyboardCore.csproj -c Release
产物位于 artifacts/packages/KeyboardCore.1.0.0.nupkg。升级版本时可修改 csproj 的 Version,或使用 dotnet pack KeyboardCore/KeyboardCore.csproj -c Release -p:Version=1.0.1。
将 artifacts/packages 添加为本地 NuGet 源后安装;也可在项目目录执行:
dotnet add package KeyboardCore --version 1.0.0 --source E:/Project/Keyboard/artifacts/packages
.NET 6 / 8 / 10 宿主必须使用 Windows 目标框架;下面以 .NET 8 为例。该包同时依赖 WPF 和 WinForms,推荐显式启用两项桌面框架支持:
<PropertyGroup>
<TargetFramework>net8.0-windows</TargetFramework>
<UseWPF>true</UseWPF>
<UseWindowsForms>true</UseWindowsForms>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="KeyboardCore" Version="1.0.0" />
</ItemGroup>
.NET Framework 项目使用 4.8 目标,在 NuGet 包管理器中选择本地源安装同一版本即可。旧式项目如果提示缺少桌面框架引用,按前述说明添加 WindowsBase、PresentationCore、PresentationFramework、System.Xaml 和 System.Windows.Forms 引用。打包命令只生成本地 nupkg,不会发布至 nuget.org 或其他服务器。
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net6.0-windows7.0 is compatible. net7.0-windows was computed. net8.0-windows was computed. net8.0-windows7.0 is compatible. net9.0-windows was computed. net10.0-windows was computed. net10.0-windows7.0 is compatible. |
| .NET Framework | net48 is compatible. net481 was computed. |
-
.NETFramework 4.8
- No dependencies.
-
net10.0-windows7.0
- No dependencies.
-
net6.0-windows7.0
- No dependencies.
-
net8.0-windows7.0
- No dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.