c# Windows 10 虚拟键盘问题

Posted

技术标签:

【中文标题】c# Windows 10 虚拟键盘问题【英文标题】:c# Windows 10 virtual keyboard issues 【发布时间】:2016-11-03 18:25:15 【问题描述】:

我开发了一个 c# 代码 sn-p 来确定虚拟(屏幕)键盘是否显示。

以下代码在 Windows 7、8 和 8.1 中运行良好,但在 Windows 10 中,IsKeyboardVisible 始终返回 true...

public static bool IsKeyboardVisible() 
    Process keyboardProc;
    UInt32 WS_DISABLED = 0x8000000;
    UInt32 WS_VISIBLE = 0X94000000;
    int GWL_STYLE = -16;
    IntPtr keyboardHandle = GetKeyboardWindowHandle();

    bool visible = false;

    if (keyboardHandle != IntPtr.Zero) 
        UInt32 style = GetWindowLong(keyboardHandle, GWL_STYLE);
        // in Win10, this always returns "true", i.e. WS_DISABLED is
        // 
        //visible = ((style & WS_DISABLED) != WS_DISABLED);
        // UPDATE: I found this code helping here
        visible = (style == WS_VISIBLE);
    
    return visible;

我使用了一个关于 SO 的教程,但很抱歉没有记下作者。

有没有人知道所有最新 Windows 版本的工作代码 sn-p,所以我不必检查实际的操作系统来打开版本...?

更新

我找到了original post here,它允许我更正代码。所以现在我的问题是同样的老 Win10 问题 - 我无法使用

显示虚拟键盘
string progFiles = @"C:\Program Files\Common Files\Microsoft Shared\ink";
string keyboardPath = Path.Combine(progFiles, "TabTip.exe");
keyboardProc = Process.Start(keyboardPath);

...再次,我可以使用任何“全平台”代码,或者 Win10 的建议方法是什么?

更新 2 我发现了在 64 位操作系统上运行 32 位应用程序的问题。话虽这么说,无论我尝试在System32 或“sysWOW64` 文件夹中运行osk.exe 都会出现错误......除了制作64位版本还有其他方法吗???

【问题讨论】:

【参考方案1】:

在对TabTip.exeosk.exe 以及x86 和x64 兼容性问题进行了大量研究之后,我通过在我的系统上搜索osk.exe 并尝试运行它们找到了解决方案。我在以下文件夹中找到了 4 个版本:

C:\Windows\System32 C:\Windows\SysWOW64 C:\Windows\WinSxS\amd64_microsoft... C:\Windows\WinSxS\wow64_microsoft...

看来C:\Windows\WinSxS\amd64_microsoft... 中的一个工作正常(但不是其他三个)...

鉴于“amd64_....”文件夹在不同机器上可能不一样(我实际上检查过它们不匹配,我没有搜索这是否取决于机器、Windows 版本或其他任何东西...)。

所以基本上我做了一个小例程来查看WinSxS 文件夹并返回osk.exe 的第一次出现,它工作得很好。我还使用简单的操作系统架构测试使代码在 32 位操作系统上运行:

 string OSKpath64 = getOskPath(@"C:\Windows\WinSxS");
 if (string.IsNullOrWhiteSpace(OSKpath64)) 
     OSKpath64 = "osk.exe";
  
  string OSKpath32 = @"C:\Windows\System32\osk.exe";
  if (!File.Exists(OSKpath32)) 
      OSKpath32 = @"osk.exe";
  
  System.Diagnostics.Process.Start((Environment.Is64BitOperatingSystem) ? OSKpath64 : OSKpath32);

更新: WinSxS 文件夹中的一个工作版本和一个非工作版本的混淆让我感到紧张。它工作得很好,因为amd_.. 文件夹按字母顺序排列在wow64_... 之前。

因此,我建议在 getOskPath 方法中添加一个测试,以返回第一个本机 64 位 osk.exe(不是模拟的)。

使用IsWin64Emulatormethod found here,方法如下:

static string getOskPath(string dir) 
    string path = Path.Combine(dir, "osk.exe");
    if (File.Exists(path)) 
        Process p = System.Diagnostics.Process.Start(path);
        if (p.IsWin64Emulator()) 
            path = string.Empty;
        
        p.Kill();
        return path;
    
    DirectoryInfo di = new DirectoryInfo(dir);
    foreach (DirectoryInfo subDir in di.GetDirectories().Reverse()) 
        path = getOskPath(Path.Combine(dir, subDir.Name));
        if (!string.IsNullOrWhiteSpace(path)) 
            return path;
        
    
    return string.Empty;

【讨论】:

【参考方案2】:

和我一样的问题,我在这里尝试所有答案,但它不起作用。 用谷歌找到解决方案后,没关系。

// Step 1: For Load On-Screen Keyboard
    const string Kernel32dll = "Kernel32.Dll";
    [DllImport(Kernel32dll, EntryPoint = "Wow64DisableWow64FsRedirection")]
    public static extern bool Wow64DisableWow64FsRedirection(ref IntPtr ptr);

    [DllImport(Kernel32dll, EntryPoint = "Wow64EnableWow64FsRedirection")]
    public static extern bool Wow64EnableWow64FsRedirection(IntPtr ptr);

    IntPtr wow64Value;
    //---------------------------------------

   // Step 2: Function-----
   if (Environment.Is64BitOperatingSystem)
            
                if (Wow64DisableWow64FsRedirection(ref wow64Value))
                
                    System.Diagnostics.Process.Start("osk.exe");
                    Wow64EnableWow64FsRedirection(wow64Value);
                
            
            else
            
                System.Diagnostics.Process.Start("osk.exe");
            
   //----------------

【讨论】:

这是有风险的,它也会影响 CLR 和即时编译器。最简单的方法是执行 c:\windows\sysnative\osk.exe,“sysnative”告诉文件系统主管您打算使用本机并且永远不希望它重定向。 这段代码我只是按照示例进行操作,它对我有用。所以我只是分享(因为我也得到了难以归档的解决方案)。其实这段代码我不是很清楚,如果你有更好的方法,可以分享一下吗?

以上是关于c# Windows 10 虚拟键盘问题的主要内容,如果未能解决你的问题,请参考以下文章

Windows 10 上 TabTip.exe(虚拟键盘)的大小和位置?

WPF 禁用TextBox的触摸后自动弹出虚拟键盘

WPF 禁用TextBox的触摸后自动弹出虚拟键盘

win7系统下如何调出虚拟键盘

使用 C#/Windows API 的虚拟键盘 - 发送键输入,但不获取焦点

win10怎么打开虚拟键盘