using System; using System.Collections.Generic; using System.Linq; using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; namespace KeyBoard { /// /// MainWindow.xaml 的交互逻辑 /// public partial class MainWindow : Window { // Windows API 导入 [DllImport("user32.dll")] static extern IntPtr GetForegroundWindow(); [DllImport("user32.dll")] static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId); [DllImport("user32.dll")] static extern IntPtr GetFocus(); [DllImport("user32.dll")] static extern bool AttachThreadInput(uint idAttach, uint idAttachTo, bool fAttach); [DllImport("user32.dll")] static extern bool PostMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam); [DllImport("user32.dll")] static extern bool PostThreadMessage(uint idThread, uint Msg, IntPtr wParam, IntPtr lParam); [DllImport("kernel32.dll")] static extern uint GetCurrentThreadId(); // 消息常量 const uint WM_CHAR = 0x0102; const uint WM_KEYDOWN = 0x0100; const uint WM_KEYUP = 0x0101; const uint WM_LBUTTONDOWN = 0x0201; const uint WM_LBUTTONUP = 0x0202; // 当前活动窗口句柄 private IntPtr targetWindow = IntPtr.Zero; private uint targetThreadId = 0; private uint currentThreadId = 0; public MainWindow() { InitializeComponent(); } private void Window_Loaded(object sender, RoutedEventArgs e) { // 创建按钮样式 if (!this.Resources.Contains("KeyboardButtonStyle")) { var style = new System.Windows.Style(typeof(System.Windows.Controls.Button)); style.Setters.Add(new System.Windows.Setter(System.Windows.Controls.Button.WidthProperty, 60.0)); style.Setters.Add(new System.Windows.Setter(System.Windows.Controls.Button.HeightProperty, 50.0)); style.Setters.Add(new System.Windows.Setter(System.Windows.Controls.Button.MarginProperty, new Thickness(2))); this.Resources.Add("KeyboardButtonStyle", style); } // 获取当前线程ID currentThreadId = GetCurrentThreadId(); } // 在窗口失去焦点时保存目标窗口信息 private void Window_Deactivated(object sender, EventArgs e) { // 获取当前活动窗口 targetWindow = GetForegroundWindow(); if (targetWindow != IntPtr.Zero) { GetWindowThreadProcessId(targetWindow, out targetThreadId); } } // 使用PreviewMouseDown事件而不是Click事件 private void Button_PreviewMouseDown(object sender, MouseButtonEventArgs e) { e.Handled = true; // 阻止事件继续传播 var button = sender as System.Windows.Controls.Button; if (button?.Tag != null) { char keyChar = button.Tag.ToString()[0]; SendCharacter(keyChar); } // 防止按钮获得焦点 this.Focus(); } private void Space_PreviewMouseDown(object sender, MouseButtonEventArgs e) { e.Handled = true; SendCharacter(' '); this.Focus(); } private void Backspace_PreviewMouseDown(object sender, MouseButtonEventArgs e) { e.Handled = true; SendBackspace(); this.Focus(); } // 发送字符到目标窗口 private void SendCharacter(char ch) { if (targetWindow != IntPtr.Zero && targetThreadId != 0) { // 附加到目标线程的输入队列 AttachThreadInput(currentThreadId, targetThreadId, true); // 发送字符消息 PostMessage(targetWindow, WM_CHAR, new IntPtr(ch), IntPtr.Zero); // 分离线程输入 AttachThreadInput(currentThreadId, targetThreadId, false); } else { // 如果没有保存目标窗口,则发送到当前活动窗口 IntPtr currentForegroundWindow = GetForegroundWindow(); if (currentForegroundWindow != IntPtr.Zero) { PostMessage(currentForegroundWindow, WM_CHAR, new IntPtr(ch), IntPtr.Zero); } } } // 发送退格键 private void SendBackspace() { IntPtr windowToSend = targetWindow != IntPtr.Zero ? targetWindow : GetForegroundWindow(); if (windowToSend != IntPtr.Zero) { uint threadId = targetThreadId != 0 ? targetThreadId : GetWindowThreadProcessId(windowToSend, out _); if (threadId != 0) { AttachThreadInput(currentThreadId, threadId, true); PostMessage(windowToSend, WM_KEYDOWN, new IntPtr(0x08), IntPtr.Zero); // VK_BACK PostMessage(windowToSend, WM_KEYUP, new IntPtr(0x08), IntPtr.Zero); AttachThreadInput(currentThreadId, threadId, false); } } } // 关闭按钮 private void CloseButton_Click(object sender, RoutedEventArgs e) { this.Close(); } } }