using Microsoft.Win32; using System; using System.Diagnostics; using System.IO; using System.Runtime.InteropServices; using System.Threading; using System.Threading.Tasks; namespace CCDCount.DLL.Tools { public static class OnScreenKeyboard { [DllImport("kernel32.dll")] private static extern IntPtr GetModuleHandle(string lpModuleName); [DllImport("user32.dll")] private static extern IntPtr FindWindow(string lpClassName, string lpWindowName); [DllImport("user32.dll")] private static extern bool ShowWindow(IntPtr hWnd, int nCmdShow); [DllImport("user32.dll")] private static extern bool SetForegroundWindow(IntPtr hWnd); [DllImport("user32.dll")] private static extern bool IsIconic(IntPtr hWnd); private const int SW_SHOW = 5; private const int SW_RESTORE = 9; private const int SW_HIDE = 0; /// /// 启动软键盘(兼容Windows 10及以上版本) /// public static void KeyBoardShow() { //// 检查是否为Windows 10或更高版本 //if (IsWindows10OrHigher()) //{ // // 尝试启动TabTip // if (TryStartTabTip()) // return; //} // 回退到传统osk //StartOnScreenKeyboardRobust(); StartOnScreenKeyboard(); } /// /// 隐藏软键盘 /// public static void KeyBoardHide() { try { // 隐藏TabTip窗口 //IntPtr tabTipHwnd = FindWindow("IPTip_Main_Window", null); //if (tabTipHwnd != IntPtr.Zero) //{ // ShowWindow(tabTipHwnd, SW_HIDE); //} // 隐藏OSK窗口 IntPtr oskHwnd = FindWindow("OSKMainClass", "屏幕键盘"); if (oskHwnd != IntPtr.Zero) { ShowWindow(oskHwnd, SW_HIDE); } } catch { // 忽略异常 } } private static void StartOnScreenKeyboard() { try { // 检查是否已经运行 Process[] oskProcesses = Process.GetProcessesByName("osk"); if (oskProcesses.Length > 0) { Console.WriteLine("进入了分支"); // 如果已经运行,尝试显示窗口 IntPtr oskHwnd = FindWindow("OSKMainClass", "屏幕键盘"); if (oskHwnd != IntPtr.Zero) { // 【修改点】:判断是否最小化 if (IsIconic(oskHwnd)) { // 如果最小化,使用 SW_RESTORE (9) 恢复窗口 ShowWindow(oskHwnd, SW_RESTORE); } else { // 如果未最小化,使用 SW_SHOW (5) 显示/激活 ShowWindow(oskHwnd, SW_SHOW); } // 确保窗口前置 SetForegroundWindow(oskHwnd); return; } else { // 如果找不到窗口,杀死进程重新启动 foreach (var process in oskProcesses) { try { process.Kill(); } catch { } } } } Console.WriteLine("执行开启软键盘"); Process.Start(Path.Combine(Environment.SystemDirectory, "osk.exe")); } catch (Exception ex) { throw new InvalidOperationException("无法启动屏幕键盘", ex); } } /// /// 健壮的 OSK 启动方法 /// private static void StartOnScreenKeyboardRobust() { try { // 1. 彻底清理已存在的 osk 进程,防止句柄冲突 KillOskProcess(); // 2. 准备启动信息 string oskPath = Path.Combine(Environment.SystemDirectory, "osk.exe"); if (!File.Exists(oskPath)) { throw new FileNotFoundException("未找到 osk.exe", oskPath); } ProcessStartInfo startInfo = new ProcessStartInfo { FileName = oskPath, UseShellExecute = true, // 关键:使用 Shell 执行,有助于权限处理 Verb = "open" }; // 3. 启动进程 Process proc = Process.Start(startInfo); // 4. 等待窗口出现并激活 // osk.exe 启动较慢,需要轮询等待窗口句柄 IntPtr hwnd = IntPtr.Zero; int retryCount = 0; const int maxRetries = 50; // 最多等待 5秒 (50 * 100ms) while (retryCount < maxRetries) { // 查找窗口类名 OSKMainClass,标题可能是 "屏幕键盘" 或 "On-Screen Keyboard" (取决于系统语言) hwnd = FindWindow("OSKMainClass", null); if (hwnd != IntPtr.Zero) { break; } Thread.Sleep(100); retryCount++; } if (hwnd != IntPtr.Zero) { // 确保窗口不是最小化状态 if (IsIconic(hwnd)) { ShowWindow(hwnd, SW_RESTORE); } else { ShowWindow(hwnd, SW_SHOW); } // 尝试将窗口前置 SetForegroundWindow(hwnd); } else { System.Diagnostics.Debug.WriteLine("警告: OSK 进程已启动,但未检测到窗口句柄。可能需要管理员权限。"); } } catch (Exception ex) { System.Diagnostics.Debug.WriteLine($"启动 OSK 失败: {ex.Message}"); // 在生产环境中,建议记录日志而不是直接抛出异常,以免崩溃主程序 } } /// /// 强制杀死所有 osk 进程 /// private static void KillOskProcess() { try { Process[] processes = Process.GetProcessesByName("osk"); foreach (var p in processes) { try { if (!p.HasExited) { p.Kill(); p.WaitForExit(1000); // 等待进程完全退出 } } catch { } } } catch { } } private static bool IsWindows10OrHigher() { var os = Environment.OSVersion; if (os.Version.Major >= 10) return true; try { using (var key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion")) { var currentBuild = key?.GetValue("CurrentBuild")?.ToString(); if (int.TryParse(currentBuild, out int buildNumber)) { // Windows 10 build 10240及以上 return buildNumber >= 10240; } } } catch { // 忽略异常 } // 兼容性检查:Windows 8.1及以后版本的Major是6,但Minor版本不同 return os.Version.Major == 10 || (os.Version.Major == 6 && os.Version.Minor >= 2); } private static bool TryStartTabTip() { try { // 检查是否已经运行 Process[] tabTipProcesses = Process.GetProcessesByName("TabTip"); if (tabTipProcesses.Length > 0) { // 如果找不到窗口,杀死进程重新启动 foreach (var process in tabTipProcesses) { try { process.Kill(); } catch { } } } // 方法1:通过注册表查找路径 string tabTipPath = GetTabTipPathFromRegistry(); if (!string.IsNullOrEmpty(tabTipPath) && File.Exists(tabTipPath)) { Process.Start(tabTipPath); return true; } // 方法2:通过系统路径查找 string systemPath = Path.Combine(Environment.SystemDirectory, "TabTip.exe"); if (File.Exists(systemPath)) { Process.Start(systemPath); return true; } // 方法3:使用modern Windows 10路径 string modernPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), @"TabletTip\1.7\TabTip.exe"); if (File.Exists(modernPath)) { Process.Start(modernPath); return true; } // 方法4:使用默认路径 string defaultPath = @"C:\Program Files\Common Files\Microsoft Shared\ink\TabTip.exe"; if (File.Exists(defaultPath)) { Process.Start(defaultPath); return true; } } catch (Exception ex) { // 记录异常但不中断 System.Diagnostics.Debug.WriteLine($"启动TabTip失败: {ex.Message}"); } return false; } private static string GetTabTipPathFromRegistry() { try { using (var key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Appx\AppxAllUserStore\InboxApplications")) { if (key != null) { foreach (var subKeyName in key.GetSubKeyNames()) { if (subKeyName.Contains("Microsoft.Windows.Keyboard")) { using (var subKey = key.OpenSubKey(subKeyName)) { var installPath = subKey?.GetValue("Path")?.ToString(); if (!string.IsNullOrEmpty(installPath)) { string tabTipPath = Path.Combine(installPath, "TabTip.exe"); if (File.Exists(tabTipPath)) return tabTipPath; } } } } } } } catch { // 忽略注册表访问异常 } return null; } } }