neggenbe
neggenbe

Reputation: 1885

c# Windows 10 virtual keyboard issues

I have developed a c# code snippet to determine if the virtual (on-screen) keyboard was showing or not.

The code below worked fine in Windows 7, 8 and 8.1, but in Windows 10, the IsKeyboardVisible always returns 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;
}

I used a tutorial on SO, but it's a while ago so sorry for not crediting the author.

Does anyone know about a working code snippet for all recent Windows versions, so I don't have to check the actual OS to switch on the version...?

UPDATE

I found the original post here, which allowed me to correct the code. So now my problem is the same old Win10 issue - I can't show the virtual keyboard using

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

... Again, is there any "all-platform" code I can use, or what is the suggested approach for Win10?

UPDATE 2 I found out about issues running a 32-bit application on a 64-bit os. That being said, the error occurs whether I try to run osk.exe in the System32 or the "sysWOW64` folder... Is there any other way than making a 64-bit release???

Upvotes: 0

Views: 3775

Answers (2)

Le Tri Cuong
Le Tri Cuong

Reputation: 11

Same problem with me, I try all answer here, but it not work. After finding solution with google, this is is ok.

// 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");
            }
   //----------------

Upvotes: 0

neggenbe
neggenbe

Reputation: 1885

After much digging about TabTip.exe, osk.exe and x86 and x64 compatibility issues, I found a solution by searching the osk.exe on my system and trying to run each of them. I found 4 version the following folders:

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

It appears the one in C:\Windows\WinSxS\amd64_microsoft... works fine (not the other three though)...

Given the "amd64_...." folder might not be the same on different machines (I actually checked and they don't match, I didn't search whether this depends on the machine, the windows build or anything else...).

So basically I did a small routine to look into WinSxS folder and returning the very firs occurrence of osk.exe, which works just fine. I also made the code working on a 32-bit OS using a simple OS-architecture test:

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

UPDATE: The confusion with one working and one non-working version within the WinSxS folder made me nervous. It works just fine because the amd_.. folder is alphabetically before wow64_....

I therefore suggest to add a test in the getOskPath method to return the first native 64-bit osk.exe (not the emulated one).

Using the IsWin64Emulator method found here, the method looks like this:

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

Upvotes: 1

Related Questions