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();
}
}
}