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