using System; using System.Text; using System.Windows; using System.Windows.Controls; using System.Windows.Controls.Primitives; using System.Windows.Media; namespace ivf_tl_Operate.CustomUserControls { /// /// 软键盘模式。 /// public enum SoftKeyboardMode { /// 数字键盘(0-9 / 退格 / 清除 / 确定)—— 数字/参数输入。 Number, /// 密码/全键盘(字母+数字+常用符号)—— 登录/调试密码。 Password } /// /// M4-04-1 · 自绘内置软键盘控件(数字键盘 + 密码/全键盘)。 /// /// 取代 osk.exe(需求 11)。键盘维护一份内部输入缓冲,所有按键只在缓冲上增删, /// 每次变化通过 把「当前完整文本」抛给宿主(SoftKeyboardHost), /// 由宿主写回目标 TextBox/PasswordBox。点 确定/× 触发 , /// 由宿主收起键盘。键盘不直接引用任何页面或具体输入框,做到代码隔离、可复用。 /// /// 不涉及任何业务/密码校验逻辑:tl13579 比对、参数阈值校验仍在原页面,键盘只负责录入。 /// public partial class SoftKeyboard : UserControl { private readonly StringBuilder _buffer = new StringBuilder(); private bool _shift; // 全键盘大小写 private bool _fullPadBuilt; /// 当前缓冲文本变化(参数为当前完整文本)。宿主据此写回目标输入框。 public event Action KeyInput; /// 用户点「确定」或「×」请求收起键盘(参数:true=确定提交,false=取消/关闭)。 public event Action RequestClose; public SoftKeyboard() { InitializeComponent(); } #region 依赖属性 /// 键盘模式(数字 / 密码全键盘)。 public SoftKeyboardMode KeyboardMode { get => (SoftKeyboardMode)GetValue(KeyboardModeProperty); set => SetValue(KeyboardModeProperty, value); } public static readonly DependencyProperty KeyboardModeProperty = DependencyProperty.Register(nameof(KeyboardMode), typeof(SoftKeyboardMode), typeof(SoftKeyboard), new PropertyMetadata(SoftKeyboardMode.Number, OnKeyboardModeChanged)); private static void OnKeyboardModeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { if (d is SoftKeyboard kb) kb.ApplyMode(); } /// 预览/回显时是否按密码掩码(●)显示。默认随模式:Password=掩码。可被宿主覆盖。 public bool MaskPreview { get => (bool)GetValue(MaskPreviewProperty); set => SetValue(MaskPreviewProperty, value); } public static readonly DependencyProperty MaskPreviewProperty = DependencyProperty.Register(nameof(MaskPreview), typeof(bool), typeof(SoftKeyboard), new PropertyMetadata(false)); #endregion /// 当前键盘缓冲内容。 public string Text => _buffer.ToString(); /// /// 重置键盘:设定模式 + 初始文本(用于绑定输入框时把已有值带入)。宿主弹出前调用。 /// public void Reset(SoftKeyboardMode mode, string initialText, bool mask) { _buffer.Clear(); if (!string.IsNullOrEmpty(initialText)) _buffer.Append(initialText); _shift = false; MaskPreview = mask; KeyboardMode = mode; // 触发 ApplyMode ApplyMode(); UpdatePreview(); } private void ApplyMode() { if (_numberPad == null) return; // 未加载 if (KeyboardMode == SoftKeyboardMode.Password) { BuildFullPadOnce(); _numberPad.Visibility = Visibility.Collapsed; _fullPad.Visibility = Visibility.Visible; } else { _numberPad.Visibility = Visibility.Visible; _fullPad.Visibility = Visibility.Collapsed; } } #region 全键盘按键动态构建(触控基准统一应用) private void BuildFullPadOnce() { if (_fullPadBuilt) return; FillRow(_rowDigits, "1234567890"); FillRow(_rowQ, "qwertyuiop"); FillRow(_rowA, "asdfghjkl"); FillRow(_rowZ, "zxcvbnm"); _fullPadBuilt = true; } private void FillRow(System.Windows.Controls.Primitives.UniformGrid host, string chars) { foreach (char c in chars) { var b = new Button { Content = c.ToString(), Tag = c.ToString(), Margin = new Thickness(2) }; b.Click += Key_Click; host.Children.Add(b); } } #endregion #region 按键事件 private void Key_Click(object sender, RoutedEventArgs e) { if (!(sender is Button b) || b.Tag == null) return; string ch = b.Tag.ToString(); // 全键盘 Shift:字母大写 if (KeyboardMode == SoftKeyboardMode.Password && _shift && ch.Length == 1 && char.IsLetter(ch[0])) ch = ch.ToUpperInvariant(); _buffer.Append(ch); EmitChanged(); } private void Back_Click(object sender, RoutedEventArgs e) { if (_buffer.Length > 0) _buffer.Remove(_buffer.Length - 1, 1); EmitChanged(); } private void Clear_Click(object sender, RoutedEventArgs e) { _buffer.Clear(); EmitChanged(); } private void Shift_Click(object sender, RoutedEventArgs e) { _shift = !_shift; if (_shiftBtn != null) _shiftBtn.Background = _shift ? new SolidColorBrush(Color.FromRgb(0x4D, 0x75, 0xAC)) : new SolidColorBrush(Color.FromRgb(0xB0, 0xB4, 0xB9)); } private void Enter_Click(object sender, RoutedEventArgs e) { RequestClose?.Invoke(true); } private void Close_Click(object sender, RoutedEventArgs e) { RequestClose?.Invoke(false); } #endregion private void EmitChanged() { UpdatePreview(); KeyInput?.Invoke(_buffer.ToString()); } private void UpdatePreview() { if (_preview == null) return; if (MaskPreview) _preview.Text = new string('●', _buffer.Length); else _preview.Text = _buffer.ToString(); } } }